Initial checkin of lldb code from internal Apple repo.


git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@105619 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/API/SBAddress.cpp b/source/API/SBAddress.cpp
new file mode 100644
index 0000000..482ecec
--- /dev/null
+++ b/source/API/SBAddress.cpp
@@ -0,0 +1,118 @@
+//===-- SBAddress.cpp -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBAddress.h"
+#include "lldb/API/SBProcess.h"
+#include "lldb/Core/Address.h"
+
+using namespace lldb;
+
+
+SBAddress::SBAddress () :
+    m_lldb_object_ap ()
+{
+}
+
+SBAddress::SBAddress (const lldb_private::Address *lldb_object_ptr) :
+    m_lldb_object_ap ()
+{
+    if (lldb_object_ptr)
+        m_lldb_object_ap.reset (new lldb_private::Address(*lldb_object_ptr));
+}
+
+SBAddress::SBAddress (const SBAddress &rhs) :
+    m_lldb_object_ap ()
+{
+    if (rhs.IsValid())
+        m_lldb_object_ap.reset (new lldb_private::Address(*rhs.m_lldb_object_ap.get()));
+}
+
+SBAddress::~SBAddress ()
+{
+}
+
+const SBAddress &
+SBAddress::operator = (const SBAddress &rhs)
+{
+    if (this != &rhs)
+    {
+        if (rhs.IsValid())
+            m_lldb_object_ap.reset (new lldb_private::Address(*rhs.m_lldb_object_ap.get()));
+    }
+    return *this;
+}
+
+bool
+SBAddress::IsValid () const
+{
+    return m_lldb_object_ap.get() != NULL && m_lldb_object_ap->IsValid();
+}
+
+void
+SBAddress::SetAddress (const lldb_private::Address *lldb_object_ptr)
+{
+    if (lldb_object_ptr)
+    {
+        if (m_lldb_object_ap.get())
+            *m_lldb_object_ap = *lldb_object_ptr;
+        else
+            m_lldb_object_ap.reset (new lldb_private::Address(*lldb_object_ptr));
+        return;
+    }
+    if (m_lldb_object_ap.get())
+        m_lldb_object_ap->Clear();
+}
+
+lldb::addr_t
+SBAddress::GetFileAddress () const
+{
+    if (m_lldb_object_ap.get())
+        return m_lldb_object_ap->GetFileAddress();
+    else
+        return LLDB_INVALID_ADDRESS;
+}
+
+lldb::addr_t
+SBAddress::GetLoadAddress (const SBProcess &process) const
+{
+    if (m_lldb_object_ap.get())
+        return m_lldb_object_ap->GetLoadAddress(process.get());
+    else
+        return LLDB_INVALID_ADDRESS;
+}
+
+bool
+SBAddress::OffsetAddress (addr_t offset)
+{
+    if (m_lldb_object_ap.get())
+    {
+        addr_t addr_offset = m_lldb_object_ap->GetOffset();
+        if (addr_offset != LLDB_INVALID_ADDRESS)
+        {
+            m_lldb_object_ap->SetOffset(addr_offset + offset);
+            return true;
+        }
+    }
+    return false;
+}
+
+
+const lldb_private::Address *
+SBAddress::operator->() const
+{
+    return m_lldb_object_ap.get();
+}
+
+const lldb_private::Address &
+SBAddress::operator*() const
+{
+    return *m_lldb_object_ap;
+}
+
+
diff --git a/source/API/SBBlock.cpp b/source/API/SBBlock.cpp
new file mode 100644
index 0000000..536febd
--- /dev/null
+++ b/source/API/SBBlock.cpp
@@ -0,0 +1,47 @@
+//===-- SBBlock.cpp ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBBlock.h"
+#include "lldb/Symbol/Block.h"
+
+using namespace lldb;
+
+
+SBBlock::SBBlock () :
+    m_lldb_object_ptr (NULL)
+{
+}
+
+SBBlock::SBBlock (lldb_private::Block *lldb_object_ptr) :
+    m_lldb_object_ptr (lldb_object_ptr)
+{
+}
+
+SBBlock::~SBBlock ()
+{
+    m_lldb_object_ptr = NULL;
+}
+
+bool
+SBBlock::IsValid () const
+{
+    return m_lldb_object_ptr != NULL;
+}
+
+void
+SBBlock::AppendVariables (bool can_create, bool get_parent_variables, lldb_private::VariableList *var_list)
+{
+    if (IsValid())
+    {
+        m_lldb_object_ptr->AppendVariables (can_create, get_parent_variables, var_list);
+    }
+}
+
+
+
diff --git a/source/API/SBBreakpoint.cpp b/source/API/SBBreakpoint.cpp
new file mode 100644
index 0000000..2cf4e0b
--- /dev/null
+++ b/source/API/SBBreakpoint.cpp
@@ -0,0 +1,404 @@
+//===-- SBBreakpoint.cpp ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBBreakpoint.h"
+#include "lldb/API/SBBreakpointLocation.h"
+#include "lldb/API/SBDebugger.h"
+#include "lldb/API/SBProcess.h"
+#include "lldb/API/SBThread.h"
+
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/Target.h"
+
+
+#include "lldb/lldb-enumerations.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+struct CallbackData
+{
+    SBBreakpoint::BreakpointHitCallback callback;
+    void *callback_baton;
+};
+
+class SBBreakpointCallbackBaton : public Baton
+{
+public:
+
+    SBBreakpointCallbackBaton (SBBreakpoint::BreakpointHitCallback callback, void *baton) :
+        Baton (new CallbackData)
+    {
+        CallbackData *data = (CallbackData *)m_data;
+        data->callback = callback;
+        data->callback_baton = baton;
+    }
+    
+    virtual ~SBBreakpointCallbackBaton()
+    {
+        CallbackData *data = (CallbackData *)m_data;
+
+        if (data)
+        {
+            delete data;
+            m_data = NULL;
+        }
+    }
+};
+
+
+SBBreakpoint::SBBreakpoint () :
+    m_break_sp ()
+{
+}
+
+SBBreakpoint::SBBreakpoint (const SBBreakpoint& rhs) :
+    m_break_sp (rhs.m_break_sp)
+{
+}
+
+
+SBBreakpoint::SBBreakpoint (const lldb::BreakpointSP &bp_sp) :
+    m_break_sp (bp_sp)
+{
+}
+
+SBBreakpoint::~SBBreakpoint()
+{
+}
+
+const SBBreakpoint &
+SBBreakpoint::operator = (const SBBreakpoint& rhs)
+{
+    if (this != &rhs)
+    {
+        m_break_sp = rhs.m_break_sp;
+    }
+    return *this;
+}
+
+break_id_t
+SBBreakpoint::GetID () const
+{
+    if (m_break_sp)
+        return m_break_sp->GetID();
+    return LLDB_INVALID_BREAK_ID;
+}
+
+
+bool
+SBBreakpoint::IsValid() const
+{
+    return m_break_sp;
+}
+
+void
+SBBreakpoint::Dump (FILE *f)
+{
+    if (m_break_sp)
+    {
+        if (f == NULL)
+            f = SBDebugger::GetOutputFileHandle();
+        if (f == NULL)
+            return;
+        lldb_private::StreamFile str (f);
+        m_break_sp->Dump (&str);
+    }
+}
+
+void
+SBBreakpoint::ClearAllBreakpointSites ()
+{
+    if (m_break_sp)
+        m_break_sp->ClearAllBreakpointSites ();
+}
+
+SBBreakpointLocation
+SBBreakpoint::FindLocationByAddress (addr_t vm_addr)
+{
+    SBBreakpointLocation sb_bp_location;
+
+    if (m_break_sp)
+    {
+        if (vm_addr != LLDB_INVALID_ADDRESS)
+        {
+            Address address;
+            Process *sb_process = m_break_sp->GetTarget().GetProcessSP().get();
+            if (sb_process == NULL || sb_process->ResolveLoadAddress (vm_addr, address) == false)
+            {
+                address.SetSection (NULL);
+                address.SetOffset (vm_addr);
+            }
+            sb_bp_location.SetLocation (m_break_sp->FindLocationByAddress (address));
+        }
+    }
+    return sb_bp_location;
+}
+
+break_id_t
+SBBreakpoint::FindLocationIDByAddress (addr_t vm_addr)
+{
+    break_id_t lldb_id = (break_id_t) 0;
+
+    if (m_break_sp)
+    {
+        if (vm_addr != LLDB_INVALID_ADDRESS)
+        {
+            Address address;
+            Process *sb_process = m_break_sp->GetTarget().GetProcessSP().get();
+            if (sb_process == NULL || sb_process->ResolveLoadAddress (vm_addr, address) == false)
+            {
+                address.SetSection (NULL);
+                address.SetOffset (vm_addr);
+            }
+            lldb_id = m_break_sp->FindLocationIDByAddress (address);
+        }
+    }
+
+    return lldb_id;
+}
+
+SBBreakpointLocation
+SBBreakpoint::FindLocationByID (break_id_t bp_loc_id)
+{
+    SBBreakpointLocation sb_bp_location;
+
+    if (m_break_sp)
+        sb_bp_location.SetLocation (m_break_sp->FindLocationByID (bp_loc_id));
+
+    return sb_bp_location;
+}
+
+SBBreakpointLocation
+SBBreakpoint::GetLocationAtIndex (uint32_t index)
+{
+    SBBreakpointLocation sb_bp_location;
+
+    if (m_break_sp)
+        sb_bp_location.SetLocation (m_break_sp->GetLocationAtIndex (index));
+
+    return sb_bp_location;
+}
+
+void
+SBBreakpoint::ListLocations (FILE* f, const char *description_level)
+{
+   if (f == NULL)
+       f = SBDebugger::GetOutputFileHandle();
+
+   if (f == NULL)
+       return;
+
+    if (m_break_sp)
+    {
+        DescriptionLevel level;
+        if (strcmp (description_level, "brief") == 0)
+            level = eDescriptionLevelBrief;
+        else if (strcmp (description_level, "full") == 0)
+            level = eDescriptionLevelFull;
+        else if (strcmp (description_level, "verbose") == 0)
+            level = eDescriptionLevelVerbose;
+        else
+            level = eDescriptionLevelBrief;
+
+        StreamFile str (f);
+
+        str.IndentMore();
+        int num_locs = m_break_sp->GetNumLocations();
+        for (int i = 0; i < num_locs; ++i)
+        {
+            BreakpointLocation *loc = m_break_sp->GetLocationAtIndex (i).get();
+            loc->GetDescription (&str, level);
+            str.EOL();
+        }
+    }
+}
+
+void
+SBBreakpoint::SetEnabled (bool enable)
+{
+    if (m_break_sp)
+        m_break_sp->SetEnabled (enable);
+}
+
+bool
+SBBreakpoint::IsEnabled ()
+{
+    if (m_break_sp)
+        return m_break_sp->IsEnabled();
+    else
+        return false;
+}
+
+void
+SBBreakpoint::SetIgnoreCount (int32_t count)
+{
+    if (m_break_sp)
+        m_break_sp->SetIgnoreCount (count);
+}
+
+int32_t
+SBBreakpoint::GetIgnoreCount () const
+{
+    if (m_break_sp)
+        return m_break_sp->GetIgnoreCount();
+    else
+        return 0;
+}
+
+void
+SBBreakpoint::SetThreadID (tid_t sb_thread_id)
+{
+    if (m_break_sp)
+        m_break_sp->SetThreadID (sb_thread_id);
+}
+
+tid_t
+SBBreakpoint::GetThreadID ()
+{
+    tid_t lldb_thread_id = LLDB_INVALID_THREAD_ID;
+    if (m_break_sp)
+        lldb_thread_id = m_break_sp->GetThreadID();
+
+    return lldb_thread_id;
+}
+
+size_t
+SBBreakpoint::GetNumResolvedLocations() const
+{
+    if (m_break_sp)
+        return m_break_sp->GetNumResolvedLocations();
+    else
+        return 0;
+}
+
+size_t
+SBBreakpoint::GetNumLocations() const
+{
+    if (m_break_sp)
+        return m_break_sp->GetNumLocations();
+    else
+        return 0;
+}
+
+void
+SBBreakpoint::GetDescription (FILE *f, const char *description_level, bool describe_locations)
+{
+    if (f == NULL)
+        return;
+
+    if (m_break_sp)
+    {
+        DescriptionLevel level;
+        if (strcmp (description_level, "brief") == 0)
+            level = eDescriptionLevelBrief;
+        else if (strcmp (description_level, "full") == 0)
+            level = eDescriptionLevelFull;
+        else if (strcmp (description_level, "verbose") == 0)
+            level = eDescriptionLevelVerbose;
+        else
+            level = eDescriptionLevelBrief;
+
+        StreamFile str (f);
+
+        m_break_sp->GetDescription (&str, level);
+        str.EOL();
+        if (describe_locations)
+        {
+          //str.IndentMore();
+          // int num_locs = m_break_sp->GetNumLocations();
+          //  for (int i = 0; i < num_locs; ++i)
+          //  {
+          //      BreakpointLocation *loc = m_break_sp->FindLocationByIndex (i);
+          //      loc->GetDescription (&str, level);
+          //      str.EOL();
+          //  }
+            ListLocations (f, description_level);
+        }
+    }
+}
+
+bool
+SBBreakpoint::PrivateBreakpointHitCallback 
+(
+    void *baton, 
+    StoppointCallbackContext *ctx, 
+    lldb::user_id_t break_id, 
+    lldb::user_id_t break_loc_id
+)
+{
+    BreakpointSP bp_sp(ctx->context.target->GetBreakpointList().FindBreakpointByID(break_id));
+    if (baton && bp_sp)
+    {
+        CallbackData *data = (CallbackData *)baton;
+        lldb_private::Breakpoint *bp = bp_sp.get();
+        if (bp && data->callback)
+        {
+            if (ctx->context.process)
+            {
+                SBProcess sb_process (ctx->context.process->GetSP());
+                SBThread sb_thread;
+                SBBreakpointLocation sb_location;
+                assert (bp_sp);
+                sb_location.SetLocation (bp_sp->FindLocationByID (break_loc_id));
+                if (ctx->context.thread)
+                    sb_thread.SetThread(ctx->context.thread->GetSP());
+
+                return data->callback (data->callback_baton, 
+                                          sb_process, 
+                                          sb_thread, 
+                                          sb_location);
+            }
+        }
+    }
+    return true;    // Return true if we should stop at this breakpoint
+}
+
+void
+SBBreakpoint::SetCallback (BreakpointHitCallback callback, void *baton)
+{
+    if (m_break_sp.get())
+    {
+        BatonSP baton_sp(new SBBreakpointCallbackBaton (callback, baton));
+        m_break_sp->SetCallback (SBBreakpoint::PrivateBreakpointHitCallback, baton_sp, false);
+    }
+}
+
+
+lldb_private::Breakpoint *
+SBBreakpoint::operator->() const
+{
+    return m_break_sp.get();
+}
+
+lldb_private::Breakpoint *
+SBBreakpoint::get() const
+{
+    return m_break_sp.get();
+}
+
+lldb::BreakpointSP &
+SBBreakpoint::operator *()
+{
+    return m_break_sp;
+}
+
+const lldb::BreakpointSP &
+SBBreakpoint::operator *() const
+{
+    return m_break_sp;
+}
+
diff --git a/source/API/SBBreakpointLocation.cpp b/source/API/SBBreakpointLocation.cpp
new file mode 100644
index 0000000..8bb36bd
--- /dev/null
+++ b/source/API/SBBreakpointLocation.cpp
@@ -0,0 +1,162 @@
+//===-- SBBreakpointLocation.cpp --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBBreakpointLocation.h"
+#include "lldb/API/SBDefines.h"
+#include "lldb/API/SBDebugger.h"
+
+#include "lldb/lldb-types.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+
+//class SBBreakpointLocation
+
+SBBreakpointLocation::SBBreakpointLocation ()
+{
+}
+
+SBBreakpointLocation::SBBreakpointLocation (const lldb::BreakpointLocationSP &break_loc_sp) :
+    m_break_loc_sp (break_loc_sp)
+{
+}
+
+SBBreakpointLocation::~SBBreakpointLocation ()
+{
+}
+
+bool
+SBBreakpointLocation::IsValid() const
+{
+    return m_break_loc_sp.get() != NULL;
+}
+
+addr_t
+SBBreakpointLocation::GetLoadAddress ()
+{
+    addr_t ret_addr = LLDB_INVALID_ADDRESS;
+
+    if (m_break_loc_sp)
+    {
+        ret_addr = m_break_loc_sp->GetLoadAddress();
+    }
+
+    return ret_addr;
+}
+
+void
+SBBreakpointLocation::SetEnabled (bool enabled)
+{
+    if (m_break_loc_sp)
+    {
+        m_break_loc_sp->SetEnabled (enabled);
+    }
+}
+
+bool
+SBBreakpointLocation::IsEnabled ()
+{
+    if (m_break_loc_sp)
+        return m_break_loc_sp->IsEnabled();
+    else
+        return false;
+}
+
+int32_t
+SBBreakpointLocation::GetIgnoreCount ()
+{
+    if (m_break_loc_sp)
+        return m_break_loc_sp->GetIgnoreCount();
+    else
+        return 0;
+}
+
+void
+SBBreakpointLocation::SetIgnoreCount (int32_t n)
+{
+    if (m_break_loc_sp)
+        m_break_loc_sp->SetIgnoreCount (n);
+}
+
+void
+SBBreakpointLocation::SetThreadID (tid_t thread_id)
+{
+    if (m_break_loc_sp)
+        m_break_loc_sp->SetThreadID (thread_id);
+}
+
+tid_t
+SBBreakpointLocation::GetThreadID ()
+{
+    tid_t sb_thread_id = (lldb::tid_t) LLDB_INVALID_THREAD_ID;
+    if (m_break_loc_sp)
+        sb_thread_id = m_break_loc_sp->GetThreadID();
+
+    return sb_thread_id;
+}
+
+bool
+SBBreakpointLocation::IsResolved ()
+{
+    if (m_break_loc_sp)
+        return m_break_loc_sp->IsResolved();
+    else
+        return false;
+}
+
+void
+SBBreakpointLocation::SetLocation (const lldb::BreakpointLocationSP &break_loc_sp)
+{
+    if (m_break_loc_sp)
+    {
+        // Uninstall the callbacks?
+    }
+    m_break_loc_sp = break_loc_sp;
+}
+
+void
+SBBreakpointLocation::GetDescription (FILE *f, const char *description_level)
+{
+    if (f == NULL)
+        return;
+
+    if (m_break_loc_sp)
+    {
+        DescriptionLevel level;
+        if (strcmp (description_level, "brief") == 0)
+            level = eDescriptionLevelBrief;
+        else if (strcmp (description_level, "full") == 0)
+            level = eDescriptionLevelFull;
+        else if (strcmp (description_level, "verbose") == 0)
+            level = eDescriptionLevelVerbose;
+        else
+            level = eDescriptionLevelBrief;
+
+        StreamFile str (f);
+
+        m_break_loc_sp->GetDescription (&str, level);
+        str.EOL();
+    }
+}
+
+SBBreakpoint
+SBBreakpointLocation::GetBreakpoint ()
+{
+    SBBreakpoint sb_bp;
+    if (m_break_loc_sp)
+        *sb_bp = m_break_loc_sp->GetBreakpoint ().GetSP();    
+    return sb_bp;
+}
+
diff --git a/source/API/SBBroadcaster.cpp b/source/API/SBBroadcaster.cpp
new file mode 100644
index 0000000..b9debcf
--- /dev/null
+++ b/source/API/SBBroadcaster.cpp
@@ -0,0 +1,142 @@
+//===-- SBBroadcaster.cpp ---------------------------------------*- 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/Broadcaster.h"
+#include "lldb/lldb-forward-rtti.h"
+
+#include "SBBroadcaster.h"
+#include "SBListener.h"
+#include "SBEvent.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+SBBroadcaster::SBBroadcaster () :
+    m_lldb_object (NULL),
+    m_lldb_object_owned (false)
+{
+}
+
+
+SBBroadcaster::SBBroadcaster (const char *name) :
+    m_lldb_object (new Broadcaster (name)),
+    m_lldb_object_owned (true)
+{
+}
+
+SBBroadcaster::SBBroadcaster (lldb_private::Broadcaster *broadcaster, bool owns) :
+    m_lldb_object (broadcaster),
+    m_lldb_object_owned (owns)
+{
+}
+
+SBBroadcaster::~SBBroadcaster()
+{
+    SetLLDBObjectPtr (NULL, false);
+}
+
+void
+SBBroadcaster::BroadcastEventByType (uint32_t event_type, bool unique)
+{
+    if (m_lldb_object == NULL)
+        return;
+
+    if (unique)
+        m_lldb_object->BroadcastEventIfUnique (event_type);
+    else
+        m_lldb_object->BroadcastEvent (event_type);
+}
+
+void
+SBBroadcaster::BroadcastEvent (const SBEvent &event, bool unique)
+{
+    if (m_lldb_object == NULL)
+        return;
+
+    EventSP event_sp = event.GetSharedPtr ();
+    if (unique)
+        m_lldb_object->BroadcastEventIfUnique (event_sp);
+    else
+        m_lldb_object->BroadcastEvent (event_sp);
+}
+
+void
+SBBroadcaster::AddInitialEventsToListener (const SBListener &listener, uint32_t requested_events)
+{
+    if (m_lldb_object)
+        m_lldb_object->AddInitialEventsToListener (listener.get(), requested_events);
+}
+
+uint32_t
+SBBroadcaster::AddListener (const SBListener &listener, uint32_t event_mask)
+{
+    if (m_lldb_object)
+        return m_lldb_object->AddListener (listener.get(), event_mask);
+    return 0;
+}
+
+const char *
+SBBroadcaster::GetName ()
+{
+    if (m_lldb_object)
+        return m_lldb_object->GetBroadcasterName().AsCString();
+    return NULL;
+}
+
+bool
+SBBroadcaster::EventTypeHasListeners (uint32_t event_type)
+{
+    if (m_lldb_object)
+        return m_lldb_object->EventTypeHasListeners (event_type);
+    return false;
+}
+
+bool
+SBBroadcaster::RemoveListener (const SBListener &listener, uint32_t event_mask)
+{
+    if (m_lldb_object)
+        return m_lldb_object->RemoveListener (listener.get(), event_mask);
+    return false;
+}
+
+Broadcaster *
+SBBroadcaster::GetLLDBObjectPtr () const
+{
+    return m_lldb_object;
+}
+
+void
+SBBroadcaster::SetLLDBObjectPtr (Broadcaster *broadcaster, bool owns)
+{
+    if (m_lldb_object && m_lldb_object_owned)
+        delete m_lldb_object;
+    m_lldb_object = broadcaster;
+    m_lldb_object_owned = owns;
+}
+
+
+bool
+SBBroadcaster::IsValid () const
+{
+    return m_lldb_object != NULL;
+}
+
+bool
+SBBroadcaster::operator == (const SBBroadcaster &rhs) const
+{
+    return m_lldb_object == rhs.m_lldb_object;
+    
+}
+
+bool
+SBBroadcaster::operator != (const SBBroadcaster &rhs) const
+{
+    return m_lldb_object != rhs.m_lldb_object;
+}
diff --git a/source/API/SBCommandContext.cpp b/source/API/SBCommandContext.cpp
new file mode 100644
index 0000000..3a1b60a
--- /dev/null
+++ b/source/API/SBCommandContext.cpp
@@ -0,0 +1,34 @@
+//===-- SBCommandContext.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+#include "SBCommandContext.h"
+
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+SBCommandContext::SBCommandContext (CommandContext *lldb_object) :
+    m_lldb_object (lldb_object)
+{
+}
+
+SBCommandContext::~SBCommandContext ()
+{
+}
+
+bool
+SBCommandContext::IsValid () const
+{
+    return m_lldb_object != NULL;
+}
+
diff --git a/source/API/SBCommandInterpreter.cpp b/source/API/SBCommandInterpreter.cpp
new file mode 100644
index 0000000..1e40320
--- /dev/null
+++ b/source/API/SBCommandInterpreter.cpp
@@ -0,0 +1,193 @@
+//===-- SBCommandInterpreter.cpp --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-types.h"
+#include "lldb/Core/Args.h"
+#include "lldb/Core/SourceManager.h"
+#include "lldb/Core/Listener.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Target.h"
+
+#include "SBBroadcaster.h"
+#include "SBDebugger.h"
+#include "SBCommandReturnObject.h"
+#include "SBCommandContext.h"
+#include "SBSourceManager.h"
+#include "SBCommandInterpreter.h"
+#include "SBProcess.h"
+#include "SBTarget.h"
+#include "SBListener.h"
+#include "SBStringList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+SBCommandInterpreter::SBCommandInterpreter (CommandInterpreter &interpreter) :
+    m_interpreter (interpreter)
+{
+}
+
+SBCommandInterpreter::~SBCommandInterpreter ()
+{
+}
+
+bool
+SBCommandInterpreter::CommandExists (const char *cmd)
+{
+    return m_interpreter.CommandExists (cmd);
+}
+
+bool
+SBCommandInterpreter::AliasExists (const char *cmd)
+{
+    return m_interpreter.AliasExists (cmd);
+}
+
+bool
+SBCommandInterpreter::UserCommandExists (const char *cmd)
+{
+    return m_interpreter.UserCommandExists (cmd);
+}
+
+lldb::ReturnStatus
+SBCommandInterpreter::HandleCommand (const char *command_line, SBCommandReturnObject &result, bool add_to_history)
+{
+    result.Clear();
+    m_interpreter.HandleCommand (command_line, add_to_history, result.GetLLDBObjectRef());
+    return result.GetStatus();
+}
+
+int
+SBCommandInterpreter::HandleCompletion (const char *current_line,
+                                        const char *cursor,
+                                        const char *last_char,
+                                        int match_start_point,
+                                        int max_return_elements,
+                                        SBStringList &matches)
+{
+    int num_completions;
+    lldb_private::StringList lldb_matches;
+    num_completions =  m_interpreter.HandleCompletion (current_line, cursor, last_char, match_start_point,
+                                                       max_return_elements, lldb_matches);
+
+    SBStringList temp_list (&lldb_matches);
+    matches.AppendList (temp_list);
+
+    return num_completions;
+}
+
+const char **
+SBCommandInterpreter::GetEnvironmentVariables ()
+{
+    const Args *env_vars =  m_interpreter.GetEnvironmentVariables();
+    if (env_vars)
+        return env_vars->GetConstArgumentVector ();
+    return NULL;
+}
+
+bool
+SBCommandInterpreter::HasCommands ()
+{
+    return m_interpreter.HasCommands();
+}
+
+bool
+SBCommandInterpreter::HasAliases ()
+{
+    return m_interpreter.HasAliases();
+}
+
+bool
+SBCommandInterpreter::HasUserCommands ()
+{
+    return m_interpreter.HasUserCommands ();
+}
+
+bool
+SBCommandInterpreter::HasAliasOptions ()
+{
+    return m_interpreter.HasAliasOptions ();
+}
+
+bool
+SBCommandInterpreter::HasInterpreterVariables ()
+{
+    return m_interpreter.HasInterpreterVariables ();
+}
+
+SBProcess
+SBCommandInterpreter::GetProcess ()
+{
+    SBProcess process;
+    CommandContext *context = m_interpreter.Context();
+    if (context)
+    {
+        Target *target = context->GetTarget();
+        if (target)
+            process.SetProcess(target->GetProcessSP());
+    }
+    return process;
+}
+
+ssize_t
+SBCommandInterpreter::WriteToScriptInterpreter (const char *src)
+{
+    if (src)
+        return WriteToScriptInterpreter (src, strlen(src));
+    return 0;
+}
+
+ssize_t
+SBCommandInterpreter::WriteToScriptInterpreter (const char *src, size_t src_len)
+{
+    if (src && src[0])
+    {
+        ScriptInterpreter *script_interpreter = m_interpreter.GetScriptInterpreter();
+        if (script_interpreter)
+            return ::write (script_interpreter->GetMasterFileDescriptor(), src, src_len);
+    }
+    return 0;
+}
+
+
+CommandInterpreter *
+SBCommandInterpreter::GetLLDBObjectPtr ()
+{
+    return &m_interpreter;
+}
+
+CommandInterpreter &
+SBCommandInterpreter::GetLLDBObjectRef ()
+{
+    return m_interpreter;
+}
+
+void
+SBCommandInterpreter::SourceInitFileInHomeDirectory (SBCommandReturnObject &result)
+{
+    result.Clear();
+    m_interpreter.SourceInitFile (false, result.GetLLDBObjectRef());
+}
+
+void
+SBCommandInterpreter::SourceInitFileInCurrentWorkingDirectory (SBCommandReturnObject &result)
+{
+    result.Clear();
+    m_interpreter.SourceInitFile (true, result.GetLLDBObjectRef());
+}
+
+SBBroadcaster
+SBCommandInterpreter::GetBroadcaster ()
+{
+    SBBroadcaster broadcaster (&m_interpreter, false);
+    return broadcaster;
+}
+
diff --git a/source/API/SBCommandReturnObject.cpp b/source/API/SBCommandReturnObject.cpp
new file mode 100644
index 0000000..3910cc4
--- /dev/null
+++ b/source/API/SBCommandReturnObject.cpp
@@ -0,0 +1,148 @@
+//===-- SBCommandReturnObject.cpp -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+#include "SBCommandReturnObject.h"
+
+using namespace lldb;
+
+SBCommandReturnObject::SBCommandReturnObject () :
+    m_return_object_ap (new lldb_private::CommandReturnObject ())
+{
+}
+
+SBCommandReturnObject::~SBCommandReturnObject ()
+{
+    // m_return_object_ap will automatically delete any pointer it owns
+}
+
+bool
+SBCommandReturnObject::IsValid() const
+{
+    return m_return_object_ap.get() != NULL;
+}
+
+
+const char *
+SBCommandReturnObject::GetOutput ()
+{
+    if (m_return_object_ap.get())
+        return m_return_object_ap->GetOutputStream().GetData();
+    return NULL;
+}
+
+const char *
+SBCommandReturnObject::GetError ()
+{
+    if (m_return_object_ap.get())
+        return m_return_object_ap->GetErrorStream().GetData();
+    return NULL;
+}
+
+size_t
+SBCommandReturnObject::GetOutputSize ()
+{
+    if (m_return_object_ap.get())
+        return m_return_object_ap->GetOutputStream().GetSize();
+    return 0;
+}
+
+size_t
+SBCommandReturnObject::GetErrorSize ()
+{
+    if (m_return_object_ap.get())
+        return m_return_object_ap->GetErrorStream().GetSize();
+    return 0;
+}
+
+size_t
+SBCommandReturnObject::PutOutput (FILE *fh)
+{
+    if (fh)
+    {
+        size_t num_bytes = GetOutputSize ();
+        if (num_bytes)
+            return ::fprintf (fh, "%s", GetOutput());
+    }
+    return 0;
+}
+
+size_t
+SBCommandReturnObject::PutError (FILE *fh)
+{
+    if (fh)
+    {
+        size_t num_bytes = GetErrorSize ();
+        if (num_bytes)
+            return ::fprintf (fh, "%s", GetError());
+    }
+    return 0;
+}
+
+void
+SBCommandReturnObject::Clear()
+{
+    if (m_return_object_ap.get())
+        m_return_object_ap->Clear();
+}
+
+lldb::ReturnStatus
+SBCommandReturnObject::GetStatus()
+{
+    if (m_return_object_ap.get())
+        return m_return_object_ap->GetStatus();
+    return lldb::eReturnStatusInvalid;
+}
+
+bool
+SBCommandReturnObject::Succeeded ()
+{
+    if (m_return_object_ap.get())
+        return m_return_object_ap->Succeeded();
+    return false;
+}
+
+bool
+SBCommandReturnObject::HasResult ()
+{
+    if (m_return_object_ap.get())
+        return m_return_object_ap->HasResult();
+    return false;
+}
+
+void
+SBCommandReturnObject::AppendMessage (const char *message)
+{
+    if (m_return_object_ap.get())
+        m_return_object_ap->AppendMessage (message);
+}
+
+lldb_private::CommandReturnObject *
+SBCommandReturnObject::GetLLDBObjectPtr()
+{
+    return m_return_object_ap.get();
+}
+
+
+lldb_private::CommandReturnObject &
+SBCommandReturnObject::GetLLDBObjectRef()
+{
+    assert(m_return_object_ap.get());
+    return *(m_return_object_ap.get());
+}
+
+
+void
+SBCommandReturnObject::SetLLDBObjectPtr (lldb_private::CommandReturnObject *ptr)
+{
+    if (m_return_object_ap.get())
+        m_return_object_ap.reset (ptr);
+}
+
diff --git a/source/API/SBCommunication.cpp b/source/API/SBCommunication.cpp
new file mode 100644
index 0000000..e2a7917
--- /dev/null
+++ b/source/API/SBCommunication.cpp
@@ -0,0 +1,194 @@
+//===-- SBCommunication.cpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBCommunication.h"
+#include "lldb/API/SBBroadcaster.h"
+#include "lldb/Core/Communication.h"
+#include "lldb/Core/ConnectionFileDescriptor.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+
+SBCommunication::SBCommunication() :
+    m_lldb_object (NULL),
+    m_lldb_object_owned (false)
+{
+}
+
+SBCommunication::SBCommunication(const char * broadcaster_name) :
+    m_lldb_object (new Communication (broadcaster_name)),
+    m_lldb_object_owned (true)
+{
+}
+
+SBCommunication::~SBCommunication()
+{
+    if (m_lldb_object && m_lldb_object_owned)
+        delete m_lldb_object;
+    m_lldb_object = NULL;
+    m_lldb_object_owned = false;
+}
+
+ConnectionStatus
+SBCommunication::CheckIfBytesAvailable ()
+{
+    if (m_lldb_object)
+        return m_lldb_object->BytesAvailable (0, NULL);
+    return eConnectionStatusNoConnection;
+}
+
+ConnectionStatus
+SBCommunication::WaitForBytesAvailableInfinite ()
+{
+    if (m_lldb_object)
+        return m_lldb_object->BytesAvailable (UINT32_MAX, NULL);
+    return eConnectionStatusNoConnection;
+}
+
+ConnectionStatus
+SBCommunication::WaitForBytesAvailableWithTimeout (uint32_t timeout_usec)
+{
+    if (m_lldb_object)
+        return m_lldb_object->BytesAvailable (timeout_usec, NULL);
+    return eConnectionStatusNoConnection;
+}
+
+ConnectionStatus
+SBCommunication::Connect (const char *url)
+{
+    if (m_lldb_object)
+    {
+        if (!m_lldb_object->HasConnection ())
+            m_lldb_object->SetConnection (new ConnectionFileDescriptor());
+        return m_lldb_object->Connect (url, NULL);
+    }
+    return eConnectionStatusNoConnection;
+}
+
+ConnectionStatus
+SBCommunication::AdoptFileDesriptor (int fd, bool owns_fd)
+{
+    if (m_lldb_object)
+    {
+        if (m_lldb_object->HasConnection ())
+        {
+            if (m_lldb_object->IsConnected())
+                m_lldb_object->Disconnect ();
+        }
+        m_lldb_object->SetConnection (new ConnectionFileDescriptor (fd, owns_fd));
+        if (m_lldb_object->IsConnected())
+            return eConnectionStatusSuccess;
+        else
+            return eConnectionStatusLostConnection;
+    }
+    return eConnectionStatusNoConnection;
+}
+
+
+ConnectionStatus
+SBCommunication::Disconnect ()
+{
+    if (m_lldb_object)
+        return m_lldb_object->Disconnect ();
+    return eConnectionStatusNoConnection;
+}
+
+bool
+SBCommunication::IsConnected () const
+{
+    if (m_lldb_object)
+        return m_lldb_object->IsConnected ();
+    return false;
+}
+
+size_t
+SBCommunication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status)
+{
+    if (m_lldb_object)
+        return m_lldb_object->Read (dst, dst_len, timeout_usec, status, NULL);
+    status = eConnectionStatusNoConnection;
+    return 0;
+}
+
+
+size_t
+SBCommunication::Write (const void *src, size_t src_len, ConnectionStatus &status)
+{
+    if (m_lldb_object)
+        return m_lldb_object->Write (src, src_len, status, NULL);
+    status = eConnectionStatusNoConnection;
+    return 0;
+}
+
+bool
+SBCommunication::ReadThreadStart ()
+{
+    if (m_lldb_object)
+        return m_lldb_object->StartReadThread ();
+    return false;
+}
+
+
+bool
+SBCommunication::ReadThreadStop ()
+{
+    if (m_lldb_object)
+        return m_lldb_object->StopReadThread ();
+    return false;
+}
+
+bool
+SBCommunication::ReadThreadIsRunning ()
+{
+    if (m_lldb_object)
+        return m_lldb_object->ReadThreadIsRunning ();
+    return false;
+}
+
+bool
+SBCommunication::SetReadThreadBytesReceivedCallback
+(
+    ReadThreadBytesReceived callback,
+    void *callback_baton
+)
+{
+    if (m_lldb_object)
+    {
+        m_lldb_object->SetReadThreadBytesReceivedCallback (callback, callback_baton);
+        return true;
+    }
+    return false;
+}
+
+SBBroadcaster
+SBCommunication::GetBroadcaster ()
+{
+    SBBroadcaster broadcaster (m_lldb_object, false);
+    return broadcaster;
+}
+
+
+//
+//void
+//SBCommunication::CreateIfNeeded ()
+//{
+//    if (m_lldb_object == NULL)
+//    {
+//        static uint32_t g_broadcaster_num;
+//        char broadcaster_name[256];
+//        ::snprintf (name, broadcaster_name, "%p SBCommunication", this);
+//        m_lldb_object = new Communication (broadcaster_name);
+//        m_lldb_object_owned = true;
+//    }
+//    assert (m_lldb_object);
+//}
+//
+//
diff --git a/source/API/SBCompileUnit.cpp b/source/API/SBCompileUnit.cpp
new file mode 100644
index 0000000..a12934a
--- /dev/null
+++ b/source/API/SBCompileUnit.cpp
@@ -0,0 +1,120 @@
+//===-- SBCompileUnit.cpp ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBCompileUnit.h"
+#include "lldb/API/SBLineEntry.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/LineEntry.h"
+#include "lldb/Symbol/LineTable.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+SBCompileUnit::SBCompileUnit () :
+    m_lldb_object_ptr (NULL)
+{
+}
+
+SBCompileUnit::SBCompileUnit (lldb_private::CompileUnit *lldb_object_ptr) :
+    m_lldb_object_ptr (lldb_object_ptr)
+{
+}
+
+SBCompileUnit::~SBCompileUnit ()
+{
+    m_lldb_object_ptr = NULL;
+}
+
+SBFileSpec
+SBCompileUnit::GetFileSpec () const
+{
+    SBFileSpec file_spec;
+    if (m_lldb_object_ptr)
+        file_spec.SetFileSpec(*m_lldb_object_ptr);
+    return file_spec;
+}
+
+uint32_t
+SBCompileUnit::GetNumLineEntries () const
+{
+    if (m_lldb_object_ptr)
+    {
+        LineTable *line_table = m_lldb_object_ptr->GetLineTable ();
+        if (line_table)
+            return line_table->GetSize();
+    }
+    return 0;
+}
+
+SBLineEntry
+SBCompileUnit::GetLineEntryAtIndex (uint32_t idx) const
+{
+    SBLineEntry sb_line_entry;
+    if (m_lldb_object_ptr)
+    {
+        LineTable *line_table = m_lldb_object_ptr->GetLineTable ();
+        if (line_table)
+        {
+            LineEntry line_entry;
+            if (line_table->GetLineEntryAtIndex(idx, line_entry))
+                sb_line_entry.SetLineEntry(line_entry);
+        }
+    }
+    return sb_line_entry;
+}
+
+uint32_t
+SBCompileUnit::FindLineEntryIndex (uint32_t start_idx, uint32_t line, SBFileSpec *inline_file_spec) const
+{
+    if (m_lldb_object_ptr)
+    {
+        FileSpec file_spec;
+        if (inline_file_spec && inline_file_spec->IsValid())
+            file_spec = inline_file_spec->ref();
+        else
+            file_spec = *m_lldb_object_ptr;
+
+        return m_lldb_object_ptr->FindLineEntry (start_idx,
+                                                 line,
+                                                 inline_file_spec ? inline_file_spec->get() : NULL,
+                                                 NULL);
+    }
+    return UINT32_MAX;
+}
+
+bool
+SBCompileUnit::IsValid () const
+{
+    return m_lldb_object_ptr != NULL;
+}
+
+bool
+SBCompileUnit::operator == (const SBCompileUnit &rhs) const
+{
+    return m_lldb_object_ptr == rhs.m_lldb_object_ptr;
+}
+
+bool
+SBCompileUnit::operator != (const SBCompileUnit &rhs) const
+{
+    return m_lldb_object_ptr != rhs.m_lldb_object_ptr;
+}
+
+const lldb_private::CompileUnit *
+SBCompileUnit::operator->() const
+{
+    return m_lldb_object_ptr;
+}
+
+const lldb_private::CompileUnit &
+SBCompileUnit::operator*() const
+{
+    return *m_lldb_object_ptr;
+}
diff --git a/source/API/SBDebugger.cpp b/source/API/SBDebugger.cpp
new file mode 100644
index 0000000..d31c93c
--- /dev/null
+++ b/source/API/SBDebugger.cpp
@@ -0,0 +1,569 @@
+//===-- SBDebugger.cpp ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SBDebugger.h"
+
+#include "lldb/lldb-include.h"
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/State.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/TargetList.h"
+
+#include "SBListener.h"
+#include "SBBroadcaster.h"
+#include "SBCommandInterpreter.h"
+#include "SBCommandReturnObject.h"
+#include "SBEvent.h"
+#include "SBFrame.h"
+#include "SBTarget.h"
+#include "SBProcess.h"
+#include "SBThread.h"
+#include "SBSourceManager.h"
+#include "SBInputReader.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+SBDebugger::Initialize ()
+{
+    Debugger::Initialize();
+}
+
+void
+SBDebugger::Terminate ()
+{
+    Debugger::Terminate();
+}
+
+void
+SBDebugger::SetAsync (bool b)
+{
+    static bool value_set_once = false;
+
+    if (!value_set_once)
+    {
+        value_set_once = true;
+        Debugger::GetSharedInstance().SetAsyncExecution(b);
+    }
+}
+
+void
+SBDebugger::SetInputFile (const char *tty_name)
+{
+    // DEPRECATED: will be removed in next submission
+    FILE *fh = ::fopen (tty_name, "r");
+    SetInputFileHandle  (fh, true);
+}
+
+void
+SBDebugger::SetOutputFile (const char *tty_name)
+{
+    // DEPRECATED: will be removed in next submission
+    FILE *fh = ::fopen (tty_name, "w");
+    SetOutputFileHandle (fh, true);
+    SetErrorFileHandle  (fh, false);
+}
+
+void
+SBDebugger::SetErrorFile (const char *tty_name)
+{
+    // DEPRECATED: will be removed in next submission
+}
+
+
+// Shouldn't really be settable after initialization as this could cause lots of problems; don't want users
+// trying to switch modes in the middle of a debugging session.
+void
+SBDebugger::SetInputFileHandle (FILE *fh, bool transfer_ownership)
+{
+    Debugger::GetSharedInstance().SetInputFileHandle (fh, transfer_ownership);
+}
+
+void
+SBDebugger::SetOutputFileHandle (FILE *fh, bool transfer_ownership)
+{
+    Debugger::GetSharedInstance().SetOutputFileHandle (fh, transfer_ownership);
+}
+
+void
+SBDebugger::SetErrorFileHandle (FILE *fh, bool transfer_ownership)
+{
+    Debugger::GetSharedInstance().SetErrorFileHandle (fh, transfer_ownership);
+}
+
+FILE *
+SBDebugger::GetInputFileHandle ()
+{
+    return Debugger::GetSharedInstance().GetInputFileHandle();
+}
+
+FILE *
+SBDebugger::GetOutputFileHandle ()
+{
+    return Debugger::GetSharedInstance().GetOutputFileHandle();
+}
+
+FILE *
+SBDebugger::GetErrorFileHandle ()
+{
+    return Debugger::GetSharedInstance().GetErrorFileHandle();
+}
+
+SBCommandInterpreter
+SBDebugger::GetCommandInterpreter ()
+{
+    SBCommandInterpreter sb_interpreter(Debugger::GetSharedInstance().GetCommandInterpreter());
+    return sb_interpreter;
+}
+
+void
+SBDebugger::HandleCommand (const char *command)
+{
+    SBProcess process;
+    SBCommandInterpreter sb_interpreter(Debugger::GetSharedInstance().GetCommandInterpreter());
+    SBCommandReturnObject result;
+
+    sb_interpreter.HandleCommand (command, result, false);
+
+    if (GetErrorFileHandle() != NULL)
+        result.PutError (GetErrorFileHandle());
+    if (GetOutputFileHandle() != NULL)
+        result.PutOutput (GetOutputFileHandle());
+
+    if (Debugger::GetSharedInstance().GetAsyncExecution() == false)
+    {
+        process = GetCommandInterpreter().GetProcess ();
+        if (process.IsValid())
+        {
+            EventSP event_sp;
+            Listener &lldb_listener = Debugger::GetSharedInstance().GetListener();
+            while (lldb_listener.GetNextEventForBroadcaster (process.get(), event_sp))
+            {
+                SBEvent event(event_sp);
+                HandleProcessEvent (process, event, GetOutputFileHandle(), GetErrorFileHandle());
+            }
+        }
+    }
+}
+
+SBListener
+SBDebugger::GetListener ()
+{
+    SBListener sb_listener(Debugger::GetSharedInstance().GetListener());
+    return sb_listener;
+}
+
+void
+SBDebugger::HandleProcessEvent (const SBProcess &process, const SBEvent &event, FILE *out, FILE *err)
+{
+     const uint32_t event_type = event.GetType();
+     char stdio_buffer[1024];
+     size_t len;
+
+     if (event_type & Process::eBroadcastBitSTDOUT)
+     {
+         while ((len = process.GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
+             if (out != NULL)
+                 ::fwrite (stdio_buffer, 1, len, out);
+     }
+     else if (event_type & Process::eBroadcastBitSTDERR)
+     {
+         while ((len = process.GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
+             if (out != NULL)
+                 ::fwrite (stdio_buffer, 1, len, out);
+     }
+     else if (event_type & Process::eBroadcastBitStateChanged)
+     {
+         // Drain any stdout messages.
+         while ((len = process.GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
+             if (out != NULL)
+                 ::fwrite (stdio_buffer, 1, len, out);
+
+         // Drain any stderr messages.
+         while ((len = process.GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
+             if (out != NULL)
+                 ::fwrite (stdio_buffer, 1, len, out);
+
+         StateType event_state = SBProcess::GetStateFromEvent (event);
+
+         if (event_state == eStateInvalid)
+             return;
+
+         bool is_stopped = StateIsStoppedState (event_state);
+         if (!is_stopped)
+             process.ReportCurrentState (event, out);
+   }
+}
+
+void
+SBDebugger::UpdateCurrentThread (SBProcess &process)
+{
+    if (process.IsValid())
+    {
+        SBThread curr_thread = process.GetCurrentThread ();
+        SBThread thread;
+        StopReason curr_thread_stop_reason = eStopReasonInvalid;
+        if (curr_thread.IsValid())
+        {
+            if (curr_thread.GetStopReason() != eStopReasonInvalid)
+                curr_thread_stop_reason = curr_thread.GetStopReason ();
+        }
+
+        if (! curr_thread.IsValid()
+            || curr_thread_stop_reason == eStopReasonInvalid
+            || curr_thread_stop_reason == eStopReasonNone)
+          {
+            // Prefer a thread that has just completed its plan over another thread as current thread.
+            SBThread plan_thread;
+            SBThread other_thread;
+            const size_t num_threads = process.GetNumThreads ();
+            size_t i;
+            for (i = 0; i < num_threads; ++i)
+            {
+                thread = process.GetThreadAtIndex(i);
+                if (thread.GetStopReason () != eStopReasonInvalid)
+                {
+                    switch (thread.GetStopReason ())
+                    {
+                        default:
+                        case eStopReasonInvalid:
+                        case eStopReasonNone:
+                            break;
+
+                        case eStopReasonTrace:
+                        case eStopReasonBreakpoint:
+                        case eStopReasonWatchpoint:
+                        case eStopReasonSignal:
+                        case eStopReasonException:
+                            if (! other_thread.IsValid())
+                                other_thread = thread;
+                            break;
+                        case eStopReasonPlanComplete:
+                            if (! plan_thread.IsValid())
+                                plan_thread = thread;
+                            break;
+                    }
+                }
+            }
+            if (plan_thread.IsValid())
+                process.SetCurrentThreadByID (plan_thread.GetThreadID());
+            else if (other_thread.IsValid())
+                process.SetCurrentThreadByID (other_thread.GetThreadID());
+            else
+            {
+                if (curr_thread.IsValid())
+                    thread = curr_thread;
+                else
+                    thread = process.GetThreadAtIndex(0);
+
+                if (thread.IsValid())
+                    process.SetCurrentThreadByID (thread.GetThreadID());
+            }
+        }
+    }
+}
+
+void
+SBDebugger::ReportCurrentLocation (FILE *out, FILE *err)
+{
+    if ((out == NULL) || (err == NULL))
+        return;
+
+    SBTarget sb_target (GetCurrentTarget());
+    if (!sb_target.IsValid())
+    {
+        fprintf (out, "no target\n");
+        return;
+    }
+
+    SBProcess process = sb_target.GetProcess ();
+    if (process.IsValid())
+    {
+        StateType state = process.GetState();
+
+        if (StateIsStoppedState (state))
+        {
+            if (state == eStateExited)
+            {
+                int exit_status = process.GetExitStatus();
+                const char *exit_description = process.GetExitDescription();
+                ::fprintf (out, "Process %d exited with status = %i (0x%8.8x) %s\n",
+                           process.GetProcessID(),
+                           exit_status,
+                           exit_status,
+                           exit_description ? exit_description : "");
+            }
+            else
+            {
+                fprintf (out, "Process %d %s\n", process.GetProcessID(), StateAsCString (state));
+                SBThread current_thread = process.GetThreadAtIndex (0);
+                if (current_thread.IsValid())
+                {
+                    process.DisplayThreadsInfo (out, err, true);
+                }
+                else
+                    fprintf (out, "No valid thread found in current process\n");
+            }
+        }
+        else
+            fprintf (out, "No current location or status available\n");
+    }
+}
+
+SBSourceManager &
+SBDebugger::GetSourceManager ()
+{
+    static SourceManager g_lldb_source_manager;
+    static SBSourceManager g_sb_source_manager (g_lldb_source_manager);
+    return g_sb_source_manager;
+}
+
+
+bool
+SBDebugger::GetDefaultArchitecture (char *arch_name, size_t arch_name_len)
+{
+    if (arch_name && arch_name_len)
+    {
+        ArchSpec &default_arch = lldb_private::GetDefaultArchitecture ();
+        if (default_arch.IsValid())
+        {
+            ::snprintf (arch_name, arch_name_len, "%s", default_arch.AsCString());
+            return true;
+        }
+    }
+    if (arch_name && arch_name_len)
+        arch_name[0] = '\0';
+    return false;
+}
+
+
+bool
+SBDebugger::SetDefaultArchitecture (const char *arch_name)
+{
+    if (arch_name)
+    {
+        ArchSpec arch (arch_name);
+        if (arch.IsValid())
+        {
+            lldb_private::GetDefaultArchitecture () = arch;
+            return true;
+        }
+    }
+    return false;
+}
+
+ScriptLanguage
+SBDebugger::GetScriptingLanguage (const char *script_language_name)
+{
+    return Args::StringToScriptLanguage (script_language_name,
+                                         eScriptLanguageDefault,
+                                         NULL);
+}
+//pid_t
+/*
+SBDebugger::AttachByName (const char *process_name, const char *filename)
+{
+    SBTarget *temp_target = GetCurrentTarget();
+    SBTarget sb_target;
+    pid_t return_pid = (pid_t) LLDB_INVALID_PROCESS_ID;
+
+    if (temp_target == NULL)
+    {
+        if (filename != NULL)
+        {
+            sb_target = CreateWithFile (filename);
+            sb_target.SetArch (LLDB_ARCH_DEFAULT);
+        }
+    }
+    else
+    {
+          sb_target = *temp_target;
+    }
+
+    if (sb_target.IsValid())
+    {
+        SBProcess process = sb_target.GetProcess ();
+        if (process.IsValid())
+        {
+            return_pid = process.AttachByName (process_name);
+        }
+    }
+    return return_pid;
+}
+*/
+
+const char *
+SBDebugger::GetVersionString ()
+{
+    return lldb_private::GetVersion();
+}
+
+const char *
+SBDebugger::StateAsCString (lldb::StateType state)
+{
+    return lldb_private::StateAsCString (state);
+}
+
+bool
+SBDebugger::StateIsRunningState (lldb::StateType state)
+{
+    return lldb_private::StateIsRunningState (state);
+}
+
+bool
+SBDebugger::StateIsStoppedState (lldb::StateType state)
+{
+    return lldb_private::StateIsStoppedState (state);
+}
+
+
+SBTarget
+SBDebugger::CreateTargetWithFileAndTargetTriple (const char *filename,
+                                                 const char *target_triple)
+{
+    ArchSpec arch;
+    FileSpec file_spec (filename);
+    arch.SetArchFromTargetTriple(target_triple);
+    TargetSP target_sp;
+    Error error (Debugger::GetSharedInstance().GetTargetList().CreateTarget (file_spec, arch, NULL, true, target_sp));
+    SBTarget target(target_sp);
+    return target;
+}
+
+SBTarget
+SBDebugger::CreateTargetWithFileAndArch (const char *filename, const char *archname)
+{
+    FileSpec file (filename);
+    ArchSpec arch = lldb_private::GetDefaultArchitecture();
+    TargetSP target_sp;
+    Error error;
+
+    if (archname != NULL)
+    {
+        ArchSpec arch2 (archname);
+        error = Debugger::GetSharedInstance().GetTargetList().CreateTarget (file, arch2, NULL, true, target_sp);
+    }
+    else
+    {
+        if (!arch.IsValid())
+            arch = LLDB_ARCH_DEFAULT;
+
+        error = Debugger::GetSharedInstance().GetTargetList().CreateTarget (file, arch, NULL, true, target_sp);
+
+        if (error.Fail())
+        {
+            if (arch == LLDB_ARCH_DEFAULT_32BIT)
+                arch = LLDB_ARCH_DEFAULT_64BIT;
+            else
+                arch = LLDB_ARCH_DEFAULT_32BIT;
+
+            error = Debugger::GetSharedInstance().GetTargetList().CreateTarget (file, arch, NULL, true, target_sp);
+        }
+    }
+
+    if (error.Success())
+        Debugger::GetSharedInstance().GetTargetList().SetCurrentTarget (target_sp.get());
+    else
+        target_sp.reset();
+
+    SBTarget sb_target (target_sp);
+    return sb_target;
+}
+
+SBTarget
+SBDebugger::CreateTarget (const char *filename)
+{
+    FileSpec file (filename);
+    ArchSpec arch = lldb_private::GetDefaultArchitecture();
+    TargetSP target_sp;
+    Error error;
+
+    if (!arch.IsValid())
+        arch = LLDB_ARCH_DEFAULT;
+
+    error = Debugger::GetSharedInstance().GetTargetList().CreateTarget (file, arch, NULL, true, target_sp);
+
+    if (error.Fail())
+    {
+        if (arch == LLDB_ARCH_DEFAULT_32BIT)
+            arch = LLDB_ARCH_DEFAULT_64BIT;
+        else
+            arch = LLDB_ARCH_DEFAULT_32BIT;
+
+        error = Debugger::GetSharedInstance().GetTargetList().CreateTarget (file, arch, NULL, true, target_sp);
+    }
+
+    if (!error.Fail())
+        Debugger::GetSharedInstance().GetTargetList().SetCurrentTarget (target_sp.get());
+
+    SBTarget sb_target (target_sp);
+    return sb_target;
+}
+
+SBTarget
+SBDebugger::GetTargetAtIndex (uint32_t idx)
+{
+    SBTarget sb_target (Debugger::GetSharedInstance().GetTargetList().GetTargetAtIndex (idx));
+    return sb_target;
+}
+
+SBTarget
+SBDebugger::FindTargetWithProcessID (pid_t pid)
+{
+    SBTarget sb_target(Debugger::GetSharedInstance().GetTargetList().FindTargetWithProcessID (pid));
+    return sb_target;
+}
+
+SBTarget
+SBDebugger::FindTargetWithFileAndArch (const char *filename, const char *arch_name)
+{
+    ArchSpec arch;
+    if (arch_name)
+        arch.SetArch(arch_name);
+    return SBTarget (Debugger::GetSharedInstance().GetTargetList().FindTargetWithExecutableAndArchitecture (FileSpec(filename),
+                                                                                                            arch_name ? &arch : NULL));
+}
+
+SBTarget
+SBDebugger::FindTargetWithLLDBProcess (const lldb::ProcessSP &process_sp)
+{
+    SBTarget sb_target(Debugger::GetSharedInstance().GetTargetList().FindTargetWithProcess (process_sp.get()));
+    return sb_target;
+}
+
+
+uint32_t
+SBDebugger::GetNumTargets ()
+{
+    return Debugger::GetSharedInstance().GetTargetList().GetNumTargets ();}
+
+SBTarget
+SBDebugger::GetCurrentTarget ()
+{
+    SBTarget sb_target(Debugger::GetSharedInstance().GetTargetList().GetCurrentTarget ());
+    return sb_target;
+}
+
+void
+SBDebugger::DispatchInput (void *baton, const void *data, size_t data_len)
+{
+    Debugger::GetSharedInstance().DispatchInput ((const char *) data, data_len);
+}
+
+void
+SBDebugger::PushInputReader (SBInputReader &reader)
+{
+    if (reader.IsValid())
+    {
+        InputReaderSP reader_sp(*reader);
+        Debugger::GetSharedInstance().PushInputReader (reader_sp);
+    }
+}
diff --git a/source/API/SBError.cpp b/source/API/SBError.cpp
new file mode 100644
index 0000000..7c257c9
--- /dev/null
+++ b/source/API/SBError.cpp
@@ -0,0 +1,179 @@
+//===-- SBError.cpp ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBError.h"
+#include "lldb/Core/Error.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+SBError::SBError () :
+    m_lldb_object_ap ()
+{
+}
+
+SBError::SBError (const SBError &rhs) :
+    m_lldb_object_ap ()
+{
+    if (rhs.IsValid())
+        m_lldb_object_ap.reset (new Error(*rhs));
+}
+
+
+SBError::~SBError()
+{
+}
+
+const SBError &
+SBError::operator = (const SBError &rhs)
+{
+    if (rhs.IsValid())
+    {
+        if (m_lldb_object_ap.get())
+            *m_lldb_object_ap = *rhs;
+        else
+            m_lldb_object_ap.reset (new Error(*rhs));
+    }
+    else
+    {
+        m_lldb_object_ap.reset();
+    }
+    return *this;
+}
+
+
+const char *
+SBError::GetCString () const
+{
+    if (m_lldb_object_ap.get())
+        return m_lldb_object_ap->AsCString();
+    return NULL;
+}
+
+void
+SBError::Clear ()
+{
+    if (m_lldb_object_ap.get())
+        m_lldb_object_ap->Clear();
+}
+
+bool
+SBError::Fail () const
+{
+    if (m_lldb_object_ap.get())
+        return m_lldb_object_ap->Fail();
+    return false;
+}
+
+bool
+SBError::Success () const
+{
+    if (m_lldb_object_ap.get())
+        return m_lldb_object_ap->Success();
+    return false;
+}
+
+uint32_t
+SBError::GetError () const
+{
+    if (m_lldb_object_ap.get())
+        return m_lldb_object_ap->GetError();
+    return true;
+}
+
+ErrorType
+SBError::GetType () const
+{
+    if (m_lldb_object_ap.get())
+        return m_lldb_object_ap->GetType();
+    return eErrorTypeInvalid;
+}
+
+void
+SBError::SetError (uint32_t err, ErrorType type)
+{
+    CreateIfNeeded ();
+    m_lldb_object_ap->SetError (err, type);
+}
+
+void
+SBError::SetError (const Error &lldb_error)
+{
+    CreateIfNeeded ();
+    *m_lldb_object_ap = lldb_error;
+}
+
+
+void
+SBError::SetErrorToErrno ()
+{
+    CreateIfNeeded ();
+    m_lldb_object_ap->SetErrorToErrno ();
+}
+
+void
+SBError::SetErrorToGenericError ()
+{
+    CreateIfNeeded ();
+    m_lldb_object_ap->SetErrorToErrno ();
+}
+
+void
+SBError::SetErrorString (const char *err_str)
+{
+    CreateIfNeeded ();
+    m_lldb_object_ap->SetErrorString (err_str);
+}
+
+int
+SBError::SetErrorStringWithFormat (const char *format, ...)
+{
+    CreateIfNeeded ();
+    va_list args;
+    va_start (args, format);
+    int num_chars = m_lldb_object_ap->SetErrorStringWithVarArg (format, args);
+    va_end (args);
+    return num_chars;
+}
+
+bool
+SBError::IsValid () const
+{
+    return m_lldb_object_ap.get() != NULL;
+}
+
+void
+SBError::CreateIfNeeded ()
+{
+    if (m_lldb_object_ap.get() == NULL)
+        m_lldb_object_ap.reset(new Error ());
+}
+
+
+lldb_private::Error *
+SBError::operator->()
+{
+    return m_lldb_object_ap.get();
+}
+
+lldb_private::Error *
+SBError::get()
+{
+    return m_lldb_object_ap.get();
+}
+
+
+const lldb_private::Error &
+SBError::operator*() const
+{
+    // Be sure to call "IsValid()" before calling this function or it will crash
+    return *m_lldb_object_ap;
+}
+
diff --git a/source/API/SBEvent.cpp b/source/API/SBEvent.cpp
new file mode 100644
index 0000000..c69957e
--- /dev/null
+++ b/source/API/SBEvent.cpp
@@ -0,0 +1,176 @@
+//===-- SBEvent.cpp ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SBEvent.h"
+#include "SBBroadcaster.h"
+
+#include "lldb/Core/Event.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+SBEvent::SBEvent () :
+    m_event_sp (),
+    m_lldb_object (NULL)
+{
+}
+
+SBEvent::SBEvent (uint32_t event_type, const char *cstr, uint32_t cstr_len) :
+    m_event_sp (new Event (event_type, new EventDataBytes (cstr, cstr_len))),
+    m_lldb_object (m_event_sp.get())
+{
+}
+
+SBEvent::SBEvent (EventSP &event_sp) :
+    m_event_sp (event_sp),
+    m_lldb_object (event_sp.get())
+{
+}
+
+SBEvent::~SBEvent()
+{
+}
+
+void
+SBEvent::Dump (FILE *f) const
+{
+    const Event *lldb_event = GetLLDBObjectPtr();
+    if (lldb_event)
+    {
+        StreamFile str(f);
+        lldb_event->Dump ((Stream *) &str);
+    }
+}
+
+const char *
+SBEvent::GetDataFlavor ()
+{
+    Event *lldb_event = SBEvent::GetLLDBObjectPtr();
+    if (lldb_event)
+        return lldb_event->GetData()->GetFlavor().AsCString();
+    return NULL;
+}
+
+uint32_t
+SBEvent::GetType () const
+{
+    const Event *lldb_event = SBEvent::GetLLDBObjectPtr();
+    if (lldb_event)
+        return lldb_event->GetType();
+    return 0;
+}
+
+SBBroadcaster
+SBEvent::GetBroadcaster () const
+{
+    SBBroadcaster broadcaster;
+    const Event *lldb_event = SBEvent::GetLLDBObjectPtr();
+    if (lldb_event)
+        broadcaster.SetLLDBObjectPtr (lldb_event->GetBroadcaster(), false);
+    return broadcaster;
+}
+
+bool
+SBEvent::BroadcasterMatchesPtr (const SBBroadcaster *broadcaster)
+{
+    if (broadcaster)
+    {
+        Event *lldb_event = SBEvent::GetLLDBObjectPtr();
+        if (lldb_event)
+            return lldb_event->BroadcasterIs (broadcaster->GetLLDBObjectPtr ());
+    }
+    return false;
+}
+
+bool
+SBEvent::BroadcasterMatchesRef (const SBBroadcaster &broadcaster)
+{
+    Event *lldb_event = SBEvent::GetLLDBObjectPtr();
+    if (lldb_event)
+        return lldb_event->BroadcasterIs (broadcaster.GetLLDBObjectPtr ());
+    return false;
+}
+
+void
+SBEvent::Clear()
+{
+    Event *lldb_event = SBEvent::GetLLDBObjectPtr();
+    if (lldb_event)
+        lldb_event->Clear();
+}
+
+EventSP &
+SBEvent::GetSharedPtr () const
+{
+    return m_event_sp;
+}
+
+Event *
+SBEvent::GetLLDBObjectPtr ()
+{
+    // There is a dangerous accessor call GetSharedPtr which can be used, so if
+    // we have anything valid in m_event_sp, we must use that since if it gets
+    // used by a function that puts something in there, then it won't update
+    // m_lldb_object...
+    if (m_event_sp)
+        m_lldb_object = m_event_sp.get();
+
+    return m_lldb_object;
+}
+
+const Event *
+SBEvent::GetLLDBObjectPtr () const
+{
+    // There is a dangerous accessor call GetSharedPtr which can be used, so if
+    // we have anything valid in m_event_sp, we must use that since if it gets
+    // used by a function that puts something in there, then it won't update
+    // m_lldb_object...
+    if (m_event_sp)
+        m_lldb_object = m_event_sp.get();
+
+    return m_lldb_object;
+}
+
+void
+SBEvent::SetEventSP (EventSP &event_sp)
+{
+    m_event_sp = event_sp;
+    m_lldb_object = m_event_sp.get();
+}
+
+void
+SBEvent::SetLLDBObjectPtr (Event* event_ptr)
+{
+    m_lldb_object = event_ptr;
+    m_event_sp.reset();
+}
+
+bool
+SBEvent::IsValid() const
+{
+    // Do NOT use m_lldb_object directly!!! Must use the SBEvent::GetLLDBObjectPtr()
+    // accessor. See comments in SBEvent::GetLLDBObjectPtr()....
+    return SBEvent::GetLLDBObjectPtr() != NULL;
+
+}
+
+const char *
+SBEvent::GetCStringFromEvent (const SBEvent &event)
+{
+    return reinterpret_cast<const char *>(EventDataBytes::GetBytesFromEvent (event.GetLLDBObjectPtr()));
+}
+
+
diff --git a/source/API/SBFileSpec.cpp b/source/API/SBFileSpec.cpp
new file mode 100644
index 0000000..48c7511
--- /dev/null
+++ b/source/API/SBFileSpec.cpp
@@ -0,0 +1,133 @@
+//===-- SBFileSpec.cpp ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBFileSpec.h"
+#include "lldb/Core/FileSpec.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+
+SBFileSpec::SBFileSpec () :
+    m_lldb_object_ap()
+{
+}
+
+SBFileSpec::SBFileSpec (const SBFileSpec &rhs) :
+    m_lldb_object_ap()
+{
+    if (rhs.m_lldb_object_ap.get())
+        m_lldb_object_ap.reset (new FileSpec (*m_lldb_object_ap));
+}
+
+SBFileSpec::SBFileSpec (const char *path) :
+    m_lldb_object_ap(new FileSpec (path))
+{
+}
+
+SBFileSpec::~SBFileSpec ()
+{
+}
+
+const SBFileSpec &
+SBFileSpec::operator = (const SBFileSpec &rhs)
+{
+    if (this != &rhs)
+    {
+        if (rhs.IsValid())
+            m_lldb_object_ap.reset (new lldb_private::FileSpec(*rhs.m_lldb_object_ap.get()));
+    }
+    return *this;
+}
+
+bool
+SBFileSpec::IsValid() const
+{
+    return m_lldb_object_ap.get() != NULL;
+}
+
+bool
+SBFileSpec::Exists () const
+{
+    if (m_lldb_object_ap.get())
+        return m_lldb_object_ap->Exists();
+    return false;
+}
+
+
+int
+SBFileSpec::ResolvePath (const char *src_path, char *dst_path, size_t dst_len)
+{
+    return lldb_private::FileSpec::Resolve (src_path, dst_path, dst_len);
+}
+
+const char *
+SBFileSpec::GetFileName() const
+{
+    if (m_lldb_object_ap.get())
+        return m_lldb_object_ap->GetFilename().AsCString();
+    return NULL;
+}
+
+const char *
+SBFileSpec::GetDirectory() const
+{
+    if (m_lldb_object_ap.get())
+        return m_lldb_object_ap->GetDirectory().AsCString();
+    return NULL;
+}
+
+uint32_t
+SBFileSpec::GetPath (char *dst_path, size_t dst_len) const
+{
+    if (m_lldb_object_ap.get())
+        return m_lldb_object_ap->GetPath (dst_path, dst_len);
+
+    if (dst_path && dst_len)
+        *dst_path = '\0';
+    return 0;
+}
+
+
+const lldb_private::FileSpec *
+SBFileSpec::operator->() const
+{
+    return m_lldb_object_ap.get();
+}
+
+const lldb_private::FileSpec *
+SBFileSpec::get() const
+{
+    return m_lldb_object_ap.get();
+}
+
+
+const lldb_private::FileSpec &
+SBFileSpec::operator*() const
+{
+    return *m_lldb_object_ap.get();
+}
+
+const lldb_private::FileSpec &
+SBFileSpec::ref() const
+{
+    return *m_lldb_object_ap.get();
+}
+
+
+void
+SBFileSpec::SetFileSpec (const lldb_private::FileSpec& fs)
+{
+    if (m_lldb_object_ap.get())
+        *m_lldb_object_ap = fs;
+    else
+        m_lldb_object_ap.reset (new FileSpec (fs));
+}
+
diff --git a/source/API/SBFrame.cpp b/source/API/SBFrame.cpp
new file mode 100644
index 0000000..d513e5b
--- /dev/null
+++ b/source/API/SBFrame.cpp
@@ -0,0 +1,394 @@
+//===-- SBFrame.cpp ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SBFrame.h"
+
+#include <string>
+#include <algorithm>
+
+#include "lldb/lldb-types.h"
+
+#include "lldb/Core/Address.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/ValueObjectRegister.h"
+#include "lldb/Core/ValueObjectVariable.h"
+#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Symbol/Variable.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Thread.h"
+
+#include "SBDebugger.h"
+#include "SBValue.h"
+#include "SBAddress.h"
+#include "SBSymbolContext.h"
+#include "SBThread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+SBFrame::SBFrame () :
+    m_lldb_object_sp ()
+{
+}
+
+SBFrame::SBFrame (const lldb::StackFrameSP &lldb_object_sp) :
+    m_lldb_object_sp (lldb_object_sp)
+{
+}
+
+SBFrame::~SBFrame()
+{
+}
+
+
+void
+SBFrame::SetFrame (const lldb::StackFrameSP &lldb_object_sp)
+{
+    m_lldb_object_sp = lldb_object_sp;
+}
+
+
+bool
+SBFrame::IsValid() const
+{
+    return (m_lldb_object_sp.get() != NULL);
+}
+
+SBSymbolContext
+SBFrame::GetSymbolContext (uint32_t resolve_scope) const
+{
+    SBSymbolContext sb_sym_ctx;
+    if (m_lldb_object_sp)
+        sb_sym_ctx.SetSymbolContext(&m_lldb_object_sp->GetSymbolContext (resolve_scope));
+    return sb_sym_ctx;
+}
+
+SBModule
+SBFrame::GetModule () const
+{
+    SBModule sb_module (m_lldb_object_sp->GetSymbolContext (eSymbolContextModule).module_sp);
+    return sb_module;
+}
+
+SBCompileUnit
+SBFrame::GetCompileUnit () const
+{
+    SBCompileUnit sb_comp_unit(m_lldb_object_sp->GetSymbolContext (eSymbolContextCompUnit).comp_unit);
+    return sb_comp_unit;
+}
+
+SBFunction
+SBFrame::GetFunction () const
+{
+    SBFunction sb_function(m_lldb_object_sp->GetSymbolContext (eSymbolContextFunction).function);
+    return sb_function;
+}
+
+SBBlock
+SBFrame::GetBlock () const
+{
+    SBBlock sb_block(m_lldb_object_sp->GetSymbolContext (eSymbolContextBlock).block);
+    return sb_block;
+}
+
+SBLineEntry
+SBFrame::GetLineEntry () const
+{
+    SBLineEntry sb_line_entry(&m_lldb_object_sp->GetSymbolContext (eSymbolContextLineEntry).line_entry);
+    return sb_line_entry;
+}
+
+uint32_t
+SBFrame::GetFrameID () const
+{
+    if (m_lldb_object_sp)
+        return m_lldb_object_sp->GetID();
+    else
+        return UINT32_MAX;
+}
+
+
+lldb::addr_t
+SBFrame::GetPC () const
+{
+    if (m_lldb_object_sp)
+        return m_lldb_object_sp->GetPC().GetLoadAddress (&m_lldb_object_sp->GetThread().GetProcess());
+    return LLDB_INVALID_ADDRESS;
+}
+
+bool
+SBFrame::SetPC (lldb::addr_t new_pc)
+{
+    if (m_lldb_object_sp)
+        return m_lldb_object_sp->GetRegisterContext()->SetPC (new_pc);
+    return false;
+}
+
+lldb::addr_t
+SBFrame::GetSP () const
+{
+    if (m_lldb_object_sp)
+        return m_lldb_object_sp->GetRegisterContext()->GetSP();
+    return LLDB_INVALID_ADDRESS;
+}
+
+
+lldb::addr_t
+SBFrame::GetFP () const
+{
+    if (m_lldb_object_sp)
+        return m_lldb_object_sp->GetRegisterContext()->GetFP();
+    return LLDB_INVALID_ADDRESS;
+}
+
+
+SBAddress
+SBFrame::GetPCAddress () const
+{
+    SBAddress sb_addr;
+    if (m_lldb_object_sp)
+        sb_addr.SetAddress (&m_lldb_object_sp->GetPC());
+    return sb_addr;
+}
+
+void
+SBFrame::Clear()
+{
+    m_lldb_object_sp.reset();
+}
+
+SBValue
+SBFrame::LookupVar (const char *var_name)
+{
+    lldb::VariableSP var_sp;
+    if (IsValid ())
+    {
+        lldb_private::VariableList variable_list;
+        SBSymbolContext sc = GetSymbolContext (eSymbolContextEverything);
+
+        SBBlock block = sc.GetBlock();
+        if (block.IsValid())
+            block.AppendVariables (true, true, &variable_list);
+
+        const uint32_t num_variables = variable_list.GetSize();
+
+        bool found = false;
+        for (int i = 0; i < num_variables && !found; ++i)
+        {
+            var_sp = variable_list.GetVariableAtIndex(i);
+            if (var_sp
+                && (var_sp.get()->GetName() == lldb_private::ConstString(var_name)))
+                found = true;
+        }
+        if (!found)
+            var_sp.reset();
+    }
+    SBValue sb_value (ValueObjectSP (new ValueObjectVariable (var_sp)));
+    return sb_value;
+}
+
+SBValue
+SBFrame::LookupVarInScope (const char *var_name, const char *scope)
+{
+    lldb::VariableSP var_sp;
+    if (IsValid())
+    {
+        std::string scope_str = scope;
+        lldb::ValueType var_scope = eValueTypeInvalid;
+        // Convert scope_str to be all lowercase;
+        std::transform (scope_str.begin(), scope_str.end(), scope_str.begin(), ::tolower);
+
+        if (scope_str.compare ("global") == 0)
+            var_scope = eValueTypeVariableGlobal;
+        else if (scope_str.compare ("local") == 0)
+            var_scope = eValueTypeVariableLocal;
+        else if (scope_str.compare ("parameter") == 0)
+           var_scope = eValueTypeVariableArgument;
+
+        if (var_scope != eValueTypeInvalid)
+        {
+            lldb_private::VariableList variable_list;
+            SBSymbolContext sc = GetSymbolContext (eSymbolContextEverything);
+
+            SBBlock block = sc.GetBlock();
+            if (block.IsValid())
+                block.AppendVariables (true, true, &variable_list);
+
+            const uint32_t num_variables = variable_list.GetSize();
+
+            bool found = false;
+            for (int i = 0; i < num_variables && !found; ++i)
+            {
+                var_sp = variable_list.GetVariableAtIndex(i);
+                if (var_sp
+                    && (var_sp.get()->GetName() == lldb_private::ConstString(var_name))
+                    && var_sp.get()->GetScope() == var_scope)
+                    found = true;
+            }
+            if (!found)
+                var_sp.reset();
+        }
+    }
+    SBValue sb_value (ValueObjectSP (new ValueObjectVariable (var_sp)));
+    return sb_value;
+}
+
+bool
+SBFrame::operator == (const SBFrame &rhs) const
+{
+    return m_lldb_object_sp.get() == rhs.m_lldb_object_sp.get();
+}
+
+bool
+SBFrame::operator != (const SBFrame &rhs) const
+{
+    return m_lldb_object_sp.get() != rhs.m_lldb_object_sp.get();
+}
+
+lldb_private::StackFrame *
+SBFrame::operator->() const
+{
+    return m_lldb_object_sp.get();
+}
+
+lldb_private::StackFrame *
+SBFrame::get() const
+{
+    return m_lldb_object_sp.get();
+}
+
+
+SBThread
+SBFrame::GetThread () const
+{
+    SBThread sb_thread (m_lldb_object_sp->GetThread().GetSP());
+    return sb_thread;
+}
+
+const char *
+SBFrame::Disassemble () const
+{
+    if (m_lldb_object_sp)
+        return m_lldb_object_sp->Disassemble();
+    return NULL;
+}
+
+
+
+lldb_private::StackFrame *
+SBFrame::GetLLDBObjectPtr ()
+{
+    return m_lldb_object_sp.get();
+}
+
+SBValueList
+SBFrame::GetVariables (bool arguments,
+                       bool locals,
+                       bool statics,
+                       bool in_scope_only)
+{
+    SBValueList value_list;
+    if (m_lldb_object_sp)
+    {
+        size_t i;
+        VariableList *variable_list = m_lldb_object_sp->GetVariableList();
+        if (variable_list)
+        {
+            const size_t num_variables = variable_list->GetSize();
+            if (num_variables)
+            {
+                for (i = 0; i < num_variables; ++i)
+                {
+                    VariableSP variable_sp (variable_list->GetVariableAtIndex(i));
+                    if (variable_sp)
+                    {
+                        bool add_variable = false;
+                        switch (variable_sp->GetScope())
+                        {
+                        case eValueTypeVariableGlobal:
+                        case eValueTypeVariableStatic:
+                            add_variable = statics;
+                            break;
+
+                        case eValueTypeVariableArgument:
+                            add_variable = arguments;
+                            break;
+
+                        case eValueTypeVariableLocal:
+                            add_variable = locals;
+                            break;
+                        }
+                        if (add_variable)
+                        {
+                            if (in_scope_only && !variable_sp->IsInScope(m_lldb_object_sp.get()))
+                                continue;
+
+                            value_list.Append(ValueObjectSP (new ValueObjectVariable (variable_sp)));
+                        }
+                    }
+                }
+            }
+        }
+        
+        if (statics)
+        {
+            CompileUnit *frame_comp_unit = m_lldb_object_sp->GetSymbolContext (eSymbolContextCompUnit).comp_unit;
+            
+            if (frame_comp_unit)
+            {
+                variable_list = frame_comp_unit->GetVariableList(true).get();
+                
+                if (variable_list)
+                {
+                    const size_t num_variables = variable_list->GetSize();
+                    if (num_variables)
+                    {
+                        for (i = 0; i < num_variables; ++i)
+                        {
+                            VariableSP variable_sp (variable_list->GetVariableAtIndex(i));
+                            if (variable_sp)
+                            {
+                                value_list.Append(ValueObjectSP (new ValueObjectVariable (variable_sp)));
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return value_list;
+}
+
+lldb::SBValueList
+SBFrame::GetRegisters ()
+{
+    SBValueList value_list;
+    if (m_lldb_object_sp)
+    {
+        RegisterContext *reg_ctx = m_lldb_object_sp->GetRegisterContext();
+        if (reg_ctx)
+        {
+            const uint32_t num_sets = reg_ctx->GetRegisterSetCount();
+            for (uint32_t set_idx = 0; set_idx < num_sets; ++set_idx)
+            {
+                value_list.Append(ValueObjectSP (new ValueObjectRegisterSet (reg_ctx, set_idx)));
+            }
+        }
+    }
+    return value_list;
+}
+
diff --git a/source/API/SBFunction.cpp b/source/API/SBFunction.cpp
new file mode 100644
index 0000000..010a5ec
--- /dev/null
+++ b/source/API/SBFunction.cpp
@@ -0,0 +1,64 @@
+//===-- SBFunction.cpp ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBFunction.h"
+#include "lldb/API/SBProcess.h"
+#include "lldb/Symbol/Function.h"
+
+using namespace lldb;
+
+
+SBFunction::SBFunction () :
+    m_lldb_object_ptr (NULL)
+{
+}
+
+SBFunction::SBFunction (lldb_private::Function *lldb_object_ptr) :
+    m_lldb_object_ptr (lldb_object_ptr)
+{
+}
+
+SBFunction::~SBFunction ()
+{
+    m_lldb_object_ptr = NULL;
+}
+
+bool
+SBFunction::IsValid () const
+{
+    return m_lldb_object_ptr != NULL;
+}
+
+const char *
+SBFunction::GetName() const
+{
+    if (m_lldb_object_ptr)
+        return m_lldb_object_ptr->GetMangled().GetName().AsCString();
+    return NULL;
+}
+
+const char *
+SBFunction::GetMangledName () const
+{
+    if (m_lldb_object_ptr)
+        return m_lldb_object_ptr->GetMangled().GetMangledName().AsCString();
+    return NULL;
+}
+
+bool
+SBFunction::operator == (const SBFunction &rhs) const
+{
+    return m_lldb_object_ptr == rhs.m_lldb_object_ptr;
+}
+
+bool
+SBFunction::operator != (const SBFunction &rhs) const
+{
+    return m_lldb_object_ptr != rhs.m_lldb_object_ptr;
+}
diff --git a/source/API/SBHostOS.cpp b/source/API/SBHostOS.cpp
new file mode 100644
index 0000000..f0af9cd
--- /dev/null
+++ b/source/API/SBHostOS.cpp
@@ -0,0 +1,64 @@
+//===-- SBHostOS.cpp --------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBHostOS.h"
+#include "lldb/API/SBError.h"
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Host/Host.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+
+SBFileSpec
+SBHostOS::GetProgramFileSpec ()
+{
+    SBFileSpec sb_filespec;
+    sb_filespec.SetFileSpec (Host::GetProgramFileSpec ());
+    return sb_filespec;
+}
+
+lldb::thread_t
+SBHostOS::ThreadCreate
+(
+    const char *name,
+    void *(*thread_function)(void *),
+    void *thread_arg,
+    SBError *error_ptr
+)
+{
+    return Host::ThreadCreate (name, thread_function, thread_arg, error_ptr ? error_ptr->get() : NULL);
+}
+
+void
+SBHostOS::ThreadCreated (const char *name)
+{
+    Host::ThreadCreated (name);
+}
+
+bool
+SBHostOS::ThreadCancel (lldb::thread_t thread, SBError *error_ptr)
+{
+    return Host::ThreadCancel (thread, error_ptr ? error_ptr->get() : NULL);
+}
+
+bool
+SBHostOS::ThreadDetach (lldb::thread_t thread, SBError *error_ptr)
+{
+    return Host::ThreadDetach (thread, error_ptr ? error_ptr->get() : NULL);
+}
+
+bool
+SBHostOS::ThreadJoin (lldb::thread_t thread, void **result, SBError *error_ptr)
+{
+    return Host::ThreadJoin (thread, result, error_ptr ? error_ptr->get() : NULL);
+}
+
+
diff --git a/source/API/SBInputReader.cpp b/source/API/SBInputReader.cpp
new file mode 100644
index 0000000..022d732
--- /dev/null
+++ b/source/API/SBInputReader.cpp
@@ -0,0 +1,169 @@
+//===-- SBInputReader.cpp ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "lldb/lldb-enumerations.h"
+
+#include "lldb/API/SBInputReader.h"
+#include "lldb/API/SBError.h"
+#include "lldb/API/SBStringList.h"
+#include "lldb/Core/InputReader.h"
+
+
+using namespace lldb;
+using namespace lldb_private;
+
+SBInputReader::SBInputReader ()  :
+    m_reader_sp (),
+    m_callback_function (NULL),
+    m_callback_baton (NULL)
+
+{
+}
+
+SBInputReader::SBInputReader (const lldb::InputReaderSP &reader_sp) :
+    m_reader_sp (reader_sp)
+{
+}
+
+SBInputReader::SBInputReader (const SBInputReader &rhs) :
+    m_reader_sp (rhs.m_reader_sp)
+{
+}
+
+SBInputReader::~SBInputReader ()
+{
+}
+
+size_t
+SBInputReader::PrivateCallback 
+(
+    void *baton, 
+    InputReader *reader, 
+    lldb::InputReaderAction notification,
+    const char *bytes, 
+    size_t bytes_len
+)
+{
+    SBInputReader *sb_reader = (SBInputReader *)baton;
+    return sb_reader->m_callback_function (sb_reader->m_callback_baton, 
+                                           sb_reader, 
+                                           notification,
+                                           bytes,
+                                           bytes_len);
+}
+
+SBError
+SBInputReader::Initialize 
+(
+    Callback callback_function,
+    void *callback_baton,
+    lldb::InputReaderGranularity granularity,
+    const char *end_token,
+    const char *prompt,
+    bool echo
+)
+{
+    SBError sb_error;
+    m_reader_sp.reset (new InputReader ());
+    
+    m_callback_function = callback_function;
+    m_callback_baton = callback_baton;
+
+    if (m_reader_sp)
+    {
+        sb_error.SetError (m_reader_sp->Initialize (SBInputReader::PrivateCallback,
+                                                    this,
+                                                    granularity,
+                                                    end_token,
+                                                    prompt,
+                                                    echo));
+    }
+
+    if (sb_error.Fail())
+    {
+        m_reader_sp.reset ();
+        m_callback_function = NULL;
+        m_callback_baton = NULL;
+    }
+
+    return sb_error;
+}
+
+bool
+SBInputReader::IsValid () const
+{
+    return (m_reader_sp.get() != NULL);
+}
+
+const SBInputReader &
+SBInputReader::operator = (const SBInputReader &rhs)
+{
+    if (this != &rhs)
+        m_reader_sp = rhs.m_reader_sp;
+    return *this;
+}
+
+lldb_private::InputReader *
+SBInputReader::operator->() const
+{
+    return m_reader_sp.get();
+}
+
+lldb::InputReaderSP &
+SBInputReader::operator *()
+{
+    return m_reader_sp;
+}
+
+const lldb::InputReaderSP &
+SBInputReader::operator *() const
+{
+    return m_reader_sp;
+}
+
+lldb_private::InputReader *
+SBInputReader::get() const
+{
+    return m_reader_sp.get();
+}
+
+bool
+SBInputReader::IsDone () const
+{
+    if (m_reader_sp)
+        return m_reader_sp->IsDone();
+    else
+        return true;
+}
+
+void
+SBInputReader::SetIsDone (bool value)
+{
+    if (m_reader_sp)
+        m_reader_sp->SetIsDone (value);
+}
+
+bool
+SBInputReader::IsActive () const
+{
+    if (m_reader_sp)
+        return m_reader_sp->IsActive();
+    else
+        return false;
+}
+
+InputReaderGranularity
+SBInputReader::GetGranularity ()
+{
+    if (m_reader_sp)
+        return m_reader_sp->GetGranularity();
+    else
+        return eInputReaderGranularityInvalid;
+}
diff --git a/source/API/SBInstruction.cpp b/source/API/SBInstruction.cpp
new file mode 100644
index 0000000..564fda0
--- /dev/null
+++ b/source/API/SBInstruction.cpp
@@ -0,0 +1,74 @@
+//===-- SBInstruction.cpp ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBInstruction.h"
+
+#include "lldb/Core/Disassembler.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//SBInstruction::SBInstruction (lldb_private::Disassembler::Instruction *lldb_insn) :
+//    m_lldb_object_sp (lldb_insn);
+//{
+//}
+
+SBInstruction::SBInstruction ()
+{
+}
+
+SBInstruction::~SBInstruction ()
+{
+}
+
+//bool
+//SBInstruction::IsValid()
+//{
+//    return (m_lldb_object_sp.get() != NULL);
+//}
+
+//size_t
+//SBInstruction::GetByteSize ()
+//{
+//    if (IsValid())
+//    {
+//        return m_lldb_object_sp->GetByteSize();
+//    }
+//    return 0;
+//}
+
+//void
+//SBInstruction::SetByteSize (size_T byte_size)
+//{
+//    if (IsValid ())
+//    {
+//        m_lldb_object_sp->SetByteSize (byte_size);
+//    }
+//}
+
+//bool
+//SBInstruction::DoesBranch ()
+//{
+//    if (IsValid ())
+//    {
+//        return m_lldb_object_sp->DoesBranch ();
+//    }
+//    return false;
+//}
+
+void
+SBInstruction::Print (FILE *out)
+{
+    if (out == NULL)
+        return;
+
+    //StreamFile out_strem (out);
+
+    //m_lldb_object_sp->Dump (out, LLDB_INVALID_ADDRESS, NULL, 0);
+}
diff --git a/source/API/SBInstructionList.cpp b/source/API/SBInstructionList.cpp
new file mode 100644
index 0000000..d34e9d1
--- /dev/null
+++ b/source/API/SBInstructionList.cpp
@@ -0,0 +1,53 @@
+//===-- SBInstructionList.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBInstructionList.h"
+#include "lldb/API/SBInstruction.h"
+
+using namespace lldb;
+
+
+SBInstructionList::SBInstructionList ()
+{
+}
+
+SBInstructionList::~SBInstructionList ()
+{
+}
+
+size_t
+SBInstructionList::GetSize ()
+{
+    return 0;
+}
+
+SBInstruction
+SBInstructionList::GetInstructionAtIndex (uint32_t idx)
+{
+    SBInstruction inst;
+    return inst;
+}
+
+void
+SBInstructionList::Clear ()
+{
+}
+
+void
+SBInstructionList::AppendInstruction (SBInstruction insn)
+{
+}
+
+void
+SBInstructionList::Print (FILE *out)
+{
+    if (out == NULL)
+        return;
+}
+
diff --git a/source/API/SBLineEntry.cpp b/source/API/SBLineEntry.cpp
new file mode 100644
index 0000000..4835400
--- /dev/null
+++ b/source/API/SBLineEntry.cpp
@@ -0,0 +1,158 @@
+//===-- SBLineEntry.cpp -----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBLineEntry.h"
+#include "lldb/Symbol/LineEntry.h"
+
+using namespace lldb;
+
+
+SBLineEntry::SBLineEntry () :
+    m_lldb_object_ap ()
+{
+}
+
+SBLineEntry::SBLineEntry (const SBLineEntry &rhs) :
+    m_lldb_object_ap ()
+{
+    if (rhs.IsValid())
+    {
+        m_lldb_object_ap.reset (new lldb_private::LineEntry (*rhs));
+    }
+}
+
+
+
+SBLineEntry::SBLineEntry (const lldb_private::LineEntry *lldb_object_ptr) :
+    m_lldb_object_ap ()
+{
+    if (lldb_object_ptr)
+        m_lldb_object_ap.reset (new lldb_private::LineEntry(*lldb_object_ptr));
+}
+
+const SBLineEntry &
+SBLineEntry::operator = (const SBLineEntry &rhs)
+{
+    if (this != &rhs)
+    {
+        if (rhs.IsValid())
+            m_lldb_object_ap.reset (new lldb_private::LineEntry(*rhs));
+    }
+    return *this;
+}
+
+void
+SBLineEntry::SetLineEntry (const lldb_private::LineEntry &lldb_object_ref)
+{
+    if (m_lldb_object_ap.get())
+        (*m_lldb_object_ap.get()) = lldb_object_ref;
+    else
+        m_lldb_object_ap.reset (new lldb_private::LineEntry (lldb_object_ref));
+}
+
+
+SBLineEntry::~SBLineEntry ()
+{
+}
+
+
+SBAddress
+SBLineEntry::GetStartAddress () const
+{
+    SBAddress sb_address;
+    if (m_lldb_object_ap.get())
+        sb_address.SetAddress(&m_lldb_object_ap->range.GetBaseAddress());
+    return sb_address;
+}
+
+SBAddress
+SBLineEntry::GetEndAddress () const
+{
+    SBAddress sb_address;
+    if (m_lldb_object_ap.get())
+    {
+        sb_address.SetAddress(&m_lldb_object_ap->range.GetBaseAddress());
+        sb_address.OffsetAddress(m_lldb_object_ap->range.GetByteSize());
+    }
+    return sb_address;
+}
+
+bool
+SBLineEntry::IsValid () const
+{
+    return m_lldb_object_ap.get() != NULL;
+}
+
+
+SBFileSpec
+SBLineEntry::GetFileSpec () const
+{
+    SBFileSpec sb_file_spec;
+    if (m_lldb_object_ap.get() && m_lldb_object_ap->file)
+        sb_file_spec.SetFileSpec(m_lldb_object_ap->file);
+    return sb_file_spec;
+}
+
+uint32_t
+SBLineEntry::GetLine () const
+{
+    if (m_lldb_object_ap.get())
+        return m_lldb_object_ap->line;
+    return 0;
+}
+
+
+uint32_t
+SBLineEntry::GetColumn () const
+{
+    if (m_lldb_object_ap.get())
+        return m_lldb_object_ap->column;
+    return 0;
+}
+
+bool
+SBLineEntry::operator == (const SBLineEntry &rhs) const
+{
+    lldb_private::LineEntry *lhs_ptr = m_lldb_object_ap.get();
+    lldb_private::LineEntry *rhs_ptr = rhs.m_lldb_object_ap.get();
+
+    if (lhs_ptr && rhs_ptr)
+        return lldb_private::LineEntry::Compare (*lhs_ptr, *rhs_ptr) == 0;
+
+    return lhs_ptr == rhs_ptr;
+}
+
+bool
+SBLineEntry::operator != (const SBLineEntry &rhs) const
+{
+    lldb_private::LineEntry *lhs_ptr = m_lldb_object_ap.get();
+    lldb_private::LineEntry *rhs_ptr = rhs.m_lldb_object_ap.get();
+
+    if (lhs_ptr && rhs_ptr)
+        return lldb_private::LineEntry::Compare (*lhs_ptr, *rhs_ptr) != 0;
+
+    return lhs_ptr != rhs_ptr;
+}
+
+const lldb_private::LineEntry *
+SBLineEntry::operator->() const
+{
+    return m_lldb_object_ap.get();
+}
+
+const lldb_private::LineEntry &
+SBLineEntry::operator*() const
+{
+    return *m_lldb_object_ap;
+}
+
+
+
+
+
diff --git a/source/API/SBListener.cpp b/source/API/SBListener.cpp
new file mode 100644
index 0000000..6f2cf7b
--- /dev/null
+++ b/source/API/SBListener.cpp
@@ -0,0 +1,299 @@
+//===-- SBListener.cpp ------------------------------------------*- 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/Listener.h"
+#include "lldb/lldb-forward-rtti.h"
+#include "lldb/Host/TimeValue.h"
+
+#include "SBListener.h"
+#include "SBEvent.h"
+#include "SBBroadcaster.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+SBListener::SBListener ()
+{
+}
+
+SBListener::SBListener (const char *name) :
+    m_lldb_object_ptr (new Listener (name)),
+    m_lldb_object_ptr_owned (true)
+{
+}
+
+SBListener::SBListener (Listener &listener) :
+    m_lldb_object_ptr (&listener),
+    m_lldb_object_ptr_owned (false)
+{
+}
+
+SBListener::~SBListener ()
+{
+    if (m_lldb_object_ptr_owned)
+    {
+        if (m_lldb_object_ptr)
+        {
+            delete m_lldb_object_ptr;
+            m_lldb_object_ptr = NULL;
+        }
+    }
+}
+
+bool
+SBListener::IsValid() const
+{
+    return m_lldb_object_ptr != NULL;
+}
+
+void
+SBListener::AddEvent (const SBEvent &event)
+{
+    EventSP &event_sp = event.GetSharedPtr ();
+    if (event_sp)
+        m_lldb_object_ptr->AddEvent (event_sp);
+}
+
+void
+SBListener::Clear ()
+{
+    if (IsValid())
+        m_lldb_object_ptr->Clear ();
+}
+
+uint32_t
+SBListener::StartListeningForEvents (const SBBroadcaster& broadcaster, uint32_t event_mask)
+{
+    if (IsValid() && broadcaster.IsValid())
+    {
+        return m_lldb_object_ptr->StartListeningForEvents (broadcaster.GetLLDBObjectPtr (), event_mask);
+    }
+    return false;
+}
+
+bool
+SBListener::StopListeningForEvents (const SBBroadcaster& broadcaster, uint32_t event_mask)
+{
+    if (IsValid() && broadcaster.IsValid())
+    {
+        return m_lldb_object_ptr->StopListeningForEvents (broadcaster.GetLLDBObjectPtr (), event_mask);
+    }
+    return false;
+}
+
+bool
+SBListener::WaitForEvent (uint32_t num_seconds, SBEvent &event)
+{
+    if (IsValid())
+    {
+        TimeValue time_value;
+        if (num_seconds != UINT32_MAX)
+        {
+            assert (num_seconds != 0); // Take this out after all calls with timeout set to zero have been removed....
+            time_value = TimeValue::Now();
+            time_value.OffsetWithSeconds (num_seconds);
+        }
+        EventSP event_sp;
+        if (m_lldb_object_ptr->WaitForEvent (time_value.IsValid() ? &time_value : NULL, event_sp))
+        {
+            event.SetEventSP (event_sp);
+            return true;
+        }
+    }
+    event.SetLLDBObjectPtr (NULL);
+    return false;
+}
+
+bool
+SBListener::WaitForEventForBroadcaster
+(
+    uint32_t num_seconds,
+    const SBBroadcaster &broadcaster,
+    SBEvent &event
+)
+{
+    if (IsValid() && broadcaster.IsValid())
+    {
+        TimeValue time_value;
+        if (num_seconds != UINT32_MAX)
+        {
+            time_value = TimeValue::Now();
+            time_value.OffsetWithSeconds (num_seconds);
+        }
+        EventSP event_sp;
+        if (m_lldb_object_ptr->WaitForEventForBroadcaster (time_value.IsValid() ? &time_value : NULL,
+                                                         broadcaster.GetLLDBObjectPtr (),
+                                                         event_sp))
+        {
+            event.SetEventSP (event_sp);
+            return true;
+        }
+
+    }
+    event.SetLLDBObjectPtr (NULL);
+    return false;
+}
+
+bool
+SBListener::WaitForEventForBroadcasterWithType
+(
+    uint32_t num_seconds,
+    const SBBroadcaster &broadcaster,
+    uint32_t event_type_mask,
+    SBEvent &event
+)
+{
+    if (IsValid() && broadcaster.IsValid())
+    {
+        TimeValue time_value;
+        if (num_seconds != UINT32_MAX)
+        {
+            time_value = TimeValue::Now();
+            time_value.OffsetWithSeconds (num_seconds);
+        }
+        EventSP event_sp;
+        if (m_lldb_object_ptr->WaitForEventForBroadcasterWithType (time_value.IsValid() ? &time_value : NULL,
+                                                                 broadcaster.GetLLDBObjectPtr (),
+                                                                 event_type_mask,
+                                                                 event_sp))
+        {
+            event.SetEventSP (event_sp);
+            return true;
+        }
+    }
+    event.SetLLDBObjectPtr (NULL);
+    return false;
+}
+
+bool
+SBListener::PeekAtNextEvent (SBEvent &event)
+{
+    if (m_lldb_object_ptr)
+    {
+        event.SetLLDBObjectPtr (m_lldb_object_ptr->PeekAtNextEvent ());
+        return event.IsValid();
+    }
+    event.SetLLDBObjectPtr (NULL);
+    return false;
+}
+
+bool
+SBListener::PeekAtNextEventForBroadcaster (const SBBroadcaster &broadcaster, SBEvent &event)
+{
+    if (IsValid() && broadcaster.IsValid())
+    {
+        event.SetLLDBObjectPtr (m_lldb_object_ptr->PeekAtNextEventForBroadcaster (broadcaster.GetLLDBObjectPtr ()));
+        return event.IsValid();
+    }
+    event.SetLLDBObjectPtr (NULL);
+    return false;
+}
+
+bool
+SBListener::PeekAtNextEventForBroadcasterWithType (const SBBroadcaster &broadcaster, uint32_t event_type_mask,
+                                                   SBEvent &event)
+{
+    if (IsValid() && broadcaster.IsValid())
+    {
+        event.SetLLDBObjectPtr(m_lldb_object_ptr->PeekAtNextEventForBroadcasterWithType (broadcaster.GetLLDBObjectPtr (), event_type_mask));
+        return event.IsValid();
+    }
+    event.SetLLDBObjectPtr (NULL);
+    return false;
+}
+
+bool
+SBListener::GetNextEvent (SBEvent &event)
+{
+    if (m_lldb_object_ptr)
+    {
+        EventSP event_sp;
+        if (m_lldb_object_ptr->GetNextEvent (event_sp))
+        {
+            event.SetEventSP (event_sp);
+            return true;
+        }
+    }
+    event.SetLLDBObjectPtr (NULL);
+    return false;
+}
+
+bool
+SBListener::GetNextEventForBroadcaster (const SBBroadcaster &broadcaster, SBEvent &event)
+{
+    if (IsValid() && broadcaster.IsValid())
+    {
+        EventSP event_sp;
+        if (m_lldb_object_ptr->GetNextEventForBroadcaster (broadcaster.GetLLDBObjectPtr (), event_sp))
+        {
+            event.SetEventSP (event_sp);
+            return true;
+        }
+    }
+    event.SetLLDBObjectPtr (NULL);
+    return false;
+}
+
+bool
+SBListener::GetNextEventForBroadcasterWithType
+(
+    const SBBroadcaster &broadcaster,
+    uint32_t event_type_mask,
+    SBEvent &event
+)
+{
+    if (IsValid() && broadcaster.IsValid())
+    {
+        EventSP event_sp;
+        if (m_lldb_object_ptr->GetNextEventForBroadcasterWithType (broadcaster.GetLLDBObjectPtr (),
+                                                                 event_type_mask,
+                                                                 event_sp))
+        {
+            event.SetEventSP (event_sp);
+            return true;
+        }
+    }
+    event.SetLLDBObjectPtr (NULL);
+    return false;
+}
+
+bool
+SBListener::HandleBroadcastEvent (const SBEvent &event)
+{
+    if (m_lldb_object_ptr)
+        return m_lldb_object_ptr->HandleBroadcastEvent (event.GetSharedPtr());
+    return false;
+}
+
+lldb_private::Listener *
+SBListener::operator->() const
+{
+    return m_lldb_object_ptr;
+}
+
+lldb_private::Listener *
+SBListener::get() const
+{
+    return m_lldb_object_ptr;
+}
+
+lldb_private::Listener &
+SBListener::operator *()
+{
+    return *m_lldb_object_ptr;
+}
+
+const lldb_private::Listener &
+SBListener::operator *() const
+{
+    return *m_lldb_object_ptr;
+}
+
+
diff --git a/source/API/SBModule.cpp b/source/API/SBModule.cpp
new file mode 100644
index 0000000..6a54c21
--- /dev/null
+++ b/source/API/SBModule.cpp
@@ -0,0 +1,107 @@
+//===-- SBModule.cpp --------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBModule.h"
+#include "lldb/API/SBFileSpec.h"
+#include "lldb/Core/Module.h"
+
+using namespace lldb;
+
+
+SBModule::SBModule () :
+    m_lldb_object_sp ()
+{
+}
+
+SBModule::SBModule (const lldb::ModuleSP& module_sp) :
+    m_lldb_object_sp (module_sp)
+{
+}
+
+SBModule::~SBModule ()
+{
+}
+
+bool
+SBModule::IsValid () const
+{
+    return m_lldb_object_sp.get() != NULL;
+}
+
+SBFileSpec
+SBModule::GetFileSpec () const
+{
+    SBFileSpec file_spec;
+    if (m_lldb_object_sp)
+        file_spec.SetFileSpec(m_lldb_object_sp->GetFileSpec());
+    return file_spec;
+}
+
+const uint8_t *
+SBModule::GetUUIDBytes () const
+{
+    if (m_lldb_object_sp)
+        return (const uint8_t *)m_lldb_object_sp->GetUUID().GetBytes();
+    return NULL;
+}
+
+
+bool
+SBModule::operator == (const SBModule &rhs) const
+{
+    if (m_lldb_object_sp)
+        return m_lldb_object_sp.get() == rhs.m_lldb_object_sp.get();
+    return false;
+}
+
+bool
+SBModule::operator != (const SBModule &rhs) const
+{
+    if (m_lldb_object_sp)
+        return m_lldb_object_sp.get() != rhs.m_lldb_object_sp.get();
+    return false;
+}
+
+lldb::ModuleSP &
+SBModule::operator *()
+{
+    return m_lldb_object_sp;
+}
+
+lldb_private::Module *
+SBModule::operator ->()
+{
+    return m_lldb_object_sp.get();
+}
+
+const lldb_private::Module *
+SBModule::operator ->() const
+{
+    return m_lldb_object_sp.get();
+}
+
+lldb_private::Module *
+SBModule::get()
+{
+    return m_lldb_object_sp.get();
+}
+
+const lldb_private::Module *
+SBModule::get() const
+{
+    return m_lldb_object_sp.get();
+}
+
+
+void
+SBModule::SetModule (const lldb::ModuleSP& module_sp)
+{
+    m_lldb_object_sp = module_sp;
+}
+
diff --git a/source/API/SBProcess.cpp b/source/API/SBProcess.cpp
new file mode 100644
index 0000000..776939c
--- /dev/null
+++ b/source/API/SBProcess.cpp
@@ -0,0 +1,604 @@
+//===-- SBProcess.cpp -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SBProcess.h"
+
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-types.h"
+
+#include "lldb/Core/Args.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/State.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/RegisterContext.h"
+
+// Project includes
+
+#include "SBBroadcaster.h"
+#include "SBDebugger.h"
+#include "SBCommandReturnObject.h"
+#include "SBEvent.h"
+#include "SBThread.h"
+#include "SBStringList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+
+SBProcess::SBProcess () :
+    m_lldb_object_sp()
+{
+}
+
+
+//----------------------------------------------------------------------
+// SBProcess constructor
+//----------------------------------------------------------------------
+
+SBProcess::SBProcess (const SBProcess& rhs) :
+    m_lldb_object_sp (rhs.m_lldb_object_sp)
+{
+}
+
+
+SBProcess::SBProcess (const lldb::ProcessSP &process_sp) :
+    m_lldb_object_sp (process_sp)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+SBProcess::~SBProcess()
+{
+}
+
+void
+SBProcess::SetProcess (const ProcessSP &process_sp)
+{
+    m_lldb_object_sp = process_sp;
+}
+
+void
+SBProcess::Clear ()
+{
+    m_lldb_object_sp.reset();
+}
+
+
+bool
+SBProcess::IsValid() const
+{
+    return m_lldb_object_sp.get() != NULL;
+}
+
+
+uint32_t
+SBProcess::GetNumThreads ()
+{
+    if (m_lldb_object_sp)
+    {
+        const bool can_update = true;
+        return m_lldb_object_sp->GetThreadList().GetSize(can_update);
+    }
+    return 0;
+}
+
+SBThread
+SBProcess::GetCurrentThread () const
+{
+    SBThread sb_thread;
+    if (m_lldb_object_sp)
+        sb_thread.SetThread (m_lldb_object_sp->GetThreadList().GetCurrentThread());
+    return sb_thread;
+}
+
+SBTarget
+SBProcess::GetTarget() const
+{
+    SBTarget sb_target;
+    if (m_lldb_object_sp)
+        sb_target = SBDebugger::FindTargetWithLLDBProcess (m_lldb_object_sp);
+    return sb_target;
+}
+
+
+size_t
+SBProcess::PutSTDIN (const char *src, size_t src_len)
+{
+    if (m_lldb_object_sp != NULL)
+    {
+        Error error;
+        return m_lldb_object_sp->PutSTDIN (src, src_len, error);
+    }
+    else
+        return 0;
+}
+
+size_t
+SBProcess::GetSTDOUT (char *dst, size_t dst_len) const
+{
+    if (m_lldb_object_sp != NULL)
+    {
+        Error error;
+        return m_lldb_object_sp->GetSTDOUT (dst, dst_len, error);
+    }
+    else
+        return 0;
+}
+
+size_t
+SBProcess::GetSTDERR (char *dst, size_t dst_len) const
+{
+    if (m_lldb_object_sp != NULL)
+    {
+        Error error;
+        return m_lldb_object_sp->GetSTDERR (dst, dst_len, error);
+    }
+    else
+        return 0;
+}
+
+void
+SBProcess::ReportCurrentState (const SBEvent &event, FILE *out) const
+{
+    if (out == NULL)
+        return;
+
+    if (m_lldb_object_sp != NULL)
+    {
+        const StateType event_state = SBProcess::GetStateFromEvent (event);
+        char message[1024];
+        int message_len = ::snprintf (message,
+                                      sizeof (message),
+                                      "Process %d %s\n",
+                                      m_lldb_object_sp->GetID(),
+                                      SBDebugger::StateAsCString (event_state));
+
+        if (message_len > 0)
+            ::fwrite (message, 1, message_len, out);
+    }
+}
+
+void
+SBProcess::AppendCurrentStateReport (const SBEvent &event, SBCommandReturnObject &result)
+{
+    if (m_lldb_object_sp != NULL)
+    {
+        const StateType event_state = SBProcess::GetStateFromEvent (event);
+        char message[1024];
+        ::snprintf (message,
+                    sizeof (message),
+                    "Process %d %s\n",
+                    m_lldb_object_sp->GetID(),
+                    SBDebugger::StateAsCString (event_state));
+
+        result.AppendMessage (message);
+    }
+}
+
+bool
+SBProcess::SetCurrentThread (const SBThread &thread)
+{
+    if (m_lldb_object_sp != NULL)
+        return m_lldb_object_sp->GetThreadList().SetCurrentThreadByID (thread.GetThreadID());
+    return false;
+}
+
+bool
+SBProcess::SetCurrentThreadByID (uint32_t tid)
+{
+    if (m_lldb_object_sp != NULL)
+        return m_lldb_object_sp->GetThreadList().SetCurrentThreadByID (tid);
+    return false;
+}
+
+SBThread
+SBProcess::GetThreadAtIndex (size_t index)
+{
+    SBThread thread;
+    if (m_lldb_object_sp)
+        thread.SetThread (m_lldb_object_sp->GetThreadList().GetThreadAtIndex(index));
+    return thread;
+}
+
+StateType
+SBProcess::GetState ()
+{
+    if (m_lldb_object_sp != NULL)
+        return m_lldb_object_sp->GetState();
+    else
+        return eStateInvalid;
+}
+
+
+int
+SBProcess::GetExitStatus ()
+{
+    if (m_lldb_object_sp != NULL)
+        return m_lldb_object_sp->GetExitStatus ();
+    else
+        return 0;
+}
+
+const char *
+SBProcess::GetExitDescription ()
+{
+    if (m_lldb_object_sp != NULL)
+        return m_lldb_object_sp->GetExitDescription ();
+    else
+        return NULL;
+}
+
+lldb::pid_t
+SBProcess::GetProcessID ()
+{
+    if (m_lldb_object_sp)
+        return m_lldb_object_sp->GetID();
+    else
+        return LLDB_INVALID_PROCESS_ID;
+}
+
+uint32_t
+SBProcess::GetAddressByteSize () const
+{
+    if (m_lldb_object_sp)
+        return m_lldb_object_sp->GetAddressByteSize();
+    else
+        return 0;
+}
+
+
+void
+SBProcess::DisplayThreadsInfo (FILE *out, FILE *err, bool only_threads_with_stop_reason)
+{
+    if (m_lldb_object_sp != NULL)
+    {
+        size_t num_thread_infos_dumped = 0;
+        size_t num_threads = GetNumThreads();
+
+        if (out == NULL)
+            out = SBDebugger::GetOutputFileHandle();
+
+        if (err == NULL)
+            err = SBDebugger::GetErrorFileHandle();
+
+        if ((out == NULL) ||(err == NULL))
+            return;
+
+        if (num_threads > 0)
+        {
+            Thread::StopInfo thread_stop_info;
+            SBThread curr_thread (m_lldb_object_sp->GetThreadList().GetCurrentThread());
+            for (int i = 0; i < num_threads; ++i)
+            {
+                SBThread thread (m_lldb_object_sp->GetThreadList().GetThreadAtIndex(i));
+                if (thread.IsValid())
+                {
+                    bool is_current_thread = false;
+                    StreamFile str (out);
+                    if (thread == curr_thread)
+                        is_current_thread = true;
+                    StopReason thread_stop_reason = eStopReasonNone;
+                    if (thread->GetStopInfo (&thread_stop_info))
+                    {
+                        thread_stop_reason = thread_stop_info.GetStopReason();
+                        if (thread_stop_reason == eStopReasonNone)
+                        {
+                            if (only_threads_with_stop_reason && !is_current_thread)
+                                continue;
+                        }
+                    }
+                    ++num_thread_infos_dumped;
+                    fprintf (out, "  %c thread #%u: tid = 0x%4.4x, pc = 0x%16.16llx",
+                             (is_current_thread ? '*' : ' '),
+                             thread->GetIndexID(), thread->GetID(), thread->GetRegisterContext()->GetPC());
+
+                    StackFrameSP frame_sp(thread->GetStackFrameAtIndex (0));
+                    if (frame_sp)
+                    {
+                        SymbolContext sc (frame_sp->GetSymbolContext (eSymbolContextEverything));
+                        fprintf (out, ", where = ");
+                        sc.DumpStopContext (&str, m_lldb_object_sp.get(), frame_sp->GetPC ());
+                    }
+
+                    if (thread_stop_reason != eStopReasonNone)
+                    {
+                        fprintf (out, ", stop reason = ");
+                        thread_stop_info.Dump (&str);
+                    }
+
+                    const char *thread_name = thread->GetName();
+                    if (thread_name && thread_name[0])
+                        fprintf (out, ", thread_name = '%s'", thread_name);
+
+                    fprintf (out, "\n");
+
+                    SBThread sb_thread (thread);
+                    sb_thread.DisplayFramesForCurrentContext (out, err, 0, 1, false, 1);
+                }
+            }
+        }
+    }
+}
+bool
+SBProcess::WaitUntilProcessHasStopped (SBCommandReturnObject &result)
+{
+    bool state_changed = false;
+
+    if (IsValid())
+    {
+        EventSP event_sp;
+        StateType state = m_lldb_object_sp->WaitForStateChangedEvents (NULL, event_sp);
+
+        while (StateIsStoppedState (state))
+        {
+            state = m_lldb_object_sp->WaitForStateChangedEvents (NULL, event_sp);
+            SBEvent event (event_sp);
+            AppendCurrentStateReport (event, result);
+            state_changed = true;
+        }
+    }
+    return state_changed;
+}
+
+SBError
+SBProcess::Continue ()
+{
+    SBError sb_error;
+    if (IsValid())
+        sb_error.SetError(m_lldb_object_sp->Resume());
+    else
+        sb_error.SetErrorString ("SBProcess is invalid");
+
+    return sb_error;
+}
+
+
+SBError
+SBProcess::Destroy ()
+{
+    SBError sb_error;
+    if (m_lldb_object_sp)
+        sb_error.SetError(m_lldb_object_sp->Destroy());
+    else
+        sb_error.SetErrorString ("SBProcess is invalid");
+
+    return sb_error;
+}
+
+
+SBError
+SBProcess::Stop ()
+{
+    SBError sb_error;
+    if (IsValid())
+        sb_error.SetError (m_lldb_object_sp->Halt());
+    else
+        sb_error.SetErrorString ("SBProcess is invalid");
+    return sb_error;
+}
+
+SBError
+SBProcess::Kill ()
+{
+    SBError sb_error;
+    if (m_lldb_object_sp)
+        sb_error.SetError (m_lldb_object_sp->Destroy());
+    else
+        sb_error.SetErrorString ("SBProcess is invalid");
+    return sb_error;
+}
+
+
+SBError
+SBProcess::AttachByName (const char *name, bool wait_for_launch)
+{
+    SBError sb_error;
+    if (m_lldb_object_sp)
+        sb_error.SetError (m_lldb_object_sp->Attach (name, wait_for_launch));
+    else
+        sb_error.SetErrorString ("SBProcess is invalid");
+    return sb_error;
+}
+
+lldb::pid_t
+SBProcess::AttachByPID (lldb::pid_t attach_pid)  // DEPRECATED: will be removed in a few builds in favor of SBError AttachByPID(pid_t)
+{
+    Attach (attach_pid);
+    return GetProcessID();
+}
+
+    
+SBError
+SBProcess::Attach (lldb::pid_t attach_pid)
+{
+    SBError sb_error;
+    if (m_lldb_object_sp)
+        sb_error.SetError  (m_lldb_object_sp->Attach (attach_pid));
+    else
+        sb_error.SetErrorString ("SBProcess is invalid");
+    return sb_error;
+}
+
+SBError
+SBProcess::Detach ()
+{
+    SBError sb_error;
+    if (m_lldb_object_sp)
+        sb_error.SetError (m_lldb_object_sp->Detach());
+    else
+        sb_error.SetErrorString ("SBProcess is invalid");    
+
+    return sb_error;
+}
+
+SBError
+SBProcess::Signal (int signal)
+{
+    SBError sb_error;
+    if (m_lldb_object_sp)
+        sb_error.SetError (m_lldb_object_sp->Signal (signal));
+    else
+        sb_error.SetErrorString ("SBProcess is invalid");    
+    return sb_error;
+}
+
+void
+SBProcess::ListThreads ()
+{    
+    FILE *out = SBDebugger::GetOutputFileHandle();
+    if (out == NULL)
+        return;
+
+    if (m_lldb_object_sp)
+    {
+        size_t num_threads = GetNumThreads ();
+        if (num_threads > 0)
+        {
+            Thread *cur_thread = m_lldb_object_sp->GetThreadList().GetCurrentThread().get();
+            for (int i = 0; i < num_threads; ++i)
+            {
+                Thread *thread = m_lldb_object_sp->GetThreadList().GetThreadAtIndex(i).get();
+                if (thread)
+                {
+                    bool is_current_thread = false;
+                    if (thread == cur_thread)
+                        is_current_thread = true;
+                    fprintf (out, "  [%u] %c tid = 0x%4.4x, pc = 0x%16.16llx",
+                             i,
+                             (is_current_thread ? '*' : ' '),
+                             thread->GetID(),
+                             thread->GetRegisterContext()->GetPC());
+                    const char *thread_name = thread->GetName();
+                    if (thread_name && thread_name[0])
+                        fprintf (out, ", name = %s", thread_name);
+                    const char *queue_name = thread->GetQueueName();
+                    if (queue_name && queue_name[0])
+                        fprintf (out, ", queue = %s", queue_name);
+                    fprintf (out, "\n");
+                }
+            }
+        }
+    }
+}
+
+SBThread
+SBProcess::GetThreadByID (tid_t sb_thread_id)
+{
+    SBThread thread;
+    if (m_lldb_object_sp)
+        thread.SetThread (m_lldb_object_sp->GetThreadList().FindThreadByID ((tid_t) sb_thread_id));
+    return thread;
+}
+
+void
+SBProcess::Backtrace (bool all_threads, uint32_t num_frames)
+{
+    if (m_lldb_object_sp)
+    {
+        if (!all_threads)
+        {
+            SBDebugger::UpdateCurrentThread (*this);
+            SBThread cur_thread = GetCurrentThread();
+            if (cur_thread.IsValid())
+              cur_thread.Backtrace (num_frames);
+        }
+        else
+        {
+            int num_threads = GetNumThreads ();
+            for (int i = 0; i < num_threads; ++i)
+            {
+                SBThread sb_thread = GetThreadAtIndex (i);
+                sb_thread.Backtrace (num_frames);
+            }
+        }
+    }
+}
+
+StateType
+SBProcess::GetStateFromEvent (const SBEvent &event)
+{
+    return Process::ProcessEventData::GetStateFromEvent (event.GetLLDBObjectPtr());
+}
+
+
+bool
+SBProcess::GetRestartedFromEvent (const SBEvent &event)
+{
+    return Process::ProcessEventData::GetRestartedFromEvent (event.GetLLDBObjectPtr());
+}
+
+SBProcess
+SBProcess::GetProcessFromEvent (const SBEvent &event)
+{
+    SBProcess process(Process::ProcessEventData::GetProcessFromEvent (event.GetLLDBObjectPtr()));
+    return process;
+}
+
+
+SBBroadcaster
+SBProcess::GetBroadcaster () const
+{
+    SBBroadcaster broadcaster(m_lldb_object_sp.get(), false);
+    return broadcaster;
+}
+
+lldb_private::Process *
+SBProcess::operator->() const
+{
+    return m_lldb_object_sp.get();
+}
+
+size_t
+SBProcess::ReadMemory (addr_t addr, void *dst, size_t dst_len, SBError &sb_error)
+{
+    size_t bytes_read = 0;
+
+    if (IsValid())
+    {
+        Error error;
+        bytes_read = m_lldb_object_sp->ReadMemory (addr, dst, dst_len, error);
+        sb_error.SetError (error);
+    }
+    else
+    {
+        sb_error.SetErrorString ("SBProcess is invalid");
+    }
+
+    return bytes_read;
+}
+
+size_t
+SBProcess::WriteMemory (addr_t addr, const void *src, size_t src_len, SBError &sb_error)
+{
+    size_t bytes_written = 0;
+
+    if (IsValid())
+    {
+        Error error;
+        bytes_written = m_lldb_object_sp->WriteMemory (addr, src, src_len, error);
+        sb_error.SetError (error);
+    }
+
+    return bytes_written;
+}
+
+// Mimic shared pointer...
+lldb_private::Process *
+SBProcess::get() const
+{
+    return m_lldb_object_sp.get();
+}
+
diff --git a/source/API/SBSourceManager.cpp b/source/API/SBSourceManager.cpp
new file mode 100644
index 0000000..f2dcf65
--- /dev/null
+++ b/source/API/SBSourceManager.cpp
@@ -0,0 +1,65 @@
+//===-- SBSourceManager.cpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "SBSourceManager.h"
+
+#include "lldb/API/SBFileSpec.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/SourceManager.h"
+
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+SBSourceManager::SBSourceManager (SourceManager& source_manager) :
+    m_source_manager (source_manager)
+{
+}
+
+SBSourceManager::~SBSourceManager()
+{
+}
+
+size_t
+SBSourceManager::DisplaySourceLinesWithLineNumbers
+(
+    const SBFileSpec &file,
+    uint32_t line,
+    uint32_t context_before,
+    uint32_t context_after,
+    const char* current_line_cstr,
+    FILE *f
+)
+{
+    if (f == NULL)
+        return 0;
+
+    if (file.IsValid())
+    {
+        StreamFile str (f);
+
+
+        return m_source_manager.DisplaySourceLinesWithLineNumbers (*file,
+                                                                   line,
+                                                                   context_before,
+                                                                   context_after,
+                                                                   current_line_cstr,
+                                                                   &str);
+    }
+    return 0;
+}
+
+SourceManager &
+SBSourceManager::GetLLDBManager ()
+{
+    return m_source_manager;
+}
diff --git a/source/API/SBStringList.cpp b/source/API/SBStringList.cpp
new file mode 100644
index 0000000..b4cfb9b
--- /dev/null
+++ b/source/API/SBStringList.cpp
@@ -0,0 +1,134 @@
+//===-- SBStringList.cpp ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBStringList.h"
+
+#include "lldb/Core/StringList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+SBStringList::SBStringList () :
+    m_lldb_object_ap ()
+{
+}
+
+SBStringList::SBStringList (const lldb_private::StringList *lldb_strings_ptr) :
+    m_lldb_object_ap ()
+{
+    if (lldb_strings_ptr)
+        m_lldb_object_ap.reset (new lldb_private::StringList (*lldb_strings_ptr));
+}
+
+SBStringList::SBStringList (const SBStringList  &rhs) :
+    m_lldb_object_ap ()
+{
+    if (rhs.IsValid())
+        m_lldb_object_ap.reset (new lldb_private::StringList(*rhs));
+}
+
+
+
+SBStringList::~SBStringList ()
+{
+}
+
+
+const SBStringList &
+SBStringList::operator = (const SBStringList &rhs)
+{
+    if (rhs.IsValid())
+        m_lldb_object_ap.reset (new lldb_private::StringList(*rhs));
+
+    return *this;
+}
+
+const lldb_private::StringList *
+SBStringList::operator->() const
+{
+    return m_lldb_object_ap.get();
+}
+
+const lldb_private::StringList &
+SBStringList::operator*() const
+{
+    return *m_lldb_object_ap;
+}
+
+bool
+SBStringList::IsValid() const
+{
+    return (m_lldb_object_ap.get() != NULL);
+}
+
+void
+SBStringList::AppendString (const char *str)
+{
+    if (str != NULL)
+    {
+        if (IsValid())
+            m_lldb_object_ap->AppendString (str);
+        else
+            m_lldb_object_ap.reset (new lldb_private::StringList (str));
+    }
+
+}
+
+void
+SBStringList::AppendList (const char **strv, int strc)
+{
+    if ((strv != NULL)
+        && (strc > 0))
+    {
+        if (IsValid())
+            m_lldb_object_ap->AppendList (strv, strc);
+        else
+            m_lldb_object_ap.reset (new lldb_private::StringList (strv, strc));
+    }
+}
+
+void
+SBStringList::AppendList (SBStringList strings)
+{
+    if (strings.IsValid())
+    {
+        if (! IsValid())
+            m_lldb_object_ap.reset (new lldb_private::StringList());
+        m_lldb_object_ap->AppendList (*(strings.m_lldb_object_ap));
+    }
+}
+
+uint32_t
+SBStringList::GetSize () const
+{
+    if (IsValid())
+    {
+        return m_lldb_object_ap->GetSize();
+    }
+    return 0;
+}
+
+const char *
+SBStringList::GetStringAtIndex (size_t idx)
+{
+    if (IsValid())
+    {
+        return m_lldb_object_ap->GetStringAtIndex (idx);
+    }
+    return NULL;
+}
+
+void
+SBStringList::Clear ()
+{
+    if (IsValid())
+    {
+        m_lldb_object_ap->Clear();
+    }
+}
diff --git a/source/API/SBSymbol.cpp b/source/API/SBSymbol.cpp
new file mode 100644
index 0000000..8500c8b
--- /dev/null
+++ b/source/API/SBSymbol.cpp
@@ -0,0 +1,64 @@
+//===-- SBSymbol.cpp --------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBSymbol.h"
+#include "lldb/Symbol/Symbol.h"
+
+using namespace lldb;
+
+
+SBSymbol::SBSymbol () :
+    m_lldb_object_ptr (NULL)
+{
+}
+
+SBSymbol::SBSymbol (lldb_private::Symbol *lldb_object_ptr) :
+    m_lldb_object_ptr (lldb_object_ptr)
+{
+}
+
+SBSymbol::~SBSymbol ()
+{
+    m_lldb_object_ptr = NULL;
+}
+
+bool
+SBSymbol::IsValid () const
+{
+    return m_lldb_object_ptr != NULL;
+}
+
+const char *
+SBSymbol::GetName() const
+{
+    if (m_lldb_object_ptr)
+        return m_lldb_object_ptr->GetMangled().GetName().AsCString();
+    return NULL;
+}
+
+const char *
+SBSymbol::GetMangledName () const
+{
+    if (m_lldb_object_ptr)
+        return m_lldb_object_ptr->GetMangled().GetMangledName().AsCString();
+    return NULL;
+}
+
+
+bool
+SBSymbol::operator == (const SBSymbol &rhs) const
+{
+    return m_lldb_object_ptr == rhs.m_lldb_object_ptr;
+}
+
+bool
+SBSymbol::operator != (const SBSymbol &rhs) const
+{
+    return m_lldb_object_ptr != rhs.m_lldb_object_ptr;
+}
diff --git a/source/API/SBSymbolContext.cpp b/source/API/SBSymbolContext.cpp
new file mode 100644
index 0000000..dec8529
--- /dev/null
+++ b/source/API/SBSymbolContext.cpp
@@ -0,0 +1,133 @@
+//===-- SBSymbolContext.cpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBSymbolContext.h"
+#include "lldb/Symbol/SymbolContext.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+
+SBSymbolContext::SBSymbolContext () :
+    m_lldb_object_ap ()
+{
+}
+
+SBSymbolContext::SBSymbolContext (const SymbolContext *sc_ptr) :
+    m_lldb_object_ap ()
+{
+    if (sc_ptr)
+        m_lldb_object_ap.reset (new SymbolContext (*sc_ptr));
+}
+
+SBSymbolContext::SBSymbolContext (const SBSymbolContext& rhs) :
+    m_lldb_object_ap ()
+{
+    if (rhs.IsValid())
+        *m_lldb_object_ap = *rhs.m_lldb_object_ap;
+}
+
+SBSymbolContext::~SBSymbolContext ()
+{
+}
+
+const SBSymbolContext &
+SBSymbolContext::operator = (const SBSymbolContext &rhs)
+{
+    if (this != &rhs)
+    {
+        if (rhs.IsValid())
+            m_lldb_object_ap.reset (new lldb_private::SymbolContext(*rhs.m_lldb_object_ap.get()));
+    }
+    return *this;
+}
+
+void
+SBSymbolContext::SetSymbolContext (const SymbolContext *sc_ptr)
+{
+    if (sc_ptr)
+    {
+        if (m_lldb_object_ap.get())
+            *m_lldb_object_ap = *sc_ptr;
+        else
+            m_lldb_object_ap.reset (new SymbolContext (*sc_ptr));
+    }
+    else
+    {
+        if (m_lldb_object_ap.get())
+            m_lldb_object_ap->Clear();
+    }
+}
+
+bool
+SBSymbolContext::IsValid () const
+{
+    return m_lldb_object_ap.get() != NULL;
+}
+
+
+
+SBModule
+SBSymbolContext::GetModule ()
+{
+    SBModule sb_module;
+    if (m_lldb_object_ap.get())
+        sb_module.SetModule(m_lldb_object_ap->module_sp);
+    return sb_module;
+}
+
+SBCompileUnit
+SBSymbolContext::GetCompileUnit ()
+{
+    return SBCompileUnit (m_lldb_object_ap.get() ? m_lldb_object_ap->comp_unit : NULL);
+}
+
+SBFunction
+SBSymbolContext::GetFunction ()
+{
+    return SBFunction (m_lldb_object_ap.get() ? m_lldb_object_ap->function : NULL);
+}
+
+SBBlock
+SBSymbolContext::GetBlock ()
+{
+    return SBBlock (m_lldb_object_ap.get() ? m_lldb_object_ap->block : NULL);
+}
+
+SBLineEntry
+SBSymbolContext::GetLineEntry ()
+{
+    SBLineEntry sb_line_entry;
+    if (m_lldb_object_ap.get())
+        sb_line_entry.SetLineEntry (m_lldb_object_ap->line_entry);
+
+    return sb_line_entry;
+}
+
+SBSymbol
+SBSymbolContext::GetSymbol ()
+{
+    return SBSymbol (m_lldb_object_ap.get() ? m_lldb_object_ap->symbol : NULL);
+}
+
+lldb_private::SymbolContext*
+SBSymbolContext::operator->() const
+{
+    return m_lldb_object_ap.get();
+}
+
+lldb_private::SymbolContext *
+SBSymbolContext::GetLLDBObjectPtr() const
+{
+    return m_lldb_object_ap.get();
+}
+
+
+
diff --git a/source/API/SBTarget.cpp b/source/API/SBTarget.cpp
new file mode 100644
index 0000000..799be37
--- /dev/null
+++ b/source/API/SBTarget.cpp
@@ -0,0 +1,553 @@
+//===-- SBTarget.cpp --------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SBTarget.h"
+
+#include "lldb/lldb-include.h"
+
+#include "lldb/API/SBFileSpec.h"
+#include "lldb/API/SBModule.h"
+#include "lldb/Breakpoint/BreakpointID.h"
+#include "lldb/Breakpoint/BreakpointIDList.h"
+#include "lldb/Breakpoint/BreakpointList.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/AddressResolver.h"
+#include "lldb/Core/AddressResolverName.h"
+#include "lldb/Core/Args.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/SearchFilter.h"
+#include "lldb/Core/STLUtils.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/TargetList.h"
+
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "../source/Commands/CommandObjectBreakpoint.h"
+
+#include "SBDebugger.h"
+#include "SBProcess.h"
+#include "SBListener.h"
+#include "SBBreakpoint.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+#define DEFAULT_DISASM_BYTE_SIZE 32
+
+//----------------------------------------------------------------------
+// SBTarget constructor
+//----------------------------------------------------------------------
+SBTarget::SBTarget ()
+{
+}
+
+SBTarget::SBTarget (const SBTarget& rhs) :
+    m_target_sp (rhs.m_target_sp)
+{
+}
+
+SBTarget::SBTarget(const TargetSP& target_sp) :
+    m_target_sp (target_sp)
+{
+}
+
+const SBTarget&
+SBTarget::Assign (const SBTarget& rhs)
+{
+    if (this != &rhs)
+    {
+        m_target_sp = rhs.m_target_sp;
+    }
+    return *this;
+}
+
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+SBTarget::~SBTarget()
+{
+}
+
+bool
+SBTarget::IsValid () const
+{
+    return m_target_sp.get() != NULL;
+}
+
+SBProcess
+SBTarget::GetProcess ()
+{
+    SBProcess sb_process;
+    if (IsValid())
+        sb_process.SetProcess (m_target_sp->GetProcessSP());
+    return sb_process;
+}
+
+SBProcess
+SBTarget::CreateProcess ()
+{
+    SBProcess sb_process;
+
+    if (IsValid())
+    {
+        SBListener sb_listener = SBDebugger::GetListener();
+        if (sb_listener.IsValid())
+            sb_process.SetProcess (m_target_sp->CreateProcess (*sb_listener));
+    }
+    return sb_process;
+}
+
+SBProcess
+SBTarget::LaunchProcess
+(
+    char const **argv,
+    char const **envp,
+    const char *tty,
+    bool stop_at_entry
+)
+{
+    SBProcess process(GetProcess ());
+    if (!process.IsValid())
+        process = CreateProcess();
+    if (process.IsValid())
+    {
+        Error error (process->Launch (argv, envp, tty, tty, tty));
+        if (error.Success())
+        {
+            if (!stop_at_entry)
+            {
+                StateType state = process->WaitForProcessToStop (NULL);
+                if (state == eStateStopped)
+                    process->Resume();
+            }
+        }
+    }
+    return process;
+}
+
+SBFileSpec
+SBTarget::GetExecutable ()
+{
+    SBFileSpec exe_file_spec;
+    if (IsValid())
+    {
+        ModuleSP exe_module_sp (m_target_sp->GetExecutableModule ());
+        if (exe_module_sp)
+            exe_file_spec.SetFileSpec (exe_module_sp->GetFileSpec());
+    }
+    return exe_file_spec;
+}
+
+
+bool
+SBTarget::DeleteTargetFromList (TargetList *list)
+{
+    if (IsValid())
+        return list->DeleteTarget (m_target_sp);
+    else
+        return false;
+}
+
+bool
+SBTarget::MakeCurrentTarget ()
+{
+    if (IsValid())
+    {
+        Debugger::GetSharedInstance().GetTargetList().SetCurrentTarget (m_target_sp.get());
+        return true;
+    }
+    return false;
+}
+
+bool
+SBTarget::operator == (const SBTarget &rhs) const
+{
+    return m_target_sp.get() == rhs.m_target_sp.get();
+}
+
+bool
+SBTarget::operator != (const SBTarget &rhs) const
+{
+    return m_target_sp.get() != rhs.m_target_sp.get();
+}
+
+lldb_private::Target *
+SBTarget::GetLLDBObjectPtr()
+{
+    return m_target_sp.get();
+}
+const lldb_private::Target *
+SBTarget::GetLLDBObjectPtr() const
+{
+    return m_target_sp.get();
+}
+
+SBBreakpoint
+SBTarget::BreakpointCreateByLocation (const char *file, uint32_t line)
+{
+    SBBreakpoint sb_bp;
+    if (file != NULL && line != 0)
+        sb_bp = BreakpointCreateByLocation (SBFileSpec (file), line);
+    return sb_bp;
+}
+
+SBBreakpoint
+SBTarget::BreakpointCreateByLocation (const SBFileSpec &sb_file_spec, uint32_t line)
+{
+    SBBreakpoint sb_bp;
+    if (m_target_sp.get() && line != 0)
+        *sb_bp = m_target_sp->CreateBreakpoint (NULL, *sb_file_spec, line, true, false);
+    return sb_bp;
+}
+
+SBBreakpoint
+SBTarget::BreakpointCreateByName (const char *symbol_name, const char *module_name)
+{
+    SBBreakpoint sb_bp;
+    if (m_target_sp.get() && symbol_name && symbol_name[0])
+    {
+        if (module_name && module_name[0])
+        {
+            FileSpec module_file_spec(module_name);
+            *sb_bp = m_target_sp->CreateBreakpoint (&module_file_spec, symbol_name, false);
+        }
+        else
+        {
+            *sb_bp = m_target_sp->CreateBreakpoint (NULL, symbol_name, false);
+        }
+    }
+    return sb_bp;
+}
+
+SBBreakpoint
+SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const char *module_name)
+{
+    SBBreakpoint sb_bp;
+    if (m_target_sp.get() && symbol_name_regex && symbol_name_regex[0])
+    {
+        RegularExpression regexp(symbol_name_regex);
+        
+        if (module_name && module_name[0])
+        {
+            FileSpec module_file_spec(module_name);
+            
+            *sb_bp = m_target_sp->CreateBreakpoint (&module_file_spec, regexp, false);
+        }
+        else
+        {
+            *sb_bp = m_target_sp->CreateBreakpoint (NULL, regexp, false);
+        }
+    }
+    return sb_bp;
+}
+
+
+
+SBBreakpoint
+SBTarget::BreakpointCreateByAddress (addr_t address)
+{
+    SBBreakpoint sb_bp;
+    if (m_target_sp.get())
+        *sb_bp = m_target_sp->CreateBreakpoint (address, false);
+    return sb_bp;
+}
+
+void
+SBTarget::ListAllBreakpoints ()
+{
+    FILE *out_file = SBDebugger::GetOutputFileHandle();
+    
+    if (out_file == NULL)
+        return;
+
+    if (IsValid())
+    {
+        const BreakpointList &bp_list = m_target_sp->GetBreakpointList();
+        size_t num_bps = bp_list.GetSize();
+        for (int i = 0; i < num_bps; ++i)
+        {
+            SBBreakpoint sb_breakpoint (bp_list.GetBreakpointByIndex (i));
+            sb_breakpoint.GetDescription (out_file, "full");
+        }
+    }
+}
+
+SBBreakpoint
+SBTarget::FindBreakpointByID (break_id_t bp_id)
+{
+    SBBreakpoint sb_breakpoint;
+    if (m_target_sp && bp_id != LLDB_INVALID_BREAK_ID)
+        *sb_breakpoint = m_target_sp->GetBreakpointByID (bp_id);
+    return sb_breakpoint;
+}
+
+
+bool
+SBTarget::BreakpointDelete (break_id_t bp_id)
+{
+    if (m_target_sp)
+        return m_target_sp->RemoveBreakpointByID (bp_id);
+    return false;
+}
+
+bool
+SBTarget::EnableAllBreakpoints ()
+{
+    if (m_target_sp)
+    {
+        m_target_sp->EnableAllBreakpoints ();
+        return true;
+    }
+    return false;
+}
+
+bool
+SBTarget::DisableAllBreakpoints ()
+{
+    if (m_target_sp)
+    {
+        m_target_sp->DisableAllBreakpoints ();
+        return true;
+    }
+    return false;
+}
+
+bool
+SBTarget::DeleteAllBreakpoints ()
+{
+    if (m_target_sp)
+    {
+        m_target_sp->RemoveAllBreakpoints ();
+        return true;
+    }
+    return false;
+}
+
+
+uint32_t
+SBTarget::GetNumModules () const
+{
+    if (m_target_sp)
+        return m_target_sp->GetImages().GetSize();
+    return 0;
+}
+
+SBModule
+SBTarget::FindModule (const SBFileSpec &sb_file_spec)
+{
+    SBModule sb_module;
+    if (m_target_sp && sb_file_spec.IsValid())
+        sb_module.SetModule (m_target_sp->GetImages().FindFirstModuleForFileSpec (*sb_file_spec, NULL));
+    return sb_module;
+}
+
+SBModule
+SBTarget::GetModuleAtIndex (uint32_t idx)
+{
+    SBModule sb_module;
+    if (m_target_sp)
+        sb_module.SetModule(m_target_sp->GetImages().GetModuleAtIndex(idx));
+    return sb_module;
+}
+
+
+SBBroadcaster
+SBTarget::GetBroadcaster () const
+{
+    SBBroadcaster broadcaster(m_target_sp.get(), false);
+    return broadcaster;
+}
+
+void
+SBTarget::Disassemble (lldb::addr_t file_address_start, lldb::addr_t file_address_end, const char *module_name)
+{
+    if (file_address_start == LLDB_INVALID_ADDRESS)
+        return;
+
+    FILE *out = SBDebugger::GetOutputFileHandle();
+    if (out == NULL)
+        return;
+
+    if (IsValid())
+    {
+        SBModule module;
+        if (module_name != NULL)
+        {
+            SBFileSpec file_spec (module_name);
+            module = FindModule (file_spec);
+        }
+        ArchSpec arch (m_target_sp->GetArchitecture());
+        if (!arch.IsValid())
+          return;
+        Disassembler *disassembler = Disassembler::FindPlugin (arch);
+        if (disassembler == NULL)
+          return;
+
+        // For now, we need a process;  the disassembly functions insist.  If we don't have one already,
+        // make one.
+
+        SBProcess process = GetProcess();
+        if (! process.IsValid())
+          process = CreateProcess();
+
+        ExecutionContext exe_context (process.get());
+
+        if (file_address_end == LLDB_INVALID_ADDRESS
+            || file_address_end < file_address_start)
+          file_address_end = file_address_start + DEFAULT_DISASM_BYTE_SIZE;
+
+        // TO BE FIXED:  SOMEHOW WE NEED TO SPECIFY/USE THE MODULE, IF THE USER SPECIFIED ONE.  I'M NOT
+        // SURE HOW TO DO THAT AT THE MOMENT.  WE ALSO NEED TO FIGURE OUT WHAT TO DO IF THERE ARE MULTIPLE
+        // MODULES CONTAINING THE SPECIFIED ADDRESSES (E.G. THEY HAVEN'T ALL LOADED & BEEN GIVEN UNIQUE
+        // ADDRESSES YET).
+
+        DataExtractor data;
+        size_t bytes_disassembled = disassembler->ParseInstructions (&exe_context, eAddressTypeLoad,
+                                                                     file_address_start,
+                                                                     file_address_end - file_address_start, data);
+
+        if (bytes_disassembled > 0)
+        {
+            size_t num_instructions = disassembler->GetInstructionList().GetSize();
+            uint32_t offset = 0;
+            StreamFile out_stream (out);
+
+            for (size_t i = 0; i < num_instructions; ++i)
+            {
+                Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i);
+                if (inst)
+                {
+                    lldb::addr_t cur_addr = file_address_start + offset;
+                    size_t inst_byte_size = inst->GetByteSize();
+                    inst->Dump (&out_stream, cur_addr, &data, offset, exe_context, false);
+                    out_stream.EOL();
+                    offset += inst_byte_size;
+                }
+            }
+        }
+    }
+}
+
+void
+SBTarget::Disassemble (const char *function_name, const char *module_name)
+{
+    if (function_name == NULL)
+        return;
+    
+    FILE *out = SBDebugger::GetOutputFileHandle();
+    if (out == NULL)
+        return;
+
+    if (IsValid())
+    {
+        SBModule module;
+
+        if (module_name != NULL)
+        {
+            SBFileSpec file_spec (module_name);
+            module = FindModule (file_spec);
+        }
+
+        ArchSpec arch (m_target_sp->GetArchitecture());
+        if (!arch.IsValid())
+          return;
+
+        Disassembler *disassembler = Disassembler::FindPlugin (arch);
+        if (disassembler == NULL)
+          return;
+
+        // For now, we need a process;  the disassembly functions insist.  If we don't have one already,
+        // make one.
+
+        SBProcess process = GetProcess();
+        if (! process.IsValid()
+            ||  process.GetProcessID() == 0)
+        {
+            fprintf (out, "Cannot disassemble functions until after process has launched.\n");
+            return;
+        }
+
+        ExecutionContext exe_context (process.get());
+
+        FileSpec *containing_module = NULL;
+
+        if (module_name != NULL)
+            containing_module = new FileSpec (module_name);
+
+        SearchFilterSP filter_sp (m_target_sp->GetSearchFilterForModule (containing_module));
+        AddressResolverSP resolver_sp (new AddressResolverName (function_name));
+
+        resolver_sp->ResolveAddress (*filter_sp);
+
+        size_t num_matches_found = resolver_sp->GetNumberOfAddresses();
+
+        if (num_matches_found == 1)
+        {
+            DataExtractor data;
+
+            AddressRange func_addresses = resolver_sp->GetAddressRangeAtIndex (0);
+            Address start_addr = func_addresses.GetBaseAddress();
+            lldb::addr_t num_bytes = func_addresses.GetByteSize();
+
+            lldb::addr_t addr = LLDB_INVALID_ADDRESS;
+            size_t bytes_disassembled = 0;
+
+
+            if (process.GetProcessID() == 0)
+            {
+                // Leave this branch in for now, but it should not be reached, since we exit above if the PID is 0.
+                addr = start_addr.GetFileAddress ();
+                bytes_disassembled = disassembler->ParseInstructions (&exe_context, eAddressTypeFile, addr,
+                                                                      num_bytes, data);
+
+            }
+            else
+            {
+                addr = start_addr.GetLoadAddress (process.get());
+                bytes_disassembled = disassembler->ParseInstructions (&exe_context, eAddressTypeLoad, addr,
+                                                                      num_bytes, data);
+
+            }
+
+            if (bytes_disassembled > 0)
+            {
+                size_t num_instructions = disassembler->GetInstructionList().GetSize();
+                uint32_t offset = 0;
+                StreamFile out_stream (out);
+
+                for (size_t i = 0; i < num_instructions; ++i)
+                {
+                    Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i);
+                    if (inst)
+                    {
+                        lldb::addr_t cur_addr = addr + offset;
+                        size_t inst_byte_size = inst->GetByteSize();
+                        inst->Dump (&out_stream, cur_addr, &data, offset, exe_context, false);
+                        out_stream.EOL();
+                        offset += inst_byte_size;
+                    }
+                }
+            }
+        }
+        else if (num_matches_found > 1)
+        {
+            // TO BE FIXED:  Eventually we want to list/disassemble all functions found.
+            fprintf (out, "Function '%s' was found in multiple modules; please specify the desired module name.\n",
+                     function_name);
+        }
+        else
+            fprintf (out, "Function '%s' was not found.\n", function_name);
+    }
+}
diff --git a/source/API/SBThread.cpp b/source/API/SBThread.cpp
new file mode 100644
index 0000000..4ae9ba1
--- /dev/null
+++ b/source/API/SBThread.cpp
@@ -0,0 +1,551 @@
+//===-- SBThread.cpp --------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SBThread.h"
+
+#include "lldb/API/SBSymbolContext.h"
+#include "lldb/API/SBFileSpec.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanContinue.h"
+#include "lldb/Target/ThreadPlanStepInstruction.h"
+#include "lldb/Target/ThreadPlanStepOut.h"
+#include "lldb/Target/ThreadPlanStepRange.h"
+#include "lldb/Target/ThreadPlanStepInRange.h"
+
+
+#include "SBAddress.h"
+#include "SBFrame.h"
+#include "SBSourceManager.h"
+#include "SBDebugger.h"
+#include "SBProcess.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+SBThread::SBThread () :
+    m_lldb_object_sp ()
+{
+}
+
+//----------------------------------------------------------------------
+// Thread constructor
+//----------------------------------------------------------------------
+SBThread::SBThread (const ThreadSP& lldb_object_sp) :
+    m_lldb_object_sp (lldb_object_sp)
+{
+}
+
+SBThread::SBThread (const SBThread &rhs)
+{
+    m_lldb_object_sp = rhs.m_lldb_object_sp;
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+SBThread::~SBThread()
+{
+}
+
+bool
+SBThread::IsValid() const
+{
+    return m_lldb_object_sp != NULL;
+}
+
+StopReason
+SBThread::GetStopReason()
+{
+    if (m_lldb_object_sp)
+    {
+        lldb_private::Thread::StopInfo thread_stop_info;
+        if (m_lldb_object_sp->GetStopInfo(&thread_stop_info))
+            return thread_stop_info.GetStopReason();
+    }
+    return eStopReasonInvalid;
+}
+
+size_t
+SBThread::GetStopDescription (char *dst, size_t dst_len)
+{
+    if (m_lldb_object_sp)
+    {
+        lldb_private::Thread::StopInfo thread_stop_info;
+        if (m_lldb_object_sp->GetStopInfo(&thread_stop_info))
+        {
+            const char *stop_desc = thread_stop_info.GetStopDescription();
+            if (stop_desc)
+            {
+                if (dst)
+                    return ::snprintf (dst, dst_len, "%s", stop_desc);
+                else
+                {
+                    // NULL dst passed in, return the length needed to contain the description
+                    return ::strlen (stop_desc) + 1; // Include the NULL byte for size
+                }
+            }
+            else
+            {
+                const char *stop_desc = NULL;
+                size_t stop_desc_len = 0;
+                switch (thread_stop_info.GetStopReason())
+                {
+                case eStopReasonTrace:
+                case eStopReasonPlanComplete:
+                    {
+                        static char trace_desc[] = "step";
+                        stop_desc = trace_desc;
+                        stop_desc_len = sizeof(trace_desc); // Include the NULL byte for size
+                    }
+                    break;
+
+                case eStopReasonBreakpoint:
+                    {
+                        static char bp_desc[] = "breakpoint hit";
+                        stop_desc = bp_desc;
+                        stop_desc_len = sizeof(bp_desc); // Include the NULL byte for size
+                    }
+                    break;
+
+                case eStopReasonWatchpoint:
+                    {
+                        static char wp_desc[] = "watchpoint hit";
+                        stop_desc = wp_desc;
+                        stop_desc_len = sizeof(wp_desc); // Include the NULL byte for size
+                    }
+                    break;
+
+                case eStopReasonSignal:
+                    {
+                        stop_desc = m_lldb_object_sp->GetProcess().GetUnixSignals ().GetSignalAsCString (thread_stop_info.GetSignal());
+                        if (stop_desc == NULL || stop_desc[0] == '\0')
+                        {
+                            static char signal_desc[] = "signal";
+                            stop_desc = signal_desc;
+                            stop_desc_len = sizeof(signal_desc); // Include the NULL byte for size
+                        }
+                    }
+                    break;
+
+                case eStopReasonException:
+                    {
+                        char exc_desc[] = "exception";
+                        stop_desc = exc_desc;
+                        stop_desc_len = sizeof(exc_desc); // Include the NULL byte for size
+                    }
+                    break;                        
+                }
+                
+                if (stop_desc && stop_desc[0])
+                {
+                    if (dst)
+                        return ::snprintf (dst, dst_len, "%s", stop_desc) + 1; // Include the NULL byte
+
+                    if (stop_desc_len == 0)
+                        stop_desc_len = ::strlen (stop_desc) + 1; // Include the NULL byte
+                        
+                    return stop_desc_len;
+                }
+            }
+        }
+    }
+    if (dst)
+        *dst = 0;
+    return 0;
+}
+
+void
+SBThread::SetThread (const ThreadSP& lldb_object_sp)
+{
+    m_lldb_object_sp = lldb_object_sp;
+}
+
+
+lldb::tid_t
+SBThread::GetThreadID () const
+{
+    if (m_lldb_object_sp)
+        return m_lldb_object_sp->GetID();
+    else
+        return LLDB_INVALID_THREAD_ID;
+}
+
+uint32_t
+SBThread::GetIndexID () const
+{
+    if (m_lldb_object_sp)
+        return m_lldb_object_sp->GetIndexID();
+    return LLDB_INVALID_INDEX32;
+}
+const char *
+SBThread::GetName () const
+{
+    if (m_lldb_object_sp)
+        return m_lldb_object_sp->GetName();
+    return NULL;
+}
+
+const char *
+SBThread::GetQueueName () const
+{
+    if (m_lldb_object_sp)
+        return m_lldb_object_sp->GetQueueName();
+    return NULL;
+}
+
+
+void
+SBThread::DisplayFramesForCurrentContext (FILE *out,
+                                          FILE *err,
+                                          uint32_t first_frame,
+                                          uint32_t num_frames,
+                                          bool show_frame_info,
+                                          uint32_t num_frames_with_source,
+                                          uint32_t source_lines_before,
+                                          uint32_t source_lines_after)
+{
+    if ((out == NULL) || (err == NULL))
+        return;
+
+    if (m_lldb_object_sp)
+    {
+        uint32_t num_stack_frames = m_lldb_object_sp->GetStackFrameCount ();
+        StackFrameSP frame_sp;
+        int frame_idx = 0;
+
+        for (frame_idx = first_frame; frame_idx < first_frame + num_frames; ++frame_idx)
+        {
+            if (frame_idx >= num_stack_frames)
+                break;
+
+            frame_sp = m_lldb_object_sp->GetStackFrameAtIndex (frame_idx);
+            if (!frame_sp)
+                break;
+
+            SBFrame sb_frame (frame_sp);
+            if (DisplaySingleFrameForCurrentContext (out,
+                                                     err,
+                                                     sb_frame,
+                                                     show_frame_info,
+                                                     num_frames_with_source > first_frame - frame_idx,
+                                                     source_lines_before,
+                                                     source_lines_after) == false)
+                break;
+        }
+    }
+}
+
+bool
+SBThread::DisplaySingleFrameForCurrentContext (FILE *out,
+                                               FILE *err,
+                                               SBFrame &frame,
+                                               bool show_frame_info,
+                                               bool show_source,
+                                               uint32_t source_lines_after,
+                                               uint32_t source_lines_before)
+{
+    bool success = false;
+
+     if ((out == NULL) || (err == NULL))
+        return false;
+
+   if (m_lldb_object_sp && frame.IsValid())
+    {
+
+        StreamFile str (out);
+
+        SBSymbolContext sc(frame.GetSymbolContext(eSymbolContextEverything));
+
+        if (show_frame_info && sc.IsValid())
+        {
+            user_id_t frame_idx = (user_id_t) frame.GetFrameID();
+            lldb::addr_t pc = frame.GetPC();
+            ::fprintf (out,
+                       "     frame #%u: tid = 0x%4.4x, pc = 0x%llx ",
+                       frame_idx,
+                       GetThreadID(),
+                       pc);
+            sc->DumpStopContext (&str, &m_lldb_object_sp->GetProcess(), *frame.GetPCAddress());
+            fprintf (out, "\n");
+            success = true;
+        }
+
+        SBCompileUnit comp_unit(sc.GetCompileUnit());
+        if (show_source && comp_unit.IsValid())
+        {
+          success = false;
+            SBLineEntry line_entry;
+            if (line_entry.IsValid())
+            {
+                SBSourceManager& source_manager = SBDebugger::GetSourceManager();
+                SBFileSpec line_entry_file_spec = line_entry.GetFileSpec();
+
+                if (line_entry_file_spec.IsValid())
+                {
+                    source_manager.DisplaySourceLinesWithLineNumbers (line_entry_file_spec,
+                                                                      line_entry.GetLine(),
+                                                                      source_lines_after,
+                                                                      source_lines_before, "->",
+                                                                      out);
+                    success = true;
+                }
+            }
+        }
+    }
+    return success;
+}
+
+void
+SBThread::StepOver (lldb::RunMode stop_other_threads)
+{
+    if (m_lldb_object_sp)
+    {
+        bool abort_other_plans = true;
+        StackFrameSP frame_sp(m_lldb_object_sp->GetStackFrameAtIndex (0));
+
+        if (frame_sp)
+        {
+            if (frame_sp->HasDebugInformation ())
+            {
+                SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
+                m_lldb_object_sp->QueueThreadPlanForStepRange (abort_other_plans, 
+                                                               eStepTypeOver,
+                                                               sc.line_entry.range, 
+                                                               sc,
+                                                               stop_other_threads);
+                
+            }
+            else
+            {
+                m_lldb_object_sp->QueueThreadPlanForStepSingleInstruction (true, 
+                                                                           abort_other_plans, 
+                                                                           stop_other_threads);
+            }
+        }
+
+        Process &process = m_lldb_object_sp->GetProcess();
+        // Why do we need to set the current thread by ID here???
+        process.GetThreadList().SetCurrentThreadByID (m_lldb_object_sp->GetID());
+        process.Resume();
+    }
+}
+
+void
+SBThread::StepInto (lldb::RunMode stop_other_threads)
+{
+    if (m_lldb_object_sp)
+    {
+        bool abort_other_plans = true;
+
+        StackFrameSP frame_sp(m_lldb_object_sp->GetStackFrameAtIndex (0));
+
+        if (frame_sp && frame_sp->HasDebugInformation ())
+        {
+            SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
+            ThreadPlan *new_plan = m_lldb_object_sp->QueueThreadPlanForStepRange (abort_other_plans, 
+                                                                                  eStepTypeInto, 
+                                                                                  sc.line_entry.range, 
+                                                                                  sc, 
+                                                                                  stop_other_threads);
+            if (new_plan)
+            {
+                ThreadPlanStepInRange *real_plan = dynamic_cast<ThreadPlanStepInRange *> (new_plan);
+                if (real_plan)
+                {
+                    bool avoid_no_debug = true;
+                    if (avoid_no_debug)
+                        real_plan->GetFlags().Set (ThreadPlanShouldStopHere::eAvoidNoDebug);
+                    else
+                        real_plan->GetFlags().Clear (ThreadPlanShouldStopHere::eAvoidNoDebug);
+                }
+            }
+        }
+        else
+        {
+            m_lldb_object_sp->QueueThreadPlanForStepSingleInstruction (false, 
+                                                                       abort_other_plans, 
+                                                                       stop_other_threads);
+        }
+
+        Process &process = m_lldb_object_sp->GetProcess();
+        // Why do we need to set the current thread by ID here???
+        process.GetThreadList().SetCurrentThreadByID (m_lldb_object_sp->GetID());
+        process.Resume();
+
+    }
+}
+
+void
+SBThread::StepOut ()
+{
+    if (m_lldb_object_sp)
+    {
+        bool abort_other_plans = true;
+        bool stop_other_threads = true;
+
+        m_lldb_object_sp->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, stop_other_threads, eVoteYes, eVoteNoOpinion);
+
+        Process &process = m_lldb_object_sp->GetProcess();
+        process.GetThreadList().SetCurrentThreadByID (m_lldb_object_sp->GetID());
+        process.Resume();
+    }
+}
+
+void
+SBThread::StepInstruction (bool step_over)
+{
+    if (m_lldb_object_sp)
+    {
+        m_lldb_object_sp->QueueThreadPlanForStepSingleInstruction (step_over, true, true);
+        Process &process = m_lldb_object_sp->GetProcess();
+        process.GetThreadList().SetCurrentThreadByID (m_lldb_object_sp->GetID());
+        process.Resume();
+    }
+}
+
+void
+SBThread::RunToAddress (lldb::addr_t addr)
+{
+    if (m_lldb_object_sp)
+    {
+        bool abort_other_plans = true;
+        bool stop_other_threads = true;
+
+        Address target_addr (NULL, addr);
+
+        m_lldb_object_sp->QueueThreadPlanForRunToAddress (abort_other_plans, target_addr, stop_other_threads);
+        Process &process = m_lldb_object_sp->GetProcess();
+        process.GetThreadList().SetCurrentThreadByID (m_lldb_object_sp->GetID());
+        process.Resume();
+    }
+
+}
+
+void
+SBThread::Backtrace (uint32_t num_frames)
+{
+    bool all_frames = false;
+    if (num_frames < 1)
+        all_frames = true;
+
+    FILE *out = SBDebugger::GetOutputFileHandle();
+    FILE *err = SBDebugger::GetErrorFileHandle();
+    
+    if ((out == NULL) || (err == NULL))
+        return;
+
+    if (m_lldb_object_sp)
+    {
+        if (out && err)
+        {
+            int max_num_frames = m_lldb_object_sp->GetStackFrameCount();
+            int last_frame = max_num_frames;
+
+            if (!all_frames && (num_frames < last_frame))
+                last_frame = num_frames;
+
+            StackFrameSP frame_sp;
+            for (int i = 0; i < last_frame; ++i)
+            {
+                frame_sp = m_lldb_object_sp->GetStackFrameAtIndex (i);
+                if (!frame_sp)
+                    break;
+
+                SBFrame sb_frame (frame_sp);
+                if (DisplaySingleFrameForCurrentContext ((FILE *) out, (FILE *) err, sb_frame, true, false, 0, 0) == false)
+                    break;
+            }
+        }
+    }
+}
+
+SBProcess
+SBThread::GetProcess ()
+{
+    SBProcess process;
+    if (m_lldb_object_sp)
+    {
+        // Have to go up to the target so we can get a shared pointer to our process...
+        process.SetProcess(m_lldb_object_sp->GetProcess().GetTarget().GetProcessSP());
+    }
+    return process;
+}
+
+uint32_t
+SBThread::GetNumFrames ()
+{
+    if (m_lldb_object_sp)
+        return m_lldb_object_sp->GetStackFrameCount();
+    return 0;
+}
+
+SBFrame
+SBThread::GetFrameAtIndex (uint32_t idx)
+{
+    SBFrame sb_frame;
+    if (m_lldb_object_sp)
+        sb_frame.SetFrame (m_lldb_object_sp->GetStackFrameAtIndex (idx));
+    return sb_frame;
+}
+
+const lldb::SBThread &
+SBThread::operator = (const lldb::SBThread &rhs)
+{
+    m_lldb_object_sp = rhs.m_lldb_object_sp;
+    return *this;
+}
+
+bool
+SBThread::operator == (const SBThread &rhs) const
+{
+    return m_lldb_object_sp.get() == rhs.m_lldb_object_sp.get();
+}
+
+bool
+SBThread::operator != (const SBThread &rhs) const
+{
+    return m_lldb_object_sp.get() != rhs.m_lldb_object_sp.get();
+}
+
+lldb_private::Thread *
+SBThread::GetLLDBObjectPtr ()
+{
+    return m_lldb_object_sp.get();
+}
+
+const lldb_private::Thread *
+SBThread::operator->() const
+{
+    return m_lldb_object_sp.get();
+}
+
+const lldb_private::Thread &
+SBThread::operator*() const
+{
+    return *m_lldb_object_sp;
+}
+
+lldb_private::Thread *
+SBThread::operator->()
+{
+    return m_lldb_object_sp.get();
+}
+
+lldb_private::Thread &
+SBThread::operator*()
+{
+    return *m_lldb_object_sp;
+}
diff --git a/source/API/SBType.cpp b/source/API/SBType.cpp
new file mode 100644
index 0000000..d8e836e
--- /dev/null
+++ b/source/API/SBType.cpp
@@ -0,0 +1,23 @@
+//===-- SBType.cpp ----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBType.h"
+#include "lldb/Symbol/ClangASTContext.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+bool
+SBType::IsPointerType (void *opaque_type)
+{
+    return ClangASTContext::IsPointerType (opaque_type);
+}
+
+
diff --git a/source/API/SBValue.cpp b/source/API/SBValue.cpp
new file mode 100644
index 0000000..21f9a0e
--- /dev/null
+++ b/source/API/SBValue.cpp
@@ -0,0 +1,372 @@
+//===-- SBValue.cpp ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SBValue.h"
+
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/Variable.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Thread.h"
+
+#include "SBProcess.h"
+#include "SBTarget.h"
+#include "SBThread.h"
+#include "SBFrame.h"
+#include "SBDebugger.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+SBValue::SBValue () :
+    m_lldb_object_sp ()
+{
+}
+
+SBValue::SBValue (const lldb::ValueObjectSP &value_sp) :
+    m_lldb_object_sp (value_sp)
+{
+}
+
+SBValue::~SBValue()
+{
+}
+
+bool
+SBValue::IsValid () const
+{
+    return  (m_lldb_object_sp.get() != NULL);
+}
+
+void
+SBValue::Print (FILE *out_file, SBFrame *frame, bool print_type, bool print_value)
+{
+    if (out_file == NULL)
+        return;
+
+    if (IsValid())
+    {
+
+        SBThread sb_thread = frame->GetThread();
+        SBProcess sb_process = sb_thread.GetProcess();
+
+        lldb_private::StackFrame *lldb_frame = frame->GetLLDBObjectPtr();
+        lldb_private::Thread *lldb_thread = sb_thread.GetLLDBObjectPtr();
+        lldb_private::Process *lldb_process = sb_process.get();
+
+        lldb_private::ExecutionContext context (lldb_process, lldb_thread, lldb_frame);
+
+        lldb_private::StreamFile out_stream (out_file);
+
+        out_stream.Printf ("%s ", m_lldb_object_sp->GetName().AsCString (NULL));
+        if (! m_lldb_object_sp->IsInScope (lldb_frame))
+            out_stream.Printf ("[out-of-scope] ");
+        if (print_type)
+        {
+            out_stream.Printf ("(%s) ", m_lldb_object_sp->GetTypeName().AsCString ("<unknown-type>"));
+        }
+
+        if (print_value)
+        {
+            ExecutionContextScope *exe_scope = frame->get();
+            const char *val_cstr = m_lldb_object_sp->GetValueAsCString(exe_scope);
+            const char *err_cstr = m_lldb_object_sp->GetError().AsCString();
+
+            if (!err_cstr)
+            {
+                const char *sum_cstr = m_lldb_object_sp->GetSummaryAsCString(exe_scope);
+                const bool is_aggregate =
+                ClangASTContext::IsAggregateType (m_lldb_object_sp->GetOpaqueClangQualType());
+                if (val_cstr)
+                    out_stream.Printf ("= %s ", val_cstr);
+
+                if (sum_cstr)
+                    out_stream.Printf ("%s ", sum_cstr);
+
+                if (is_aggregate)
+                {
+                    out_stream.PutChar ('{');
+                    const uint32_t num_children = m_lldb_object_sp->GetNumChildren();
+                    if (num_children)
+                    {
+                        out_stream.IndentMore();
+                        for (uint32_t idx = 0; idx < num_children; ++idx)
+                        {
+                            lldb::ValueObjectSP child_sp (m_lldb_object_sp->GetChildAtIndex (idx, true));
+                            if (child_sp.get())
+                            {
+                                out_stream.EOL();
+                                out_stream.Indent();
+                                out_stream.Printf ("%s (%s) = %s", child_sp.get()->GetName().AsCString (""),
+                                                   child_sp.get()->GetTypeName().AsCString ("<unknown type>"),
+                                                   child_sp.get()->GetValueAsCString(exe_scope));
+                            }
+                        }
+                        out_stream.IndentLess();
+                    }
+                    out_stream.EOL();
+                    out_stream.Indent ("}");
+                }
+            }
+        }
+        out_stream.EOL ();
+    }
+}
+
+const char *
+SBValue::GetName()
+{
+    if (IsValid())
+        return m_lldb_object_sp->GetName().AsCString();
+    else
+        return NULL;
+}
+
+const char *
+SBValue::GetTypeName ()
+{
+    if (IsValid())
+        return m_lldb_object_sp->GetTypeName().AsCString();
+    else
+        return NULL;
+}
+
+size_t
+SBValue::GetByteSize ()
+{
+    size_t result = 0;
+
+    if (IsValid())
+        result = m_lldb_object_sp->GetByteSize();
+
+    return result;
+}
+
+bool
+SBValue::IsInScope (const SBFrame &frame)
+{
+    bool result = false;
+
+    if (IsValid())
+        result = m_lldb_object_sp->IsInScope (frame.get());
+
+    return result;
+}
+
+const char *
+SBValue::GetValue (const SBFrame &frame)
+{
+    const char *value_string = NULL;
+    if ( m_lldb_object_sp)
+        value_string = m_lldb_object_sp->GetValueAsCString(frame.get());
+    return value_string;
+}
+
+bool
+SBValue::GetValueDidChange ()
+{
+    if (IsValid())
+        return m_lldb_object_sp->GetValueDidChange();
+    return false;
+}
+
+const char *
+SBValue::GetSummary (const SBFrame &frame)
+{
+    const char *value_string = NULL;
+    if ( m_lldb_object_sp)
+        value_string = m_lldb_object_sp->GetSummaryAsCString(frame.get());
+    return value_string;
+}
+
+const char *
+SBValue::GetLocation (const SBFrame &frame)
+{
+    const char *value_string = NULL;
+    if (IsValid())
+        value_string = m_lldb_object_sp->GetLocationAsCString(frame.get());
+    return value_string;
+}
+
+bool
+SBValue::SetValueFromCString (const SBFrame &frame, const char *value_str)
+{
+    bool success = false;
+    if (IsValid())
+        success = m_lldb_object_sp->SetValueFromCString (frame.get(), value_str);
+    return success;
+}
+
+SBValue
+SBValue::GetChildAtIndex (uint32_t idx)
+{
+    lldb::ValueObjectSP child_sp;
+
+    if (IsValid())
+    {
+        child_sp = m_lldb_object_sp->GetChildAtIndex (idx, true);
+    }
+
+    SBValue sb_value (child_sp);
+    return sb_value;
+}
+
+uint32_t
+SBValue::GetIndexOfChildWithName (const char *name)
+{
+    if (IsValid())
+        return m_lldb_object_sp->GetIndexOfChildWithName (ConstString(name));
+    return UINT32_MAX;
+}
+
+SBValue
+SBValue::GetChildMemberWithName (const char *name)
+{
+    lldb::ValueObjectSP child_sp;
+    const ConstString str_name (name);
+
+    if (IsValid())
+    {
+        child_sp = m_lldb_object_sp->GetChildMemberWithName (str_name, true);
+    }
+
+    SBValue sb_value (child_sp);
+    return sb_value;
+}
+
+
+uint32_t
+SBValue::GetNumChildren ()
+{
+    uint32_t num_children = 0;
+
+    if (IsValid())
+    {
+        num_children = m_lldb_object_sp->GetNumChildren();
+    }
+
+    return num_children;
+}
+
+bool
+SBValue::ValueIsStale ()
+{
+    bool result = true;
+
+    if (IsValid())
+    {
+        result = m_lldb_object_sp->GetValueIsValid();
+    }
+
+    return result;
+}
+
+
+SBValue
+SBValue::Dereference ()
+{
+    if (IsValid())
+    {
+        if (m_lldb_object_sp->IsPointerType())
+        {
+            return GetChildAtIndex(0);
+        }
+    }
+    return *this;
+}
+
+bool
+SBValue::TypeIsPtrType ()
+{
+    bool is_ptr_type = false;
+
+    if (IsValid())
+    {
+        is_ptr_type = m_lldb_object_sp->IsPointerType();
+    }
+
+    return is_ptr_type;
+}
+
+
+lldb_private::ExecutionContext
+SBValue::GetCurrentExecutionContext ()
+{
+    lldb_private::Process *process = NULL;
+    lldb_private::Thread *thread = NULL;
+    lldb_private::StackFrame *frame = NULL;
+
+    SBTarget sb_target = SBDebugger::GetCurrentTarget();
+    if (sb_target.IsValid())
+    {
+        SBProcess sb_process = sb_target.GetProcess();
+        if (sb_process.IsValid())
+        {
+            process = sb_process.get();
+            SBThread sb_thread = sb_process.GetCurrentThread();
+            if (sb_thread.IsValid())
+            {
+                thread = sb_thread.GetLLDBObjectPtr();
+                frame = thread->GetStackFrameAtIndex(0).get();
+                lldb_private::ExecutionContext exe_context (process, thread, frame);
+                return exe_context;
+            }
+            else
+            {
+                lldb_private::ExecutionContext exe_context (process, NULL, NULL);
+                return exe_context;
+            }
+        }
+    }
+
+    lldb_private::ExecutionContext exe_context (NULL, NULL, NULL);
+    return exe_context;
+}
+
+
+void *
+SBValue::GetOpaqueType()
+{
+    if (m_lldb_object_sp)
+        return m_lldb_object_sp->GetOpaqueClangQualType();
+    return NULL;
+}
+
+// Mimic shared pointer...
+lldb_private::ValueObject *
+SBValue::get() const
+{
+    return m_lldb_object_sp.get();
+}
+
+lldb_private::ValueObject *
+SBValue::operator->() const
+{
+    return m_lldb_object_sp.get();
+}
+
+lldb::ValueObjectSP &
+SBValue::operator*()
+{
+    return m_lldb_object_sp;
+}
+
+const lldb::ValueObjectSP &
+SBValue::operator*() const
+{
+    return m_lldb_object_sp;
+}
diff --git a/source/API/SBValueList.cpp b/source/API/SBValueList.cpp
new file mode 100644
index 0000000..e7cbfad
--- /dev/null
+++ b/source/API/SBValueList.cpp
@@ -0,0 +1,140 @@
+//===-- SBValueList.cpp -----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "lldb/API/SBValueList.h"
+#include "lldb/API/SBValue.h"
+
+#include "lldb/Core/ValueObjectList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+SBValueList::SBValueList () :
+    m_lldb_object_ap ()
+{
+}
+
+SBValueList::SBValueList (const SBValueList &rhs) :
+    m_lldb_object_ap ()
+{
+    if (rhs.IsValid())
+        m_lldb_object_ap.reset (new lldb_private::ValueObjectList (*rhs));
+}
+
+SBValueList::SBValueList (const lldb_private::ValueObjectList *lldb_object_ptr) :
+    m_lldb_object_ap ()
+{
+    if (lldb_object_ptr)
+        m_lldb_object_ap.reset (new lldb_private::ValueObjectList (*lldb_object_ptr));
+}
+
+SBValueList::~SBValueList ()
+{
+}
+
+bool
+SBValueList::IsValid () const
+{
+    return (m_lldb_object_ap.get() != NULL);
+}
+
+const SBValueList &
+SBValueList::operator = (const SBValueList &rhs)
+{
+    if (this != &rhs)
+    {
+        if (rhs.IsValid())
+            m_lldb_object_ap.reset (new lldb_private::ValueObjectList (*rhs));
+        else
+            m_lldb_object_ap.reset ();
+    }
+    return *this;
+}
+
+lldb_private::ValueObjectList *
+SBValueList::operator->()
+{
+    return m_lldb_object_ap.get();
+}
+
+lldb_private::ValueObjectList &
+SBValueList::operator*()
+{
+    return *m_lldb_object_ap;
+}
+
+const lldb_private::ValueObjectList *
+SBValueList::operator->() const
+{
+    return m_lldb_object_ap.get();
+}
+
+const lldb_private::ValueObjectList &
+SBValueList::operator*() const
+{
+    return *m_lldb_object_ap;
+}
+
+void
+SBValueList::Append (const SBValue &val_obj)
+{
+    if (val_obj.get())
+    {
+        CreateIfNeeded ();
+        m_lldb_object_ap->Append (*val_obj);
+    }
+}
+
+void
+SBValueList::Append (lldb::ValueObjectSP& val_obj_sp)
+{
+    if (val_obj_sp)
+    {
+        CreateIfNeeded ();
+        m_lldb_object_ap->Append (val_obj_sp);
+    }
+}
+
+
+SBValue
+SBValueList::GetValueAtIndex (uint32_t idx) const
+{
+    SBValue sb_value;
+    if (m_lldb_object_ap.get())
+        *sb_value = m_lldb_object_ap->GetValueObjectAtIndex (idx);
+    return sb_value;
+}
+
+uint32_t
+SBValueList::GetSize () const
+{
+    uint32_t size = 0;
+    if (m_lldb_object_ap.get())
+        size = m_lldb_object_ap->GetSize();
+    return size;
+}
+
+void
+SBValueList::CreateIfNeeded ()
+{
+    if (m_lldb_object_ap.get() == NULL)
+        m_lldb_object_ap.reset (new ValueObjectList());
+}
+
+
+SBValue
+SBValueList::FindValueObjectByUID (lldb::user_id_t uid)
+{
+    SBValue sb_value;
+    if ( m_lldb_object_ap.get())
+        *sb_value = m_lldb_object_ap->FindValueObjectByUID (uid);
+    return sb_value;
+}
+
diff --git a/source/Breakpoint/Breakpoint.cpp b/source/Breakpoint/Breakpoint.cpp
new file mode 100644
index 0000000..c475cf0
--- /dev/null
+++ b/source/Breakpoint/Breakpoint.cpp
@@ -0,0 +1,516 @@
+//===-- Breakpoint.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
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+#include "lldb/Core/Address.h"
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/BreakpointResolver.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/SearchFilter.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/lldb-private-log.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+const ConstString &
+Breakpoint::GetEventIdentifier ()
+{
+    static ConstString g_identifier("event-identifier.breakpoint.changed");
+    return g_identifier;
+}
+
+//----------------------------------------------------------------------
+// Breakpoint constructor
+//----------------------------------------------------------------------
+Breakpoint::Breakpoint(Target &target, SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp) :
+    m_target (target),
+    m_filter_sp (filter_sp),
+    m_resolver_sp (resolver_sp),
+    m_options (),
+    m_locations ()
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+Breakpoint::~Breakpoint()
+{
+}
+
+bool
+Breakpoint::IsInternal () const
+{
+    return LLDB_BREAK_ID_IS_INTERNAL(m_bid);
+}
+
+
+
+Target&
+Breakpoint::GetTarget ()
+{
+    return m_target;
+}
+
+const Target&
+Breakpoint::GetTarget () const
+{
+    return m_target;
+}
+
+BreakpointLocationSP
+Breakpoint::AddLocation (Address &addr, bool *new_location)
+{
+    BreakpointLocationSP bp_loc_sp (m_locations.FindByAddress(addr));
+    if (bp_loc_sp)
+    {
+        if (new_location)
+            *new_location = false;
+        return bp_loc_sp;
+    }
+
+    bp_loc_sp.reset (new BreakpointLocation (m_locations.GetNextID(), *this, addr));
+    m_locations.Add (bp_loc_sp);
+    bp_loc_sp->ResolveBreakpointSite();
+
+    if (new_location)
+        *new_location = true;
+    return bp_loc_sp;
+}
+
+BreakpointLocationSP
+Breakpoint::FindLocationByAddress (Address &addr)
+{
+    return m_locations.FindByAddress(addr);
+}
+
+break_id_t
+Breakpoint::FindLocationIDByAddress (Address &addr)
+{
+    return m_locations.FindIDByAddress(addr);
+}
+
+BreakpointLocationSP
+Breakpoint::FindLocationByID (break_id_t bp_loc_id)
+{
+    return m_locations.FindByID(bp_loc_id);
+}
+
+BreakpointLocationSP
+Breakpoint::GetLocationAtIndex (uint32_t index)
+{
+    return m_locations.GetByIndex(index);
+}
+
+BreakpointLocationSP
+Breakpoint::GetLocationSP (BreakpointLocation *bp_loc_ptr)
+{
+    assert (bp_loc_ptr->GetBreakpoint().GetID() == GetID());
+    return m_locations.FindByID(bp_loc_ptr->GetID());
+}
+
+
+// For each of the overall options we need to decide how they propagate to
+// the location options.  This will determine the precedence of options on
+// the breakpoint vrs. its locations.
+
+// Disable at the breakpoint level should override the location settings.
+// That way you can conveniently turn off a whole breakpoint without messing
+// up the individual settings.
+
+void
+Breakpoint::SetEnabled (bool enable)
+{
+    m_options.SetEnabled(enable);
+    if (enable)
+        m_locations.ResolveAllBreakpointSites();
+    else
+        m_locations.ClearAllBreakpointSites();
+}
+
+bool
+Breakpoint::IsEnabled ()
+{
+    return m_options.IsEnabled();
+}
+
+void
+Breakpoint::SetIgnoreCount (int32_t n)
+{
+    m_options.SetIgnoreCount(n);
+}
+
+int32_t
+Breakpoint::GetIgnoreCount () const
+{
+    return m_options.GetIgnoreCount();
+}
+
+void
+Breakpoint::SetThreadID (lldb::tid_t thread_id)
+{
+    m_options.SetThreadID(thread_id);
+}
+
+lldb::tid_t
+Breakpoint::GetThreadID ()
+{
+    return m_options.GetThreadID();
+}
+
+// This function is used when "baton" doesn't need to be freed
+void
+Breakpoint::SetCallback (BreakpointHitCallback callback, void *baton, bool is_synchronous)
+{
+    // The default "Baton" class will keep a copy of "baton" and won't free
+    // or delete it when it goes goes out of scope.
+    m_options.SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous);
+}
+
+// This function is used when a baton needs to be freed and therefore is 
+// contained in a "Baton" subclass.
+void
+Breakpoint::SetCallback (BreakpointHitCallback callback, const BatonSP &callback_baton_sp, bool is_synchronous)
+{
+    m_options.SetCallback(callback, callback_baton_sp, is_synchronous);
+}
+
+void
+Breakpoint::ClearCallback ()
+{
+    m_options.ClearCallback ();
+}
+
+bool
+Breakpoint::InvokeCallback (StoppointCallbackContext *context, break_id_t bp_loc_id)
+{
+    return m_options.InvokeCallback (context, GetID(), bp_loc_id);
+}
+
+BreakpointOptions *
+Breakpoint::GetOptions ()
+{
+    return &m_options;
+}
+
+void
+Breakpoint::ResolveBreakpoint ()
+{
+    if (m_resolver_sp)
+        m_resolver_sp->ResolveBreakpoint(*m_filter_sp);
+}
+
+void
+Breakpoint::ResolveBreakpointInModules (ModuleList &module_list)
+{
+    if (m_resolver_sp)
+        m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list);
+}
+
+void
+Breakpoint::ClearAllBreakpointSites ()
+{
+    m_locations.ClearAllBreakpointSites();
+}
+
+//----------------------------------------------------------------------
+// ModulesChanged: Pass in a list of new modules, and
+//----------------------------------------------------------------------
+
+void
+Breakpoint::ModulesChanged (ModuleList &module_list, bool load)
+{
+    if (load)
+    {
+        // The logic for handling new modules is:
+        // 1) If the filter rejects this module, then skip it.
+        // 2) Run through the current location list and if there are any locations
+        //    for that module, we mark the module as "seen" and we don't try to re-resolve
+        //    breakpoint locations for that module.
+        //    However, we do add breakpoint sites to these locations if needed.
+        // 3) If we don't see this module in our breakpoint location list, call ResolveInModules.
+
+        ModuleList new_modules;  // We'll stuff the "unseen" modules in this list, and then resolve
+                                   // them after the locations pass.  Have to do it this way because
+                                   // resolving breakpoints will add new locations potentially.
+
+        for (int i = 0; i < module_list.GetSize(); i++)
+        {
+            bool seen = false;
+            ModuleSP module_sp (module_list.GetModuleAtIndex (i));
+            Module *module = module_sp.get();
+            if (!m_filter_sp->ModulePasses (module_sp))
+                continue;
+
+            for (int i = 0; i < m_locations.GetSize(); i++)
+            {
+                BreakpointLocationSP break_loc = m_locations.GetByIndex(i);
+                const Section *section = break_loc->GetAddress().GetSection();
+                if (section == NULL || section->GetModule() == module)
+                {
+                    if (!seen)
+                        seen = true;
+
+                    if (!break_loc->ResolveBreakpointSite())
+                    {
+                        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+                        if (log)
+                            log->Printf ("Warning: could not set breakpoint site for breakpoint location %d of breakpoint %d.\n",
+                                         break_loc->GetID(), GetID());
+                    }
+                }
+            }
+
+            if (!seen)
+                new_modules.AppendInNeeded (module_sp);
+
+        }
+        if (new_modules.GetSize() > 0)
+        {
+            ResolveBreakpointInModules(new_modules);
+        }
+    }
+    else
+    {
+        // Go through the currently set locations and if any have breakpoints in
+        // the module list, then remove their breakpoint sites.
+        // FIXME: Think about this...  Maybe it's better to delete the locations?
+        // Are we sure that on load-unload-reload the module pointer will remain
+        // the same?  Or do we need to do an equality on modules that is an
+        // "equivalence"???
+
+        for (int i = 0; i < module_list.GetSize(); i++)
+        {
+            ModuleSP module_sp (module_list.GetModuleAtIndex (i));
+            if (!m_filter_sp->ModulePasses (module_sp))
+                continue;
+
+            for (int i = 0; i < m_locations.GetSize(); i++)
+            {
+                BreakpointLocationSP break_loc = m_locations.GetByIndex(i);
+                const Section *section = break_loc->GetAddress().GetSection();
+                if (section)
+                {
+                    if (section->GetModule() == module_sp.get())
+                        break_loc->ClearBreakpointSite();
+                }
+//                else
+//                {
+//                    Address temp_addr;
+//                    if (module->ResolveLoadAddress(break_loc->GetLoadAddress(), m_target->GetProcess(), temp_addr))
+//                        break_loc->ClearBreakpointSite();
+//                }
+            }
+        }
+    }
+}
+
+void
+Breakpoint::Dump (Stream *)
+{
+}
+
+size_t
+Breakpoint::GetNumResolvedLocations() const
+{
+    // Return the number of breakpoints that are actually resolved and set
+    // down in the inferior process.
+    return m_locations.GetNumResolvedLocations();
+}
+
+size_t
+Breakpoint::GetNumLocations() const
+{
+    return m_locations.GetSize();
+}
+
+void
+Breakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_locations)
+{
+    assert (s != NULL);
+    StreamString filter_strm;
+
+
+    s->Printf("%i ", GetID());
+    GetResolverDescription (s);
+    GetFilterDescription (&filter_strm);
+    if (filter_strm.GetString().compare ("No Filter") != 0)
+    {
+        s->Printf (", ");
+        GetFilterDescription (s);
+    }
+
+    const uint32_t num_locations = GetNumLocations ();
+    const uint32_t num_resolved_locations = GetNumResolvedLocations ();
+
+    switch (level)
+    {
+    case lldb::eDescriptionLevelBrief:
+    case lldb::eDescriptionLevelFull:
+        if (num_locations > 0)
+        {
+            s->Printf(" with %u location%s", num_locations, num_locations > 1 ? "s" : "");
+            if (num_resolved_locations > 0)
+                s->Printf(" (%u resolved)", num_resolved_locations);
+            s->PutChar(';');
+        }
+        else
+        {
+            s->Printf(" with 0 locations (Pending Breakpoint).");
+        }
+
+        if (level == lldb::eDescriptionLevelFull)
+        {
+            Baton *baton = GetOptions()->GetBaton();
+            if (baton)
+            {
+                s->EOL ();
+                s->Indent();
+                baton->GetDescription(s, level);
+            }
+        }
+        break;
+
+    case lldb::eDescriptionLevelVerbose:
+        // Verbose mode does a debug dump of the breakpoint
+        Dump (s);
+        Baton *baton = GetOptions()->GetBaton();
+        if (baton)
+        {
+            s->EOL ();
+            s->Indent();
+            baton->GetDescription(s, level);
+        }
+        break;
+    }
+
+    if (show_locations)
+    {
+        s->EOL();
+        s->IndentMore();
+        for (int i = 0; i < GetNumLocations(); ++i)
+        {
+            BreakpointLocation *loc = GetLocationAtIndex(i).get();
+            loc->GetDescription(s, level);
+            s->EOL();
+        }
+        s->IndentLess();
+
+    }
+}
+
+Breakpoint::BreakpointEventData::BreakpointEventData (Breakpoint::BreakpointEventData::EventSubType sub_type, BreakpointSP &new_breakpoint_sp) :
+    EventData (),
+    m_sub_type (sub_type),
+    m_new_breakpoint_sp (new_breakpoint_sp)
+{
+}
+
+Breakpoint::BreakpointEventData::~BreakpointEventData ()
+{
+}
+
+const ConstString &
+Breakpoint::BreakpointEventData::GetFlavorString ()
+{
+    static ConstString g_flavor ("Breakpoint::BreakpointEventData");
+    return g_flavor;
+}
+
+const ConstString &
+Breakpoint::BreakpointEventData::GetFlavor () const
+{
+    return BreakpointEventData::GetFlavorString ();
+}
+
+
+BreakpointSP &
+Breakpoint::BreakpointEventData::GetBreakpoint ()
+{
+    return m_new_breakpoint_sp;
+}
+
+Breakpoint::BreakpointEventData::EventSubType
+Breakpoint::BreakpointEventData::GetSubType () const
+{
+    return m_sub_type;
+}
+
+void
+Breakpoint::BreakpointEventData::Dump (Stream *s) const
+{
+}
+
+Breakpoint::BreakpointEventData *
+Breakpoint::BreakpointEventData::GetEventDataFromEvent (const EventSP &event_sp)
+{
+    if (event_sp)
+    {
+        EventData *event_data = event_sp->GetData();
+        if (event_data && event_data->GetFlavor() == BreakpointEventData::GetFlavorString())
+            return static_cast <BreakpointEventData *> (event_sp->GetData());
+    }
+    return NULL;
+}
+
+Breakpoint::BreakpointEventData::EventSubType
+Breakpoint::BreakpointEventData::GetSubTypeFromEvent (const EventSP &event_sp)
+{
+    BreakpointEventData *data = GetEventDataFromEvent (event_sp);
+
+    if (data == NULL)
+        return eBreakpointInvalidType;
+    else
+        return data->GetSubType();
+}
+
+BreakpointSP
+Breakpoint::BreakpointEventData::GetBreakpointFromEvent (const EventSP &event_sp)
+{
+    BreakpointEventData *data = GetEventDataFromEvent (event_sp);
+
+    if (data == NULL)
+    {
+        BreakpointSP ret_val;
+        return ret_val;
+    }
+    else
+        return data->GetBreakpoint();
+}
+
+
+void
+Breakpoint::GetResolverDescription (Stream *s)
+{
+    if (m_resolver_sp)
+        m_resolver_sp->GetDescription (s);
+}
+
+void
+Breakpoint::GetFilterDescription (Stream *s)
+{
+    m_filter_sp->GetDescription (s);
+}
+
+const BreakpointSP
+Breakpoint::GetSP ()
+{
+    return m_target.GetBreakpointList().FindBreakpointByID (GetID());
+}
diff --git a/source/Breakpoint/BreakpointID.cpp b/source/Breakpoint/BreakpointID.cpp
new file mode 100644
index 0000000..691e5c0
--- /dev/null
+++ b/source/Breakpoint/BreakpointID.cpp
@@ -0,0 +1,120 @@
+//===-- BreakpointID.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
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+#include "lldb/Breakpoint/BreakpointID.h"
+#include "lldb/Breakpoint/Breakpoint.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+BreakpointID::BreakpointID (break_id_t bp_id, break_id_t loc_id) :
+    m_break_id (bp_id),
+    m_location_id (loc_id)
+{
+}
+
+BreakpointID::~BreakpointID ()
+{
+}
+
+const char *BreakpointID::g_range_specifiers[] = { "-", "to", "To", "TO", NULL };
+
+// Tells whether or not STR is valid to use between two strings representing breakpoint IDs, to
+// indicate a range of breakpoint IDs.  This is broken out into a separate function so that we can
+// easily change or add to the format for specifying ID ranges at a later date.
+
+bool
+BreakpointID::IsRangeIdentifier (const char *str)
+{
+    int specifier_count = 0;
+    for (int i = 0; g_range_specifiers[i] != NULL; ++i)
+      ++specifier_count;
+
+    for (int i = 0; i < specifier_count; ++i)
+    {
+      if (strcmp (g_range_specifiers[i], str) == 0)
+            return true;
+    }
+
+  return false;
+}
+
+bool
+BreakpointID::IsValidIDExpression (const char *str)
+{
+    break_id_t bp_id;
+    break_id_t loc_id;
+    BreakpointID::ParseCanonicalReference (str, &bp_id, &loc_id);
+
+    if (bp_id == LLDB_INVALID_BREAK_ID)
+        return false;
+    else
+        return true;
+}
+
+void
+BreakpointID::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+    if (level == eDescriptionLevelVerbose)
+        s->Printf("%p BreakpointID:", this);
+
+    if (m_break_id == LLDB_INVALID_BREAK_ID)
+        s->PutCString ("<invalid>");
+    else if (m_location_id == LLDB_INVALID_BREAK_ID)
+        s->Printf("%i", m_break_id);
+    else
+        s->Printf("%i.%i", m_break_id, m_location_id);
+}
+
+void
+BreakpointID::GetCanonicalReference (Stream *s, break_id_t bp_id, break_id_t loc_id)
+{
+    if (bp_id == LLDB_INVALID_BREAK_ID)
+        s->PutCString ("<invalid>");
+    else if (loc_id == LLDB_INVALID_BREAK_ID)
+        s->Printf("%i", bp_id);
+    else
+        s->Printf("%i.%i", bp_id, loc_id);
+}
+
+bool
+BreakpointID::ParseCanonicalReference (const char *input, break_id_t *break_id_ptr, break_id_t *break_loc_id_ptr)
+{
+    *break_id_ptr = LLDB_INVALID_BREAK_ID;
+    *break_loc_id_ptr = LLDB_INVALID_BREAK_ID;
+
+    if (input == NULL || *input == '\0')
+        return false;
+
+    const char *format = "%i%n.%i%n";
+    int chars_consumed_1 = 0;
+    int chars_consumed_2 = 0;
+    int n_items_parsed = ::sscanf (input,
+                                   format,
+                                   break_id_ptr,        // %i   parse the breakpoint ID
+                                   &chars_consumed_1,   // %n   gets the number of characters parsed so far
+                                   break_loc_id_ptr,    // %i   parse the breakpoint location ID
+                                   &chars_consumed_2);  // %n   gets the number of characters parsed so far
+
+    if ((n_items_parsed == 1 && input[chars_consumed_1] == '\0') ||
+        (n_items_parsed == 2 && input[chars_consumed_2] == '\0'))
+        return true;
+
+    // Badly formatted canonical reference.
+    *break_id_ptr = LLDB_INVALID_BREAK_ID;
+    *break_loc_id_ptr = LLDB_INVALID_BREAK_ID;
+    return false;
+}
+
diff --git a/source/Breakpoint/BreakpointIDList.cpp b/source/Breakpoint/BreakpointIDList.cpp
new file mode 100644
index 0000000..895f1b1
--- /dev/null
+++ b/source/Breakpoint/BreakpointIDList.cpp
@@ -0,0 +1,348 @@
+//===-- BreakpointIDList.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/BreakpointIDList.h"
+
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Core/Args.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// class BreakpointIDList
+//----------------------------------------------------------------------
+
+BreakpointIDList::BreakpointIDList () :
+m_invalid_id (LLDB_INVALID_BREAK_ID, LLDB_INVALID_BREAK_ID)
+{
+}
+
+BreakpointIDList::~BreakpointIDList ()
+{
+}
+
+int
+BreakpointIDList::Size()
+{
+    return m_breakpoint_ids.size();
+}
+
+BreakpointID &
+BreakpointIDList::GetBreakpointIDAtIndex (int index)
+{
+    if (index < m_breakpoint_ids.size())
+        return m_breakpoint_ids[index];
+    else
+        return m_invalid_id;
+}
+
+bool
+BreakpointIDList::RemoveBreakpointIDAtIndex (int index)
+{
+    bool success = false;
+    if (index < m_breakpoint_ids.size())
+    {
+        BreakpointIDArray::iterator pos;
+        int i;
+
+        for (pos = m_breakpoint_ids.begin(), i = 0; i != index && pos != m_breakpoint_ids.end(); ++pos, ++i);
+        assert (i == index);
+        if (pos != m_breakpoint_ids.end())
+        {
+            m_breakpoint_ids.erase (pos);
+            success = true;
+        }
+    }
+    return success;
+}
+
+void
+BreakpointIDList::Clear()
+{
+    m_breakpoint_ids.clear ();
+}
+
+bool
+BreakpointIDList::AddBreakpointID (BreakpointID bp_id)
+{
+    m_breakpoint_ids.push_back (bp_id);
+
+    return true;  // We don't do any verification in this function, so always return true.
+}
+
+bool
+BreakpointIDList::AddBreakpointID (const char *bp_id_str)
+{
+    BreakpointID temp_bp_id;
+    break_id_t bp_id;
+    break_id_t loc_id;
+
+    bool success = BreakpointID::ParseCanonicalReference (bp_id_str, &bp_id, &loc_id);
+
+    if (success)
+    {
+        temp_bp_id.SetID (bp_id, loc_id);
+        m_breakpoint_ids.push_back (temp_bp_id);
+    }
+
+    return success;
+}
+
+bool
+BreakpointIDList::FindBreakpointID (BreakpointID &bp_id, int *position)
+{
+    bool success = false;
+    BreakpointIDArray::iterator tmp_pos;
+
+    for (int i = 0; i <  m_breakpoint_ids.size(); ++i)
+    {
+        BreakpointID tmp_id = m_breakpoint_ids[i];
+        if (tmp_id.GetBreakpointID() == bp_id.GetBreakpointID()
+            && tmp_id.GetLocationID() == bp_id.GetLocationID())
+        {
+            success = true;
+            *position = i;
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool
+BreakpointIDList::FindBreakpointID (const char *bp_id_str, int *position)
+{
+    BreakpointID temp_bp_id;
+    break_id_t bp_id;
+    break_id_t loc_id;
+
+    if (BreakpointID::ParseCanonicalReference (bp_id_str, &bp_id, &loc_id))
+    {
+        temp_bp_id.SetID (bp_id, loc_id);
+        return FindBreakpointID (temp_bp_id, position);
+    }
+    else
+        return false;
+}
+
+void
+BreakpointIDList::InsertStringArray (const char **string_array, int array_size, CommandReturnObject &result)
+{
+    if (string_array == NULL)
+        return;
+
+    for (int i = 0; i < array_size; ++i)
+    {
+        break_id_t bp_id;
+        break_id_t loc_id;
+
+        if (BreakpointID::ParseCanonicalReference (string_array[i], &bp_id, &loc_id))
+        {
+            if (bp_id != LLDB_INVALID_BREAK_ID)
+            {
+                BreakpointID temp_bp_id(bp_id, loc_id);
+                m_breakpoint_ids.push_back (temp_bp_id);
+            }
+            else
+            {
+                result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", string_array[i]);
+                result.SetStatus (eReturnStatusFailed);
+                return;
+            }
+        }
+    }
+    result.SetStatus (eReturnStatusSuccessFinishNoResult);
+}
+
+
+//  This function takes OLD_ARGS, which is usually the result of breaking the command string arguments into
+//  an array of space-separated strings, and searches through the arguments for any breakpoint ID range specifiers.
+//  Any string in the array that is not part of an ID range specifier is copied directly into NEW_ARGS.  If any
+//  ID range specifiers are found, the range is interpreted and a list of canonical breakpoint IDs corresponding to
+//  all the current breakpoints and locations in the range are added to NEW_ARGS.  When this function is done,
+//  NEW_ARGS should be a copy of OLD_ARGS, with and ID range specifiers replaced by the members of the range.
+
+void
+BreakpointIDList::FindAndReplaceIDRanges (Args &old_args, Target *target, CommandReturnObject &result,
+                                          Args &new_args)
+{
+    char *range_start;
+    const char *range_end;
+    const char *current_arg;
+    int num_old_args = old_args.GetArgumentCount();
+
+    for (int i = 0; i < num_old_args; ++i)
+    {
+        bool is_range = false;
+        current_arg = old_args.GetArgumentAtIndex (i);
+
+        int range_start_len = 0;
+        int range_end_pos = 0;
+        if (BreakpointIDList::StringContainsIDRangeExpression (current_arg, &range_start_len, &range_end_pos))
+        {
+            is_range = true;
+            range_start = (char *) malloc (range_start_len + 1);
+            strncpy (range_start, current_arg, range_start_len);
+            range_start[range_start_len] = '\0';
+            range_end = current_arg + range_end_pos;
+        }
+        else if ((i + 2 < num_old_args)
+                 && BreakpointID::IsRangeIdentifier (old_args.GetArgumentAtIndex (i+1))
+                 && BreakpointID::IsValidIDExpression (current_arg)
+                 && BreakpointID::IsValidIDExpression (old_args.GetArgumentAtIndex (i+2)))
+        {
+            range_start = (char *) current_arg;
+            range_end = old_args.GetArgumentAtIndex (i+2);
+            is_range = true;
+            i = i+2;
+        }
+
+        if (is_range)
+        {
+            break_id_t start_bp_id;
+            break_id_t end_bp_id;
+            break_id_t start_loc_id;
+            break_id_t end_loc_id;
+
+            BreakpointID::ParseCanonicalReference (range_start, &start_bp_id, &start_loc_id);
+            BreakpointID::ParseCanonicalReference (range_end, &end_bp_id, &end_loc_id);
+
+            if ((start_bp_id == LLDB_INVALID_BREAK_ID)
+                || (! target->GetBreakpointByID (start_bp_id)))
+            {
+                new_args.Clear();
+                result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", range_start);
+                result.SetStatus (eReturnStatusFailed);
+                return;
+            }
+
+            if ((end_bp_id == LLDB_INVALID_BREAK_ID)
+                || (! target->GetBreakpointByID (end_bp_id)))
+            {
+                new_args.Clear();
+                result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", range_end);
+                result.SetStatus (eReturnStatusFailed);
+                return;
+            }
+
+            // We have valid range starting & ending breakpoint IDs.  Go through all the breakpoints in the
+            // target and find all the breakpoints that fit into this range, and add them to new_args.
+
+            const BreakpointList& breakpoints = target->GetBreakpointList();
+            size_t num_breakpoints = breakpoints.GetSize();
+            for (int j = 0; j < num_breakpoints; ++j)
+            {
+                Breakpoint *breakpoint = breakpoints.GetBreakpointByIndex (j).get();
+                break_id_t cur_bp_id = breakpoint->GetID();
+
+                if ((cur_bp_id < start_bp_id) || (cur_bp_id > end_bp_id))
+                    continue;
+
+                size_t num_locations = breakpoint->GetNumLocations();
+
+                if ((cur_bp_id == start_bp_id) && (start_loc_id != LLDB_INVALID_BREAK_ID))
+                {
+                    for (int k = 0; k < num_locations; ++k)
+                    {
+                        BreakpointLocation * bp_loc = breakpoint->GetLocationAtIndex(k).get();
+                        if (bp_loc->GetID() >= start_loc_id)
+                        {
+                            StreamString canonical_id_str;
+                            BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, bp_loc->GetID());
+                            new_args.AppendArgument (canonical_id_str.GetData());
+                        }
+                    }
+                }
+                else if ((cur_bp_id == end_bp_id) && (end_loc_id != LLDB_INVALID_BREAK_ID))
+                {
+                    for (int k = 0; k < num_locations; ++k)
+                    {
+                        BreakpointLocation * bp_loc = breakpoint->GetLocationAtIndex(k).get();
+                        if (bp_loc->GetID() <= end_loc_id)
+                        {
+                            StreamString canonical_id_str;
+                            BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, bp_loc->GetID());
+                            new_args.AppendArgument (canonical_id_str.GetData());
+                        }
+                    }
+                }
+                else
+                {
+                    StreamString canonical_id_str;
+                    BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, LLDB_INVALID_BREAK_ID);
+                    new_args.AppendArgument (canonical_id_str.GetData());
+                }
+            }
+        }
+        else  // else is_range was false
+        {
+            new_args.AppendArgument (current_arg);
+        }
+    }
+
+    result.SetStatus (eReturnStatusSuccessFinishNoResult);
+    return;
+}
+
+//bool
+//BreakpointIDList::StringContainsIDRangeExpression (const char *in_string, const char **range_start,
+//                                                     const **range_end)
+bool
+BreakpointIDList::StringContainsIDRangeExpression (const char *in_string, int *range_start_len, int *range_end_pos)
+{
+    bool is_range_expression = false;
+    std::string arg_str = in_string;
+    std::string::size_type idx;
+    std::string::size_type start_pos = 0;
+
+    //*range_start = NULL;
+    //*range_end = NULL;
+    *range_start_len = 0;
+    *range_end_pos = 0;
+
+    int specifiers_size = 0;
+    for (int i = 0; BreakpointID::g_range_specifiers[i] != NULL; ++i)
+        ++specifiers_size;
+
+    for (int i = 0; i < specifiers_size && !is_range_expression; ++i)
+    {
+        const char *specifier_str = BreakpointID::g_range_specifiers[i];
+        int len = strlen (specifier_str);
+        idx = arg_str.find (BreakpointID::g_range_specifiers[i]);
+        if (idx != std::string::npos)
+        {
+            *range_start_len = idx - start_pos;
+            std::string start_str = arg_str.substr (start_pos, *range_start_len);
+            if (idx + len < arg_str.length())
+            {
+                *range_end_pos = idx + len;
+                std::string end_str = arg_str.substr (*range_end_pos);
+                if (BreakpointID::IsValidIDExpression (start_str.c_str())
+                    && BreakpointID::IsValidIDExpression (end_str.c_str()))
+                {
+                    is_range_expression = true;
+                    //*range_start = start_str;
+                    //*range_end = end_str;
+                }
+            }
+        }
+    }
+
+    if (!is_range_expression)
+    {
+        *range_start_len = 0;
+        *range_end_pos = 0;
+    }
+
+    return is_range_expression;
+}
diff --git a/source/Breakpoint/BreakpointList.cpp b/source/Breakpoint/BreakpointList.cpp
new file mode 100644
index 0000000..c10aa77
--- /dev/null
+++ b/source/Breakpoint/BreakpointList.cpp
@@ -0,0 +1,198 @@
+//===-- BreakpointList.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/BreakpointList.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb;
+using namespace lldb_private;
+
+BreakpointList::BreakpointList (bool is_internal) :
+    m_mutex (Mutex::eMutexTypeRecursive),
+    m_breakpoints(),
+    m_next_break_id (0),
+    m_is_internal (is_internal)
+{
+}
+
+BreakpointList::~BreakpointList()
+{
+}
+
+
+break_id_t
+BreakpointList::Add (BreakpointSP &bp)
+{
+    Mutex::Locker locker(m_mutex);
+    // Internal breakpoint IDs are negative, normal ones are positive
+    bp->SetID (m_is_internal ? --m_next_break_id : ++m_next_break_id);
+    m_breakpoints.push_back(bp);
+    return bp->GetID();
+}
+
+bool
+BreakpointList::Remove (break_id_t break_id)
+{
+    Mutex::Locker locker(m_mutex);
+    bp_collection::iterator pos = GetBreakpointIDIterator(break_id);    // Predicate
+    if (pos != m_breakpoints.end())
+    {
+        m_breakpoints.erase(pos);
+        return true;
+    }
+    return false;
+}
+
+void
+BreakpointList::SetEnabledAll (bool enabled)
+{
+    Mutex::Locker locker(m_mutex);
+    bp_collection::iterator pos, end = m_breakpoints.end();
+    for (pos = m_breakpoints.begin(); pos != end; ++pos)
+        (*pos)->SetEnabled (enabled);
+}
+
+
+void
+BreakpointList::RemoveAll ()
+{
+    Mutex::Locker locker(m_mutex);
+    ClearAllBreakpointSites ();
+
+    m_breakpoints.erase (m_breakpoints.begin(), m_breakpoints.end());
+}
+
+class BreakpointIDMatches
+{
+public:
+    BreakpointIDMatches (break_id_t break_id) :
+        m_break_id(break_id)
+    {
+    }
+
+    bool operator() (const BreakpointSP &bp) const
+    {
+        return m_break_id == bp->GetID();
+    }
+
+private:
+   const break_id_t m_break_id;
+};
+
+BreakpointList::bp_collection::iterator
+BreakpointList::GetBreakpointIDIterator (break_id_t break_id)
+{
+    return std::find_if(m_breakpoints.begin(), m_breakpoints.end(), // Search full range
+                        BreakpointIDMatches(break_id));             // Predicate
+}
+
+BreakpointList::bp_collection::const_iterator
+BreakpointList::GetBreakpointIDConstIterator (break_id_t break_id) const
+{
+    return std::find_if(m_breakpoints.begin(), m_breakpoints.end(), // Search full range
+                        BreakpointIDMatches(break_id));             // Predicate
+}
+
+BreakpointSP
+BreakpointList::FindBreakpointByID (break_id_t break_id)
+{
+    Mutex::Locker locker(m_mutex);
+    BreakpointSP stop_sp;
+    bp_collection::iterator pos = GetBreakpointIDIterator(break_id);
+    if (pos != m_breakpoints.end())
+        stop_sp = *pos;
+
+    return stop_sp;
+}
+
+const BreakpointSP
+BreakpointList::FindBreakpointByID (break_id_t break_id) const
+{
+    Mutex::Locker locker(m_mutex);
+    BreakpointSP stop_sp;
+    bp_collection::const_iterator pos = GetBreakpointIDConstIterator(break_id);
+    if (pos != m_breakpoints.end())
+        stop_sp = *pos;
+
+    return stop_sp;
+}
+
+void
+BreakpointList::Dump (Stream *s) const
+{
+    Mutex::Locker locker(m_mutex);
+    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+    s->Indent();
+    s->Printf("BreakpointList with %u Breakpoints:\n", (uint32_t)m_breakpoints.size());
+    s->IndentMore();
+    bp_collection::const_iterator pos;
+    bp_collection::const_iterator end = m_breakpoints.end();
+    for (pos = m_breakpoints.begin(); pos != end; ++pos)
+        (*pos)->Dump(s);
+    s->IndentLess();
+}
+
+
+BreakpointSP
+BreakpointList::GetBreakpointByIndex (uint32_t i)
+{
+    Mutex::Locker locker(m_mutex);
+    BreakpointSP stop_sp;
+    bp_collection::iterator end = m_breakpoints.end();
+    bp_collection::iterator pos;
+    uint32_t curr_i = 0;
+    for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i)
+    {
+        if (curr_i == i)
+            stop_sp = *pos;
+    }
+    return stop_sp;
+}
+
+const BreakpointSP
+BreakpointList::GetBreakpointByIndex (uint32_t i) const
+{
+    Mutex::Locker locker(m_mutex);
+    BreakpointSP stop_sp;
+    bp_collection::const_iterator end = m_breakpoints.end();
+    bp_collection::const_iterator pos;
+    uint32_t curr_i = 0;
+    for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i)
+    {
+        if (curr_i == i)
+            stop_sp = *pos;
+    }
+    return stop_sp;
+}
+
+void
+BreakpointList::UpdateBreakpoints (ModuleList& module_list, bool added)
+{
+    Mutex::Locker locker(m_mutex);
+    bp_collection::iterator end = m_breakpoints.end();
+    bp_collection::iterator pos;
+    for (pos = m_breakpoints.begin(); pos != end; ++pos)
+        (*pos)->ModulesChanged (module_list, added);
+
+}
+
+void
+BreakpointList::ClearAllBreakpointSites ()
+{
+    Mutex::Locker locker(m_mutex);
+    bp_collection::iterator end = m_breakpoints.end();
+    bp_collection::iterator pos;
+    for (pos = m_breakpoints.begin(); pos != end; ++pos)
+        (*pos)->ClearAllBreakpointSites ();
+
+}
diff --git a/source/Breakpoint/BreakpointLocation.cpp b/source/Breakpoint/BreakpointLocation.cpp
new file mode 100644
index 0000000..5c0e81d
--- /dev/null
+++ b/source/Breakpoint/BreakpointLocation.cpp
@@ -0,0 +1,389 @@
+//===-- BreakpointLocation.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
+// C++ Includes
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/BreakpointID.h"
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/lldb-private-log.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+BreakpointLocation::BreakpointLocation
+(
+    break_id_t loc_id,
+    Breakpoint &owner,
+    Address &addr,
+    lldb::tid_t tid,
+    bool hardware
+) :
+    StoppointLocation (loc_id, addr.GetLoadAddress(owner.GetTarget().GetProcessSP().get()), tid, hardware),
+    m_address (addr),
+    m_owner (owner),
+    m_options_ap (),
+    m_bp_site_sp ()
+{
+}
+
+BreakpointLocation::~BreakpointLocation()
+{
+    ClearBreakpointSite();
+}
+
+lldb::addr_t
+BreakpointLocation::GetLoadAddress ()
+{
+    return m_address.GetLoadAddress(m_owner.GetTarget().GetProcessSP().get());
+}
+
+Address &
+BreakpointLocation::GetAddress ()
+{
+    return m_address;
+}
+
+Breakpoint &
+BreakpointLocation::GetBreakpoint ()
+{
+    return m_owner;
+}
+
+bool
+BreakpointLocation::IsEnabled ()
+{
+    if (!m_owner.IsEnabled())
+        return false;
+    else if (m_options_ap.get() != NULL)
+        return m_options_ap->IsEnabled();
+    else
+        return true;
+}
+
+void
+BreakpointLocation::SetEnabled (bool enabled)
+{
+    GetLocationOptions()->SetEnabled(enabled);
+    if (enabled)
+    {
+        ResolveBreakpointSite();
+    }
+    else
+    {
+        ClearBreakpointSite();
+    }
+}
+
+void
+BreakpointLocation::SetThreadID (lldb::tid_t thread_id)
+{
+    GetLocationOptions()->SetThreadID(thread_id);
+}
+
+lldb::tid_t
+BreakpointLocation::GetThreadID ()
+{
+    return GetOptionsNoCopy()->GetThreadID();
+}
+
+bool
+BreakpointLocation::InvokeCallback (StoppointCallbackContext *context)
+{
+    bool owner_result;
+
+    owner_result = m_owner.InvokeCallback (context, GetID());
+    if (owner_result == false)
+        return false;
+    else if (m_options_ap.get() != NULL)
+        return m_options_ap->InvokeCallback (context, m_owner.GetID(), GetID());
+    else
+        return true;
+}
+
+void
+BreakpointLocation::SetCallback (BreakpointHitCallback callback, void *baton,
+                 bool is_synchronous)
+{
+    // The default "Baton" class will keep a copy of "baton" and won't free
+    // or delete it when it goes goes out of scope.
+    GetLocationOptions()->SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous);
+}
+
+void
+BreakpointLocation::SetCallback (BreakpointHitCallback callback, const BatonSP &baton_sp,
+                 bool is_synchronous)
+{
+    GetLocationOptions()->SetCallback (callback, baton_sp, is_synchronous);
+}
+
+void
+BreakpointLocation::ClearCallback ()
+{
+    GetLocationOptions()->ClearCallback();
+}
+
+int32_t
+BreakpointLocation::GetIgnoreCount ()
+{
+    return GetOptionsNoCopy()->GetIgnoreCount();
+}
+
+void
+BreakpointLocation::SetIgnoreCount (int32_t n)
+{
+    GetLocationOptions()->SetIgnoreCount(n);
+}
+
+BreakpointOptions *
+BreakpointLocation::GetOptionsNoCopy ()
+{
+    if (m_options_ap.get() != NULL)
+        return m_options_ap.get();
+    else
+        return m_owner.GetOptions ();
+}
+
+BreakpointOptions *
+BreakpointLocation::GetLocationOptions ()
+{
+    if (m_options_ap.get() == NULL)
+        m_options_ap.reset(new BreakpointOptions (*m_owner.GetOptions ()));
+
+    return m_options_ap.get();
+}
+
+// RETURNS - true if we should stop at this breakpoint, false if we
+// should continue.
+
+bool
+BreakpointLocation::ShouldStop (StoppointCallbackContext *context)
+{
+    bool should_stop = true;
+
+    m_hit_count++;
+
+    if (!IsEnabled())
+        return false;
+
+    if (GetThreadID() != LLDB_INVALID_THREAD_ID
+          && context->context.thread->GetID() != GetThreadID())
+        return false;
+
+    if (m_hit_count <= GetIgnoreCount())
+        return false;
+
+    // Tell if the callback is synchronous here.
+    context->is_synchronous = true;
+    should_stop = InvokeCallback (context);
+        
+    if (should_stop)
+    {
+        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+        if (log)
+        {
+            StreamString s;
+            GetDescription (&s, lldb::eDescriptionLevelVerbose);
+            log->Printf ("Hit breakpoint location: %s\n", s.GetData());
+        }
+    }
+    return should_stop;
+}
+
+bool
+BreakpointLocation::IsResolved () const
+{
+    return m_bp_site_sp.get() != NULL;
+}
+
+bool
+BreakpointLocation::ResolveBreakpointSite ()
+{
+    if (m_bp_site_sp)
+        return true;
+
+    Process* process = m_owner.GetTarget().GetProcessSP().get();
+    if (process == NULL)
+        return false;
+
+    BreakpointLocationSP myself_sp(m_owner.GetLocationSP (this));
+
+    lldb::user_id_t new_id = process->CreateBreakpointSite (myself_sp, false);
+
+    if (new_id == LLDB_INVALID_UID)
+    {
+        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+        if (log)
+            log->Warning ("Tried to add breakpoint site at 0x%llx but it was already present.\n",
+                          m_address.GetLoadAddress(process));
+        return false;
+    }
+
+    return true;
+}
+
+bool
+BreakpointLocation::SetBreakpointSite (BreakpointSiteSP& bp_site_sp)
+{
+    m_bp_site_sp = bp_site_sp;
+    return true;
+}
+
+bool
+BreakpointLocation::ClearBreakpointSite ()
+{
+    if (m_bp_site_sp.get())
+    {
+        m_owner.GetTarget().GetProcessSP()->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(), GetID(), m_bp_site_sp);
+        m_bp_site_sp.reset();
+        return true;
+    }
+    return false;
+}
+
+void
+BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+    SymbolContext sc;
+    s->Indent();
+    BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
+
+    if (level == lldb::eDescriptionLevelBrief)
+        return;
+
+    s->PutCString(": ");
+
+    if (level == lldb::eDescriptionLevelVerbose)
+        s->IndentMore();
+
+    if (m_address.IsSectionOffset())
+    {
+        m_address.CalculateSymbolContext(&sc);
+
+        if (level == lldb::eDescriptionLevelFull)
+        {
+            s->PutCString("where = ");
+            sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address);
+        }
+        else
+        {
+            if (sc.module_sp)
+            {
+                s->EOL();
+                s->Indent("module = ");
+                sc.module_sp->GetFileSpec().Dump (s);
+            }
+
+            if (sc.comp_unit != NULL)
+            {
+                s->EOL();
+                s->Indent("compile unit = ");
+                dynamic_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s);
+
+                if (sc.function != NULL)
+                {
+                    s->EOL();
+                    s->Indent("function = ");
+                    s->PutCString (sc.function->GetMangled().GetName().AsCString("<unknown>"));
+                }
+
+                if (sc.line_entry.line > 0)
+                {
+                    s->EOL();
+                    s->Indent("location = ");
+                    sc.line_entry.DumpStopContext (s);
+                }
+
+            }
+            else
+            {
+                // If we don't have a comp unit, see if we have a symbol we can print.
+                if (sc.symbol)
+                {
+                    s->EOL();
+                    s->Indent("symbol = ");
+                    s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>"));
+                }
+            }
+        }
+    }
+
+    if (level == lldb::eDescriptionLevelVerbose)
+    {
+        s->EOL();
+        s->Indent();
+    }
+    s->Printf ("%saddress = ", (level == lldb::eDescriptionLevelFull && m_address.IsSectionOffset()) ? ", " : "");
+    ExecutionContextScope *exe_scope = NULL;
+    Target *target = &m_owner.GetTarget();
+    if (target)
+        exe_scope = target->GetProcessSP().get();
+    if (exe_scope == NULL)
+        exe_scope = target;
+
+    m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
+
+    if (level == lldb::eDescriptionLevelVerbose)
+    {
+        s->EOL();
+        s->Indent();
+        s->Printf("resolved = %s\n", IsResolved() ? "true" : "false");
+
+        s->Indent();
+        s->Printf("enabled = %s\n", IsEnabled() ? "true" : "false");
+
+        s->Indent();
+        s->Printf ("hit count = %-4u\n", GetHitCount());
+
+        if (m_options_ap.get())
+        {
+            Baton *baton = m_options_ap->GetBaton();
+            if (baton)
+            {
+                s->Indent();
+                baton->GetDescription (s, level);
+                s->EOL();
+            }
+        }
+        s->IndentLess();
+    }
+    else
+    {
+        s->Printf(", %sresolved, %s, hit count = %u",
+                  (IsResolved() ? "" : "un"),
+                  (IsEnabled() ? "enabled" : "disabled"),
+                  GetHitCount());
+    }
+}
+
+void
+BreakpointLocation::Dump(Stream *s) const
+{
+    if (s == NULL)
+        return;
+
+    s->Printf("BreakpointLocation %u: tid = %4.4x  load addr = 0x%8.8llx  state = %s  type = %s breakpoint  hw_index = %i  hit_count = %-4u  ignore_count = %-4u",
+            GetID(),
+            m_tid,
+            (uint64_t) m_address.GetLoadAddress(m_owner.GetTarget().GetProcessSP().get()),
+            (m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled",
+            IsHardware() ? "hardware" : "software",
+            GetHardwareIndex(),
+            GetHitCount(),
+            m_options_ap.get() ? m_options_ap->GetIgnoreCount() : m_owner.GetIgnoreCount());
+}
diff --git a/source/Breakpoint/BreakpointLocationCollection.cpp b/source/Breakpoint/BreakpointLocationCollection.cpp
new file mode 100644
index 0000000..7b57426
--- /dev/null
+++ b/source/Breakpoint/BreakpointLocationCollection.cpp
@@ -0,0 +1,161 @@
+//===-- BreakpointLocationCollection.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
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/BreakpointLocationCollection.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/BreakpointLocationList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// BreakpointLocationCollection constructor
+//----------------------------------------------------------------------
+BreakpointLocationCollection::BreakpointLocationCollection() :
+    m_break_loc_collection()
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+BreakpointLocationCollection::~BreakpointLocationCollection()
+{
+}
+
+void
+BreakpointLocationCollection::Add(const BreakpointLocationSP &bp_loc)
+{
+    BreakpointLocationSP old_bp_loc = FindByIDPair (bp_loc->GetBreakpoint().GetID(), bp_loc->GetID());
+    if (!old_bp_loc.get())
+        m_break_loc_collection.push_back(bp_loc);
+}
+
+bool
+BreakpointLocationCollection::Remove (lldb::user_id_t bp_id, lldb::user_id_t bp_loc_id)
+{
+    collection::iterator pos = GetIDPairIterator(bp_id, bp_loc_id);    // Predicate
+    if (pos != m_break_loc_collection.end())
+    {
+        m_break_loc_collection.erase(pos);
+        return true;
+    }
+    return false;
+
+}
+
+class BreakpointIDPairMatches
+{
+public:
+    BreakpointIDPairMatches (lldb::user_id_t break_id, lldb::user_id_t break_loc_id) :
+        m_break_id(break_id),
+        m_break_loc_id (break_loc_id)
+    {
+    }
+
+    bool operator() (const BreakpointLocationSP &bp_loc) const
+    {
+        return m_break_id == bp_loc->GetBreakpoint().GetID()
+            && m_break_loc_id == bp_loc->GetID();
+    }
+
+private:
+   const lldb::user_id_t m_break_id;
+   const lldb::user_id_t m_break_loc_id;
+};
+
+BreakpointLocationCollection::collection::iterator
+BreakpointLocationCollection::GetIDPairIterator (lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
+{
+    return std::find_if(m_break_loc_collection.begin(), m_break_loc_collection.end(),   // Search full range
+                        BreakpointIDPairMatches(break_id, break_loc_id));               // Predicate
+}
+
+BreakpointLocationCollection::collection::const_iterator
+BreakpointLocationCollection::GetIDPairConstIterator (lldb::user_id_t break_id, lldb::user_id_t break_loc_id) const
+{
+    return std::find_if(m_break_loc_collection.begin(), m_break_loc_collection.end(),   // Search full range
+                        BreakpointIDPairMatches(break_id, break_loc_id));               // Predicate
+}
+
+BreakpointLocationSP
+BreakpointLocationCollection::FindByIDPair (lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
+{
+    BreakpointLocationSP stop_sp;
+    collection::iterator pos = GetIDPairIterator(break_id, break_loc_id);
+    if (pos != m_break_loc_collection.end())
+        stop_sp = *pos;
+
+    return stop_sp;
+}
+
+const BreakpointLocationSP
+BreakpointLocationCollection::FindByIDPair (lldb::user_id_t break_id, lldb::user_id_t break_loc_id) const
+{
+    BreakpointLocationSP stop_sp;
+    collection::const_iterator pos = GetIDPairConstIterator(break_id, break_loc_id);
+    if (pos != m_break_loc_collection.end())
+        stop_sp = *pos;
+
+    return stop_sp;
+}
+
+BreakpointLocationSP
+BreakpointLocationCollection::GetByIndex (uint32_t i)
+{
+    BreakpointLocationSP stop_sp;
+    if (i >= 0 && i < m_break_loc_collection.size())
+        stop_sp = m_break_loc_collection[i];
+
+    return stop_sp;
+}
+
+const BreakpointLocationSP
+BreakpointLocationCollection::GetByIndex (uint32_t i) const
+{
+    BreakpointLocationSP stop_sp;
+    if (i >= 0 && i < m_break_loc_collection.size())
+        stop_sp = m_break_loc_collection[i];
+
+    return stop_sp;
+}
+
+bool
+BreakpointLocationCollection::ShouldStop (StoppointCallbackContext *context)
+{
+    bool shouldStop = false;
+
+    for (int i = 0; i < GetSize(); i++) {
+        bool one_result = GetByIndex(i)->ShouldStop(context);
+        if (one_result)
+            shouldStop = true;
+    }
+    return shouldStop;
+}
+
+void
+BreakpointLocationCollection::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+    collection::iterator pos,
+        begin = m_break_loc_collection.begin(),
+        end = m_break_loc_collection.end();
+
+    for (pos = begin; pos != end; ++pos)
+    {
+        if (pos != begin)
+            s->PutChar(' ');
+        (*pos)->GetDescription(s, level);
+    }
+}
diff --git a/source/Breakpoint/BreakpointLocationList.cpp b/source/Breakpoint/BreakpointLocationList.cpp
new file mode 100644
index 0000000..d86a8cf
--- /dev/null
+++ b/source/Breakpoint/BreakpointLocationList.cpp
@@ -0,0 +1,305 @@
+//===-- BreakpointLocationList.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
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/BreakpointLocationList.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+BreakpointLocationList::BreakpointLocationList() :
+    m_locations(),
+    m_address_to_location (),
+    m_mutex (Mutex::eMutexTypeRecursive),
+    m_next_id (0)
+{
+}
+
+BreakpointLocationList::~BreakpointLocationList()
+{
+}
+
+lldb::user_id_t
+BreakpointLocationList::Add (BreakpointLocationSP &bp_loc_sp)
+{
+    if (bp_loc_sp)
+    {
+        Mutex::Locker locker (m_mutex);
+        m_locations.push_back (bp_loc_sp);
+        m_address_to_location[bp_loc_sp->GetAddress()] = bp_loc_sp;
+        return bp_loc_sp->GetID();
+    }
+    return LLDB_INVALID_BREAK_ID;
+}
+
+bool
+BreakpointLocationList::ShouldStop (StoppointCallbackContext *context, lldb::user_id_t break_id)
+{
+    BreakpointLocationSP bp = FindByID (break_id);
+    if (bp)
+    {
+        // Let the BreakpointLocation decide if it should stop here (could not have
+        // reached it's target hit count yet, or it could have a callback
+        // that decided it shouldn't stop (shared library loads/unloads).
+        return bp->ShouldStop (context);
+    }
+    // We should stop here since this BreakpointLocation isn't valid anymore or it
+    // doesn't exist.
+    return true;
+}
+
+lldb::user_id_t
+BreakpointLocationList::FindIDByAddress (Address &addr)
+{
+    BreakpointLocationSP bp_loc_sp = FindByAddress (addr);
+    if (bp_loc_sp)
+    {
+        return bp_loc_sp->GetID();
+    }
+    return LLDB_INVALID_BREAK_ID;
+}
+
+bool
+BreakpointLocationList::Remove (lldb::user_id_t break_id)
+{
+    Mutex::Locker locker (m_mutex);
+    collection::iterator pos = GetIDIterator(break_id);    // Predicate
+    if (pos != m_locations.end())
+    {
+        m_address_to_location.erase ((*pos)->GetAddress());
+        m_locations.erase(pos);
+        return true;
+    }
+    return false;
+}
+
+
+class BreakpointLocationIDMatches
+{
+public:
+    BreakpointLocationIDMatches (lldb::user_id_t break_id) :
+        m_break_id(break_id)
+    {
+    }
+
+    bool operator() (const BreakpointLocationSP &bp_loc_sp) const
+    {
+        return m_break_id == bp_loc_sp->GetID();
+    }
+
+private:
+   const lldb::user_id_t m_break_id;
+};
+
+class BreakpointLocationAddressMatches
+{
+public:
+    BreakpointLocationAddressMatches (Address& addr) :
+        m_addr(addr)
+    {
+    }
+
+    bool operator() (const BreakpointLocationSP& bp_loc_sp) const
+    {
+        return Address::CompareFileAddress(m_addr, bp_loc_sp->GetAddress()) == 0;
+    }
+
+private:
+   const Address &m_addr;
+};
+
+BreakpointLocationList::collection::iterator
+BreakpointLocationList::GetIDIterator (lldb::user_id_t break_id)
+{
+    Mutex::Locker locker (m_mutex);
+    return std::find_if (m_locations.begin(),
+                         m_locations.end(),
+                         BreakpointLocationIDMatches(break_id));
+}
+
+BreakpointLocationList::collection::const_iterator
+BreakpointLocationList::GetIDConstIterator (lldb::user_id_t break_id) const
+{
+    Mutex::Locker locker (m_mutex);
+    return std::find_if (m_locations.begin(),
+                         m_locations.end(),
+                         BreakpointLocationIDMatches(break_id));
+}
+
+BreakpointLocationSP
+BreakpointLocationList::FindByID (lldb::user_id_t break_id)
+{
+    Mutex::Locker locker (m_mutex);
+    BreakpointLocationSP stop_sp;
+    collection::iterator pos = GetIDIterator(break_id);
+    if (pos != m_locations.end())
+        stop_sp = *pos;
+
+    return stop_sp;
+}
+
+const BreakpointLocationSP
+BreakpointLocationList::FindByID (lldb::user_id_t break_id) const
+{
+    Mutex::Locker locker (m_mutex);
+    BreakpointLocationSP stop_sp;
+    collection::const_iterator pos = GetIDConstIterator(break_id);
+    if (pos != m_locations.end())
+        stop_sp = *pos;
+
+    return stop_sp;
+}
+
+size_t
+BreakpointLocationList::FindInModule (Module *module,
+                                      BreakpointLocationCollection& bp_loc_list)
+{
+    Mutex::Locker locker (m_mutex);
+    const size_t orig_size = bp_loc_list.GetSize();
+    collection::iterator pos, end = m_locations.end();
+
+    for (pos = m_locations.begin(); pos != end; ++pos)
+    {
+        bool seen = false;
+        BreakpointLocationSP break_loc = (*pos);
+        const Section *section = break_loc->GetAddress().GetSection();
+        if (section)
+        {
+            if (section->GetModule() == module)
+            {
+                if (!seen)
+                {
+                    seen = true;
+                    bp_loc_list.Add (break_loc);
+                }
+
+            }
+        }
+    }
+    return bp_loc_list.GetSize() - orig_size;
+}
+
+
+static int
+FindLocationByAddress (Address *addr_ptr, const BreakpointLocationSP *bp_loc_sp_ptr)
+{
+    return Address::CompareModulePointerAndOffset(*addr_ptr, (*bp_loc_sp_ptr)->GetAddress());
+}
+
+const BreakpointLocationSP
+BreakpointLocationList::FindByAddress (Address &addr) const
+{
+    Mutex::Locker locker (m_mutex);
+    BreakpointLocationSP stop_sp;
+    if (!m_locations.empty())
+    {
+        addr_map::const_iterator pos = m_address_to_location.find (addr);
+        if (pos != m_address_to_location.end())
+            stop_sp = pos->second;
+    }
+
+    return stop_sp;
+}
+
+void
+BreakpointLocationList::Dump (Stream *s) const
+{
+    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+    s->Indent();
+    Mutex::Locker locker (m_mutex);
+    s->Printf("BreakpointLocationList with %zu BreakpointLocations:\n", m_locations.size());
+    s->IndentMore();
+    collection::const_iterator pos, end = m_locations.end();
+    for (pos = m_locations.begin(); pos != end; ++pos)
+        (*pos).get()->Dump(s);
+    s->IndentLess();
+}
+
+
+BreakpointLocationSP
+BreakpointLocationList::GetByIndex (uint32_t i)
+{
+    Mutex::Locker locker (m_mutex);
+    BreakpointLocationSP stop_sp;
+    if (i >= 0 && i < m_locations.size())
+        stop_sp = m_locations[i];
+
+    return stop_sp;
+}
+
+const BreakpointLocationSP
+BreakpointLocationList::GetByIndex (uint32_t i) const
+{
+    Mutex::Locker locker (m_mutex);
+    BreakpointLocationSP stop_sp;
+    if (i >= 0 && i < m_locations.size())
+        stop_sp = m_locations[i];
+
+    return stop_sp;
+}
+
+void
+BreakpointLocationList::ClearAllBreakpointSites ()
+{
+    Mutex::Locker locker (m_mutex);
+    collection::iterator pos, end = m_locations.end();
+    for (pos = m_locations.begin(); pos != end; ++pos)
+        (*pos)->ClearBreakpointSite();
+}
+
+void
+BreakpointLocationList::ResolveAllBreakpointSites ()
+{
+    Mutex::Locker locker (m_mutex);
+    collection::iterator pos, end = m_locations.end();
+
+    for (pos = m_locations.begin(); pos != end; ++pos)
+        (*pos)->ResolveBreakpointSite();
+}
+
+size_t
+BreakpointLocationList::GetNumResolvedLocations() const
+{
+    Mutex::Locker locker (m_mutex);
+    size_t resolve_count = 0;
+    collection::const_iterator pos, end = m_locations.end();
+    for (pos = m_locations.begin(); pos != end; ++pos)
+    {
+        if ((*pos)->IsResolved())
+            ++resolve_count;
+    }
+    return resolve_count;
+}
+
+break_id_t
+BreakpointLocationList::GetNextID()
+{
+    return ++m_next_id;
+}
+
+void
+BreakpointLocationList::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+    Mutex::Locker locker (m_mutex);
+    collection::iterator pos, end = m_locations.end();
+
+    for (pos = m_locations.begin(); pos != end; ++pos)
+    {
+        s->Printf(" ");
+        (*pos)->GetDescription(s, level);
+    }
+}
+
diff --git a/source/Breakpoint/BreakpointOptions.cpp b/source/Breakpoint/BreakpointOptions.cpp
new file mode 100644
index 0000000..4f664c4
--- /dev/null
+++ b/source/Breakpoint/BreakpointOptions.cpp
@@ -0,0 +1,180 @@
+//===-- BreakpointOptions.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/BreakpointOptions.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StringList.h"
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+bool
+BreakpointOptions::NullCallback (void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
+{
+    return true;
+}
+
+//----------------------------------------------------------------------
+// BreakpointOptions constructor
+//----------------------------------------------------------------------
+BreakpointOptions::BreakpointOptions() :
+    m_callback (BreakpointOptions::NullCallback),
+    m_callback_is_synchronous (false),
+    m_callback_baton_sp (),
+    m_enabled (true),
+    m_ignore_count (0),
+    m_thread_id (LLDB_INVALID_THREAD_ID)
+{
+}
+
+//----------------------------------------------------------------------
+// BreakpointOptions copy constructor
+//----------------------------------------------------------------------
+BreakpointOptions::BreakpointOptions(const BreakpointOptions& rhs) :
+    m_callback (rhs.m_callback),
+    m_callback_baton_sp (rhs.m_callback_baton_sp),
+    m_callback_is_synchronous (rhs.m_callback_is_synchronous),
+    m_enabled (rhs.m_enabled),
+    m_ignore_count (rhs.m_ignore_count),
+    m_thread_id (rhs.m_thread_id)
+{
+}
+
+//----------------------------------------------------------------------
+// BreakpointOptions assignment operator
+//----------------------------------------------------------------------
+const BreakpointOptions&
+BreakpointOptions::operator=(const BreakpointOptions& rhs)
+{
+    m_callback = rhs.m_callback;
+    m_callback_baton_sp = rhs.m_callback_baton_sp;
+    m_callback_is_synchronous = rhs.m_callback_is_synchronous;
+    m_enabled = rhs.m_enabled;
+    m_ignore_count = rhs.m_ignore_count;
+    m_thread_id = rhs.m_thread_id;
+    return *this;
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+BreakpointOptions::~BreakpointOptions()
+{
+}
+
+//------------------------------------------------------------------
+// Callbacks
+//------------------------------------------------------------------
+void
+BreakpointOptions::SetCallback (BreakpointHitCallback callback, const BatonSP &callback_baton_sp, bool callback_is_synchronous)
+{
+    m_callback_is_synchronous = callback_is_synchronous;
+    m_callback = callback;
+    m_callback_baton_sp = callback_baton_sp;
+}
+
+void
+BreakpointOptions::ClearCallback ()
+{
+    m_callback = NULL;
+    m_callback_baton_sp.reset();
+}
+
+Baton *
+BreakpointOptions::GetBaton ()
+{
+    return m_callback_baton_sp.get();
+}
+
+bool
+BreakpointOptions::InvokeCallback (StoppointCallbackContext *context, 
+                                   lldb::user_id_t break_id,
+                                   lldb::user_id_t break_loc_id)
+{
+    if (m_callback && context->is_synchronous == IsCallbackSynchronous())
+    {
+        return m_callback (m_callback_baton_sp ? m_callback_baton_sp->m_data : NULL,
+                           context, 
+                           break_id, 
+                           break_loc_id);
+    }
+    else
+        return true;
+}
+
+//------------------------------------------------------------------
+// Enabled/Ignore Count
+//------------------------------------------------------------------
+bool
+BreakpointOptions::IsEnabled () const
+{
+    return m_enabled;
+}
+
+void
+BreakpointOptions::SetEnabled (bool enabled)
+{
+    m_enabled = enabled;
+}
+
+int32_t
+BreakpointOptions::GetIgnoreCount () const
+{
+    return m_ignore_count;
+}
+
+void
+BreakpointOptions::SetIgnoreCount (int32_t n)
+{
+    m_ignore_count = n;
+}
+
+void
+BreakpointOptions::SetThreadID (lldb::tid_t thread_id)
+{
+    m_thread_id = thread_id;
+}
+
+lldb::tid_t
+BreakpointOptions::GetThreadID () const
+{
+    return m_thread_id;
+}
+
+
+
+void
+BreakpointOptions::CommandBaton::GetDescription (Stream *s, lldb::DescriptionLevel level) const
+{
+    s->Indent("Breakpoint commands:\n");
+    CommandData *data = (CommandData *)m_data;
+    
+    s->IndentMore ();
+    if (data && data->user_source.GetSize() > 0)
+    {
+        const size_t num_strings = data->user_source.GetSize();
+        for (size_t i = 0; i < num_strings; ++i)
+        {
+            s->Indent(data->user_source.GetStringAtIndex(i));
+            s->EOL();
+        }
+    }
+    else
+    {
+        s->PutCString ("No commands.\n");
+    }
+    s->IndentLess ();
+}
+
diff --git a/source/Breakpoint/BreakpointResolver.cpp b/source/Breakpoint/BreakpointResolver.cpp
new file mode 100644
index 0000000..e0fbfde
--- /dev/null
+++ b/source/Breakpoint/BreakpointResolver.cpp
@@ -0,0 +1,60 @@
+//===-- BreakpointResolver.cpp ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/BreakpointResolver.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Address.h"
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/SearchFilter.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/lldb-private-log.h"
+
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// BreakpointResolver:
+//----------------------------------------------------------------------
+BreakpointResolver::BreakpointResolver (Breakpoint *bkpt) :
+    m_breakpoint (bkpt)
+{
+}
+
+BreakpointResolver::~BreakpointResolver ()
+{
+
+}
+
+void
+BreakpointResolver::SetBreakpoint (Breakpoint *bkpt)
+{
+    m_breakpoint = bkpt;
+}
+
+void
+BreakpointResolver::ResolveBreakpointInModules (SearchFilter &filter, ModuleList &modules)
+{
+    filter.SearchInModuleList(*this, modules);
+}
+
+void
+BreakpointResolver::ResolveBreakpoint (SearchFilter &filter)
+{
+    filter.Search (*this);
+}
+
diff --git a/source/Breakpoint/BreakpointResolverAddress.cpp b/source/Breakpoint/BreakpointResolverAddress.cpp
new file mode 100644
index 0000000..034ef60
--- /dev/null
+++ b/source/Breakpoint/BreakpointResolverAddress.cpp
@@ -0,0 +1,111 @@
+//===-- BreakpointResolverAddress.cpp ---------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/BreakpointResolverAddress.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private-log.h"
+
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// BreakpointResolverAddress:
+//----------------------------------------------------------------------
+BreakpointResolverAddress::BreakpointResolverAddress
+(
+    Breakpoint *bkpt,
+    const Address &addr
+) :
+    BreakpointResolver (bkpt),
+    m_addr (addr)
+{
+}
+
+BreakpointResolverAddress::~BreakpointResolverAddress ()
+{
+
+}
+
+void
+BreakpointResolverAddress::ResolveBreakpoint (SearchFilter &filter)
+{
+    // The address breakpoint only takes once, so if we've already set it we're done.
+    if (m_breakpoint->GetNumLocations() > 0)
+        return;
+    else
+        BreakpointResolver::ResolveBreakpoint(filter);
+}
+
+void
+BreakpointResolverAddress::ResolveBreakpointInModules
+(
+    SearchFilter &filter,
+    ModuleList &modules
+)
+{
+    // The address breakpoint only takes once, so if we've already set it we're done.
+    if (m_breakpoint->GetNumLocations() > 0)
+        return;
+    else
+        BreakpointResolver::ResolveBreakpointInModules (filter, modules);
+}
+
+Searcher::CallbackReturn
+BreakpointResolverAddress::SearchCallback
+(
+    SearchFilter &filter,
+    SymbolContext &context,
+    Address *addr,
+    bool containing
+)
+{
+    assert (m_breakpoint != NULL);
+
+    if (filter.AddressPasses (m_addr))
+    {
+        BreakpointLocationSP bp_loc_sp(m_breakpoint->AddLocation(m_addr));
+        if (bp_loc_sp && !m_breakpoint->IsInternal())
+        {
+            StreamString s;
+            bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
+            Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+            if (log)
+                log->Printf ("Added location: %s\n", s.GetData());
+        }
+    }
+    return Searcher::eCallbackReturnStop;
+}
+
+Searcher::Depth
+BreakpointResolverAddress::GetDepth()
+{
+    return Searcher::eDepthTarget;
+}
+
+void
+BreakpointResolverAddress::GetDescription (Stream *s)
+{
+    s->PutCString ("Address breakpoint: ");
+    m_addr.Dump(s, m_breakpoint->GetTarget().GetProcessSP().get(), Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
+}
+
+void
+BreakpointResolverAddress::Dump (Stream *s) const
+{
+
+}
diff --git a/source/Breakpoint/BreakpointResolverFileLine.cpp b/source/Breakpoint/BreakpointResolverFileLine.cpp
new file mode 100644
index 0000000..86e0596
--- /dev/null
+++ b/source/Breakpoint/BreakpointResolverFileLine.cpp
@@ -0,0 +1,122 @@
+//===-- BreakpointResolverFileLine.cpp --------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/BreakpointResolverFileLine.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/lldb-private-log.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// BreakpointResolverFileLine:
+//----------------------------------------------------------------------
+BreakpointResolverFileLine::BreakpointResolverFileLine
+(
+    Breakpoint *bkpt,
+    const FileSpec &file_spec,
+    uint32_t line_no,
+    bool check_inlines
+) :
+    BreakpointResolver (bkpt),
+    m_file_spec (file_spec),
+    m_line_number (line_no),
+    m_inlines (check_inlines)
+{
+}
+
+BreakpointResolverFileLine::~BreakpointResolverFileLine ()
+{
+}
+
+Searcher::CallbackReturn
+BreakpointResolverFileLine::SearchCallback
+(
+    SearchFilter &filter,
+    SymbolContext &context,
+    Address *addr,
+    bool containing
+)
+{
+    SymbolContextList sc_list;
+    uint32_t sc_list_size;
+    CompileUnit *cu = context.comp_unit;
+
+    assert (m_breakpoint != NULL);
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+
+    sc_list_size = cu->ResolveSymbolContext (m_file_spec, m_line_number, m_inlines, false, eSymbolContextEverything, sc_list);
+    for (int i = 0; i < sc_list_size; i++)
+    {
+        SymbolContext sc;
+        if (sc_list.GetContextAtIndex(i, sc))
+        {
+            Address line_start = sc.line_entry.range.GetBaseAddress();
+            if (line_start.IsValid())
+            {
+                BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start));
+                if (log && bp_loc_sp && !m_breakpoint->IsInternal())
+                {
+                    StreamString s;
+                    bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose);
+                    log->Printf ("Added location: %s\n", s.GetData());
+                }
+            }
+            else
+            {
+                if (log)
+                    log->Printf ("error: Unable to set breakpoint at file address 0x%llx for %s:%d\n",
+                                 line_start.GetFileAddress(),
+                                 m_file_spec.GetFilename().AsCString("<Unknown>"),
+                                 m_line_number);
+            }
+        }
+        else
+        {
+#if 0
+            s << "error: Breakpoint at '" << pos->c_str() << "' isn't resolved yet: \n";
+            if (sc.line_entry.address.Dump(&s, Address::DumpStyleSectionNameOffset))
+                s.EOL();
+            if (sc.line_entry.address.Dump(&s, Address::DumpStyleSectionPointerOffset))
+                s.EOL();
+            if (sc.line_entry.address.Dump(&s, Address::DumpStyleFileAddress))
+                s.EOL();
+            if (sc.line_entry.address.Dump(&s, Address::DumpStyleLoadAddress))
+                s.EOL();
+#endif
+        }
+    }
+    return Searcher::eCallbackReturnContinue;
+}
+
+Searcher::Depth
+BreakpointResolverFileLine::GetDepth()
+{
+    return Searcher::eDepthCompUnit;
+}
+
+void
+BreakpointResolverFileLine::GetDescription (Stream *s)
+{
+    s->Printf ("File and line breakpoint - file: \"%s\" line: %u", m_file_spec.GetFilename().AsCString(), m_line_number);
+}
+
+void
+BreakpointResolverFileLine::Dump (Stream *s) const
+{
+
+}
+
diff --git a/source/Breakpoint/BreakpointResolverName.cpp b/source/Breakpoint/BreakpointResolverName.cpp
new file mode 100644
index 0000000..b04bb8a
--- /dev/null
+++ b/source/Breakpoint/BreakpointResolverName.cpp
@@ -0,0 +1,252 @@
+//===-- BreakpointResolverName.cpp ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/BreakpointResolverName.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/lldb-private-log.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+BreakpointResolverName::BreakpointResolverName
+(
+    Breakpoint *bkpt,
+    const char *func_name,
+    Breakpoint::MatchType type
+) :
+    BreakpointResolver (bkpt),
+    m_func_name (func_name),
+    m_class_name (NULL),
+    m_regex (),
+    m_match_type (type)
+{
+    if (m_match_type == Breakpoint::Regexp)
+    {
+        if (!m_regex.Compile (m_func_name.AsCString()))
+        {
+            Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+
+            if (log)
+                log->Warning ("function name regexp: \"%s\" did not compile.", m_func_name.AsCString());
+        }
+    }
+}
+
+BreakpointResolverName::BreakpointResolverName
+(
+    Breakpoint *bkpt,
+    RegularExpression &func_regex
+) :
+    BreakpointResolver (bkpt),
+    m_func_name (NULL),
+    m_class_name (NULL),
+    m_regex (func_regex),
+    m_match_type (Breakpoint::Regexp)
+{
+
+}
+
+BreakpointResolverName::BreakpointResolverName
+(
+    Breakpoint *bkpt,
+    const char *class_name,
+    const char *method,
+    Breakpoint::MatchType type
+) :
+    BreakpointResolver (bkpt),
+    m_func_name (method),
+    m_class_name (class_name),
+    m_regex (),
+    m_match_type (type)
+{
+
+}
+
+BreakpointResolverName::~BreakpointResolverName ()
+{
+}
+
+// FIXME: Right now we look at the module level, and call the module's "FindFunctions".
+// Greg says he will add function tables, maybe at the CompileUnit level to accelerate function
+// lookup.  At that point, we should switch the depth to CompileUnit, and look in these tables.
+
+Searcher::CallbackReturn
+BreakpointResolverName::SearchCallback
+(
+    SearchFilter &filter,
+    SymbolContext &context,
+    Address *addr,
+    bool containing
+)
+{
+    SymbolContextList func_list;
+    SymbolContextList sym_list;
+
+    bool skip_prologue = true;
+    uint32_t i;
+    bool new_location;
+    SymbolContext sc;
+    Address break_addr;
+    assert (m_breakpoint != NULL);
+
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+
+    if (m_class_name)
+    {
+        if (log)
+            log->Warning ("Class/method function specification not supported yet.\n");
+        return Searcher::eCallbackReturnStop;
+    }
+
+    switch (m_match_type)
+    {
+      case Breakpoint::Exact:
+        if (context.module_sp)
+        {
+            context.module_sp->FindSymbolsWithNameAndType (m_func_name, eSymbolTypeCode, sym_list);
+            context.module_sp->FindFunctions (m_func_name, false, func_list);
+        }
+        break;
+      case Breakpoint::Regexp:
+        if (context.module_sp)
+        {
+            context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list);
+            context.module_sp->FindFunctions (m_regex, true, func_list);
+        }
+        break;
+      case Breakpoint::Glob:
+        if (log)
+            log->Warning ("glob is not supported yet.");
+        break;
+    }
+
+    // Remove any duplicates between the funcion list and the symbol list
+    if (func_list.GetSize())
+    {
+        for (i = 0; i < func_list.GetSize(); i++)
+        {
+            if (func_list.GetContextAtIndex(i, sc) == false)
+                continue;
+
+            if (sc.function == NULL)
+                continue;
+            uint32_t j = 0;
+            while (j < sym_list.GetSize())
+            {
+                SymbolContext symbol_sc;
+                if (sym_list.GetContextAtIndex(j, symbol_sc))
+                {
+                    if (symbol_sc.symbol && symbol_sc.symbol->GetAddressRangePtr())
+                    {
+                        if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRangePtr()->GetBaseAddress())
+                        {
+                            sym_list.RemoveContextAtIndex(j);
+                            continue;   // Don't increment j
+                        }
+                    }
+                }
+
+                j++;
+            }
+        }
+
+        for (i = 0; i < func_list.GetSize(); i++)
+        {
+            if (func_list.GetContextAtIndex(i, sc))
+            {
+                if (sc.function)
+                {
+                    break_addr = sc.function->GetAddressRange().GetBaseAddress();
+                    if (skip_prologue)
+                    {
+                        const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
+                        if (prologue_byte_size)
+                            break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
+                    }
+
+                    if (filter.AddressPasses(break_addr))
+                    {
+                        BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location));
+                        if (bp_loc_sp && new_location && !m_breakpoint->IsInternal())
+                        {
+                            if (log)
+                            {
+                                StreamString s;
+                                bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
+                                log->Printf ("Added location: %s\n", s.GetData());
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    for (i = 0; i < sym_list.GetSize(); i++)
+    {
+        if (sym_list.GetContextAtIndex(i, sc))
+        {
+            if (sc.symbol && sc.symbol->GetAddressRangePtr())
+            {
+                break_addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress();
+
+                if (skip_prologue)
+                {
+                    const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize();
+                    if (prologue_byte_size)
+                        break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
+                }
+
+                if (filter.AddressPasses(break_addr))
+                {
+                    BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location));
+                    if (bp_loc_sp && new_location && !m_breakpoint->IsInternal())
+                    {
+                        StreamString s;
+                        bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
+                        if (log) 
+                            log->Printf ("Added location: %s\n", s.GetData());
+                    }
+                }
+            }
+        }
+    }
+    return Searcher::eCallbackReturnContinue;
+}
+
+Searcher::Depth
+BreakpointResolverName::GetDepth()
+{
+    return Searcher::eDepthModule;
+}
+
+void
+BreakpointResolverName::GetDescription (Stream *s)
+{
+    s->PutCString("Breakpoint by name: ");
+
+    if (m_match_type == Breakpoint::Regexp)
+        s->Printf("'%s' (regular expression)", m_regex.GetText());
+    else
+        s->Printf("'%s'", m_func_name.AsCString());
+}
+
+void
+BreakpointResolverName::Dump (Stream *s) const
+{
+
+}
+
diff --git a/source/Breakpoint/BreakpointSite.cpp b/source/Breakpoint/BreakpointSite.cpp
new file mode 100644
index 0000000..cd0920d
--- /dev/null
+++ b/source/Breakpoint/BreakpointSite.cpp
@@ -0,0 +1,221 @@
+//===-- BreakpointSite.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/BreakpointSite.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/BreakpointSiteList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+BreakpointSite::BreakpointSite
+(
+    BreakpointSiteList *list,
+    BreakpointLocationSP& owner,
+    lldb::addr_t addr,
+    lldb::tid_t tid,
+    bool use_hardware
+) :
+    StoppointLocation(GetNextID(), addr, tid, use_hardware),
+    m_type (eSoftware), // Process subclasses need to set this correctly using SetType()
+    m_saved_opcode(),
+    m_trap_opcode(),
+    m_enabled(false), // Need to create it disabled, so the first enable turns it on.
+    m_owners()
+{
+    m_owners.Add(owner);
+}
+
+BreakpointSite::~BreakpointSite()
+{
+    BreakpointLocationSP bp_loc_sp;
+    for (int i = 0; i < m_owners.GetSize(); i++)
+    {
+        m_owners.GetByIndex(i)->ClearBreakpointSite();
+    }
+}
+
+break_id_t
+BreakpointSite::GetNextID()
+{
+    static break_id_t g_next_id = 0;
+    return ++g_next_id;
+}
+
+// RETURNS - true if we should stop at this breakpoint, false if we
+// should continue.
+
+bool
+BreakpointSite::ShouldStop (StoppointCallbackContext *context)
+{
+    m_hit_count++;
+    return m_owners.ShouldStop (context);
+}
+
+bool
+BreakpointSite::IsBreakpointAtThisSite (lldb::break_id_t bp_id)
+{
+    for (int i = 0; i < m_owners.GetSize(); i++)
+    {
+        if (m_owners.GetByIndex(i)->GetBreakpoint().GetID() == bp_id)
+            return true;
+    }
+    return false;
+}
+
+void
+BreakpointSite::Dump(Stream *s) const
+{
+    if (s == NULL)
+        return;
+
+    s->Printf("BreakpointSite %u: tid = %4.4x  addr = 0x%8.8llx  type = %s breakpoint  hw_index = %i  hit_count = %-4u",
+            GetID(),
+            m_tid,
+            (uint64_t)m_addr,
+            IsHardware() ? "hardware" : "software",
+            GetHardwareIndex(),
+            GetHitCount());
+}
+
+void
+BreakpointSite::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+    if (level != lldb::eDescriptionLevelBrief)
+        s->Printf ("breakpoint site: %d ", GetID());
+    m_owners.GetDescription (s, level);
+}
+
+uint8_t *
+BreakpointSite::GetTrapOpcodeBytes()
+{
+    return &m_trap_opcode[0];
+}
+
+const uint8_t *
+BreakpointSite::GetTrapOpcodeBytes() const
+{
+    return &m_trap_opcode[0];
+}
+
+size_t
+BreakpointSite::GetTrapOpcodeMaxByteSize() const
+{
+    return sizeof(m_trap_opcode);
+}
+
+bool
+BreakpointSite::SetTrapOpcode (const uint8_t *trap_opcode, size_t trap_opcode_size)
+{
+    if (trap_opcode_size > 0 && trap_opcode_size <= sizeof(m_trap_opcode))
+    {
+        m_byte_size = trap_opcode_size;
+        ::memcpy (m_trap_opcode, trap_opcode, trap_opcode_size);
+        return true;
+    }
+    m_byte_size = 0;
+    return false;
+}
+
+uint8_t *
+BreakpointSite::GetSavedOpcodeBytes()
+{
+    return &m_saved_opcode[0];
+}
+
+const uint8_t *
+BreakpointSite::GetSavedOpcodeBytes() const
+{
+    return &m_saved_opcode[0];
+}
+
+bool
+BreakpointSite::IsEnabled () const
+{
+    return m_enabled;
+}
+
+void
+BreakpointSite::SetEnabled (bool enabled)
+{
+    m_enabled = enabled;
+}
+
+void
+BreakpointSite::AddOwner (BreakpointLocationSP &owner)
+{
+    m_owners.Add(owner);
+}
+
+uint32_t
+BreakpointSite::RemoveOwner (lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
+{
+    m_owners.Remove(break_id, break_loc_id);
+    return m_owners.GetSize();
+}
+
+uint32_t
+BreakpointSite::GetNumberOfOwners ()
+{
+    return m_owners.GetSize();
+}
+
+BreakpointLocationSP
+BreakpointSite::GetOwnerAtIndex (uint32_t index)
+{
+    return m_owners.GetByIndex (index);
+}
+
+bool
+BreakpointSite::IntersectsRange(lldb::addr_t addr, size_t size, lldb::addr_t *intersect_addr, size_t *intersect_size, size_t *opcode_offset) const
+{
+    // We only use software traps for software breakpoints
+    if (!IsHardware())
+    {
+        if (m_byte_size > 0)
+        {
+            const lldb::addr_t bp_end_addr = m_addr + m_byte_size;
+            const lldb::addr_t end_addr = addr + size;
+            // Is the breakpoint end address before the passed in start address?
+            if (bp_end_addr <= addr)
+                return false;
+            // Is the breakpoint start address after passed in end address?
+            if (end_addr <= m_addr)
+                return false;
+            if (intersect_addr || intersect_size || opcode_offset)
+            {
+                if (m_addr < addr)
+                {
+                    if (intersect_addr)
+                        *intersect_addr = addr;
+                    if (intersect_size)
+                        *intersect_size = std::min<lldb::addr_t>(bp_end_addr, end_addr) - addr;
+                    if (opcode_offset)
+                        *opcode_offset = addr - m_addr;
+                }
+                else
+                {
+                    if (intersect_addr)
+                        *intersect_addr = m_addr;
+                    if (intersect_size)
+                        *intersect_size = std::min<lldb::addr_t>(bp_end_addr, end_addr) - m_addr;
+                    if (opcode_offset)
+                        *opcode_offset = 0;
+                }
+            }
+            return true;
+        }
+    }
+    return false;
+}
diff --git a/source/Breakpoint/BreakpointSiteList.cpp b/source/Breakpoint/BreakpointSiteList.cpp
new file mode 100644
index 0000000..19e18bb
--- /dev/null
+++ b/source/Breakpoint/BreakpointSiteList.cpp
@@ -0,0 +1,229 @@
+//===-- BreakpointSiteList.cpp ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/BreakpointSiteList.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Stream.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+BreakpointSiteList::BreakpointSiteList() :
+    m_bp_site_list()
+{
+}
+
+BreakpointSiteList::~BreakpointSiteList()
+{
+}
+
+// Add breakpoint site to the list.  However, if the element already exists in the
+// list, then we don't add it, and return LLDB_INVALID_BREAK_ID.
+
+lldb::user_id_t
+BreakpointSiteList::Add(const BreakpointSiteSP &bp)
+{
+    lldb::addr_t bp_site_load_addr = bp->GetLoadAddress();
+    collection::iterator iter = m_bp_site_list.find (bp_site_load_addr);
+
+    if (iter == m_bp_site_list.end())
+    {
+        m_bp_site_list.insert (iter, collection::value_type (bp_site_load_addr, bp));
+        return bp->GetID();
+    }
+    else
+    {
+        return LLDB_INVALID_BREAK_ID;
+    }
+}
+
+bool
+BreakpointSiteList::ShouldStop (StoppointCallbackContext *context, lldb::user_id_t break_id)
+{
+    BreakpointSiteSP bp = FindByID (break_id);
+    if (bp)
+    {
+        // Let the BreakpointSite decide if it should stop here (could not have
+        // reached it's target hit count yet, or it could have a callback
+        // that decided it shouldn't stop (shared library loads/unloads).
+        return bp->ShouldStop (context);
+    }
+    // We should stop here since this BreakpointSite isn't valid anymore or it
+    // doesn't exist.
+    return true;
+}
+lldb::user_id_t
+BreakpointSiteList::FindIDByAddress (lldb::addr_t addr)
+{
+    BreakpointSiteSP bp = FindByAddress (addr);
+    if (bp)
+    {
+        //DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8llx ) => %u", __FUNCTION__, (uint64_t)addr, bp->GetID());
+        return bp.get()->GetID();
+    }
+    //DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8llx ) => NONE", __FUNCTION__, (uint64_t)addr);
+    return LLDB_INVALID_BREAK_ID;
+}
+
+bool
+BreakpointSiteList::Remove (lldb::user_id_t break_id)
+{
+    collection::iterator pos = GetIDIterator(break_id);    // Predicate
+    if (pos != m_bp_site_list.end())
+    {
+        m_bp_site_list.erase(pos);
+        return true;
+    }
+    return false;
+}
+
+bool
+BreakpointSiteList::RemoveByAddress (lldb::addr_t address)
+{
+    collection::iterator pos =  m_bp_site_list.find(address);
+    if (pos != m_bp_site_list.end())
+    {
+        m_bp_site_list.erase(pos);
+        return true;
+    }
+    return false;
+}
+
+class BreakpointSiteIDMatches
+{
+public:
+    BreakpointSiteIDMatches (lldb::user_id_t break_id) :
+        m_break_id(break_id)
+    {
+    }
+
+    bool operator() (std::pair <lldb::addr_t, BreakpointSiteSP> val_pair) const
+    {
+        return m_break_id == val_pair.second.get()->GetID();
+    }
+
+private:
+   const lldb::user_id_t m_break_id;
+};
+
+BreakpointSiteList::collection::iterator
+BreakpointSiteList::GetIDIterator (lldb::user_id_t break_id)
+{
+    return std::find_if(m_bp_site_list.begin(), m_bp_site_list.end(),   // Search full range
+                        BreakpointSiteIDMatches(break_id));             // Predicate
+}
+
+BreakpointSiteList::collection::const_iterator
+BreakpointSiteList::GetIDConstIterator (lldb::user_id_t break_id) const
+{
+    return std::find_if(m_bp_site_list.begin(), m_bp_site_list.end(),   // Search full range
+                        BreakpointSiteIDMatches(break_id));             // Predicate
+}
+
+BreakpointSiteSP
+BreakpointSiteList::FindByID (lldb::user_id_t break_id)
+{
+    BreakpointSiteSP stop_sp;
+    collection::iterator pos = GetIDIterator(break_id);
+    if (pos != m_bp_site_list.end())
+        stop_sp = pos->second;
+
+    return stop_sp;
+}
+
+const BreakpointSiteSP
+BreakpointSiteList::FindByID (lldb::user_id_t break_id) const
+{
+    BreakpointSiteSP stop_sp;
+    collection::const_iterator pos = GetIDConstIterator(break_id);
+    if (pos != m_bp_site_list.end())
+        stop_sp = pos->second;
+
+    return stop_sp;
+}
+
+BreakpointSiteSP
+BreakpointSiteList::FindByAddress (lldb::addr_t addr)
+{
+    BreakpointSiteSP found_sp;
+
+    collection::iterator iter =  m_bp_site_list.find(addr);
+    if (iter != m_bp_site_list.end())
+        found_sp = iter->second;
+    return found_sp;
+}
+
+void
+BreakpointSiteList::Dump (Stream *s) const
+{
+    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+    s->Indent();
+    s->Printf("BreakpointSiteList with %u BreakpointSites:\n", (uint32_t)m_bp_site_list.size());
+    s->IndentMore();
+    collection::const_iterator pos;
+    collection::const_iterator end = m_bp_site_list.end();
+    for (pos = m_bp_site_list.begin(); pos != end; ++pos)
+        pos->second.get()->Dump(s);
+    s->IndentLess();
+}
+
+
+BreakpointSiteSP
+BreakpointSiteList::GetByIndex (uint32_t i)
+{
+    BreakpointSiteSP stop_sp;
+    collection::iterator end = m_bp_site_list.end();
+    collection::iterator pos;
+    uint32_t curr_i = 0;
+    for (pos = m_bp_site_list.begin(), curr_i = 0; pos != end; ++pos, ++curr_i)
+    {
+        if (curr_i == i)
+            stop_sp = pos->second;
+    }
+    return stop_sp;
+}
+
+const BreakpointSiteSP
+BreakpointSiteList::GetByIndex (uint32_t i) const
+{
+    BreakpointSiteSP stop_sp;
+    collection::const_iterator end = m_bp_site_list.end();
+    collection::const_iterator pos;
+    uint32_t curr_i = 0;
+    for (pos = m_bp_site_list.begin(), curr_i = 0; pos != end; ++pos, ++curr_i)
+    {
+        if (curr_i == i)
+            stop_sp = pos->second;
+    }
+    return stop_sp;
+}
+
+void
+BreakpointSiteList::SetEnabledForAll (const bool enabled, const lldb::user_id_t except_id)
+{
+    collection::iterator end = m_bp_site_list.end();
+    collection::iterator pos;
+    for (pos = m_bp_site_list.begin(); pos != end; ++pos)
+    {
+        if (except_id != LLDB_INVALID_BREAK_ID && except_id != pos->second->GetID())
+            pos->second->SetEnabled (enabled);
+        else
+            pos->second->SetEnabled (!enabled);
+    }
+}
+
+const BreakpointSiteList::collection *
+BreakpointSiteList::GetMap ()
+{
+    return &m_bp_site_list;
+}
diff --git a/source/Breakpoint/Stoppoint.cpp b/source/Breakpoint/Stoppoint.cpp
new file mode 100644
index 0000000..583ab47
--- /dev/null
+++ b/source/Breakpoint/Stoppoint.cpp
@@ -0,0 +1,46 @@
+//===-- Stoppoint.cpp -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-private.h"
+#include "lldb/Breakpoint/Stoppoint.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Stoppoint constructor
+//----------------------------------------------------------------------
+Stoppoint::Stoppoint() :
+    m_bid (LLDB_INVALID_BREAK_ID)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+Stoppoint::~Stoppoint()
+{
+}
+
+break_id_t
+Stoppoint::GetID () const
+{
+    return m_bid;
+}
+
+void
+Stoppoint::SetID (break_id_t bid)
+{
+    m_bid = bid;
+}
diff --git a/source/Breakpoint/StoppointCallbackContext.cpp b/source/Breakpoint/StoppointCallbackContext.cpp
new file mode 100644
index 0000000..8662062
--- /dev/null
+++ b/source/Breakpoint/StoppointCallbackContext.cpp
@@ -0,0 +1,38 @@
+//===-- StoppointCallbackContext.cpp ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb_private;
+
+StoppointCallbackContext::StoppointCallbackContext() :
+    event (NULL),
+    context()
+{
+}
+
+StoppointCallbackContext::StoppointCallbackContext(Event *e, Process* p, Thread *t, StackFrame *f, bool synchronously) :
+    event (e),
+    context (p, t, f),
+    is_synchronous(synchronously)
+{
+}
+
+void
+StoppointCallbackContext::Clear()
+{
+    event = NULL;
+    context.Clear();
+    is_synchronous = false;
+}
diff --git a/source/Breakpoint/StoppointLocation.cpp b/source/Breakpoint/StoppointLocation.cpp
new file mode 100644
index 0000000..999ad53
--- /dev/null
+++ b/source/Breakpoint/StoppointLocation.cpp
@@ -0,0 +1,120 @@
+//===-- StoppointLocation.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/StoppointLocation.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// StoppointLocation constructor
+//----------------------------------------------------------------------
+StoppointLocation::StoppointLocation (break_id_t bid, addr_t addr, tid_t tid, bool hardware) :
+    m_loc_id(bid),
+    m_tid(tid),
+    m_byte_size(0),
+    m_addr(addr),
+    m_hit_count(0),
+    m_hw_preferred(hardware),
+    m_hw_index(LLDB_INVALID_INDEX32)
+{
+}
+
+StoppointLocation::StoppointLocation (break_id_t bid, addr_t addr, tid_t tid, size_t size, bool hardware) :
+    m_loc_id(bid),
+    m_tid(tid),
+    m_byte_size(size),
+    m_addr(addr),
+    m_hit_count(0),
+    m_hw_preferred(hardware),
+    m_hw_index(LLDB_INVALID_INDEX32)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+StoppointLocation::~StoppointLocation()
+{
+}
+
+
+size_t
+StoppointLocation::GetByteSize () const
+{
+    return m_byte_size;
+}
+
+addr_t
+StoppointLocation::GetLoadAddress() const
+{
+    return m_addr;
+}
+
+tid_t
+StoppointLocation::GetThreadID() const
+{
+    return m_tid;
+}
+
+uint32_t
+StoppointLocation::GetHitCount () const
+{
+    return m_hit_count;
+}
+
+bool
+StoppointLocation::HardwarePreferred () const
+{
+    return m_hw_preferred;
+}
+
+bool
+StoppointLocation::IsHardware () const
+{
+    return m_hw_index != LLDB_INVALID_INDEX32;
+}
+
+uint32_t
+StoppointLocation::GetHardwareIndex () const
+{
+    return m_hw_index;
+}
+
+void
+StoppointLocation::SetHardwareIndex (uint32_t hw_index)
+{
+    m_hw_index = hw_index;
+}
+
+// RETURNS - true if we should stop at this breakpoint, false if we
+// should continue.
+
+bool
+StoppointLocation::ShouldStop (StoppointCallbackContext *context)
+{
+    return true;
+}
+
+break_id_t
+StoppointLocation::GetID() const
+{
+    return m_loc_id;
+}
+
+void
+StoppointLocation::Dump (Stream *stream) const
+{
+
+}
diff --git a/source/Breakpoint/WatchpointLocation.cpp b/source/Breakpoint/WatchpointLocation.cpp
new file mode 100644
index 0000000..f765ef4
--- /dev/null
+++ b/source/Breakpoint/WatchpointLocation.cpp
@@ -0,0 +1,137 @@
+//===-- WatchpointLocation.cpp ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/WatchpointLocation.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Stream.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+WatchpointLocation::WatchpointLocation (lldb::addr_t addr, lldb::tid_t tid, bool hardware) :
+    StoppointLocation (GetNextID(), addr, tid, hardware),
+    m_enabled(0),
+    m_watch_read(0),
+    m_watch_write(0),
+    m_watch_was_read(0),
+    m_watch_was_written(0),
+    m_ignore_count(0),
+    m_callback(NULL),
+    m_callback_baton(NULL)
+{
+}
+
+WatchpointLocation::~WatchpointLocation()
+{
+}
+
+break_id_t
+WatchpointLocation::GetNextID()
+{
+    static break_id_t g_next_ID = 0;
+    return ++g_next_ID;
+}
+
+bool
+WatchpointLocation::SetCallback (WatchpointHitCallback callback, void *callback_baton)
+{
+    m_callback = callback;
+    m_callback_baton = callback_baton;
+    return true;
+}
+
+
+// RETURNS - true if we should stop at this breakpoint, false if we
+// should continue.
+
+bool
+WatchpointLocation::BreakpointWasHit (StoppointCallbackContext *context)
+{
+    m_hit_count++;
+
+    if (m_hit_count > m_ignore_count)
+    {
+        uint32_t access = 0;
+        if (m_watch_was_read)
+            access |= LLDB_WATCH_TYPE_READ;
+        if (m_watch_was_written)
+            access |= LLDB_WATCH_TYPE_WRITE;
+        return m_callback(m_callback_baton, context, GetID(), access);
+    }
+    return false;
+}
+
+void
+WatchpointLocation::Dump(Stream *s) const
+{
+    if (s == NULL)
+        return;
+
+    s->Printf("WatchpointLocation %u: tid = %4.4x  addr = 0x%8.8llx  size = %zu  state = %s  type = %s watchpoint (%s%s)  hw_index = %i  hit_count = %-4u  ignore_count = %-4u  callback = %8p baton = %8p",
+            GetID(),
+            m_tid,
+            (uint64_t)m_addr,
+            m_byte_size,
+            m_enabled ? "enabled " : "disabled",
+            IsHardware() ? "hardware" : "software",
+            m_watch_read ? "r" : "",
+            m_watch_write ? "w" : "",
+            GetHardwareIndex(),
+            GetHitCount(),
+            GetIgnoreCount(),
+            m_callback,
+            m_callback_baton);
+}
+
+bool
+WatchpointLocation::IsEnabled() const
+{
+    return m_enabled;
+}
+
+void
+WatchpointLocation::SetEnabled(uint32_t enabled)
+{
+    if (!enabled)
+        SetHardwareIndex(LLDB_INVALID_INDEX32);
+    m_enabled = enabled;
+}
+
+void
+WatchpointLocation::SetWatchpointType (uint32_t type)
+{
+    m_watch_read = (type & LLDB_WATCH_TYPE_READ) != 0;
+    m_watch_write = (type & LLDB_WATCH_TYPE_WRITE) != 0;
+}
+
+bool
+WatchpointLocation::WatchpointRead () const
+{
+    return m_watch_read != 0;
+}
+bool
+WatchpointLocation::WatchpointWrite () const
+{
+    return m_watch_write != 0;
+}
+int32_t
+WatchpointLocation::GetIgnoreCount () const
+{
+    return m_ignore_count;
+}
+
+void
+WatchpointLocation::SetIgnoreCount (int32_t n)
+{
+    m_ignore_count = n;
+}
diff --git a/source/Commands/CommandObjectAdd.cpp b/source/Commands/CommandObjectAdd.cpp
new file mode 100644
index 0000000..cd1d02d
--- /dev/null
+++ b/source/Commands/CommandObjectAdd.cpp
@@ -0,0 +1,51 @@
+//===-- CommandObjectAdd.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectAdd.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectAdd
+//-------------------------------------------------------------------------
+
+CommandObjectAdd::CommandObjectAdd () :
+    CommandObject ("add",
+                     "Allows the user to add a new command/function pair to the debugger's dictionary.",
+                     "add <new-command-name> <script-function-name>")
+{
+}
+
+CommandObjectAdd::~CommandObjectAdd()
+{
+}
+
+
+bool
+CommandObjectAdd::Execute
+(
+    Args& command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    result.AppendMessage ("This function has not been implemented yet.");
+    result.SetStatus (eReturnStatusSuccessFinishNoResult);
+    return result.Succeeded();
+}
diff --git a/source/Commands/CommandObjectAdd.h b/source/Commands/CommandObjectAdd.h
new file mode 100644
index 0000000..9aa59b6
--- /dev/null
+++ b/source/Commands/CommandObjectAdd.h
@@ -0,0 +1,43 @@
+//===-- CommandObjectAdd.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_CommandObjectAdd_h_
+#define liblldb_CommandObjectAdd_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+//-------------------------------------------------------------------------
+// CommandObjectAdd
+//-------------------------------------------------------------------------
+
+class CommandObjectAdd : public CommandObject
+{
+public:
+
+    CommandObjectAdd ();
+
+    virtual
+    ~CommandObjectAdd ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectAdd_h_
diff --git a/source/Commands/CommandObjectAlias.cpp b/source/Commands/CommandObjectAlias.cpp
new file mode 100644
index 0000000..50c2ab9
--- /dev/null
+++ b/source/Commands/CommandObjectAlias.cpp
@@ -0,0 +1,225 @@
+//===-- CommandObjectAlias.cpp ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectAlias.h"
+
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectAlias
+//-------------------------------------------------------------------------
+
+CommandObjectAlias::CommandObjectAlias () :
+    CommandObject ("alias",
+                     "Allows users to define their own debugger command abbreviations.",
+                     "alias <new_command> <old_command> [<options-for-aliased-command>]")
+{
+    SetHelpLong(
+"'alias' allows the user to create a short-cut or abbreviation for long \n\
+commands, multi-word commands, and commands that take particular options. \n\
+Below are some simple examples of how one might use the 'alias' command: \n\
+\n  'alias sc script'       // Creates the abbreviation 'sc' for the 'script' \n\
+                          // command. \n\
+  'alias bp breakpoint'   // Creates the abbreviation 'bp' for the 'breakpoint' \n\
+                          // command.  Since breakpoint commands are two-word \n\
+                          // commands, the user will still need to enter the \n\
+                          // second word after 'bp', e.g. 'bp enable' or \n\
+                          // 'bp delete'. \n\
+  'alias bpi breakpoint list'   // Creates the abbreviation 'bpi' for the \n\
+                                // two-word command 'breakpoint list'. \n\
+\nAn alias can include some options for the command, with the values either \n\
+filled in at the time the alias is created, or specified as positional \n\
+arguments, to be filled in when the alias is invoked.  The following example \n\
+shows how to create aliases with options: \n\
+\n\
+    'alias bfl breakpoint set -f %1 -l %2' \n\
+\nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\
+options already part of the alias.  So if the user wants to set a breakpoint \n\
+by file and line without explicitly having to use the -f and -l options, the \n\
+user can now use 'bfl' instead.  The '%1' and '%2' are positional placeholders \n\
+for the actual arguments that will be passed when the alias command is used. \n\
+The number in the placeholder refers to the position/order the actual value \n\
+occupies when the alias is used.  So all the occurrences of '%1' in the alias \n\
+will be replaced with the first argument, all the occurrences of '%2' in the \n\
+alias will be replaced with the second argument, and so on.  This also allows \n\
+actual arguments to be used multiple times within an alias (see 'process \n\
+launch' example below).  So in the 'bfl' case, the actual file value will be \n\
+filled in with the first argument following 'bfl' and the actual line number \n\
+value will be filled in with the second argument.  The user would use this \n\
+alias as follows: \n\
+\n   (dbg)  alias bfl breakpoint set -f %1 -l %2 \n\
+   <... some time later ...> \n\
+   (dbg)  bfl my-file.c 137 \n\
+\nThis would be the same as if the user had entered \n\
+'breakpoint set -f my-file.c -l 137'. \n\
+\nAnother example: \n\
+\n    (dbg)  alias pltty  process launch -s -o %1 -e %1 \n\
+    (dbg)  pltty /dev/tty0 \n\
+    // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\
+\nIf the user always wanted to pass the same value to a particular option, the \n\
+alias could be defined with that value directly in the alias as a constant, \n\
+rather than using a positional placeholder: \n\
+\n     alias bl3  breakpoint set -f %1 -l 3  // Always sets a breakpoint on line \n\
+                                           // 3 of whatever file is indicated. \n");
+
+}
+
+CommandObjectAlias::~CommandObjectAlias ()
+{
+}
+
+
+bool
+CommandObjectAlias::Execute (Args& args, CommandContext *context, CommandInterpreter *interpreter,
+                               CommandReturnObject &result)
+{
+    const int argc = args.GetArgumentCount();
+
+    if (argc < 2)
+      {
+        result.AppendError ("'alias' requires at least two arguments");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+      }
+
+    const std::string alias_command = args.GetArgumentAtIndex(0);
+    const std::string actual_command = args.GetArgumentAtIndex(1);
+
+    args.Shift();  // Shift the alias command word off the argument vector.
+    args.Shift();  // Shift the old command word off the argument vector.
+
+    // Verify that the command is alias'able, and get the appropriate command object.
+
+    if (interpreter->CommandExists (alias_command.c_str()))
+    {
+        result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
+                                     alias_command.c_str());
+        result.SetStatus (eReturnStatusFailed);
+    }
+    else
+    {
+         CommandObjectSP command_obj_sp(interpreter->GetCommandSP (actual_command.c_str()));
+         CommandObjectSP subcommand_obj_sp;
+         bool use_subcommand = false;
+         if (command_obj_sp.get())
+         {
+             CommandObject *cmd_obj = command_obj_sp.get();
+             CommandObject *sub_cmd_obj;
+             OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
+             OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
+
+             if (cmd_obj->IsMultiwordObject())
+             {
+                 if (argc >= 3)
+                 {
+                     const std::string sub_command = args.GetArgumentAtIndex(0);
+                     assert (sub_command.length() != 0);
+                     subcommand_obj_sp =
+                                       (((CommandObjectMultiword *) cmd_obj)->GetSubcommandSP (sub_command.c_str()));
+                     if (subcommand_obj_sp.get())
+                     {
+                         sub_cmd_obj = subcommand_obj_sp.get();
+                         use_subcommand = true;
+                         args.Shift();  // Shift the sub_command word off the argument vector.
+                     }
+                     else
+                     {
+                         result.AppendErrorWithFormat ("Error occurred while attempting to look up command '%s %s'.\n",
+                                                      alias_command.c_str(), sub_command.c_str());
+                         result.SetStatus (eReturnStatusFailed);
+                         return false;
+                     }
+                 }
+             }
+
+             // Verify & handle any options/arguments passed to the alias command
+
+             if (args.GetArgumentCount () > 0)
+             {
+                 if ((!use_subcommand && (cmd_obj->WantsRawCommandString()))
+                     || (use_subcommand && (sub_cmd_obj->WantsRawCommandString())))
+                 {
+                     result.AppendErrorWithFormat ("'%s' cannot be aliased with any options or arguments.\n",
+                                                  (use_subcommand ? sub_cmd_obj->GetCommandName()
+                                                                  : cmd_obj->GetCommandName()));
+                     result.SetStatus (eReturnStatusFailed);
+                     return false;
+                 }
+
+                 // options or arguments have been passed to the alias command, and must be verified & processed here.
+                 if ((!use_subcommand && (cmd_obj->GetOptions() != NULL))
+                     || (use_subcommand && (sub_cmd_obj->GetOptions() != NULL)))
+                 {
+                     Options *options;
+                     if (use_subcommand)
+                         options = sub_cmd_obj->GetOptions();
+                     else
+                         options = cmd_obj->GetOptions();
+                     options->ResetOptionValues ();
+                     args.Unshift ("dummy_arg");
+                     args.ParseAliasOptions (*options, result, option_arg_vector);
+                     args.Shift ();
+                     if (result.Succeeded())
+                         options->VerifyPartialOptions (result);
+                     if (!result.Succeeded())
+                         return false;
+                 }
+                 else
+                 {
+                     for (int i = 0; i < args.GetArgumentCount(); ++i)
+                         option_arg_vector->push_back (OptionArgPair ("<argument>",
+                                                                      std::string (args.GetArgumentAtIndex (i))));
+                 }
+             }
+
+             // Create the alias.
+
+             if (interpreter->AliasExists (alias_command.c_str())
+                 || interpreter->UserCommandExists (alias_command.c_str()))
+             {
+                 OptionArgVectorSP tmp_option_arg_sp (interpreter->GetAliasOptions (alias_command.c_str()));
+                 if (tmp_option_arg_sp.get())
+                 {
+                     if (option_arg_vector->size() == 0)
+                         interpreter->RemoveAliasOptions (alias_command.c_str());
+                 }
+                 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n", alias_command.c_str());
+             }
+
+             if (use_subcommand)
+                 interpreter->AddAlias (alias_command.c_str(), subcommand_obj_sp);
+             else
+                 interpreter->AddAlias (alias_command.c_str(), command_obj_sp);
+             if (option_arg_vector->size() > 0)
+                 interpreter->AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
+             result.SetStatus (eReturnStatusSuccessFinishNoResult);
+         }
+         else
+         {
+             result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str());
+             result.SetStatus (eReturnStatusFailed);
+         }
+    }
+
+    return result.Succeeded();
+}
+
diff --git a/source/Commands/CommandObjectAlias.h b/source/Commands/CommandObjectAlias.h
new file mode 100644
index 0000000..859b7ce
--- /dev/null
+++ b/source/Commands/CommandObjectAlias.h
@@ -0,0 +1,43 @@
+//===-- CommandObjectAlias.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_CommandObjectAlias_h_
+#define liblldb_CommandObjectAlias_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectAlias
+//-------------------------------------------------------------------------
+
+class CommandObjectAlias : public CommandObject
+{
+public:
+
+    CommandObjectAlias ();
+
+    virtual
+    ~CommandObjectAlias ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectAlias_h_
diff --git a/source/Commands/CommandObjectAppend.cpp b/source/Commands/CommandObjectAppend.cpp
new file mode 100644
index 0000000..613b85b
--- /dev/null
+++ b/source/Commands/CommandObjectAppend.cpp
@@ -0,0 +1,95 @@
+//===-- CommandObjectAppend.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectAppend.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-----------------------------------------------------------------------------
+// CommandObjectAppend
+//-----------------------------------------------------------------------------
+
+CommandObjectAppend::CommandObjectAppend () :
+    CommandObject ("append",
+                   "Allows the user to append a value to a single debugger setting variable, for settings that are of list types. Type 'settings' to see a list of debugger setting variables",
+                   "append <var-name> <value-string>")
+{
+}
+
+CommandObjectAppend::~CommandObjectAppend ()
+{
+}
+
+bool
+CommandObjectAppend::Execute
+(
+    Args& command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    CommandInterpreter::VariableMap::iterator pos;
+
+    const int argc = command.GetArgumentCount();
+    if (argc < 2)
+    {
+        result.AppendError ("'append' requires at least two arguments");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    const char *var_name = command.GetArgumentAtIndex(0);
+    command.Shift();
+
+
+    if (var_name == NULL || var_name[0] == '\0')
+    {
+        result.AppendError ("'set' command requires a valid variable name. No value supplied");
+        result.SetStatus (eReturnStatusFailed);
+    }
+    else
+    {
+        StateVariable *var = interpreter->GetStateVariable(var_name);
+        if (var == NULL)
+        {
+            result.AppendErrorWithFormat ("'%s' is not a settable internal variable.\n", var_name);
+            result.SetStatus (eReturnStatusFailed);
+        }
+        else
+        {
+            if (var->GetType() == StateVariable::eTypeString)
+            {
+                for (int i = 0; i < command.GetArgumentCount(); ++i)
+                    var->AppendStringValue (command.GetArgumentAtIndex(i));
+                result.SetStatus (eReturnStatusSuccessFinishNoResult);
+            }
+            else if (var->GetType() == StateVariable::eTypeStringArray)
+            {
+                var->GetArgs().AppendArguments (command);
+                result.SetStatus (eReturnStatusSuccessFinishNoResult);
+            }
+            else
+            {
+                result.AppendErrorWithFormat ("Values cannot be appended to variable '%s'.  Try 'set' instead.\n", var_name);
+                result.SetStatus (eReturnStatusFailed);
+            }
+        }
+    }
+    return result.Succeeded();
+}
+
diff --git a/source/Commands/CommandObjectAppend.h b/source/Commands/CommandObjectAppend.h
new file mode 100644
index 0000000..4362837
--- /dev/null
+++ b/source/Commands/CommandObjectAppend.h
@@ -0,0 +1,43 @@
+//===-- CommandObjectAppend.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_CommandObjectAppend_h_
+#define liblldb_CommandObjectAppend_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+//-----------------------------------------------------------------------------
+// CommandObjectAppend
+//-----------------------------------------------------------------------------
+
+class CommandObjectAppend : public CommandObject
+{
+public:
+    CommandObjectAppend ();
+
+    virtual
+    ~CommandObjectAppend ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectAppend_h_
diff --git a/source/Commands/CommandObjectApropos.cpp b/source/Commands/CommandObjectApropos.cpp
new file mode 100644
index 0000000..0fcc093
--- /dev/null
+++ b/source/Commands/CommandObjectApropos.cpp
@@ -0,0 +1,96 @@
+//===-- CommandObjectApropos.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectApropos.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Options.h"
+
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectApropos
+//-------------------------------------------------------------------------
+
+CommandObjectApropos::CommandObjectApropos () :
+    CommandObject ("apropos",
+                     "Finds a list of debugger commands related to a particular word/subject.",
+                     "apropos <search-word>")
+{
+}
+
+CommandObjectApropos::~CommandObjectApropos()
+{
+}
+
+
+bool
+CommandObjectApropos::Execute (Args &command, CommandContext *context, CommandInterpreter *interpreter, 
+                              CommandReturnObject &result)
+{
+    const int argc = command.GetArgumentCount ();
+
+    if (argc == 1)
+    {
+        const char *search_word = command.GetArgumentAtIndex(0);
+        if ((search_word != NULL)
+            && (strlen (search_word) > 0))
+        {
+            // The bulk of the work must be done inside the Command Interpreter, since the command dictionary
+            // is private.
+            StringList commands_found;
+            StringList commands_help;
+            interpreter->FindCommandsForApropos (search_word, commands_found, commands_help);
+            if (commands_found.GetSize() == 0)
+            {
+                result.AppendMessageWithFormat ("No commands found pertaining to '%s'.", search_word);
+                result.AppendMessage ("Try 'help' to see a complete list of debugger commands.");
+            }
+            else
+            {
+                result.AppendMessageWithFormat ("The following commands may relate to '%s':\n", search_word);
+                size_t max_len = 0;
+
+                for (int i = 0; i < commands_found.GetSize(); ++i)
+                {
+                    int len = strlen (commands_found.GetStringAtIndex (i));
+                    if (len > max_len)
+                        max_len = len;
+                }
+
+                for (int i = 0; i < commands_found.GetSize(); ++i)
+                    interpreter->OutputFormattedHelpText (result.GetOutputStream(), commands_found.GetStringAtIndex(i),
+                                                         "--", commands_help.GetStringAtIndex(i), max_len);
+
+            }
+            result.SetStatus (eReturnStatusSuccessFinishNoResult);
+        }
+        else
+        {
+            result.AppendError ("'' is not a valid search word.\n");
+            result.SetStatus (eReturnStatusFailed);
+        }
+    }
+    else
+    {
+        result.AppendError ("'apropos' must be called with exactly one argument.\n");
+        result.SetStatus (eReturnStatusFailed);
+    }
+
+    return result.Succeeded();
+}
diff --git a/source/Commands/CommandObjectApropos.h b/source/Commands/CommandObjectApropos.h
new file mode 100644
index 0000000..a079a3f
--- /dev/null
+++ b/source/Commands/CommandObjectApropos.h
@@ -0,0 +1,45 @@
+//===-- CommandObjectApropos.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_CommandObjectApropos_h_
+#define liblldb_CommandObjectApropos_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectApropos
+//-------------------------------------------------------------------------
+
+class CommandObjectApropos : public CommandObject
+{
+public:
+
+    CommandObjectApropos ();
+
+    virtual
+    ~CommandObjectApropos ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectApropos_h_
diff --git a/source/Commands/CommandObjectArgs.cpp b/source/Commands/CommandObjectArgs.cpp
new file mode 100644
index 0000000..7f1fd3d
--- /dev/null
+++ b/source/Commands/CommandObjectArgs.cpp
@@ -0,0 +1,279 @@
+//===-- CommandObjectArgs.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectArgs.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Expression/ClangExpression.h"
+#include "lldb/Expression/ClangExpressionVariable.h"
+#include "lldb/Expression/ClangFunction.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/Variable.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/StackFrame.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+// This command is a toy.  I'm just using it to have a way to construct the arguments to
+// calling functions.
+//
+
+CommandObjectArgs::CommandOptions::CommandOptions () :
+Options()
+{
+    // Keep only one place to reset the values to their defaults
+    ResetOptionValues();
+}
+
+
+CommandObjectArgs::CommandOptions::~CommandOptions ()
+{
+}
+
+Error
+CommandObjectArgs::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
+{
+    Error error;
+    
+    char short_option = (char) m_getopt_table[option_idx].val;
+    
+    switch (short_option)
+    {
+        default:
+            error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
+            break;
+    }
+    
+    return error;
+}
+
+void
+CommandObjectArgs::CommandOptions::ResetOptionValues ()
+{
+    Options::ResetOptionValues();
+}
+
+const lldb::OptionDefinition*
+CommandObjectArgs::CommandOptions::GetDefinitions ()
+{
+    return g_option_table;
+}
+
+CommandObjectArgs::CommandObjectArgs () :
+    CommandObject ("args",
+                   "When stopped at the start of a function, reads function arguments of type (u?)int(8|16|32|64)_t, (void|char)*",
+                   "args")
+{
+}
+
+CommandObjectArgs::~CommandObjectArgs ()
+{
+}
+
+Options *
+CommandObjectArgs::GetOptions ()
+{
+    return &m_options;
+}
+
+bool
+CommandObjectArgs::Execute(Args &command,
+                           CommandContext *context,
+                           CommandInterpreter *interpreter,
+                           CommandReturnObject &result)
+{
+    ConstString target_triple;
+    
+    Process *process = context->GetExecutionContext().process;
+    if (!process)
+    {
+        result.AppendError ("Args found no process.");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+    
+    const ABI *abi = process->GetABI ();
+    if (!abi)
+    {
+        result.AppendError ("The current process has no ABI.");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+    
+    int num_args = command.GetArgumentCount ();
+    int arg_index;
+    
+    if (!num_args)
+    {
+        result.AppendError ("args requires at least one argument");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+    
+    Thread *thread = context->GetExecutionContext ().thread;
+    
+    if (!thread)
+    {
+        result.AppendError ("args found no thread.");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+        
+    lldb::StackFrameSP thread_cur_frame = thread->GetCurrentFrame ();
+    if (!thread_cur_frame)
+    {
+        result.AppendError ("The current thread has no current frame.");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+    
+    Module *thread_module = thread_cur_frame->GetPC ().GetModule ();
+    if (!thread_module)
+    {
+        result.AppendError ("The PC has no associated module.");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+    
+    TypeList *thread_type_list = thread_module->GetTypeList ();
+    if (!thread_type_list)
+    {
+        result.AppendError ("The module has no type list.");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+    
+    ClangASTContext &ast_context = thread_type_list->GetClangASTContext();
+    
+    ValueList value_list;
+    
+    for (arg_index = 0; arg_index < num_args; ++arg_index)
+    {
+        const char *arg_type_cstr = command.GetArgumentAtIndex(arg_index);
+        Value value;
+        value.SetValueType(Value::eValueTypeScalar);
+        void *type;
+        
+        char *int_pos;
+        if ((int_pos = strstr (arg_type_cstr, "int")))
+        {
+            Encoding encoding = eEncodingSint;
+            
+            int width = 0;
+            
+            if (int_pos > arg_type_cstr + 1)
+            {
+                result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
+                result.SetStatus (eReturnStatusFailed);
+                return false;
+            }
+            if (int_pos == arg_type_cstr + 1 && arg_type_cstr[0] != 'u')
+            {
+                result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
+                result.SetStatus (eReturnStatusFailed);
+                return false;
+            }
+            if (arg_type_cstr[0] == 'u')
+            {
+                encoding = eEncodingUint;
+            }
+            
+            char *width_pos = int_pos + 3;
+            
+            if (!strcmp (width_pos, "8_t"))
+                width = 8;
+            else if (!strcmp (width_pos, "16_t"))
+                width = 16;
+            else if (!strcmp (width_pos, "32_t"))
+                width = 32;
+            else if (!strcmp (width_pos, "64_t"))
+                width = 64;
+            else
+            {
+                result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
+                result.SetStatus (eReturnStatusFailed);
+                return false;
+            }
+            
+            type = ast_context.GetBuiltinTypeForEncodingAndBitSize(encoding, width);
+            
+            if (!type)
+            {
+                result.AppendErrorWithFormat ("Couldn't get Clang type for format %s (%s integer, width %d).\n",
+                                             arg_type_cstr,
+                                             (encoding == eEncodingSint ? "signed" : "unsigned"),
+                                             width);
+                
+                result.SetStatus (eReturnStatusFailed);
+                return false;
+            }
+        }
+        else if (strchr (arg_type_cstr, '*'))
+        {
+            if (!strcmp (arg_type_cstr, "void*"))
+                type = ast_context.CreatePointerType (ast_context.GetVoidBuiltInType ());
+            else if (!strcmp (arg_type_cstr, "char*"))
+                type = ast_context.GetCStringType (false);
+            else
+            {
+                result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
+                result.SetStatus (eReturnStatusFailed);
+                return false;
+            }
+        }
+        else 
+        {
+            result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+                     
+        value.SetContext (Value::eContextTypeOpaqueClangQualType, type);
+        
+        value_list.PushValue(value);
+    }
+    
+    if (!abi->GetArgumentValues (*thread, value_list))
+    {
+        result.AppendError ("Couldn't get argument values");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+    
+    result.GetOutputStream ().Printf("Arguments : \n");
+
+    for (arg_index = 0; arg_index < num_args; ++arg_index)
+    {
+        result.GetOutputStream ().Printf ("%d (%s): ", arg_index, command.GetArgumentAtIndex (arg_index));
+        value_list.GetValueAtIndex (arg_index)->Dump (&result.GetOutputStream ());
+        result.GetOutputStream ().Printf("\n");
+    }
+    
+    return result.Succeeded();
+}
+
+lldb::OptionDefinition
+CommandObjectArgs::CommandOptions::g_option_table[] =
+{
+    { 0, false, "debug",      'g', no_argument,       NULL, 0, NULL,                           "Enable verbose debug logging of the expression parsing and evaluation."},
+    { 0, false, NULL, 0, 0, NULL, NULL, NULL, NULL }
+};
+
diff --git a/source/Commands/CommandObjectArgs.h b/source/Commands/CommandObjectArgs.h
new file mode 100644
index 0000000..d326d42
--- /dev/null
+++ b/source/Commands/CommandObjectArgs.h
@@ -0,0 +1,76 @@
+//===-- CommandObjectArgs.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_CommandObjectArgs_h_
+#define liblldb_CommandObjectArgs_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Core/Language.h"
+
+namespace lldb_private {
+    
+    class CommandObjectArgs : public CommandObject
+    {
+    public:
+        
+        class CommandOptions : public Options
+        {
+        public:
+            
+            CommandOptions ();
+            
+            virtual
+            ~CommandOptions ();
+            
+            virtual Error
+            SetOptionValue (int option_idx, const char *option_arg);
+            
+            void
+            ResetOptionValues ();
+            
+            const lldb::OptionDefinition*
+            GetDefinitions ();
+            
+            // Options table: Required for subclasses of Options.
+            
+            static lldb::OptionDefinition g_option_table[];
+        };
+        
+        CommandObjectArgs ();
+        
+        virtual
+        ~CommandObjectArgs ();
+        
+        virtual
+        Options *
+        GetOptions ();
+        
+        
+        virtual bool
+        Execute (Args& command,
+                 CommandContext *context,
+                 CommandInterpreter *interpreter,
+                 CommandReturnObject &result);
+        
+        virtual bool
+        WantsRawCommandString() { return false; }
+        
+    protected:
+        
+        CommandOptions m_options;
+    };
+    
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectArgs_h_
diff --git a/source/Commands/CommandObjectBreakpoint.cpp b/source/Commands/CommandObjectBreakpoint.cpp
new file mode 100644
index 0000000..d24ba8f
--- /dev/null
+++ b/source/Commands/CommandObjectBreakpoint.cpp
@@ -0,0 +1,953 @@
+//===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectBreakpoint.h"
+#include "CommandObjectBreakpointCommand.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Breakpoint/BreakpointIDList.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Interpreter/CommandCompletions.h"
+#include "lldb/Target/StackFrame.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static void
+AddBreakpointDescription (CommandContext *context, StreamString *s, Breakpoint *bp, lldb::DescriptionLevel level)
+{
+    s->IndentMore();
+    bp->GetDescription (s, level, true);
+    s->IndentLess();
+    s->EOL();
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointSet::CommandOptions
+//-------------------------------------------------------------------------
+
+CommandObjectBreakpointSet::CommandOptions::CommandOptions() :
+    Options (),
+    m_filename (),
+    m_line_num (0),
+    m_column (0),
+    m_ignore_inlines (false),
+    m_func_name (),
+    m_func_regexp (),
+    m_modules (),
+    m_load_addr()
+{
+    BuildValidOptionSets();
+}
+
+CommandObjectBreakpointSet::CommandOptions::~CommandOptions ()
+{
+}
+
+lldb::OptionDefinition
+CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
+{
+    { 0, false, "file",       'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, "<filename>",
+        "Set the breakpoint by source location in this particular file."},
+
+    { 0, true, "line",       'l', required_argument, NULL, 0, "<linenum>",
+        "Set the breakpoint by source location at this particular line."},
+
+    { 0, false, "shlib",       's', required_argument, NULL, CommandCompletions::eModuleCompletion, "<shlib-name>",
+        "Set the breakpoint only in this shared library (can use this option multiple times for multiple shlibs)."},
+
+    // Comment out this option for the moment, as we don't actually use it, but will in the future.
+    // This way users won't see it, but the infrastructure is left in place.
+    //    { 0, false, "column",     'c', required_argument, NULL, "<column>",
+    //    "Set the breakpoint by source location at this particular column."},
+
+    { 0, false, "ignore_inlines", 'i', no_argument,   NULL, 0, NULL,
+        "Ignore inlined subroutines when setting the breakppoint." },
+
+    { 1, true, "address",    'a', required_argument, NULL, 0, "<address>",
+        "Set the breakpoint by address, at the specified address."},
+
+    { 1, false, "ignore_inlines", 'i', no_argument,   NULL, 0, NULL,
+        "Ignore inlined subroutines when setting the breakppoint." },
+
+    { 2, true, "name",       'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, "<function-name>",
+        "Set the breakpoint by function name." },
+
+    { 2, false, "shlib",       's', required_argument, NULL, CommandCompletions::eModuleCompletion, "<shlib-name>",
+        "Set the breakpoint only in this shared library (can use this option multiple times for multiple shlibs)."},
+
+    { 2, false, "ignore_inlines", 'i', no_argument,   NULL, 0, NULL,
+        "Ignore inlined subroutines when setting the breakpoint." },
+
+    { 3, true, "func_regex", 'r', required_argument, NULL, 0, "<regular-expression>",
+        "Set the breakpoint by function name, evaluating a regular-expression to find the function name(s)." },
+
+    { 3, false, "shlib",       's', required_argument, NULL, CommandCompletions::eModuleCompletion, "<shlib-name>",
+        "Set the breakpoint only in this shared library (can use this option multiple times for multiple shlibs)."},
+
+    { 3, false, "ignore_inlines", 'i', no_argument,   NULL, 0, NULL,
+        "Ignore inlined subroutines when setting the breakpoint." },
+
+    { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+const lldb::OptionDefinition*
+CommandObjectBreakpointSet::CommandOptions::GetDefinitions ()
+{
+    return g_option_table;
+}
+
+Error
+CommandObjectBreakpointSet::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
+{
+    Error error;
+    char short_option = (char) m_getopt_table[option_idx].val;
+
+    switch (short_option)
+    {
+        case 'a':
+            m_load_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 0);
+            if (m_load_addr == LLDB_INVALID_ADDRESS)
+                m_load_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 16);
+
+            if (m_load_addr == LLDB_INVALID_ADDRESS)
+                error.SetErrorStringWithFormat ("Invalid address string '%s'.\n", optarg);
+            break;
+
+        case 'c':
+            m_column = Args::StringToUInt32 (option_arg, 0);
+            break;
+        case 'f':
+            m_filename = option_arg;
+            break;
+        case 'i':
+            m_ignore_inlines = true;
+            break;
+        case 'l':
+            m_line_num = Args::StringToUInt32 (option_arg, 0);
+            break;
+        case 'n':
+            m_func_name = option_arg;
+            break;
+        case 'r':
+            m_func_regexp = option_arg;
+            break;
+        case 's':
+            {
+                m_modules.push_back (std::string (option_arg));
+                break;
+            }
+        default:
+            error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
+            break;
+    }
+
+    return error;
+}
+
+void
+CommandObjectBreakpointSet::CommandOptions::ResetOptionValues ()
+{
+    Options::ResetOptionValues();
+
+    m_filename.clear();
+    m_line_num = 0;
+    m_column = 0;
+    m_ignore_inlines = false;
+    m_func_name.clear();
+    m_func_regexp.clear();
+    m_load_addr = LLDB_INVALID_ADDRESS;
+    m_modules.clear();
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointSet
+//-------------------------------------------------------------------------
+
+CommandObjectBreakpointSet::CommandObjectBreakpointSet () :
+    CommandObject ("breakpoint set", "Sets a breakpoint or set of breakpoints in the executable.", 
+                   "breakpoint set <cmd-options>")
+{
+}
+
+CommandObjectBreakpointSet::~CommandObjectBreakpointSet ()
+{
+}
+
+Options *
+CommandObjectBreakpointSet::GetOptions ()
+{
+    return &m_options;
+}
+
+bool
+CommandObjectBreakpointSet::Execute
+(
+    Args& command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    Target *target = context->GetTarget();
+    if (target == NULL)
+    {
+        result.AppendError ("Invalid target, set executable file using 'file' command.");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    // The following are the various types of breakpoints that could be set:
+    //   1).  -f -l -p  [-s -g]   (setting breakpoint by source location)
+    //   2).  -a  [-s -g]         (setting breakpoint by address)
+    //   3).  -n  [-s -g]         (setting breakpoint by function name)
+    //   4).  -r  [-s -g]         (setting breakpoint by function name regular expression)
+
+    BreakpointSetType break_type = eSetTypeInvalid;
+
+    if (m_options.m_line_num != 0)
+        break_type = eSetTypeFileAndLine;
+    else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
+        break_type = eSetTypeAddress;
+    else if (!m_options.m_func_name.empty())
+        break_type = eSetTypeFunctionName;
+    else if  (!m_options.m_func_regexp.empty())
+        break_type = eSetTypeFunctionRegexp;
+
+    ModuleSP module_sp = target->GetExecutableModule();
+    Breakpoint *bp = NULL;
+    FileSpec module;
+    bool use_module = false;
+    int num_modules = m_options.m_modules.size();
+
+    if ((num_modules > 0) && (break_type != eSetTypeAddress))
+        use_module = true;
+
+    switch (break_type)
+    {
+        case eSetTypeFileAndLine: // Breakpoint by source position
+        {
+            FileSpec file;
+            if (m_options.m_filename.empty())
+            {
+                StackFrame *cur_frame = context->GetExecutionContext().frame;
+                if (cur_frame == NULL)
+                {
+                    result.AppendError ("Attempting to set breakpoint by line number alone with no selected frame.");
+                    result.SetStatus (eReturnStatusFailed);
+                    break;
+                }
+                else if (!cur_frame->HasDebugInformation())
+                {
+                    result.AppendError ("Attempting to set breakpoint by line number alone but selected frame has no debug info.");
+                    result.SetStatus (eReturnStatusFailed);
+                    break;
+                }
+                else
+                {
+                    const SymbolContext &context = cur_frame->GetSymbolContext(true);
+                    if (context.line_entry.file)
+                    {
+                        file = context.line_entry.file;
+                    }
+                    else if (context.comp_unit != NULL)
+                    {    file = context.comp_unit;
+                    }
+                    else
+                    {
+                        result.AppendError ("Attempting to set breakpoint by line number alone but can't find the file for the selected frame.");
+                        result.SetStatus (eReturnStatusFailed);
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                file.SetFile(m_options.m_filename.c_str());
+            }
+
+            if (use_module)
+            {
+                for (int i = 0; i < num_modules; ++i)
+                {
+                    module.SetFile(m_options.m_modules[i].c_str());
+                    bp = target->CreateBreakpoint (&module,
+                                                   file,
+                                                   m_options.m_line_num,
+                                                   m_options.m_ignore_inlines).get();
+                    if (bp)
+                    {
+                        StreamString &output_stream = result.GetOutputStream();
+                        output_stream.Printf ("Breakpoint created: ");
+                        bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief);
+                        output_stream.EOL();
+                        result.SetStatus (eReturnStatusSuccessFinishResult);
+                    }
+                    else
+                    {
+                        result.AppendErrorWithFormat("Breakpoint creation failed: No breakpoint created in module '%s'.\n",
+                                                    m_options.m_modules[i].c_str());
+                        result.SetStatus (eReturnStatusFailed);
+                    }
+                }
+            }
+            else
+                bp = target->CreateBreakpoint (NULL,
+                                               file,
+                                               m_options.m_line_num,
+                                               m_options.m_ignore_inlines).get();
+        }
+        break;
+        case eSetTypeAddress: // Breakpoint by address
+            bp = target->CreateBreakpoint (m_options.m_load_addr, false).get();
+            break;
+        case eSetTypeFunctionName: // Breakpoint by function name
+            if (use_module)
+            {
+                for (int i = 0; i < num_modules; ++i)
+                {
+                    module.SetFile(m_options.m_modules[i].c_str());
+                    bp = target->CreateBreakpoint (&module, m_options.m_func_name.c_str()).get();
+                    if (bp)
+                    {
+                        StreamString &output_stream = result.GetOutputStream();
+                        output_stream.Printf ("Breakpoint created: ");
+                        bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief);
+                        output_stream.EOL();
+                        result.SetStatus (eReturnStatusSuccessFinishResult);
+                    }
+                    else
+                    {
+                        result.AppendErrorWithFormat("Breakpoint creation failed: No breakpoint created in module '%s'.\n",
+                                                    m_options.m_modules[i].c_str());
+                        result.SetStatus (eReturnStatusFailed);
+                    }
+                }
+            }
+            else
+                bp = target->CreateBreakpoint (NULL, m_options.m_func_name.c_str()).get();
+            break;
+        case eSetTypeFunctionRegexp: // Breakpoint by regular expression function name
+            {
+                RegularExpression regexp(m_options.m_func_regexp.c_str());
+                if (use_module)
+                {
+                    for (int i = 0; i < num_modules; ++i)
+                    {
+                        module.SetFile(m_options.m_modules[i].c_str());
+                        bp = target->CreateBreakpoint (&module, regexp).get();
+                        if (bp)
+                        {
+                            StreamString &output_stream = result.GetOutputStream();
+                            output_stream.Printf ("Breakpoint created: ");
+                            bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief);
+                            output_stream.EOL();
+                            result.SetStatus (eReturnStatusSuccessFinishResult);
+                        }
+                        else
+                        {
+                            result.AppendErrorWithFormat("Breakpoint creation failed: No breakpoint created in module '%s'.\n",
+                                                        m_options.m_modules[i].c_str());
+                            result.SetStatus (eReturnStatusFailed);
+                        }
+                    }
+                }
+                else
+                    bp = target->CreateBreakpoint (NULL, regexp).get();
+            }
+            break;
+        default:
+            break;
+    }
+
+    if (bp && !use_module)
+    {
+        StreamString &output_stream = result.GetOutputStream();
+        output_stream.Printf ("Breakpoint created: ");
+        bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief);
+        output_stream.EOL();
+        result.SetStatus (eReturnStatusSuccessFinishResult);
+    }
+    else if (!bp)
+    {
+        result.AppendError ("Breakpoint creation failed: No breakpoint created.");
+        result.SetStatus (eReturnStatusFailed);
+    }
+
+    return result.Succeeded();
+}
+
+
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordBreakpoint
+//-------------------------------------------------------------------------
+
+CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint (CommandInterpreter *interpreter) :
+    CommandObjectMultiword ("breakpoint",
+                              "A set of commands for operating on breakpoints.",
+                              "breakpoint <command> [<command-options>]")
+{
+    bool status;
+
+    CommandObjectSP list_command_object (new CommandObjectBreakpointList ());
+    CommandObjectSP delete_command_object (new CommandObjectBreakpointDelete ());
+    CommandObjectSP enable_command_object (new CommandObjectBreakpointEnable ());
+    CommandObjectSP disable_command_object (new CommandObjectBreakpointDisable ());
+    CommandObjectSP set_command_object (new CommandObjectBreakpointSet ());
+    CommandObjectSP command_command_object (new CommandObjectBreakpointCommand (interpreter));
+
+    enable_command_object->SetCommandName("breakpoint enable");
+    disable_command_object->SetCommandName("breakpoint disable");
+    set_command_object->SetCommandName("breakpoint set");
+    command_command_object->SetCommandName ("breakpoint command");
+    list_command_object->SetCommandName ("breakpoint list");
+
+    status = LoadSubCommand (list_command_object, "list", interpreter);
+    status = LoadSubCommand (enable_command_object, "enable", interpreter);
+    status = LoadSubCommand (disable_command_object, "disable", interpreter);
+    status = LoadSubCommand (delete_command_object, "delete", interpreter);
+    status = LoadSubCommand (set_command_object, "set", interpreter);
+    status = LoadSubCommand (command_command_object, "command", interpreter);
+}
+
+CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint ()
+{
+}
+
+void
+CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (Args &args, Target *target, CommandReturnObject &result,
+                                                         BreakpointIDList *valid_ids)
+{
+    // args can be strings representing 1). integers (for breakpoint ids)
+    //                                  2). the full breakpoint & location canonical representation
+    //                                  3). the word "to" or a hyphen, representing a range (in which case there
+    //                                      had *better* be an entry both before & after of one of the first two types.
+
+    Args temp_args;
+
+    // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff directly from the old ARGS to
+    // the new TEMP_ARGS.  Do not copy breakpoint id range strings over; instead generate a list of strings for
+    // all the breakpoint ids in the range, and shove all of those breakpoint id strings into TEMP_ARGS.
+
+    BreakpointIDList::FindAndReplaceIDRanges (args, target, result, temp_args);
+
+    // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual BreakpointIDList:
+
+    valid_ids->InsertStringArray ((const char **) temp_args.GetArgumentVector(), temp_args.GetArgumentCount(), result);
+
+    // At this point,  all of the breakpoint ids that the user passed in have been converted to breakpoint IDs
+    // and put into valid_ids.
+
+    if (result.Succeeded())
+    {
+        // Now that we've converted everything from args into a list of breakpoint ids, go through our tentative list
+        // of breakpoint id's and verify that they correspond to valid/currently set breakpoints.
+
+        for (int i = 0; i < valid_ids->Size(); ++i)
+        {
+            BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex (i);
+            Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
+            if (breakpoint != NULL)
+            {
+                int num_locations = breakpoint->GetNumLocations();
+                if (cur_bp_id.GetLocationID() > num_locations)
+                {
+                    StreamString id_str;
+                    BreakpointID::GetCanonicalReference (&id_str, cur_bp_id.GetBreakpointID(),
+                                                           cur_bp_id.GetLocationID());
+                    i = valid_ids->Size() + 1;
+                    result.AppendErrorWithFormat ("'%s' is not a currently valid breakpoint/location id.\n",
+                                                 id_str.GetData());
+                    result.SetStatus (eReturnStatusFailed);
+                }
+            }
+            else
+            {
+                i = valid_ids->Size() + 1;
+                result.AppendErrorWithFormat ("'%d' is not a currently valid breakpoint id.\n", cur_bp_id.GetBreakpointID());
+                result.SetStatus (eReturnStatusFailed);
+            }
+        }
+    }
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointList::Options
+//-------------------------------------------------------------------------
+
+CommandObjectBreakpointList::CommandOptions::CommandOptions() :
+    Options (),
+    m_level (lldb::eDescriptionLevelFull)  // Breakpoint List defaults to brief descriptions
+{
+    BuildValidOptionSets();
+}
+
+CommandObjectBreakpointList::CommandOptions::~CommandOptions ()
+{
+}
+
+lldb::OptionDefinition
+CommandObjectBreakpointList::CommandOptions::g_option_table[] =
+{
+    { 0, false, "brief",    'b', no_argument, NULL, 0, NULL,
+        "Give a brief description of the breakpoint (no location info)."},
+
+    // FIXME: We need to add an "internal" command, and then add this sort of thing to it.
+    // But I need to see it for now, and don't want to wait.
+    { 0, false, "internal", 'i', no_argument, NULL, 0, NULL,
+        "Show debugger internal breakpoints" },
+
+    { 1, false, "full",    'f', no_argument, NULL, 0, NULL,
+        "Give a full description of the breakpoint and its locations."},
+    // DITTO FIXME
+    { 1, false, "internal", 'i', no_argument, NULL, 0, NULL,
+        "Show debugger internal breakpoints" },
+
+    { 2, false, "verbose", 'v', no_argument, NULL, 0, NULL,
+        "Explain everything we know about the breakpoint (for debugging debugger bugs)." },
+    // DITTO FIXME
+    { 2, false, "internal", 'i', no_argument, NULL, 0, NULL,
+        "Show debugger internal breakpoints" },
+
+    { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+const lldb::OptionDefinition*
+CommandObjectBreakpointList::CommandOptions::GetDefinitions ()
+{
+    return g_option_table;
+}
+
+Error
+CommandObjectBreakpointList::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
+{
+    Error error;
+    char short_option = (char) m_getopt_table[option_idx].val;
+
+    switch (short_option)
+    {
+        case 'b':
+            m_level = lldb::eDescriptionLevelBrief;
+            break;
+        case 'f':
+            m_level = lldb::eDescriptionLevelFull;
+            break;
+        case 'v':
+            m_level = lldb::eDescriptionLevelVerbose;
+            break;
+        case 'i':
+            m_internal = true;
+            break;
+        default:
+            error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
+            break;
+    }
+
+    return error;
+}
+
+void
+CommandObjectBreakpointList::CommandOptions::ResetOptionValues ()
+{
+    Options::ResetOptionValues();
+
+    m_level = lldb::eDescriptionLevelFull;
+    m_internal = false;
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointList
+//-------------------------------------------------------------------------
+
+CommandObjectBreakpointList::CommandObjectBreakpointList () :
+    CommandObject ("breakpoint list",
+                     "List some or all breakpoints at configurable levels of detail.",
+                     "breakpoint list [<breakpoint-id>]")
+{
+}
+
+CommandObjectBreakpointList::~CommandObjectBreakpointList ()
+{
+}
+
+Options *
+CommandObjectBreakpointList::GetOptions ()
+{
+    return &m_options;
+}
+
+bool
+CommandObjectBreakpointList::Execute
+(
+    Args& args,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    Target *target = context->GetTarget();
+    if (target == NULL)
+    {
+        result.AppendError ("Invalid target, set executable file using 'file' command.");
+        result.SetStatus (eReturnStatusSuccessFinishNoResult);
+        return true;
+    }
+
+    const BreakpointList &breakpoints = target->GetBreakpointList(m_options.m_internal);
+    size_t num_breakpoints = breakpoints.GetSize();
+
+    if (num_breakpoints == 0)
+    {
+        result.AppendMessage ("No breakpoints currently set.");
+        result.SetStatus (eReturnStatusSuccessFinishNoResult);
+        return true;
+    }
+
+    StreamString &output_stream = result.GetOutputStream();
+
+    if (args.GetArgumentCount() == 0)
+    {
+        // No breakpoint selected; show info about all currently set breakpoints.
+        result.AppendMessage ("Current breakpoints:");
+        for (int i = 0; i < num_breakpoints; ++i)
+        {
+            Breakpoint *breakpoint = breakpoints.GetBreakpointByIndex (i).get();
+            AddBreakpointDescription (context, &output_stream, breakpoint, m_options.m_level);
+        }
+        result.SetStatus (eReturnStatusSuccessFinishNoResult);
+    }
+    else
+    {
+        // Particular breakpoints selected; show info about that breakpoint.
+        BreakpointIDList valid_bp_ids;
+        CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (args, target, result, &valid_bp_ids);
+
+        if (result.Succeeded())
+        {
+            for (int i = 0; i < valid_bp_ids.Size(); ++i)
+            {
+                BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
+                Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
+                AddBreakpointDescription (context, &output_stream, breakpoint, m_options.m_level);
+            }
+            result.SetStatus (eReturnStatusSuccessFinishNoResult);
+        }
+        else
+        {
+            result.AppendError ("Invalid breakpoint id.");
+            result.SetStatus (eReturnStatusFailed);
+        }
+    }
+
+    return result.Succeeded();
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointEnable
+//-------------------------------------------------------------------------
+
+CommandObjectBreakpointEnable::CommandObjectBreakpointEnable () :
+    CommandObject ("enable",
+                     "Enables the specified disabled breakpoint(s).  If no breakpoints are specified, enables all of them.",
+                     "breakpoint enable [<breakpoint-id> | <breakpoint-id-list>]")
+{
+    // This command object can either be called via 'enable' or 'breakpoint enable'.  Because it has two different
+    // potential invocation methods, we need to be a little tricky about generating the syntax string.
+    //StreamString tmp_string;
+    //tmp_string.Printf ("%s <breakpoint-id>", GetCommandName());
+    //m_cmd_syntax.assign (tmp_string.GetData(), tmp_string.GetSize());
+}
+
+
+CommandObjectBreakpointEnable::~CommandObjectBreakpointEnable ()
+{
+}
+
+
+bool
+CommandObjectBreakpointEnable::Execute (Args& args, CommandContext *context,
+                                          CommandInterpreter *interpreter, CommandReturnObject &result)
+{
+    Target *target = context->GetTarget();
+    if (target == NULL)
+    {
+        result.AppendError ("Invalid target, set executable file using 'file' command.");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    const BreakpointList &breakpoints = target->GetBreakpointList();
+    size_t num_breakpoints = breakpoints.GetSize();
+
+    if (num_breakpoints == 0)
+    {
+        result.AppendError ("No breakpoints exist to be enabled.");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    if (args.GetArgumentCount() == 0)
+    {
+        // No breakpoint selected; enable all currently set breakpoints.
+        target->EnableAllBreakpoints ();
+        result.AppendMessageWithFormat ("All breakpoints enabled. (%d breakpoints)\n", num_breakpoints);
+        result.SetStatus (eReturnStatusSuccessFinishNoResult);
+    }
+    else
+    {
+        // Particular breakpoint selected; enable that breakpoint.
+        BreakpointIDList valid_bp_ids;
+        CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (args, target, result, &valid_bp_ids);
+
+        if (result.Succeeded())
+        {
+            int enable_count = 0;
+            int loc_count = 0;
+            for (int i = 0; i < valid_bp_ids.Size(); ++i)
+            {
+                BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
+
+                if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
+                {
+                    Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
+                    if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
+                    {
+                        BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get();
+                        if (location)
+                        {
+                            location->SetEnabled (true);
+                            breakpoint->SetEnabled (true);
+                            ++loc_count;
+                        }
+                    }
+                    else
+                    {
+                        target->EnableBreakpointByID (cur_bp_id.GetBreakpointID());
+                        ++enable_count;
+
+                        int num_locations = breakpoint->GetNumLocations ();
+                        for (int j = 0; j < num_locations; ++j)
+                        {
+                            BreakpointLocation *cur_loc = breakpoint->GetLocationAtIndex(j).get();
+                            if (cur_loc)
+                                cur_loc->SetEnabled (true);
+                        }
+                    }
+                }
+            }
+            result.AppendMessageWithFormat ("%d breakpoints enabled.\n", enable_count + loc_count);
+            result.SetStatus (eReturnStatusSuccessFinishNoResult);
+        }
+    }
+
+    return result.Succeeded();
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointDisable
+//-------------------------------------------------------------------------
+
+CommandObjectBreakpointDisable::CommandObjectBreakpointDisable () :
+    CommandObject ("disable",
+                   "Disables the specified breakpoint(s) without removing it/them.  If no breakpoints are specified, disables them all.",
+                   "disable [<breakpoint-id> | <breakpoint-id-list>]")
+{
+    // This command object can either be called via 'enable' or 'breakpoint enable'.  Because it has two different
+    // potential invocation methods, we need to be a little tricky about generating the syntax string.
+    //StreamString tmp_string;
+    //tmp_string.Printf ("%s <breakpoint-id>", GetCommandName());
+    //m_cmd_syntax.assign(tmp_string.GetData(), tmp_string.GetSize());
+}
+
+CommandObjectBreakpointDisable::~CommandObjectBreakpointDisable ()
+{
+}
+
+bool
+CommandObjectBreakpointDisable::Execute (Args& args, CommandContext *context,
+                                           CommandInterpreter *interpreter, CommandReturnObject &result)
+{
+    Target *target = context->GetTarget();
+    if (target == NULL)
+    {
+        result.AppendError ("Invalid target, set executable file using 'file' command.");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    const BreakpointList &breakpoints = target->GetBreakpointList();
+    size_t num_breakpoints = breakpoints.GetSize();
+
+    if (num_breakpoints == 0)
+    {
+        result.AppendError ("No breakpoints exist to be disabled.");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    if (args.GetArgumentCount() == 0)
+    {
+        // No breakpoint selected; disable all currently set breakpoints.
+        target->DisableAllBreakpoints ();
+        result.AppendMessageWithFormat ("All breakpoints disabled. (%d breakpoints)\n", num_breakpoints);
+        result.SetStatus (eReturnStatusSuccessFinishNoResult);
+    }
+    else
+    {
+        // Particular breakpoint selected; disable that breakpoint.
+        BreakpointIDList valid_bp_ids;
+
+        CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (args, target, result, &valid_bp_ids);
+
+        if (result.Succeeded())
+        {
+            int disable_count = 0;
+            int loc_count = 0;
+            for (int i = 0; i < valid_bp_ids.Size(); ++i)
+            {
+                BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
+
+                if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
+                {
+                    Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
+                    if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
+                    {
+                        BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get();
+                        if (location)
+                        {
+                            location->SetEnabled (false);
+                            ++loc_count;
+                        }
+                    }
+                    else
+                    {
+                        target->DisableBreakpointByID (cur_bp_id.GetBreakpointID());
+                        ++disable_count;
+
+                        int num_locations = breakpoint->GetNumLocations();
+                        for (int j = 0; j < num_locations; ++j)
+                        {
+                            BreakpointLocation *cur_loc = breakpoint->GetLocationAtIndex(j).get();
+                            if (cur_loc)
+                                cur_loc->SetEnabled (false);
+                        }
+                    }
+                }
+            }
+            result.AppendMessageWithFormat ("%d breakpoints disabled.\n", disable_count + loc_count);
+            result.SetStatus (eReturnStatusSuccessFinishNoResult);
+        }
+    }
+
+    return result.Succeeded();
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointDelete
+//-------------------------------------------------------------------------
+
+CommandObjectBreakpointDelete::CommandObjectBreakpointDelete() :
+    CommandObject ("breakpoint delete",
+                   "Delete the specified breakpoint(s).  If no breakpoints are specified, deletes them all.",
+                   "breakpoint delete [<breakpoint-id> | <breakpoint-id-list>]")
+{
+}
+
+
+CommandObjectBreakpointDelete::~CommandObjectBreakpointDelete ()
+{
+}
+
+bool
+CommandObjectBreakpointDelete::Execute (Args& args, CommandContext *context,
+                                          CommandInterpreter *interpreter, CommandReturnObject &result)
+{
+    Target *target = context->GetTarget();
+    if (target == NULL)
+    {
+        result.AppendError ("Invalid target, set executable file using 'file' command.");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    const BreakpointList &breakpoints = target->GetBreakpointList();
+    size_t num_breakpoints = breakpoints.GetSize();
+
+    if (num_breakpoints == 0)
+    {
+        result.AppendError ("No breakpoints exist to be deleted.");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    if (args.GetArgumentCount() == 0)
+    {
+        // No breakpoint selected; disable all currently set breakpoints.
+        if (args.GetArgumentCount() != 0)
+        {
+            result.AppendErrorWithFormat ("Specify breakpoints to delete with the -i option.\n");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        target->RemoveAllBreakpoints ();
+        result.AppendMessageWithFormat ("All breakpoints removed. (%d breakpoints)\n", num_breakpoints);
+        result.SetStatus (eReturnStatusSuccessFinishNoResult);
+    }
+    else
+    {
+        // Particular breakpoint selected; disable that breakpoint.
+        BreakpointIDList valid_bp_ids;
+        CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (args, target, result, &valid_bp_ids);
+
+        if (result.Succeeded())
+        {
+            int delete_count = 0;
+            int disable_count = 0;
+            for (int i = 0; i < valid_bp_ids.Size(); ++i)
+            {
+                BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
+
+                if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
+                {
+                    if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
+                    {
+                        Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
+                        BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get();
+                        // It makes no sense to try to delete individual locations, so we disable them instead.
+                        if (location)
+                        {
+                            location->SetEnabled (false);
+                            ++disable_count;
+                        }
+                    }
+                    else
+                    {
+                        target->RemoveBreakpointByID (cur_bp_id.GetBreakpointID());
+                        ++delete_count;
+                    }
+                }
+            }
+            result.AppendMessageWithFormat ("%d breakpoints deleted; %d breakpoint locations disabled.\n",
+                                           delete_count, disable_count);
+            result.SetStatus (eReturnStatusSuccessFinishNoResult);
+        }
+    }
+    return result.Succeeded();
+}
diff --git a/source/Commands/CommandObjectBreakpoint.h b/source/Commands/CommandObjectBreakpoint.h
new file mode 100644
index 0000000..4900743
--- /dev/null
+++ b/source/Commands/CommandObjectBreakpoint.h
@@ -0,0 +1,235 @@
+//===-- CommandObjectBreakpoint.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_CommandObjectBreakpoint_h_
+#define liblldb_CommandObjectBreakpoint_h_
+
+// C Includes
+// C++ Includes
+
+#include <utility>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Address.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Core/STLUtils.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordBreakpoint
+//-------------------------------------------------------------------------
+
+class CommandObjectMultiwordBreakpoint : public CommandObjectMultiword
+{
+public:
+    CommandObjectMultiwordBreakpoint (CommandInterpreter *interpreter);
+
+    virtual
+    ~CommandObjectMultiwordBreakpoint ();
+
+    static void
+    VerifyBreakpointIDs (Args &args, Target *target, CommandReturnObject &result, BreakpointIDList *valid_ids);
+
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordBreakpointSet
+//-------------------------------------------------------------------------
+
+
+class CommandObjectBreakpointSet : public CommandObject
+{
+public:
+
+    typedef enum BreakpointSetType
+    {
+        eSetTypeInvalid,
+        eSetTypeFileAndLine,
+        eSetTypeAddress,
+        eSetTypeFunctionName,
+        eSetTypeFunctionRegexp,
+    } BreakpointSetType;
+
+    CommandObjectBreakpointSet ();
+
+    virtual
+    ~CommandObjectBreakpointSet ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+    virtual Options *
+    GetOptions ();
+
+    class CommandOptions : public Options
+    {
+    public:
+
+        CommandOptions ();
+
+        virtual
+        ~CommandOptions ();
+
+        virtual Error
+        SetOptionValue (int option_idx, const char *option_arg);
+
+        void
+        ResetOptionValues ();
+
+        const lldb::OptionDefinition*
+        GetDefinitions ();
+
+        // Options table: Required for subclasses of Options.
+
+        static lldb::OptionDefinition g_option_table[];
+
+        // Instance variables to hold the values for command options.
+
+        std::string m_filename;
+        unsigned int m_line_num;
+        unsigned int m_column;
+        bool m_ignore_inlines;
+        std::string m_func_name;
+        std::string m_func_regexp;
+        lldb::addr_t m_load_addr;
+        STLStringArray m_modules;
+
+    };
+
+private:
+    CommandOptions m_options;
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointEnable
+//-------------------------------------------------------------------------
+
+class CommandObjectBreakpointEnable : public CommandObject
+{
+public:
+    CommandObjectBreakpointEnable ();
+
+    virtual
+    ~CommandObjectBreakpointEnable ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+private:
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointDisable
+//-------------------------------------------------------------------------
+
+class CommandObjectBreakpointDisable : public CommandObject
+{
+public:
+    CommandObjectBreakpointDisable ();
+
+    virtual
+    ~CommandObjectBreakpointDisable ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+private:
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointList
+//-------------------------------------------------------------------------
+
+class CommandObjectBreakpointList : public CommandObject
+{
+public:
+    CommandObjectBreakpointList ();
+
+    virtual
+    ~CommandObjectBreakpointList ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+    virtual Options *
+    GetOptions ();
+
+    class CommandOptions : public Options
+    {
+    public:
+
+        CommandOptions ();
+
+        virtual
+        ~CommandOptions ();
+
+        virtual Error
+        SetOptionValue (int option_idx, const char *option_arg);
+
+        void
+        ResetOptionValues ();
+
+        const lldb::OptionDefinition *
+        GetDefinitions ();
+
+        // Options table: Required for subclasses of Options.
+
+        static lldb::OptionDefinition g_option_table[];
+
+        // Instance variables to hold the values for command options.
+
+        lldb::DescriptionLevel m_level;
+
+        bool m_internal;
+    };
+
+private:
+    CommandOptions m_options;
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointDelete
+//-------------------------------------------------------------------------
+
+class CommandObjectBreakpointDelete : public CommandObject
+{
+public:
+    CommandObjectBreakpointDelete ();
+
+    virtual
+    ~CommandObjectBreakpointDelete ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+private:
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectBreakpoint_h_
diff --git a/source/Commands/CommandObjectBreakpointCommand.cpp b/source/Commands/CommandObjectBreakpointCommand.cpp
new file mode 100644
index 0000000..8a5a443
--- /dev/null
+++ b/source/Commands/CommandObjectBreakpointCommand.cpp
@@ -0,0 +1,695 @@
+//===-- CommandObjectBreakpointCommand.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
+// C++ Includes
+
+
+#include "CommandObjectBreakpointCommand.h"
+#include "CommandObjectBreakpoint.h"
+
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Breakpoint/BreakpointIDList.h"
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Core/State.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointCommandAdd::CommandOptions
+//-------------------------------------------------------------------------
+
+CommandObjectBreakpointCommandAdd::CommandOptions::CommandOptions () :
+    Options ()
+{
+    BuildValidOptionSets();
+}
+
+CommandObjectBreakpointCommandAdd::CommandOptions::~CommandOptions ()
+{
+}
+
+lldb::OptionDefinition
+CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
+{
+    { 0, true, "script",    's', no_argument, NULL, 0, NULL,
+        "Write the breakpoint command script in the default scripting language."},
+
+    { 1, true, "python",    'p', no_argument, NULL, 0, NULL,
+        "Write the breakpoint command script in the Python scripting language."},
+
+    { 2, true, "commands",  'c', no_argument, NULL, 0, NULL,
+        "Write the breakpoint command script using the command line commands."},
+
+    { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+const lldb::OptionDefinition*
+CommandObjectBreakpointCommandAdd::CommandOptions::GetDefinitions ()
+{
+    return g_option_table;
+}
+
+
+Error
+CommandObjectBreakpointCommandAdd::CommandOptions::SetOptionValue 
+(
+    int option_idx, 
+    const char *option_arg
+)
+{
+    Error error;
+    char short_option = (char) m_getopt_table[option_idx].val;
+
+    switch (short_option)
+      {
+      case 's':
+        m_use_commands = false;
+        m_use_script_language = true;
+        m_script_language = eScriptLanguageDefault;
+        break;
+      case 'p':
+        m_use_commands = false;
+        m_use_script_language = true;
+        m_script_language = eScriptLanguagePython;
+        break;
+      case 'c':
+        m_use_commands = true;
+        m_use_script_language = false;
+        m_script_language = eScriptLanguageNone;
+        break;
+      default:
+        break;
+      }
+    return error;
+}
+
+void
+CommandObjectBreakpointCommandAdd::CommandOptions::ResetOptionValues ()
+{
+    Options::ResetOptionValues();
+
+    m_use_commands = false;
+    m_use_script_language = false;
+    m_script_language = eScriptLanguageNone;
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointCommandAdd
+//-------------------------------------------------------------------------
+
+
+CommandObjectBreakpointCommandAdd::CommandObjectBreakpointCommandAdd () :
+    CommandObject ("add",
+                   "Adds a set of commands to a breakpoint to be executed whenever a breakpoint is hit.",
+                   "breakpoint command add <cmd-options> <breakpoint-id>")
+{
+    SetHelpLong (
+"\nGeneral information about entering breakpoint commands \n\
+------------------------------------------------------ \n\
+ \n\
+This command will cause you to be prompted to enter the command or set \n\
+of commands you wish to be executed when the specified breakpoint is \n\
+hit.  You will be told to enter your command(s), and will see a '> ' \n\
+prompt. Because you can enter one or many commands to be executed when \n\
+a breakpoint is hit, you will continue to be prompted after each \n\
+new-line that you enter, until you enter the word 'DONE', which will \n\
+cause the commands you have entered to be stored with the breakpoint \n\
+and executed when the breakpoint is hit. \n\
+ \n\
+Syntax checking is not necessarily done when breakpoint commands are \n\
+entered.  An improperly written breakpoint command will attempt to get \n\
+executed when the breakpoint gets hit, and usually silently fail.  If \n\
+your breakpoint command does not appear to be getting executed, go \n\
+back and check your syntax. \n\
+ \n\
+ \n\
+Special information about PYTHON breakpoint commands \n\
+---------------------------------------------------- \n\
+ \n\
+You may enter either one line of Python or multiple lines of Python \n\
+(including defining whole functions, if desired).  If you enter a \n\
+single line of Python, that will be passed to the Python interpreter \n\
+'as is' when the breakpoint gets hit.  If you enter function \n\
+definitions, they will be passed to the Python interpreter as soon as \n\
+you finish entering the breakpoint command, and they can be called \n\
+later (don't forget to add calls to them, if you want them called when \n\
+the breakpoint is hit).  If you enter multiple lines of Python that \n\
+are not function definitions, they will be collected into a new, \n\
+automatically generated Python function, and a call to the newly \n\
+generated function will be attached to the breakpoint.  Important \n\
+Note: Because loose Python code gets collected into functions, if you \n\
+want to access global variables in the 'loose' code, you need to \n\
+specify that they are global, using the 'global' keyword.  Be sure to \n\
+use correct Python syntax, including indentation, when entering Python \n\
+breakpoint commands. \n\
+ \n\
+Example Python one-line breakpoint command: \n\
+ \n\
+(lldb) breakpoint command add -p 1 \n\
+Enter your Python command(s). Type 'DONE' to end. \n\
+> print \"Hit this breakpoint!\" \n\
+> DONE \n\
+ \n\
+Example multiple line Python breakpoint command, using function definition: \n\
+ \n\
+(lldb) breakpoint command add -p 1 \n\
+Enter your Python command(s). Type 'DONE' to end. \n\
+> def breakpoint_output (bp_no): \n\
+>     out_string = \"Hit breakpoint number \" + repr (bp_no) \n\
+>     print out_string \n\
+>     return True \n\
+> breakpoint_output (1) \n\
+> DONE \n\
+ \n\
+ \n\
+Example multiple line Python breakpoint command, using 'loose' Python: \n\
+ \n\
+(lldb) breakpoint command add -p 1 \n\
+Enter your Python command(s). Type 'DONE' to end. \n\
+> global bp_count \n\
+> bp_count = bp_count + 1 \n\
+> print \"Hit this breakpoint \" + repr(bp_count) + \" times!\" \n\
+> DONE \n\
+ \n\
+In this case, since there is a reference to a global variable, \n\
+'bp_count', you will also need to make sure 'bp_count' exists and is \n\
+initialized: \n\
+ \n\
+(lldb) script \n\
+>>> bp_count = 0 \n\
+>>> quit() \n\
+ \n\
+(lldb)  \n\
+ \n\
+Special information  debugger command breakpoint commands \n\
+--------------------------------------------------------- \n\
+ \n\
+You may enter any debugger command, exactly as you would at the \n\
+debugger prompt.  You may enter as many debugger commands as you like, \n\
+but do NOT enter more than one command per line. \n" );
+}
+
+CommandObjectBreakpointCommandAdd::~CommandObjectBreakpointCommandAdd ()
+{
+}
+
+bool
+CommandObjectBreakpointCommandAdd::Execute 
+(
+    Args& command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    Target *target = context->GetTarget();
+
+    if (target == NULL)
+    {
+        result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    const BreakpointList &breakpoints = target->GetBreakpointList();
+    size_t num_breakpoints = breakpoints.GetSize();
+
+    if (num_breakpoints == 0)
+    {
+        result.AppendError ("No breakpoints exist to have commands added");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    if (command.GetArgumentCount() == 0)
+    {
+        result.AppendError ("No breakpoint specified to which to add the commands");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    BreakpointIDList valid_bp_ids;
+    CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
+
+    if (result.Succeeded())
+    {
+        for (int i = 0; i < valid_bp_ids.Size(); ++i)
+        {
+            BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
+            if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
+            {
+                Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
+                if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
+                {
+                    BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
+                    if (bp_loc_sp)
+                    {
+                        if (m_options.m_use_script_language)
+                        {
+                            interpreter->GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp_loc_sp->GetLocationOptions(),
+                                                                                                          result);
+                        }
+                        else
+                        {
+                            CollectDataForBreakpointCommandCallback (bp_loc_sp->GetLocationOptions(), result);
+                        }
+                    }
+                }
+                else
+                {
+                    if (m_options.m_use_script_language)
+                    {
+                        interpreter->GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp->GetOptions(),
+                                                                                                      result);
+                    }
+                    else
+                    {
+                        CollectDataForBreakpointCommandCallback (bp->GetOptions(), result);
+                    }
+                }
+            }
+        }
+    }
+
+    return result.Succeeded();
+}
+
+Options *
+CommandObjectBreakpointCommandAdd::GetOptions ()
+{
+    return &m_options;
+}
+
+const char *g_reader_instructions = "Enter your debugger command(s).  Type 'DONE' to end.";
+
+void
+CommandObjectBreakpointCommandAdd::CollectDataForBreakpointCommandCallback
+(
+    BreakpointOptions *bp_options,
+    CommandReturnObject &result
+)
+{
+    InputReaderSP reader_sp (new InputReader());
+    std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
+    if (reader_sp && data_ap.get())
+    {
+        BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
+        bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp);
+
+        Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback,
+                                          bp_options,                   // baton
+                                          eInputReaderGranularityLine,  // token size, to pass to callback function
+                                          "DONE",                       // end token
+                                          "> ",                         // prompt
+                                          true));                       // echo input
+        if (err.Success())
+        {
+            Debugger::GetSharedInstance().PushInputReader (reader_sp);
+            result.SetStatus (eReturnStatusSuccessFinishNoResult);
+        }
+        else
+        {
+            result.AppendError (err.AsCString());
+            result.SetStatus (eReturnStatusFailed);
+        }
+    }
+    else
+    {
+        result.AppendError("out of memory");
+        result.SetStatus (eReturnStatusFailed);
+    }
+
+}
+
+size_t
+CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback
+(
+    void *baton, 
+    InputReader *reader, 
+    lldb::InputReaderAction notification,
+    const char *bytes, 
+    size_t bytes_len
+)
+{
+    FILE *out_fh = Debugger::GetSharedInstance().GetOutputFileHandle();
+
+    switch (notification)
+    {
+    case eInputReaderActivate:
+        if (out_fh)
+        {
+            ::fprintf (out_fh, "%s\n", g_reader_instructions);
+            if (reader->GetPrompt())
+                ::fprintf (out_fh, "%s", reader->GetPrompt());
+        }
+        break;
+
+    case eInputReaderDeactivate:
+        break;
+
+    case eInputReaderReactivate:
+        if (out_fh && reader->GetPrompt())
+            ::fprintf (out_fh, "%s", reader->GetPrompt());
+        break;
+
+    case eInputReaderGotToken:
+        if (bytes && bytes_len && baton)
+        {
+            BreakpointOptions *bp_options = (BreakpointOptions *) baton;
+            if (bp_options)
+            {
+                Baton *bp_options_baton = bp_options->GetBaton();
+                if (bp_options_baton)
+                    ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len); 
+            }
+        }
+        if (out_fh && !reader->IsDone() && reader->GetPrompt())
+            ::fprintf (out_fh, "%s", reader->GetPrompt());
+        break;
+        
+    case eInputReaderDone:
+        break;
+    }
+
+    return bytes_len;
+}
+
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointCommandRemove
+//-------------------------------------------------------------------------
+
+CommandObjectBreakpointCommandRemove::CommandObjectBreakpointCommandRemove () :
+    CommandObject ("remove",
+                   "Remove the set of commands from a breakpoint.",
+                   "breakpoint command remove <breakpoint-id>")
+{
+}
+
+CommandObjectBreakpointCommandRemove::~CommandObjectBreakpointCommandRemove ()
+{
+}
+
+bool
+CommandObjectBreakpointCommandRemove::Execute (Args& command,
+                                               CommandContext *context,
+                                               CommandInterpreter *interpreter,
+                                               CommandReturnObject &result)
+{
+    Target *target = context->GetTarget();
+
+    if (target == NULL)
+    {
+        result.AppendError ("There is not a current executable; there are no breakpoints from which to remove commands");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    const BreakpointList &breakpoints = target->GetBreakpointList();
+    size_t num_breakpoints = breakpoints.GetSize();
+
+    if (num_breakpoints == 0)
+    {
+        result.AppendError ("No breakpoints exist to have commands removed");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    if (command.GetArgumentCount() == 0)
+    {
+        result.AppendError ("No breakpoint specified from which to remove the commands");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    BreakpointIDList valid_bp_ids;
+    CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
+
+    if (result.Succeeded())
+    {
+        for (int i = 0; i < valid_bp_ids.Size(); ++i)
+        {
+            BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
+            if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
+            {
+                Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
+                if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
+                {
+                    BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
+                    if (bp_loc_sp)
+                        bp_loc_sp->ClearCallback();
+                    else
+                    {
+                        result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n", 
+                                                     cur_bp_id.GetBreakpointID(),
+                                                     cur_bp_id.GetLocationID());
+                        result.SetStatus (eReturnStatusFailed);
+                        return false;
+                    }
+                }
+                else
+                {
+                    bp->ClearCallback();
+                }
+            }
+        }
+    }
+    return result.Succeeded();
+}
+
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointCommandList
+//-------------------------------------------------------------------------
+
+CommandObjectBreakpointCommandList::CommandObjectBreakpointCommandList () :
+    CommandObject ("List",
+                   "List the script or set of commands to be executed when the breakpoint is hit.",
+                   "breakpoint command list <breakpoint-id>")
+{
+}
+
+CommandObjectBreakpointCommandList::~CommandObjectBreakpointCommandList ()
+{
+}
+
+bool
+CommandObjectBreakpointCommandList::Execute (Args& command,
+                                             CommandContext *context,
+                                             CommandInterpreter *interpreter,
+                                             CommandReturnObject &result)
+{
+    Target *target = context->GetTarget();
+
+    if (target == NULL)
+    {
+        result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    const BreakpointList &breakpoints = target->GetBreakpointList();
+    size_t num_breakpoints = breakpoints.GetSize();
+
+    if (num_breakpoints == 0)
+    {
+        result.AppendError ("No breakpoints exist for which to list commands");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    if (command.GetArgumentCount() == 0)
+    {
+        result.AppendError ("No breakpoint specified for which to list the commands");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    BreakpointIDList valid_bp_ids;
+    CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
+
+    if (result.Succeeded())
+    {
+        for (int i = 0; i < valid_bp_ids.Size(); ++i)
+        {
+            BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
+            if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
+            {
+                Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
+                
+                if (bp)
+                {
+                    BreakpointOptions *bp_options = NULL;
+                    if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
+                    {
+                        BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
+                        if (bp_loc_sp)
+                            bp_options = bp_loc_sp->GetOptionsNoCopy();
+                        else
+                        {
+                            result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n", 
+                                                         cur_bp_id.GetBreakpointID(),
+                                                         cur_bp_id.GetLocationID());
+                            result.SetStatus (eReturnStatusFailed);
+                            return false;
+                        }
+                    }
+                    else
+                    {
+                        bp_options = bp->GetOptions();
+                    }
+
+                    if (bp_options)
+                    {
+                        StreamString id_str;
+                        BreakpointID::GetCanonicalReference (&id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
+                        Baton *baton = bp_options->GetBaton();
+                        if (baton)
+                        {
+                            result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
+                            result.GetOutputStream().IndentMore ();
+                            baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
+                            result.GetOutputStream().IndentLess ();
+                        }
+                        else
+                        {
+                            result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n", id_str.GetData());
+                        }
+                    }
+                    result.SetStatus (eReturnStatusSuccessFinishResult);
+                }
+                else
+                {
+                    result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
+                    result.SetStatus (eReturnStatusFailed);
+                }
+
+            }
+        }
+    }
+
+    return result.Succeeded();
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointCommand
+//-------------------------------------------------------------------------
+
+CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter *interpreter) :
+    CommandObjectMultiword ("command",
+                            "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').",
+                            "command <sub-command> [<sub-command-options>] <breakpoint-id>")
+{
+    bool status;
+    CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd ());
+    CommandObjectSP remove_command_object (new CommandObjectBreakpointCommandRemove ());
+    CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList ());
+
+    add_command_object->SetCommandName ("breakpoint command add");
+    remove_command_object->SetCommandName ("breakpoint command remove");
+    list_command_object->SetCommandName ("breakpoint command list");
+
+    status = LoadSubCommand (add_command_object, "add", interpreter);
+    status = LoadSubCommand (remove_command_object, "remove", interpreter);
+    status = LoadSubCommand (list_command_object, "list", interpreter);
+}
+
+
+CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
+{
+}
+
+bool
+CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction 
+(
+    void *baton, 
+    StoppointCallbackContext *context,
+    lldb::user_id_t break_id, 
+    lldb::user_id_t break_loc_id
+)
+{
+    bool ret_value = true;
+    if (baton == NULL)
+        return true;
+    
+    
+    BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
+    StringList &commands = data->user_source;
+
+    if (commands.GetSize() > 0)
+    {
+        uint32_t num_commands = commands.GetSize();
+        CommandInterpreter &interpreter = Debugger::GetSharedInstance().GetCommandInterpreter();
+        CommandReturnObject result;
+        ExecutionContext exe_ctx = context->context;
+        
+        FILE *out_fh = Debugger::GetSharedInstance().GetOutputFileHandle();
+        FILE *err_fh = Debugger::GetSharedInstance().GetErrorFileHandle();
+            
+
+        uint32_t i;
+        for (i = 0; i < num_commands; ++i)
+        {
+            
+            // First time through we use the context from the stoppoint, after that we use whatever
+            // has been set by the previous command.
+            
+            if (!interpreter.HandleCommand (commands.GetStringAtIndex(i), false, result, &exe_ctx))
+                break;
+                
+            // FIXME: This isn't really the right way to do this.  We should be able to peek at the public 
+            // to see if there is any new events, but that is racey, since the internal process thread has to run and
+            // deliver the event to the public queue before a run will show up.  So for now we check
+            // the internal thread state.
+            
+            lldb::StateType internal_state = exe_ctx.process->GetPrivateState();
+            if (internal_state != eStateStopped)
+            {
+                if (i < num_commands - 1)
+                {
+                    if (out_fh)
+                        ::fprintf (out_fh, "Short-circuiting command execution because target state changed to %s."
+                                           " last command: \"%s\"\n", StateAsCString(internal_state),
+                                           commands.GetStringAtIndex(i));
+                }
+                break;
+            }
+            
+            // First time through we use the context from the stoppoint, after that we use whatever
+            // has been set by the previous command.
+            exe_ctx = Debugger::GetSharedInstance().GetCurrentExecutionContext();
+
+            
+            if (out_fh)
+                ::fprintf (out_fh, "%s", result.GetErrorStream().GetData());
+            if (err_fh)
+                ::fprintf (err_fh, "%s", result.GetOutputStream().GetData());
+            result.Clear();
+            result.SetStatus (eReturnStatusSuccessFinishNoResult);
+        }
+
+        if (err_fh && !result.Succeeded() && i < num_commands)
+            ::fprintf (err_fh, "Attempt to execute '%s' failed.\n", commands.GetStringAtIndex(i));
+
+        if (out_fh)
+            ::fprintf (out_fh, "%s", result.GetErrorStream().GetData());
+
+        if (err_fh)
+            ::fprintf (err_fh, "%s", result.GetOutputStream().GetData());        
+    }
+    return ret_value;
+}
+
diff --git a/source/Commands/CommandObjectBreakpointCommand.h b/source/Commands/CommandObjectBreakpointCommand.h
new file mode 100644
index 0000000..2ba2c60
--- /dev/null
+++ b/source/Commands/CommandObjectBreakpointCommand.h
@@ -0,0 +1,169 @@
+//===-- CommandObjectBreakpointCommand.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_CommandObjectBreakpointCommand_h_
+#define liblldb_CommandObjectBreakpointCommand_h_
+
+// C Includes
+// C++ Includes
+
+
+// Other libraries and framework includes
+// Project includes
+
+#include "lldb/lldb-types.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Core/InputReader.h"
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordBreakpoint
+//-------------------------------------------------------------------------
+
+class CommandObjectBreakpointCommand : public CommandObjectMultiword
+{
+public:
+    CommandObjectBreakpointCommand (CommandInterpreter *interpreter);
+
+    virtual
+    ~CommandObjectBreakpointCommand ();
+
+
+    static bool
+    BreakpointOptionsCallbackFunction (void *baton, 
+                                       StoppointCallbackContext *context,
+                                       lldb::user_id_t break_id, 
+                                       lldb::user_id_t break_loc_id);
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointCommandAdd
+//-------------------------------------------------------------------------
+
+
+class CommandObjectBreakpointCommandAdd : public CommandObject
+{
+public:
+
+    CommandObjectBreakpointCommandAdd ();
+
+    virtual
+    ~CommandObjectBreakpointCommandAdd ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+    virtual Options *
+    GetOptions ();
+
+    void
+    CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options, 
+                                             CommandReturnObject &result);
+
+    static size_t
+    GenerateBreakpointCommandCallback (void *baton, 
+                                       InputReader *reader, 
+                                       lldb::InputReaderAction notification,
+                                       const char *bytes, 
+                                       size_t bytes_len);
+    
+    static bool
+    BreakpointOptionsCallbackFunction (void *baton, 
+                                       StoppointCallbackContext *context, 
+                                       lldb::user_id_t break_id,
+                                       lldb::user_id_t break_loc_id);
+    
+
+    class CommandOptions : public Options
+    {
+    public:
+
+        CommandOptions ();
+
+        virtual
+        ~CommandOptions ();
+
+        virtual Error
+        SetOptionValue (int option_idx, const char *option_arg);
+
+        void
+        ResetOptionValues ();
+
+        const lldb::OptionDefinition*
+        GetDefinitions ();
+
+        // Options table: Required for subclasses of Options.
+
+        static lldb::OptionDefinition g_option_table[];
+
+        // Instance variables to hold the values for command options.
+
+        bool m_use_commands;
+        bool m_use_script_language;
+        lldb::ScriptLanguage m_script_language;
+    };
+
+private:
+    CommandOptions m_options;
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointCommandRemove
+//-------------------------------------------------------------------------
+
+class CommandObjectBreakpointCommandRemove : public CommandObject
+{
+public:
+    CommandObjectBreakpointCommandRemove ();
+
+    virtual
+    ~CommandObjectBreakpointCommandRemove ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+private:
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointCommandList
+//-------------------------------------------------------------------------
+
+class CommandObjectBreakpointCommandList : public CommandObject
+{
+public:
+    CommandObjectBreakpointCommandList ();
+
+    virtual
+    ~CommandObjectBreakpointCommandList ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+private:
+};
+
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectBreakpointCommand_h_
diff --git a/source/Commands/CommandObjectCall.cpp b/source/Commands/CommandObjectCall.cpp
new file mode 100644
index 0000000..58d0a0e
--- /dev/null
+++ b/source/Commands/CommandObjectCall.cpp
@@ -0,0 +1,307 @@
+//===-- CommandObjectCall.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectCall.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Expression/ClangExpression.h"
+#include "lldb/Expression/ClangExpressionVariable.h"
+#include "lldb/Expression/ClangFunction.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/Variable.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/StackFrame.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+// This command is a toy.  I'm just using it to have a way to construct the arguments to
+// calling functions.
+//
+
+CommandObjectCall::CommandOptions::CommandOptions () :
+    Options()
+{
+    // Keep only one place to reset the values to their defaults
+    ResetOptionValues();
+}
+
+
+CommandObjectCall::CommandOptions::~CommandOptions ()
+{
+}
+
+Error
+CommandObjectCall::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
+{
+    Error error;
+
+    char short_option = (char) m_getopt_table[option_idx].val;
+
+    switch (short_option)
+    {
+    case 'l':
+        if (language.SetLanguageFromCString (option_arg) == false)
+        {
+            error.SetErrorStringWithFormat("Invalid language option argument '%s'.\n", option_arg);
+        }
+        break;
+
+    case 'g':
+        debug = true;
+        break;
+
+    case 'f':
+        error = Args::StringToFormat(option_arg,format);
+        break;
+
+    case 'n':
+        noexecute = true;
+        break;
+            
+    case 'a':
+        use_abi = true;
+        break;
+            
+    default:
+        error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
+        break;
+    }
+
+    return error;
+}
+
+void
+CommandObjectCall::CommandOptions::ResetOptionValues ()
+{
+    Options::ResetOptionValues();
+    language.Clear();
+    debug = false;
+    format = eFormatDefault;
+    show_types = true;
+    show_summary = true;
+    noexecute = false;
+    use_abi = false;
+}
+
+const lldb::OptionDefinition*
+CommandObjectCall::CommandOptions::GetDefinitions ()
+{
+    return g_option_table;
+}
+
+CommandObjectCall::CommandObjectCall () :
+    CommandObject (
+            "call",
+            "Call a function.",
+            "call <return_type> <function-name> [[<arg1-type> <arg1-value>] ... <argn-type> <argn-value>] [<cmd-options>]",
+            eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
+{
+}
+
+CommandObjectCall::~CommandObjectCall ()
+{
+}
+
+Options *
+CommandObjectCall::GetOptions ()
+{
+    return &m_options;
+}
+
+bool
+CommandObjectCall::Execute
+(
+    Args &command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    ConstString target_triple;
+    int num_args = command.GetArgumentCount();
+
+    Target *target = context->GetTarget ();
+    if (target)
+        target->GetTargetTriple(target_triple);
+
+    if (!target_triple)
+        target_triple = Host::GetTargetTriple ();
+
+    ExecutionContext exe_ctx(context->GetExecutionContext());
+    if (exe_ctx.thread == NULL || exe_ctx.frame == NULL)
+    {
+        result.AppendError ("No currently selected thread and frame.");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    if (num_args < 2)
+    {
+        result.AppendErrorWithFormat ("Invalid usage, should be: %s.\n", GetSyntax());
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    if ((num_args - 2) %2 != 0)
+    {
+        result.AppendErrorWithFormat ("Invalid usage - unmatched args & types, should be: %s.\n", GetSyntax());
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    if (target_triple)
+    {
+        //const char *return_type = command.GetArgumentAtIndex(0);
+        const char *function_name = command.GetArgumentAtIndex(1);
+        // Look up the called function:
+
+        Function *target_fn = exe_ctx.frame->GetSymbolContext(eSymbolContextEverything).FindFunctionByName (function_name);
+
+        // FIXME: If target_fn is NULL, we should look up the name as a symbol and use it and the provided
+        // return type.
+
+        if (target_fn == NULL)
+        {
+            result.AppendErrorWithFormat ("Could not find function '%s'.\n", function_name);
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        ValueList value_list;
+        // Okay, now parse arguments.  For now we only accept basic types.
+        for (int i = 2; i < num_args; i+= 2)
+        {
+            const char *type_str = command.GetArgumentAtIndex(i);
+            const char *value_str = command.GetArgumentAtIndex(i + 1);
+            bool success;
+            if (strcmp(type_str, "int") == 0
+                || strcmp(type_str, "int32_t") == 0)
+            {
+                value_list.PushValue(Value(Args::StringToSInt32(value_str, 0, 0, &success)));
+            }
+            else if (strcmp (type_str, "int64_t") == 0)
+            {
+                value_list.PushValue(Value(Args::StringToSInt64(value_str, 0, 0, &success)));
+            }
+            else if (strcmp(type_str, "uint") == 0
+                || strcmp(type_str, "uint32_t") == 0)
+            {
+                value_list.PushValue(Value(Args::StringToUInt32(value_str, 0, 0, &success)));
+            }
+            else if (strcmp (type_str, "uint64_t") == 0)
+            {
+                value_list.PushValue(Value(Args::StringToUInt64(value_str, 0, 0, &success)));
+            }
+            else if (strcmp (type_str, "cstr") == 0)
+            {
+                Value val ((intptr_t)value_str);
+                val.SetValueType (Value::eValueTypeHostAddress);
+                
+                
+                void *cstr_type = target->GetScratchClangASTContext()->GetCStringType(true);
+                val.SetContext (Value::eContextTypeOpaqueClangQualType, cstr_type);
+                value_list.PushValue(val);
+                
+                success = true;
+            }
+
+            if (!success)
+            {
+                result.AppendErrorWithFormat ("Could not convert value: '%s' to type '%s'.\n", value_str, type_str);
+                result.SetStatus (eReturnStatusFailed);
+                return false;
+            }
+        }
+        // Okay, we have the function and the argument list and the return type.  Now make a ClangFunction object and
+        // run it:
+
+        StreamString errors;
+        ClangFunction clang_fun (target_triple.GetCString(), *target_fn, target->GetScratchClangASTContext(), value_list);
+        if (m_options.noexecute)
+        {
+            // Now write down the argument values for this call.
+            lldb::addr_t args_addr = LLDB_INVALID_ADDRESS;
+            if (!clang_fun.InsertFunction (exe_ctx, args_addr, errors))
+            {
+                result.AppendErrorWithFormat("Error inserting function: '%s'.\n", errors.GetData());
+                result.SetStatus (eReturnStatusFailed);
+                return false;
+            }
+            else
+            {
+                result.Succeeded();
+                return true;
+            }
+        }
+        
+        ClangFunction::ExecutionResults return_status;
+        Value return_value;
+        
+        if (m_options.use_abi)
+        {
+            return_status = clang_fun.ExecuteFunctionWithABI(exe_ctx, errors, return_value);
+        }
+        else 
+        {
+            bool stop_others = true;
+            return_status = clang_fun.ExecuteFunction(exe_ctx, errors, stop_others, NULL, return_value);
+        }
+
+        // Now figure out what to do with the return value.
+        if (return_status == ClangFunction::eExecutionSetupError)
+        {
+            result.AppendErrorWithFormat("Error setting up function execution: '%s'.\n", errors.GetData());
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+        else if (return_status != ClangFunction::eExecutionCompleted)
+        {
+            result.AppendWarningWithFormat("Interrupted while calling function: '%s'.\n", errors.GetData());
+            result.SetStatus(eReturnStatusSuccessFinishNoResult);
+            return true;
+        }
+        else
+        {
+            // Now print out the result.
+            result.GetOutputStream().Printf("Return value: ");
+            return_value.Dump(&(result.GetOutputStream()));
+            result.Succeeded();
+        }
+
+    }
+    else
+    {
+        result.AppendError ("invalid target triple");
+        result.SetStatus (eReturnStatusFailed);
+    }
+    return result.Succeeded();
+}
+
+lldb::OptionDefinition
+CommandObjectCall::CommandOptions::g_option_table[] =
+{
+{ 0, true,  "language",   'l', required_argument, NULL, 0, "[c|c++|objc|objc++]",          "Sets the language to use when parsing the expression."},
+{ 0, false, "format",     'f', required_argument, NULL, 0, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]",  "Specify the format that the expression output should use."},
+{ 0, false, "debug",      'g', no_argument,       NULL, 0, NULL,                           "Enable verbose debug logging of the expression parsing and evaluation."},
+{ 0, false, "noexecute",  'n', no_argument,       NULL, 0, "no execute",                   "Only JIT and copy the wrapper & arguments, but don't execute."},
+{ 0, false, "useabi",     'a', no_argument,       NULL, 0, NULL,                           "Use the ABI instead of the JIT to marshall arguments."},
+{ 0, false, NULL, 0, 0, NULL, NULL, NULL, NULL }
+};
+
diff --git a/source/Commands/CommandObjectCall.h b/source/Commands/CommandObjectCall.h
new file mode 100644
index 0000000..c051a14
--- /dev/null
+++ b/source/Commands/CommandObjectCall.h
@@ -0,0 +1,84 @@
+//===-- CommandObjectCall.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_CommandObjectCall_h_
+#define liblldb_CommandObjectCall_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Core/Language.h"
+
+namespace lldb_private {
+
+class CommandObjectCall : public CommandObject
+{
+public:
+
+    class CommandOptions : public Options
+    {
+    public:
+
+        CommandOptions ();
+
+        virtual
+        ~CommandOptions ();
+
+        virtual Error
+        SetOptionValue (int option_idx, const char *option_arg);
+
+        void
+        ResetOptionValues ();
+
+        const lldb::OptionDefinition*
+        GetDefinitions ();
+
+        // Options table: Required for subclasses of Options.
+
+        static lldb::OptionDefinition g_option_table[];
+        Language  language;
+        lldb::Encoding  encoding;
+        lldb::Format    format;
+        bool        debug;
+        bool        show_types;
+        bool        show_summary;
+        bool        noexecute;
+        bool        use_abi;
+    };
+
+    CommandObjectCall ();
+
+    virtual
+    ~CommandObjectCall ();
+
+    virtual
+    Options *
+    GetOptions ();
+
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+    virtual bool
+    WantsRawCommandString() { return false; }
+
+protected:
+
+    CommandOptions m_options;
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectCall_h_
diff --git a/source/Commands/CommandObjectDelete.cpp b/source/Commands/CommandObjectDelete.cpp
new file mode 100644
index 0000000..2fc072e
--- /dev/null
+++ b/source/Commands/CommandObjectDelete.cpp
@@ -0,0 +1,32 @@
+//===-- CommandObjectDelete.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectDelete.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectDelete
+//-------------------------------------------------------------------------
+
+CommandObjectDelete::CommandObjectDelete () :
+CommandObjectCrossref ("delete", "Lists the kinds of objects you can delete, and shows syntax for deleting them.", "delete")
+{
+}
+
+CommandObjectDelete::~CommandObjectDelete ()
+{
+}
+
+
diff --git a/source/Commands/CommandObjectDelete.h b/source/Commands/CommandObjectDelete.h
new file mode 100644
index 0000000..f7d86b7
--- /dev/null
+++ b/source/Commands/CommandObjectDelete.h
@@ -0,0 +1,37 @@
+//===-- CommandObjectDelete.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_CommandObjectDelete_h_
+#define liblldb_CommandObjectDelete_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectCrossref.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectDelete
+//-------------------------------------------------------------------------
+
+class CommandObjectDelete : public CommandObjectCrossref
+{
+public:
+    CommandObjectDelete ();
+
+    virtual
+    ~CommandObjectDelete ();
+
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectDelete_h_
diff --git a/source/Commands/CommandObjectDisassemble.cpp b/source/Commands/CommandObjectDisassemble.cpp
new file mode 100644
index 0000000..0985504
--- /dev/null
+++ b/source/Commands/CommandObjectDisassemble.cpp
@@ -0,0 +1,431 @@
+//===-- CommandObjectDisassemble.cpp ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectDisassemble.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/AddressRange.h"
+#include "lldb/Core/Args.h"
+#include "lldb/Interpreter/CommandCompletions.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Core/SourceManager.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#define DEFAULT_DISASM_BYTE_SIZE 32
+
+using namespace lldb;
+using namespace lldb_private;
+
+CommandObjectDisassemble::CommandOptions::CommandOptions () :
+    Options(),
+    m_func_name(),
+    m_load_addr()
+{
+    ResetOptionValues();
+}
+
+CommandObjectDisassemble::CommandOptions::~CommandOptions ()
+{
+}
+
+Error
+CommandObjectDisassemble::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
+{
+    Error error;
+
+    char short_option = (char) m_getopt_table[option_idx].val;
+
+    switch (short_option)
+    {
+    case 'm':
+        show_mixed = true;
+        break;
+
+    case 'c':
+        num_lines_context = Args::StringToUInt32(option_arg, 0, 0);
+        break;
+
+    case 'b':
+        show_bytes = true;
+        break;
+
+    case 'a':
+        m_load_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 0);
+        if (m_load_addr == LLDB_INVALID_ADDRESS)
+            m_load_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 16);
+
+        if (m_load_addr == LLDB_INVALID_ADDRESS)
+            error.SetErrorStringWithFormat ("Invalid address string '%s'.\n", optarg);
+        break;
+
+    case 'n':
+        m_func_name = option_arg;
+        break;
+
+    case 'r':
+        raw = true;
+        break;
+
+    default:
+        error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
+        break;
+    }
+
+    return error;
+}
+
+void
+CommandObjectDisassemble::CommandOptions::ResetOptionValues ()
+{
+    Options::ResetOptionValues();
+    show_mixed = false;
+    show_bytes = false;
+    num_lines_context = 0;
+    m_func_name.clear();
+    m_load_addr = LLDB_INVALID_ADDRESS;
+}
+
+const lldb::OptionDefinition*
+CommandObjectDisassemble::CommandOptions::GetDefinitions ()
+{
+    return g_option_table;
+}
+
+lldb::OptionDefinition
+CommandObjectDisassemble::CommandOptions::g_option_table[] =
+{
+{ 0, false, "bytes",    'b', no_argument,       NULL, 0, NULL,             "Show opcode bytes when disassembling."},
+{ 0, false, "context",  'c', required_argument, NULL, 0, "<num-lines>",    "Number of context lines of source to show."},
+{ 0, false, "mixed",    'm', no_argument,       NULL, 0, NULL,             "Enable mixed source and assembly display."},
+{ 0, false, "raw",      'r', no_argument,       NULL, 0, NULL,             "Print raw disassembly with no symbol information."},
+
+{ 1, false, "address",  'a', required_argument, NULL, 0, "<address>",      "Address to start disassembling."},
+{ 1, false, "bytes",    'b', no_argument,       NULL, 0, NULL,             "Show opcode bytes when disassembling."},
+{ 1, false, "context",  'c', required_argument, NULL, 0, "<num-lines>",    "Number of context lines of source to show."},
+{ 1, false, "mixed",    'm', no_argument,       NULL, 0, NULL,             "Enable mixed source and assembly display."},
+{ 1, false, "raw",      'r', no_argument,       NULL, 0, NULL,             "Print raw disassembly with no symbol information."},
+
+{ 2, false, "name",     'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, "<function-name>",             "Disassemble entire contents of the given function name."},
+{ 2, false, "bytes",    'b', no_argument,       NULL, 0, NULL,             "Show opcode bytes when disassembling."},
+{ 2, false, "context",  'c', required_argument, NULL, 0, "<num-lines>",    "Number of context lines of source to show."},
+{ 2, false, "mixed",    'm', no_argument,       NULL, 0, NULL,             "Enable mixed source and assembly display."},
+{ 2, false, "raw",      'r', no_argument,       NULL, 0, NULL,             "Print raw disassembly with no symbol information."},
+
+{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+
+
+//-------------------------------------------------------------------------
+// CommandObjectDisassemble
+//-------------------------------------------------------------------------
+
+CommandObjectDisassemble::CommandObjectDisassemble () :
+    CommandObject ("disassemble",
+                     "Disassemble bytes in the current function or anywhere in the inferior program.",
+                     "disassemble [[<start-addr> [<end-addr>]] | <function-name>] [<cmd-options>]")
+{
+}
+
+CommandObjectDisassemble::~CommandObjectDisassemble()
+{
+}
+
+void
+CommandObjectDisassemble::Disassemble
+(
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result,
+    Disassembler *disassembler,
+    const SymbolContextList &sc_list
+)
+{
+    const size_t count = sc_list.GetSize();
+    SymbolContext sc;
+    AddressRange range;
+    for (size_t i=0; i<count; ++i)
+    {
+        if (sc_list.GetContextAtIndex(i, sc) == false)
+            break;
+        if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range))
+        {
+            lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(context->GetExecutionContext().process);
+            if (addr != LLDB_INVALID_ADDRESS)
+            {
+                lldb::addr_t end_addr = addr + range.GetByteSize();
+                Disassemble (context, interpreter, result, disassembler, addr, end_addr);
+            }
+        }
+    }
+}
+
+void
+CommandObjectDisassemble::Disassemble
+(
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result,
+    Disassembler *disassembler,
+    lldb::addr_t addr,
+    lldb::addr_t end_addr
+)
+{
+    if (addr == LLDB_INVALID_ADDRESS)
+        return;
+
+    if (end_addr == LLDB_INVALID_ADDRESS || addr >= end_addr)
+        end_addr = addr + DEFAULT_DISASM_BYTE_SIZE;
+
+    ExecutionContext exe_ctx (context->GetExecutionContext());
+    DataExtractor data;
+    size_t bytes_disassembled = disassembler->ParseInstructions (&exe_ctx, eAddressTypeLoad, addr, end_addr - addr, data);
+    if (bytes_disassembled == 0)
+    {
+        // Nothing got disassembled...
+    }
+    else
+    {
+        // We got some things disassembled...
+        size_t num_instructions = disassembler->GetInstructionList().GetSize();
+        uint32_t offset = 0;
+        Stream &output_stream = result.GetOutputStream();
+        SymbolContext sc;
+        SymbolContext prev_sc;
+        AddressRange sc_range;
+        if (m_options.show_mixed)
+            output_stream.IndentMore ();
+
+        for (size_t i=0; i<num_instructions; ++i)
+        {
+            Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i);
+            if (inst)
+            {
+                lldb::addr_t curr_addr = addr + offset;
+                if (m_options.show_mixed)
+                {
+                    Process *process = context->GetExecutionContext().process;
+                    if (!sc_range.ContainsLoadAddress (curr_addr, process))
+                    {
+                        prev_sc = sc;
+                        Address curr_so_addr;
+                        if (process && process->ResolveLoadAddress (curr_addr, curr_so_addr))
+                        {
+                            if (curr_so_addr.GetSection())
+                            {
+                                Module *module = curr_so_addr.GetSection()->GetModule();
+                                uint32_t resolved_mask = module->ResolveSymbolContextForAddress(curr_so_addr, eSymbolContextEverything, sc);
+                                if (resolved_mask)
+                                {
+                                    sc.GetAddressRange (eSymbolContextEverything, sc_range);
+                                    if (sc != prev_sc)
+                                    {
+                                        if (offset != 0)
+                                            output_stream.EOL();
+
+                                        sc.DumpStopContext(&output_stream, process, curr_so_addr);
+                                        output_stream.EOL();
+                                        if (sc.comp_unit && sc.line_entry.IsValid())
+                                        {
+                                            interpreter->GetSourceManager().DisplaySourceLinesWithLineNumbers (
+                                                    sc.line_entry.file,
+                                                    sc.line_entry.line,
+                                                    m_options.num_lines_context,
+                                                    m_options.num_lines_context,
+                                                    m_options.num_lines_context ? "->" : "",
+                                                    &output_stream);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                if (m_options.show_mixed)
+                    output_stream.IndentMore ();
+                output_stream.Indent();
+                size_t inst_byte_size = inst->GetByteSize();
+                inst->Dump(&output_stream, curr_addr, m_options.show_bytes ? &data : NULL, offset, exe_ctx, m_options.raw);
+                output_stream.EOL();
+                offset += inst_byte_size;
+                if (m_options.show_mixed)
+                    output_stream.IndentLess ();
+            }
+            else
+            {
+                break;
+            }
+        }
+        if (m_options.show_mixed)
+            output_stream.IndentLess ();
+
+    }
+}
+
+bool
+CommandObjectDisassemble::Execute
+(
+    Args& command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    Target *target = context->GetTarget();
+    if (target == NULL)
+    {
+        result.AppendError ("invalid target, set executable file using 'file' command");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    ArchSpec arch(target->GetArchitecture());
+    if (!arch.IsValid())
+    {
+        result.AppendError ("target needs valid architecure in order to be able to disassemble");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    Disassembler *disassembler = Disassembler::FindPlugin(arch);
+
+    if (disassembler == NULL)
+    {
+        result.AppendErrorWithFormat ("Unable to find Disassembler plug-in for %s architecture.\n", arch.AsCString());
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    result.SetStatus (eReturnStatusSuccessFinishResult);
+
+    lldb::addr_t addr = LLDB_INVALID_ADDRESS;
+    lldb::addr_t end_addr = LLDB_INVALID_ADDRESS;
+    ConstString name;
+    const size_t argc = command.GetArgumentCount();
+    if (argc == 0 && m_options.m_load_addr != LLDB_INVALID_ADDRESS)
+    {
+        addr = m_options.m_load_addr;
+        end_addr = addr + DEFAULT_DISASM_BYTE_SIZE;
+    } else if (argc == 0 && !m_options.m_func_name.empty())
+    {
+        ConstString tmpname(m_options.m_func_name.c_str());
+        name = tmpname;
+    } else if (argc == 0)
+    {
+        ExecutionContext exe_ctx(context->GetExecutionContext());
+        if (exe_ctx.frame)
+        {
+            SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
+            if (sc.function)
+            {
+                addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(exe_ctx.process);
+                if (addr != LLDB_INVALID_ADDRESS)
+                    end_addr = addr + sc.function->GetAddressRange().GetByteSize();
+            }
+            else if (sc.symbol && sc.symbol->GetAddressRangePtr())
+            {
+                addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress().GetLoadAddress(exe_ctx.process);
+                if (addr != LLDB_INVALID_ADDRESS)
+                {
+                    end_addr = addr + sc.symbol->GetAddressRangePtr()->GetByteSize();
+                    if (addr == end_addr)
+                        end_addr += DEFAULT_DISASM_BYTE_SIZE;
+                }
+            }
+            else
+            {
+                addr = exe_ctx.frame->GetPC().GetLoadAddress(exe_ctx.process);
+                if (addr != LLDB_INVALID_ADDRESS)
+                    end_addr = addr + DEFAULT_DISASM_BYTE_SIZE;
+            }
+        }
+        else
+        {
+            result.AppendError ("invalid frame");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+    }
+    else if (argc == 1)
+    {
+        const char *arg = command.GetArgumentAtIndex(0);
+        addr = Args::StringToAddress (arg);
+        if (addr == LLDB_INVALID_ADDRESS)
+        {   
+            // Lookup function or symbol name?
+            ConstString tmpname(arg);
+            name = tmpname;
+        }
+        else
+        {
+            end_addr = addr + DEFAULT_DISASM_BYTE_SIZE;
+        }
+    }
+    else if (argc >= 1 && argc <= 2)
+    {
+        addr = Args::StringToAddress (command.GetArgumentAtIndex(0));
+        if (addr == LLDB_INVALID_ADDRESS)
+        {
+            result.AppendErrorWithFormat ("Unable to parse address '%s'.\n", command.GetArgumentAtIndex(0));
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+        end_addr = Args::StringToAddress (command.GetArgumentAtIndex(1), addr);
+        if (end_addr == LLDB_INVALID_ADDRESS)
+        {
+            result.AppendErrorWithFormat ("Unable to parse address '%s'.\n", command.GetArgumentAtIndex(1));
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+    }
+
+    if (!name.IsEmpty())
+    {
+        SymbolContextList sc_list;
+
+        if (target->GetImages().FindFunctions(name, sc_list))
+        {
+            Disassemble (context, interpreter, result, disassembler, sc_list);
+        }
+        else if (target->GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeCode, sc_list))
+        {
+            Disassemble (context, interpreter, result, disassembler, sc_list);
+        }
+        else
+        {
+            result.AppendErrorWithFormat ("Unable to find symbol with name '%s'.\n", name.GetCString());
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+    }
+
+    if (addr < end_addr)
+    {
+        Disassemble (context, interpreter, result, disassembler, addr, end_addr);
+    }
+
+    if (addr == LLDB_INVALID_ADDRESS && name.IsEmpty())
+    {
+        result.AppendError ("No recognizable address of function name provided");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+    {
+        return result.Succeeded();
+    }
+}
diff --git a/source/Commands/CommandObjectDisassemble.h b/source/Commands/CommandObjectDisassemble.h
new file mode 100644
index 0000000..2cf800d
--- /dev/null
+++ b/source/Commands/CommandObjectDisassemble.h
@@ -0,0 +1,95 @@
+//===-- CommandObjectDisassemble.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_CommandObjectDisassemble_h_
+#define liblldb_CommandObjectDisassemble_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Core/Options.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectDisassemble
+//-------------------------------------------------------------------------
+
+class CommandObjectDisassemble : public CommandObject
+{
+public:
+    class CommandOptions : public Options
+    {
+    public:
+
+        CommandOptions ();
+
+        virtual
+        ~CommandOptions ();
+
+        virtual Error
+        SetOptionValue (int option_idx, const char *option_arg);
+
+        void
+        ResetOptionValues ();
+
+        const lldb::OptionDefinition*
+        GetDefinitions ();
+
+        bool show_mixed; // Show mixed source/assembly
+        bool show_bytes;
+        uint32_t num_lines_context;
+        bool raw;
+        std::string m_func_name;
+        lldb::addr_t m_load_addr;
+        static lldb::OptionDefinition g_option_table[];
+    };
+
+    CommandObjectDisassemble ();
+
+    virtual
+    ~CommandObjectDisassemble ();
+
+    virtual
+    Options *
+    GetOptions ()
+    {
+        return &m_options;
+    }
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+protected:
+    CommandOptions m_options;
+
+    void
+    Disassemble (CommandContext *context,
+                 CommandInterpreter *interpreter,
+                 CommandReturnObject &result,
+                 Disassembler *disassembler,
+                 lldb::addr_t addr,
+                 lldb::addr_t end_addr);
+
+    void
+    Disassemble (CommandContext *context,
+                 CommandInterpreter *interpreter,
+                 CommandReturnObject &result,
+                 Disassembler *disassembler,
+                 const SymbolContextList &sc_list);
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectDisassemble_h_
diff --git a/source/Commands/CommandObjectExpression.cpp b/source/Commands/CommandObjectExpression.cpp
new file mode 100644
index 0000000..9afc8c0
--- /dev/null
+++ b/source/Commands/CommandObjectExpression.cpp
@@ -0,0 +1,554 @@
+//===-- CommandObjectExpression.cpp -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectExpression.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/InputReader.h"
+#include "lldb/Expression/ClangExpression.h"
+#include "lldb/Expression/ClangExpressionDeclMap.h"
+#include "lldb/Expression/ClangExpressionVariable.h"
+#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/Variable.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "llvm/ADT/StringRef.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+CommandObjectExpression::CommandOptions::CommandOptions () :
+    Options()
+{
+    // Keep only one place to reset the values to their defaults
+    ResetOptionValues();
+}
+
+
+CommandObjectExpression::CommandOptions::~CommandOptions ()
+{
+}
+
+Error
+CommandObjectExpression::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
+{
+    Error error;
+
+    char short_option = (char) m_getopt_table[option_idx].val;
+
+    switch (short_option)
+    {
+    case 'l':
+        if (language.SetLanguageFromCString (option_arg) == false)
+        {
+            error.SetErrorStringWithFormat("Invalid language option argument '%s'.\n", option_arg);
+        }
+        break;
+
+    case 'g':
+        debug = true;
+        break;
+
+    case 'f':
+        error = Args::StringToFormat(option_arg, format);
+        break;
+
+    default:
+        error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
+        break;
+    }
+
+    return error;
+}
+
+void
+CommandObjectExpression::CommandOptions::ResetOptionValues ()
+{
+    Options::ResetOptionValues();
+    language.Clear();
+    debug = false;
+    format = eFormatDefault;
+    show_types = true;
+    show_summary = true;
+}
+
+const lldb::OptionDefinition*
+CommandObjectExpression::CommandOptions::GetDefinitions ()
+{
+    return g_option_table;
+}
+
+CommandObjectExpression::CommandObjectExpression () :
+    CommandObject (
+            "expression",
+            "Evaluate a C expression in the current program context, using variables currently in scope.",
+            "expression [<cmd-options>] <expr>"),
+    m_expr_line_count (0),
+    m_expr_lines ()
+{
+  SetHelpLong(
+"Examples: \n\
+\n\
+   expr my_struct->a = my_array[3] \n\
+   expr -f bin -- (index * 8) + 5 \n\
+   expr char c[] = \"foo\"; c[0]\n");
+}
+
+CommandObjectExpression::~CommandObjectExpression ()
+{
+}
+
+Options *
+CommandObjectExpression::GetOptions ()
+{
+    return &m_options;
+}
+
+
+bool
+CommandObjectExpression::Execute
+(
+    Args& command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    return false;
+}
+
+
+size_t
+CommandObjectExpression::MultiLineExpressionCallback
+(
+    void *baton, 
+    InputReader *reader, 
+    lldb::InputReaderAction notification,
+    const char *bytes, 
+    size_t bytes_len
+)
+{
+    FILE *out_fh = Debugger::GetSharedInstance().GetOutputFileHandle();
+    CommandObjectExpression *cmd_object_expr = (CommandObjectExpression *) baton;
+
+    switch (notification)
+    {
+    case eInputReaderActivate:
+        if (out_fh)
+            ::fprintf (out_fh, "%s\n", "Enter expressions, then terminate with an empty line to evaluate:");
+        // Fall through
+    case eInputReaderReactivate:
+        //if (out_fh)
+        //    ::fprintf (out_fh, "%3u: ", cmd_object_expr->m_expr_line_count);
+        break;
+
+    case eInputReaderDeactivate:
+        break;
+
+    case eInputReaderGotToken:
+        ++cmd_object_expr->m_expr_line_count;
+        if (bytes && bytes_len)
+        {
+            cmd_object_expr->m_expr_lines.append (bytes, bytes_len + 1);
+        }
+
+        if (bytes_len == 0)
+            reader->SetIsDone(true);
+        //else if (out_fh && !reader->IsDone())
+        //    ::fprintf (out_fh, "%3u: ", cmd_object_expr->m_expr_line_count);
+        break;
+        
+    case eInputReaderDone:
+        {
+            StreamFile out_stream(Debugger::GetSharedInstance().GetOutputFileHandle());
+            StreamFile err_stream(Debugger::GetSharedInstance().GetErrorFileHandle());
+            bool bare = false;
+            cmd_object_expr->EvaluateExpression (cmd_object_expr->m_expr_lines.c_str(), 
+                                                 bare, 
+                                                 out_stream, 
+                                                 err_stream);
+        }
+        break;
+    }
+
+    return bytes_len;
+}
+
+bool
+CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream &output_stream, Stream &error_stream)
+{
+    bool success = false;
+    ConstString target_triple;
+    Target *target = m_exe_ctx.target;
+    if (target)
+        target->GetTargetTriple(target_triple);
+
+    if (!target_triple)
+        target_triple = Host::GetTargetTriple ();
+
+
+    if (target_triple)
+    {
+        const bool show_types = m_options.show_types;
+        const bool show_summary = m_options.show_summary;
+        const bool debug = m_options.debug;
+        
+        ClangExpressionDeclMap expr_decl_map(&m_exe_ctx);
+        ClangExpression clang_expr(target_triple.AsCString(), &expr_decl_map);
+        
+        unsigned num_errors = 0;
+        
+        if (bare)
+            num_errors = clang_expr.ParseBareExpression (llvm::StringRef(expr), error_stream);
+        else
+            num_errors = clang_expr.ParseExpression (expr, error_stream);
+
+        if (num_errors == 0)
+        {
+            StreamString dwarf_opcodes;
+            dwarf_opcodes.SetByteOrder(eByteOrderHost);
+            dwarf_opcodes.GetFlags().Set(Stream::eBinary);
+            ClangExpressionVariableList expr_local_vars;
+            clang_expr.ConvertExpressionToDWARF (expr_local_vars, dwarf_opcodes);
+
+            success = true;
+
+            DataExtractor dwarf_opcodes_data(dwarf_opcodes.GetData(), dwarf_opcodes.GetSize(), eByteOrderHost, 8);
+            DWARFExpression expr(dwarf_opcodes_data, 0, dwarf_opcodes_data.GetByteSize(), NULL);
+            expr.SetExpressionLocalVariableList(&expr_local_vars);
+            if (debug)
+            {
+                output_stream << "Expression parsed ok, dwarf opcodes:";
+                output_stream.IndentMore();
+                expr.GetDescription(&output_stream, lldb::eDescriptionLevelVerbose);
+                output_stream.IndentLess();
+                output_stream.EOL();
+            }
+
+            clang::ASTContext *ast_context = clang_expr.GetASTContext();
+            Value expr_result;
+            Error expr_error;
+            bool expr_success = expr.Evaluate (&m_exe_ctx, ast_context, NULL, expr_result, &expr_error);
+            if (expr_success)
+            {
+                lldb::Format format = m_options.format;
+
+                // Resolve any values that are possible
+                expr_result.ResolveValue(&m_exe_ctx, ast_context);
+
+                if (expr_result.GetContextType() == Value::eContextTypeInvalid &&
+                    expr_result.GetValueType() == Value::eValueTypeScalar &&
+                    format == eFormatDefault)
+                {
+                    // The expression result is just a scalar with no special formatting
+                    expr_result.GetScalar().GetValue (&output_stream, show_types);
+                    output_stream.EOL();
+                }
+                else
+                {
+                    DataExtractor data;
+                    expr_error = expr_result.GetValueAsData (&m_exe_ctx, ast_context, data, 0);
+                    if (expr_error.Success())
+                    {
+                        if (format == eFormatDefault)
+                            format = expr_result.GetValueDefaultFormat ();
+
+                        void *clang_type = expr_result.GetValueOpaqueClangQualType();
+                        if (clang_type)
+                        {
+                            if (show_types)
+                                Type::DumpClangTypeName(&output_stream, clang_type);
+
+                            Type::DumpValue (
+                                &m_exe_ctx,                 // The execution context for memory and variable access
+                                ast_context,                // The ASTContext that the clang type belongs to
+                                clang_type,                 // The opaque clang type we want to dump that value of
+                                &output_stream,             // Stream to dump to
+                                format,                     // Format to use when dumping
+                                data,                       // A buffer containing the bytes for the clang type
+                                0,                          // Byte offset within "data" where value is
+                                data.GetByteSize(),         // Size in bytes of the value we are dumping
+                                0,                          // Bitfield bit size
+                                0,                          // Bitfield bit offset
+                                show_types,                 // Show types?
+                                show_summary,               // Show summary?
+                                debug,                      // Debug logging output?
+                                UINT32_MAX);                // Depth to dump in case this is an aggregate type
+                        }
+                        else
+                        {
+                            data.Dump(&output_stream,       // Stream to dump to
+                                      0,                    // Byte offset within "data"
+                                      format,               // Format to use when dumping
+                                      data.GetByteSize(),   // Size in bytes of each item we are dumping
+                                      1,                    // Number of items to dump
+                                      UINT32_MAX,           // Number of items per line
+                                      LLDB_INVALID_ADDRESS,   // Invalid address, don't show any offset/address context
+                                      0,                    // Bitfield bit size
+                                      0);                   // Bitfield bit offset
+                        }
+                        output_stream.EOL();
+                    }
+                    else
+                    {
+                        error_stream.Printf ("error: %s\n", expr_error.AsCString());
+                        success = false;
+                    }
+                }
+            }
+            else
+            {
+                error_stream.Printf ("error: %s\n", expr_error.AsCString());
+            }
+        }
+    }
+    else
+    {
+        error_stream.PutCString ("error: invalid target triple\n");
+    }
+
+    return success;
+}
+
+bool
+CommandObjectExpression::ExecuteRawCommandString
+(
+    const char *command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    ConstString target_triple;
+    Target *target = context->GetTarget ();
+    if (target)
+        target->GetTargetTriple(target_triple);
+
+    if (!target_triple)
+        target_triple = Host::GetTargetTriple ();
+
+    ExecutionContext exe_ctx(context->GetExecutionContext());
+
+    Stream &output_stream = result.GetOutputStream();
+
+    m_options.ResetOptionValues();
+
+    const char * expr = NULL;
+
+    if (command[0] == '\0')
+    {
+        m_expr_lines.clear();
+        m_expr_line_count = 0;
+        
+        InputReaderSP reader_sp (new InputReader());
+        if (reader_sp)
+        {
+            Error err (reader_sp->Initialize (CommandObjectExpression::MultiLineExpressionCallback,
+                                              this,                         // baton
+                                              eInputReaderGranularityLine,  // token size, to pass to callback function
+                                              NULL,                       // end token
+                                              NULL,                         // prompt
+                                              true));                       // echo input
+            if (err.Success())
+            {
+                Debugger::GetSharedInstance().PushInputReader (reader_sp);
+                result.SetStatus (eReturnStatusSuccessFinishNoResult);
+            }
+            else
+            {
+                result.AppendError (err.AsCString());
+                result.SetStatus (eReturnStatusFailed);
+            }
+        }
+        else
+        {
+            result.AppendError("out of memory");
+            result.SetStatus (eReturnStatusFailed);
+        }
+        return result.Succeeded();
+    }
+
+    if (command[0] == '-')
+    {
+        // We have some options and these options MUST end with --.
+        const char *end_options = NULL;
+        const char *s = command;
+        while (s && s[0])
+        {
+            end_options = ::strstr (s, "--");
+            if (end_options)
+            {
+                end_options += 2; // Get past the "--"
+                if (::isspace (end_options[0]))
+                {
+                    expr = end_options;
+                    while (::isspace (*expr))
+                        ++expr;
+                    break;
+                }
+            }
+            s = end_options;
+        }
+
+        if (end_options)
+        {
+            Args args(command, end_options - command);
+            if (!ParseOptions(args, interpreter, result))
+                return false;
+        }
+    }
+
+    const bool show_types = m_options.show_types;
+    const bool show_summary = m_options.show_summary;
+    const bool debug = m_options.debug;
+
+
+    if (expr == NULL)
+        expr = command;
+
+    if (target_triple)
+    {
+        ClangExpressionDeclMap expr_decl_map(&exe_ctx);
+
+        ClangExpression clang_expr(target_triple.AsCString(), &expr_decl_map);        
+        
+        unsigned num_errors = clang_expr.ParseExpression (expr, result.GetErrorStream());
+
+        if (num_errors == 0)
+        {
+            StreamString dwarf_opcodes;
+            dwarf_opcodes.SetByteOrder(eByteOrderHost);
+            dwarf_opcodes.GetFlags().Set(Stream::eBinary);
+            ClangExpressionVariableList expr_local_vars;
+            clang_expr.ConvertExpressionToDWARF (expr_local_vars, dwarf_opcodes);
+
+            result.SetStatus (eReturnStatusSuccessFinishResult);
+
+            DataExtractor dwarf_opcodes_data(dwarf_opcodes.GetData(), dwarf_opcodes.GetSize(), eByteOrderHost, 8);
+            DWARFExpression expr(dwarf_opcodes_data, 0, dwarf_opcodes_data.GetByteSize(), NULL);
+            expr.SetExpressionLocalVariableList(&expr_local_vars);
+            expr.SetExpressionDeclMap(&expr_decl_map);
+            if (debug)
+            {
+                output_stream << "Expression parsed ok, dwarf opcodes:";
+                output_stream.IndentMore();
+                expr.GetDescription(&output_stream, lldb::eDescriptionLevelVerbose);
+                output_stream.IndentLess();
+                output_stream.EOL();
+            }
+
+            clang::ASTContext *ast_context = clang_expr.GetASTContext();
+            Value expr_result;
+            Error expr_error;
+            bool expr_success = expr.Evaluate (&exe_ctx, ast_context, NULL, expr_result, &expr_error);
+            if (expr_success)
+            {
+                lldb::Format format = m_options.format;
+
+                // Resolve any values that are possible
+                expr_result.ResolveValue(&exe_ctx, ast_context);
+
+                if (expr_result.GetContextType() == Value::eContextTypeInvalid &&
+                    expr_result.GetValueType() == Value::eValueTypeScalar &&
+                    format == eFormatDefault)
+                {
+                    // The expression result is just a scalar with no special formatting
+                    expr_result.GetScalar().GetValue (&output_stream, show_types);
+                    output_stream.EOL();
+                }
+                else
+                {
+                    DataExtractor data;
+                    expr_error = expr_result.GetValueAsData (&exe_ctx, ast_context, data, 0);
+                    if (expr_error.Success())
+                    {
+                        if (format == eFormatDefault)
+                            format = expr_result.GetValueDefaultFormat ();
+
+                        void *clang_type = expr_result.GetValueOpaqueClangQualType();
+                        if (clang_type)
+                        {
+                            if (show_types)
+                                Type::DumpClangTypeName(&output_stream, clang_type);
+
+                            Type::DumpValue (
+                                &exe_ctx,                   // The execution context for memory and variable access
+                                ast_context,                // The ASTContext that the clang type belongs to
+                                clang_type,                 // The opaque clang type we want to dump that value of
+                                &output_stream,             // Stream to dump to
+                                format,                     // Format to use when dumping
+                                data,                       // A buffer containing the bytes for the clang type
+                                0,                          // Byte offset within "data" where value is
+                                data.GetByteSize(),         // Size in bytes of the value we are dumping
+                                0,                          // Bitfield bit size
+                                0,                          // Bitfield bit offset
+                                show_types,                 // Show types?
+                                show_summary,               // Show summary?
+                                debug,                      // Debug logging output?
+                                UINT32_MAX);                // Depth to dump in case this is an aggregate type
+                        }
+                        else
+                        {
+                            data.Dump(&output_stream,       // Stream to dump to
+                                      0,                    // Byte offset within "data"
+                                      format,               // Format to use when dumping
+                                      data.GetByteSize(),   // Size in bytes of each item we are dumping
+                                      1,                    // Number of items to dump
+                                      UINT32_MAX,           // Number of items per line
+                                      LLDB_INVALID_ADDRESS,   // Invalid address, don't show any offset/address context
+                                      0,                    // Bitfield bit size
+                                      0);                   // Bitfield bit offset
+                        }
+                        output_stream.EOL();
+                    }
+                    else
+                    {
+                        result.AppendError(expr_error.AsCString());
+                        result.SetStatus (eReturnStatusFailed);
+                    }
+                }
+            }
+            else
+            {
+                result.AppendError (expr_error.AsCString());
+                result.SetStatus (eReturnStatusFailed);
+            }
+        }
+        else
+        {
+            result.SetStatus (eReturnStatusFailed);
+        }
+    }
+    else
+    {
+        result.AppendError ("invalid target triple");
+        result.SetStatus (eReturnStatusFailed);
+    }
+    return result.Succeeded();
+}
+
+lldb::OptionDefinition
+CommandObjectExpression::CommandOptions::g_option_table[] =
+{
+{ 0, true,  "language",   'l', required_argument, NULL, 0, "[c|c++|objc|objc++]",          "Sets the language to use when parsing the expression."},
+{ 0, false, "format",     'f', required_argument, NULL, 0, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]",  "Specify the format that the expression output should use."},
+{ 0, false, "debug",      'g', no_argument,       NULL, 0, NULL,                           "Enable verbose debug logging of the expression parsing and evaluation."},
+{ 0, false, NULL, 0, 0, NULL, NULL, NULL, NULL }
+};
+
diff --git a/source/Commands/CommandObjectExpression.h b/source/Commands/CommandObjectExpression.h
new file mode 100644
index 0000000..c67ba74
--- /dev/null
+++ b/source/Commands/CommandObjectExpression.h
@@ -0,0 +1,105 @@
+//===-- CommandObjectExpression.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_CommandObjectExpression_h_
+#define liblldb_CommandObjectExpression_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Core/Language.h"
+#include "lldb/Target/ExecutionContext.h"
+
+namespace lldb_private {
+
+class CommandObjectExpression : public CommandObject
+{
+public:
+
+    class CommandOptions : public Options
+    {
+    public:
+
+        CommandOptions ();
+
+        virtual
+        ~CommandOptions ();
+
+        virtual Error
+        SetOptionValue (int option_idx, const char *option_arg);
+
+        void
+        ResetOptionValues ();
+
+        const lldb::OptionDefinition*
+        GetDefinitions ();
+
+        // Options table: Required for subclasses of Options.
+
+        static lldb::OptionDefinition g_option_table[];
+        Language  language;
+        lldb::Encoding  encoding;
+        lldb::Format    format;
+        bool        debug;
+        bool        show_types;
+        bool        show_summary;
+    };
+
+    CommandObjectExpression ();
+
+    virtual
+    ~CommandObjectExpression ();
+
+    virtual
+    Options *
+    GetOptions ();
+
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+    virtual bool
+    WantsRawCommandString() { return true; }
+
+    virtual bool
+    ExecuteRawCommandString (const char *command,
+                             CommandContext *context,
+                             CommandInterpreter *interpreter,
+                             CommandReturnObject &result);
+
+protected:
+
+    static size_t
+    MultiLineExpressionCallback (void *baton, 
+                                 InputReader *reader, 
+                                 lldb::InputReaderAction notification,
+                                 const char *bytes, 
+                                 size_t bytes_len);
+
+    bool
+    EvaluateExpression (const char *expr, 
+                        bool bare,
+                        Stream &output_stream, 
+                        Stream &error_stream);
+
+    CommandOptions m_options;
+    ExecutionContext m_exe_ctx;
+    uint32_t m_expr_line_count;
+    std::string m_expr_lines; // Multi-line expression support
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectExpression_h_
diff --git a/source/Commands/CommandObjectFile.cpp b/source/Commands/CommandObjectFile.cpp
new file mode 100644
index 0000000..01576c5
--- /dev/null
+++ b/source/Commands/CommandObjectFile.cpp
@@ -0,0 +1,170 @@
+//===-- CommandObjectFile.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectFile.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+CommandObjectFile::CommandOptions::CommandOptions() :
+    Options (),
+    m_arch ()  // Breakpoint info defaults to brief descriptions
+{
+    BuildValidOptionSets();
+}
+
+CommandObjectFile::CommandOptions::~CommandOptions ()
+{
+}
+
+lldb::OptionDefinition
+CommandObjectFile::CommandOptions::g_option_table[] =
+{
+    { 0, false, "arch", 'a', required_argument, NULL, 0, "<arch>", "Specify the architecture to launch."},
+    { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+const lldb::OptionDefinition *
+CommandObjectFile::CommandOptions::GetDefinitions ()
+{
+    return g_option_table;
+}
+
+Error
+CommandObjectFile::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
+{
+    Error error;
+    char short_option = (char) m_getopt_table[option_idx].val;
+
+    switch (short_option)
+    {
+        case 'a':
+            {
+                ArchSpec option_arch (option_arg);
+                if (option_arch.IsValid())
+                    m_arch = option_arch;
+                else
+                    error.SetErrorStringWithFormat ("Invalid arch string '%s'.\n", optarg);
+            }
+            break;
+
+        default:
+            error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
+            break;
+    }
+
+    return error;
+}
+
+void
+CommandObjectFile::CommandOptions::ResetOptionValues ()
+{
+    Options::ResetOptionValues();
+    m_arch.Clear();
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectFile
+//-------------------------------------------------------------------------
+
+CommandObjectFile::CommandObjectFile() :
+    CommandObject ("file",
+                   "Sets the file to be used as the main executable by the debugger.",
+                   "file [<cmd-options>] <filename>")
+{
+}
+
+CommandObjectFile::~CommandObjectFile ()
+{
+}
+
+Options *
+CommandObjectFile::GetOptions ()
+{
+    return &m_options;
+}
+
+bool
+CommandObjectFile::Execute
+(
+    Args& command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    const char *file_path = command.GetArgumentAtIndex(0);
+    Timer scoped_timer(__PRETTY_FUNCTION__, "(dbg) file '%s'", file_path);
+    const int argc = command.GetArgumentCount();
+    if (argc == 1)
+    {
+        FileSpec file_spec (file_path);
+
+        if (! file_spec.Exists())
+        {
+            result.AppendErrorWithFormat ("File '%s' does not exist.\n", file_path);
+            result.SetStatus (eReturnStatusFailed);
+            return result.Succeeded();
+        }
+
+        TargetSP target_sp;
+
+        ArchSpec arch;
+        if (m_options.m_arch.IsValid())
+            arch = m_options.m_arch;
+        else
+        {
+            arch = lldb_private::GetDefaultArchitecture ();
+            if (!arch.IsValid())
+                arch = LLDB_ARCH_DEFAULT;
+        }
+
+        Error error = Debugger::GetSharedInstance().GetTargetList().CreateTarget (file_spec, arch, NULL, true, target_sp);
+
+        if (error.Fail() && !m_options.m_arch.IsValid())
+        {
+            if (arch == LLDB_ARCH_DEFAULT_32BIT)
+                arch = LLDB_ARCH_DEFAULT_64BIT;
+            else
+                arch = LLDB_ARCH_DEFAULT_32BIT;
+            error = Debugger::GetSharedInstance().GetTargetList().CreateTarget (file_spec, arch, NULL, true, target_sp);
+        }
+
+        if (target_sp)
+        {
+            Debugger::GetSharedInstance().GetTargetList().SetCurrentTarget(target_sp.get());
+            result.AppendMessageWithFormat ("Current executable set to '%s' (%s).\n", file_path, arch.AsCString());
+            result.SetStatus (eReturnStatusSuccessFinishNoResult);
+        }
+        else
+        {
+            result.AppendError(error.AsCString());
+            result.SetStatus (eReturnStatusFailed);
+        }
+    }
+    else
+    {
+        result.AppendErrorWithFormat("'%s' takes exactly one executable path argument.\n", m_cmd_name.c_str());
+        result.SetStatus (eReturnStatusFailed);
+    }
+    return result.Succeeded();
+
+}
diff --git a/source/Commands/CommandObjectFile.h b/source/Commands/CommandObjectFile.h
new file mode 100644
index 0000000..c44f610
--- /dev/null
+++ b/source/Commands/CommandObjectFile.h
@@ -0,0 +1,79 @@
+//===-- CommandObjectFile.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_CommandObjectFile_h_
+#define liblldb_CommandObjectFile_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Options.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectFile
+//-------------------------------------------------------------------------
+
+class CommandObjectFile : public CommandObject
+{
+public:
+
+    CommandObjectFile ();
+
+    virtual
+    ~CommandObjectFile ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+    virtual Options *
+    GetOptions ();
+
+    class CommandOptions : public Options
+    {
+    public:
+
+        CommandOptions ();
+
+        virtual
+        ~CommandOptions ();
+
+        virtual Error
+        SetOptionValue (int option_idx, const char *option_arg);
+
+        void
+        ResetOptionValues ();
+
+        const lldb::OptionDefinition*
+        GetDefinitions ();
+
+        // Options table: Required for subclasses of Options.
+
+        static lldb::OptionDefinition g_option_table[];
+
+        // Instance variables to hold the values for command options.
+
+        ArchSpec m_arch;
+    };
+
+private:
+    CommandOptions m_options;
+
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectFile_h_
diff --git a/source/Commands/CommandObjectFrame.cpp b/source/Commands/CommandObjectFrame.cpp
new file mode 100644
index 0000000..78682dc
--- /dev/null
+++ b/source/Commands/CommandObjectFrame.cpp
@@ -0,0 +1,171 @@
+//===-- CommandObjectFrame.cpp ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectFrame.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Thread.h"
+
+#include "CommandObjectThread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+#pragma mark CommandObjectFrameInfo
+
+//-------------------------------------------------------------------------
+// CommandObjectFrameInfo
+//-------------------------------------------------------------------------
+
+class CommandObjectFrameInfo : public CommandObject
+{
+public:
+
+    CommandObjectFrameInfo () :
+    CommandObject ("frame info",
+                   "Lists information about the currently selected frame in the current thread.",
+                   "frame info",
+                   eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
+    {
+    }
+
+    ~CommandObjectFrameInfo ()
+    {
+    }
+
+    bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        ExecutionContext exe_ctx(context->GetExecutionContext());
+        if (exe_ctx.frame)
+        {
+            exe_ctx.frame->Dump (&result.GetOutputStream(), true);
+            result.GetOutputStream().EOL();
+            result.SetStatus (eReturnStatusSuccessFinishResult);
+        }
+        else
+        {
+            result.AppendError ("no current frame");
+            result.SetStatus (eReturnStatusFailed);
+        }
+        return result.Succeeded();
+    }
+};
+
+#pragma mark CommandObjectFrameSelect
+
+//-------------------------------------------------------------------------
+// CommandObjectFrameSelect
+//-------------------------------------------------------------------------
+
+class CommandObjectFrameSelect : public CommandObject
+{
+public:
+
+    CommandObjectFrameSelect () :
+    CommandObject ("frame select",
+                   "Select the current frame by index in the current thread.",
+                   "frame select <frame-index>",
+                   eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
+    {
+    }
+
+    ~CommandObjectFrameSelect ()
+    {
+    }
+
+    bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        ExecutionContext exe_ctx (context->GetExecutionContext());
+        if (exe_ctx.thread)
+        {
+            if (command.GetArgumentCount() == 1)
+            {
+                const char *frame_idx_cstr = command.GetArgumentAtIndex(0);
+
+                const uint32_t num_frames = exe_ctx.thread->GetStackFrameCount();
+                const uint32_t frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0);
+                if (frame_idx < num_frames)
+                {
+                    exe_ctx.thread->SetCurrentFrameByIndex (frame_idx);
+                    exe_ctx.frame = exe_ctx.thread->GetCurrentFrame ().get();
+
+                    if (exe_ctx.frame)
+                    {
+                        if (DisplayFrameForExecutionContext (exe_ctx.thread,
+                                                             exe_ctx.frame,
+                                                             interpreter,
+                                                             result.GetOutputStream(),
+                                                             true,
+                                                             true,
+                                                             3,
+                                                             3))
+                        {
+                            result.SetStatus (eReturnStatusSuccessFinishResult);
+                            return result.Succeeded();
+                        }
+                    }
+                }
+                if (frame_idx == UINT32_MAX)
+                    result.AppendErrorWithFormat ("Invalid frame index: %s.\n", frame_idx_cstr);
+                else
+                    result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx);
+            }
+            else
+            {
+                result.AppendError ("invalid arguments");
+                result.AppendErrorWithFormat ("Usage: %s\n", m_cmd_syntax.c_str());
+            }
+        }
+        else
+        {
+            result.AppendError ("no current thread");
+        }
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+};
+
+#pragma mark CommandObjectMultiwordFrame
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordFrame
+//-------------------------------------------------------------------------
+
+CommandObjectMultiwordFrame::CommandObjectMultiwordFrame (CommandInterpreter *interpreter) :
+    CommandObjectMultiword ("frame",
+                            "A set of commands for operating on the current thread's frames.",
+                            "frame <subcommand> [<subcommand-options>]")
+{
+    LoadSubCommand (CommandObjectSP (new CommandObjectFrameInfo ()), "info", interpreter);
+    LoadSubCommand (CommandObjectSP (new CommandObjectFrameSelect ()), "select", interpreter);
+}
+
+CommandObjectMultiwordFrame::~CommandObjectMultiwordFrame ()
+{
+}
+
diff --git a/source/Commands/CommandObjectFrame.h b/source/Commands/CommandObjectFrame.h
new file mode 100644
index 0000000..cb9cafe
--- /dev/null
+++ b/source/Commands/CommandObjectFrame.h
@@ -0,0 +1,40 @@
+//===-- CommandObjectFrame.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_CommandObjectFrame_h_
+#define liblldb_CommandObjectFrame_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Options.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordFrame
+//-------------------------------------------------------------------------
+
+class CommandObjectMultiwordFrame : public CommandObjectMultiword
+{
+public:
+
+    CommandObjectMultiwordFrame (CommandInterpreter *interpreter);
+
+    virtual
+    ~CommandObjectMultiwordFrame ();
+
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectFrame_h_
diff --git a/source/Commands/CommandObjectHelp.cpp b/source/Commands/CommandObjectHelp.cpp
new file mode 100644
index 0000000..35e5b2e
--- /dev/null
+++ b/source/Commands/CommandObjectHelp.cpp
@@ -0,0 +1,266 @@
+//===-- CommandObjectHelp.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectHelp.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectHelp
+//-------------------------------------------------------------------------
+
+CommandObjectHelp::CommandObjectHelp () :
+    CommandObject ("help",
+                     "Shows a list of all debugger commands, or give details about specific commands.",
+                     "help [<cmd-name>]")
+{
+}
+
+CommandObjectHelp::~CommandObjectHelp()
+{
+}
+
+
+bool
+CommandObjectHelp::OldExecute
+(
+    Args& command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    CommandObject::CommandMap::iterator pos;
+    CommandObject *cmd_obj;
+
+    const int argc = command.GetArgumentCount();
+    if (argc > 0)
+    {
+        cmd_obj = interpreter->GetCommandObject (command.GetArgumentAtIndex(0), false, false);
+        if (cmd_obj == NULL)
+        {
+            cmd_obj = interpreter->GetCommandObject (command.GetArgumentAtIndex(0), true, false);
+            if (cmd_obj != NULL)
+            {
+                StreamString alias_help_str;
+                interpreter->GetAliasHelp (command.GetArgumentAtIndex(0), cmd_obj->GetCommandName(), alias_help_str);
+                result.AppendMessageWithFormat ("'%s' is an alias for %s.\n", command.GetArgumentAtIndex (0),
+                                               alias_help_str.GetData());
+            }
+        }
+
+        if (cmd_obj)
+        {
+            Stream &output_strm = result.GetOutputStream();
+            if (cmd_obj->GetOptions() != NULL)
+            {
+                const char * long_help = cmd_obj->GetHelpLong();
+                if ((long_help!= NULL)
+                    && strlen (long_help) > 0)
+                    output_strm.Printf ("\n%s", cmd_obj->GetHelpLong());
+                else
+                    output_strm.Printf ("\n%s\n", cmd_obj->GetHelp());
+                output_strm.Printf ("\nSyntax: %s\n", cmd_obj->GetSyntax());
+                cmd_obj->GetOptions()->GenerateOptionUsage (output_strm, cmd_obj);
+            }
+            else if (cmd_obj->IsMultiwordObject())
+            {
+                bool done = false;
+                if (argc > 1)
+                {
+                    CommandObject::CommandMap::iterator pos;
+                    std::string sub_command = command.GetArgumentAtIndex(1);
+                    pos = ((CommandObjectMultiword *) cmd_obj)->m_subcommand_dict.find(sub_command);
+                    if (pos != ((CommandObjectMultiword *) cmd_obj)->m_subcommand_dict.end())
+                    {
+                        CommandObject *sub_cmd_obj = pos->second.get();
+                        if (sub_cmd_obj->GetOptions() != NULL)
+                        {
+                            output_strm.Printf ("\n%s\n", sub_cmd_obj->GetHelp());
+                            output_strm.Printf ("\nSyntax: %s\n", sub_cmd_obj->GetSyntax());
+                            sub_cmd_obj->GetOptions()->GenerateOptionUsage (output_strm, sub_cmd_obj);
+                            done = true;
+                        }
+                        else
+                        {
+                            output_strm.Printf ("\n%s\n", sub_cmd_obj->GetHelp());
+                            output_strm.Printf ("\nSyntax: %s\n", sub_cmd_obj->GetSyntax());
+                            done = true;
+                        }
+                    }
+                }
+                if (!done)
+                {
+                    output_strm.Printf ("%s\n", cmd_obj->GetHelp());
+                    ((CommandObjectMultiword *) cmd_obj)->GenerateHelpText (result, interpreter);
+                }
+            }
+            else
+            {
+                const char *long_help = cmd_obj->GetHelpLong();
+                if ((long_help != NULL)
+                    && (strlen (long_help) > 0))
+                    output_strm.Printf ("\n%s", cmd_obj->GetHelpLong());
+                else
+                    output_strm.Printf ("\n%s\n", cmd_obj->GetHelp());
+                output_strm.Printf ("\nSyntax: %s\n", cmd_obj->GetSyntax());
+            }
+            result.SetStatus (eReturnStatusSuccessFinishNoResult);
+        }
+        else
+        {
+            result.AppendErrorWithFormat
+            ("'%s' is not a known command.\nTry 'help' to see a current list of commands.\n",
+             command.GetArgumentAtIndex(0));
+            result.SetStatus (eReturnStatusFailed);
+        }
+    }
+    else
+    {
+        result.SetStatus (eReturnStatusSuccessFinishNoResult);
+        interpreter->GetHelp(result);
+    }
+    return result.Succeeded();
+}
+
+bool
+CommandObjectHelp::Execute (Args &command, CommandContext *context, CommandInterpreter *interpreter, 
+                            CommandReturnObject &result)
+{
+    CommandObject::CommandMap::iterator pos;
+    CommandObject *cmd_obj;
+    const int argc = command.GetArgumentCount ();
+
+    // 'help' doesn't take any options or arguments, other than command names.  If argc is 0, we show the user
+    // all commands and aliases.  Otherwise every argument must be the name of a command or a sub-command.
+
+    if (argc == 0)
+    {
+        result.SetStatus (eReturnStatusSuccessFinishNoResult);
+        interpreter->GetHelp (result);  // General help, for ALL commands.
+    }
+    else
+    {
+        // Get command object for the first command argument. Only search built-in command dictionary.
+        cmd_obj = interpreter->GetCommandObject (command.GetArgumentAtIndex (0), false, false);
+        if (cmd_obj == NULL)
+          {
+            // That failed, so now search in the aliases dictionary, too.
+            cmd_obj = interpreter->GetCommandObject (command.GetArgumentAtIndex (0), true, false);
+          }
+
+        if (cmd_obj != NULL)
+        {
+            bool all_okay = true;
+            CommandObject *sub_cmd_obj = cmd_obj;
+            // Loop down through sub_command dictionaries until we find the command object that corresponds
+            // to the help command entered.
+            for (int i = 1; i < argc && all_okay; ++i)
+            {
+                std::string sub_command = command.GetArgumentAtIndex(i);
+                if (! sub_cmd_obj->IsMultiwordObject ())
+                {
+                    all_okay = false;
+                }
+                else
+                {
+                    pos = ((CommandObjectMultiword *) sub_cmd_obj)->m_subcommand_dict.find (sub_command);
+                    if (pos != ((CommandObjectMultiword *) sub_cmd_obj)->m_subcommand_dict.end())
+                      sub_cmd_obj = pos->second.get();
+                    else
+                      all_okay = false;
+                }
+            }
+
+            if (!all_okay || (sub_cmd_obj == NULL))
+            {
+                std::string cmd_string;
+                command.GetCommandString (cmd_string);
+                result.AppendErrorWithFormat
+                                      ("'%s' is not a known command.\nTry 'help' to see a current list of commands.\n",
+                                       cmd_string.c_str());
+                result.SetStatus (eReturnStatusFailed);
+            }
+            else
+            {
+                Stream &output_strm = result.GetOutputStream();
+                if (sub_cmd_obj->GetOptions() != NULL)
+                {
+                    output_strm.Printf ("%s\n", sub_cmd_obj->GetHelp());
+                    output_strm.Printf ("\nSyntax: %s\n", sub_cmd_obj->GetSyntax());
+                    sub_cmd_obj->GetOptions()->GenerateOptionUsage (output_strm, sub_cmd_obj);
+                    const char *long_help = sub_cmd_obj->GetHelpLong();
+                    if ((long_help != NULL)
+                        && (strlen (long_help) > 0))
+                      output_strm.Printf ("\n%s", long_help);
+                }
+                else if (sub_cmd_obj->IsMultiwordObject())
+                {
+                    output_strm.Printf ("%s\n", sub_cmd_obj->GetHelp());
+                    ((CommandObjectMultiword *) sub_cmd_obj)->GenerateHelpText (result, interpreter);
+                }
+                else
+                {
+                  const char *long_help = sub_cmd_obj->GetHelpLong();
+                  if ((long_help != NULL)
+                      && (strlen (long_help) > 0))
+                    output_strm.Printf ("%s", long_help);
+                  else
+                    output_strm.Printf ("%s\n", sub_cmd_obj->GetHelp());
+                  output_strm.Printf ("\nSyntax: %s\n", sub_cmd_obj->GetSyntax());
+                }
+            }
+        }
+        else
+        {
+            result.AppendErrorWithFormat 
+                                      ("'%s' is not a known command.\nTry 'help' to see a current list of commands.\n",
+                                       command.GetArgumentAtIndex(0));
+            result.SetStatus (eReturnStatusFailed);
+        }
+    }
+
+    return result.Succeeded();
+}
+
+int
+CommandObjectHelp::HandleCompletion
+(
+    Args &input,
+    int &cursor_index,
+    int &cursor_char_position,
+    int match_start_point,
+    int max_return_elements,
+    CommandInterpreter *interpreter,
+    StringList &matches
+)
+{
+    // Return the completions of the commands in the help system:
+    if (cursor_index == 0)
+    {
+        return interpreter->HandleCompletionMatches(input, cursor_index, cursor_char_position, match_start_point, max_return_elements, matches);
+    }
+    else
+    {
+        CommandObject *cmd_obj = interpreter->GetCommandObject (input.GetArgumentAtIndex(0), true, false);
+        input.Shift();
+        cursor_index--;
+        return cmd_obj->HandleCompletion (input, cursor_index, cursor_char_position, match_start_point, max_return_elements, interpreter, matches);
+    }
+}
diff --git a/source/Commands/CommandObjectHelp.h b/source/Commands/CommandObjectHelp.h
new file mode 100644
index 0000000..a8084aa
--- /dev/null
+++ b/source/Commands/CommandObjectHelp.h
@@ -0,0 +1,59 @@
+//===-- CommandObjectHelp.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_CommandObjectHelp_h_
+#define liblldb_CommandObjectHelp_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectHelp
+//-------------------------------------------------------------------------
+
+class CommandObjectHelp : public CommandObject
+{
+public:
+
+    CommandObjectHelp ();
+
+    virtual
+    ~CommandObjectHelp ();
+
+    bool
+    OldExecute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+    
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+    virtual int
+    HandleCompletion (Args &input,
+                      int &cursor_index,
+                      int &cursor_char_position,
+                      int match_start_point,
+                      int max_return_elements,
+                      CommandInterpreter *interpreter,
+                      StringList &matches);
+
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectHelp_h_
diff --git a/source/Commands/CommandObjectImage.cpp b/source/Commands/CommandObjectImage.cpp
new file mode 100644
index 0000000..ab728e9
--- /dev/null
+++ b/source/Commands/CommandObjectImage.cpp
@@ -0,0 +1,1419 @@
+//===-- CommandObjectImage.cpp ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectImage.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Symbol/LineTable.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Interpreter/CommandCompletions.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Static Helper functions
+//----------------------------------------------------------------------
+static void
+DumpModuleArchitecture (Stream &strm, Module *module, uint32_t width)
+{
+    if (module)
+    {
+        if (width)
+            strm.Printf("%-*s", width, module->GetArchitecture().AsCString());
+        else
+            strm.PutCString(module->GetArchitecture().AsCString());
+    }
+}
+
+static void
+DumpModuleUUID (Stream &strm, Module *module)
+{
+    module->GetUUID().Dump (&strm);
+}
+
+static uint32_t
+DumpCompileUnitLineTable
+(
+    CommandContext *context,
+    Stream &strm,
+    Module *module,
+    const FileSpec &file_spec,
+    bool load_addresses
+)
+{
+    uint32_t num_matches = 0;
+    if (module)
+    {
+        SymbolContextList sc_list;
+        num_matches = module->ResolveSymbolContextsForFileSpec (file_spec,
+                                                                0,
+                                                                false,
+                                                                eSymbolContextCompUnit,
+                                                                sc_list);
+        
+        for (uint32_t i=0; i<num_matches; ++i)
+        {
+            SymbolContext sc;
+            if (sc_list.GetContextAtIndex(i, sc))
+            {
+                if (i > 0)
+                    strm << "\n\n";
+
+                strm << "Line table for " << *dynamic_cast<FileSpec*> (sc.comp_unit) << " in `"
+                     << module->GetFileSpec().GetFilename() << "\n";
+                LineTable *line_table = sc.comp_unit->GetLineTable();
+                if (line_table)
+                    line_table->GetDescription (&strm, context->GetExecutionContext().process, lldb::eDescriptionLevelBrief);
+                else
+                    strm << "No line table";
+            }
+        }
+    }
+    return num_matches;
+}
+
+static void
+DumpFullpath (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width)
+{
+    if (file_spec_ptr)
+    {
+        if (width > 0)
+        {
+            char fullpath[PATH_MAX];
+            if (file_spec_ptr->GetPath(fullpath, sizeof(fullpath)))
+            {
+                strm.Printf("%-*s", width, fullpath);
+                return;
+            }
+        }
+        else
+        {
+            file_spec_ptr->Dump(&strm);
+            return;
+        }
+    }
+    // Keep the width spacing correct if things go wrong...
+    if (width > 0)
+        strm.Printf("%-*s", width, "");
+}
+
+static void
+DumpDirectory (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width)
+{
+    if (file_spec_ptr)
+    {
+        if (width > 0)
+            strm.Printf("%-*s", width, file_spec_ptr->GetDirectory().AsCString(""));
+        else
+            file_spec_ptr->GetDirectory().Dump(&strm);
+        return;
+    }
+    // Keep the width spacing correct if things go wrong...
+    if (width > 0)
+        strm.Printf("%-*s", width, "");
+}
+
+static void
+DumpBasename (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width)
+{
+    if (file_spec_ptr)
+    {
+        if (width > 0)
+            strm.Printf("%-*s", width, file_spec_ptr->GetFilename().AsCString(""));
+        else
+            file_spec_ptr->GetFilename().Dump(&strm);
+        return;
+    }
+    // Keep the width spacing correct if things go wrong...
+    if (width > 0)
+        strm.Printf("%-*s", width, "");
+}
+
+
+static void
+DumpModuleSymtab (CommandContext *context, Stream &strm, Module *module)
+{
+    if (module)
+    {
+        ObjectFile *objfile = module->GetObjectFile ();
+        if (objfile)
+        {
+            Symtab *symtab = objfile->GetSymtab();
+            if (symtab)
+                symtab->Dump(&strm, context->GetExecutionContext().process);
+        }
+    }
+}
+
+static void
+DumpModuleSections (CommandContext *context, Stream &strm, Module *module)
+{
+    if (module)
+    {
+        ObjectFile *objfile = module->GetObjectFile ();
+        if (objfile)
+        {
+            SectionList *section_list = objfile->GetSectionList();
+            if (section_list)
+                section_list->Dump(&strm, context->GetExecutionContext().process, true);
+        }
+    }
+}
+
+static bool
+DumpModuleSymbolVendor (Stream &strm, Module *module)
+{
+    if (module)
+    {
+        SymbolVendor *symbol_vendor = module->GetSymbolVendor(true);
+        if (symbol_vendor)
+        {
+            symbol_vendor->Dump(&strm);
+            return true;
+        }
+    }
+    return false;
+}
+
+static bool
+LookupAddressInModule (CommandContext *context, Stream &strm, Module *module, uint32_t resolve_mask, lldb::addr_t raw_addr, lldb::addr_t offset)
+{
+    if (module)
+    {
+        lldb::addr_t addr = raw_addr - offset;
+        Address so_addr;
+        SymbolContext sc;
+        Process *process = context->GetExecutionContext().process;
+        if (process && process->IsAlive())
+        {
+            if (!process->ResolveLoadAddress (addr, so_addr))
+                return false;
+            else if (so_addr.GetModule() != module)
+                return false;
+        }
+        else
+        {
+            if (!module->ResolveFileAddress (addr, so_addr))
+                return false;
+        }
+
+        // If an offset was given, print out the address we ended up looking up
+        if (offset)
+            strm.Printf("0x%llx: ", addr);
+
+        ExecutionContextScope *exe_scope = context->GetExecutionContext().GetBestExecutionContextScope();
+        if (so_addr.Dump (&strm, exe_scope, Address::DumpStyleSectionNameOffset))
+            strm.PutCString(": ");
+        so_addr.Dump (&strm, exe_scope, Address::DumpStyleResolvedDescription);
+        return true;
+    }
+
+    return false;
+}
+
+static uint32_t
+LookupSymbolInModule (CommandContext *context, Stream &strm, Module *module, const char *name, bool name_is_regex)
+{
+    if (module)
+    {
+        SymbolContext sc;
+
+        ObjectFile *objfile = module->GetObjectFile ();
+        if (objfile)
+        {
+            Symtab *symtab = objfile->GetSymtab();
+            if (symtab)
+            {
+                uint32_t i;
+                std::vector<uint32_t> match_indexes;
+                ConstString symbol_name (name);
+                uint32_t num_matches = 0;
+                if (name_is_regex)
+                {
+                    RegularExpression name_regexp(name);
+                    num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType (name_regexp, eSymbolTypeAny,
+                                                                                   match_indexes);
+                }
+                else
+                {
+                    num_matches = symtab->AppendSymbolIndexesWithName (symbol_name, match_indexes);
+                }
+
+
+                if (num_matches > 0)
+                {
+                    strm.Indent ();
+                    strm.Printf("%u symbols match %s'%s' in ", num_matches,
+                                name_is_regex ? "the regular expression " : "", name);
+                    DumpFullpath (strm, &module->GetFileSpec(), 0);
+                    strm.PutCString(":\n");
+                    strm.IndentMore ();
+                    Symtab::DumpSymbolHeader (&strm);
+                    for (i=0; i < num_matches; ++i)
+                    {
+                        Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]);
+                        strm.Indent ();
+                        symbol->Dump (&strm, context->GetExecutionContext().process, i);
+                    }
+                    strm.IndentLess ();
+                    return num_matches;
+                }
+            }
+        }
+    }
+    return 0;
+}
+
+
+static void
+DumpSymbolContextList (CommandContext *context, Stream &strm, SymbolContextList &sc_list, bool prepend_addr)
+{
+    strm.IndentMore ();
+    uint32_t i;
+    const uint32_t num_matches = sc_list.GetSize();
+
+    for (i=0; i<num_matches; ++i)
+    {
+        SymbolContext sc;
+        if (sc_list.GetContextAtIndex(i, sc))
+        {
+            strm.Indent();
+            if (prepend_addr)
+            {
+                if (sc.line_entry.range.GetBaseAddress().IsValid())
+                {
+                    lldb::addr_t vm_addr =
+                                      sc.line_entry.range.GetBaseAddress().GetLoadAddress(context->GetExecutionContext().process);
+                    int addr_size = sizeof (addr_t);
+                    Process *process = context->GetExecutionContext().process;
+                    if (process)
+                        addr_size = process->GetAddressByteSize();
+                    if (vm_addr != LLDB_INVALID_ADDRESS)
+                        strm.Address (vm_addr, addr_size);
+                    else
+                        sc.line_entry.range.GetBaseAddress().Dump (&strm, NULL, Address::DumpStyleSectionNameOffset);
+
+                    strm.PutCString(" in ");
+                }
+            }
+            sc.DumpStopContext(&strm, context->GetExecutionContext().process, sc.line_entry.range.GetBaseAddress());
+        }
+    }
+    strm.IndentLess ();
+}
+
+static uint32_t
+LookupFunctionInModule (CommandContext *context, Stream &strm, Module *module, const char *name, bool name_is_regex)
+{
+    if (module && name && name[0])
+    {
+        SymbolContextList sc_list;
+
+        SymbolVendor *symbol_vendor = module->GetSymbolVendor();
+        if (symbol_vendor)
+        {
+            uint32_t num_matches = 0;
+            if (name_is_regex)
+            {
+                RegularExpression function_name_regex (name);
+                num_matches = symbol_vendor->FindFunctions(function_name_regex, true, sc_list);
+
+            }
+            else
+            {
+                ConstString function_name(name);
+                num_matches = symbol_vendor->FindFunctions(function_name, true, sc_list);
+            }
+
+            if (num_matches)
+            {
+                strm.Indent ();
+                strm.Printf("%u match%s found in ", num_matches, num_matches > 1 ? "es" : "");
+                DumpFullpath (strm, &module->GetFileSpec(), 0);
+                strm.PutCString(":\n");
+                DumpSymbolContextList (context, strm, sc_list, true);
+            }
+            return num_matches;
+        }
+    }
+    return 0;
+}
+
+static uint32_t
+LookupFileAndLineInModule (CommandContext *context, Stream &strm, Module *module, const FileSpec &file_spec, uint32_t line, bool check_inlines)
+{
+    if (module && file_spec)
+    {
+        SymbolContextList sc_list;
+        const uint32_t num_matches = module->ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines,
+                                                                             eSymbolContextEverything, sc_list);
+        if (num_matches > 0)
+        {
+            strm.Indent ();
+            strm.Printf("%u match%s found in ", num_matches, num_matches > 1 ? "es" : "");
+            strm << file_spec;
+            if (line > 0)
+                strm.Printf (":%u", line);
+            strm << " in ";
+            DumpFullpath (strm, &module->GetFileSpec(), 0);
+            strm.PutCString(":\n");
+            DumpSymbolContextList (context, strm, sc_list, true);
+            return num_matches;
+        }
+    }
+    return 0;
+
+}
+
+
+//----------------------------------------------------------------------
+// Image symbol table dumping command
+//----------------------------------------------------------------------
+
+class CommandObjectImageDumpModuleList : public CommandObject
+{
+public:
+
+    CommandObjectImageDumpModuleList (const char *name,
+                   const char *help,
+                   const char *syntax) :
+        CommandObject (name, help, syntax)
+    {
+    }
+
+    virtual
+    ~CommandObjectImageDumpModuleList ()
+    {
+    }
+
+    virtual int
+    HandleArgumentCompletion (Args &input,
+                      int &cursor_index,
+                      int &cursor_char_position,
+                      OptionElementVector &opt_element_vector,
+                      int match_start_point,
+                      int max_return_elements,
+                      CommandInterpreter *interpreter,
+                      StringList &matches)
+    {
+        // Arguments are the standard module completer.
+        std::string completion_str (input.GetArgumentAtIndex(cursor_index));
+        completion_str.erase (cursor_char_position);
+
+        CommandCompletions::InvokeCommonCompletionCallbacks (CommandCompletions::eModuleCompletion,
+                                         completion_str.c_str(),
+                                         match_start_point,
+                                         max_return_elements,
+                                         interpreter,
+                                         NULL,
+                                         matches);
+        return matches.GetSize();
+    }
+};
+
+class CommandObjectImageDumpSourceFileList : public CommandObject
+{
+public:
+
+    CommandObjectImageDumpSourceFileList (const char *name,
+                   const char *help,
+                   const char *syntax) :
+        CommandObject (name, help, syntax)
+    {
+    }
+
+    virtual
+    ~CommandObjectImageDumpSourceFileList ()
+    {
+    }
+
+    virtual int
+    HandleArgumentCompletion (Args &input,
+                      int &cursor_index,
+                      int &cursor_char_position,
+                      OptionElementVector &opt_element_vector,
+                      int match_start_point,
+                      int max_return_elements,
+                      CommandInterpreter *interpreter,
+                      StringList &matches)
+    {
+        // Arguments are the standard source file completer.
+        std::string completion_str (input.GetArgumentAtIndex(cursor_index));
+        completion_str.erase (cursor_char_position);
+
+        CommandCompletions::InvokeCommonCompletionCallbacks (CommandCompletions::eSourceFileCompletion,
+                                         completion_str.c_str(),
+                                         match_start_point,
+                                         max_return_elements,
+                                         interpreter,
+                                         NULL,
+                                         matches);
+        return matches.GetSize();
+    }
+};
+
+
+class CommandObjectImageDumpSymtab : public CommandObjectImageDumpModuleList
+{
+public:
+    CommandObjectImageDumpSymtab () :
+        CommandObjectImageDumpModuleList ("image dump symtab",
+                         "Dump the symbol table from one or more executable images.",
+                         "image dump symtab [<file1> ...]")
+    {
+    }
+
+    virtual
+    ~CommandObjectImageDumpSymtab ()
+    {
+    }
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        Target *target = context->GetTarget();
+        if (target == NULL)
+        {
+            result.AppendError ("invalid target, set executable file using 'file' command");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+        else
+        {
+            uint32_t num_dumped = 0;
+
+            uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
+            result.GetOutputStream().SetAddressByteSize(addr_byte_size);
+            result.GetErrorStream().SetAddressByteSize(addr_byte_size);
+
+            if (command.GetArgumentCount() == 0)
+            {
+                // Dump all sections for all modules images
+                const uint32_t num_modules = target->GetImages().GetSize();
+                if (num_modules > 0)
+                {
+                    result.GetOutputStream().Printf("Dumping symbol table for %u modules.\n", num_modules);
+                    for (uint32_t image_idx = 0;  image_idx<num_modules; ++image_idx)
+                    {
+                        num_dumped++;
+                        DumpModuleSymtab (context, result.GetOutputStream(), target->GetImages().GetModulePointerAtIndex(image_idx));
+                    }
+                }
+                else
+                {
+                    result.AppendError ("the target has no associated executable images");
+                    result.SetStatus (eReturnStatusFailed);
+                    return false;
+                }
+            }
+            else
+            {
+                // Dump specified images (by basename or fullpath)
+                const char *arg_cstr;
+                for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
+                {
+                    FileSpec image_file(arg_cstr);
+                    ModuleList matching_modules;
+                    const size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules);
+
+                    if (num_matching_modules > 0)
+                    {
+                        for (size_t i=0; i<num_matching_modules; ++i)
+                        {
+                            Module *image_module = matching_modules.GetModulePointerAtIndex(i);
+                            if (image_module)
+                            {
+                                num_dumped++;
+                                DumpModuleSymtab (context, result.GetOutputStream(), image_module);
+                            }
+                        }
+                    }
+                    else
+                        result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
+                }
+            }
+
+            if (num_dumped > 0)
+                result.SetStatus (eReturnStatusSuccessFinishResult);
+            else
+            {
+                result.AppendError ("no matching executable images found");
+                result.SetStatus (eReturnStatusFailed);
+            }
+        }
+        return result.Succeeded();
+    }
+
+};
+
+//----------------------------------------------------------------------
+// Image section dumping command
+//----------------------------------------------------------------------
+class CommandObjectImageDumpSections : public CommandObjectImageDumpModuleList
+{
+public:
+    CommandObjectImageDumpSections () :
+        CommandObjectImageDumpModuleList (
+                "image dump sections",
+                "Dump the sections from one or more executable images.",
+                "image dump sections [<file1> ...]")
+    {
+    }
+
+    virtual
+    ~CommandObjectImageDumpSections ()
+    {
+    }
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        Target *target = context->GetTarget();
+        if (target == NULL)
+        {
+            result.AppendError ("invalid target, set executable file using 'file' command");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+        else
+        {
+            uint32_t num_dumped = 0;
+
+            uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
+            result.GetOutputStream().SetAddressByteSize(addr_byte_size);
+            result.GetErrorStream().SetAddressByteSize(addr_byte_size);
+
+            if (command.GetArgumentCount() == 0)
+            {
+                // Dump all sections for all modules images
+                const uint32_t num_modules = target->GetImages().GetSize();
+                if (num_modules > 0)
+                {
+                    result.GetOutputStream().Printf("Dumping sections for %u modules.\n", num_modules);
+                    for (uint32_t image_idx = 0;  image_idx<num_modules; ++image_idx)
+                    {
+                        num_dumped++;
+                        DumpModuleSections (context, result.GetOutputStream(), target->GetImages().GetModulePointerAtIndex(image_idx));
+                    }
+                }
+                else
+                {
+                    result.AppendError ("the target has no associated executable images");
+                    result.SetStatus (eReturnStatusFailed);
+                    return false;
+                }
+            }
+            else
+            {
+                // Dump specified images (by basename or fullpath)
+                const char *arg_cstr;
+                for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
+                {
+                    FileSpec image_file(arg_cstr);
+                    ModuleList matching_modules;
+                    const size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules);
+
+                    if (num_matching_modules > 0)
+                    {
+                        for (size_t i=0; i<num_matching_modules; ++i)
+                        {
+                            Module * image_module = matching_modules.GetModulePointerAtIndex(i);
+                            if (image_module)
+                            {
+                                num_dumped++;
+                                DumpModuleSections (context, result.GetOutputStream(), image_module);
+                            }
+                        }
+                    }
+                    else
+                        result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
+                }
+            }
+
+            if (num_dumped > 0)
+                result.SetStatus (eReturnStatusSuccessFinishResult);
+            else
+            {
+                result.AppendError ("no matching executable images found");
+                result.SetStatus (eReturnStatusFailed);
+            }
+        }
+        return result.Succeeded();
+    }
+};
+
+//----------------------------------------------------------------------
+// Image debug symbol dumping command
+//----------------------------------------------------------------------
+class CommandObjectImageDumpSymfile : public CommandObjectImageDumpModuleList
+{
+public:
+    CommandObjectImageDumpSymfile () :
+        CommandObjectImageDumpModuleList ("image dump symfile",
+                         "Dump the debug symbol file for one or more executable images.",
+                         "image dump symfile [<file1> ...]")
+    {
+    }
+
+    virtual
+    ~CommandObjectImageDumpSymfile ()
+    {
+    }
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        Target *target = context->GetTarget();
+        if (target == NULL)
+        {
+            result.AppendError ("invalid target, set executable file using 'file' command");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+        else
+        {
+            uint32_t num_dumped = 0;
+
+            uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
+            result.GetOutputStream().SetAddressByteSize(addr_byte_size);
+            result.GetErrorStream().SetAddressByteSize(addr_byte_size);
+
+            if (command.GetArgumentCount() == 0)
+            {
+                // Dump all sections for all modules images
+                const uint32_t num_modules = target->GetImages().GetSize();
+                if (num_modules > 0)
+                {
+                    result.GetOutputStream().Printf("Dumping debug symbols for %u modules.\n", num_modules);
+                    for (uint32_t image_idx = 0;  image_idx<num_modules; ++image_idx)
+                    {
+                        if (DumpModuleSymbolVendor (result.GetOutputStream(), target->GetImages().GetModulePointerAtIndex(image_idx)))
+                            num_dumped++;
+                    }
+                }
+                else
+                {
+                    result.AppendError ("the target has no associated executable images");
+                    result.SetStatus (eReturnStatusFailed);
+                    return false;
+                }
+            }
+            else
+            {
+                // Dump specified images (by basename or fullpath)
+                const char *arg_cstr;
+                for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
+                {
+                    FileSpec image_file(arg_cstr);
+                    ModuleList matching_modules;
+                    const size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules);
+
+                    if (num_matching_modules > 0)
+                    {
+                        for (size_t i=0; i<num_matching_modules; ++i)
+                        {
+                            Module * image_module = matching_modules.GetModulePointerAtIndex(i);
+                            if (image_module)
+                            {
+                                if (DumpModuleSymbolVendor (result.GetOutputStream(), image_module))
+                                    num_dumped++;
+                            }
+                        }
+                    }
+                    else
+                        result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
+                }
+            }
+
+            if (num_dumped > 0)
+                result.SetStatus (eReturnStatusSuccessFinishResult);
+            else
+            {
+                result.AppendError ("no matching executable images found");
+                result.SetStatus (eReturnStatusFailed);
+            }
+        }
+        return result.Succeeded();
+    }
+};
+
+//----------------------------------------------------------------------
+// Image debug symbol dumping command
+//----------------------------------------------------------------------
+class CommandObjectImageDumpLineTable : public CommandObjectImageDumpSourceFileList
+{
+public:
+    CommandObjectImageDumpLineTable () :
+        CommandObjectImageDumpSourceFileList ("image dump line-table",
+                         "Dump the debug symbol file for one or more executable images.",
+                         "image dump line-table <file1> [<file2> ...]")
+    {
+    }
+
+    virtual
+    ~CommandObjectImageDumpLineTable ()
+    {
+    }
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        Target *target = context->GetTarget();
+        if (target == NULL)
+        {
+            result.AppendError ("invalid target, set executable file using 'file' command");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+        else
+        {
+            ExecutionContext exe_ctx(context->GetExecutionContext());
+            uint32_t total_num_dumped = 0;
+
+            uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
+            result.GetOutputStream().SetAddressByteSize(addr_byte_size);
+            result.GetErrorStream().SetAddressByteSize(addr_byte_size);
+
+            if (command.GetArgumentCount() == 0)
+            {
+                result.AppendErrorWithFormat ("\nSyntax: %s\n", m_cmd_syntax.c_str());
+                result.SetStatus (eReturnStatusFailed);
+            }
+            else
+            {
+                // Dump specified images (by basename or fullpath)
+                const char *arg_cstr;
+                for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
+                {
+                    FileSpec file_spec(arg_cstr);
+                    const uint32_t num_modules = target->GetImages().GetSize();
+                    if (num_modules > 0)
+                    {
+                        uint32_t num_dumped = 0;
+                        for (uint32_t i = 0; i<num_modules; ++i)
+                        {
+                            if (DumpCompileUnitLineTable (context,
+                                                          result.GetOutputStream(),
+                                                          target->GetImages().GetModulePointerAtIndex(i),
+                                                          file_spec,
+                                                          exe_ctx.process != NULL && exe_ctx.process->IsAlive()))
+                                num_dumped++;
+                        }
+                        if (num_dumped == 0)
+                            result.AppendWarningWithFormat ("No source filenames matched '%s'.\n", arg_cstr);
+                        else
+                            total_num_dumped += num_dumped;
+                    }
+                }
+            }
+
+            if (total_num_dumped > 0)
+                result.SetStatus (eReturnStatusSuccessFinishResult);
+            else
+            {
+                result.AppendError ("no source filenames matched any command arguments");
+                result.SetStatus (eReturnStatusFailed);
+            }
+        }
+        return result.Succeeded();
+    }
+};
+
+//----------------------------------------------------------------------
+// Dump multi-word command
+//----------------------------------------------------------------------
+class CommandObjectImageDump : public CommandObjectMultiword
+{
+public:
+
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    CommandObjectImageDump(CommandInterpreter *interpreter) :
+        CommandObjectMultiword ("image dump",
+                                  "Dumps information in one or more executable images; 'line-table' expects a source file name",
+                                  "image dump [symtab|sections|symfile|line-table] [<file1> <file2> ...]")
+    {
+        LoadSubCommand (CommandObjectSP (new CommandObjectImageDumpSymtab ()), "symtab", interpreter);
+        LoadSubCommand (CommandObjectSP (new CommandObjectImageDumpSections ()), "sections", interpreter);
+        LoadSubCommand (CommandObjectSP (new CommandObjectImageDumpSymfile ()), "symfile", interpreter);
+        LoadSubCommand (CommandObjectSP (new CommandObjectImageDumpLineTable ()), "line-table", interpreter);
+    }
+
+    virtual
+    ~CommandObjectImageDump()
+    {
+    }
+};
+
+//----------------------------------------------------------------------
+// List images with associated information
+//----------------------------------------------------------------------
+class CommandObjectImageList : public CommandObject
+{
+public:
+
+    class CommandOptions : public Options
+    {
+    public:
+
+        CommandOptions () :
+            Options(),
+            m_format_array()
+        {
+        }
+
+        virtual
+        ~CommandOptions ()
+        {
+        }
+
+        virtual Error
+        SetOptionValue (int option_idx, const char *option_arg)
+        {
+            char short_option = (char) m_getopt_table[option_idx].val;
+            uint32_t width = 0;
+            if (option_arg)
+                width = strtoul (option_arg, NULL, 0);
+            m_format_array.push_back(std::make_pair(short_option, width));
+            Error error;
+            return error;
+        }
+
+        void
+        ResetOptionValues ()
+        {
+            Options::ResetOptionValues();
+            m_format_array.clear();
+        }
+
+        const lldb::OptionDefinition*
+        GetDefinitions ()
+        {
+            return g_option_table;
+        }
+
+        // Options table: Required for subclasses of Options.
+
+        static lldb::OptionDefinition g_option_table[];
+
+        // Instance variables to hold the values for command options.
+        typedef std::vector< std::pair<char, uint32_t> > FormatWidthCollection;
+        FormatWidthCollection m_format_array;
+    };
+
+    CommandObjectImageList () :
+        CommandObject (
+                "image list",
+                "List current executable and dependent shared library images.",
+                "image list [<cmd-options>]")
+    {
+    }
+
+    virtual
+    ~CommandObjectImageList ()
+    {
+    }
+
+    virtual
+    Options *
+    GetOptions ()
+    {
+        return &m_options;
+    }
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        Target *target = context->GetTarget();
+        if (target == NULL)
+        {
+            result.AppendError ("invalid target, set executable file using 'file' command");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+        else
+        {
+            uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
+            result.GetOutputStream().SetAddressByteSize(addr_byte_size);
+            result.GetErrorStream().SetAddressByteSize(addr_byte_size);
+            // Dump all sections for all modules images
+            const uint32_t num_modules = target->GetImages().GetSize();
+            if (num_modules > 0)
+            {
+                Stream &strm = result.GetOutputStream();
+
+                for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx)
+                {
+                    Module *module = target->GetImages().GetModulePointerAtIndex(image_idx);
+                    strm.Printf("[%3u] ", image_idx);
+
+                    if (m_options.m_format_array.empty())
+                    {
+                        DumpFullpath(strm, &module->GetFileSpec(), 0);
+                    }
+                    else
+                    {
+                        const size_t num_entries = m_options.m_format_array.size();
+                        for (size_t i=0; i<num_entries; ++i)
+                        {
+                            if (i > 0)
+                                strm.PutChar(' ');
+                            char format_char = m_options.m_format_array[i].first;
+                            uint32_t width = m_options.m_format_array[i].second;
+                            switch (format_char)
+                            {
+                            case 'a':
+                                DumpModuleArchitecture (strm, module, width);
+                                break;
+
+                            case 'f':
+                                DumpFullpath (strm, &module->GetFileSpec(), width);
+                                break;
+
+                            case 'd':
+                                DumpDirectory (strm, &module->GetFileSpec(), width);
+                                break;
+
+                            case 'b':
+                                DumpBasename (strm, &module->GetFileSpec(), width);
+                                break;
+
+                            case 's':
+                            case 'S':
+                                {
+                                    SymbolVendor *symbol_vendor = module->GetSymbolVendor();
+                                    if (symbol_vendor)
+                                    {
+                                        SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();
+                                        if (symbol_file)
+                                        {
+                                            if (format_char == 'S')
+                                                DumpBasename(strm, &symbol_file->GetObjectFile()->GetFileSpec(), width);
+                                            else
+                                                DumpFullpath (strm, &symbol_file->GetObjectFile()->GetFileSpec(), width);
+                                            break;
+                                        }
+                                    }
+                                    strm.Printf("%.*s", width, "<NONE>");
+                                }
+                                break;
+
+                            case 'u':
+                                DumpModuleUUID(strm, module);
+                                break;
+
+                            default:
+                                break;
+                            }
+                        }
+                    }
+                    strm.EOL();
+                }
+                result.SetStatus (eReturnStatusSuccessFinishResult);
+            }
+            else
+            {
+                result.AppendError ("the target has no associated executable images");
+                result.SetStatus (eReturnStatusFailed);
+                return false;
+            }
+        }
+        return result.Succeeded();
+    }
+protected:
+
+    CommandOptions m_options;
+};
+
+lldb::OptionDefinition
+CommandObjectImageList::CommandOptions::g_option_table[] =
+{
+{ 0, false, "arch",       'a', optional_argument, NULL, 0, "<width>",   "Display the architecture when listing images."},
+{ 0, false, "uuid",       'u', no_argument,       NULL, 0, NULL,        "Display the UUID when listing images."},
+{ 0, false, "fullpath",   'f', optional_argument, NULL, 0, "<width>",   "Display the fullpath to the image object file."},
+{ 0, false, "directory",  'd', optional_argument, NULL, 0, "<width>",   "Display the directory with optional width for the image object file."},
+{ 0, false, "basename",   'b', optional_argument, NULL, 0, "<width>",   "Display the basename with optional width for the image object file."},
+{ 0, false, "symfile",    's', optional_argument, NULL, 0, "<width>",   "Display the fullpath to the image symbol file with optional width."},
+{ 0, false, "symfile-basename", 'S', optional_argument, NULL, 0, "<width>",   "Display the basename to the image symbol file with optional width."},
+{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+
+
+//----------------------------------------------------------------------
+// Lookup information in images
+//----------------------------------------------------------------------
+class CommandObjectImageLookup : public CommandObject
+{
+public:
+
+    enum
+    {
+        eLookupTypeInvalid = -1,
+        eLookupTypeAddress = 0,
+        eLookupTypeSymbol,
+        eLookupTypeFileLine,    // Line is optional
+        eLookupTypeFunction,
+        kNumLookupTypes
+    };
+
+    class CommandOptions : public Options
+    {
+    public:
+
+        CommandOptions () :
+            Options()
+        {
+            ResetOptionValues();
+        }
+
+        virtual
+        ~CommandOptions ()
+        {
+        }
+
+        virtual Error
+        SetOptionValue (int option_idx, const char *option_arg)
+        {
+            Error error;
+
+            char short_option = (char) m_getopt_table[option_idx].val;
+
+            switch (short_option)
+            {
+            case 'a':
+                m_type = eLookupTypeAddress;
+                m_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS);
+                if (m_addr == LLDB_INVALID_ADDRESS)
+                    error.SetErrorStringWithFormat ("Invalid address string '%s'.\n", option_arg);
+                break;
+
+            case 'o':
+                m_offset = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS);
+                if (m_offset == LLDB_INVALID_ADDRESS)
+                    error.SetErrorStringWithFormat ("Invalid offset string '%s'.\n", option_arg);
+                break;
+
+            case 's':
+                m_str = option_arg;
+                m_type = eLookupTypeSymbol;
+                break;
+
+            case 'f':
+                m_file.SetFile (option_arg);
+                m_type = eLookupTypeFileLine;
+                break;
+
+            case 'i':
+                m_check_inlines = false;
+                break;
+
+            case 'l':
+                m_line_number = Args::StringToUInt32(option_arg, UINT32_MAX);
+                if (m_line_number == UINT32_MAX)
+                    error.SetErrorStringWithFormat ("Invalid line number string '%s'.\n", option_arg);
+                else if (m_line_number == 0)
+                    error.SetErrorString ("Zero is an invalid line number.");
+                m_type = eLookupTypeFileLine;
+                break;
+
+            case 'n':
+                m_str = option_arg;
+                m_type = eLookupTypeFunction;
+                break;
+
+            case 'r':
+                m_use_regex = true;
+                break;
+            }
+
+            return error;
+        }
+
+        void
+        ResetOptionValues ()
+        {
+            Options::ResetOptionValues();
+            m_type = eLookupTypeInvalid;
+            m_str.clear();
+            m_file.Clear();
+            m_addr = LLDB_INVALID_ADDRESS;
+            m_offset = 0;
+            m_line_number = 0;
+            m_use_regex = false;
+            m_check_inlines = true;
+        }
+
+        const lldb::OptionDefinition*
+        GetDefinitions ()
+        {
+            return g_option_table;
+        }
+
+        // Options table: Required for subclasses of Options.
+
+        static lldb::OptionDefinition g_option_table[];
+        int             m_type;         // Should be a eLookupTypeXXX enum after parsing options
+        std::string     m_str;          // Holds name lookup
+        FileSpec        m_file;         // Files for file lookups
+        lldb::addr_t    m_addr;         // Holds the address to lookup
+        lldb::addr_t    m_offset;       // Subtract this offset from m_addr before doing lookups.
+        uint32_t        m_line_number;  // Line number for file+line lookups
+        bool            m_use_regex;    // Name lookups in m_str are regular expressions.
+        bool            m_check_inlines;// Check for inline entries when looking up by file/line.
+    };
+
+    CommandObjectImageLookup () :
+        CommandObject (
+                "image lookup",
+                "Look up information within executable and dependent shared library images.",
+                "image lookup [<cmd-options>] [<file1>...]")
+    {
+    }
+
+    virtual
+    ~CommandObjectImageLookup ()
+    {
+    }
+
+    virtual
+    Options *
+    GetOptions ()
+    {
+        return &m_options;
+    }
+
+
+    bool
+    LookupInModule (CommandContext *context, Module *module, CommandReturnObject &result, bool &syntax_error)
+    {
+        switch (m_options.m_type)
+        {
+        case eLookupTypeAddress:
+            if (m_options.m_addr != LLDB_INVALID_ADDRESS)
+            {
+                if (LookupAddressInModule (context, result.GetOutputStream(), module, eSymbolContextEverything, m_options.m_addr, m_options.m_offset))
+                {
+                    result.SetStatus(eReturnStatusSuccessFinishResult);
+                    return true;
+                }
+            }
+            break;
+
+        case eLookupTypeSymbol:
+            if (!m_options.m_str.empty())
+            {
+                if (LookupSymbolInModule (context, result.GetOutputStream(), module, m_options.m_str.c_str(), m_options.m_use_regex))
+                {
+                    result.SetStatus(eReturnStatusSuccessFinishResult);
+                    return true;
+                }
+            }
+            break;
+
+        case eLookupTypeFileLine:
+            if (m_options.m_file)
+            {
+
+                if (LookupFileAndLineInModule (context,
+                                               result.GetOutputStream(),
+                                               module,
+                                               m_options.m_file,
+                                               m_options.m_line_number,
+                                               m_options.m_check_inlines))
+                {
+                    result.SetStatus(eReturnStatusSuccessFinishResult);
+                    return true;
+                }
+            }
+            break;
+
+        case eLookupTypeFunction:
+            if (!m_options.m_str.empty())
+            {
+                if (LookupFunctionInModule (context,
+                                            result.GetOutputStream(),
+                                            module,
+                                            m_options.m_str.c_str(),
+                                            m_options.m_use_regex))
+                {
+                    result.SetStatus(eReturnStatusSuccessFinishResult);
+                    return true;
+                }
+            }
+            break;
+
+        default:
+            m_options.GenerateOptionUsage (result.GetErrorStream(), this);
+            syntax_error = true;
+            break;
+        }
+
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        Target *target = context->GetTarget();
+        if (target == NULL)
+        {
+            result.AppendError ("invalid target, set executable file using 'file' command");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+        else
+        {
+            bool syntax_error = false;
+            uint32_t i;
+            uint32_t num_successful_lookups = 0;
+            uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
+            result.GetOutputStream().SetAddressByteSize(addr_byte_size);
+            result.GetErrorStream().SetAddressByteSize(addr_byte_size);
+            // Dump all sections for all modules images
+
+            if (command.GetArgumentCount() == 0)
+            {
+                // Dump all sections for all modules images
+                const uint32_t num_modules = target->GetImages().GetSize();
+                if (num_modules > 0)
+                {
+                    for (i = 0; i<num_modules && syntax_error == false; ++i)
+                    {
+                        if (LookupInModule (context, target->GetImages().GetModulePointerAtIndex(i), result, syntax_error))
+                        {
+                            result.GetOutputStream().EOL();
+                            num_successful_lookups++;
+                        }
+                    }
+                }
+                else
+                {
+                    result.AppendError ("the target has no associated executable images");
+                    result.SetStatus (eReturnStatusFailed);
+                    return false;
+                }
+            }
+            else
+            {
+                // Dump specified images (by basename or fullpath)
+                const char *arg_cstr;
+                for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != NULL && syntax_error == false; ++i)
+                {
+                    FileSpec image_file(arg_cstr);
+                    ModuleList matching_modules;
+                    const size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules);
+
+                    if (num_matching_modules > 0)
+                    {
+                        for (size_t i=0; i<num_matching_modules; ++i)
+                        {
+                            Module * image_module = matching_modules.GetModulePointerAtIndex(i);
+                            if (image_module)
+                            {
+                                if (LookupInModule (context, image_module, result, syntax_error))
+                                {
+                                    result.GetOutputStream().EOL();
+                                    num_successful_lookups++;
+                                }
+                            }
+                        }
+                    }
+                    else
+                        result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
+                }
+            }
+
+            if (num_successful_lookups > 0)
+                result.SetStatus (eReturnStatusSuccessFinishResult);
+            else
+                result.SetStatus (eReturnStatusFailed);
+        }
+        return result.Succeeded();
+    }
+protected:
+
+    CommandOptions m_options;
+};
+
+lldb::OptionDefinition
+CommandObjectImageLookup::CommandOptions::g_option_table[] =
+{
+{ 1, true,  "address",    'a', required_argument, NULL, 0, "<addr>",    "Lookup an address in one or more executable images."},
+{ 1, false, "offset",     'o', required_argument, NULL, 0, "<offset>",  "When looking up an address subtract <offset> from any addresses before doing the lookup."},
+{ 2, true,  "symbol",     's', required_argument, NULL, 0, "<name>",    "Lookup a symbol by name in the symbol tables in one or more executable images."},
+{ 2, false, "regex",      'r', no_argument,       NULL, 0, NULL,        "The <name> argument for name lookups are regular expressions."},
+{ 3, true,  "file",       'f', required_argument, NULL, 0, "<file>",    "Lookup a file by fullpath or basename in one or more executable images."},
+{ 3, false, "line",       'l', required_argument, NULL, 0, "<line>",    "Lookup a line number in a file (must be used in conjunction with --file)."},
+{ 3, false, "no-inlines", 'i', no_argument,       NULL, 0, NULL,        "Check inline line entries (must be used in conjunction with --file)."},
+{ 4, true,  "function",   'n', required_argument, NULL, 0, "<name>",    "Lookup a function by name in the debug symbols in one or more executable images."},
+{ 5, false, "regex",      'r', no_argument,       NULL, 0, NULL,        "The <name> argument for name lookups are regular expressions."},
+{ 0, false, NULL,           0, 0,                 NULL, 0, NULL, NULL }
+};
+
+
+
+
+
+//----------------------------------------------------------------------
+// CommandObjectImage constructor
+//----------------------------------------------------------------------
+CommandObjectImage::CommandObjectImage(CommandInterpreter *interpreter) :
+    CommandObjectMultiword ("image",
+                              "Access information for one or more executable images.",
+                              "image [dump|list] ...")
+{
+    LoadSubCommand (CommandObjectSP (new CommandObjectImageDump (interpreter)), "dump", interpreter);
+    LoadSubCommand (CommandObjectSP (new CommandObjectImageList ()), "list", interpreter);
+    LoadSubCommand (CommandObjectSP (new CommandObjectImageLookup ()), "lookup", interpreter);
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+CommandObjectImage::~CommandObjectImage()
+{
+}
+
diff --git a/source/Commands/CommandObjectImage.h b/source/Commands/CommandObjectImage.h
new file mode 100644
index 0000000..8863a36
--- /dev/null
+++ b/source/Commands/CommandObjectImage.h
@@ -0,0 +1,44 @@
+//===-- CommandObjectImage.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_CommandObjectImage_h_
+#define liblldb_CommandObjectImage_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectImage
+//-------------------------------------------------------------------------
+
+class CommandObjectImage : public CommandObjectMultiword
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    CommandObjectImage(CommandInterpreter *interpreter);
+    virtual
+    ~CommandObjectImage();
+
+private:
+    //------------------------------------------------------------------
+    // For CommandObjectImage only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (CommandObjectImage);
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectImage_h_
diff --git a/source/Commands/CommandObjectInfo.cpp b/source/Commands/CommandObjectInfo.cpp
new file mode 100644
index 0000000..f817cc1
--- /dev/null
+++ b/source/Commands/CommandObjectInfo.cpp
@@ -0,0 +1,32 @@
+//===-- CommandObjectInfo.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectInfo.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectInfo
+//-------------------------------------------------------------------------
+
+CommandObjectInfo::CommandObjectInfo () :
+CommandObjectCrossref ("info", "Lists the kinds of objects for which you can get information, and shows the syntax for doing so.", "info")
+{
+}
+
+CommandObjectInfo::~CommandObjectInfo ()
+{
+}
+
+
diff --git a/source/Commands/CommandObjectInfo.h b/source/Commands/CommandObjectInfo.h
new file mode 100644
index 0000000..44f9bd1
--- /dev/null
+++ b/source/Commands/CommandObjectInfo.h
@@ -0,0 +1,37 @@
+//===-- CommandObjectInfo.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_CommandObjectInfo_h_
+#define liblldb_CommandObjectInfo_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectCrossref.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectInfo
+//-------------------------------------------------------------------------
+
+class CommandObjectInfo : public CommandObjectCrossref
+{
+public:
+    CommandObjectInfo ();
+
+    virtual
+    ~CommandObjectInfo ();
+
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectInfo_h_
diff --git a/source/Commands/CommandObjectLog.cpp b/source/Commands/CommandObjectLog.cpp
new file mode 100644
index 0000000..6b54bad
--- /dev/null
+++ b/source/Commands/CommandObjectLog.cpp
@@ -0,0 +1,452 @@
+//===-- CommandObjectLog.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectLog.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private-log.h"
+
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/Timer.h"
+
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+#include "lldb/Symbol/LineTable.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
+
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+static LogChannelSP
+GetLogChannelPluginForChannel (const char *channel)
+{
+    std::string log_channel_plugin_name(channel);
+    log_channel_plugin_name += LogChannel::GetPluginSuffix();
+    LogChannelSP log_channel_sp (LogChannel::FindPlugin (log_channel_plugin_name.c_str()));
+    return log_channel_sp;
+}
+
+
+class CommandObjectLogEnable : public CommandObject
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    CommandObjectLogEnable() :
+        CommandObject ("log enable",
+                       "Enable logging for a single log channel.",
+                       "log enable [<cmd-options>] <channel>")
+    {
+    }
+
+    virtual
+    ~CommandObjectLogEnable()
+    {
+    }
+
+    Options *
+    GetOptions ()
+    {
+        return &m_options;
+    }
+
+    virtual bool
+    Execute (Args& args,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        if (args.GetArgumentCount() < 1)
+        {
+            result.GetErrorStream() << m_cmd_syntax.c_str();
+        }
+        else
+        {
+            Log::Callbacks log_callbacks;
+
+            std::string channel(args.GetArgumentAtIndex(0));
+            args.Shift ();  // Shift off the channel
+            StreamSP log_stream_sp;
+
+            if (m_options.log_file.empty())
+            {
+                std::string log_file("<lldb.debugger>");
+                LogStreamMap::iterator pos = m_log_streams.find(log_file);
+                if (pos == m_log_streams.end())
+                {
+                    log_stream_sp = Log::GetStreamForSTDOUT ();
+                    if (log_stream_sp)
+                        m_log_streams[log_file] = log_stream_sp;
+                }
+                else
+                    log_stream_sp = pos->second;
+            }
+            else
+            {
+                LogStreamMap::iterator pos = m_log_streams.find(m_options.log_file);
+                if (pos == m_log_streams.end())
+                {
+                    log_stream_sp.reset (new StreamFile (m_options.log_file.c_str(), "w"));
+                    m_log_streams[m_options.log_file] = log_stream_sp;
+                }
+                else
+                    log_stream_sp = pos->second;
+            }
+            assert (log_stream_sp.get());
+            uint32_t log_options = m_options.log_options;
+            if (log_options == 0)
+                log_options = LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE;
+            if (Log::GetLogChannelCallbacks (channel.c_str(), log_callbacks))
+            {
+                log_callbacks.enable (log_stream_sp, log_options, args, &result.GetErrorStream());
+                result.SetStatus(eReturnStatusSuccessFinishNoResult);
+            }
+            else
+            {
+                LogChannelSP log_channel_sp (GetLogChannelPluginForChannel(channel.c_str()));
+                if (log_channel_sp)
+                {
+                    if (log_channel_sp->Enable (log_stream_sp, log_options, &result.GetErrorStream(), args))
+                    {
+                        result.SetStatus (eReturnStatusSuccessFinishNoResult);
+                    }
+                    else
+                    {
+                        result.AppendErrorWithFormat("Invalid log channel '%s'.\n", channel.c_str());
+                        result.SetStatus (eReturnStatusFailed);
+                    }
+                }
+                else
+                {
+                    result.AppendErrorWithFormat("Invalid log channel '%s'.\n", channel.c_str());
+                    result.SetStatus (eReturnStatusFailed);
+                }
+            }
+        }
+        return result.Succeeded();
+    }
+
+
+    class CommandOptions : public Options
+    {
+    public:
+
+        CommandOptions () :
+            Options (),
+            log_file (),
+            log_options (0)
+        {
+        }
+
+
+        virtual
+        ~CommandOptions ()
+        {
+        }
+
+        virtual Error
+        SetOptionValue (int option_idx, const char *option_arg)
+        {
+            Error error;
+            char short_option = (char) m_getopt_table[option_idx].val;
+
+            switch (short_option)
+            {
+            case 'f':  log_file = option_arg;                                 break;
+            case 't':  log_options |= LLDB_LOG_OPTION_THREADSAFE;             break;
+            case 'v':  log_options |= LLDB_LOG_OPTION_VERBOSE;                break;
+            case 'g':  log_options |= LLDB_LOG_OPTION_DEBUG;                  break;
+            case 's':  log_options |= LLDB_LOG_OPTION_PREPEND_SEQUENCE;       break;
+            case 'T':  log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP;      break;
+            case 'p':  log_options |= LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD;break;
+            case 'n':  log_options |= LLDB_LOG_OPTION_PREPEND_THREAD_NAME;    break;
+            default:
+                error.SetErrorStringWithFormat ("Unrecognized option '%c'\n", short_option);
+                break;
+            }
+
+            return error;
+        }
+
+        void
+        ResetOptionValues ()
+        {
+            Options::ResetOptionValues();
+            log_file.clear();
+            log_options = 0;
+        }
+
+        const lldb::OptionDefinition*
+        GetDefinitions ()
+        {
+            return g_option_table;
+        }
+
+        // Options table: Required for subclasses of Options.
+
+        static lldb::OptionDefinition g_option_table[];
+
+        // Instance variables to hold the values for command options.
+
+        std::string log_file;
+        uint32_t log_options;
+    };
+
+protected:
+    typedef std::map<std::string, StreamSP> LogStreamMap;
+    CommandOptions m_options;
+    LogStreamMap m_log_streams;
+};
+
+lldb::OptionDefinition
+CommandObjectLogEnable::CommandOptions::g_option_table[] =
+{
+{ 0, false, "file",       'f', required_argument, NULL, 0, "<filename>",   "Set the destination file to log to."},
+{ 0, false, "threadsafe", 't', no_argument,       NULL, 0, NULL,           "Enable thread safe logging to avoid interweaved log lines." },
+{ 0, false, "verbose",    'v', no_argument,       NULL, 0, NULL,           "Enable verbose logging." },
+{ 0, false, "debug",      'g', no_argument,       NULL, 0, NULL,           "Enable debug logging." },
+{ 0, false, "sequence",   's', no_argument,       NULL, 0, NULL,           "Prepend all log lines with an increasing integer sequence id." },
+{ 0, false, "timestamp",  'T', no_argument,       NULL, 0, NULL,           "Prepend all log lines with a timestamp." },
+{ 0, false, "pid-tid",    'p', no_argument,       NULL, 0, NULL,           "Prepend all log lines with the process and thread ID that generates the log line." },
+{ 0, false, "thread-name",'n', no_argument,       NULL, 0, NULL,           "Prepend all log lines with the thread name for the thread that generates the log line." },
+{ 0, false, NULL,          0,  0,                 NULL, 0, NULL,           NULL }
+};
+
+class CommandObjectLogDisable : public CommandObject
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    CommandObjectLogDisable() :
+        CommandObject ("log disable",
+                        "Disable one or more log channels.",
+                        "log disable <channel> [<channel> ...]")
+    {
+    }
+
+    virtual
+    ~CommandObjectLogDisable()
+    {
+    }
+
+    virtual bool
+    Execute (Args& args,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        const size_t argc = args.GetArgumentCount();
+        if (argc == 0)
+        {
+            result.GetErrorStream() << m_cmd_syntax.c_str();
+        }
+        else
+        {
+            for (size_t i=0; i<argc; ++i)
+            {
+                Log::Callbacks log_callbacks;
+
+                std::string channel(args.GetArgumentAtIndex(i));
+                if (Log::GetLogChannelCallbacks (channel.c_str(), log_callbacks))
+                {
+                    log_callbacks.disable ();
+                    result.SetStatus(eReturnStatusSuccessFinishNoResult);
+                }
+                else if (channel == "all")
+                {
+                    Log::DisableAllLogChannels();
+                }
+                else
+                {
+                    LogChannelSP log_channel_sp (GetLogChannelPluginForChannel(channel.c_str()));
+                    if (log_channel_sp)
+                    {
+                        log_channel_sp->Disable();
+                        result.SetStatus(eReturnStatusSuccessFinishNoResult);
+                    }
+                    else
+                        result.AppendErrorWithFormat("Invalid log channel '%s'.\n", args.GetArgumentAtIndex(0));
+                }
+            }
+        }
+        return result.Succeeded();
+    }
+};
+
+class CommandObjectLogList : public CommandObject
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    CommandObjectLogList() :
+        CommandObject ("log list",
+                       "List the log categories for one or more log channels.",
+                       "log list <channel> [<channel> ...]")
+    {
+    }
+
+    virtual
+    ~CommandObjectLogList()
+    {
+    }
+
+    virtual bool
+    Execute (Args& args,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        const size_t argc = args.GetArgumentCount();
+        if (argc == 0)
+        {
+            Log::ListAllLogChannels (&result.GetOutputStream());
+            result.SetStatus(eReturnStatusSuccessFinishResult);
+        }
+        else
+        {
+            for (size_t i=0; i<argc; ++i)
+            {
+                Log::Callbacks log_callbacks;
+
+                std::string channel(args.GetArgumentAtIndex(i));
+                if (Log::GetLogChannelCallbacks (channel.c_str(), log_callbacks))
+                {
+                    log_callbacks.list_categories (&result.GetOutputStream());
+                    result.SetStatus(eReturnStatusSuccessFinishResult);
+                }
+                else if (channel == "all")
+                {
+                    Log::ListAllLogChannels (&result.GetOutputStream());
+                    result.SetStatus(eReturnStatusSuccessFinishResult);
+                }
+                else
+                {
+                    LogChannelSP log_channel_sp (GetLogChannelPluginForChannel(channel.c_str()));
+                    if (log_channel_sp)
+                    {
+                        log_channel_sp->ListCategories(&result.GetOutputStream());
+                        result.SetStatus(eReturnStatusSuccessFinishNoResult);
+                    }
+                    else
+                        result.AppendErrorWithFormat("Invalid log channel '%s'.\n", args.GetArgumentAtIndex(0));
+                }
+            }
+        }
+        return result.Succeeded();
+    }
+};
+
+class CommandObjectLogTimer : public CommandObject
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    CommandObjectLogTimer() :
+        CommandObject ("log timers",
+                       "Enable, disable, dump, and reset LLDB internal performance timers.",
+                       "log timers < enable | disable | dump | reset >")
+    {
+    }
+
+    virtual
+    ~CommandObjectLogTimer()
+    {
+    }
+
+    virtual bool
+    Execute (Args& args,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        const size_t argc = args.GetArgumentCount();
+        result.SetStatus(eReturnStatusFailed);
+
+        if (argc == 1)
+        {
+            const char *sub_command = args.GetArgumentAtIndex(0);
+
+            if (strcasecmp(sub_command, "enable") == 0)
+            {
+                Timer::SetDisplayDepth (UINT32_MAX);
+                result.SetStatus(eReturnStatusSuccessFinishNoResult);
+            }
+            else if (strcasecmp(sub_command, "disable") == 0)
+            {
+                Timer::DumpCategoryTimes (&result.GetOutputStream());
+                Timer::SetDisplayDepth (0);
+                result.SetStatus(eReturnStatusSuccessFinishResult);
+            }
+            else if (strcasecmp(sub_command, "dump") == 0)
+            {
+                Timer::DumpCategoryTimes (&result.GetOutputStream());
+                result.SetStatus(eReturnStatusSuccessFinishResult);
+            }
+            else if (strcasecmp(sub_command, "reset") == 0)
+            {
+                Timer::ResetCategoryTimes ();
+                result.SetStatus(eReturnStatusSuccessFinishResult);
+            }
+
+        }
+        if (!result.Succeeded())
+        {
+            result.AppendError("Missing subcommand");
+            result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
+        }
+        return result.Succeeded();
+    }
+};
+
+//----------------------------------------------------------------------
+// CommandObjectLog constructor
+//----------------------------------------------------------------------
+CommandObjectLog::CommandObjectLog(CommandInterpreter *interpreter) :
+    CommandObjectMultiword ("log",
+                            "A set of commands for operating on logs.",
+                            "log <command> [<command-options>]")
+{
+    LoadSubCommand (CommandObjectSP (new CommandObjectLogEnable), "enable", interpreter);
+    LoadSubCommand (CommandObjectSP (new CommandObjectLogDisable), "disable", interpreter);
+    LoadSubCommand (CommandObjectSP (new CommandObjectLogList), "list", interpreter);
+    LoadSubCommand (CommandObjectSP (new CommandObjectLogTimer), "timers", interpreter);
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+CommandObjectLog::~CommandObjectLog()
+{
+}
+
+
+
+
diff --git a/source/Commands/CommandObjectLog.h b/source/Commands/CommandObjectLog.h
new file mode 100644
index 0000000..a1ba258
--- /dev/null
+++ b/source/Commands/CommandObjectLog.h
@@ -0,0 +1,48 @@
+//===-- CommandObjectLog.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_CommandObjectLog_h_
+#define liblldb_CommandObjectLog_h_
+
+// C Includes
+// C++ Includes
+#include <map>
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectLog
+//-------------------------------------------------------------------------
+
+class CommandObjectLog : public CommandObjectMultiword
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    CommandObjectLog(CommandInterpreter *interpreter);
+
+    virtual
+    ~CommandObjectLog();
+
+private:
+    //------------------------------------------------------------------
+    // For CommandObjectLog only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (CommandObjectLog);
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectLog_h_
diff --git a/source/Commands/CommandObjectMemory.cpp b/source/Commands/CommandObjectMemory.cpp
new file mode 100644
index 0000000..91abd81
--- /dev/null
+++ b/source/Commands/CommandObjectMemory.cpp
@@ -0,0 +1,680 @@
+//===-- CommandObjectMemory.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectMemory.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Read memory from the inferior process
+//----------------------------------------------------------------------
+class CommandObjectMemoryRead : public CommandObject
+{
+public:
+
+    class CommandOptions : public Options
+    {
+    public:
+        CommandOptions () :
+            Options()
+        {
+            ResetOptionValues();
+        }
+
+        virtual
+        ~CommandOptions ()
+        {
+        }
+
+        virtual Error
+        SetOptionValue (int option_idx, const char *option_arg)
+        {
+            Error error;
+            char short_option = (char) m_getopt_table[option_idx].val;
+
+            switch (short_option)
+            {
+            case 'f':
+                error = Args::StringToFormat (option_arg, m_format);
+
+                switch (m_format)
+                {
+                default:
+                    break;
+
+                case eFormatBoolean:
+                    if (m_byte_size == 0)
+                        m_byte_size = 1;
+                    if (m_num_per_line == 0)
+                        m_num_per_line = 1;
+                    break;
+
+                case eFormatCString:
+                    if (m_num_per_line == 0)
+                        m_num_per_line = 1;
+                    break;
+
+                case eFormatPointer:
+                    break;
+
+                case eFormatBinary:
+                case eFormatFloat:
+                case eFormatOctal:
+                case eFormatDecimal:
+                case eFormatEnum:
+                case eFormatUnicode16:
+                case eFormatUnicode32:
+                case eFormatUnsigned:
+                    if (m_byte_size == 0)
+                        m_byte_size = 4;
+                    if (m_num_per_line == 0)
+                        m_num_per_line = 1;
+                    break;
+
+                case eFormatBytes:
+                case eFormatBytesWithASCII:
+                case eFormatChar:
+                case eFormatCharPrintable:
+                    if (m_byte_size == 0)
+                        m_byte_size = 1;
+                    break;
+                case eFormatComplex:
+                    if (m_byte_size == 0)
+                        m_byte_size = 8;
+                    break;
+                case eFormatHex:
+                    if (m_byte_size == 0)
+                        m_byte_size = 4;
+                    break;
+
+                case eFormatVectorOfChar:
+                case eFormatVectorOfSInt8:
+                case eFormatVectorOfUInt8:
+                case eFormatVectorOfSInt16:
+                case eFormatVectorOfUInt16:
+                case eFormatVectorOfSInt32:
+                case eFormatVectorOfUInt32:
+                case eFormatVectorOfSInt64:
+                case eFormatVectorOfUInt64:
+                case eFormatVectorOfFloat32:
+                case eFormatVectorOfFloat64:
+                case eFormatVectorOfUInt128:
+                    break;
+                }
+                break;
+
+            case 'l':
+                m_num_per_line = Args::StringToUInt32 (option_arg, 0);
+                if (m_num_per_line == 0)
+                    error.SetErrorStringWithFormat("Invalid value for --num-per-line option '%s'. Must be positive integer value.\n", option_arg);
+                break;
+
+            case 'c':
+                m_count = Args::StringToUInt32 (option_arg, 0);
+                if (m_count == 0)
+                    error.SetErrorStringWithFormat("Invalid value for --count option '%s'. Must be positive integer value.\n", option_arg);
+                break;
+
+            case 's':
+                m_byte_size = Args::StringToUInt32 (option_arg, 0);
+                if (m_byte_size == 0)
+                    error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg);
+                break;
+
+            default:
+                error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
+                break;
+            }
+            return error;
+        }
+
+        void
+        ResetOptionValues ()
+        {
+            Options::ResetOptionValues();
+            m_format = eFormatBytesWithASCII;
+            m_byte_size = 0;
+            m_count = 0;
+            m_num_per_line = 0;
+        }
+
+        const lldb::OptionDefinition*
+        GetDefinitions ()
+        {
+            return g_option_table;
+        }
+
+        // Options table: Required for subclasses of Options.
+
+        static lldb::OptionDefinition g_option_table[];
+
+        // Instance variables to hold the values for command options.
+        lldb::Format m_format;
+        uint32_t m_byte_size;
+        uint32_t m_count;
+        uint32_t m_num_per_line;
+    };
+
+    CommandObjectMemoryRead () :
+        CommandObject ("memory read",
+                       "Read memory from the process being debugged.",
+                       "memory read [<cmd-options>] <start-addr> [<end-addr>]",
+                       eFlagProcessMustBeLaunched)
+    {
+    }
+
+    virtual
+    ~CommandObjectMemoryRead ()
+    {
+    }
+
+    Options *
+    GetOptions ()
+    {
+        return &m_options;
+    }
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        Process *process = context->GetExecutionContext().process;
+        if (process == NULL)
+        {
+            result.AppendError("need a process to read memory");
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        const size_t argc = command.GetArgumentCount();
+
+        if (argc == 0 || argc > 2)
+        {
+            result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+
+        size_t item_byte_size = m_options.m_byte_size;
+        if (item_byte_size == 0)
+        {
+            if (m_options.m_format == eFormatPointer)
+                item_byte_size = process->GetAddressByteSize();
+            else
+                item_byte_size = 1;
+        }
+
+        size_t item_count = m_options.m_count;
+
+        size_t num_per_line = m_options.m_num_per_line;
+        if (num_per_line == 0)
+        {
+            num_per_line = (16/item_byte_size);
+            if (num_per_line == 0)
+                num_per_line = 1;
+        }
+
+        size_t total_byte_size = m_options.m_count * item_byte_size;
+        if (total_byte_size == 0)
+            total_byte_size = 32;
+
+        lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
+
+        if (addr == LLDB_INVALID_ADDRESS)
+        {
+            result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+
+        if (argc == 2)
+        {
+            lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
+            if (end_addr == LLDB_INVALID_ADDRESS)
+            {
+                result.AppendErrorWithFormat("Invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
+                result.SetStatus(eReturnStatusFailed);
+                return false;
+            }
+            else if (end_addr <= addr)
+            {
+                result.AppendErrorWithFormat("End address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr);
+                result.SetStatus(eReturnStatusFailed);
+                return false;
+            }
+            else if (item_count != 0)
+            {
+                result.AppendErrorWithFormat("Specify either the end address (0x%llx) or the count (--count %u), not both.\n", end_addr, item_count);
+                result.SetStatus(eReturnStatusFailed);
+                return false;
+            }
+
+            total_byte_size = end_addr - addr;
+            item_count = total_byte_size / item_byte_size;
+        }
+        else
+        {
+            if (item_count == 0)
+                item_count = 32;
+        }
+
+        DataBufferSP data_sp(new DataBufferHeap (total_byte_size, '\0'));
+        Error error;
+        size_t bytes_read = process->ReadMemory(addr, data_sp->GetBytes (), data_sp->GetByteSize(), error);
+        if (bytes_read == 0)
+        {
+            result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
+            result.AppendError(error.AsCString());
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+
+        if (bytes_read < total_byte_size)
+            result.AppendWarningWithFormat("Not all bytes (%u/%u) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);
+
+        result.SetStatus(eReturnStatusSuccessFinishResult);
+        DataExtractor data(data_sp, process->GetByteOrder(), process->GetAddressByteSize());
+
+        Stream &output_stream = result.GetOutputStream();
+        data.Dump(&output_stream,
+                  0,
+                  m_options.m_format,
+                  item_byte_size,
+                  item_count,
+                  num_per_line,
+                  addr,
+                  0,
+                  0);
+        output_stream.EOL();
+        return true;
+    }
+
+protected:
+    CommandOptions m_options;
+};
+
+lldb::OptionDefinition
+CommandObjectMemoryRead::CommandOptions::g_option_table[] =
+{
+    { 0, false, "format",       'f', required_argument, NULL, 0, "<format>",   "The format that will be used to display the memory. Defaults to bytes with ASCII (--format=Y)."},
+    { 0, false, "size",         's', required_argument, NULL, 0, "<byte-size>","The size in bytes to use when displaying with the selected format."},
+    { 0, false, "num-per-line", 'l', required_argument, NULL, 0, "<N>",        "The number of items per line to display."},
+    { 0, false, "count",        'c', required_argument, NULL, 0, "<N>",        "The number of total items to display."},
+    { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+
+//----------------------------------------------------------------------
+// Write memory to the inferior process
+//----------------------------------------------------------------------
+class CommandObjectMemoryWrite : public CommandObject
+{
+public:
+
+    class CommandOptions : public Options
+    {
+    public:
+        CommandOptions () :
+            Options()
+        {
+            ResetOptionValues();
+        }
+
+        virtual
+        ~CommandOptions ()
+        {
+        }
+
+        virtual Error
+        SetOptionValue (int option_idx, const char *option_arg)
+        {
+            Error error;
+            char short_option = (char) m_getopt_table[option_idx].val;
+            switch (short_option)
+            {
+            case 'f':
+                error = Args::StringToFormat (option_arg, m_format);
+                break;
+
+            case 's':
+                m_byte_size = Args::StringToUInt32 (option_arg, 0);
+                if (m_byte_size == 0)
+                    error.SetErrorStringWithFormat("Invalid value for --size option '%s'.  Must be positive integer value.\n", option_arg);
+                break;
+
+
+            default:
+                error.SetErrorStringWithFormat("Unrecognized short option '%c'\n", short_option);
+                break;
+            }
+            return error;
+        }
+
+        void
+        ResetOptionValues ()
+        {
+            Options::ResetOptionValues();
+            m_format = eFormatBytes;
+            m_byte_size = 1;
+        }
+
+        const lldb::OptionDefinition*
+        GetDefinitions ()
+        {
+            return g_option_table;
+        }
+
+        // Options table: Required for subclasses of Options.
+
+        static lldb::OptionDefinition g_option_table[];
+
+        // Instance variables to hold the values for command options.
+        lldb::Format m_format;
+        uint32_t m_byte_size;
+    };
+
+    CommandObjectMemoryWrite () :
+        CommandObject ("memory write",
+                       "Write memory to the process being debugged.",
+                       "memory write [<cmd-options>] <addr> [value1 value2 ...]",
+                       eFlagProcessMustBeLaunched)
+    {
+    }
+
+    virtual
+    ~CommandObjectMemoryWrite ()
+    {
+    }
+
+    Options *
+    GetOptions ()
+    {
+        return &m_options;
+    }
+
+    bool
+    UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
+    {
+        if (total_byte_size > 8)
+            return false;
+
+        if (total_byte_size == 8)
+            return true;
+
+        const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
+        return uval64 <= max;
+    }
+
+    bool
+    SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
+    {
+        if (total_byte_size > 8)
+            return false;
+
+        if (total_byte_size == 8)
+            return true;
+
+        const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
+        const int64_t min = ~(max);
+        return min <= sval64 && sval64 <= max;
+    }
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        Process *process = context->GetExecutionContext().process;
+        if (process == NULL)
+        {
+            result.AppendError("need a process to read memory");
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+
+        const size_t argc = command.GetArgumentCount();
+
+        if (argc < 2)
+        {
+            result.AppendErrorWithFormat ("%s takes an address and at least one value.\n", m_cmd_name.c_str());
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+
+        size_t item_byte_size = m_options.m_byte_size ? m_options.m_byte_size : 1;
+        StreamString buffer (Stream::eBinary,
+                             process->GetAddressByteSize(),
+                             process->GetByteOrder());
+
+        lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
+
+        if (addr == LLDB_INVALID_ADDRESS)
+        {
+            result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        command.Shift(); // shift off the address argument
+        uint64_t uval64;
+        int64_t sval64;
+        bool success = false;
+        const uint32_t num_value_args = command.GetArgumentCount();
+        uint32_t i;
+        for (i=0; i<num_value_args; ++i)
+        {
+            const char *value_str = command.GetArgumentAtIndex(i);
+
+            switch (m_options.m_format)
+            {
+            case eFormatFloat:  // TODO: add support for floats soon
+            case eFormatCharPrintable:
+            case eFormatBytesWithASCII:
+            case eFormatComplex:
+            case eFormatEnum:
+            case eFormatUnicode16:
+            case eFormatUnicode32:
+            case eFormatVectorOfChar:
+            case eFormatVectorOfSInt8:
+            case eFormatVectorOfUInt8:
+            case eFormatVectorOfSInt16:
+            case eFormatVectorOfUInt16:
+            case eFormatVectorOfSInt32:
+            case eFormatVectorOfUInt32:
+            case eFormatVectorOfSInt64:
+            case eFormatVectorOfUInt64:
+            case eFormatVectorOfFloat32:
+            case eFormatVectorOfFloat64:
+            case eFormatVectorOfUInt128:
+                result.AppendError("unsupported format for writing memory");
+                result.SetStatus(eReturnStatusFailed);
+                return false;
+
+            case eFormatDefault:
+            case eFormatBytes:
+            case eFormatHex:
+                // Decode hex bytes
+                uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
+                if (!success)
+                {
+                    result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
+                    result.SetStatus(eReturnStatusFailed);
+                    return false;
+                }
+                else if (!UIntValueIsValidForSize (uval64, item_byte_size))
+                {
+                    result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
+                    result.SetStatus(eReturnStatusFailed);
+                    return false;
+                }
+                buffer.PutMaxHex64 (uval64, item_byte_size);
+                break;
+
+            case eFormatBoolean:
+                uval64 = Args::StringToBoolean(value_str, false, &success);
+                if (!success)
+                {
+                    result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
+                    result.SetStatus(eReturnStatusFailed);
+                    return false;
+                }
+                buffer.PutMaxHex64 (uval64, item_byte_size);
+                break;
+
+            case eFormatBinary:
+                uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
+                if (!success)
+                {
+                    result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
+                    result.SetStatus(eReturnStatusFailed);
+                    return false;
+                }
+                else if (!UIntValueIsValidForSize (uval64, item_byte_size))
+                {
+                    result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
+                    result.SetStatus(eReturnStatusFailed);
+                    return false;
+                }
+                buffer.PutMaxHex64 (uval64, item_byte_size);
+                break;
+
+            case eFormatChar:
+            case eFormatCString:
+                if (value_str[0])
+                {
+                    size_t len = strlen (value_str);
+                    // Include the NULL for C strings...
+                    if (m_options.m_format == eFormatCString)
+                        ++len;
+                    Error error;
+                    if (process->WriteMemory (addr, value_str, len, error) == len)
+                    {
+                        addr += len;
+                    }
+                    else
+                    {
+                        result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
+                        result.SetStatus(eReturnStatusFailed);
+                        return false;
+                    }
+                }
+                break;
+
+            case eFormatDecimal:
+                sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
+                if (!success)
+                {
+                    result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
+                    result.SetStatus(eReturnStatusFailed);
+                    return false;
+                }
+                else if (!SIntValueIsValidForSize (sval64, item_byte_size))
+                {
+                    result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %u byte signed integer value.\n", sval64, item_byte_size);
+                    result.SetStatus(eReturnStatusFailed);
+                    return false;
+                }
+                buffer.PutMaxHex64 (sval64, item_byte_size);
+                break;
+
+            case eFormatUnsigned:
+                uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
+                if (!success)
+                {
+                    result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
+                    result.SetStatus(eReturnStatusFailed);
+                    return false;
+                }
+                else if (!UIntValueIsValidForSize (uval64, item_byte_size))
+                {
+                    result.AppendErrorWithFormat ("Value %llu is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
+                    result.SetStatus(eReturnStatusFailed);
+                    return false;
+                }
+                buffer.PutMaxHex64 (uval64, item_byte_size);
+                break;
+
+            case eFormatOctal:
+                uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
+                if (!success)
+                {
+                    result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
+                    result.SetStatus(eReturnStatusFailed);
+                    return false;
+                }
+                else if (!UIntValueIsValidForSize (uval64, item_byte_size))
+                {
+                    result.AppendErrorWithFormat ("Value %llo is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
+                    result.SetStatus(eReturnStatusFailed);
+                    return false;
+                }
+                buffer.PutMaxHex64 (uval64, item_byte_size);
+                break;
+            }
+        }
+
+        if (!buffer.GetString().empty())
+        {
+            Error error;
+            if (process->WriteMemory (addr, buffer.GetString().data(), buffer.GetString().size(), error) == buffer.GetString().size())
+                return true;
+            else
+            {
+                result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
+                result.SetStatus(eReturnStatusFailed);
+                return false;
+            }
+        }
+        return true;
+    }
+
+protected:
+    CommandOptions m_options;
+};
+
+lldb::OptionDefinition
+CommandObjectMemoryWrite::CommandOptions::g_option_table[] =
+{
+    { 0, false, "format", 'f', required_argument, NULL, 0, "<format>",   "The format value types that will be decoded and written to memory."},
+    { 0, false, "size",   's', required_argument, NULL, 0, "<byte-size>","The size in bytes of the values to write to memory."},
+    { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+
+//-------------------------------------------------------------------------
+// CommandObjectMemory
+//-------------------------------------------------------------------------
+
+CommandObjectMemory::CommandObjectMemory (CommandInterpreter *interpreter) :
+    CommandObjectMultiword ("memory",
+                            "A set of commands for operating on a memory.",
+                            "memory <subcommand> [<subcommand-options>]")
+{
+    LoadSubCommand (CommandObjectSP (new CommandObjectMemoryRead ()), "read", interpreter);
+    LoadSubCommand (CommandObjectSP (new CommandObjectMemoryWrite ()), "write", interpreter);
+}
+
+CommandObjectMemory::~CommandObjectMemory ()
+{
+}
diff --git a/source/Commands/CommandObjectMemory.h b/source/Commands/CommandObjectMemory.h
new file mode 100644
index 0000000..a466540
--- /dev/null
+++ b/source/Commands/CommandObjectMemory.h
@@ -0,0 +1,33 @@
+//===-- CommandObjectMemory.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_CommandObjectMemory_h_
+#define liblldb_CommandObjectMemory_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+namespace lldb_private {
+
+class CommandObjectMemory : public CommandObjectMultiword
+{
+public:
+    CommandObjectMemory (CommandInterpreter *interpreter);
+
+    virtual
+    ~CommandObjectMemory ();
+};
+
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectMemory_h_
diff --git a/source/Commands/CommandObjectProcess.cpp b/source/Commands/CommandObjectProcess.cpp
new file mode 100644
index 0000000..ea0f6af
--- /dev/null
+++ b/source/Commands/CommandObjectProcess.cpp
@@ -0,0 +1,833 @@
+//===-- CommandObjectProcess.cpp --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectProcess.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Core/State.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectProcessLaunch
+//-------------------------------------------------------------------------
+
+class CommandObjectProcessLaunch : public CommandObject
+{
+public:
+
+    class CommandOptions : public Options
+    {
+    public:
+
+        CommandOptions () :
+            Options()
+        {
+            // Keep default values of all options in one place: ResetOptionValues ()
+            ResetOptionValues ();
+        }
+
+        ~CommandOptions ()
+        {
+        }
+
+        Error
+        SetOptionValue (int option_idx, const char *option_arg)
+        {
+            Error error;
+            char short_option = (char) m_getopt_table[option_idx].val;
+
+            switch (short_option)
+            {
+                case 's':   stop_at_entry = true;       break;
+                case 'e':   stderr_path = option_arg;   break;
+                case 'i':   stdin_path  = option_arg;   break;
+                case 'o':   stdout_path = option_arg;   break;
+                case 'p':   plugin_name = option_arg;   break;
+                default:
+                    error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
+                    break;
+
+            }
+            return error;
+        }
+
+        void
+        ResetOptionValues ()
+        {
+            Options::ResetOptionValues();
+            stop_at_entry = false;
+            stdin_path.clear();
+            stdout_path.clear();
+            stderr_path.clear();
+            plugin_name.clear();
+        }
+
+        const lldb::OptionDefinition*
+        GetDefinitions ()
+        {
+            return g_option_table;
+        }
+
+        // Options table: Required for subclasses of Options.
+
+        static lldb::OptionDefinition g_option_table[];
+
+        // Instance variables to hold the values for command options.
+
+        bool stop_at_entry;
+        std::string stderr_path;
+        std::string stdin_path;
+        std::string stdout_path;
+        std::string plugin_name;
+
+    };
+
+    CommandObjectProcessLaunch () :
+        CommandObject ("process launch",
+                       "Launches the executable in the debugger.",
+                       "process launch [<cmd-options>] [<arguments-for-running-the-program>]")
+    {
+    }
+
+
+    ~CommandObjectProcessLaunch ()
+    {
+    }
+
+    Options *
+    GetOptions ()
+    {
+        return &m_options;
+    }
+
+    bool
+    Execute (Args& launch_args,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        Target *target = context->GetTarget();
+        bool synchronous_execution = interpreter->GetSynchronous ();
+    //    bool launched = false;
+    //    bool stopped_after_launch = false;
+
+        if (target == NULL)
+        {
+            result.AppendError ("invalid target, set executable file using 'file' command");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        // If our listener is NULL, users aren't allows to launch
+        Listener *listener = interpreter->GetListener();
+        if (listener == NULL)
+        {
+            result.AppendError ("operation not allowed through the command interpreter");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        char filename[PATH_MAX];
+        Module *exe_module = target->GetExecutableModule().get();
+        exe_module->GetFileSpec().GetPath(filename, sizeof(filename));
+
+        Process *process = context->GetExecutionContext().process;
+        if (process)
+        {
+            if (process->IsAlive())
+            {
+               result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before running again.\n",
+                                            process->GetID());
+                result.SetStatus (eReturnStatusFailed);
+                return false;
+            }
+        }
+
+        const char *plugin_name;
+        if (!m_options.plugin_name.empty())
+            plugin_name = m_options.plugin_name.c_str();
+        else
+            plugin_name = NULL;
+
+        process = target->CreateProcess (*listener, plugin_name).get();
+
+        const Args *environment = interpreter->GetEnvironmentVariables();
+        const Args *run_args = interpreter->GetProgramArguments();
+
+        // There are two possible sources of args to be passed to the process upon launching:  Those the user
+        // typed at the run command (launch_args); or those the user pre-set in the run-args variable (run_args).
+
+        // If launch_args is empty, use run_args.
+        if (launch_args.GetArgumentCount() == 0)
+        {
+            if (run_args != NULL)
+                launch_args.AppendArguments (*run_args);
+        }
+        else
+        {
+            // launch-args was not empty; use that, AND re-set run-args to contains launch-args values.
+            StateVariable *run_args_var = interpreter->GetStateVariable ("run-args");
+            if (run_args_var != NULL)
+            {
+                run_args_var->ArrayClearValues();
+                run_args_var->GetArgs().AppendArguments (launch_args);
+            }
+        }
+
+
+        if (process)
+        {
+            const char *archname = exe_module->GetArchitecture().AsCString();
+
+            const char * stdin_path = NULL;
+            const char * stdout_path = NULL;
+            const char * stderr_path = NULL;
+
+            if (!(m_options.stdin_path.empty() &&
+                m_options.stdout_path.empty() &&
+                m_options.stderr_path.empty()))
+            {
+                stdin_path =    m_options.stdin_path.empty()  ? "/dev/null" : m_options.stdin_path.c_str();
+                stdout_path =   m_options.stdout_path.empty() ? "/dev/null" : m_options.stdout_path.c_str();
+                stderr_path =   m_options.stderr_path.empty() ? "/dev/null" : m_options.stderr_path.c_str();
+            }
+
+            Error error (process->Launch (launch_args.GetConstArgumentVector(),
+                                          environment ? environment->GetConstArgumentVector() : NULL,
+                                          stdin_path,
+                                          stdout_path,
+                                          stderr_path));
+                         
+            if (error.Success())
+            {
+                result.AppendMessageWithFormat ("Launching '%s'  (%s)\n", filename, archname);
+                result.SetStatus (eReturnStatusSuccessContinuingNoResult);
+                if (m_options.stop_at_entry == false)
+                {
+                    StateType state = process->WaitForProcessToStop (NULL);
+
+                    if (state == eStateStopped)
+                    {
+                        // Call continue_command.
+                        CommandReturnObject continue_result;
+                        interpreter->HandleCommand("process continue", false, continue_result);
+                    }
+
+                    if (synchronous_execution)
+                    {
+                        result.SetDidChangeProcessState (true);
+                        result.SetStatus (eReturnStatusSuccessFinishNoResult);
+                    }
+                }
+            }
+            else
+            {
+                result.AppendErrorWithFormat ("Process launch failed: %s",
+                                              error.AsCString());
+                result.SetStatus (eReturnStatusFailed);
+            }
+        }
+        else
+        {
+            result.AppendErrorWithFormat ("Process launch failed: unable to create a process object.\n");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        return result.Succeeded();
+    }
+
+protected:
+
+    CommandOptions m_options;
+};
+
+
+lldb::OptionDefinition
+CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
+{
+{ 0, false, "stop-at-entry", 's', no_argument,       NULL, 0, NULL,        "Stop at the entry point of the program when launching a process."},
+{ 0, false, "stdin",         'i', required_argument, NULL, 0, "<path>",    "Redirect stdin for the process to <path>."},
+{ 0, false, "stdout",        'o', required_argument, NULL, 0, "<path>",    "Redirect stdout for the process to <path>."},
+{ 0, false, "stderr",        'e', required_argument, NULL, 0, "<path>",    "Redirect stderr for the process to <path>."},
+{ 0, false, "plugin",        'p', required_argument, NULL, 0, "<plugin>",  "Name of the process plugin you want to use."},
+{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+
+//-------------------------------------------------------------------------
+// CommandObjectProcessAttach
+//-------------------------------------------------------------------------
+
+class CommandObjectProcessAttach : public CommandObject
+{
+public:
+
+    CommandObjectProcessAttach () :
+        CommandObject ("process attach",
+                       "Attaches to a process.",
+                       "process attach <cmd-options>")
+    {
+        SetHelpLong("Currently, you must set the executable file before you can attach "
+                    "to a process.\n");
+    }
+
+    ~CommandObjectProcessAttach ()
+    {
+    }
+
+    bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        Target *target = context->GetTarget();
+        if (target == NULL)
+        {
+            result.AppendError ("invalid target, set executable file using 'file' command");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        // If our listener is NULL, users aren't allows to launch
+        Listener *listener = interpreter->GetListener();
+        if (listener == NULL)
+        {
+            result.AppendError ("operation not allowed through the command interpreter");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+        Process *process = context->GetExecutionContext().process;
+        if (process)
+        {
+            if (process->IsAlive())
+            {
+                result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n", process->GetID());
+                result.SetStatus (eReturnStatusFailed);
+                return false;
+            }
+        }
+
+        if (command.GetArgumentCount())
+        {
+            result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
+            result.SetStatus (eReturnStatusFailed);
+        }
+        else
+        {
+            const char *plugin_name = NULL;
+            
+            if (!m_options.plugin_name.empty())
+                plugin_name = m_options.plugin_name.c_str();
+
+            process = target->CreateProcess (*listener, plugin_name).get();
+
+            if (process)
+            {
+                Error error;
+                int attach_pid = m_options.pid;
+
+                if (attach_pid != LLDB_INVALID_PROCESS_ID)
+                {
+                    error = process->Attach (attach_pid);
+                    if (error.Success())
+                    {
+                        result.SetStatus (eReturnStatusSuccessContinuingNoResult);
+                    }
+                    else
+                    {
+                        result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n", 
+                                                     attach_pid, 
+                                                     error.AsCString());
+                        result.SetStatus (eReturnStatusFailed);
+                    }
+                }
+                else if (!m_options.name.empty())
+                {
+                    error = process->Attach (m_options.name.c_str(), m_options.waitfor);
+                    if (error.Success())
+                    {
+                        result.SetStatus (eReturnStatusSuccessContinuingNoResult);
+                    }
+                    else
+                    {
+                        if (m_options.waitfor)
+                            result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n", 
+                                                         m_options.name.c_str(),
+                                                         error.AsCString());
+                        else
+                            result.AppendErrorWithFormat ("Failed to a process named '%s': %s\n", 
+                                                         m_options.name.c_str(),
+                                                         error.AsCString());
+                        result.SetStatus (eReturnStatusFailed);
+                    }
+                }
+            }
+        }
+        return result.Succeeded();
+    }
+    
+    Options *
+    GetOptions ()
+    {
+        return &m_options;
+    }
+
+    class CommandOptions : public Options
+    {
+    public:
+
+        CommandOptions () :
+            Options()
+        {
+            // Keep default values of all options in one place: ResetOptionValues ()
+            ResetOptionValues ();
+        }
+
+        ~CommandOptions ()
+        {
+        }
+
+        Error
+        SetOptionValue (int option_idx, const char *option_arg)
+        {
+            Error error;
+            char short_option = (char) m_getopt_table[option_idx].val;
+            bool success = false;
+            switch (short_option)
+            {
+                case 'p':   
+                    pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
+                    if (!success || pid == LLDB_INVALID_PROCESS_ID)
+                    {
+                        error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
+                    }
+                    break;
+
+                case 'P':
+                    plugin_name = option_arg;
+                    break;
+
+                case 'n': 
+                    name.assign(option_arg);
+                    break;
+
+                case 'w':   
+                    waitfor = true; 
+                    break;
+
+                default:
+                    error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
+                    break;
+            }
+            return error;
+        }
+
+        void
+        ResetOptionValues ()
+        {
+            Options::ResetOptionValues();
+            pid = LLDB_INVALID_PROCESS_ID;
+            name.clear();
+            waitfor = false;
+        }
+
+        const lldb::OptionDefinition*
+        GetDefinitions ()
+        {
+            return g_option_table;
+        }
+
+        // Options table: Required for subclasses of Options.
+
+        static lldb::OptionDefinition g_option_table[];
+
+        // Instance variables to hold the values for command options.
+
+        lldb::pid_t pid;
+        std::string plugin_name;
+        std::string name;
+        bool waitfor;
+    };
+
+protected:
+
+    CommandOptions m_options;
+};
+
+
+lldb::OptionDefinition
+CommandObjectProcessAttach::CommandOptions::g_option_table[] =
+{
+{ 0, false, "pid",          'p', required_argument, NULL, 0, "<pid>",           "The process ID of an existing process to attach to."},
+{ 0, false, "plugin",       'P', required_argument, NULL, 0, "<plugin>",        "Name of the process plugin you want to use."},
+{ 1, true,  "name",         'n', required_argument, NULL, 0, "<process-name>",  "The name of the process to attach to."},
+{ 1, false, "waitfor",      'w', no_argument,       NULL, 0, NULL,              "Wait for the the process with <process-name> to launch."},
+{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectProcessContinue
+//-------------------------------------------------------------------------
+
+class CommandObjectProcessContinue : public CommandObject
+{
+public:
+
+    CommandObjectProcessContinue () :
+        CommandObject ("process continue",
+                       "Continues execution all threads in the current process.",
+                       "process continue",
+                       eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
+    {
+    }
+
+
+    ~CommandObjectProcessContinue ()
+    {
+    }
+
+    bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        Process *process = context->GetExecutionContext().process;
+        bool synchronous_execution = interpreter->GetSynchronous ();
+
+        if (process == NULL)
+        {
+            result.AppendError ("no process to continue");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+         }
+
+        StateType state = process->GetState();
+        if (state == eStateStopped)
+        {
+            if (command.GetArgumentCount() != 0)
+            {
+                result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
+                result.SetStatus (eReturnStatusFailed);
+                return false;
+            }
+
+            const uint32_t num_threads = process->GetThreadList().GetSize();
+
+            // Set the actions that the threads should each take when resuming
+            for (uint32_t idx=0; idx<num_threads; ++idx)
+            {
+                process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
+            }
+
+            Error error(process->Resume());
+            if (error.Success())
+            {
+                result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
+                if (synchronous_execution)
+                {
+                    StateType state = process->WaitForProcessToStop (NULL);
+
+                    result.SetDidChangeProcessState (true);
+                    result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
+                    result.SetStatus (eReturnStatusSuccessFinishNoResult);
+                }
+                else
+                {
+                    result.SetStatus (eReturnStatusSuccessContinuingNoResult);
+                }
+            }
+            else
+            {
+                result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
+                result.SetStatus (eReturnStatusFailed);
+            }
+        }
+        else
+        {
+            result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
+                                         StateAsCString(state));
+            result.SetStatus (eReturnStatusFailed);
+        }
+        return result.Succeeded();
+    }
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectProcessDetach
+//-------------------------------------------------------------------------
+
+class CommandObjectProcessDetach : public CommandObject
+{
+public:
+
+    CommandObjectProcessDetach () :
+        CommandObject ("process detach",
+                       "Detaches from the current process being debugged.",
+                       "process detach",
+                       eFlagProcessMustBeLaunched)
+    {
+    }
+
+    ~CommandObjectProcessDetach ()
+    {
+    }
+
+    bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        Process *process = context->GetExecutionContext().process;
+        if (process == NULL)
+        {
+            result.AppendError ("must have a valid process in order to detach");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        Error error (process->Detach());
+        if (error.Success())
+        {
+            result.SetStatus (eReturnStatusSuccessFinishResult);
+        }
+        else
+        {
+            result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+        return result.Succeeded();
+    }
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectProcessSignal
+//-------------------------------------------------------------------------
+
+class CommandObjectProcessSignal : public CommandObject
+{
+public:
+
+    CommandObjectProcessSignal () :
+        CommandObject ("process signal",
+                       "Sends a UNIX signal to the current process being debugged.",
+                       "process signal <unix-signal-number>")
+    {
+    }
+
+    ~CommandObjectProcessSignal ()
+    {
+    }
+
+    bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        Process *process = context->GetExecutionContext().process;
+        if (process == NULL)
+        {
+            result.AppendError ("no process to signal");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        if (command.GetArgumentCount() == 1)
+        {
+            int signo = Args::StringToSInt32(command.GetArgumentAtIndex(0), -1, 0);
+            if (signo == -1)
+            {
+                result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
+                result.SetStatus (eReturnStatusFailed);
+            }
+            else
+            {
+                Error error (process->Signal (signo));
+                if (error.Success())
+                {
+                    result.SetStatus (eReturnStatusSuccessFinishResult);
+                }
+                else
+                {
+                    result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
+                    result.SetStatus (eReturnStatusFailed);
+                }
+            }
+        }
+        else
+        {
+            result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
+                                        m_cmd_syntax.c_str());
+            result.SetStatus (eReturnStatusFailed);
+        }
+        return result.Succeeded();
+    }
+};
+
+
+//-------------------------------------------------------------------------
+// CommandObjectProcessInterrupt
+//-------------------------------------------------------------------------
+
+class CommandObjectProcessInterrupt : public CommandObject
+{
+public:
+
+
+    CommandObjectProcessInterrupt () :
+    CommandObject ("process interrupt",
+                   "Interrupts the current process being debugged.",
+                   "process interrupt",
+                   eFlagProcessMustBeLaunched)
+    {
+    }
+
+    ~CommandObjectProcessInterrupt ()
+    {
+    }
+
+    bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        Process *process = context->GetExecutionContext().process;
+        if (process == NULL)
+        {
+            result.AppendError ("no process to halt");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        if (command.GetArgumentCount() == 0)
+        {
+            Error error(process->Halt ());
+            if (error.Success())
+            {
+                result.SetStatus (eReturnStatusSuccessFinishResult);
+                
+                // Maybe we should add a "SuspendThreadPlans so we
+                // can halt, and keep in place all the current thread plans.
+                process->GetThreadList().DiscardThreadPlans();
+            }
+            else
+            {
+                result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
+                result.SetStatus (eReturnStatusFailed);
+            }
+        }
+        else
+        {
+            result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
+                                        m_cmd_name.c_str(),
+                                        m_cmd_syntax.c_str());
+            result.SetStatus (eReturnStatusFailed);
+        }
+        return result.Succeeded();
+    }
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectProcessKill
+//-------------------------------------------------------------------------
+
+class CommandObjectProcessKill : public CommandObject
+{
+public:
+
+    CommandObjectProcessKill () :
+    CommandObject ("process kill",
+                   "Terminates the current process being debugged.",
+                   "process kill",
+                   eFlagProcessMustBeLaunched)
+    {
+    }
+
+    ~CommandObjectProcessKill ()
+    {
+    }
+
+    bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        Process *process = context->GetExecutionContext().process;
+        if (process == NULL)
+        {
+            result.AppendError ("no process to kill");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        if (command.GetArgumentCount() == 0)
+        {
+            Error error (process->Destroy());
+            if (error.Success())
+            {
+                result.SetStatus (eReturnStatusSuccessFinishResult);
+            }
+            else
+            {
+                result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
+                result.SetStatus (eReturnStatusFailed);
+            }
+        }
+        else
+        {
+            result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
+                                        m_cmd_name.c_str(),
+                                        m_cmd_syntax.c_str());
+            result.SetStatus (eReturnStatusFailed);
+        }
+        return result.Succeeded();
+    }
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordProcess
+//-------------------------------------------------------------------------
+
+CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter *interpreter) :
+    CommandObjectMultiword ("process",
+                              "A set of commands for operating on a process.",
+                              "process <subcommand> [<subcommand-options>]")
+{
+    LoadSubCommand (CommandObjectSP (new CommandObjectProcessAttach ()), "attach", interpreter);
+    LoadSubCommand (CommandObjectSP (new CommandObjectProcessLaunch ()), "launch", interpreter);
+    LoadSubCommand (CommandObjectSP (new CommandObjectProcessContinue ()), "continue", interpreter);
+    LoadSubCommand (CommandObjectSP (new CommandObjectProcessDetach ()), "detach", interpreter);
+    LoadSubCommand (CommandObjectSP (new CommandObjectProcessSignal ()), "signal", interpreter);
+    LoadSubCommand (CommandObjectSP (new CommandObjectProcessInterrupt ()), "interrupt", interpreter);
+    LoadSubCommand (CommandObjectSP (new CommandObjectProcessKill ()), "kill", interpreter);
+}
+
+CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
+{
+}
+
diff --git a/source/Commands/CommandObjectProcess.h b/source/Commands/CommandObjectProcess.h
new file mode 100644
index 0000000..9a8d59e
--- /dev/null
+++ b/source/Commands/CommandObjectProcess.h
@@ -0,0 +1,37 @@
+//===-- CommandObjectProcess.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_CommandObjectProcess_h_
+#define liblldb_CommandObjectProcess_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordProcess
+//-------------------------------------------------------------------------
+
+class CommandObjectMultiwordProcess : public CommandObjectMultiword
+{
+public:
+    CommandObjectMultiwordProcess (CommandInterpreter *interpreter);
+
+    virtual
+    ~CommandObjectMultiwordProcess ();
+
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectProcess_h_
diff --git a/source/Commands/CommandObjectQuit.cpp b/source/Commands/CommandObjectQuit.cpp
new file mode 100644
index 0000000..b66f4b1
--- /dev/null
+++ b/source/Commands/CommandObjectQuit.cpp
@@ -0,0 +1,48 @@
+//===-- CommandObjectQuit.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectQuit.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "CommandInterpreter.h"
+#include "CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectQuit
+//-------------------------------------------------------------------------
+
+CommandObjectQuit::CommandObjectQuit () :
+    CommandObject ("quit", "Quits out of the LLDB debugger.", "quit")
+{
+}
+
+CommandObjectQuit::~CommandObjectQuit ()
+{
+}
+
+bool
+CommandObjectQuit::Execute
+(
+    Args& command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    interpreter->BroadcastEvent (CommandInterpreter::eBroadcastBitQuitCommandReceived);
+    result.SetStatus (eReturnStatusQuit);
+    return true;
+}
+
diff --git a/source/Commands/CommandObjectQuit.h b/source/Commands/CommandObjectQuit.h
new file mode 100644
index 0000000..a45d8a4
--- /dev/null
+++ b/source/Commands/CommandObjectQuit.h
@@ -0,0 +1,51 @@
+//===-- CommandObjectQuit.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_CommandObjectQuit_h_
+#define liblldb_CommandObjectQuit_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectQuit
+//-------------------------------------------------------------------------
+
+// SPECIAL NOTE!! The CommandObjectQuit is special, because the actual function to execute
+// when the user types 'quit' is passed (via function pointer) to the Command Interpreter when it
+// is constructed.  The function pointer is then stored in this CommandObjectQuit, and is invoked
+// via the CommandObjectQuit::Execute function.  This is the only command object that works this
+// way; it was done this way because different Command Interpreter callers may want or need different things
+// to be done in order to shut down properly.
+
+class CommandObjectQuit : public CommandObject
+{
+public:
+
+    CommandObjectQuit ();
+
+    virtual
+    ~CommandObjectQuit ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectQuit_h_
diff --git a/source/Commands/CommandObjectRegister.cpp b/source/Commands/CommandObjectRegister.cpp
new file mode 100644
index 0000000..c4cb705
--- /dev/null
+++ b/source/Commands/CommandObjectRegister.cpp
@@ -0,0 +1,231 @@
+//===-- CommandObjectRegister.cpp -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectRegister.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/RegisterContext.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// "register read"
+//----------------------------------------------------------------------
+class CommandObjectRegisterRead : public CommandObject
+{
+public:
+    CommandObjectRegisterRead () :
+        CommandObject ("register read",
+                       "Dump the one or more register values from the current frame.",
+                       "register read [<reg-name1> [<reg-name2> [...]]]",
+                       eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
+    {
+    }
+
+    virtual
+    ~CommandObjectRegisterRead ()
+    {
+    }
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        StreamString &output_stream = result.GetOutputStream();
+        DataExtractor reg_data;
+        ExecutionContext exe_ctx(context->GetExecutionContext());
+        RegisterContext *reg_context = exe_ctx.GetRegisterContext ();
+
+        if (reg_context)
+        {
+            const RegisterInfo *reg_info = NULL;
+            if (command.GetArgumentCount() == 0)
+            {
+                uint32_t set_idx;
+                const uint32_t num_register_sets = reg_context->GetRegisterSetCount();
+                for (set_idx = 0; set_idx < num_register_sets; ++set_idx)
+                {
+                    uint32_t unavailable_count = 0;
+                    const RegisterSet * const reg_set = reg_context->GetRegisterSet(set_idx);
+                    output_stream.Printf ("%s:\n", reg_set->name);
+                    output_stream.IndentMore ();
+                    const uint32_t num_registers = reg_set->num_registers;
+                    for (uint32_t reg_idx = 0; reg_idx < num_registers; ++reg_idx)
+                    {
+                        uint32_t reg = reg_set->registers[reg_idx];
+                        reg_info = reg_context->GetRegisterInfoAtIndex(reg);
+                        if (reg_context->ReadRegisterBytes(reg, reg_data))
+                        {
+                            output_stream.Indent ();
+                            output_stream.Printf ("%-12s = ", reg_info ? reg_info->name : "<INVALID REGINFO>");
+                            reg_data.Dump(&output_stream, 0, reg_info->format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
+                            output_stream.EOL();
+                        }
+                        else
+                        {
+                            ++unavailable_count;
+                        }
+                    }
+                    if (unavailable_count)
+                    {
+                        output_stream.Indent ();
+                        output_stream.Printf("%u registers were unavailable.\n", unavailable_count);
+                    }
+                    output_stream.IndentLess ();
+                    output_stream.EOL();
+                }
+            }
+            else
+            {
+                const char *arg_cstr;
+                for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
+                {
+                    reg_info = reg_context->GetRegisterInfoByName(arg_cstr);
+
+                    if (reg_info)
+                    {
+                        output_stream.Printf("%-12s = ", reg_info->name);
+                        if (reg_context->ReadRegisterBytes(reg_info->reg, reg_data))
+                        {
+                            reg_data.Dump(&output_stream, 0, reg_info->format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
+                        }
+                        else
+                        {
+                            output_stream.PutCString ("error: unavailable");
+                        }
+                        output_stream.EOL();
+                    }
+                    else
+                    {
+                        result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr);
+                    }
+                }
+            }
+        }
+        else
+        {
+            result.AppendError ("no current frame");
+            result.SetStatus (eReturnStatusFailed);
+        }
+        return result.Succeeded();
+    }
+};
+
+
+//----------------------------------------------------------------------
+// "register write"
+//----------------------------------------------------------------------
+class CommandObjectRegisterWrite : public CommandObject
+{
+public:
+    CommandObjectRegisterWrite () :
+        CommandObject ("register write",
+                       "Modify a single register value.",
+                       "register write <reg-name> <value>",
+                       eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
+    {
+    }
+
+    virtual
+    ~CommandObjectRegisterWrite ()
+    {
+    }
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        DataExtractor reg_data;
+        ExecutionContext exe_ctx(context->GetExecutionContext());
+        RegisterContext *reg_context = exe_ctx.GetRegisterContext ();
+
+        if (reg_context)
+        {
+            if (command.GetArgumentCount() != 2)
+            {
+                result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>");
+                result.SetStatus (eReturnStatusFailed);
+            }
+            else
+            {
+                const char *reg_name = command.GetArgumentAtIndex(0);
+                const char *value_str = command.GetArgumentAtIndex(1);
+                const RegisterInfo *reg_info = reg_context->GetRegisterInfoByName(reg_name);
+
+                if (reg_info)
+                {
+                    Scalar scalar;
+                    Error error(scalar.SetValueFromCString (value_str, reg_info->encoding, reg_info->byte_size));
+                    if (error.Success())
+                    {
+                        if (reg_context->WriteRegisterValue(reg_info->reg, scalar))
+                        {
+                            result.SetStatus (eReturnStatusSuccessFinishNoResult);
+                            return true;
+                        }
+                    }
+                    else
+                    {
+                        result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n",
+                                                     reg_name,
+                                                     value_str,
+                                                     error.AsCString());
+                        result.SetStatus (eReturnStatusFailed);
+                    }
+                }
+                else
+                {
+                    result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name);
+                    result.SetStatus (eReturnStatusFailed);
+                }
+            }
+        }
+        else
+        {
+            result.AppendError ("no current frame");
+            result.SetStatus (eReturnStatusFailed);
+        }
+        return result.Succeeded();
+    }
+};
+
+
+//----------------------------------------------------------------------
+// CommandObjectRegister constructor
+//----------------------------------------------------------------------
+CommandObjectRegister::CommandObjectRegister(CommandInterpreter *interpreter) :
+    CommandObjectMultiword ("register",
+                            "Access thread registers.",
+                            "register [read|write] ...")
+{
+    LoadSubCommand (CommandObjectSP (new CommandObjectRegisterRead ()), "read", interpreter);
+    LoadSubCommand (CommandObjectSP (new CommandObjectRegisterWrite ()), "write", interpreter);
+}
+
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+CommandObjectRegister::~CommandObjectRegister()
+{
+}
diff --git a/source/Commands/CommandObjectRegister.h b/source/Commands/CommandObjectRegister.h
new file mode 100644
index 0000000..740bc54
--- /dev/null
+++ b/source/Commands/CommandObjectRegister.h
@@ -0,0 +1,44 @@
+//===-- CommandObjectRegister.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_CommandObjectRegister_h_
+#define liblldb_CommandObjectRegister_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectRegister
+//-------------------------------------------------------------------------
+
+class CommandObjectRegister : public CommandObjectMultiword
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    CommandObjectRegister(CommandInterpreter *interpreter);
+    virtual
+    ~CommandObjectRegister();
+
+private:
+    //------------------------------------------------------------------
+    // For CommandObjectRegister only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (CommandObjectRegister);
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectRegister_h_
diff --git a/source/Commands/CommandObjectRemove.cpp b/source/Commands/CommandObjectRemove.cpp
new file mode 100644
index 0000000..28736cd
--- /dev/null
+++ b/source/Commands/CommandObjectRemove.cpp
@@ -0,0 +1,89 @@
+//===-- CommandObjectRemove.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectRemove.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectRemove
+//-------------------------------------------------------------------------
+
+CommandObjectRemove::CommandObjectRemove () :
+    CommandObject ("remove",
+                     "Allows the user to remove/delete user-defined command functions (script functions).",
+                     "remove <command-name-to-be-removed>")
+{
+}
+
+CommandObjectRemove::~CommandObjectRemove()
+{
+}
+
+
+bool
+CommandObjectRemove::Execute (Args& args, CommandContext *context, CommandInterpreter *interpreter,
+                              CommandReturnObject &result)
+{
+    CommandObject::CommandMap::iterator pos;
+    CommandObject *cmd_obj;
+
+    if (args.GetArgumentCount() != 0)
+    {
+        const char *command_name = args.GetArgumentAtIndex(0);
+        cmd_obj = interpreter->GetCommandObject(command_name);
+        if (cmd_obj)
+        {
+            if (interpreter->CommandExists (command_name))
+            {
+                result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
+                                              command_name);
+                result.SetStatus (eReturnStatusFailed);
+            }
+            else
+            {
+
+                if (interpreter->RemoveUser (command_name) == false)
+                {
+                    if (interpreter->UserCommandExists (command_name))
+                        result.AppendErrorWithFormat ("Unknown error occurred; unable to remove command '%s'.\n",
+                                                     command_name);
+                    else
+                        result.AppendErrorWithFormat ("'%s' is not a user-defined command/function name.\n",
+                                                     command_name);
+                    result.SetStatus (eReturnStatusFailed);
+                }
+                else
+                    result.SetStatus (eReturnStatusSuccessFinishNoResult);
+            }
+        }
+        else
+        {
+            result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a current list of commands.\n",
+                                         command_name);
+            result.SetStatus (eReturnStatusFailed);
+        }
+    }
+    else
+    {
+        result.AppendError ("must call remove with a valid command");
+        result.SetStatus (eReturnStatusFailed);
+    }
+
+    return result.Succeeded();
+}
+
diff --git a/source/Commands/CommandObjectRemove.h b/source/Commands/CommandObjectRemove.h
new file mode 100644
index 0000000..4b017a4
--- /dev/null
+++ b/source/Commands/CommandObjectRemove.h
@@ -0,0 +1,44 @@
+//===-- CommandObjectRemove.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_CommandObjectRemove_h_
+#define liblldb_CommandObjectRemove_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectRemove
+//-------------------------------------------------------------------------
+
+class CommandObjectRemove : public CommandObject
+{
+public:
+
+    CommandObjectRemove ();
+
+    virtual
+    ~CommandObjectRemove ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectRemove_h_
diff --git a/source/Commands/CommandObjectScript.cpp b/source/Commands/CommandObjectScript.cpp
new file mode 100644
index 0000000..64864be
--- /dev/null
+++ b/source/Commands/CommandObjectScript.cpp
@@ -0,0 +1,149 @@
+//===-- CommandObjectScript.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectScript.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Interpreter/ScriptInterpreterPython.h"
+#include "lldb/Interpreter/ScriptInterpreterNone.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectScript
+//-------------------------------------------------------------------------
+
+CommandObjectScript::CommandObjectScript (ScriptLanguage script_lang) :
+    CommandObject ("script",
+                   "Passes an expression to the script interpreter for evaluation and returns the results. Drops user into the interactive interpreter if no expressions are given.",
+                   "script [<script-expressions-for-evaluation>]"),
+    m_script_lang (script_lang),
+    m_interpreter_ap ()
+{
+}
+
+CommandObjectScript::~CommandObjectScript ()
+{
+}
+
+bool
+CommandObjectScript::ExecuteRawCommandString
+(
+    const char *command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    std::string arg_str (command);
+
+    ScriptInterpreter *script_interpreter = GetInterpreter ();
+
+    if (script_interpreter == NULL)
+    {
+        result.AppendError("no script interpeter");
+        result.SetStatus (eReturnStatusFailed);
+    }
+
+    FILE *out_fh = Debugger::GetSharedInstance().GetOutputFileHandle();
+    FILE *err_fh = Debugger::GetSharedInstance().GetOutputFileHandle();
+    if (out_fh && err_fh)
+    {
+        if (arg_str.empty())
+            script_interpreter->ExecuteInterpreterLoop (out_fh, err_fh);
+        else
+            script_interpreter->ExecuteOneLine (arg_str, out_fh, err_fh); 
+        result.SetStatus (eReturnStatusSuccessFinishNoResult);
+    }
+    else
+    {
+        if (out_fh == NULL)
+            result.AppendError("invalid output file handle");
+        else
+            result.AppendError("invalid error file handle");
+    }
+    return result.Succeeded();
+}
+
+bool
+CommandObjectScript::WantsRawCommandString()
+{
+    return true;
+}
+
+bool
+CommandObjectScript::Execute
+(
+    Args& command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    std::string arg_str;
+    ScriptInterpreter *script_interpreter = GetInterpreter ();
+
+    if (script_interpreter == NULL)
+    {
+        result.AppendError("no script interpeter");
+        result.SetStatus (eReturnStatusFailed);
+    }
+
+    const int argc = command.GetArgumentCount();
+    for (int i = 0; i < argc; ++i)
+        arg_str.append(command.GetArgumentAtIndex(i));
+
+
+    FILE *out_fh = Debugger::GetSharedInstance().GetOutputFileHandle();
+    FILE *err_fh = Debugger::GetSharedInstance().GetOutputFileHandle();
+    if (out_fh && err_fh)
+    {
+        if (arg_str.empty())
+            script_interpreter->ExecuteInterpreterLoop (out_fh, err_fh);
+        else
+            script_interpreter->ExecuteOneLine (arg_str, out_fh, err_fh); 
+        result.SetStatus (eReturnStatusSuccessFinishNoResult);
+    }
+    else
+    {
+        if (out_fh == NULL)
+            result.AppendError("invalid output file handle");
+        else
+            result.AppendError("invalid error file handle");
+    }
+    return result.Succeeded();
+}
+
+
+ScriptInterpreter *
+CommandObjectScript::GetInterpreter ()
+{
+    if (m_interpreter_ap.get() == NULL)
+    {
+        switch (m_script_lang)
+        {
+        case eScriptLanguagePython:
+            m_interpreter_ap.reset (new ScriptInterpreterPython ());
+            break;
+
+        case eScriptLanguageNone:
+            m_interpreter_ap.reset (new ScriptInterpreterNone ());
+            break;
+        }
+    }
+    return m_interpreter_ap.get();
+}
diff --git a/source/Commands/CommandObjectScript.h b/source/Commands/CommandObjectScript.h
new file mode 100644
index 0000000..7cd5751
--- /dev/null
+++ b/source/Commands/CommandObjectScript.h
@@ -0,0 +1,58 @@
+//===-- CommandObjectScript.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_CommandObjectScript_h_
+#define liblldb_CommandObjectScript_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectScript
+//-------------------------------------------------------------------------
+
+class CommandObjectScript : public CommandObject
+{
+public:
+
+    CommandObjectScript (lldb::ScriptLanguage script_lang);
+
+    virtual
+    ~CommandObjectScript ();
+
+    bool WantsRawCommandString();
+
+    virtual bool
+    ExecuteRawCommandString (const char *command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+    ScriptInterpreter *
+    GetInterpreter ();
+
+private:
+    lldb::ScriptLanguage m_script_lang;
+    std::auto_ptr<ScriptInterpreter> m_interpreter_ap;
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectScript_h_
diff --git a/source/Commands/CommandObjectSelect.cpp b/source/Commands/CommandObjectSelect.cpp
new file mode 100644
index 0000000..f357cd2
--- /dev/null
+++ b/source/Commands/CommandObjectSelect.cpp
@@ -0,0 +1,32 @@
+//===-- CommandObjectSelect.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectSelect.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectSelect
+//-------------------------------------------------------------------------
+
+CommandObjectSelect::CommandObjectSelect () :
+    CommandObjectCrossref ("select", "Lists the kinds of objects you can select, and shows syntax for selecting them.", "select")
+{
+}
+
+CommandObjectSelect::~CommandObjectSelect ()
+{
+}
+
+
diff --git a/source/Commands/CommandObjectSelect.h b/source/Commands/CommandObjectSelect.h
new file mode 100644
index 0000000..18a64eb
--- /dev/null
+++ b/source/Commands/CommandObjectSelect.h
@@ -0,0 +1,37 @@
+//===-- CommandObjectSelect.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_CommandObjectSelect_h_
+#define liblldb_CommandObjectSelect_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectCrossref.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectSelect
+//-------------------------------------------------------------------------
+
+class CommandObjectSelect : public CommandObjectCrossref
+{
+public:
+    CommandObjectSelect ();
+
+    virtual
+    ~CommandObjectSelect ();
+
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectSelect_h_
diff --git a/source/Commands/CommandObjectSet.cpp b/source/Commands/CommandObjectSet.cpp
new file mode 100644
index 0000000..46ad049
--- /dev/null
+++ b/source/Commands/CommandObjectSet.cpp
@@ -0,0 +1,153 @@
+//===-- CommandObjectSet.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectSet.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectSet
+//-------------------------------------------------------------------------
+
+CommandObjectSet::CommandObjectSet () :
+    CommandObject ("set",
+                   "Allows the user to set or change the value of a single debugger setting variable.",
+                   "set <setting_name> <value>")
+{
+}
+
+CommandObjectSet::~CommandObjectSet()
+{
+}
+
+
+bool
+CommandObjectSet::Execute
+(
+    Args& command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    CommandInterpreter::VariableMap::iterator pos;
+
+    const int argc = command.GetArgumentCount();
+
+    if (argc < 1)
+    {
+        result.AppendError ("'set' takes at least two arguments");
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+
+    const char *var_name = command.GetArgumentAtIndex(0);
+    const char *var_value = command.GetArgumentAtIndex(1);
+
+    if (var_name == NULL || var_name[0] == '\0')
+    {
+        result.AppendError ("'set' command requires a valid variable name; No value supplied");
+        result.SetStatus (eReturnStatusFailed);
+    }
+    else if (var_value == NULL || var_value[0] == '\0')
+    {
+        // No value given:  Check to see if we're trying to clear an array.
+        StateVariable *var = interpreter->GetStateVariable (var_name);
+        if (var != NULL
+            && var->GetType() == StateVariable::eTypeStringArray)
+        {
+            var->ArrayClearValues();
+            result.SetStatus (eReturnStatusSuccessFinishNoResult);
+        }
+        else
+        {
+            result.AppendError ("'set' command requires a valid variable value; No value supplied");
+            result.SetStatus (eReturnStatusFailed);
+        }
+    }
+    else
+    {
+        StateVariable *var = interpreter->GetStateVariable(var_name);
+        if (var == NULL)
+        {
+            result.AppendErrorWithFormat ("'%s' is not a settable internal variable.\n", var_name);
+            result.SetStatus (eReturnStatusFailed);
+        }
+        else
+        {
+            result.SetStatus (eReturnStatusSuccessFinishNoResult);
+            if (var->GetType() == StateVariable::eTypeBoolean)
+            {
+                bool success = false;
+                bool new_value = Args::StringToBoolean (var_value, false, &success);
+
+                if (success)
+                {
+                    result.SetStatus(eReturnStatusSuccessFinishResult);
+                    if (!var->HasVerifyFunction() || var->VerifyValue (interpreter, (void *) &new_value, result))
+                        var->SetBoolValue (new_value);
+                }
+                else
+                {
+                    result.AppendErrorWithFormat ("Invalid boolean string '%s'.\n", var_value);
+                    result.SetStatus (eReturnStatusFailed);
+                }
+            }
+            else if (var->GetType() == StateVariable::eTypeInteger)
+            {
+                bool success = false;
+                int new_value = Args::StringToSInt32(var_value, -1, 0, &success);
+
+                if (success)
+                {
+                    result.SetStatus(eReturnStatusSuccessFinishResult);
+                    if (!var->HasVerifyFunction() || var->VerifyValue (interpreter, (void *) &new_value, result))
+                        var->SetIntValue (new_value);
+                }
+                else
+                {
+                    result.AppendErrorWithFormat ("Invalid boolean string '%s'.\n", var_value);
+                    result.SetStatus (eReturnStatusFailed);
+                }
+            }
+            else if (var->GetType() == StateVariable::eTypeString)
+            {
+                if (!var->HasVerifyFunction() || var->VerifyValue (interpreter, (void *) var_value, result))
+                    var->SetStringValue (var_value);
+            }
+            else if (var->GetType() == StateVariable::eTypeStringArray)
+            {
+                if (var_value == NULL || var_value[0] == '\0')
+                    var->ArrayClearValues ();
+                else
+                {
+                    command.Shift(); // shift off variable name
+                    var->ArrayClearValues(); // clear the old values
+                    var->GetArgs().AppendArguments (command); // set the new values.
+                }
+            }
+            else
+            {
+                result.AppendErrorWithFormat ("Variable '%s' has unrecognized type.\n",
+                                              var->GetName());
+                result.SetStatus (eReturnStatusFailed);
+            }
+        }
+    }
+    return result.Succeeded();
+}
+
diff --git a/source/Commands/CommandObjectSet.h b/source/Commands/CommandObjectSet.h
new file mode 100644
index 0000000..1a3c3df
--- /dev/null
+++ b/source/Commands/CommandObjectSet.h
@@ -0,0 +1,44 @@
+//===-- CommandObjectSet.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_CommandObjectSet_h_
+#define liblldb_CommandObjectSet_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectSet
+//-------------------------------------------------------------------------
+
+class CommandObjectSet : public CommandObject
+{
+public:
+
+    CommandObjectSet ();
+
+    virtual
+    ~CommandObjectSet ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectSet_h_
diff --git a/source/Commands/CommandObjectSettings.cpp b/source/Commands/CommandObjectSettings.cpp
new file mode 100644
index 0000000..078b699
--- /dev/null
+++ b/source/Commands/CommandObjectSettings.cpp
@@ -0,0 +1,62 @@
+//===-- CommandObjectSettings.cpp -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectSettings.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectSettings
+//-------------------------------------------------------------------------
+
+CommandObjectSettings::CommandObjectSettings () :
+    CommandObject ("settings",
+                   "Lists the debugger settings variables available to the user to 'set' or 'show'.",
+                   "settings")
+{
+}
+
+CommandObjectSettings::~CommandObjectSettings()
+{
+}
+
+
+bool
+CommandObjectSettings::Execute
+(
+    Args& command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    CommandInterpreter::VariableMap::iterator pos;
+
+    if (command.GetArgumentCount() != 0)
+    {
+        result.AppendError ("'settings' does not take any arguments");
+        result.SetStatus (eReturnStatusFailed);
+    }
+    else
+    {
+        interpreter->ShowVariableHelp (result);
+        result.SetStatus (eReturnStatusSuccessFinishNoResult);
+    }
+
+    return result.Succeeded();
+}
+
diff --git a/source/Commands/CommandObjectSettings.h b/source/Commands/CommandObjectSettings.h
new file mode 100644
index 0000000..674a98b
--- /dev/null
+++ b/source/Commands/CommandObjectSettings.h
@@ -0,0 +1,44 @@
+//===-- CommandObjectSettings.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_CommandObjectSettings_h_
+#define liblldb_CommandObjectSettings_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectSettings
+//-------------------------------------------------------------------------
+
+class CommandObjectSettings : public CommandObject
+{
+public:
+
+    CommandObjectSettings ();
+
+    virtual
+    ~CommandObjectSettings ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectSettings_h_
diff --git a/source/Commands/CommandObjectShow.cpp b/source/Commands/CommandObjectShow.cpp
new file mode 100644
index 0000000..be6f688
--- /dev/null
+++ b/source/Commands/CommandObjectShow.cpp
@@ -0,0 +1,74 @@
+//===-- CommandObjectShow.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectShow.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectShow
+//-------------------------------------------------------------------------
+
+CommandObjectShow::CommandObjectShow () :
+    CommandObject ("show",
+                    "Allows the user to see a single debugger setting variable and its value, or lists them all.",
+                    "show [<setting-variable-name>]")
+{
+}
+
+CommandObjectShow::~CommandObjectShow()
+{
+}
+
+
+bool
+CommandObjectShow::Execute
+(
+    Args& command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    CommandInterpreter::VariableMap::iterator pos;
+
+    if (command.GetArgumentCount())
+    {
+        // The user requested to see the value of a particular variable.
+
+        const char *var_name = command.GetArgumentAtIndex(0);
+        StateVariable *var = interpreter->GetStateVariable(var_name);
+        if (var)
+        {
+            var->AppendVariableInformation (result);
+            result.SetStatus (eReturnStatusSuccessFinishNoResult);
+        }
+        else
+        {
+            result.AppendErrorWithFormat ("Unrecognized variable '%s'; cannot do 'show' command.\n", var_name);
+            result.SetStatus (eReturnStatusFailed);
+        }
+    }
+    else
+    {
+        // The user didn't specify a particular variable, so show the values of all of them.
+        interpreter->ShowVariableValues(result);
+        result.SetStatus (eReturnStatusSuccessFinishNoResult);
+    }
+
+    return result.Succeeded();
+}
diff --git a/source/Commands/CommandObjectShow.h b/source/Commands/CommandObjectShow.h
new file mode 100644
index 0000000..460280a
--- /dev/null
+++ b/source/Commands/CommandObjectShow.h
@@ -0,0 +1,44 @@
+//===-- CommandObjectShow.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_CommandObjectShow_h_
+#define liblldb_CommandObjectShow_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectShow
+//-------------------------------------------------------------------------
+
+class CommandObjectShow : public CommandObject
+{
+public:
+
+    CommandObjectShow ();
+
+    virtual
+    ~CommandObjectShow ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectShow_h_
diff --git a/source/Commands/CommandObjectSource.cpp b/source/Commands/CommandObjectSource.cpp
new file mode 100644
index 0000000..e2c3a0a
--- /dev/null
+++ b/source/Commands/CommandObjectSource.cpp
@@ -0,0 +1,127 @@
+//===-- CommandObjectSource.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectSource.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/TargetList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+const char *k_space_characters = "\t\n\v\f\r ";
+
+//-------------------------------------------------------------------------
+// CommandObjectSource
+//-------------------------------------------------------------------------
+
+CommandObjectSource::CommandObjectSource() :
+    CommandObject ("source",
+                   "Reads in debugger commands from the file <filename> and executes them.",
+                   "source <filename>")
+{
+}
+
+CommandObjectSource::~CommandObjectSource ()
+{
+}
+
+bool
+CommandObjectSource::Execute
+(
+    Args& args,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    const int argc = args.GetArgumentCount();
+    if (argc == 1)
+    {
+        const char *filename = args.GetArgumentAtIndex(0);
+        bool success = true;
+
+        result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
+
+        FileSpec cmd_file (filename);
+        if (cmd_file.Exists())
+        {
+            STLStringArray commands;
+            success = cmd_file.ReadFileLines (commands);
+
+            STLStringArray::iterator pos = commands.begin();
+
+            // Trim out any empty lines or lines that start with the comment
+            // char '#'
+            while (pos != commands.end())
+            {
+                bool remove_string = false;
+                size_t non_space = pos->find_first_not_of (k_space_characters);
+                if (non_space == std::string::npos)
+                    remove_string = true; // Empty line
+                else if ((*pos)[non_space] == '#')
+                    remove_string = true; // Comment line that starts with '#'
+
+                if (remove_string)
+                    pos = commands.erase(pos);
+                else
+                    ++pos;
+            }
+
+            if (commands.size() > 0)
+            {
+                const size_t num_commands = commands.size();
+                size_t i;
+                for (i = 0; i<num_commands; ++i)
+                {
+                    result.GetOutputStream().Printf("%s %s\n", interpreter->GetPrompt(), commands[i].c_str());
+                    if (!interpreter->HandleCommand(commands[i].c_str(), false, result))
+                        break;
+                }
+
+                if (i < num_commands)
+                {
+                    result.AppendErrorWithFormat("Aborting source of '%s' after command '%s' failed.\n", filename, commands[i].c_str());
+                    result.SetStatus (eReturnStatusSuccessFinishResult);
+                }
+                else
+                {
+                    success = true;
+                    result.SetStatus (eReturnStatusFailed);
+                }
+            }
+        }
+        else
+        {
+            result.AppendErrorWithFormat ("File '%s' does not exist.\n", filename);
+            result.SetStatus (eReturnStatusFailed);
+            success = false;
+        }
+
+        if (success)
+        {
+            result.SetStatus (eReturnStatusSuccessFinishNoResult);
+        }
+    }
+    else
+    {
+        result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName());
+        result.SetStatus (eReturnStatusFailed);
+    }
+    return result.Succeeded();
+
+}
diff --git a/source/Commands/CommandObjectSource.h b/source/Commands/CommandObjectSource.h
new file mode 100644
index 0000000..416e3c0
--- /dev/null
+++ b/source/Commands/CommandObjectSource.h
@@ -0,0 +1,48 @@
+//===-- CommandObjectSource.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_CommandObjectSource_h_
+#define liblldb_CommandObjectSource_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Core/STLUtils.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectSource
+//-------------------------------------------------------------------------
+
+class CommandObjectSource : public CommandObject
+{
+public:
+
+    CommandObjectSource ();
+
+    virtual
+    ~CommandObjectSource ();
+
+    STLStringArray &
+    GetCommands ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectSource_h_
diff --git a/source/Commands/CommandObjectSourceFile.cpp b/source/Commands/CommandObjectSourceFile.cpp
new file mode 100644
index 0000000..df70bc9
--- /dev/null
+++ b/source/Commands/CommandObjectSourceFile.cpp
@@ -0,0 +1,206 @@
+//===-- CommandObjectSourceFile.cpp -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectSourceFile.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Core/SourceManager.h"
+#include "lldb/Target/TargetList.h"
+#include "lldb/Interpreter/CommandCompletions.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+CommandObjectSourceFile::CommandOptions::CommandOptions () :
+    Options()
+{
+}
+
+CommandObjectSourceFile::CommandOptions::~CommandOptions ()
+{
+}
+
+Error
+CommandObjectSourceFile::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
+{
+    Error error;
+    const char short_option = g_option_table[option_idx].short_option;
+    switch (short_option)
+    {
+    case 'l':
+        start_line = Args::StringToUInt32 (option_arg, 0);
+        if (start_line == 0)
+            error.SetErrorStringWithFormat("Invalid line number: '%s'.\n", option_arg);
+        break;
+
+    case 'n':
+        num_lines = Args::StringToUInt32 (option_arg, 0);
+        if (num_lines == 0)
+            error.SetErrorStringWithFormat("Invalid line count: '%s'.\n", option_arg);
+        break;
+
+     case 'f':
+        file_name = option_arg;
+        break;
+
+   default:
+        error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
+        break;
+    }
+
+    return error;
+}
+
+void
+CommandObjectSourceFile::CommandOptions::ResetOptionValues ()
+{
+    Options::ResetOptionValues();
+
+    file_spec.Clear();
+    file_name.clear();
+    start_line = 0;
+    num_lines = 10;
+}
+
+const lldb::OptionDefinition*
+CommandObjectSourceFile::CommandOptions::GetDefinitions ()
+{
+    return g_option_table;
+}
+
+lldb::OptionDefinition
+CommandObjectSourceFile::CommandOptions::g_option_table[] =
+{
+{ 0, false, "line",       'l', required_argument, NULL, 0, "<line>",    "The line number at which to start the display source."},
+{ 0, false, "file",       'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, "<file>",    "The file from which to display source."},
+{ 0, false, "count",      'n', required_argument, NULL, 0, "<count>",   "The number of source lines to display."},
+{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+
+
+//-------------------------------------------------------------------------
+// CommandObjectSourceFile
+//-------------------------------------------------------------------------
+
+CommandObjectSourceFile::CommandObjectSourceFile() :
+    CommandObject ("source-file",
+                     "Display source files from the current executable's debug info.",
+                     "source-file [<cmd-options>] [<filename>]")
+{
+}
+
+CommandObjectSourceFile::~CommandObjectSourceFile ()
+{
+}
+
+
+Options *
+CommandObjectSourceFile::GetOptions ()
+{
+    return &m_options;
+}
+
+
+bool
+CommandObjectSourceFile::Execute
+(
+    Args& args,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    const int argc = args.GetArgumentCount();
+
+    if (argc != 0)
+    {
+        result.AppendErrorWithFormat("'%s' takes no arguments, only flags.\n", GetCommandName());
+        result.SetStatus (eReturnStatusFailed);
+    }
+
+    ExecutionContext exe_ctx(context->GetExecutionContext());
+    if (m_options.file_name.empty())
+    {
+        // Last valid source manager context, or the current frame if no
+        // valid last context in source manager.
+        // One little trick here, if you type the exact same list command twice in a row, it is
+        // more likely because you typed it once, then typed it again
+        if (m_options.start_line == 0)
+        {
+            if (interpreter->GetSourceManager().DisplayMoreWithLineNumbers (&result.GetOutputStream()))
+            {
+                result.SetStatus (eReturnStatusSuccessFinishResult);
+            }
+        }
+        else
+        {
+            if (interpreter->GetSourceManager().DisplaySourceLinesWithLineNumbersUsingLastFile(
+                        m_options.start_line,   // Line to display
+                        0,                      // Lines before line to display
+                        m_options.num_lines,    // Lines after line to display
+                        "",                     // Don't mark "line"
+                        &result.GetOutputStream()))
+            {
+                result.SetStatus (eReturnStatusSuccessFinishResult);
+            }
+
+        }
+    }
+    else
+    {
+        const char *filename = m_options.file_name.c_str();
+        Target *target = context->GetTarget();
+        if (target == NULL)
+        {
+            result.AppendError ("invalid target, set executable file using 'file' command");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+
+        bool check_inlines = false;
+        SymbolContextList sc_list;
+        size_t num_matches = target->GetImages().ResolveSymbolContextForFilePath (filename,
+                                                                                  0,
+                                                                                  check_inlines,
+                                                                                  eSymbolContextModule | eSymbolContextCompUnit,
+                                                                                  sc_list);
+        if (num_matches > 0)
+        {
+            SymbolContext sc;
+            if (sc_list.GetContextAtIndex(0, sc))
+            {
+                if (sc.comp_unit)
+                {
+                    interpreter->GetSourceManager ().DisplaySourceLinesWithLineNumbers (sc.comp_unit,
+                                                                                        m_options.start_line,   // Line to display
+                                                                                        0,                      // Lines before line to display
+                                                                                        m_options.num_lines,    // Lines after line to display
+                                                                                        "",                     // Don't mark "line"
+                                                                                        &result.GetOutputStream());
+
+                    result.SetStatus (eReturnStatusSuccessFinishResult);
+
+                }
+            }
+        }
+    }
+
+    return result.Succeeded();
+}
+
diff --git a/source/Commands/CommandObjectSourceFile.h b/source/Commands/CommandObjectSourceFile.h
new file mode 100644
index 0000000..ba12f0f
--- /dev/null
+++ b/source/Commands/CommandObjectSourceFile.h
@@ -0,0 +1,80 @@
+//===-- CommandObjectSourceFile.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_CommandObjectSourceFile_h_
+#define liblldb_CommandObjectSourceFile_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Core/FileSpec.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectSourceFile
+//-------------------------------------------------------------------------
+
+class CommandObjectSourceFile : public CommandObject
+{
+public:
+    class CommandOptions : public Options
+    {
+    public:
+
+        CommandOptions ();
+
+        virtual
+        ~CommandOptions ();
+
+        virtual Error
+        SetOptionValue (int option_idx, const char *option_arg);
+
+        void
+        ResetOptionValues ();
+
+        const lldb::OptionDefinition*
+        GetDefinitions ();
+
+        // Options table: Required for subclasses of Options.
+
+        static lldb::OptionDefinition g_option_table[];
+
+        // Instance variables to hold the values for command options.
+        FileSpec file_spec;
+        std::string file_name;
+        uint32_t start_line;
+        uint32_t num_lines;
+    };
+
+    CommandObjectSourceFile ();
+
+    virtual
+    ~CommandObjectSourceFile ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+    virtual
+    Options *
+    GetOptions ();
+
+protected:
+    CommandOptions m_options;
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectSourceFile_h_
diff --git a/source/Commands/CommandObjectStatus.cpp b/source/Commands/CommandObjectStatus.cpp
new file mode 100644
index 0000000..501e0b2
--- /dev/null
+++ b/source/Commands/CommandObjectStatus.cpp
@@ -0,0 +1,97 @@
+//===-- CommandObjectStatus.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectStatus.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "CommandObjectThread.h"
+
+#include "lldb/Core/State.h"
+
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectStatus
+//-------------------------------------------------------------------------
+
+CommandObjectStatus::CommandObjectStatus () :
+    CommandObject ("status",
+                   "Shows the current status and location of executing process.",
+                   "status",
+                   0)
+{
+}
+
+CommandObjectStatus::~CommandObjectStatus()
+{
+}
+
+
+bool
+CommandObjectStatus::Execute
+(
+    Args& command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    StreamString &output_stream = result.GetOutputStream();
+    result.SetStatus (eReturnStatusSuccessFinishNoResult);
+    ExecutionContext exe_ctx(context->GetExecutionContext());
+    if (exe_ctx.process)
+    {
+        const StateType state = exe_ctx.process->GetState();
+        if (StateIsStoppedState(state))
+        {
+            if (state == eStateExited)
+            {
+                int exit_status = exe_ctx.process->GetExitStatus();
+                const char *exit_description = exe_ctx.process->GetExitDescription();
+                output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
+                                      exe_ctx.process->GetID(),
+                                      exit_status,
+                                      exit_status,
+                                      exit_description ? exit_description : "");
+            }
+            else
+            {
+                output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
+                if (exe_ctx.thread == NULL)
+                    exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
+                if (exe_ctx.thread != NULL)
+                {
+                    DisplayThreadsInfo (interpreter, &exe_ctx, result, true, true);
+                }
+                else
+                {
+                    result.AppendError ("No valid thread found in current process.");
+                    result.SetStatus (eReturnStatusFailed);
+                }
+            }
+        }
+    }
+    else
+    {
+        result.AppendError ("No current location or status available.");
+        result.SetStatus (eReturnStatusFailed);
+    }
+    return result.Succeeded();
+}
+
diff --git a/source/Commands/CommandObjectStatus.h b/source/Commands/CommandObjectStatus.h
new file mode 100644
index 0000000..da5fa7b
--- /dev/null
+++ b/source/Commands/CommandObjectStatus.h
@@ -0,0 +1,44 @@
+//===-- CommandObjectStatus.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_CommandObjectStatus_h_
+#define liblldb_CommandObjectStatus_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectStatus
+//-------------------------------------------------------------------------
+
+class CommandObjectStatus : public CommandObject
+{
+public:
+
+    CommandObjectStatus ();
+
+    ~CommandObjectStatus ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectStatus_h_
diff --git a/source/Commands/CommandObjectSyntax.cpp b/source/Commands/CommandObjectSyntax.cpp
new file mode 100644
index 0000000..b1fc42f
--- /dev/null
+++ b/source/Commands/CommandObjectSyntax.cpp
@@ -0,0 +1,148 @@
+//===-- CommandObjectSyntax.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectSyntax.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Options.h"
+
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectSyntax
+//-------------------------------------------------------------------------
+
+CommandObjectSyntax::CommandObjectSyntax () :
+    CommandObject ("syntax",
+                     "Shows the correct syntax for a given debugger command.",
+                     "syntax <command>")
+{
+}
+
+CommandObjectSyntax::~CommandObjectSyntax()
+{
+}
+
+
+bool
+CommandObjectSyntax::OldExecute
+(
+    Args& command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    CommandObject *cmd_obj;
+
+    if (command.GetArgumentCount() != 0)
+    {
+        cmd_obj = interpreter->GetCommandObject(command.GetArgumentAtIndex(0));
+        if (cmd_obj)
+        {
+            Stream &output_strm = result.GetOutputStream();
+            if (cmd_obj->GetOptions() != NULL)
+            {
+                output_strm.Printf ("\nSyntax: %s\n", cmd_obj->GetSyntax());
+                //cmd_obj->GetOptions()->GenerateOptionUsage (output_strm, cmd_obj);
+                output_strm.Printf ("(Try 'help %s' for more information on command options syntax.)\n",
+                                    cmd_obj->GetCommandName());
+                result.SetStatus (eReturnStatusSuccessFinishNoResult);
+            }
+            else
+            {
+                output_strm.Printf ("\nSyntax: %s\n", cmd_obj->GetSyntax());
+                result.SetStatus (eReturnStatusSuccessFinishNoResult);
+            }
+        }
+        else
+        {
+            result.AppendErrorWithFormat ("'%s' is not a known command.\n", command.GetArgumentAtIndex(0));
+            result.AppendError ("Try 'help' to see a current list of commands.");
+            result.SetStatus (eReturnStatusFailed);
+        }
+    }
+    else
+    {
+        result.AppendError ("Must call 'syntax' with a valid command.");
+        result.SetStatus (eReturnStatusFailed);
+    }
+    return result.Succeeded();
+}
+
+bool
+CommandObjectSyntax::Execute (Args &command, CommandContext *context, CommandInterpreter *interpreter, 
+                              CommandReturnObject &result)
+{
+    CommandObject::CommandMap::iterator pos;
+    CommandObject *cmd_obj;
+    const int argc = command.GetArgumentCount();
+
+    if (argc > 0)
+    {
+        cmd_obj = interpreter->GetCommandObject (command.GetArgumentAtIndex(0));
+        bool all_okay = true;
+        for (int i = 1; i < argc; ++i)
+        {
+            std::string sub_command = command.GetArgumentAtIndex (i);
+            if (! cmd_obj->IsMultiwordObject())
+                all_okay = false;
+            else
+            {
+                pos = ((CommandObjectMultiword *) cmd_obj)->m_subcommand_dict.find (sub_command);
+                if (pos != ((CommandObjectMultiword *) cmd_obj)->m_subcommand_dict.end())
+                    cmd_obj = pos->second.get();
+                else
+                    all_okay = false;
+            }
+        }
+        
+        if (all_okay && (cmd_obj != NULL))
+        {
+            Stream &output_strm = result.GetOutputStream();
+            if (cmd_obj->GetOptions() != NULL)
+            {
+                output_strm.Printf ("\nSyntax: %s\n", cmd_obj->GetSyntax());
+                //cmd_obj->GetOptions()->GenerateOptionUsage (output_strm, cmd_obj);
+                output_strm.Printf ("(Try 'help %s' for more information on command options syntax.)\n",
+                                    cmd_obj->GetCommandName());
+                result.SetStatus (eReturnStatusSuccessFinishNoResult);
+            }
+            else
+            {
+                output_strm.Printf ("\nSyntax: %s\n", cmd_obj->GetSyntax());
+                result.SetStatus (eReturnStatusSuccessFinishNoResult);
+            }
+        }
+        else
+        {
+            std::string cmd_string;
+            command.GetCommandString (cmd_string);
+            result.AppendErrorWithFormat ("'%s' is not a known command.\n", cmd_string.c_str());
+            result.AppendError ("Try 'help' to see a current list of commands.");
+            result.SetStatus (eReturnStatusFailed);
+        }
+    }
+    else
+    {
+        result.AppendError ("Must call 'syntax' with a valid command.");
+        result.SetStatus (eReturnStatusFailed);
+    }
+
+    return result.Succeeded();
+}
diff --git a/source/Commands/CommandObjectSyntax.h b/source/Commands/CommandObjectSyntax.h
new file mode 100644
index 0000000..e5f5f4e
--- /dev/null
+++ b/source/Commands/CommandObjectSyntax.h
@@ -0,0 +1,51 @@
+//===-- CommandObjectSyntax.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_CommandObjectSyntax_h_
+#define liblldb_CommandObjectSyntax_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectSyntax
+//-------------------------------------------------------------------------
+
+class CommandObjectSyntax : public CommandObject
+{
+public:
+
+    CommandObjectSyntax ();
+
+    virtual
+    ~CommandObjectSyntax ();
+
+    bool
+    OldExecute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+    
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectSyntax_h_
diff --git a/source/Commands/CommandObjectTarget.cpp b/source/Commands/CommandObjectTarget.cpp
new file mode 100644
index 0000000..5ea240e
--- /dev/null
+++ b/source/Commands/CommandObjectTarget.cpp
@@ -0,0 +1,430 @@
+//===-- CommandObjectTarget.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectTarget.h"
+
+// C Includes
+#include <errno.h>
+#include <sys/errno.h>
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+#pragma mark CommandObjectTargetImageSearchPaths
+
+class CommandObjectTargetImageSearchPathsAdd : public CommandObject
+{
+public:
+
+    CommandObjectTargetImageSearchPathsAdd () :
+        CommandObject ("target image-search-paths add",
+                       "Add new image search paths substitution pairs to the current target.",
+                       "target image-search-paths add <path-prefix> <new-path-prefix> [<path-prefix> <new-path-prefix>] ...")
+    {
+    }
+
+    ~CommandObjectTargetImageSearchPathsAdd ()
+    {
+    }
+
+    bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        Target * target = context->GetTarget();
+        if (target)
+        {
+            uint32_t argc = command.GetArgumentCount();
+            if (argc & 1)
+            {
+                result.AppendError ("add requires an even number of arguments");
+                result.SetStatus (eReturnStatusFailed);
+            }
+            else
+            {
+                for (uint32_t i=0; i<argc; i+=2)
+                {
+                    const char *from = command.GetArgumentAtIndex(i);
+                    const char *to = command.GetArgumentAtIndex(i+1);
+                    
+                    if (from[0] && to[0])
+                    {
+                        bool last_pair = ((argc - i) == 2);
+                        target->GetImageSearchPathList().Append(ConstString(from),
+                                                                ConstString(to),
+                                                                last_pair); // Notify if this is the last pair
+                    }
+                    else
+                    {
+                        if (from[0])
+                            result.AppendError ("<path-prefix> can't be empty");
+                        else
+                            result.AppendError ("<new-path-prefix> can't be empty");
+                        result.SetStatus (eReturnStatusFailed);
+                    }
+                }
+            }
+        }
+        else
+        {
+            result.AppendError ("invalid target");
+            result.SetStatus (eReturnStatusFailed);
+        }
+        return result.Succeeded();
+    }
+};
+
+class CommandObjectTargetImageSearchPathsClear : public CommandObject
+{
+public:
+
+    CommandObjectTargetImageSearchPathsClear () :
+        CommandObject ("target image-search-paths clear",
+                       "Clears all current image search paths substitution pairs from the current target.",
+                       "target image-search-paths clear")
+    {
+    }
+
+    ~CommandObjectTargetImageSearchPathsClear ()
+    {
+    }
+
+    bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        Target * target = context->GetTarget();
+        if (target)
+        {
+            bool notify = true;
+            target->GetImageSearchPathList().Clear(notify);
+        }
+        else
+        {
+            result.AppendError ("invalid target");
+            result.SetStatus (eReturnStatusFailed);
+        }
+        return result.Succeeded();
+    }
+};
+
+class CommandObjectTargetImageSearchPathsInsert : public CommandObject
+{
+public:
+
+    CommandObjectTargetImageSearchPathsInsert () :
+        CommandObject ("target image-search-paths insert",
+                       "Inserts a new image search paths substitution pair to the current target at the specified index.",
+                       "target image-search-paths insert <index> <path-prefix> <new-path-prefix> [<path-prefix> <new-path-prefix>] ...")
+    {
+    }
+
+    ~CommandObjectTargetImageSearchPathsInsert ()
+    {
+    }
+
+    bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        Target * target = context->GetTarget();
+        if (target)
+        {
+            uint32_t argc = command.GetArgumentCount();
+            // check for at least 3 arguments and an odd nubmer of parameters
+            if (argc >= 3 && argc & 1)
+            {
+                bool success = false;
+
+                uint32_t insert_idx = Args::StringToUInt32(command.GetArgumentAtIndex(0), UINT32_MAX, 0, &success);
+
+                if (!success)
+                {
+                    result.AppendErrorWithFormat("<index> parameter is not an integer: '%s'.\n", command.GetArgumentAtIndex(0));
+                    result.SetStatus (eReturnStatusFailed);
+                    return result.Succeeded();
+                }
+
+                // shift off the index
+                command.Shift();
+                argc = command.GetArgumentCount();
+
+                for (uint32_t i=0; i<argc; i+=2, ++insert_idx)
+                {
+                    const char *from = command.GetArgumentAtIndex(i);
+                    const char *to = command.GetArgumentAtIndex(i+1);
+                    
+                    if (from[0] && to[0])
+                    {
+                        bool last_pair = ((argc - i) == 2);
+                        target->GetImageSearchPathList().Insert (ConstString(from),
+                                                                 ConstString(to),
+                                                                 insert_idx,
+                                                                 last_pair);
+                    }
+                    else
+                    {
+                        if (from[0])
+                            result.AppendError ("<path-prefix> can't be empty");
+                        else
+                            result.AppendError ("<new-path-prefix> can't be empty");
+                        result.SetStatus (eReturnStatusFailed);
+                        return false;
+                    }
+                }
+            }
+            else
+            {
+                result.AppendError ("insert requires at least three arguments");
+                result.SetStatus (eReturnStatusFailed);
+                return result.Succeeded();
+            }
+
+        }
+        else
+        {
+            result.AppendError ("invalid target");
+            result.SetStatus (eReturnStatusFailed);
+        }
+        return result.Succeeded();
+    }
+};
+
+class CommandObjectTargetImageSearchPathsList : public CommandObject
+{
+public:
+
+    CommandObjectTargetImageSearchPathsList () :
+        CommandObject ("target image-search-paths list",
+                       "Lists all current image search paths substitution pairs in the current target.",
+                       "target image-search-paths list")
+    {
+    }
+
+    ~CommandObjectTargetImageSearchPathsList ()
+    {
+    }
+
+    bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        Target * target = context->GetTarget();
+        if (target)
+        {
+            if (command.GetArgumentCount() != 0)
+            {
+                result.AppendError ("list takes no arguments");
+                result.SetStatus (eReturnStatusFailed);
+                return result.Succeeded();
+            }
+
+            target->GetImageSearchPathList().Dump(&result.GetOutputStream());
+        }
+        else
+        {
+            result.AppendError ("invalid target");
+            result.SetStatus (eReturnStatusFailed);
+        }
+        return result.Succeeded();
+    }
+};
+
+class CommandObjectTargetImageSearchPathsQuery : public CommandObject
+{
+public:
+
+    CommandObjectTargetImageSearchPathsQuery () :
+    CommandObject ("target image-search-paths query",
+                   "Transforms a path using the first applicable image search path.",
+                   "target image-search-paths query <path>")
+    {
+    }
+
+    ~CommandObjectTargetImageSearchPathsQuery ()
+    {
+    }
+
+    bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        Target * target = context->GetTarget();
+        if (target)
+        {
+            if (command.GetArgumentCount() != 1)
+            {
+                result.AppendError ("query requires one argument");
+                result.SetStatus (eReturnStatusFailed);
+                return result.Succeeded();
+            }
+
+            ConstString orig(command.GetArgumentAtIndex(0));
+            ConstString transformed;
+            if (target->GetImageSearchPathList().RemapPath(orig, transformed))
+                result.GetOutputStream().Printf("%s\n", transformed.GetCString());
+            else
+                result.GetOutputStream().Printf("%s\n", orig.GetCString());
+        }
+        else
+        {
+            result.AppendError ("invalid target");
+            result.SetStatus (eReturnStatusFailed);
+        }
+        return result.Succeeded();
+    }
+};
+
+// TODO: implement the target select later when we start doing multiple targets
+//#pragma mark CommandObjectTargetSelect
+//
+////-------------------------------------------------------------------------
+//// CommandObjectTargetSelect
+////-------------------------------------------------------------------------
+//
+//class CommandObjectTargetSelect : public CommandObject
+//{
+//public:
+//
+//    CommandObjectTargetSelect () :
+//    CommandObject ("frame select",
+//                   "Select the current frame by index in the current thread.",
+//                   "frame select <frame-index>")
+//    {
+//    }
+//
+//    ~CommandObjectTargetSelect ()
+//    {
+//    }
+//
+//    bool
+//    Execute (Args& command,
+//             CommandContext *context,
+//             CommandInterpreter *interpreter,
+//             CommandReturnObject &result)
+//    {
+//        ExecutionContext exe_ctx (context->GetExecutionContext());
+//        if (exe_ctx.thread)
+//        {
+//            if (command.GetArgumentCount() == 1)
+//            {
+//                const char *frame_idx_cstr = command.GetArgumentAtIndex(0);
+//
+//                const uint32_t num_frames = exe_ctx.thread->GetStackFrameCount();
+//                const uint32_t frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0);
+//                if (frame_idx < num_frames)
+//                {
+//                    exe_ctx.thread->SetCurrentFrameByIndex (frame_idx);
+//                    exe_ctx.frame = exe_ctx.thread->GetCurrentFrame ().get();
+//
+//                    if (exe_ctx.frame)
+//                    {
+//                        if (DisplayFrameForExecutionContext (exe_ctx.thread,
+//                                                             exe_ctx.frame,
+//                                                             interpreter,
+//                                                             result.GetOutputStream(),
+//                                                             true,
+//                                                             true,
+//                                                             3,
+//                                                             3))
+//                        {
+//                            result.SetStatus (eReturnStatusSuccessFinishResult);
+//                            return result.Succeeded();
+//                        }
+//                    }
+//                }
+//                if (frame_idx == UINT32_MAX)
+//                    result.AppendErrorWithFormat ("Invalid frame index: %s.\n", frame_idx_cstr);
+//                else
+//                    result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx);
+//            }
+//            else
+//            {
+//                result.AppendError ("invalid arguments");
+//                result.AppendErrorWithFormat ("Usage: %s\n", m_cmd_syntax.c_str());
+//            }
+//        }
+//        else
+//        {
+//            result.AppendError ("no current thread");
+//        }
+//        result.SetStatus (eReturnStatusFailed);
+//        return false;
+//    }
+//};
+
+
+#pragma mark CommandObjectMultiwordTarget
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordImageSearchPaths
+//-------------------------------------------------------------------------
+
+class CommandObjectMultiwordImageSearchPaths : public CommandObjectMultiword
+{
+public:
+
+    CommandObjectMultiwordImageSearchPaths (CommandInterpreter *interpreter) :
+        CommandObjectMultiword ("target image-search-paths",
+                                "A set of commands for operating on debugger target image search paths.",
+                                "target image-search-paths <subcommand> [<subcommand-options>]")
+    {
+        LoadSubCommand (CommandObjectSP (new CommandObjectTargetImageSearchPathsAdd ()), "add", interpreter);
+        LoadSubCommand (CommandObjectSP (new CommandObjectTargetImageSearchPathsClear ()), "clear", interpreter);
+        LoadSubCommand (CommandObjectSP (new CommandObjectTargetImageSearchPathsInsert ()), "insert", interpreter);
+        LoadSubCommand (CommandObjectSP (new CommandObjectTargetImageSearchPathsList ()), "list", interpreter);
+        LoadSubCommand (CommandObjectSP (new CommandObjectTargetImageSearchPathsQuery ()), "query", interpreter);
+    }
+
+    ~CommandObjectMultiwordImageSearchPaths()
+    {
+    }
+};
+
+
+#pragma mark CommandObjectMultiwordTarget
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordTarget
+//-------------------------------------------------------------------------
+
+CommandObjectMultiwordTarget::CommandObjectMultiwordTarget (CommandInterpreter *interpreter) :
+    CommandObjectMultiword ("target",
+                            "A set of commands for operating on debugger targets.",
+                            "target <subcommand> [<subcommand-options>]")
+{
+    LoadSubCommand (CommandObjectSP (new CommandObjectMultiwordImageSearchPaths (interpreter)), "image-search-paths", interpreter);
+}
+
+CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget ()
+{
+}
+
diff --git a/source/Commands/CommandObjectTarget.h b/source/Commands/CommandObjectTarget.h
new file mode 100644
index 0000000..cd569e1
--- /dev/null
+++ b/source/Commands/CommandObjectTarget.h
@@ -0,0 +1,41 @@
+//===-- CommandObjectTarget.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_CommandObjectTarget_h_
+#define liblldb_CommandObjectTarget_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Options.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordTarget
+//-------------------------------------------------------------------------
+
+class CommandObjectMultiwordTarget : public CommandObjectMultiword
+{
+public:
+
+    CommandObjectMultiwordTarget (CommandInterpreter *interpreter);
+
+    virtual
+    ~CommandObjectMultiwordTarget ();
+
+
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectTarget_h_
diff --git a/source/Commands/CommandObjectThread.cpp b/source/Commands/CommandObjectThread.cpp
new file mode 100644
index 0000000..07777a1
--- /dev/null
+++ b/source/Commands/CommandObjectThread.cpp
@@ -0,0 +1,1277 @@
+//===-- CommandObjectThread.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectThread.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Options.h"
+#include "lldb/Core/State.h"
+#include "lldb/Core/SourceManager.h"
+
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanContinue.h"
+#include "lldb/Target/ThreadPlanStepInstruction.h"
+#include "lldb/Target/ThreadPlanStepOut.h"
+#include "lldb/Target/ThreadPlanStepRange.h"
+#include "lldb/Target/ThreadPlanStepInRange.h"
+#include "lldb/Symbol/LineTable.h"
+#include "lldb/Symbol/LineEntry.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+bool
+lldb_private::DisplayThreadInfo
+(
+    CommandInterpreter *interpreter,
+    Stream &strm,
+    Thread *thread,
+    bool only_threads_with_stop_reason,
+    bool show_source
+)
+{
+    if (thread)
+    {
+        if (only_threads_with_stop_reason)
+        {
+            StopReason thread_stop_reason = eStopReasonNone;
+            Thread::StopInfo thread_stop_info;
+            if (thread->GetStopInfo(&thread_stop_info))
+            {
+                thread_stop_reason = thread_stop_info.GetStopReason();
+                if (thread_stop_reason == eStopReasonNone)
+                    return false;
+            }
+        }
+
+        strm.Indent();
+        strm.Printf("%c ", thread->GetProcess().GetThreadList().GetCurrentThread().get() == thread ? '*' : ' ');
+
+        // Show one frame with only the first showing source
+        if (show_source)
+        {
+            DisplayFramesForExecutionContext (thread,
+                                              interpreter,
+                                              strm,
+                                              true,
+                                              0,    // Start at first frame
+                                              1,    // Number of frames to show
+                                              false,// Don't show the frame info since we already displayed most of it above...
+                                              1,    // Show source for the first frame
+                                              3,    // lines of source context before
+                                              3);   // lines of source context after
+        }
+        else
+        {
+            thread->DumpInfo (strm,
+                              true, // Dump the stop reason?
+                              true, // Dump the thread name?
+                              true, // Dump the queue name?
+                              0);   // Display context info for stack frame zero
+
+            strm.EOL();
+        }
+
+        return true;
+    }
+    return false;
+}
+
+size_t
+lldb_private::DisplayThreadsInfo
+(
+    CommandInterpreter *interpreter,
+    ExecutionContext *exe_ctx,
+    CommandReturnObject &result,
+    bool only_threads_with_stop_reason,
+    bool show_source
+)
+{
+    StreamString strm;
+
+    size_t num_thread_infos_dumped = 0;
+
+    if (!exe_ctx->process)
+        return 0;
+
+    const size_t num_threads = exe_ctx->process->GetThreadList().GetSize();
+    if (num_threads > 0)
+    {
+
+        for (uint32_t i = 0; i < num_threads; i++)
+        {
+            Thread *thread = exe_ctx->process->GetThreadList().GetThreadAtIndex(i).get();
+            if (thread)
+            {
+                if (DisplayThreadInfo (interpreter,
+                                       strm,
+                                       thread,
+                                       only_threads_with_stop_reason,
+                                       show_source))
+                    ++num_thread_infos_dumped;
+            }
+        }
+    }
+
+    if (num_thread_infos_dumped > 0)
+    {
+        if (num_thread_infos_dumped < num_threads)
+            result.GetOutputStream().Printf("%u of %u threads stopped with reasons:\n", num_thread_infos_dumped, num_threads);
+
+        result.GetOutputStream().GetString().append(strm.GetString());
+        result.SetStatus (eReturnStatusSuccessFinishNoResult);
+    }
+    return num_thread_infos_dumped;
+}
+
+
+size_t
+lldb_private::DisplayFramesForExecutionContext
+(
+    Thread *thread,
+    CommandInterpreter *interpreter,
+    Stream& strm,
+    bool ascending,
+    uint32_t first_frame,
+    uint32_t num_frames,
+    bool show_frame_info,
+    uint32_t num_frames_with_source,
+    uint32_t source_lines_before,
+    uint32_t source_lines_after
+)
+{
+    if (thread == NULL)
+        return 0;
+
+    size_t num_frames_displayed = 0;
+
+    if (num_frames == 0)
+        return 0;
+    
+    thread->DumpInfo (strm,
+                      true,     // Dump the stop reason?
+                      true,     // Dump the thread name?
+                      true,     // Dump the queue name?
+                      0);       // Dump info for stack frame zero
+    strm.EOL();
+    strm.IndentMore();
+
+    StackFrameSP frame_sp;
+    int frame_idx = 0;
+
+    if (ascending)
+    {
+        for (frame_idx = first_frame; frame_idx < first_frame + num_frames; ++frame_idx)
+        {
+            frame_sp = thread->GetStackFrameAtIndex (frame_idx);
+            if (frame_sp.get() == NULL)
+                break;
+
+            if (DisplayFrameForExecutionContext (thread,
+                                                 frame_sp.get(),
+                                                 interpreter,
+                                                 strm,
+                                                 show_frame_info,
+                                                 num_frames_with_source > first_frame - frame_idx,
+                                                 source_lines_before,
+                                                 source_lines_after) == false)
+                break;
+
+            ++num_frames_displayed;
+        }
+    }
+    else
+    {
+        for (frame_idx = first_frame + num_frames - 1; frame_idx >= first_frame; --frame_idx)
+        {
+            frame_sp = thread->GetStackFrameAtIndex (frame_idx);
+            if (frame_sp == NULL)
+                break;
+
+            if (DisplayFrameForExecutionContext (thread,
+                                                 frame_sp.get(),
+                                                 interpreter,
+                                                 strm,
+                                                 show_frame_info,
+                                                 num_frames_with_source > first_frame - frame_idx,
+                                                 source_lines_before,
+                                                 source_lines_after) == false)
+                break;
+
+            ++num_frames_displayed;
+        }
+    }
+    strm.IndentLess();
+    return num_frames_displayed;
+}
+
+bool
+lldb_private::DisplayFrameForExecutionContext
+(
+    Thread *thread,
+    StackFrame *frame,
+    CommandInterpreter *interpreter,
+    Stream& strm,
+    bool show_frame_info,
+    bool show_source,
+    uint32_t source_lines_before,
+    uint32_t source_lines_after
+)
+{
+    // thread and frame must be filled in prior to calling this function
+    if (thread && frame)
+    {
+        if (show_frame_info)
+        {
+            strm.Indent();
+            frame->Dump (&strm, true);
+            strm.EOL();
+        }
+
+        SymbolContext sc (frame->GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry));
+
+        if (show_source && sc.comp_unit && sc.line_entry.IsValid())
+        {
+            interpreter->GetSourceManager().DisplaySourceLinesWithLineNumbers (
+                    sc.line_entry.file,
+                    sc.line_entry.line,
+                    3,
+                    3,
+                    "->",
+                    &strm);
+
+        }
+        return true;
+    }
+    return false;
+}
+
+
+//-------------------------------------------------------------------------
+// CommandObjectThreadBacktrace
+//-------------------------------------------------------------------------
+
+class CommandObjectThreadBacktrace : public CommandObject
+{
+public:
+
+    CommandObjectThreadBacktrace () :
+        CommandObject ("thread backtrace",
+                       "Shows the stack for one or more threads.",
+                       "thread backtrace [<thread-idx>] ...",
+                       eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
+        m_ascending (true)
+    {
+    }
+
+    ~CommandObjectThreadBacktrace()
+    {
+    }
+
+
+    bool
+    Execute
+    (
+        Args& command,
+        CommandContext *context,
+        CommandInterpreter *interpreter,
+        CommandReturnObject &result
+    )
+    {
+        if (command.GetArgumentCount() == 0)
+        {
+            ExecutionContext exe_ctx(context->GetExecutionContext());
+            if (exe_ctx.thread)
+            {
+                bool show_frame_info = true;
+                uint32_t num_frames_with_source = 0; // Don't show any frasmes with source when backtracing
+                if (DisplayFramesForExecutionContext (exe_ctx.thread,
+                                                      interpreter,
+                                                      result.GetOutputStream(),
+                                                      m_ascending,
+                                                      0,
+                                                      UINT32_MAX,
+                                                      show_frame_info,
+                                                      num_frames_with_source,
+                                                      3,
+                                                      3))
+                {
+                    result.SetStatus (eReturnStatusSuccessFinishResult);
+                }
+            }
+            else
+            {
+                result.AppendError ("invalid thread");
+                result.SetStatus (eReturnStatusFailed);
+            }
+        }
+        else
+        {
+            result.AppendError ("backtrace doesn't take arguments (for now)");
+            result.SetStatus (eReturnStatusFailed);
+        }
+        return result.Succeeded();
+    }
+protected:
+    bool m_ascending;
+};
+
+
+typedef enum StepScope
+{
+    eStepScopeSource,
+    eStepScopeInstruction
+};
+
+class CommandObjectThreadStepWithTypeAndScope : public CommandObject
+{
+public:
+
+    class CommandOptions : public Options
+    {
+    public:
+
+        CommandOptions () :
+            Options()
+        {
+            // Keep default values of all options in one place: ResetOptionValues ()
+            ResetOptionValues ();
+        }
+
+        virtual
+        ~CommandOptions ()
+        {
+        }
+
+        virtual Error
+        SetOptionValue (int option_idx, const char *option_arg)
+        {
+            Error error;
+            char short_option = (char) m_getopt_table[option_idx].val;
+
+            switch (short_option)
+            {
+                case 'a':
+                {
+                    bool success;
+                    m_avoid_no_debug =  Args::StringToBoolean (option_arg, true, &success);
+                    if (!success)
+                        error.SetErrorStringWithFormat("Invalid boolean value for option '%c'.\n", short_option);
+                }
+                break;
+                case 'm':
+                {
+                    bool found_one = false;
+                    OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; 
+                    m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
+                    if (!found_one)
+                        error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
+                }
+                break;
+                default:
+                    error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
+                    break;
+
+            }
+            return error;
+        }
+
+        void
+        ResetOptionValues ()
+        {
+            Options::ResetOptionValues();
+            m_avoid_no_debug = true;
+            m_run_mode = eOnlyDuringStepping;
+        }
+
+        const lldb::OptionDefinition*
+        GetDefinitions ()
+        {
+            return g_option_table;
+        }
+
+        // Options table: Required for subclasses of Options.
+
+        static lldb::OptionDefinition g_option_table[];
+
+        // Instance variables to hold the values for command options.
+        bool m_avoid_no_debug;
+        RunMode m_run_mode;
+    };
+
+    CommandObjectThreadStepWithTypeAndScope (const char *name,
+                         const char *help,
+                         const char *syntax,
+                         uint32_t flags,
+                         StepType step_type,
+                         StepScope step_scope) :
+        CommandObject (name, help, syntax, flags),
+        m_step_type (step_type),
+        m_step_scope (step_scope),
+        m_options ()
+    {
+    }
+
+    virtual
+    ~CommandObjectThreadStepWithTypeAndScope ()
+    {
+    }
+
+    virtual
+    Options *
+    GetOptions ()
+    {
+        return &m_options;
+    }
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        Process *process = context->GetExecutionContext().process;
+        bool synchronous_execution = interpreter->GetSynchronous();
+
+        if (process == NULL)
+        {
+            result.AppendError ("need a valid process to step");
+            result.SetStatus (eReturnStatusFailed);
+
+        }
+        else
+        {
+            const uint32_t num_threads = process->GetThreadList().GetSize();
+            Thread *thread = NULL;
+
+            if (command.GetArgumentCount() == 0)
+            {
+                thread = process->GetThreadList().GetCurrentThread().get();
+                if (thread == NULL)
+                {
+                    result.AppendError ("no current thread in process");
+                    result.SetStatus (eReturnStatusFailed);
+                    return false;
+                }
+            }
+            else
+            {
+                const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
+                uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32);
+                if (step_thread_idx == LLDB_INVALID_INDEX32)
+                {
+                    result.AppendErrorWithFormat ("Invalid thread index '%s'.\n", thread_idx_cstr);
+                    result.SetStatus (eReturnStatusFailed);
+                    return false;
+                }
+                thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
+                if (thread == NULL)
+                {
+                    result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", 
+                                                  step_thread_idx, 0, num_threads);
+                    result.SetStatus (eReturnStatusFailed);
+                    return false;
+                }
+            }
+
+            const bool abort_other_plans = false;
+            const lldb::RunMode stop_other_threads = m_options.m_run_mode;
+            
+            // This is a bit unfortunate, but not all the commands in this command object support
+            // only while stepping, so I use the bool for them.
+            bool bool_stop_other_threads;
+            if (m_options.m_run_mode == eAllThreads)
+                bool_stop_other_threads = false;
+            else
+                bool_stop_other_threads = true;
+
+            if (m_step_type == eStepTypeInto)
+            {
+                StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
+                ThreadPlan *new_plan;
+
+                if (frame->HasDebugInformation ())
+                {
+                    new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, m_step_type, 
+                                                                    frame->GetSymbolContext(eSymbolContextEverything).line_entry.range, 
+                                                                    frame->GetSymbolContext(eSymbolContextEverything), 
+                                                                    stop_other_threads);
+                    if (new_plan)
+                    {
+                        ThreadPlanStepInRange *real_plan = dynamic_cast<ThreadPlanStepInRange *> (new_plan);
+                        if (real_plan)
+                        {
+                            if (m_options.m_avoid_no_debug)
+                            {
+                                real_plan->GetFlags().Set (ThreadPlanShouldStopHere::eAvoidNoDebug);
+                            }
+                            else
+                            {
+                                real_plan->GetFlags().Clear (ThreadPlanShouldStopHere::eAvoidNoDebug);
+                            }
+                        }
+                    }
+                }
+                else
+                    new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
+
+                process->GetThreadList().SetCurrentThreadByID (thread->GetID());
+                process->Resume ();
+            }
+            else if (m_step_type == eStepTypeOver)
+            {
+                StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
+                ThreadPlan *new_plan;
+
+                if (frame->HasDebugInformation())
+                    new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, 
+                                                                    m_step_type, 
+                                                                    frame->GetSymbolContext(eSymbolContextEverything).line_entry.range, 
+                                                                    frame->GetSymbolContext(eSymbolContextEverything), 
+                                                                    stop_other_threads);
+                else
+                    new_plan = thread->QueueThreadPlanForStepSingleInstruction (true, 
+                                                                                abort_other_plans, 
+                                                                                bool_stop_other_threads);
+
+                // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
+                // Maybe there should be a parameter to control this.
+                new_plan->SetOkayToDiscard(false);
+
+                process->GetThreadList().SetCurrentThreadByID (thread->GetID());
+                process->Resume ();
+            }
+            else if (m_step_type == eStepTypeTrace)
+            {
+                thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
+                process->GetThreadList().SetCurrentThreadByID (thread->GetID());
+                process->Resume ();
+            }
+            else if (m_step_type == eStepTypeTraceOver)
+            {
+                thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
+                process->GetThreadList().SetCurrentThreadByID (thread->GetID());
+                process->Resume ();
+            }
+            else if (m_step_type == eStepTypeOut)
+            {
+                ThreadPlan *new_plan;
+
+                new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, bool_stop_other_threads, eVoteYes, eVoteNoOpinion);
+                // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
+                // Maybe there should be a parameter to control this.
+                new_plan->SetOkayToDiscard(false);
+
+                process->GetThreadList().SetCurrentThreadByID (thread->GetID());
+                process->Resume ();
+            }
+            else
+            {
+                result.AppendError ("step type is not supported");
+                result.SetStatus (eReturnStatusFailed);
+            }
+            if (synchronous_execution)
+            {
+                StateType state = process->WaitForProcessToStop (NULL);
+                
+                //EventSP event_sp;
+                //StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
+                //while (! StateIsStoppedState (state))
+                //  {
+                //    state = process->WaitForStateChangedEvents (NULL, event_sp);
+                //  }
+                process->GetThreadList().SetCurrentThreadByID (thread->GetID());
+                result.SetDidChangeProcessState (true);
+                result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
+                result.SetStatus (eReturnStatusSuccessFinishNoResult);
+            }
+        }
+        return result.Succeeded();
+    }
+
+protected:
+    StepType m_step_type;
+    StepScope m_step_scope;
+    CommandOptions m_options;
+};
+
+static lldb::OptionEnumValueElement
+g_tri_running_mode[] =
+{
+{ eOnlyThisThread,     "thisThread",    "Run only this thread"},
+{ eAllThreads,         "allThreads",    "Run all threads"},
+{ eOnlyDuringStepping, "whileStepping", "Run only this thread while stepping"},
+{ 0, NULL, NULL }
+};
+
+static lldb::OptionEnumValueElement
+g_duo_running_mode[] =
+{
+{ eOnlyThisThread,     "thisThread",    "Run only this thread"},
+{ eAllThreads,         "allThreads",    "Run all threads"},
+{ 0, NULL, NULL }
+};
+
+lldb::OptionDefinition
+CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
+{
+{ 0, true, "avoid_no_debug", 'a', required_argument,       NULL, 0, "<avoid_no_debug>",        "Should step-in step over functions with no debug information"},
+{ 0, true, "run_mode", 'm', required_argument,       g_tri_running_mode, 0, "<run_mode>",        "Determine how to run other threads while stepping this one"},
+{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+
+//-------------------------------------------------------------------------
+// CommandObjectThreadContinue
+//-------------------------------------------------------------------------
+
+class CommandObjectThreadContinue : public CommandObject
+{
+public:
+
+    CommandObjectThreadContinue () :
+        CommandObject ("thread continue",
+                       "Continues execution of one or more threads in an active process.",
+                       "thread continue <thread-index> [<thread-index> ...]",
+                       eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
+    {
+    }
+
+
+    virtual
+    ~CommandObjectThreadContinue ()
+    {
+    }
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        bool synchronous_execution = interpreter->GetSynchronous ();
+
+        if (!context->GetTarget())
+        {
+            result.AppendError ("invalid target, set executable file using 'file' command");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        Process *process = context->GetExecutionContext().process;
+        if (process == NULL)
+        {
+            result.AppendError ("no process exists. Cannot continue");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        StateType state = process->GetState();
+        if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended))
+        {
+            const uint32_t num_threads = process->GetThreadList().GetSize();
+            uint32_t idx;
+            const size_t argc = command.GetArgumentCount();
+            if (argc > 0)
+            {
+                std::vector<uint32_t> resume_thread_indexes;
+                for (uint32_t i=0; i<argc; ++i)
+                {
+                    idx = Args::StringToUInt32 (command.GetArgumentAtIndex(0), LLDB_INVALID_INDEX32);
+                    if (idx < num_threads)
+                        resume_thread_indexes.push_back(idx);
+                    else
+                        result.AppendWarningWithFormat("Thread index %u out of range.\n", idx);
+                }
+
+                if (resume_thread_indexes.empty())
+                {
+                    result.AppendError ("no valid thread indexes were specified");
+                    result.SetStatus (eReturnStatusFailed);
+                    return false;
+                }
+                else
+                {
+                    result.AppendMessage ("Resuming thread ");
+                    for (idx=0; idx<num_threads; ++idx)
+                    {
+                        Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
+                        if (find(resume_thread_indexes.begin(), resume_thread_indexes.end(), idx) != resume_thread_indexes.end())
+                        {
+                            result.AppendMessageWithFormat ("%u ", idx);
+                            thread->SetResumeState (eStateRunning);
+                        }
+                        else
+                        {
+                            thread->SetResumeState (eStateSuspended);
+                        }
+                    }
+                    result.AppendMessageWithFormat ("in process %i\n", process->GetID());
+                }
+            }
+            else
+            {
+                Thread *current_thread = process->GetThreadList().GetCurrentThread().get();
+                if (current_thread == NULL)
+                {
+                    result.AppendError ("the process doesn't have a current thread");
+                    result.SetStatus (eReturnStatusFailed);
+                    return false;
+                }
+                // Set the actions that the threads should each take when resuming
+                for (idx=0; idx<num_threads; ++idx)
+                {
+                    Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
+                    if (thread == current_thread)
+                    {
+                        result.AppendMessageWithFormat ("Resuming thread 0x%4.4x in process %i\n", thread->GetID(), process->GetID());
+                        thread->SetResumeState (eStateRunning);
+                    }
+                    else
+                    {
+                        thread->SetResumeState (eStateSuspended);
+                    }
+                }
+            }
+
+            Error error (process->Resume());
+            if (error.Success())
+            {
+                result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
+                if (synchronous_execution)
+                {
+                    StateType state = process->WaitForProcessToStop (NULL);
+
+                    result.SetDidChangeProcessState (true);
+                    result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
+                    result.SetStatus (eReturnStatusSuccessFinishNoResult);
+                }
+                else
+                {
+                    result.SetStatus (eReturnStatusSuccessContinuingNoResult);
+                }
+            }
+            else
+            {
+                result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString());
+                result.SetStatus (eReturnStatusFailed);
+            }
+        }
+        else
+        {
+            result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
+                                          StateAsCString(state));
+            result.SetStatus (eReturnStatusFailed);
+        }
+
+        return result.Succeeded();
+    }
+
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectThreadUntil
+//-------------------------------------------------------------------------
+
+class CommandObjectThreadUntil : public CommandObject
+{
+public:
+
+    class CommandOptions : public Options
+    {
+    public:
+        uint32_t m_thread_idx;
+        uint32_t m_frame_idx;
+
+        CommandOptions () :
+            Options(),
+            m_thread_idx(LLDB_INVALID_THREAD_ID),
+            m_frame_idx(LLDB_INVALID_FRAME_ID)
+        {
+            // Keep default values of all options in one place: ResetOptionValues ()
+            ResetOptionValues ();
+        }
+
+        virtual
+        ~CommandOptions ()
+        {
+        }
+
+        virtual Error
+        SetOptionValue (int option_idx, const char *option_arg)
+        {
+            Error error;
+            char short_option = (char) m_getopt_table[option_idx].val;
+
+            switch (short_option)
+            {
+                case 't':
+                {
+                    uint32_t m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32);
+                    if (m_thread_idx == LLDB_INVALID_INDEX32)
+                    {
+                        error.SetErrorStringWithFormat ("Invalid thread index '%s'.\n", option_arg);
+                    }
+                }
+                break;
+                case 'f':
+                {
+                    m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID);
+                    if (m_frame_idx == LLDB_INVALID_FRAME_ID)
+                    {
+                        error.SetErrorStringWithFormat ("Invalid frame index '%s'.\n", option_arg);
+                    }
+                }
+                break;
+                case 'm':
+                {
+                    bool found_one = false;
+                    OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; 
+                    lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
+
+                    if (!found_one)
+                        error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
+                    else if (run_mode == eAllThreads)
+                        m_stop_others = false;
+                    else
+                        m_stop_others = true;
+        
+                }
+                break;
+                default:
+                    error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
+                    break;
+
+            }
+            return error;
+        }
+
+        void
+        ResetOptionValues ()
+        {
+            Options::ResetOptionValues();
+            m_thread_idx = LLDB_INVALID_THREAD_ID;
+            m_frame_idx = 0;
+            m_stop_others = false;
+        }
+
+        const lldb::OptionDefinition*
+        GetDefinitions ()
+        {
+            return g_option_table;
+        }
+
+        uint32_t m_step_thread_idx;
+        bool m_stop_others;
+
+        // Options table: Required for subclasses of Options.
+
+        static lldb::OptionDefinition g_option_table[];
+
+        // Instance variables to hold the values for command options.
+    };
+
+    CommandObjectThreadUntil () :
+        CommandObject ("thread until",
+                       "Runs the current or specified thread until it reaches a given line number or leaves the current function.",
+                       "thread until [<cmd-options>] <line-number>",
+                       eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
+        m_options ()
+    {
+    }
+
+
+    virtual
+    ~CommandObjectThreadUntil ()
+    {
+    }
+
+    virtual
+    Options *
+    GetOptions ()
+    {
+        return &m_options;
+    }
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        bool synchronous_execution = interpreter->GetSynchronous ();
+
+        if (!context->GetTarget())
+        {
+            result.AppendError ("invalid target, set executable file using 'file' command");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        Process *process = context->GetExecutionContext().process;
+        if (process == NULL)
+        {
+            result.AppendError ("need a valid process to step");
+            result.SetStatus (eReturnStatusFailed);
+
+        }
+        else
+        {
+            Thread *thread = NULL;
+            uint32_t line_number;
+
+            if (command.GetArgumentCount() != 1)
+            {
+                result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax());
+                result.SetStatus (eReturnStatusFailed);
+                return false;
+            }
+
+            line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
+            if (line_number == UINT32_MAX)
+            {
+                result.AppendErrorWithFormat ("Invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
+                result.SetStatus (eReturnStatusFailed);
+                return false;
+            }
+
+            if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
+            {
+                thread = process->GetThreadList().GetCurrentThread().get();
+            }
+            else
+            {
+                thread = process->GetThreadList().GetThreadAtIndex(m_options.m_thread_idx).get();
+            }
+
+            if (thread == NULL)
+            {
+                const uint32_t num_threads = process->GetThreadList().GetSize();
+                result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", m_options.m_thread_idx, 0, num_threads);
+                result.SetStatus (eReturnStatusFailed);
+                return false;
+            }
+
+            const bool abort_other_plans = true;
+
+            StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
+            if (frame == NULL)
+            {
+
+                result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", m_options.m_frame_idx, m_options.m_thread_idx);
+                result.SetStatus (eReturnStatusFailed);
+                return false;
+            }
+
+            ThreadPlan *new_plan;
+
+            if (frame->HasDebugInformation ())
+            {
+                // Finally we got here...  Translate the given line number to a bunch of addresses:
+                SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit));
+                LineTable *line_table = NULL;
+                if (sc.comp_unit)
+                    line_table = sc.comp_unit->GetLineTable();
+
+                if (line_table == NULL)
+                {
+                    result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n",
+                                                 m_options.m_frame_idx, m_options.m_thread_idx);
+                    result.SetStatus (eReturnStatusFailed);
+                    return false;
+                }
+
+                LineEntry function_start;
+                uint32_t index_ptr = 0, end_ptr;
+                std::vector<addr_t> address_list;
+
+                // Find the beginning & end index of the
+                AddressRange fun_addr_range = sc.function->GetAddressRange();
+                Address fun_start_addr = fun_addr_range.GetBaseAddress();
+                line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr);
+
+                Address fun_end_addr(fun_start_addr.GetSection(), fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
+                line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
+
+                while (index_ptr <= end_ptr)
+                {
+                    LineEntry line_entry;
+                    index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, &line_entry);
+                    if (index_ptr == UINT32_MAX)
+                        break;
+
+                    addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(process);
+                    if (address != LLDB_INVALID_ADDRESS)
+                        address_list.push_back (address);
+                    index_ptr++;
+                }
+
+                new_plan = thread->QueueThreadPlanForStepUntil (abort_other_plans, address_list.data(), address_list.size(), m_options.m_stop_others);
+                new_plan->SetOkayToDiscard(false);
+            }
+            else
+            {
+                result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", m_options.m_frame_idx, m_options.m_thread_idx);
+                result.SetStatus (eReturnStatusFailed);
+                return false;
+
+            }
+
+            process->GetThreadList().SetCurrentThreadByID (m_options.m_thread_idx);
+            Error error (process->Resume ());
+            if (error.Success())
+            {
+                result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
+                if (synchronous_execution)
+                {
+                    StateType state = process->WaitForProcessToStop (NULL);
+
+                    result.SetDidChangeProcessState (true);
+                    result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
+                    result.SetStatus (eReturnStatusSuccessFinishNoResult);
+                }
+                else
+                {
+                    result.SetStatus (eReturnStatusSuccessContinuingNoResult);
+                }
+            }
+            else
+            {
+                result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
+                result.SetStatus (eReturnStatusFailed);
+            }
+
+        }
+        return result.Succeeded();
+    }
+protected:
+    CommandOptions m_options;
+
+};
+
+lldb::OptionDefinition
+CommandObjectThreadUntil::CommandOptions::g_option_table[] =
+{
+{ 0, true, "frame", 'f', required_argument,       NULL, 0, "<frame>",        "Frame index for until operation - defaults to 0"},
+{ 0, true, "thread", 't', required_argument,       NULL, 0, "<thread>",      "Thread index for the thread for until operation"},
+{ 0, true, "run_mode", 'm', required_argument,       g_duo_running_mode, 0, "<run_mode>",        "Determine how to run other threads while stepping this one"},
+{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+
+//-------------------------------------------------------------------------
+// CommandObjectThreadSelect
+//-------------------------------------------------------------------------
+
+class CommandObjectThreadSelect : public CommandObject
+{
+public:
+
+    CommandObjectThreadSelect () :
+        CommandObject ("thread select",
+                         "Selects a threads as the currently active thread.",
+                         "thread select <thread-index>",
+                         eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
+    {
+    }
+
+
+    virtual
+    ~CommandObjectThreadSelect ()
+    {
+    }
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        Process *process = context->GetExecutionContext().process;
+        if (process == NULL)
+        {
+            result.AppendError ("no process");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+        else if (command.GetArgumentCount() != 1)
+        {
+            result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0);
+
+        Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
+        if (new_thread == NULL)
+        {
+            result.AppendErrorWithFormat ("Invalid thread #%s.\n", command.GetArgumentAtIndex(0));
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        process->GetThreadList().SetCurrentThreadByID(new_thread->GetID());
+        
+        DisplayThreadInfo (interpreter,
+                           result.GetOutputStream(),
+                           new_thread,
+                           false,
+                           true);
+
+        return result.Succeeded();
+    }
+
+};
+
+
+//-------------------------------------------------------------------------
+// CommandObjectThreadList
+//-------------------------------------------------------------------------
+
+CommandObjectThreadList::CommandObjectThreadList ():
+    CommandObject ("thread list",
+                     "Shows a summary of all current threads in a process.",
+                     "thread list",
+                     eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
+{
+}
+
+CommandObjectThreadList::~CommandObjectThreadList()
+{
+}
+
+bool
+CommandObjectThreadList::Execute
+(
+    Args& command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    StreamString &strm = result.GetOutputStream();
+    result.SetStatus (eReturnStatusSuccessFinishNoResult);
+    ExecutionContext exe_ctx(context->GetExecutionContext());
+    if (exe_ctx.process)
+    {
+        const StateType state = exe_ctx.process->GetState();
+
+        if (StateIsStoppedState(state))
+        {
+            if (state == eStateExited)
+            {
+                int exit_status = exe_ctx.process->GetExitStatus();
+                const char *exit_description = exe_ctx.process->GetExitDescription();
+                strm.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
+                                      exe_ctx.process->GetID(),
+                                      exit_status,
+                                      exit_status,
+                                      exit_description ? exit_description : "");
+            }
+            else
+            {
+                strm.Printf ("Process %d state is %s\n", exe_ctx.process->GetID(), StateAsCString (state));
+                if (exe_ctx.thread == NULL)
+                    exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
+                if (exe_ctx.thread != NULL)
+                {
+                    DisplayThreadsInfo (interpreter, &exe_ctx, result, false, false);
+                }
+                else
+                {
+                    result.AppendError ("no valid thread found in current process");
+                    result.SetStatus (eReturnStatusFailed);
+                }
+            }
+        }
+        else
+        {
+            result.AppendError ("process is currently running");
+            result.SetStatus (eReturnStatusFailed);
+        }
+    }
+    else
+    {
+        result.AppendError ("no current location or status available");
+        result.SetStatus (eReturnStatusFailed);
+    }
+    return result.Succeeded();
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordThread
+//-------------------------------------------------------------------------
+
+CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter *interpreter) :
+    CommandObjectMultiword ("thread",
+                            "A set of commands for operating on one or more thread within a running process.",
+                            "thread <subcommand> [<subcommand-options>]")
+{
+    LoadSubCommand (CommandObjectSP (new CommandObjectThreadBacktrace ()), "backtrace", interpreter);
+    LoadSubCommand (CommandObjectSP (new CommandObjectThreadContinue ()), "continue", interpreter);
+    LoadSubCommand (CommandObjectSP (new CommandObjectThreadList ()), "list", interpreter);
+    LoadSubCommand (CommandObjectSP (new CommandObjectThreadSelect ()), "select", interpreter);
+    LoadSubCommand (CommandObjectSP (new CommandObjectThreadUntil ()), "until", interpreter);
+    LoadSubCommand (CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-in",
+                                                                                  "Source level single step in in specified thread (current thread, if none specified).",
+                                                                                  "thread step-in [<thread-id>]",
+                                                                                  eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
+                                                                                  eStepTypeInto,
+                                                                                  eStepScopeSource)),
+                    "step-in", interpreter);
+
+    LoadSubCommand (CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-out",
+                                                                                      "Source level single step out in specified thread (current thread, if none specified).",
+                                                                                      "thread step-out [<thread-id>]",
+                                                                                      eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
+                                                                                      eStepTypeOut,
+                                                                                      eStepScopeSource)),
+                    "step-out", interpreter);
+
+    LoadSubCommand (CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-over",
+                                                                                      "Source level single step over in specified thread (current thread, if none specified).",
+                                                                                      "thread step-over [<thread-id>]",
+                                                                                      eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
+                                                                                      eStepTypeOver,
+                                                                                      eStepScopeSource)),
+                    "step-over", interpreter);
+
+    LoadSubCommand (CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-inst",
+                                                                                      "Single step one instruction in specified thread (current thread, if none specified).",
+                                                                                      "thread step-inst [<thread-id>]",
+                                                                                      eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
+                                                                                      eStepTypeTrace,
+                                                                                      eStepScopeInstruction)),
+                    "step-inst", interpreter);
+    LoadSubCommand (CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-inst-over",
+                                                                                      "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
+                                                                                      "thread step-inst-over [<thread-id>]",
+                                                                                      eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
+                                                                                      eStepTypeTraceOver,
+                                                                                      eStepScopeInstruction)),
+                    "step-inst-over", interpreter);
+}
+
+CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
+{
+}
+
+
diff --git a/source/Commands/CommandObjectThread.h b/source/Commands/CommandObjectThread.h
new file mode 100644
index 0000000..21bba71
--- /dev/null
+++ b/source/Commands/CommandObjectThread.h
@@ -0,0 +1,87 @@
+//===-- CommandObjectThread.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_CommandObjectThread_h_
+#define liblldb_CommandObjectThread_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+namespace lldb_private {
+
+class CommandObjectThreadList : public CommandObject
+{
+public:
+
+    CommandObjectThreadList ();
+
+    ~CommandObjectThreadList ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+};
+
+
+class CommandObjectMultiwordThread : public CommandObjectMultiword
+{
+public:
+
+    CommandObjectMultiwordThread (CommandInterpreter *interpreter);
+
+    virtual
+    ~CommandObjectMultiwordThread ();
+
+};
+
+
+bool
+DisplayThreadInfo (CommandInterpreter *interpreter,
+                   Stream &strm,
+                   Thread *thread,
+                   bool only_threads_with_stop_reason,
+                   bool show_source);
+
+size_t
+DisplayThreadsInfo (CommandInterpreter *interpreter,
+                    ExecutionContext *exe_ctx,
+                    CommandReturnObject &result,
+                    bool only_threads_with_stop_reason,
+                    bool show_source);
+
+size_t
+DisplayFramesForExecutionContext (Thread *thread,
+                                  CommandInterpreter *interpreter,
+                                  Stream& strm,
+                                  bool ascending,
+                                  uint32_t first_frame,
+                                  uint32_t num_frames,
+                                  bool show_frame_info,
+                                  uint32_t num_frames_with_source,
+                                  uint32_t source_lines_before,
+                                  uint32_t source_lines_after);
+
+bool
+DisplayFrameForExecutionContext (Thread *thread,
+                                 StackFrame *frame,
+                                 CommandInterpreter *interpreter,
+                                 Stream& strm,
+                                 bool show_frame_info,
+                                 bool show_source,
+                                 uint32_t source_lines_before,
+                                 uint32_t source_lines_after);
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectThread_h_
diff --git a/source/Commands/CommandObjectTranslate.cpp b/source/Commands/CommandObjectTranslate.cpp
new file mode 100644
index 0000000..48a1062
--- /dev/null
+++ b/source/Commands/CommandObjectTranslate.cpp
@@ -0,0 +1,75 @@
+//===-- CommandObjectTranslate.cpp ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectTranslate.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Options.h"
+
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectTranslate
+//-------------------------------------------------------------------------
+
+CommandObjectTranslate::CommandObjectTranslate () :
+    CommandObject ("translate",
+                     "Shows the actual function called for a given debugger command.",
+                     "translate <command>")
+{
+}
+
+CommandObjectTranslate::~CommandObjectTranslate()
+{
+}
+
+
+bool
+CommandObjectTranslate::Execute
+(
+    Args& command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    CommandObject *cmd_obj;
+
+    if (command.GetArgumentCount() != 0)
+    {
+        cmd_obj = interpreter->GetCommandObject(command.GetArgumentAtIndex(0));
+        if (cmd_obj)
+        {
+            result.SetStatus (eReturnStatusSuccessFinishNoResult);
+            result.AppendMessageWithFormat ("%s\n", cmd_obj->Translate());
+        }
+        else
+        {
+            result.AppendErrroWithFormat
+            ("'%s' is not a known command.\nTry 'help' to see a current list of commands.\n",
+             command.GetArgumentAtIndex(0));
+            result.SetStatus (eReturnStatusFailed);
+        }
+    }
+    else
+    {
+        result.AppendError ("must call translate with a valid command");
+        result.SetStatus (eReturnStatusFailed);
+    }
+
+    return result.Succeeded();
+}
diff --git a/source/Commands/CommandObjectTranslate.h b/source/Commands/CommandObjectTranslate.h
new file mode 100644
index 0000000..efc3c8b
--- /dev/null
+++ b/source/Commands/CommandObjectTranslate.h
@@ -0,0 +1,44 @@
+//===-- CommandObjectTranslate.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_CommandObjectTranslate_h_
+#define liblldb_CommandObjectTranslate_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectTranslate
+//-------------------------------------------------------------------------
+
+class CommandObjectTranslate : public CommandObject
+{
+public:
+
+    CommandObjectTranslate ();
+
+    virtual
+    ~CommandObjectTranslate ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectTranslate_h_
diff --git a/source/Commands/CommandObjectUnalias.cpp b/source/Commands/CommandObjectUnalias.cpp
new file mode 100644
index 0000000..6c2f508
--- /dev/null
+++ b/source/Commands/CommandObjectUnalias.cpp
@@ -0,0 +1,87 @@
+//===-- CommandObjectUnalias.cpp --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectUnalias.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectUnalias
+//-------------------------------------------------------------------------
+
+CommandObjectUnalias::CommandObjectUnalias () :
+    CommandObject ("unalias",
+                     "Allows the user to remove/delete a user-defined command abbreviation.",
+                     "unalias <alias-name-to-be-removed>")
+{
+}
+
+CommandObjectUnalias::~CommandObjectUnalias()
+{
+}
+
+
+bool
+CommandObjectUnalias::Execute (Args& args, CommandContext *context, CommandInterpreter *interpreter,
+                               CommandReturnObject &result)
+{
+    CommandObject::CommandMap::iterator pos;
+    CommandObject *cmd_obj;
+
+    if (args.GetArgumentCount() != 0)
+    {
+        const char *command_name = args.GetArgumentAtIndex(0);
+        cmd_obj = interpreter->GetCommandObject(command_name);
+        if (cmd_obj)
+        {
+            if (interpreter->CommandExists (command_name))
+            {
+                result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
+                                              command_name);
+                result.SetStatus (eReturnStatusFailed);
+            }
+            else
+            {
+
+                if (interpreter->RemoveAlias (command_name) == false)
+                {
+                    if (interpreter->AliasExists (command_name))
+                        result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n", command_name);
+                    else
+                        result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name);
+                    result.SetStatus (eReturnStatusFailed);
+                }
+                else
+                    result.SetStatus (eReturnStatusSuccessFinishNoResult);
+            }
+        }
+        else
+        {
+            result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a current list of commands.\n",
+                                         command_name);
+            result.SetStatus (eReturnStatusFailed);
+        }
+    }
+    else
+    {
+        result.AppendError ("must call 'unalias' with a valid alias");
+        result.SetStatus (eReturnStatusFailed);
+    }
+
+    return result.Succeeded();
+}
+
diff --git a/source/Commands/CommandObjectUnalias.h b/source/Commands/CommandObjectUnalias.h
new file mode 100644
index 0000000..5d1cafb
--- /dev/null
+++ b/source/Commands/CommandObjectUnalias.h
@@ -0,0 +1,44 @@
+//===-- CommandObjectUnalias.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_CommandObjectUnalias_h_
+#define liblldb_CommandObjectUnalias_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectUnalias
+//-------------------------------------------------------------------------
+
+class CommandObjectUnalias : public CommandObject
+{
+public:
+
+    CommandObjectUnalias ();
+
+    virtual
+    ~CommandObjectUnalias ();
+
+    virtual bool
+    Execute (Args& args,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result);
+
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectUnalias_h_
diff --git a/source/Commands/CommandObjectVariable.cpp b/source/Commands/CommandObjectVariable.cpp
new file mode 100644
index 0000000..6bde482
--- /dev/null
+++ b/source/Commands/CommandObjectVariable.cpp
@@ -0,0 +1,801 @@
+//===-- CommandObjectVariable.cpp -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectVariable.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Options.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectVariable.h"
+
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/Variable.h"
+#include "lldb/Symbol/VariableList.h"
+
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//void
+//DumpValueObjectValues (Stream *sout, const char *root_valobj_name, ValueObjectSP& valobj_sp, bool follow_ptrs_and_refs, uint32_t curr_depth, uint32_t max_depth)
+//{
+//    ValueObject *valobj = valobj_sp.get();
+//    if (valobj)
+//    {
+//        const char *name_cstr = valobj->GetName().AsCString(NULL);
+//        const char *val_cstr = valobj->GetValueAsCString();
+//        const char *loc_cstr = valobj->GetLocationAsCString();
+//        const char *type_cstr = valobj->GetTypeName().AsCString();
+//        const char *sum_cstr = valobj->GetSummaryAsCString();
+//        const char *err_cstr = valobj->GetError().AsCString();
+//        // Indent
+//        sout->Indent();
+//        if (root_valobj_name)
+//        {
+//            sout->Printf ("%s = ", root_valobj_name);
+//        }
+//
+//        if (name_cstr)
+//            sout->Printf ("%s => ", name_cstr);
+//
+//        sout->Printf ("ValueObject{%u}", valobj->GetID());
+//        const uint32_t num_children = valobj->GetNumChildren();
+//
+//        if (type_cstr)
+//            sout->Printf (", type = '%s'", type_cstr);
+//
+//        if (loc_cstr)
+//            sout->Printf (", location = %s", loc_cstr);
+//
+//        sout->Printf (", num_children = %u", num_children);
+//
+//        if (val_cstr)
+//            sout->Printf (", value = %s", val_cstr);
+//
+//        if (err_cstr)
+//            sout->Printf (", error = %s", err_cstr);
+//
+//        if (sum_cstr)
+//            sout->Printf (", summary = %s", sum_cstr);
+//
+//        sout->EOL();
+//        bool is_ptr_or_ref = ClangASTContext::IsPointerOrReferenceType (valobj->GetOpaqueClangQualType());
+//        if (!follow_ptrs_and_refs && is_ptr_or_ref)
+//            return;
+//
+//        if (curr_depth < max_depth)
+//        {
+//            for (uint32_t idx=0; idx<num_children; ++idx)
+//            {
+//                ValueObjectSP child_sp(valobj->GetChildAtIndex(idx, true));
+//                if (child_sp.get())
+//                {
+//                    sout->IndentMore();
+//                    DumpValueObjectValues (sout, NULL, child_sp, follow_ptrs_and_refs, curr_depth + 1, max_depth);
+//                    sout->IndentLess();
+//                }
+//            }
+//        }
+//    }
+//}
+
+//----------------------------------------------------------------------
+// List images with associated information
+//----------------------------------------------------------------------
+class CommandObjectVariableList : public CommandObject
+{
+public:
+
+    class CommandOptions : public Options
+    {
+    public:
+
+        CommandOptions () :
+            Options()
+        {
+            ResetOptionValues ();
+        }
+
+        virtual
+        ~CommandOptions ()
+        {
+        }
+
+        virtual Error
+        SetOptionValue (int option_idx, const char *option_arg)
+        {
+            Error error;
+            bool success;
+            char short_option = (char) m_getopt_table[option_idx].val;
+            switch (short_option)
+            {
+            case 'o':   use_objc     = true;  break;
+            case 'n':   name = option_arg;    break;
+            case 'r':   use_regex    = true;  break;
+            case 'a':   show_args    = false; break;
+            case 'l':   show_locals  = false; break;
+            case 'g':   show_globals = false; break;
+            case 't':   show_types   = false; break;
+            case 'y':   show_summary = false; break;
+            case 'L':   show_location= true;  break;
+            case 'D':   debug        = true;  break;
+            case 'd':
+                max_depth = Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success);
+                if (!success)
+                    error.SetErrorStringWithFormat("Invalid max depth '%s'.\n", option_arg);
+                break;
+
+            case 'p':
+                ptr_depth = Args::StringToUInt32 (option_arg, 0, 0, &success);
+                if (!success)
+                    error.SetErrorStringWithFormat("Invalid pointer depth '%s'.\n", option_arg);
+                break;
+
+            case 'G':
+                {
+                    ConstString const_string (option_arg);
+                    globals.push_back(const_string);
+                }
+                break;
+
+            case 's':
+                show_scope = true;
+                break;
+
+            default:
+                error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
+                break;
+            }
+
+            return error;
+        }
+
+        void
+        ResetOptionValues ()
+        {
+            Options::ResetOptionValues();
+
+            name.clear();
+            use_objc      = false;
+            use_regex     = false;
+            show_args     = true;
+            show_locals   = true;
+            show_globals  = true;
+            show_types    = true;
+            show_scope    = false;
+            show_summary  = true;
+            show_location = false;
+            debug         = false;
+            max_depth     = UINT32_MAX;
+            ptr_depth     = 0;
+            globals.clear();
+        }
+
+        const lldb::OptionDefinition*
+        GetDefinitions ()
+        {
+            return g_option_table;
+        }
+
+        // Options table: Required for subclasses of Options.
+
+        static lldb::OptionDefinition g_option_table[];
+        std::string name;
+        bool use_objc;
+        bool use_regex;
+        bool show_args;
+        bool show_locals;
+        bool show_globals;
+        bool show_types;
+        bool show_scope; // local/arg/global/static
+        bool show_summary;
+        bool show_location;
+        bool debug;
+        uint32_t max_depth; // The depth to print when dumping concrete (not pointers) aggreate values
+        uint32_t ptr_depth; // The default depth that is dumped when we find pointers
+        std::vector<ConstString> globals;
+        // Instance variables to hold the values for command options.
+    };
+
+    CommandObjectVariableList () :
+        CommandObject (
+                "variable list",
+                "Show specified argument, local variable, static variable or global variable.  If none specified, list them all.",
+                "variable list [<cmd-options>] [<var-name1> [<var-name2>...]]")
+    {
+    }
+
+    virtual
+    ~CommandObjectVariableList ()
+    {
+    }
+
+    virtual
+    Options *
+    GetOptions ()
+    {
+        return &m_options;
+    }
+
+    void
+    DumpVariable (CommandReturnObject &result, ExecutionContext *exe_ctx, Variable *variable)
+    {
+        if (variable)
+        {
+            Stream &s = result.GetOutputStream();
+            DWARFExpression &expr = variable->LocationExpression();
+            Value expr_result;
+            Error expr_error;
+            Type *variable_type = variable->GetType();
+            bool expr_success = expr.Evaluate(exe_ctx, NULL, NULL, expr_result, &expr_error);
+
+            if (m_options.debug)
+                s.Printf ("Variable{0x%8.8x}: ", variable->GetID());
+
+            if (!expr_success)
+                s.Printf ("%s = ERROR (%s)", variable->GetName().AsCString(NULL), expr_error.AsCString());
+            else
+            {
+                Value::ValueType expr_value_type = expr_result.GetValueType();
+                switch (expr_value_type)
+                {
+                case Value::eValueTypeScalar:
+                    s.Printf ("%s = ", variable->GetName().AsCString(NULL));
+                    if (variable_type)
+                    {
+                        DataExtractor data;
+                        if (expr_result.ResolveValue (exe_ctx, NULL).GetData (data))
+                            variable_type->DumpValue (exe_ctx, &s, data, 0, m_options.show_types, m_options.show_summary, m_options.debug);
+                    }
+                    break;
+
+                    case Value::eValueTypeFileAddress:
+                    case Value::eValueTypeLoadAddress:
+                    case Value::eValueTypeHostAddress:
+                    {
+                        s.Printf ("%s = ", variable->GetName().AsCString(NULL));
+                        lldb::addr_t addr = LLDB_INVALID_ADDRESS;
+                        lldb::AddressType addr_type = eAddressTypeLoad;
+
+                        if (expr_value_type == Value::eValueTypeFileAddress)
+                        {
+                            lldb::addr_t file_addr = expr_result.ResolveValue (exe_ctx, NULL).ULongLong(LLDB_INVALID_ADDRESS);
+                            SymbolContext var_sc;
+                            variable->CalculateSymbolContext(&var_sc);
+                            if (var_sc.module_sp)
+                            {
+                                ObjectFile *objfile = var_sc.module_sp->GetObjectFile();
+                                if (objfile)
+                                {
+                                    Address so_addr(file_addr, objfile->GetSectionList());
+                                    addr = so_addr.GetLoadAddress(exe_ctx->process);
+                                }
+                                if (addr == LLDB_INVALID_ADDRESS)
+                                {
+                                    result.GetErrorStream().Printf ("error: %s is not loaded", var_sc.module_sp->GetFileSpec().GetFilename().AsCString());
+                                }
+                            }
+                            else
+                            {
+                                result.GetErrorStream().Printf ("error: unable to resolve the variable address 0x%llx", file_addr);
+                            }
+                        }
+                        else
+                        {
+                            if (expr_value_type == Value::eValueTypeHostAddress)
+                                addr_type = eAddressTypeHost;
+                            addr = expr_result.ResolveValue (exe_ctx, NULL).ULongLong(LLDB_INVALID_ADDRESS);
+                        }
+
+                        if (addr != LLDB_INVALID_ADDRESS)
+                        {
+                            if (m_options.debug)
+                                s.Printf("@ 0x%8.8llx, value = ", addr);
+                            variable_type->DumpValueInMemory (exe_ctx, &s, addr, addr_type, m_options.show_types, m_options.show_summary, m_options.debug);
+                        }
+                    }
+                    break;
+                }
+            }
+            s.EOL();
+        }
+    }
+
+    void
+    DumpValueObject (CommandReturnObject &result,
+                     ExecutionContextScope *exe_scope,
+                     ValueObject *valobj,
+                     const char *root_valobj_name,
+                     uint32_t ptr_depth,
+                     uint32_t curr_depth,
+                     uint32_t max_depth,
+                     bool use_objc)
+    {
+        if (valobj)
+        {
+            Stream &s = result.GetOutputStream();
+
+            //const char *loc_cstr = valobj->GetLocationAsCString();
+            if (m_options.show_location)
+            {
+                s.Printf("@ %s: ", valobj->GetLocationAsCString(exe_scope));
+            }
+            if (m_options.debug)
+                s.Printf ("%p ValueObject{%u} ", valobj, valobj->GetID());
+
+            s.Indent();
+
+            if (m_options.show_types)
+                s.Printf("(%s) ", valobj->GetTypeName().AsCString());
+
+            const char *name_cstr = root_valobj_name ? root_valobj_name : valobj->GetName().AsCString("");
+            s.Printf ("%s = ", name_cstr);
+
+            const char *val_cstr = valobj->GetValueAsCString(exe_scope);
+            const char *err_cstr = valobj->GetError().AsCString();
+
+            if (err_cstr)
+            {
+                s.Printf ("error: %s\n", err_cstr);
+            }
+            else
+            {
+                const char *sum_cstr = valobj->GetSummaryAsCString(exe_scope);
+
+                const bool is_aggregate = ClangASTContext::IsAggregateType (valobj->GetOpaqueClangQualType());
+
+                if (val_cstr)
+                    s.PutCString(val_cstr);
+
+                if (sum_cstr)
+                    s.Printf(" %s", sum_cstr);
+                
+                if (use_objc)
+                {
+                    if (!ClangASTContext::IsPointerType (valobj->GetOpaqueClangQualType()))
+                        return;
+                    
+                    if (!valobj->GetValueIsValid())
+                        return;
+                    
+                    Process *process = exe_scope->CalculateProcess();
+                    
+                    if (!process)
+                        return;
+                    
+                    Scalar scalar;
+                    
+                    if (!Type::GetValueAsScalar (valobj->GetClangAST(),
+                                                 valobj->GetOpaqueClangQualType(),
+                                                 valobj->GetDataExtractor(),
+                                                 0,
+                                                 valobj->GetByteSize(),
+                                                 scalar))
+                        return;
+                                        
+                    ConstString po_output;
+                    
+                    ExecutionContext exe_ctx;
+                    exe_scope->Calculate(exe_ctx);
+                    
+                    Value val(scalar);
+                    val.SetContext(Value::eContextTypeOpaqueClangQualType, 
+                                   ClangASTContext::GetVoidPtrType(valobj->GetClangAST(), false));
+                    
+                    if (!process->GetObjCObjectPrinter().PrintObject(po_output, val, exe_ctx))
+                        return;
+                    
+                    s.Printf("\n%s\n", po_output.GetCString());
+                                        
+                    return;
+                }
+
+
+                if (curr_depth < max_depth)
+                {
+                    if (is_aggregate)
+                        s.PutChar('{');
+
+                    bool is_ptr_or_ref = ClangASTContext::IsPointerOrReferenceType (valobj->GetOpaqueClangQualType());
+                    
+                    if (is_ptr_or_ref && ptr_depth == 0)
+                        return;
+
+                    const uint32_t num_children = valobj->GetNumChildren();
+                    if (num_children)
+                    {
+                        s.IndentMore();
+                        for (uint32_t idx=0; idx<num_children; ++idx)
+                        {
+                            ValueObjectSP child_sp(valobj->GetChildAtIndex(idx, true));
+                            if (child_sp.get())
+                            {
+                                s.EOL();
+                                DumpValueObject (result,
+                                                 exe_scope,
+                                                 child_sp.get(),
+                                                 NULL,
+                                                 is_ptr_or_ref ? ptr_depth - 1 : ptr_depth,
+                                                 curr_depth + 1,
+                                                 max_depth,
+                                                 false);
+                                if (idx + 1 < num_children)
+                                    s.PutChar(',');
+                            }
+                        }
+                        s.IndentLess();
+                    }
+                    if (is_aggregate)
+                    {
+                        s.EOL();
+                        s.Indent("}");
+                    }
+                }
+                else
+                {
+                    if (is_aggregate)
+                    {
+                        s.PutCString("{...}");
+                    }
+                }
+
+            }
+        }
+    }
+
+    virtual bool
+    Execute (Args& command,
+             CommandContext *context,
+             CommandInterpreter *interpreter,
+             CommandReturnObject &result)
+    {
+        ExecutionContext exe_ctx(context->GetExecutionContext());
+        if (exe_ctx.frame == NULL)
+        {
+            result.AppendError ("invalid frame");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+        else
+        {
+            VariableList variable_list;
+
+            SymbolContext frame_sc = exe_ctx.frame->GetSymbolContext (eSymbolContextEverything);
+            if (exe_ctx.frame && frame_sc.block)
+                frame_sc.block->AppendVariables(true, true, &variable_list);
+            VariableSP var_sp;
+            ValueObjectSP valobj_sp;
+            //ValueObjectList &valobj_list = exe_ctx.frame->GetValueObjectList();
+            const char *name_cstr = NULL;
+            size_t idx;
+            if (!m_options.globals.empty())
+            {
+                uint32_t fail_count = 0;
+                Target *target = context->GetTarget();
+                if (target)
+                {
+                    const size_t num_globals = m_options.globals.size();
+                    for (idx = 0; idx < num_globals; ++idx)
+                    {
+                        VariableList global_var_list;
+                        const uint32_t num_matching_globals = target->GetImages().FindGlobalVariables (m_options.globals[idx], true, UINT32_MAX, global_var_list);
+
+                        if (num_matching_globals == 0)
+                        {
+                            ++fail_count;
+                            result.GetErrorStream().Printf ("error: can't find global variable '%s'\n", m_options.globals[idx].AsCString());
+                        }
+                        else
+                        {
+                            for (uint32_t global_idx=0; global_idx<num_matching_globals; ++global_idx)
+                            {
+                                var_sp = global_var_list.GetVariableAtIndex(global_idx);
+                                if (var_sp)
+                                {
+                                    valobj_sp = exe_ctx.frame->GetValueObjectList().FindValueObjectByValueName (m_options.globals[idx].AsCString());
+                                    if (!valobj_sp)
+                                        valobj_sp.reset (new ValueObjectVariable (var_sp));
+
+                                    if (valobj_sp)
+                                    {
+                                        exe_ctx.frame->GetValueObjectList().Append (valobj_sp);
+                                        DumpValueObject (result, exe_ctx.frame, valobj_sp.get(), name_cstr, m_options.ptr_depth, 0, m_options.max_depth, false);
+                                        result.GetOutputStream().EOL();
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                if (fail_count)
+                {
+                    result.SetStatus (eReturnStatusFailed);
+                }
+            }
+            
+            if (command.GetArgumentCount() > 0)
+            {
+                // If we have any args to the variable command, we will make
+                // variable objects from them...
+                for (idx = 0; (name_cstr = command.GetArgumentAtIndex(idx)) != NULL; ++idx)
+                {
+                    uint32_t ptr_depth = m_options.ptr_depth;
+                    // If first character is a '*', then show pointer contents
+                    if (name_cstr[0] == '*')
+                    {
+                        ++ptr_depth;
+                        name_cstr++; // Skip the '*'
+                    }
+
+                    std::string var_path (name_cstr);
+                    size_t separator_idx = var_path.find_first_of(".-[");
+
+                    ConstString name_const_string;
+                    if (separator_idx == std::string::npos)
+                        name_const_string.SetCString (var_path.c_str());
+                    else
+                        name_const_string.SetCStringWithLength (var_path.c_str(), separator_idx);
+
+                    var_sp = variable_list.FindVariable(name_const_string);
+                    if (var_sp)
+                    {
+                        //DumpVariable (result, &exe_ctx, var_sp.get());
+                        // TODO: redo history variables using a different map
+//                        if (var_path[0] == '$')
+//                            valobj_sp = valobj_list.FindValueObjectByValueObjectName (name_const_string.GetCString());
+//                        else
+                            valobj_sp = exe_ctx.frame->GetValueObjectList().FindValueObjectByValueName (name_const_string.GetCString());
+
+                        if (!valobj_sp)
+                        {
+                            valobj_sp.reset (new ValueObjectVariable (var_sp));
+                            exe_ctx.frame->GetValueObjectList().Append (valobj_sp);
+                        }
+
+                        var_path.erase (0, name_const_string.GetLength ());
+                        // We are dumping at least one child
+                        while (separator_idx != std::string::npos)
+                        {
+                            // Calculate the next separator index ahead of time
+                            ValueObjectSP child_valobj_sp;
+                            const char separator_type = var_path[0];
+                            switch (separator_type)
+                            {
+
+                            case '-':
+                                if (var_path.size() >= 2 && var_path[1] != '>')
+                                {
+                                    result.GetErrorStream().Printf ("error: invalid character in variable path starting at '%s'\n",
+                                                                    var_path.c_str());
+                                    var_path.clear();
+                                    valobj_sp.reset();
+                                    break;
+                                }
+                                var_path.erase (0, 1); // Remove the '-'
+                                // Fall through
+                            case '.':
+                                {
+                                    var_path.erase (0, 1); // Remove the '.' or '>'
+                                    separator_idx = var_path.find_first_of(".-[");
+                                    ConstString child_name;
+                                    if (separator_idx == std::string::npos)
+                                        child_name.SetCString (var_path.c_str());
+                                    else
+                                        child_name.SetCStringWithLength(var_path.c_str(), separator_idx);
+
+                                    child_valobj_sp = valobj_sp->GetChildMemberWithName (child_name, true);
+                                    if (!child_valobj_sp)
+                                    {
+                                        result.GetErrorStream().Printf ("error: can't find child of '%s' named '%s'\n",
+                                                                        valobj_sp->GetName().AsCString(),
+                                                                        child_name.GetCString());
+                                        var_path.clear();
+                                        valobj_sp.reset();
+                                        break;
+                                    }
+                                    // Remove the child name from the path
+                                    var_path.erase(0, child_name.GetLength());
+                                }
+                                break;
+
+                            case '[':
+                                // Array member access, or treating pointer as an array
+                                if (var_path.size() > 2) // Need at least two brackets and a number
+                                {
+                                    char *end = NULL;
+                                    int32_t child_index = ::strtol (&var_path[1], &end, 0);
+                                    if (end && *end == ']')
+                                    {
+
+                                        if (valobj_sp->IsPointerType ())
+                                        {
+                                            child_valobj_sp = valobj_sp->GetSyntheticArrayMemberFromPointer (child_index, true);
+                                        }
+                                        else
+                                        {
+                                            child_valobj_sp = valobj_sp->GetChildAtIndex (child_index, true);
+                                        }
+
+                                        if (!child_valobj_sp)
+                                        {
+                                            result.GetErrorStream().Printf ("error: invalid array index %u in '%s'\n",
+                                                                            child_index,
+                                                                            valobj_sp->GetName().AsCString());
+                                            var_path.clear();
+                                            valobj_sp.reset();
+                                            break;
+                                        }
+
+                                        // Erase the array member specification '[%i]' where %i is the array index
+                                        var_path.erase(0, (end - var_path.c_str()) + 1);
+                                        separator_idx = var_path.find_first_of(".-[");
+
+                                        // Break out early from the switch since we were able to find the child member
+                                        break;
+                                    }
+                                }
+                                result.GetErrorStream().Printf ("error: invalid array member specification for '%s' starting at '%s'\n",
+                                                                valobj_sp->GetName().AsCString(),
+                                                                var_path.c_str());
+                                var_path.clear();
+                                valobj_sp.reset();
+                                break;
+
+                                break;
+
+                            default:
+                                result.GetErrorStream().Printf ("error: invalid character in variable path starting at '%s'\n",
+                                                                    var_path.c_str());
+                                var_path.clear();
+                                valobj_sp.reset();
+                                separator_idx = std::string::npos;
+                                break;
+                            }
+
+                            if (child_valobj_sp)
+                                valobj_sp = child_valobj_sp;
+
+                            if (var_path.empty())
+                                break;
+
+                        }
+
+                        if (valobj_sp)
+                        {
+                            DumpValueObject (result, exe_ctx.frame, valobj_sp.get(), name_cstr, ptr_depth, 0, m_options.max_depth, m_options.use_objc);
+                            result.GetOutputStream().EOL();
+                        }
+                    }
+                    else
+                    {
+                        result.GetErrorStream().Printf ("error: unable to find any variables named '%s'\n", name_cstr);
+                        var_path.clear();
+                    }
+                }
+            }
+            else
+            {
+
+                if (m_options.show_globals)
+                {
+                    if (frame_sc.comp_unit)
+                    {
+                        variable_list.AddVariables (frame_sc.comp_unit->GetVariableList(true).get());
+                    }
+                }
+
+                const uint32_t num_variables = variable_list.GetSize();
+    
+                if (num_variables > 0)
+                {
+                    for (uint32_t i=0; i<num_variables; i++)
+                    {
+                        Variable *variable = variable_list.GetVariableAtIndex(i).get();
+                        bool dump_variable = true;
+                        
+                        switch (variable->GetScope())
+                        {
+                        case eValueTypeVariableGlobal:
+                            dump_variable = m_options.show_globals;
+                            if (dump_variable && m_options.show_scope)
+                                result.GetOutputStream().PutCString("GLOBAL: ");
+                            break;
+
+                        case eValueTypeVariableStatic:
+                            dump_variable = m_options.show_globals;
+                            if (dump_variable && m_options.show_scope)
+                                result.GetOutputStream().PutCString("STATIC: ");
+                            break;
+                            
+                        case eValueTypeVariableArgument:
+                            dump_variable = m_options.show_args;
+                            if (dump_variable && m_options.show_scope)
+                                result.GetOutputStream().PutCString("   ARG: ");
+                            break;
+                            
+                        case eValueTypeVariableLocal:
+                            dump_variable = m_options.show_locals;
+                            if (dump_variable && m_options.show_scope)
+                                result.GetOutputStream().PutCString(" LOCAL: ");
+                            break;
+
+                        default:
+                            break;
+                        }
+                        
+                        if (dump_variable)
+                            DumpVariable (result, &exe_ctx, variable);
+                    }
+                }
+            }
+            result.SetStatus (eReturnStatusSuccessFinishResult);
+        }
+        return result.Succeeded();
+    }
+protected:
+
+    CommandOptions m_options;
+};
+
+lldb::OptionDefinition
+CommandObjectVariableList::CommandOptions::g_option_table[] =
+{
+{ 0, false, "debug",      'D', no_argument,       NULL, 0, NULL,        "Show verbose debug information."},
+{ 0, false, "depth",      'd', required_argument, NULL, 0, "<count>",   "Set the max recurse depth when dumping aggregate types (default is infinity)."},
+{ 0, false, "globals",    'g', no_argument,       NULL, 0, NULL,        "List global and static variables for the current stack frame source file."},
+{ 0, false, "global",     'G', required_argument, NULL, 0, NULL,        "Find a global variable by name (which might not be in the current stack frame source file)."},
+{ 0, false, "location",   'L', no_argument,       NULL, 0, NULL,        "Show variable location information."},
+{ 0, false, "name",       'n', required_argument, NULL, 0, "<name>",    "Lookup a variable by name or regex (--regex) for the current execution context."},
+{ 0, false, "no-args",    'a', no_argument,       NULL, 0, NULL,        "Omit function arguments."},
+{ 0, false, "no-locals",  'l', no_argument,       NULL, 0, NULL,        "Omit local variables."},
+{ 0, false, "no-types",   't', no_argument,       NULL, 0, NULL,        "Omit variable type names."},
+{ 0, false, "no-summary", 'y', no_argument,       NULL, 0, NULL,        "Omit summary information."},
+{ 0, false, "scope",      's', no_argument,       NULL, 0, NULL,        "Show variable scope (argument, local, global, static)."},
+{ 0, false, "objc",       'o', no_argument,       NULL, 0, NULL,        "When looking up a variable by name (--name), print as an Objective-C object."},
+{ 0, false, "ptr-depth",  'p', required_argument, NULL, 0, "<count>",   "The number of pointers to be traversed when dumping values (default is zero)."},
+{ 0, false, "regex",      'r', no_argument,       NULL, 0, NULL,        "The <name> argument for name lookups are regular expressions."},
+{ 0, false, NULL, 0, 0, NULL, NULL, NULL, NULL }
+};
+
+//----------------------------------------------------------------------
+// CommandObjectVariable constructor
+//----------------------------------------------------------------------
+CommandObjectVariable::CommandObjectVariable(CommandInterpreter *interpreter) :
+    CommandObjectMultiword ("variable",
+                              "Access program arguments, locals, static and global variables.",
+                              "variable [list] ...")
+{
+    LoadSubCommand (CommandObjectSP (new CommandObjectVariableList ()), "list", interpreter);
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+CommandObjectVariable::~CommandObjectVariable()
+{
+}
+
+
+
+
diff --git a/source/Commands/CommandObjectVariable.h b/source/Commands/CommandObjectVariable.h
new file mode 100644
index 0000000..65869c7
--- /dev/null
+++ b/source/Commands/CommandObjectVariable.h
@@ -0,0 +1,43 @@
+//===-- CommandObjectVariable.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_CommandObjectVariable_h_
+#define liblldb_CommandObjectVariable_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectImage
+//-------------------------------------------------------------------------
+
+class CommandObjectVariable : public CommandObjectMultiword
+{
+public:
+
+    CommandObjectVariable (CommandInterpreter *iterpreter);
+
+    virtual
+    ~CommandObjectVariable ();
+
+private:
+    //------------------------------------------------------------------
+    // For CommandObjectVariable only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (CommandObjectVariable);
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectVariable_h_
diff --git a/source/Core/Address.cpp b/source/Core/Address.cpp
new file mode 100644
index 0000000..e2481e1
--- /dev/null
+++ b/source/Core/Address.cpp
@@ -0,0 +1,875 @@
+//===-- Address.cpp ---------------------------------------------*- 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/Address.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static size_t
+ReadBytes (ExecutionContextScope *exe_scope, const Address &address, void *dst, size_t dst_len)
+{
+    if (exe_scope == NULL)
+        return 0;
+
+    lldb::AddressType addr_type = eAddressTypeInvalid;
+    addr_t addr = LLDB_INVALID_ADDRESS;
+
+    Process *process = exe_scope->CalculateProcess();
+
+    if (process && process->IsAlive())
+    {
+        addr = address.GetLoadAddress(process);
+        if (addr != LLDB_INVALID_ADDRESS)
+            addr_type = eAddressTypeLoad;
+    }
+
+    if (addr == LLDB_INVALID_ADDRESS)
+    {
+        addr = address.GetFileAddress();
+        if (addr != LLDB_INVALID_ADDRESS)
+            addr_type = eAddressTypeFile;
+    }
+
+    if (addr_type == eAddressTypeInvalid)
+        return false;
+
+    Target *target = exe_scope->CalculateTarget();
+    if (target)
+    {
+        Error error;
+        return target->ReadMemory (addr_type, addr, dst, dst_len, error, NULL);
+    }
+    return 0;
+}
+
+static bool
+GetByteOrderAndAddressSize (ExecutionContextScope *exe_scope, const Address &address, ByteOrder& byte_order, uint32_t& addr_size)
+{
+    byte_order = eByteOrderInvalid;
+    addr_size = 0;
+    if (exe_scope == NULL)
+        return false;
+
+    Process *process = exe_scope->CalculateProcess();
+    if (process)
+    {
+        byte_order = process->GetByteOrder();
+        addr_size = process->GetAddressByteSize();
+    }
+
+    if (byte_order == eByteOrderInvalid || addr_size == 0)
+    {
+        Module *module = address.GetModule();
+        if (module)
+        {
+            byte_order = module->GetArchitecture().GetDefaultEndian();
+            addr_size = module->GetArchitecture().GetAddressByteSize();
+        }
+    }
+    return byte_order != eByteOrderInvalid && addr_size != 0;
+}
+
+static uint64_t
+ReadUIntMax64 (ExecutionContextScope *exe_scope, const Address &address, uint32_t byte_size, bool &success)
+{
+    uint64_t uval64 = 0;
+    if (exe_scope == NULL || byte_size > sizeof(uint64_t))
+    {
+        success = false;
+        return 0;
+    }
+    uint64_t buf;
+
+    success = ReadBytes (exe_scope, address, &buf, byte_size) == byte_size;
+    if (success)
+    {
+        ByteOrder byte_order = eByteOrderInvalid;
+        uint32_t addr_size = 0;
+        if (GetByteOrderAndAddressSize (exe_scope, address, byte_order, addr_size))
+        {
+            DataExtractor data (&buf, sizeof(buf), byte_order, addr_size);
+            uint32_t offset = 0;
+            uval64 = data.GetU64(&offset);
+        }
+        else
+            success = false;
+    }
+    return uval64;
+}
+
+static bool
+ReadAddress (ExecutionContextScope *exe_scope, const Address &address, uint32_t pointer_size, Address &deref_so_addr)
+{
+    if (exe_scope == NULL)
+        return false;
+
+
+    bool success = false;
+    addr_t deref_addr = ReadUIntMax64 (exe_scope, address, pointer_size, success);
+    if (success)
+    {
+        Process *process = exe_scope->CalculateProcess();
+        if (process && process->IsAlive())
+        {
+            if (!process->ResolveLoadAddress (deref_addr, deref_so_addr))
+            {
+                deref_so_addr.SetSection(NULL);
+                deref_so_addr.SetOffset(deref_addr);
+            }
+        }
+        else
+        {
+            Target *target = exe_scope->CalculateTarget();
+            if (target == NULL)
+                return false;
+
+            if (!target->GetImages().ResolveFileAddress(deref_addr, deref_so_addr))
+            {
+                deref_so_addr.SetSection(NULL);
+                deref_so_addr.SetOffset(deref_addr);
+            }
+        }
+        return true;
+    }
+    return false;
+}
+
+static bool
+DumpUInt (ExecutionContextScope *exe_scope, const Address &address, uint32_t byte_size, Stream* strm)
+{
+    if (exe_scope == NULL)
+        return 0;
+    std::vector<uint8_t> buf(byte_size, 0);
+
+    if (ReadBytes (exe_scope, address, &buf[0], buf.size()) == buf.size())
+    {
+        ByteOrder byte_order = eByteOrderInvalid;
+        uint32_t addr_size = 0;
+        if (GetByteOrderAndAddressSize (exe_scope, address, byte_order, addr_size))
+        {
+            DataExtractor data (buf.data(), buf.size(), byte_order, addr_size);
+
+            data.Dump (strm,
+                       0,                 // Start offset in "data"
+                       eFormatHex,        // Print as characters
+                       buf.size(),        // Size of item
+                       1,                 // Items count
+                       UINT32_MAX,        // num per line
+                       LLDB_INVALID_ADDRESS,// base address
+                       0,                 // bitfield bit size
+                       0);                // bitfield bit offset
+
+            return true;
+        }
+    }
+    return false;
+}
+
+
+static size_t
+ReadCStringFromMemory (ExecutionContextScope *exe_scope, const Address &address, Stream *strm)
+{
+    if (exe_scope == NULL)
+        return 0;
+    const size_t k_buf_len = 256;
+    char buf[k_buf_len+1];
+    buf[k_buf_len] = '\0'; // NULL terminate
+
+    // Byte order and adderss size don't matter for C string dumping..
+    DataExtractor data (buf, sizeof(buf), eByteOrderHost, 4);
+    size_t total_len = 0;
+    size_t bytes_read;
+    Address curr_address(address);
+    strm->PutChar ('"');
+    while ((bytes_read = ReadBytes (exe_scope, curr_address, buf, k_buf_len)) > 0)
+    {
+        size_t len = strlen(buf);
+        if (len == 0)
+            break;
+        if (len > bytes_read)
+            len = bytes_read;
+
+        data.Dump (strm,
+                   0,                 // Start offset in "data"
+                   eFormatChar,       // Print as characters
+                   1,                 // Size of item (1 byte for a char!)
+                   len,               // How many bytes to print?
+                   UINT32_MAX,        // num per line
+                   LLDB_INVALID_ADDRESS,// base address
+                   0,                 // bitfield bit size
+
+                   0);                // bitfield bit offset
+
+        total_len += bytes_read;
+
+        if (len < k_buf_len)
+            break;
+        curr_address.SetOffset (curr_address.GetOffset() + bytes_read);
+    }
+    strm->PutChar ('"');
+    return total_len;
+}
+
+Address::Address () :
+    m_section (NULL),
+    m_offset (LLDB_INVALID_ADDRESS)
+{
+}
+
+Address::Address (const Address& rhs) :
+    m_section (rhs.m_section),
+    m_offset (rhs.m_offset)
+{
+}
+
+Address::Address (const Section* section, addr_t offset) :
+    m_section (section),
+    m_offset (offset)
+{
+}
+
+Address::Address (addr_t address, const SectionList * sections) :
+    m_section (NULL),
+    m_offset (LLDB_INVALID_ADDRESS)
+{
+    ResolveAddressUsingFileSections(address, sections);
+}
+
+Address::~Address ()
+{
+}
+
+
+const Address&
+Address::operator= (const Address& rhs)
+{
+    if (this != &rhs)
+    {
+        m_section = rhs.m_section;
+        m_offset = rhs.m_offset;
+    }
+    return *this;
+}
+
+bool
+Address::IsValid() const
+{
+    return m_offset != LLDB_INVALID_ADDRESS;
+}
+
+bool
+Address::IsSectionOffset() const
+{
+    return m_section != NULL && IsValid();
+}
+
+bool
+Address::ResolveAddressUsingFileSections (addr_t addr, const SectionList *sections)
+{
+    if (sections)
+        m_section = sections->FindSectionContainingFileAddress(addr).get();
+    else
+        m_section = NULL;
+
+    if (m_section != NULL)
+    {
+        assert( m_section->ContainsFileAddress(addr) );
+        m_offset = addr - m_section->GetFileAddress();
+        return true;    // Successfully transformed addr into a section offset address
+    }
+
+    m_offset = addr;
+    return false;       // Failed to resolve this address to a section offset value
+}
+
+//bool
+//Address::ResolveAddressUsingLoadSections (addr_t addr, const SectionList *sections)
+//{
+//    if (sections)
+//        m_section = sections->FindSectionContainingLoadAddress(addr).get();
+//    else
+//        m_section = NULL;
+//
+//    if (m_section != NULL)
+//    {
+//        assert( m_section->ContainsLoadAddress(addr) );
+//        m_offset = addr - m_section->GetLoadBaseAddress();
+//        return true;    // Successfully transformed addr into a section offset address
+//    }
+//
+//    m_offset = addr;
+//    return false;       // Failed to resolve this address to a section offset value
+//}
+//
+Module *
+Address::GetModule () const
+{
+    if (m_section)
+        return m_section->GetModule();
+    return NULL;
+}
+
+const Section*
+Address::GetSection () const
+{
+    return m_section;
+}
+
+
+//addr_t
+//Address::Address() const
+//{
+//  addr_t addr = GetLoadAddress();
+//  if (addr != LLDB_INVALID_ADDRESS)
+//      return addr;
+//  return GetFileAddress();
+//}
+//
+
+addr_t
+Address::GetFileAddress () const
+{
+    if (m_section != NULL)
+    {
+        addr_t sect_file_addr = m_section->GetFileAddress();
+        if (sect_file_addr == LLDB_INVALID_ADDRESS)
+        {
+            // Section isn't resolved, we can't return a valid file address
+            return LLDB_INVALID_ADDRESS;
+        }
+        // We have a valid file range, so we can return the file based
+        // address by adding the file base address to our offset
+        return sect_file_addr + m_offset;
+    }
+    // No section, we just return the offset since it is the value in this case
+    return m_offset;
+}
+
+addr_t
+Address::GetLoadAddress (Process *process) const
+{
+    if (m_section != NULL)
+    {
+        if (process)
+        {
+            addr_t sect_load_addr = m_section->GetLoadBaseAddress (process);
+
+            if (sect_load_addr != LLDB_INVALID_ADDRESS)
+            {
+                // We have a valid file range, so we can return the file based
+                // address by adding the file base address to our offset
+                return sect_load_addr + m_offset;
+            }
+        }
+       // The section isn't resolved or no process was supplied so we can't
+       // return a valid file address.
+       return LLDB_INVALID_ADDRESS;
+    }
+    // No section, we just return the offset since it is the value in this case
+    return m_offset;
+}
+
+addr_t
+Address::GetOffset () const
+{
+    return m_offset;
+}
+
+bool
+Address::SetOffset (addr_t offset)
+{
+    bool changed = m_offset != offset;
+    m_offset = offset;
+    return changed;
+}
+
+void
+Address::SetSection (const Section* section)
+{
+    m_section = section;
+}
+
+void
+Address::Clear()
+{
+    m_section = NULL;
+    m_offset = LLDB_INVALID_ADDRESS;
+}
+
+
+bool
+Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, DumpStyle fallback_style) const
+{
+    // If the section was NULL, only load address is going to work.
+    if (m_section == NULL)
+        style = DumpStyleLoadAddress;
+
+    Process *process = NULL;
+    if (exe_scope)
+        process = exe_scope->CalculateProcess();
+    int addr_size = sizeof (addr_t);
+    if (process)
+      addr_size = process->GetAddressByteSize ();
+
+    lldb_private::Address so_addr;
+
+    switch (style)
+    {
+    case DumpStyleSectionNameOffset:
+        if (m_section != NULL)
+        {
+            m_section->DumpName(s);
+            s->Printf (" + %llu", m_offset);
+        }
+        else
+        {
+            s->Printf("0x%16.16llx", m_offset);
+        }
+        break;
+
+    case DumpStyleSectionPointerOffset:
+        s->Printf("(Section *)%.*p + 0x%16.16llx", (int)sizeof(void*) * 2, m_section, m_offset);
+        break;
+
+    case DumpStyleModuleWithFileAddress:
+        s->Printf("%s[", m_section->GetModule()->GetFileSpec().GetFilename().AsCString());
+        // Fall through
+    case DumpStyleFileAddress:
+        {
+            addr_t file_addr = GetFileAddress();
+            if (file_addr == LLDB_INVALID_ADDRESS)
+            {
+                if (fallback_style != DumpStyleInvalid)
+                    return Dump (s, exe_scope, fallback_style);
+                return false;
+            }
+            s->Address (file_addr, addr_size);
+            if (style == DumpStyleModuleWithFileAddress)
+                s->PutChar(']');
+        }
+        break;
+
+    case DumpStyleLoadAddress:
+        {
+            addr_t load_addr = GetLoadAddress (process);
+            if (load_addr == LLDB_INVALID_ADDRESS)
+            {
+                if (fallback_style != DumpStyleInvalid)
+                    return Dump (s, exe_scope, fallback_style);
+                return false;
+            }
+            s->Address (load_addr, addr_size);
+        }
+        break;
+
+    case DumpStyleResolvedDescription:
+        if (IsSectionOffset())
+        {
+            lldb::AddressType addr_type = eAddressTypeLoad;
+            addr_t addr = GetLoadAddress (process);
+            if (addr == LLDB_INVALID_ADDRESS)
+            {
+                addr = GetFileAddress();
+                addr_type = eAddressTypeFile;
+            }
+
+            uint32_t pointer_size = 4;
+            lldb_private::Module *module = GetModule();
+            if (process)
+                pointer_size = process->GetAddressByteSize();
+            else if (module)
+                pointer_size = module->GetArchitecture().GetAddressByteSize();
+
+            bool showed_info = false;
+            const Section *section = GetSection();
+            if (section)
+            {
+                SectionType sect_type = section->GetSectionType();
+                switch (sect_type)
+                {
+                case eSectionTypeDataCString:
+                    // Read the C string from memory and display it
+                    showed_info = true;
+                    ReadCStringFromMemory (exe_scope, *this, s);
+                    break;
+
+                case eSectionTypeDataCStringPointers:
+                    {
+                        if (ReadAddress (exe_scope, *this, pointer_size, so_addr))
+                        {
+#if VERBOSE_OUTPUT
+                            s->PutCString("(char *)");
+                            so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress);
+                            s->PutCString(": ");
+#endif
+                            showed_info = true;
+                            ReadCStringFromMemory (exe_scope, so_addr, s);
+                        }
+                    }
+                    break;
+
+                case eSectionTypeDataObjCMessageRefs:
+                    {
+                        if (ReadAddress (exe_scope, *this, pointer_size, so_addr))
+                        {
+                            if (so_addr.IsSectionOffset())
+                            {
+                                lldb_private::SymbolContext func_sc;
+                                process->GetTarget().GetImages().ResolveSymbolContextForAddress (so_addr,
+                                                                                                 eSymbolContextEverything,
+                                                                                                 func_sc);
+                                if (func_sc.function || func_sc.symbol)
+                                {
+                                    showed_info = true;
+#if VERBOSE_OUTPUT
+                                    s->PutCString ("(objc_msgref *) -> { (func*)");
+                                    so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress);
+#else
+                                    s->PutCString ("{ ");
+#endif
+                                    Address cstr_addr(*this);
+                                    cstr_addr.SetOffset(cstr_addr.GetOffset() + pointer_size);
+                                    func_sc.DumpStopContext(s, process, so_addr, true);
+                                    if (ReadAddress (exe_scope, cstr_addr, pointer_size, so_addr))
+                                    {
+#if VERBOSE_OUTPUT
+                                        s->PutCString("), (char *)");
+                                        so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress);
+                                        s->PutCString(" (");
+#else
+                                        s->PutCString(", ");
+#endif
+                                        ReadCStringFromMemory (exe_scope, so_addr, s);
+                                    }
+#if VERBOSE_OUTPUT
+                                    s->PutCString(") }");
+#else
+                                    s->PutCString(" }");
+#endif
+                                }
+                            }
+                        }
+                    }
+                    break;
+
+                case eSectionTypeDataObjCCFStrings:
+                    {
+                        Address cfstring_data_addr(*this);
+                        cfstring_data_addr.SetOffset(cfstring_data_addr.GetOffset() + (2 * pointer_size));
+                        if (ReadAddress (exe_scope, cfstring_data_addr, pointer_size, so_addr))
+                        {
+#if VERBOSE_OUTPUT
+                            s->PutCString("(CFString *) ");
+                            cfstring_data_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress);
+                            s->PutCString(" -> @");
+#else
+                            s->PutChar('@');
+#endif
+                            if (so_addr.Dump(s, exe_scope, DumpStyleResolvedDescription))
+                                showed_info = true;
+                        }
+                    }
+                    break;
+
+                case eSectionTypeData4:
+                    // Read the 4 byte data and display it
+                    showed_info = true;
+                    s->PutCString("(uint32_t) ");
+                    DumpUInt (exe_scope, *this, 4, s);
+                    break;
+
+                case eSectionTypeData8:
+                    // Read the 8 byte data and display it
+                    showed_info = true;
+                    s->PutCString("(uint64_t) ");
+                    DumpUInt (exe_scope, *this, 8, s);
+                    break;
+
+                case eSectionTypeData16:
+                    // Read the 16 byte data and display it
+                    showed_info = true;
+                    s->PutCString("(uint128_t) ");
+                    DumpUInt (exe_scope, *this, 16, s);
+                    break;
+
+                case eSectionTypeDataPointers:
+                    // Read the pointer data and display it
+                    {
+                        if (ReadAddress (exe_scope, *this, pointer_size, so_addr))
+                        {
+                            s->PutCString ("(void *)");
+                            so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress);
+
+                            showed_info = true;
+                            if (so_addr.IsSectionOffset())
+                            {
+                                lldb_private::SymbolContext pointer_sc;
+                                process->GetTarget().GetImages().ResolveSymbolContextForAddress (so_addr,
+                                                                                                 eSymbolContextEverything,
+                                                                                                 pointer_sc);
+                                if (pointer_sc.function || pointer_sc.symbol)
+                                {
+                                    s->PutCString(": ");
+                                    pointer_sc.DumpStopContext(s, process, so_addr, false);
+                                }
+                            }
+                        }
+                    }
+                    break;
+                }
+            }
+
+            if (!showed_info)
+            {
+                if (module)
+                {
+                    lldb_private::SymbolContext sc;
+                    module->ResolveSymbolContextForAddress(*this, eSymbolContextEverything, sc);
+                    if (sc.function || sc.symbol)
+                    {
+                        bool show_stop_context = true;
+                        if (sc.function == NULL && sc.symbol != NULL)
+                        {
+                            // If we have just a symbol make sure it is in the right section
+                            if (sc.symbol->GetAddressRangePtr())
+                            {
+                                if (sc.symbol->GetAddressRangePtr()->GetBaseAddress().GetSection() != GetSection())
+                                    show_stop_context = false;
+                            }
+                        }
+                        if (show_stop_context)
+                        {
+                            // We have a function or a symbol from the same
+                            // sections as this address.
+                            sc.DumpStopContext(s, process, *this, false);
+                        }
+                        else
+                        {
+                            // We found a symbol but it was in a different
+                            // section so it isn't the symbol we should be
+                            // showing, just show the section name + offset
+                            Dump (s, exe_scope, DumpStyleSectionNameOffset);
+                        }
+                    }
+                }
+            }
+        }
+        else
+        {
+            if (fallback_style != DumpStyleInvalid)
+                return Dump (s, exe_scope, fallback_style);
+            return false;
+        }
+        break;
+    }
+
+    return true;
+}
+
+//Stream& operator << (Stream& s, const Address& so_addr)
+//{
+//    so_addr.Dump(&s, Address::DumpStyleSectionNameOffset);
+//    return s;
+//}
+//
+void
+Address::CalculateSymbolContext (SymbolContext *sc)
+{
+    sc->Clear();
+    // Absolute addresses don't have enough information to reconstruct even their target.
+    if (m_section == NULL)
+        return;
+
+    if (m_section->GetModule())
+    {
+        sc->module_sp = m_section->GetModule()->GetSP();
+        if (sc->module_sp)
+            sc->module_sp->ResolveSymbolContextForAddress (*this, eSymbolContextEverything, *sc);
+    }
+}
+
+void
+Address::DumpSymbolContext (Stream *s)
+{
+    SymbolContext sc;
+    CalculateSymbolContext (&sc);
+    sc.Dump (s, NULL);
+}
+
+void
+Address::DumpDebug(Stream *s) const
+{
+    *s << (void *)this << ": " << "Address";
+    if (m_section != NULL)
+    {
+        *s << ", section = " << (void *)m_section << " (" << m_section->GetName() << "), offset = " << m_offset;
+    }
+    else
+    {
+        *s << ", vm_addr = " << m_offset;
+    }
+    s->EOL();
+}
+
+int
+Address::CompareFileAddress (const Address& a, const Address& b)
+{
+    addr_t a_file_addr = a.GetFileAddress();
+    addr_t b_file_addr = b.GetFileAddress();
+    if (a_file_addr < b_file_addr)
+        return -1;
+    if (a_file_addr > b_file_addr)
+        return +1;
+    return 0;
+}
+
+
+int
+Address::CompareLoadAddress (const Address& a, const Address& b, Process *process)
+{
+    assert (process != NULL);
+    addr_t a_load_addr = a.GetLoadAddress (process);
+    addr_t b_load_addr = b.GetLoadAddress (process);
+    if (a_load_addr < b_load_addr)
+        return -1;
+    if (a_load_addr > b_load_addr)
+        return +1;
+    return 0;
+}
+
+int
+Address::CompareModulePointerAndOffset (const Address& a, const Address& b)
+{
+    Module *a_module = a.GetModule ();
+    Module *b_module = b.GetModule ();
+    if (a_module < b_module)
+        return -1;
+    if (a_module > b_module)
+        return +1;
+    // Modules are the same, just compare the file address since they should
+    // be unique
+    addr_t a_file_addr = a.GetFileAddress();
+    addr_t b_file_addr = b.GetFileAddress();
+    if (a_file_addr < b_file_addr)
+        return -1;
+    if (a_file_addr > b_file_addr)
+        return +1;
+    return 0;
+}
+
+
+size_t
+Address::MemorySize () const
+{
+    // Noting special for the memory size of a single Address object,
+    // it is just the size of itself.
+    return sizeof(Address);
+}
+
+
+/// The only comparisons that make sense are the load addresses
+//bool
+//lldb::operator< (const Address& lhs, const Address& rhs)
+//{
+//    lldb::addr_t lhs_addr = lhs.GetLoadAddress();
+//    lldb::addr_t rhs_addr = rhs.GetLoadAddress();
+//
+//    if (lhs_addr == rhs_addr)
+//    {
+//        lhs_addr = lhs.GetFileAddress();
+//        rhs_addr = rhs.GetFileAddress();
+//    }
+//    return lhs_addr < rhs_addr;
+//}
+//
+//bool
+//lldb::operator<=    (const Address& lhs, const Address& rhs)
+//{
+//    lldb::addr_t lhs_addr = lhs.GetLoadAddress();
+//    lldb::addr_t rhs_addr = rhs.GetLoadAddress();
+//
+//    if (lhs_addr == rhs_addr)
+//    {
+//        lhs_addr = lhs.GetFileAddress();
+//        rhs_addr = rhs.GetFileAddress();
+//    }
+//    return lhs_addr <= rhs_addr;
+//}
+//
+//bool
+//lldb::operator> (const Address& lhs, const Address& rhs)
+//{
+//    lldb::addr_t lhs_addr = lhs.GetLoadAddress();
+//    lldb::addr_t rhs_addr = rhs.GetLoadAddress();
+//
+//    if (lhs_addr == rhs_addr)
+//    {
+//        lhs_addr = lhs.GetFileAddress();
+//        rhs_addr = rhs.GetFileAddress();
+//    }
+//    return lhs_addr > rhs_addr;
+//}
+//
+//bool
+//lldb::operator>=    (const Address& lhs, const Address& rhs)
+//{
+//    lldb::addr_t lhs_addr = lhs.GetLoadAddress();
+//    lldb::addr_t rhs_addr = rhs.GetLoadAddress();
+//
+//    if (lhs_addr == rhs_addr)
+//    {
+//        lhs_addr = lhs.GetFileAddress();
+//        rhs_addr = rhs.GetFileAddress();
+//    }
+//    return lhs_addr >= rhs_addr;
+//}
+//
+
+// The operator == checks for exact equality only (same section, same offset)
+bool
+lldb_private::operator== (const Address& a, const Address& rhs)
+{
+    return  a.GetSection() == rhs.GetSection() &&
+            a.GetOffset()  == rhs.GetOffset();
+}
+// The operator != checks for exact inequality only (differing section, or
+// different offset)
+bool
+lldb_private::operator!= (const Address& a, const Address& rhs)
+{
+    return  a.GetSection() != rhs.GetSection() ||
+            a.GetOffset()  != rhs.GetOffset();
+}
+
+bool
+Address::IsLinkedAddress () const
+{
+    return m_section && m_section->GetLinkedSection();
+}
+
+
+void
+Address::ResolveLinkedAddress ()
+{
+    if (m_section)
+    {
+        const Section *linked_section = m_section->GetLinkedSection();
+        if (linked_section)
+        {
+            m_offset += m_section->GetLinkedOffset();
+            m_section = linked_section;
+        }
+    }
+}
diff --git a/source/Core/AddressRange.cpp b/source/Core/AddressRange.cpp
new file mode 100644
index 0000000..8c29979
--- /dev/null
+++ b/source/Core/AddressRange.cpp
@@ -0,0 +1,222 @@
+//===-- AddressRange.cpp ----------------------------------------*- 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/AddressRange.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+AddressRange::AddressRange () :
+    m_base_addr(),
+    m_byte_size(0)
+{
+}
+
+AddressRange::AddressRange (addr_t file_addr, addr_t byte_size, const SectionList *section_list) :
+    m_base_addr(file_addr, section_list),
+    m_byte_size(byte_size)
+{
+}
+
+AddressRange::AddressRange (const Section* section, addr_t offset, addr_t byte_size) :
+    m_base_addr(section, offset),
+    m_byte_size(byte_size)
+{
+}
+
+AddressRange::AddressRange (const Address& so_addr, addr_t byte_size) :
+    m_base_addr(so_addr),
+    m_byte_size(byte_size)
+{
+}
+
+AddressRange::~AddressRange ()
+{
+}
+
+Address &
+AddressRange::GetBaseAddress()
+{
+    return m_base_addr;
+}
+
+const Address &
+AddressRange::GetBaseAddress() const
+{
+    return m_base_addr;
+}
+
+addr_t
+AddressRange::GetByteSize() const
+{
+    return m_byte_size;
+}
+
+void
+AddressRange::SetByteSize(addr_t byte_size)
+{
+    m_byte_size = byte_size;
+}
+
+//bool
+//AddressRange::Contains (const Address &addr) const
+//{
+//    const addr_t byte_size = GetByteSize();
+//    if (byte_size)
+//        return addr.GetSection() == m_base_addr.GetSection() && (addr.GetOffset() - m_base_addr.GetOffset()) < byte_size;
+//}
+//
+//bool
+//AddressRange::Contains (const Address *addr) const
+//{
+//    if (addr)
+//        return Contains (*addr);
+//    return false;
+//}
+
+bool
+AddressRange::ContainsFileAddress (const Address &addr) const
+{
+    if (addr.GetSection() == m_base_addr.GetSection())
+        return (addr.GetOffset() - m_base_addr.GetOffset()) < GetByteSize();
+    addr_t file_base_addr = GetBaseAddress().GetFileAddress();
+    if (file_base_addr == LLDB_INVALID_ADDRESS)
+        return false;
+
+    addr_t file_addr = addr.GetFileAddress();
+    if (file_addr == LLDB_INVALID_ADDRESS)
+        return false;
+
+    if (file_base_addr <= file_addr)
+        return (file_addr - file_base_addr) < GetByteSize();
+
+    return false;
+}
+
+bool
+AddressRange::ContainsFileAddress (addr_t file_addr) const
+{
+    if (file_addr == LLDB_INVALID_ADDRESS)
+        return false;
+
+    addr_t file_base_addr = GetBaseAddress().GetFileAddress();
+    if (file_base_addr == LLDB_INVALID_ADDRESS)
+        return false;
+
+    if (file_base_addr <= file_addr)
+        return (file_addr - file_base_addr) < GetByteSize();
+
+    return false;
+}
+
+
+bool
+AddressRange::ContainsLoadAddress (const Address &addr, Process *process) const
+{
+    if (addr.GetSection() == m_base_addr.GetSection())
+        return (addr.GetOffset() - m_base_addr.GetOffset()) < GetByteSize();
+    addr_t load_base_addr = GetBaseAddress().GetLoadAddress(process);
+    if (load_base_addr == LLDB_INVALID_ADDRESS)
+        return false;
+
+    addr_t load_addr = addr.GetLoadAddress(process);
+    if (load_addr == LLDB_INVALID_ADDRESS)
+        return false;
+
+    if (load_base_addr <= load_addr)
+        return (load_addr - load_base_addr) < GetByteSize();
+
+    return false;
+}
+
+bool
+AddressRange::ContainsLoadAddress (addr_t load_addr, Process *process) const
+{
+    if (load_addr == LLDB_INVALID_ADDRESS)
+        return false;
+
+    addr_t load_base_addr = GetBaseAddress().GetLoadAddress(process);
+    if (load_base_addr == LLDB_INVALID_ADDRESS)
+        return false;
+
+    if (load_base_addr <= load_addr)
+        return (load_addr - load_base_addr) < GetByteSize();
+
+    return false;
+}
+
+void
+AddressRange::Clear()
+{
+    m_base_addr.Clear();
+    m_byte_size = 0;
+}
+
+bool
+AddressRange::Dump(Stream *s, Process *process, Address::DumpStyle style, Address::DumpStyle fallback_style) const
+{
+    addr_t vmaddr = LLDB_INVALID_ADDRESS;
+    int addr_size = sizeof (addr_t);
+    if (process)
+      addr_size = process->GetAddressByteSize ();
+
+    switch (style)
+    {
+    case Address::DumpStyleSectionNameOffset:
+    case Address::DumpStyleSectionPointerOffset:
+        s->PutChar ('[');
+        m_base_addr.Dump(s, process, style, fallback_style);
+        s->PutChar ('-');
+        s->Address (m_base_addr.GetOffset() + GetByteSize(), addr_size);
+        s->PutChar (')');
+        return true;
+        break;
+
+    case Address::DumpStyleFileAddress:
+        vmaddr = m_base_addr.GetFileAddress();
+        break;
+
+    case Address::DumpStyleLoadAddress:
+        vmaddr = m_base_addr.GetLoadAddress(process);
+        break;
+    }
+
+    if (vmaddr != LLDB_INVALID_ADDRESS)
+    {
+        s->AddressRange(vmaddr, vmaddr + GetByteSize(), addr_size);
+        return true;
+    }
+
+    return false;
+}
+
+
+void
+AddressRange::DumpDebug (Stream *s) const
+{
+    s->Printf("%.*p: AddressRange section = %*p, offset = 0x%16.16llx, byte_size = 0x%16.16llx\n", (int)sizeof(void*) * 2, this, (int)sizeof(void*) * 2, m_base_addr.GetSection(), m_base_addr.GetOffset(), GetByteSize());
+}
+
+size_t
+AddressRange::MemorySize () const
+{
+    // Noting special for the memory size of a single AddressRange object,
+    // it is just the size of itself.
+    return sizeof(AddressRange);
+}
+//
+//bool
+//lldb::operator==    (const AddressRange& lhs, const AddressRange& rhs)
+//{
+//    if (lhs.GetBaseAddress() == rhs.GetBaseAddress())
+//        return lhs.GetByteSize() == rhs.GetByteSize();
+//    return false;
+//}
diff --git a/source/Core/AddressResolver.cpp b/source/Core/AddressResolver.cpp
new file mode 100644
index 0000000..5369d96
--- /dev/null
+++ b/source/Core/AddressResolver.cpp
@@ -0,0 +1,67 @@
+//===-- AddressResolver.cpp -------------------------------------*- 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/AddressResolver.h"
+
+
+// Project includes
+
+#include "lldb/Core/Address.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/SearchFilter.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/lldb-private-log.h"
+
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// AddressResolver:
+//----------------------------------------------------------------------
+AddressResolver::AddressResolver ()
+{
+}
+
+AddressResolver::~AddressResolver ()
+{
+
+}
+
+void
+AddressResolver::ResolveAddressInModules (SearchFilter &filter, ModuleList &modules)
+{
+    filter.SearchInModuleList(*this, modules);
+}
+
+void
+AddressResolver::ResolveAddress (SearchFilter &filter)
+{
+    filter.Search (*this);
+}
+
+std::vector<AddressRange> &
+AddressResolver::GetAddressRanges ()
+{
+    return m_address_ranges;
+}
+
+size_t
+AddressResolver::GetNumberOfAddresses ()
+{
+    return m_address_ranges.size();
+}
+
+AddressRange &
+AddressResolver::GetAddressRangeAtIndex (size_t idx)
+{
+  return m_address_ranges[idx];
+}
diff --git a/source/Core/AddressResolverFileLine.cpp b/source/Core/AddressResolverFileLine.cpp
new file mode 100644
index 0000000..c4aadcc
--- /dev/null
+++ b/source/Core/AddressResolverFileLine.cpp
@@ -0,0 +1,100 @@
+//===-- AddressResolverFileLine.cpp -----------------------------*- 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/AddressResolverFileLine.h"
+
+// Project includes
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/lldb-private-log.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// AddressResolverFileLine:
+//----------------------------------------------------------------------
+AddressResolverFileLine::AddressResolverFileLine
+(
+    const FileSpec &file_spec,
+        uint32_t line_no,
+    bool check_inlines
+) :
+    AddressResolver (),
+    m_file_spec (file_spec),
+    m_line_number (line_no),
+    m_inlines (check_inlines)
+{
+}
+
+AddressResolverFileLine::~AddressResolverFileLine ()
+{
+}
+
+Searcher::CallbackReturn
+AddressResolverFileLine::SearchCallback
+(
+    SearchFilter &filter,
+    SymbolContext &context,
+        Address *addr,
+    bool containing
+)
+{
+    SymbolContextList sc_list;
+    uint32_t sc_list_size;
+    CompileUnit *cu = context.comp_unit;
+
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+
+    sc_list_size = cu->ResolveSymbolContext (m_file_spec, m_line_number, m_inlines, false, eSymbolContextEverything,
+                                             sc_list);
+    for (int i = 0; i < sc_list_size; i++)
+    {
+        SymbolContext sc;
+        if (sc_list.GetContextAtIndex(i, sc))
+        {
+            Address line_start = sc.line_entry.range.GetBaseAddress();
+            addr_t byte_size = sc.line_entry.range.GetByteSize();
+            if (line_start.IsValid())
+            {
+                AddressRange new_range (line_start, byte_size);
+                m_address_ranges.push_back (new_range);
+                if (log)
+                {
+                    StreamString s;
+                    //new_bp_loc->GetDescription (&s, lldb::eDescriptionLevelVerbose);
+                    //log->Printf ("Added address: %s\n", s.GetData());
+                }
+            }
+            else
+            {
+                if (log)
+                  log->Printf ("error: Unable to resolve address at file address 0x%llx for %s:%d\n",
+                               line_start.GetFileAddress(),
+                               m_file_spec.GetFilename().AsCString("<Unknown>"),
+                               m_line_number);
+            }
+        }
+    }
+    return Searcher::eCallbackReturnContinue;
+}
+
+Searcher::Depth
+AddressResolverFileLine::GetDepth()
+{
+    return Searcher::eDepthCompUnit;
+}
+
+void
+AddressResolverFileLine::GetDescription (Stream *s)
+{
+    s->Printf ("File and line address - file: \"%s\" line: %u", m_file_spec.GetFilename().AsCString(), m_line_number);
+}
+
+
diff --git a/source/Core/AddressResolverName.cpp b/source/Core/AddressResolverName.cpp
new file mode 100644
index 0000000..9e154c6
--- /dev/null
+++ b/source/Core/AddressResolverName.cpp
@@ -0,0 +1,231 @@
+//===-- AddressResolverName.cpp ---------------------------------*- 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/AddressResolverName.h"
+
+// Project includes
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/lldb-private-log.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+AddressResolverName::AddressResolverName
+(
+    const char *func_name,
+    AddressResolver::MatchType type
+) :
+    AddressResolver (),
+    m_func_name (func_name),
+    m_class_name (NULL),
+    m_regex (),
+    m_match_type (type)
+{
+    if (m_match_type == AddressResolver::Regexp)
+    {
+        if (!m_regex.Compile (m_func_name.AsCString()))
+        {
+            Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+
+            if (log)
+                log->Warning ("function name regexp: \"%s\" did not compile.", m_func_name.AsCString());
+        }
+    }
+}
+
+AddressResolverName::AddressResolverName
+(
+    RegularExpression &func_regex
+) :
+    AddressResolver (),
+    m_func_name (NULL),
+    m_class_name (NULL),
+    m_regex (func_regex),
+    m_match_type (AddressResolver::Regexp)
+{
+
+}
+
+AddressResolverName::AddressResolverName
+(
+    const char *class_name,
+    const char *method,
+    AddressResolver::MatchType type
+) :
+    AddressResolver (),
+    m_func_name (method),
+    m_class_name (class_name),
+    m_regex (),
+    m_match_type (type)
+{
+
+}
+
+AddressResolverName::~AddressResolverName ()
+{
+}
+
+// FIXME: Right now we look at the module level, and call the module's "FindFunctions".
+// Greg says he will add function tables, maybe at the CompileUnit level to accelerate function
+// lookup.  At that point, we should switch the depth to CompileUnit, and look in these tables.
+
+Searcher::CallbackReturn
+AddressResolverName::SearchCallback
+(
+    SearchFilter &filter,
+    SymbolContext &context,
+    Address *addr,
+    bool containing
+)
+{
+    SymbolContextList func_list;
+    SymbolContextList sym_list;
+
+    bool skip_prologue = true;
+    uint32_t i;
+    SymbolContext sc;
+    Address func_addr;
+
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+
+    if (m_class_name)
+    {
+        if (log)
+            log->Warning ("Class/method function specification not supported yet.\n");
+        return Searcher::eCallbackReturnStop;
+    }
+
+    switch (m_match_type)
+    {
+      case AddressResolver::Exact:
+        if (context.module_sp)
+        {
+            context.module_sp->FindSymbolsWithNameAndType (m_func_name, eSymbolTypeCode, sym_list);
+            context.module_sp->FindFunctions (m_func_name, false, func_list);
+        }
+        break;
+      case AddressResolver::Regexp:
+        if (context.module_sp)
+        {
+            context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list);
+            context.module_sp->FindFunctions (m_regex, true, func_list);
+        }
+        break;
+      case AddressResolver::Glob:
+        if (log)
+            log->Warning ("glob is not supported yet.");
+        break;
+    }
+
+    // Remove any duplicates between the funcion list and the symbol list
+    if (func_list.GetSize())
+    {
+        for (i = 0; i < func_list.GetSize(); i++)
+        {
+            if (func_list.GetContextAtIndex(i, sc) == false)
+                continue;
+
+            if (sc.function == NULL)
+                continue;
+            uint32_t j = 0;
+            while (j < sym_list.GetSize())
+            {
+                SymbolContext symbol_sc;
+                if (sym_list.GetContextAtIndex(j, symbol_sc))
+                {
+                    if (symbol_sc.symbol && symbol_sc.symbol->GetAddressRangePtr())
+                    {
+                        if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRangePtr()->GetBaseAddress())
+                        {
+                            sym_list.RemoveContextAtIndex(j);
+                            continue;   // Don't increment j
+                        }
+                    }
+                }
+
+                j++;
+            }
+        }
+
+        for (i = 0; i < func_list.GetSize(); i++)
+        {
+            if (func_list.GetContextAtIndex(i, sc))
+            {
+                if (sc.function)
+                {
+                    func_addr = sc.function->GetAddressRange().GetBaseAddress();
+                    addr_t byte_size = sc.function->GetAddressRange().GetByteSize();
+                    if (skip_prologue)
+                    {
+                        const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
+                        if (prologue_byte_size)
+                        {
+                            func_addr.SetOffset (func_addr.GetOffset() + prologue_byte_size);
+                            byte_size -= prologue_byte_size;
+                        }
+                    }
+
+                    if (filter.AddressPasses (func_addr))
+                    {
+                        AddressRange new_range (func_addr, byte_size);
+                        m_address_ranges.push_back (new_range);
+                    }
+                }
+            }
+        }
+    }
+
+    for (i = 0; i < sym_list.GetSize(); i++)
+    {
+        if (sym_list.GetContextAtIndex(i, sc))
+        {
+            if (sc.symbol && sc.symbol->GetAddressRangePtr())
+            {
+                func_addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress();
+                addr_t byte_size = sc.symbol->GetAddressRangePtr()->GetByteSize();
+
+                if (skip_prologue)
+                {
+                    const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize();
+                    if (prologue_byte_size)
+                    {
+                        func_addr.SetOffset (func_addr.GetOffset() + prologue_byte_size);
+                        byte_size -= prologue_byte_size;
+                    }
+                }
+
+                if (filter.AddressPasses (func_addr))
+                {
+                    AddressRange new_range (func_addr, byte_size);
+                    m_address_ranges.push_back (new_range);
+                }
+            }
+        }
+    }
+    return Searcher::eCallbackReturnContinue;
+}
+
+Searcher::Depth
+AddressResolverName::GetDepth()
+{
+    return Searcher::eDepthModule;
+}
+
+void
+AddressResolverName::GetDescription (Stream *s)
+{
+    s->PutCString("Address by function name: ");
+
+    if (m_match_type == AddressResolver::Regexp)
+        s->Printf("'%s' (regular expression)", m_regex.GetText());
+    else
+        s->Printf("'%s'", m_func_name.AsCString());
+}
+
diff --git a/source/Core/ArchSpec.cpp b/source/Core/ArchSpec.cpp
new file mode 100644
index 0000000..3cc8232
--- /dev/null
+++ b/source/Core/ArchSpec.cpp
@@ -0,0 +1,1681 @@
+//===-- ArchSpec.cpp --------------------------------------------*- 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/ArchSpec.h"
+
+#include <mach/mach.h>
+#include <mach-o/nlist.h>
+
+#include <string>
+
+using namespace lldb;
+using namespace lldb_private;
+
+#define ARCH_SPEC_SEPARATOR_CHAR    '-'
+
+#ifndef CPU_TYPE_ARM
+#define CPU_TYPE_ARM            ((cpu_type_t) 12)
+#endif
+
+#ifndef CPU_SUBTYPE_ARM_ALL
+#define CPU_SUBTYPE_ARM_ALL     ((cpu_subtype_t) 0)
+#endif
+
+#ifndef CPU_SUBTYPE_ARM_V4T
+#define CPU_SUBTYPE_ARM_V4T     ((cpu_subtype_t) 5)
+#endif
+
+#ifndef CPU_SUBTYPE_ARM_V6
+#define CPU_SUBTYPE_ARM_V6      ((cpu_subtype_t) 6)
+#endif
+
+#ifndef CPU_SUBTYPE_ARM_V5TEJ
+#define CPU_SUBTYPE_ARM_V5TEJ   ((cpu_subtype_t) 7)
+#endif
+
+#ifndef CPU_SUBTYPE_ARM_XSCALE
+#define CPU_SUBTYPE_ARM_XSCALE  ((cpu_subtype_t) 8)
+#endif
+
+#ifndef CPU_SUBTYPE_ARM_V7
+#define CPU_SUBTYPE_ARM_V7      ((cpu_subtype_t) 9)
+#endif
+
+//----------------------------------------------------------------------
+// A structure that describes all of the information we want to know
+// about each architecture.
+//----------------------------------------------------------------------
+struct ArchDefinition
+{
+    uint32_t cpu;
+    uint32_t sub;
+    const char *name;
+};
+
+//----------------------------------------------------------------------
+// A table that gets searched linearly for matches. This table is used
+// to convert cpu type and subtypes to architecture names, and to
+// convert architecture names to cpu types and subtypes. The ordering
+// is important and allows the precedence to be set when the table is
+// built.
+//----------------------------------------------------------------------
+static ArchDefinition g_arch_defs[] =
+{
+    { CPU_TYPE_ANY,         CPU_TYPE_ANY                , "all"         },
+    { CPU_TYPE_ARM,         CPU_TYPE_ANY                , "arm"         },
+    { CPU_TYPE_ARM,         CPU_SUBTYPE_ARM_ALL         , "arm"         },
+    { CPU_TYPE_ARM,         CPU_SUBTYPE_ARM_V4T         , "armv4"       },
+    { CPU_TYPE_ARM,         CPU_SUBTYPE_ARM_V5TEJ       , "armv5"       },
+    { CPU_TYPE_ARM,         CPU_SUBTYPE_ARM_V6          , "armv6"       },
+    { CPU_TYPE_ARM,         CPU_SUBTYPE_ARM_V7          , "armv7"       },
+    { CPU_TYPE_ARM,         CPU_SUBTYPE_ARM_XSCALE      , "xscale"      },
+    { CPU_TYPE_POWERPC,     CPU_TYPE_ANY                , "ppc"         },
+    { CPU_TYPE_POWERPC,     CPU_SUBTYPE_POWERPC_ALL     , "ppc"         },
+    { CPU_TYPE_POWERPC,     CPU_SUBTYPE_POWERPC_601     , "ppc601"      },
+    { CPU_TYPE_POWERPC,     CPU_SUBTYPE_POWERPC_602     , "ppc602"      },
+    { CPU_TYPE_POWERPC,     CPU_SUBTYPE_POWERPC_603     , "ppc603"      },
+    { CPU_TYPE_POWERPC,     CPU_SUBTYPE_POWERPC_603e    , "ppc603e"     },
+    { CPU_TYPE_POWERPC,     CPU_SUBTYPE_POWERPC_603ev   , "ppc603ev"    },
+    { CPU_TYPE_POWERPC,     CPU_SUBTYPE_POWERPC_604     , "ppc604"      },
+    { CPU_TYPE_POWERPC,     CPU_SUBTYPE_POWERPC_604e    , "ppc604e"     },
+    { CPU_TYPE_POWERPC,     CPU_SUBTYPE_POWERPC_620     , "ppc620"      },
+    { CPU_TYPE_POWERPC,     CPU_SUBTYPE_POWERPC_750     , "ppc750"      },
+    { CPU_TYPE_POWERPC,     CPU_SUBTYPE_POWERPC_7400    , "ppc7400"     },
+    { CPU_TYPE_POWERPC,     CPU_SUBTYPE_POWERPC_7450    , "ppc7450"     },
+    { CPU_TYPE_POWERPC,     CPU_SUBTYPE_POWERPC_970     , "ppc970"      },
+    { CPU_TYPE_POWERPC64,   CPU_SUBTYPE_POWERPC_ALL     , "ppc64"       },
+    { CPU_TYPE_POWERPC64,   CPU_SUBTYPE_POWERPC_970     , "ppc970-64"   },
+    { CPU_TYPE_I386,        CPU_SUBTYPE_I386_ALL        , "i386"        },
+    { CPU_TYPE_I386,        CPU_SUBTYPE_486             , "i486"        },
+    { CPU_TYPE_I386,        CPU_SUBTYPE_486SX           , "i486sx"      },
+    { CPU_TYPE_I386,        CPU_TYPE_ANY                , "i386"        },
+    { CPU_TYPE_X86_64,      CPU_SUBTYPE_X86_64_ALL      , "x86_64"      },
+    { CPU_TYPE_X86_64,      CPU_TYPE_ANY                , "x86_64"      },
+
+    // TODO: when we get a platform that knows more about the host OS we should
+    // let it call some accessor funcitons to set the default system arch for
+    // the default, 32 and 64 bit cases instead of hard coding it in this
+    // table.
+
+#if defined (__i386__) || defined(__x86_64__)
+    { CPU_TYPE_X86_64,      CPU_SUBTYPE_X86_64_ALL      , LLDB_ARCH_DEFAULT         },
+    { CPU_TYPE_I386,        CPU_SUBTYPE_I386_ALL        , LLDB_ARCH_DEFAULT_32BIT   },
+    { CPU_TYPE_X86_64,      CPU_SUBTYPE_X86_64_ALL      , LLDB_ARCH_DEFAULT_64BIT   },
+#elif defined (__arm__)
+    { CPU_TYPE_ARM,         CPU_SUBTYPE_ARM_V6          , LLDB_ARCH_DEFAULT         },
+    { CPU_TYPE_ARM,         CPU_SUBTYPE_ARM_V6          , LLDB_ARCH_DEFAULT_32BIT   },
+#elif defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__)
+    { CPU_TYPE_POWERPC,     CPU_SUBTYPE_POWERPC_7400    , LLDB_ARCH_DEFAULT         },
+    { CPU_TYPE_POWERPC,     CPU_SUBTYPE_POWERPC_7400    , LLDB_ARCH_DEFAULT_32BIT   },
+    { CPU_TYPE_POWERPC64,   CPU_SUBTYPE_POWERPC_970     , LLDB_ARCH_DEFAULT_64BIT   },
+#endif
+};
+
+//----------------------------------------------------------------------
+// Figure out how many architecture definitions we have
+//----------------------------------------------------------------------
+const size_t k_num_arch_defs = sizeof(g_arch_defs)/sizeof(ArchDefinition);
+
+
+//----------------------------------------------------------------------
+// Default constructor
+//----------------------------------------------------------------------
+ArchSpec::ArchSpec() :
+    m_cpu (LLDB_INVALID_CPUTYPE),
+    m_sub (0)
+{
+}
+
+//----------------------------------------------------------------------
+// Constructor that initializes the object with supplied cpu and
+// subtypes.
+//----------------------------------------------------------------------
+ArchSpec::ArchSpec(uint32_t cpu, uint32_t sub) :
+    m_cpu (cpu),
+    m_sub (sub)
+{
+}
+
+//----------------------------------------------------------------------
+// Constructor that initializes the object with supplied
+// architecture name. There are also predefined values in
+// Defines.h:
+//  liblldb_ARCH_DEFAULT
+//      The arch the current system defaults to when a program is
+//      launched without any extra attributes or settings.
+//
+//  liblldb_ARCH_DEFAULT_32BIT
+//      The 32 bit arch the current system defaults to (if any)
+//
+//  liblldb_ARCH_DEFAULT_32BIT
+//      The 64 bit arch the current system defaults to (if any)
+//----------------------------------------------------------------------
+ArchSpec::ArchSpec(const char *arch_name) :
+    m_cpu (LLDB_INVALID_CPUTYPE),
+    m_sub (0)
+{
+    if (arch_name)
+        SetArch(arch_name);
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ArchSpec::~ArchSpec()
+{
+}
+
+//----------------------------------------------------------------------
+// Assignment operator
+//----------------------------------------------------------------------
+const ArchSpec&
+ArchSpec::operator= (const ArchSpec& rhs)
+{
+    if (this != &rhs)
+    {
+        m_cpu = rhs.m_cpu;
+        m_sub = rhs.m_sub;
+    }
+    return *this;
+}
+
+//----------------------------------------------------------------------
+// Get a C string representation of the current architecture
+//----------------------------------------------------------------------
+const char *
+ArchSpec::AsCString() const
+{
+    return ArchSpec::AsCString(m_cpu, m_sub);
+}
+
+//----------------------------------------------------------------------
+// Class function to get a C string representation given a CPU type
+// and subtype.
+//----------------------------------------------------------------------
+const char *
+ArchSpec::AsCString(uint32_t cpu, uint32_t sub)
+{
+    for (uint32_t i=0; i<k_num_arch_defs; i++)
+    {
+        if (cpu == g_arch_defs[i].cpu)
+        {
+            if (sub == g_arch_defs[i].sub)
+                return g_arch_defs[i].name;
+            else if (sub != CPU_TYPE_ANY && sub != LLDB_INVALID_CPUTYPE)
+            {
+                if ((sub & ~CPU_SUBTYPE_MASK) == g_arch_defs[i].sub)
+                    return g_arch_defs[i].name;
+            }
+        }
+    }
+    static char s_cpu_hex_str[64];
+    ::snprintf(s_cpu_hex_str, sizeof(s_cpu_hex_str), "%u%c%u", cpu, ARCH_SPEC_SEPARATOR_CHAR, sub);
+    return s_cpu_hex_str;
+}
+
+//----------------------------------------------------------------------
+// Clears the object contents back to a default invalid state.
+//----------------------------------------------------------------------
+void
+ArchSpec::Clear()
+{
+    m_cpu = LLDB_INVALID_CPUTYPE;
+    m_sub = 0;
+}
+
+
+//----------------------------------------------------------------------
+// CPU subtype get accessor.
+//----------------------------------------------------------------------
+uint32_t
+ArchSpec::GetCPUSubtype() const
+{
+    if (m_sub == CPU_TYPE_ANY || m_sub == LLDB_INVALID_CPUTYPE)
+        return m_sub;
+    return m_sub & ~CPU_SUBTYPE_MASK;
+}
+
+
+//----------------------------------------------------------------------
+// CPU type get accessor.
+//----------------------------------------------------------------------
+uint32_t
+ArchSpec::GetCPUType() const
+{
+    return m_cpu;
+}
+
+
+//----------------------------------------------------------------------
+// Feature flags get accessor.
+//----------------------------------------------------------------------
+uint32_t
+ArchSpec::GetFeatureFlags() const
+{
+    if (m_sub == CPU_TYPE_ANY || m_sub == LLDB_INVALID_CPUTYPE)
+        return 0;
+    return m_sub & CPU_SUBTYPE_MASK;
+}
+
+
+static const char * g_i386_dwarf_reg_names[] =
+{
+    "eax",
+    "ecx",
+    "edx",
+    "ebx",
+    "esp",
+    "ebp",
+    "esi",
+    "edi",
+    "eip",
+    "eflags"
+};
+
+static const char * g_i386_gcc_reg_names[] =
+{
+    "eax",
+    "ecx",
+    "edx",
+    "ebx",
+    "ebp",
+    "esp",
+    "esi",
+    "edi",
+    "eip",
+    "eflags"
+};
+
+static const char * g_x86_64_dwarf_and_gcc_reg_names[] = {
+    "rax",
+    "rdx",
+    "rcx",
+    "rbx",
+    "rsi",
+    "rdi",
+    "rbp",
+    "rsp",
+    "r8",
+    "r9",
+    "r10",
+    "r11",
+    "r12",
+    "r13",
+    "r14",
+    "r15",
+    "rip"
+};
+
+// Values take from:
+// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0040a/IHI0040A_aadwarf.pdf
+
+enum
+{
+    eRegNumARM_DWARF_r0         = 0,
+    eRegNumARM_DWARF_r1         = 1,
+    eRegNumARM_DWARF_r2         = 2,
+    eRegNumARM_DWARF_r3         = 3,
+    eRegNumARM_DWARF_r4         = 4,
+    eRegNumARM_DWARF_r5         = 5,
+    eRegNumARM_DWARF_r6         = 6,
+    eRegNumARM_DWARF_r7         = 7,
+    eRegNumARM_DWARF_r8         = 8,
+    eRegNumARM_DWARF_r9         = 9,
+    eRegNumARM_DWARF_r10        = 10,
+    eRegNumARM_DWARF_r11        = 11,
+    eRegNumARM_DWARF_r12        = 12,
+    eRegNumARM_DWARF_r13        = 13,   // SP
+    eRegNumARM_DWARF_r14        = 14,   // LR
+    eRegNumARM_DWARF_r15        = 15,   // PC
+
+    eRegNumARM_DWARF_f0_obsolete= 16,
+    eRegNumARM_DWARF_f1_obsolete,
+    eRegNumARM_DWARF_f2_obsolete,
+    eRegNumARM_DWARF_f3_obsolete,
+    eRegNumARM_DWARF_f4_obsolete,
+    eRegNumARM_DWARF_f5_obsolete,
+    eRegNumARM_DWARF_f6_obsolete,
+    eRegNumARM_DWARF_f7_obsolete,
+
+    eRegNumARM_DWARF_s0_obsolete = 16,
+    eRegNumARM_DWARF_s1_obsolete,
+    eRegNumARM_DWARF_s2_obsolete,
+    eRegNumARM_DWARF_s3_obsolete,
+    eRegNumARM_DWARF_s4_obsolete,
+    eRegNumARM_DWARF_s5_obsolete,
+    eRegNumARM_DWARF_s6_obsolete,
+    eRegNumARM_DWARF_s7_obsolete,
+    eRegNumARM_DWARF_s8_obsolete,
+    eRegNumARM_DWARF_s9_obsolete,
+    eRegNumARM_DWARF_s10_obsolete,
+    eRegNumARM_DWARF_s11_obsolete,
+    eRegNumARM_DWARF_s12_obsolete,
+    eRegNumARM_DWARF_s13_obsolete,
+    eRegNumARM_DWARF_s14_obsolete,
+    eRegNumARM_DWARF_s15_obsolete,
+    eRegNumARM_DWARF_s16_obsolete,
+    eRegNumARM_DWARF_s17_obsolete,
+    eRegNumARM_DWARF_s18_obsolete,
+    eRegNumARM_DWARF_s19_obsolete,
+    eRegNumARM_DWARF_s20_obsolete,
+    eRegNumARM_DWARF_s21_obsolete,
+    eRegNumARM_DWARF_s22_obsolete,
+    eRegNumARM_DWARF_s23_obsolete,
+    eRegNumARM_DWARF_s24_obsolete,
+    eRegNumARM_DWARF_s25_obsolete,
+    eRegNumARM_DWARF_s26_obsolete,
+    eRegNumARM_DWARF_s27_obsolete,
+    eRegNumARM_DWARF_s28_obsolete,
+    eRegNumARM_DWARF_s29_obsolete,
+    eRegNumARM_DWARF_s30_obsolete,
+    eRegNumARM_DWARF_s31_obsolete,
+
+    eRegNumARM_DWARF_s0 = 64,
+    eRegNumARM_DWARF_s1,
+    eRegNumARM_DWARF_s2,
+    eRegNumARM_DWARF_s3,
+    eRegNumARM_DWARF_s4,
+    eRegNumARM_DWARF_s5,
+    eRegNumARM_DWARF_s6,
+    eRegNumARM_DWARF_s7,
+    eRegNumARM_DWARF_s8,
+    eRegNumARM_DWARF_s9,
+    eRegNumARM_DWARF_s10,
+    eRegNumARM_DWARF_s11,
+    eRegNumARM_DWARF_s12,
+    eRegNumARM_DWARF_s13,
+    eRegNumARM_DWARF_s14,
+    eRegNumARM_DWARF_s15,
+    eRegNumARM_DWARF_s16,
+    eRegNumARM_DWARF_s17,
+    eRegNumARM_DWARF_s18,
+    eRegNumARM_DWARF_s19,
+    eRegNumARM_DWARF_s20,
+    eRegNumARM_DWARF_s21,
+    eRegNumARM_DWARF_s22,
+    eRegNumARM_DWARF_s23,
+    eRegNumARM_DWARF_s24,
+    eRegNumARM_DWARF_s25,
+    eRegNumARM_DWARF_s26,
+    eRegNumARM_DWARF_s27,
+    eRegNumARM_DWARF_s28,
+    eRegNumARM_DWARF_s29,
+    eRegNumARM_DWARF_s30,
+    eRegNumARM_DWARF_s31,
+
+    eRegNumARM_DWARF_f0         = 96,
+    eRegNumARM_DWARF_f1,
+    eRegNumARM_DWARF_f2,
+    eRegNumARM_DWARF_f3,
+    eRegNumARM_DWARF_f4,
+    eRegNumARM_DWARF_f5,
+    eRegNumARM_DWARF_f6,
+    eRegNumARM_DWARF_f7,
+
+    eRegNumARM_DWARF_ACC0       = 104,
+    eRegNumARM_DWARF_ACC1,
+    eRegNumARM_DWARF_ACC2,
+    eRegNumARM_DWARF_ACC3,
+    eRegNumARM_DWARF_ACC4,
+    eRegNumARM_DWARF_ACC5,
+    eRegNumARM_DWARF_ACC6,
+    eRegNumARM_DWARF_ACC7,
+
+    eRegNumARM_DWARF_wCGR0      = 104,  // These overlap with ACC0-ACC7
+    eRegNumARM_DWARF_wCGR1,
+    eRegNumARM_DWARF_wCGR2,
+    eRegNumARM_DWARF_wCGR3,
+    eRegNumARM_DWARF_wCGR4,
+    eRegNumARM_DWARF_wCGR5,
+    eRegNumARM_DWARF_wCGR6,
+    eRegNumARM_DWARF_wCGR7,
+
+    eRegNumARM_DWARF_wR0        = 112,
+    eRegNumARM_DWARF_wR1,
+    eRegNumARM_DWARF_wR2,
+    eRegNumARM_DWARF_wR3,
+    eRegNumARM_DWARF_wR4,
+    eRegNumARM_DWARF_wR5,
+    eRegNumARM_DWARF_wR6,
+    eRegNumARM_DWARF_wR7,
+    eRegNumARM_DWARF_wR8,
+    eRegNumARM_DWARF_wR9,
+    eRegNumARM_DWARF_wR10,
+    eRegNumARM_DWARF_wR11,
+    eRegNumARM_DWARF_wR12,
+    eRegNumARM_DWARF_wR13,
+    eRegNumARM_DWARF_wR14,
+    eRegNumARM_DWARF_wR15,
+
+    eRegNumARM_DWARF_spsr       = 128,
+    eRegNumARM_DWARF_spsr_fiq,
+    eRegNumARM_DWARF_spsr_irq,
+    eRegNumARM_DWARF_spsr_abt,
+    eRegNumARM_DWARF_spsr_und,
+    eRegNumARM_DWARF_spsr_svc,
+
+    eRegNumARM_DWARF_r8_usr     = 144,
+    eRegNumARM_DWARF_r9_usr,
+    eRegNumARM_DWARF_r10_usr,
+    eRegNumARM_DWARF_r11_usr,
+    eRegNumARM_DWARF_r12_usr,
+    eRegNumARM_DWARF_r13_usr,
+    eRegNumARM_DWARF_r14_usr,
+
+    eRegNumARM_DWARF_r8_fiq     = 151,
+    eRegNumARM_DWARF_r9_fiq,
+    eRegNumARM_DWARF_r10_fiq,
+    eRegNumARM_DWARF_r11_fiq,
+    eRegNumARM_DWARF_r12_fiq,
+    eRegNumARM_DWARF_r13_fiq,
+    eRegNumARM_DWARF_r14_fiq,
+
+    eRegNumARM_DWARF_r13_irq,
+    eRegNumARM_DWARF_r14_irq,
+
+    eRegNumARM_DWARF_r13_abt,
+    eRegNumARM_DWARF_r14_abt,
+
+    eRegNumARM_DWARF_r13_und,
+    eRegNumARM_DWARF_r14_und,
+
+    eRegNumARM_DWARF_r13_svc,
+    eRegNumARM_DWARF_r14_svc,
+
+    eRegNumARM_DWARF_wC0        = 192,
+    eRegNumARM_DWARF_wC1,
+    eRegNumARM_DWARF_wC2,
+    eRegNumARM_DWARF_wC3,
+    eRegNumARM_DWARF_wC4,
+    eRegNumARM_DWARF_wC5,
+    eRegNumARM_DWARF_wC6,
+    eRegNumARM_DWARF_wC7,
+
+    eRegNumARM_DWARF_d0         = 256,  // VFP-v3/NEON D0-D31 (32 64 bit registers)
+    eRegNumARM_DWARF_d1,
+    eRegNumARM_DWARF_d2,
+    eRegNumARM_DWARF_d3,
+    eRegNumARM_DWARF_d4,
+    eRegNumARM_DWARF_d5,
+    eRegNumARM_DWARF_d6,
+    eRegNumARM_DWARF_d7,
+    eRegNumARM_DWARF_d8,
+    eRegNumARM_DWARF_d9,
+    eRegNumARM_DWARF_d10,
+    eRegNumARM_DWARF_d11,
+    eRegNumARM_DWARF_d12,
+    eRegNumARM_DWARF_d13,
+    eRegNumARM_DWARF_d14,
+    eRegNumARM_DWARF_d15,
+    eRegNumARM_DWARF_d16,
+    eRegNumARM_DWARF_d17,
+    eRegNumARM_DWARF_d18,
+    eRegNumARM_DWARF_d19,
+    eRegNumARM_DWARF_d20,
+    eRegNumARM_DWARF_d21,
+    eRegNumARM_DWARF_d22,
+    eRegNumARM_DWARF_d23,
+    eRegNumARM_DWARF_d24,
+    eRegNumARM_DWARF_d25,
+    eRegNumARM_DWARF_d26,
+    eRegNumARM_DWARF_d27,
+    eRegNumARM_DWARF_d28,
+    eRegNumARM_DWARF_d29,
+    eRegNumARM_DWARF_d30,
+    eRegNumARM_DWARF_d31
+};
+
+// Register numbering definitions for 32 and 64 bit ppc for RegisterNumberingType::Dwarf
+enum
+{
+    eRegNumPPC_DWARF_r0         = 0,
+    eRegNumPPC_DWARF_r1         = 1,
+    eRegNumPPC_DWARF_r2         = 2,
+    eRegNumPPC_DWARF_r3         = 3,
+    eRegNumPPC_DWARF_r4         = 4,
+    eRegNumPPC_DWARF_r5         = 5,
+    eRegNumPPC_DWARF_r6         = 6,
+    eRegNumPPC_DWARF_r7         = 7,
+    eRegNumPPC_DWARF_r8         = 8,
+    eRegNumPPC_DWARF_r9         = 9,
+    eRegNumPPC_DWARF_r10        = 10,
+    eRegNumPPC_DWARF_r11        = 11,
+    eRegNumPPC_DWARF_r12        = 12,
+    eRegNumPPC_DWARF_r13        = 13,
+    eRegNumPPC_DWARF_r14        = 14,
+    eRegNumPPC_DWARF_r15        = 15,
+    eRegNumPPC_DWARF_r16        = 16,
+    eRegNumPPC_DWARF_r17        = 17,
+    eRegNumPPC_DWARF_r18        = 18,
+    eRegNumPPC_DWARF_r19        = 19,
+    eRegNumPPC_DWARF_r20        = 20,
+    eRegNumPPC_DWARF_r21        = 21,
+    eRegNumPPC_DWARF_r22        = 22,
+    eRegNumPPC_DWARF_r23        = 23,
+    eRegNumPPC_DWARF_r24        = 24,
+    eRegNumPPC_DWARF_r25        = 25,
+    eRegNumPPC_DWARF_r26        = 26,
+    eRegNumPPC_DWARF_r27        = 27,
+    eRegNumPPC_DWARF_r28        = 28,
+    eRegNumPPC_DWARF_r29        = 29,
+    eRegNumPPC_DWARF_r30        = 30,
+    eRegNumPPC_DWARF_r31        = 31,
+
+    eRegNumPPC_DWARF_fr0        = 32,
+    eRegNumPPC_DWARF_fr1        = 33,
+    eRegNumPPC_DWARF_fr2        = 34,
+    eRegNumPPC_DWARF_fr3        = 35,
+    eRegNumPPC_DWARF_fr4        = 36,
+    eRegNumPPC_DWARF_fr5        = 37,
+    eRegNumPPC_DWARF_fr6        = 38,
+    eRegNumPPC_DWARF_fr7        = 39,
+    eRegNumPPC_DWARF_fr8        = 40,
+    eRegNumPPC_DWARF_fr9        = 41,
+    eRegNumPPC_DWARF_fr10       = 42,
+    eRegNumPPC_DWARF_fr11       = 43,
+    eRegNumPPC_DWARF_fr12       = 44,
+    eRegNumPPC_DWARF_fr13       = 45,
+    eRegNumPPC_DWARF_fr14       = 46,
+    eRegNumPPC_DWARF_fr15       = 47,
+    eRegNumPPC_DWARF_fr16       = 48,
+    eRegNumPPC_DWARF_fr17       = 49,
+    eRegNumPPC_DWARF_fr18       = 50,
+    eRegNumPPC_DWARF_fr19       = 51,
+    eRegNumPPC_DWARF_fr20       = 52,
+    eRegNumPPC_DWARF_fr21       = 53,
+    eRegNumPPC_DWARF_fr22       = 54,
+    eRegNumPPC_DWARF_fr23       = 55,
+    eRegNumPPC_DWARF_fr24       = 56,
+    eRegNumPPC_DWARF_fr25       = 57,
+    eRegNumPPC_DWARF_fr26       = 58,
+    eRegNumPPC_DWARF_fr27       = 59,
+    eRegNumPPC_DWARF_fr28       = 60,
+    eRegNumPPC_DWARF_fr29       = 61,
+    eRegNumPPC_DWARF_fr30       = 62,
+    eRegNumPPC_DWARF_fr31       = 63,
+
+    eRegNumPPC_DWARF_cr         = 64,
+    eRegNumPPC_DWARF_fpscr      = 65,
+    eRegNumPPC_DWARF_msr        = 66,
+    eRegNumPPC_DWARF_vscr       = 67,
+
+    eRegNumPPC_DWARF_sr0        = 70,
+    eRegNumPPC_DWARF_sr1,
+    eRegNumPPC_DWARF_sr2,
+    eRegNumPPC_DWARF_sr3,
+    eRegNumPPC_DWARF_sr4,
+    eRegNumPPC_DWARF_sr5,
+    eRegNumPPC_DWARF_sr6,
+    eRegNumPPC_DWARF_sr7,
+    eRegNumPPC_DWARF_sr8,
+    eRegNumPPC_DWARF_sr9,
+    eRegNumPPC_DWARF_sr10,
+    eRegNumPPC_DWARF_sr11,
+    eRegNumPPC_DWARF_sr12,
+    eRegNumPPC_DWARF_sr13,
+    eRegNumPPC_DWARF_sr14,
+    eRegNumPPC_DWARF_sr15,
+
+
+    eRegNumPPC_DWARF_acc        = 99,
+    eRegNumPPC_DWARF_mq         = 100,
+    eRegNumPPC_DWARF_xer        = 101,
+    eRegNumPPC_DWARF_rtcu       = 104,
+    eRegNumPPC_DWARF_rtcl       = 105,
+
+    eRegNumPPC_DWARF_lr         = 108,
+    eRegNumPPC_DWARF_ctr        = 109,
+
+    eRegNumPPC_DWARF_dsisr      = 118,
+    eRegNumPPC_DWARF_dar        = 119,
+    eRegNumPPC_DWARF_dec        = 122,
+    eRegNumPPC_DWARF_sdr1       = 125,
+    eRegNumPPC_DWARF_srr0       = 126,
+    eRegNumPPC_DWARF_srr1       = 127,
+
+    eRegNumPPC_DWARF_vrsave     = 356,
+    eRegNumPPC_DWARF_sprg0      = 372,
+    eRegNumPPC_DWARF_sprg1,
+    eRegNumPPC_DWARF_sprg2,
+    eRegNumPPC_DWARF_sprg3,
+
+    eRegNumPPC_DWARF_asr        = 380,
+    eRegNumPPC_DWARF_ear        = 382,
+    eRegNumPPC_DWARF_tb         = 384,
+    eRegNumPPC_DWARF_tbu        = 385,
+    eRegNumPPC_DWARF_pvr        = 387,
+
+    eRegNumPPC_DWARF_spefscr    = 612,
+
+    eRegNumPPC_DWARF_ibat0u     = 628,
+    eRegNumPPC_DWARF_ibat0l     = 629,
+    eRegNumPPC_DWARF_ibat1u     = 630,
+    eRegNumPPC_DWARF_ibat1l     = 631,
+    eRegNumPPC_DWARF_ibat2u     = 632,
+    eRegNumPPC_DWARF_ibat2l     = 633,
+    eRegNumPPC_DWARF_ibat3u     = 634,
+    eRegNumPPC_DWARF_ibat3l     = 635,
+    eRegNumPPC_DWARF_dbat0u     = 636,
+    eRegNumPPC_DWARF_dbat0l     = 637,
+    eRegNumPPC_DWARF_dbat1u     = 638,
+    eRegNumPPC_DWARF_dbat1l     = 639,
+    eRegNumPPC_DWARF_dbat2u     = 640,
+    eRegNumPPC_DWARF_dbat2l     = 641,
+    eRegNumPPC_DWARF_dbat3u     = 642,
+    eRegNumPPC_DWARF_dbat3l     = 643,
+
+    eRegNumPPC_DWARF_hid0       = 1108,
+    eRegNumPPC_DWARF_hid1,
+    eRegNumPPC_DWARF_hid2,
+    eRegNumPPC_DWARF_hid3,
+    eRegNumPPC_DWARF_hid4,
+    eRegNumPPC_DWARF_hid5,
+    eRegNumPPC_DWARF_hid6,
+    eRegNumPPC_DWARF_hid7,
+    eRegNumPPC_DWARF_hid8,
+    eRegNumPPC_DWARF_hid9,
+    eRegNumPPC_DWARF_hid10,
+    eRegNumPPC_DWARF_hid11,
+    eRegNumPPC_DWARF_hid12,
+    eRegNumPPC_DWARF_hid13,
+    eRegNumPPC_DWARF_hid14,
+    eRegNumPPC_DWARF_hid15,
+
+    eRegNumPPC_DWARF_vr0        = 1124,
+    eRegNumPPC_DWARF_vr1,
+    eRegNumPPC_DWARF_vr2,
+    eRegNumPPC_DWARF_vr3,
+    eRegNumPPC_DWARF_vr4,
+    eRegNumPPC_DWARF_vr5,
+    eRegNumPPC_DWARF_vr6,
+    eRegNumPPC_DWARF_vr7,
+    eRegNumPPC_DWARF_vr8,
+    eRegNumPPC_DWARF_vr9,
+    eRegNumPPC_DWARF_vr10,
+    eRegNumPPC_DWARF_vr11,
+    eRegNumPPC_DWARF_vr12,
+    eRegNumPPC_DWARF_vr13,
+    eRegNumPPC_DWARF_vr14,
+    eRegNumPPC_DWARF_vr15,
+    eRegNumPPC_DWARF_vr16,
+    eRegNumPPC_DWARF_vr17,
+    eRegNumPPC_DWARF_vr18,
+    eRegNumPPC_DWARF_vr19,
+    eRegNumPPC_DWARF_vr20,
+    eRegNumPPC_DWARF_vr21,
+    eRegNumPPC_DWARF_vr22,
+    eRegNumPPC_DWARF_vr23,
+    eRegNumPPC_DWARF_vr24,
+    eRegNumPPC_DWARF_vr25,
+    eRegNumPPC_DWARF_vr26,
+    eRegNumPPC_DWARF_vr27,
+    eRegNumPPC_DWARF_vr28,
+    eRegNumPPC_DWARF_vr29,
+    eRegNumPPC_DWARF_vr30,
+    eRegNumPPC_DWARF_vr31,
+
+    eRegNumPPC_DWARF_ev0        = 1200,
+    eRegNumPPC_DWARF_ev1,
+    eRegNumPPC_DWARF_ev2,
+    eRegNumPPC_DWARF_ev3,
+    eRegNumPPC_DWARF_ev4,
+    eRegNumPPC_DWARF_ev5,
+    eRegNumPPC_DWARF_ev6,
+    eRegNumPPC_DWARF_ev7,
+    eRegNumPPC_DWARF_ev8,
+    eRegNumPPC_DWARF_ev9,
+    eRegNumPPC_DWARF_ev10,
+    eRegNumPPC_DWARF_ev11,
+    eRegNumPPC_DWARF_ev12,
+    eRegNumPPC_DWARF_ev13,
+    eRegNumPPC_DWARF_ev14,
+    eRegNumPPC_DWARF_ev15,
+    eRegNumPPC_DWARF_ev16,
+    eRegNumPPC_DWARF_ev17,
+    eRegNumPPC_DWARF_ev18,
+    eRegNumPPC_DWARF_ev19,
+    eRegNumPPC_DWARF_ev20,
+    eRegNumPPC_DWARF_ev21,
+    eRegNumPPC_DWARF_ev22,
+    eRegNumPPC_DWARF_ev23,
+    eRegNumPPC_DWARF_ev24,
+    eRegNumPPC_DWARF_ev25,
+    eRegNumPPC_DWARF_ev26,
+    eRegNumPPC_DWARF_ev27,
+    eRegNumPPC_DWARF_ev28,
+    eRegNumPPC_DWARF_ev29,
+    eRegNumPPC_DWARF_ev30,
+    eRegNumPPC_DWARF_ev31
+};
+
+// Register numbering definitions for 32 and 64 bit ppc for RegisterNumberingType::GCC
+enum
+{
+    eRegNumPPC_GCC_r0       = 0,
+    eRegNumPPC_GCC_r1       = 1,
+    eRegNumPPC_GCC_r2       = 2,
+    eRegNumPPC_GCC_r3       = 3,
+    eRegNumPPC_GCC_r4       = 4,
+    eRegNumPPC_GCC_r5       = 5,
+    eRegNumPPC_GCC_r6       = 6,
+    eRegNumPPC_GCC_r7       = 7,
+    eRegNumPPC_GCC_r8       = 8,
+    eRegNumPPC_GCC_r9       = 9,
+    eRegNumPPC_GCC_r10      = 10,
+    eRegNumPPC_GCC_r11      = 11,
+    eRegNumPPC_GCC_r12      = 12,
+    eRegNumPPC_GCC_r13      = 13,
+    eRegNumPPC_GCC_r14      = 14,
+    eRegNumPPC_GCC_r15      = 15,
+    eRegNumPPC_GCC_r16      = 16,
+    eRegNumPPC_GCC_r17      = 17,
+    eRegNumPPC_GCC_r18      = 18,
+    eRegNumPPC_GCC_r19      = 19,
+    eRegNumPPC_GCC_r20      = 20,
+    eRegNumPPC_GCC_r21      = 21,
+    eRegNumPPC_GCC_r22      = 22,
+    eRegNumPPC_GCC_r23      = 23,
+    eRegNumPPC_GCC_r24      = 24,
+    eRegNumPPC_GCC_r25      = 25,
+    eRegNumPPC_GCC_r26      = 26,
+    eRegNumPPC_GCC_r27      = 27,
+    eRegNumPPC_GCC_r28      = 28,
+    eRegNumPPC_GCC_r29      = 29,
+    eRegNumPPC_GCC_r30      = 30,
+    eRegNumPPC_GCC_r31      = 31,
+    eRegNumPPC_GCC_fr0      = 32,
+    eRegNumPPC_GCC_fr1      = 33,
+    eRegNumPPC_GCC_fr2      = 34,
+    eRegNumPPC_GCC_fr3      = 35,
+    eRegNumPPC_GCC_fr4      = 36,
+    eRegNumPPC_GCC_fr5      = 37,
+    eRegNumPPC_GCC_fr6      = 38,
+    eRegNumPPC_GCC_fr7      = 39,
+    eRegNumPPC_GCC_fr8      = 40,
+    eRegNumPPC_GCC_fr9      = 41,
+    eRegNumPPC_GCC_fr10     = 42,
+    eRegNumPPC_GCC_fr11     = 43,
+    eRegNumPPC_GCC_fr12     = 44,
+    eRegNumPPC_GCC_fr13     = 45,
+    eRegNumPPC_GCC_fr14     = 46,
+    eRegNumPPC_GCC_fr15     = 47,
+    eRegNumPPC_GCC_fr16     = 48,
+    eRegNumPPC_GCC_fr17     = 49,
+    eRegNumPPC_GCC_fr18     = 50,
+    eRegNumPPC_GCC_fr19     = 51,
+    eRegNumPPC_GCC_fr20     = 52,
+    eRegNumPPC_GCC_fr21     = 53,
+    eRegNumPPC_GCC_fr22     = 54,
+    eRegNumPPC_GCC_fr23     = 55,
+    eRegNumPPC_GCC_fr24     = 56,
+    eRegNumPPC_GCC_fr25     = 57,
+    eRegNumPPC_GCC_fr26     = 58,
+    eRegNumPPC_GCC_fr27     = 59,
+    eRegNumPPC_GCC_fr28     = 60,
+    eRegNumPPC_GCC_fr29     = 61,
+    eRegNumPPC_GCC_fr30     = 62,
+    eRegNumPPC_GCC_fr31     = 63,
+    eRegNumPPC_GCC_mq       = 64,
+    eRegNumPPC_GCC_lr       = 65,
+    eRegNumPPC_GCC_ctr      = 66,
+    eRegNumPPC_GCC_ap       = 67,
+    eRegNumPPC_GCC_cr0      = 68,
+    eRegNumPPC_GCC_cr1      = 69,
+    eRegNumPPC_GCC_cr2      = 70,
+    eRegNumPPC_GCC_cr3      = 71,
+    eRegNumPPC_GCC_cr4      = 72,
+    eRegNumPPC_GCC_cr5      = 73,
+    eRegNumPPC_GCC_cr6      = 74,
+    eRegNumPPC_GCC_cr7      = 75,
+    eRegNumPPC_GCC_xer      = 76,
+    eRegNumPPC_GCC_v0       = 77,
+    eRegNumPPC_GCC_v1       = 78,
+    eRegNumPPC_GCC_v2       = 79,
+    eRegNumPPC_GCC_v3       = 80,
+    eRegNumPPC_GCC_v4       = 81,
+    eRegNumPPC_GCC_v5       = 82,
+    eRegNumPPC_GCC_v6       = 83,
+    eRegNumPPC_GCC_v7       = 84,
+    eRegNumPPC_GCC_v8       = 85,
+    eRegNumPPC_GCC_v9       = 86,
+    eRegNumPPC_GCC_v10      = 87,
+    eRegNumPPC_GCC_v11      = 88,
+    eRegNumPPC_GCC_v12      = 89,
+    eRegNumPPC_GCC_v13      = 90,
+    eRegNumPPC_GCC_v14      = 91,
+    eRegNumPPC_GCC_v15      = 92,
+    eRegNumPPC_GCC_v16      = 93,
+    eRegNumPPC_GCC_v17      = 94,
+    eRegNumPPC_GCC_v18      = 95,
+    eRegNumPPC_GCC_v19      = 96,
+    eRegNumPPC_GCC_v20      = 97,
+    eRegNumPPC_GCC_v21      = 98,
+    eRegNumPPC_GCC_v22      = 99,
+    eRegNumPPC_GCC_v23      = 100,
+    eRegNumPPC_GCC_v24      = 101,
+    eRegNumPPC_GCC_v25      = 102,
+    eRegNumPPC_GCC_v26      = 103,
+    eRegNumPPC_GCC_v27      = 104,
+    eRegNumPPC_GCC_v28      = 105,
+    eRegNumPPC_GCC_v29      = 106,
+    eRegNumPPC_GCC_v30      = 107,
+    eRegNumPPC_GCC_v31      = 108,
+    eRegNumPPC_GCC_vrsave   = 109,
+    eRegNumPPC_GCC_vscr     = 110,
+    eRegNumPPC_GCC_spe_acc  = 111,
+    eRegNumPPC_GCC_spefscr  = 112,
+    eRegNumPPC_GCC_sfp      = 113,
+};
+
+static const char * g_arm_gcc_reg_names[] = {
+    "r0",   "r1",   "r2",   "r3",   "r4",   "r5",   "r6",   "r7",
+    "r8",   "r9",   "r10",  "r11",  "r12",  "sp",   "lr",   "pc",
+    "f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7",
+    "cc",   "sfp",  "afp",
+    "mv0",  "mv1",  "mv2",  "mv3",  "mv4",  "mv5",  "mv6",  "mv7",
+    "mv8",  "mv9",  "mv10", "mv11", "mv12", "mv13", "mv14", "mv15",
+    "wcgr0","wcgr1","wcgr2","wcgr3",
+    "wr0",  "wr1",  "wr2",  "wr3",  "wr4",  "wr5",  "wr6",  "wr7",
+    "wr8",  "wr9",  "wr10", "wr11", "wr12", "wr13", "wr14", "wr15",
+    "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "s6",   "s7",
+    "s8",   "s9",   "s10",  "s11",  "s12",  "s13",  "s14",  "s15",
+    "s16",  "s17",  "s18",  "s19",  "s20",  "s21",  "s22",  "s23",
+    "s24",  "s25",  "s26",  "s27",  "s28",  "s29",  "s30",  "s31",
+    "vfpcc"
+};
+
+//----------------------------------------------------------------------
+// Get register names for the current object architecture given
+// a register number, and a reg_kind for that register number.
+//----------------------------------------------------------------------
+const char *
+ArchSpec::GetRegisterName(uint32_t reg_num, uint32_t reg_kind) const
+{
+    return ArchSpec::GetRegisterName(m_cpu, m_sub, reg_num, reg_kind);
+}
+
+
+//----------------------------------------------------------------------
+// Get register names for the specified CPU type and subtype given
+// a register number, and a reg_kind for that register number.
+//----------------------------------------------------------------------
+const char *
+ArchSpec::GetRegisterName(uint32_t cpu, uint32_t subtype, uint32_t reg_num, uint32_t reg_kind)
+{
+    if (cpu == CPU_TYPE_I386)
+    {
+        switch (reg_kind)
+        {
+        case eRegisterKindGCC:
+            if (reg_num < sizeof(g_i386_gcc_reg_names)/sizeof(const char *))
+                return g_i386_gcc_reg_names[reg_num];
+            break;
+        case eRegisterKindDWARF:
+            if (reg_num < sizeof(g_i386_dwarf_reg_names)/sizeof(const char *))
+                return g_i386_dwarf_reg_names[reg_num];
+            break;
+        default:
+            break;
+        }
+    }
+    else if (cpu == CPU_TYPE_X86_64)
+    {
+        switch (reg_kind)
+        {
+        case eRegisterKindGCC:
+        case eRegisterKindDWARF:
+            if (reg_num < sizeof(g_x86_64_dwarf_and_gcc_reg_names)/sizeof(const char *))
+                return g_x86_64_dwarf_and_gcc_reg_names[reg_num];
+            break;
+        default:
+            break;
+        }
+    }
+    else if (cpu == CPU_TYPE_ARM)
+    {
+        switch (reg_kind)
+        {
+        case eRegisterKindGCC:
+            if (reg_num < sizeof(g_arm_gcc_reg_names)/sizeof(const char *))
+                return g_arm_gcc_reg_names[reg_num];
+            break;
+
+        case eRegisterKindDWARF:
+            switch (reg_num)
+            {
+            case eRegNumARM_DWARF_r0:       return "r0";
+            case eRegNumARM_DWARF_r1:       return "r1";
+            case eRegNumARM_DWARF_r2:       return "r2";
+            case eRegNumARM_DWARF_r3:       return "r3";
+            case eRegNumARM_DWARF_r4:       return "r4";
+            case eRegNumARM_DWARF_r5:       return "r5";
+            case eRegNumARM_DWARF_r6:       return "r6";
+            case eRegNumARM_DWARF_r7:       return "r7";
+            case eRegNumARM_DWARF_r8:       return "r8";
+            case eRegNumARM_DWARF_r9:       return "r9";
+            case eRegNumARM_DWARF_r10:      return "r10";
+            case eRegNumARM_DWARF_r11:      return "r11";
+            case eRegNumARM_DWARF_r12:      return "r12";
+            case eRegNumARM_DWARF_r13:      return "sp";
+            case eRegNumARM_DWARF_r14:      return "lr";
+            case eRegNumARM_DWARF_r15:      return "pc";
+            case eRegNumARM_DWARF_s0_obsolete:  case eRegNumARM_DWARF_s0:       return "s0";
+            case eRegNumARM_DWARF_s1_obsolete:  case eRegNumARM_DWARF_s1:       return "s1";
+            case eRegNumARM_DWARF_s2_obsolete:  case eRegNumARM_DWARF_s2:       return "s2";
+            case eRegNumARM_DWARF_s3_obsolete:  case eRegNumARM_DWARF_s3:       return "s3";
+            case eRegNumARM_DWARF_s4_obsolete:  case eRegNumARM_DWARF_s4:       return "s4";
+            case eRegNumARM_DWARF_s5_obsolete:  case eRegNumARM_DWARF_s5:       return "s5";
+            case eRegNumARM_DWARF_s6_obsolete:  case eRegNumARM_DWARF_s6:       return "s6";
+            case eRegNumARM_DWARF_s7_obsolete:  case eRegNumARM_DWARF_s7:       return "s7";
+            case eRegNumARM_DWARF_s8_obsolete:  case eRegNumARM_DWARF_s8:       return "s8";
+            case eRegNumARM_DWARF_s9_obsolete:  case eRegNumARM_DWARF_s9:       return "s9";
+            case eRegNumARM_DWARF_s10_obsolete: case eRegNumARM_DWARF_s10:      return "s10";
+            case eRegNumARM_DWARF_s11_obsolete: case eRegNumARM_DWARF_s11:      return "s11";
+            case eRegNumARM_DWARF_s12_obsolete: case eRegNumARM_DWARF_s12:      return "s12";
+            case eRegNumARM_DWARF_s13_obsolete: case eRegNumARM_DWARF_s13:      return "s13";
+            case eRegNumARM_DWARF_s14_obsolete: case eRegNumARM_DWARF_s14:      return "s14";
+            case eRegNumARM_DWARF_s15_obsolete: case eRegNumARM_DWARF_s15:      return "s15";
+            case eRegNumARM_DWARF_s16_obsolete: case eRegNumARM_DWARF_s16:      return "s16";
+            case eRegNumARM_DWARF_s17_obsolete: case eRegNumARM_DWARF_s17:      return "s17";
+            case eRegNumARM_DWARF_s18_obsolete: case eRegNumARM_DWARF_s18:      return "s18";
+            case eRegNumARM_DWARF_s19_obsolete: case eRegNumARM_DWARF_s19:      return "s19";
+            case eRegNumARM_DWARF_s20_obsolete: case eRegNumARM_DWARF_s20:      return "s20";
+            case eRegNumARM_DWARF_s21_obsolete: case eRegNumARM_DWARF_s21:      return "s21";
+            case eRegNumARM_DWARF_s22_obsolete: case eRegNumARM_DWARF_s22:      return "s22";
+            case eRegNumARM_DWARF_s23_obsolete: case eRegNumARM_DWARF_s23:      return "s23";
+            case eRegNumARM_DWARF_s24_obsolete: case eRegNumARM_DWARF_s24:      return "s24";
+            case eRegNumARM_DWARF_s25_obsolete: case eRegNumARM_DWARF_s25:      return "s25";
+            case eRegNumARM_DWARF_s26_obsolete: case eRegNumARM_DWARF_s26:      return "s26";
+            case eRegNumARM_DWARF_s27_obsolete: case eRegNumARM_DWARF_s27:      return "s27";
+            case eRegNumARM_DWARF_s28_obsolete: case eRegNumARM_DWARF_s28:      return "s28";
+            case eRegNumARM_DWARF_s29_obsolete: case eRegNumARM_DWARF_s29:      return "s29";
+            case eRegNumARM_DWARF_s30_obsolete: case eRegNumARM_DWARF_s30:      return "s30";
+            case eRegNumARM_DWARF_s31_obsolete: case eRegNumARM_DWARF_s31:      return "s31";
+            case eRegNumARM_DWARF_f0:       return "f0";
+            case eRegNumARM_DWARF_f1:       return "f1";
+            case eRegNumARM_DWARF_f2:       return "f2";
+            case eRegNumARM_DWARF_f3:       return "f3";
+            case eRegNumARM_DWARF_f4:       return "f4";
+            case eRegNumARM_DWARF_f5:       return "f5";
+            case eRegNumARM_DWARF_f6:       return "f6";
+            case eRegNumARM_DWARF_f7:       return "f7";
+            case eRegNumARM_DWARF_wCGR0:    return "wCGR0/ACC0";
+            case eRegNumARM_DWARF_wCGR1:    return "wCGR1/ACC1";
+            case eRegNumARM_DWARF_wCGR2:    return "wCGR2/ACC2";
+            case eRegNumARM_DWARF_wCGR3:    return "wCGR3/ACC3";
+            case eRegNumARM_DWARF_wCGR4:    return "wCGR4/ACC4";
+            case eRegNumARM_DWARF_wCGR5:    return "wCGR5/ACC5";
+            case eRegNumARM_DWARF_wCGR6:    return "wCGR6/ACC6";
+            case eRegNumARM_DWARF_wCGR7:    return "wCGR7/ACC7";
+            case eRegNumARM_DWARF_wR0:      return "wR0";
+            case eRegNumARM_DWARF_wR1:      return "wR1";
+            case eRegNumARM_DWARF_wR2:      return "wR2";
+            case eRegNumARM_DWARF_wR3:      return "wR3";
+            case eRegNumARM_DWARF_wR4:      return "wR4";
+            case eRegNumARM_DWARF_wR5:      return "wR5";
+            case eRegNumARM_DWARF_wR6:      return "wR6";
+            case eRegNumARM_DWARF_wR7:      return "wR7";
+            case eRegNumARM_DWARF_wR8:      return "wR8";
+            case eRegNumARM_DWARF_wR9:      return "wR9";
+            case eRegNumARM_DWARF_wR10:     return "wR10";
+            case eRegNumARM_DWARF_wR11:     return "wR11";
+            case eRegNumARM_DWARF_wR12:     return "wR12";
+            case eRegNumARM_DWARF_wR13:     return "wR13";
+            case eRegNumARM_DWARF_wR14:     return "wR14";
+            case eRegNumARM_DWARF_wR15:     return "wR15";
+            case eRegNumARM_DWARF_spsr:     return "spsr";
+            case eRegNumARM_DWARF_spsr_fiq: return "spsr_fiq";
+            case eRegNumARM_DWARF_spsr_irq: return "spsr_irq";
+            case eRegNumARM_DWARF_spsr_abt: return "spsr_abt";
+            case eRegNumARM_DWARF_spsr_und: return "spsr_und";
+            case eRegNumARM_DWARF_spsr_svc: return "spsr_svc";
+            case eRegNumARM_DWARF_r8_usr:   return "r8_usr";
+            case eRegNumARM_DWARF_r9_usr:   return "r9_usr";
+            case eRegNumARM_DWARF_r10_usr:  return "r10_usr";
+            case eRegNumARM_DWARF_r11_usr:  return "r11_usr";
+            case eRegNumARM_DWARF_r12_usr:  return "r12_usr";
+            case eRegNumARM_DWARF_r13_usr:  return "sp_usr";
+            case eRegNumARM_DWARF_r14_usr:  return "lr_usr";
+            case eRegNumARM_DWARF_r8_fiq:   return "r8_fiq";
+            case eRegNumARM_DWARF_r9_fiq:   return "r9_fiq";
+            case eRegNumARM_DWARF_r10_fiq:  return "r10_fiq";
+            case eRegNumARM_DWARF_r11_fiq:  return "r11_fiq";
+            case eRegNumARM_DWARF_r12_fiq:  return "r12_fiq";
+            case eRegNumARM_DWARF_r13_fiq:  return "sp_fiq";
+            case eRegNumARM_DWARF_r14_fiq:  return "lr_fiq";
+            case eRegNumARM_DWARF_r13_irq:  return "sp_irq";
+            case eRegNumARM_DWARF_r14_irq:  return "lr_irq";
+            case eRegNumARM_DWARF_r13_abt:  return "sp_abt";
+            case eRegNumARM_DWARF_r14_abt:  return "lr_abt";
+            case eRegNumARM_DWARF_r13_und:  return "sp_und";
+            case eRegNumARM_DWARF_r14_und:  return "lr_und";
+            case eRegNumARM_DWARF_r13_svc:  return "sp_svc";
+            case eRegNumARM_DWARF_r14_svc:  return "lr_svc";
+            case eRegNumARM_DWARF_wC0:      return "wC0";
+            case eRegNumARM_DWARF_wC1:      return "wC1";
+            case eRegNumARM_DWARF_wC2:      return "wC2";
+            case eRegNumARM_DWARF_wC3:      return "wC3";
+            case eRegNumARM_DWARF_wC4:      return "wC4";
+            case eRegNumARM_DWARF_wC5:      return "wC5";
+            case eRegNumARM_DWARF_wC6:      return "wC6";
+            case eRegNumARM_DWARF_wC7:      return "wC7";
+            case eRegNumARM_DWARF_d0:       return "d0";
+            case eRegNumARM_DWARF_d1:       return "d1";
+            case eRegNumARM_DWARF_d2:       return "d2";
+            case eRegNumARM_DWARF_d3:       return "d3";
+            case eRegNumARM_DWARF_d4:       return "d4";
+            case eRegNumARM_DWARF_d5:       return "d5";
+            case eRegNumARM_DWARF_d6:       return "d6";
+            case eRegNumARM_DWARF_d7:       return "d7";
+            case eRegNumARM_DWARF_d8:       return "d8";
+            case eRegNumARM_DWARF_d9:       return "d9";
+            case eRegNumARM_DWARF_d10:      return "d10";
+            case eRegNumARM_DWARF_d11:      return "d11";
+            case eRegNumARM_DWARF_d12:      return "d12";
+            case eRegNumARM_DWARF_d13:      return "d13";
+            case eRegNumARM_DWARF_d14:      return "d14";
+            case eRegNumARM_DWARF_d15:      return "d15";
+            case eRegNumARM_DWARF_d16:      return "d16";
+            case eRegNumARM_DWARF_d17:      return "d17";
+            case eRegNumARM_DWARF_d18:      return "d18";
+            case eRegNumARM_DWARF_d19:      return "d19";
+            case eRegNumARM_DWARF_d20:      return "d20";
+            case eRegNumARM_DWARF_d21:      return "d21";
+            case eRegNumARM_DWARF_d22:      return "d22";
+            case eRegNumARM_DWARF_d23:      return "d23";
+            case eRegNumARM_DWARF_d24:      return "d24";
+            case eRegNumARM_DWARF_d25:      return "d25";
+            case eRegNumARM_DWARF_d26:      return "d26";
+            case eRegNumARM_DWARF_d27:      return "d27";
+            case eRegNumARM_DWARF_d28:      return "d28";
+            case eRegNumARM_DWARF_d29:      return "d29";
+            case eRegNumARM_DWARF_d30:      return "d30";
+            case eRegNumARM_DWARF_d31:      return "d31";
+            }
+            break;
+        default:
+            break;
+        }
+    }
+    else if (cpu == CPU_TYPE_POWERPC || cpu == CPU_TYPE_POWERPC64)
+    {
+        switch (reg_kind)
+        {
+        case eRegisterKindGCC:
+            switch (reg_num)
+            {
+            case eRegNumPPC_GCC_r0:         return "r0";
+            case eRegNumPPC_GCC_r1:         return "r1";
+            case eRegNumPPC_GCC_r2:         return "r2";
+            case eRegNumPPC_GCC_r3:         return "r3";
+            case eRegNumPPC_GCC_r4:         return "r4";
+            case eRegNumPPC_GCC_r5:         return "r5";
+            case eRegNumPPC_GCC_r6:         return "r6";
+            case eRegNumPPC_GCC_r7:         return "r7";
+            case eRegNumPPC_GCC_r8:         return "r8";
+            case eRegNumPPC_GCC_r9:         return "r9";
+            case eRegNumPPC_GCC_r10:        return "r10";
+            case eRegNumPPC_GCC_r11:        return "r11";
+            case eRegNumPPC_GCC_r12:        return "r12";
+            case eRegNumPPC_GCC_r13:        return "r13";
+            case eRegNumPPC_GCC_r14:        return "r14";
+            case eRegNumPPC_GCC_r15:        return "r15";
+            case eRegNumPPC_GCC_r16:        return "r16";
+            case eRegNumPPC_GCC_r17:        return "r17";
+            case eRegNumPPC_GCC_r18:        return "r18";
+            case eRegNumPPC_GCC_r19:        return "r19";
+            case eRegNumPPC_GCC_r20:        return "r20";
+            case eRegNumPPC_GCC_r21:        return "r21";
+            case eRegNumPPC_GCC_r22:        return "r22";
+            case eRegNumPPC_GCC_r23:        return "r23";
+            case eRegNumPPC_GCC_r24:        return "r24";
+            case eRegNumPPC_GCC_r25:        return "r25";
+            case eRegNumPPC_GCC_r26:        return "r26";
+            case eRegNumPPC_GCC_r27:        return "r27";
+            case eRegNumPPC_GCC_r28:        return "r28";
+            case eRegNumPPC_GCC_r29:        return "r29";
+            case eRegNumPPC_GCC_r30:        return "r30";
+            case eRegNumPPC_GCC_r31:        return "r31";
+            case eRegNumPPC_GCC_fr0:        return "fr0";
+            case eRegNumPPC_GCC_fr1:        return "fr1";
+            case eRegNumPPC_GCC_fr2:        return "fr2";
+            case eRegNumPPC_GCC_fr3:        return "fr3";
+            case eRegNumPPC_GCC_fr4:        return "fr4";
+            case eRegNumPPC_GCC_fr5:        return "fr5";
+            case eRegNumPPC_GCC_fr6:        return "fr6";
+            case eRegNumPPC_GCC_fr7:        return "fr7";
+            case eRegNumPPC_GCC_fr8:        return "fr8";
+            case eRegNumPPC_GCC_fr9:        return "fr9";
+            case eRegNumPPC_GCC_fr10:       return "fr10";
+            case eRegNumPPC_GCC_fr11:       return "fr11";
+            case eRegNumPPC_GCC_fr12:       return "fr12";
+            case eRegNumPPC_GCC_fr13:       return "fr13";
+            case eRegNumPPC_GCC_fr14:       return "fr14";
+            case eRegNumPPC_GCC_fr15:       return "fr15";
+            case eRegNumPPC_GCC_fr16:       return "fr16";
+            case eRegNumPPC_GCC_fr17:       return "fr17";
+            case eRegNumPPC_GCC_fr18:       return "fr18";
+            case eRegNumPPC_GCC_fr19:       return "fr19";
+            case eRegNumPPC_GCC_fr20:       return "fr20";
+            case eRegNumPPC_GCC_fr21:       return "fr21";
+            case eRegNumPPC_GCC_fr22:       return "fr22";
+            case eRegNumPPC_GCC_fr23:       return "fr23";
+            case eRegNumPPC_GCC_fr24:       return "fr24";
+            case eRegNumPPC_GCC_fr25:       return "fr25";
+            case eRegNumPPC_GCC_fr26:       return "fr26";
+            case eRegNumPPC_GCC_fr27:       return "fr27";
+            case eRegNumPPC_GCC_fr28:       return "fr28";
+            case eRegNumPPC_GCC_fr29:       return "fr29";
+            case eRegNumPPC_GCC_fr30:       return "fr30";
+            case eRegNumPPC_GCC_fr31:       return "fr31";
+            case eRegNumPPC_GCC_mq:         return "mq";
+            case eRegNumPPC_GCC_lr:         return "lr";
+            case eRegNumPPC_GCC_ctr:        return "ctr";
+            case eRegNumPPC_GCC_ap:         return "ap";
+            case eRegNumPPC_GCC_cr0:        return "cr0";
+            case eRegNumPPC_GCC_cr1:        return "cr1";
+            case eRegNumPPC_GCC_cr2:        return "cr2";
+            case eRegNumPPC_GCC_cr3:        return "cr3";
+            case eRegNumPPC_GCC_cr4:        return "cr4";
+            case eRegNumPPC_GCC_cr5:        return "cr5";
+            case eRegNumPPC_GCC_cr6:        return "cr6";
+            case eRegNumPPC_GCC_cr7:        return "cr7";
+            case eRegNumPPC_GCC_xer:        return "xer";
+            case eRegNumPPC_GCC_v0:         return "v0";
+            case eRegNumPPC_GCC_v1:         return "v1";
+            case eRegNumPPC_GCC_v2:         return "v2";
+            case eRegNumPPC_GCC_v3:         return "v3";
+            case eRegNumPPC_GCC_v4:         return "v4";
+            case eRegNumPPC_GCC_v5:         return "v5";
+            case eRegNumPPC_GCC_v6:         return "v6";
+            case eRegNumPPC_GCC_v7:         return "v7";
+            case eRegNumPPC_GCC_v8:         return "v8";
+            case eRegNumPPC_GCC_v9:         return "v9";
+            case eRegNumPPC_GCC_v10:        return "v10";
+            case eRegNumPPC_GCC_v11:        return "v11";
+            case eRegNumPPC_GCC_v12:        return "v12";
+            case eRegNumPPC_GCC_v13:        return "v13";
+            case eRegNumPPC_GCC_v14:        return "v14";
+            case eRegNumPPC_GCC_v15:        return "v15";
+            case eRegNumPPC_GCC_v16:        return "v16";
+            case eRegNumPPC_GCC_v17:        return "v17";
+            case eRegNumPPC_GCC_v18:        return "v18";
+            case eRegNumPPC_GCC_v19:        return "v19";
+            case eRegNumPPC_GCC_v20:        return "v20";
+            case eRegNumPPC_GCC_v21:        return "v21";
+            case eRegNumPPC_GCC_v22:        return "v22";
+            case eRegNumPPC_GCC_v23:        return "v23";
+            case eRegNumPPC_GCC_v24:        return "v24";
+            case eRegNumPPC_GCC_v25:        return "v25";
+            case eRegNumPPC_GCC_v26:        return "v26";
+            case eRegNumPPC_GCC_v27:        return "v27";
+            case eRegNumPPC_GCC_v28:        return "v28";
+            case eRegNumPPC_GCC_v29:        return "v29";
+            case eRegNumPPC_GCC_v30:        return "v30";
+            case eRegNumPPC_GCC_v31:        return "v31";
+            case eRegNumPPC_GCC_vrsave:     return "vrsave";
+            case eRegNumPPC_GCC_vscr:       return "vscr";
+            case eRegNumPPC_GCC_spe_acc:    return "spe_acc";
+            case eRegNumPPC_GCC_spefscr:    return "spefscr";
+            case eRegNumPPC_GCC_sfp:        return "sfp";
+            default:
+                break;
+            }
+            break;
+
+        case eRegisterKindDWARF:
+            switch (reg_num)
+            {
+            case eRegNumPPC_DWARF_r0:       return "r0";
+            case eRegNumPPC_DWARF_r1:       return "r1";
+            case eRegNumPPC_DWARF_r2:       return "r2";
+            case eRegNumPPC_DWARF_r3:       return "r3";
+            case eRegNumPPC_DWARF_r4:       return "r4";
+            case eRegNumPPC_DWARF_r5:       return "r5";
+            case eRegNumPPC_DWARF_r6:       return "r6";
+            case eRegNumPPC_DWARF_r7:       return "r7";
+            case eRegNumPPC_DWARF_r8:       return "r8";
+            case eRegNumPPC_DWARF_r9:       return "r9";
+            case eRegNumPPC_DWARF_r10:      return "r10";
+            case eRegNumPPC_DWARF_r11:      return "r11";
+            case eRegNumPPC_DWARF_r12:      return "r12";
+            case eRegNumPPC_DWARF_r13:      return "r13";
+            case eRegNumPPC_DWARF_r14:      return "r14";
+            case eRegNumPPC_DWARF_r15:      return "r15";
+            case eRegNumPPC_DWARF_r16:      return "r16";
+            case eRegNumPPC_DWARF_r17:      return "r17";
+            case eRegNumPPC_DWARF_r18:      return "r18";
+            case eRegNumPPC_DWARF_r19:      return "r19";
+            case eRegNumPPC_DWARF_r20:      return "r20";
+            case eRegNumPPC_DWARF_r21:      return "r21";
+            case eRegNumPPC_DWARF_r22:      return "r22";
+            case eRegNumPPC_DWARF_r23:      return "r23";
+            case eRegNumPPC_DWARF_r24:      return "r24";
+            case eRegNumPPC_DWARF_r25:      return "r25";
+            case eRegNumPPC_DWARF_r26:      return "r26";
+            case eRegNumPPC_DWARF_r27:      return "r27";
+            case eRegNumPPC_DWARF_r28:      return "r28";
+            case eRegNumPPC_DWARF_r29:      return "r29";
+            case eRegNumPPC_DWARF_r30:      return "r30";
+            case eRegNumPPC_DWARF_r31:      return "r31";
+
+            case eRegNumPPC_DWARF_fr0:      return "fr0";
+            case eRegNumPPC_DWARF_fr1:      return "fr1";
+            case eRegNumPPC_DWARF_fr2:      return "fr2";
+            case eRegNumPPC_DWARF_fr3:      return "fr3";
+            case eRegNumPPC_DWARF_fr4:      return "fr4";
+            case eRegNumPPC_DWARF_fr5:      return "fr5";
+            case eRegNumPPC_DWARF_fr6:      return "fr6";
+            case eRegNumPPC_DWARF_fr7:      return "fr7";
+            case eRegNumPPC_DWARF_fr8:      return "fr8";
+            case eRegNumPPC_DWARF_fr9:      return "fr9";
+            case eRegNumPPC_DWARF_fr10:     return "fr10";
+            case eRegNumPPC_DWARF_fr11:     return "fr11";
+            case eRegNumPPC_DWARF_fr12:     return "fr12";
+            case eRegNumPPC_DWARF_fr13:     return "fr13";
+            case eRegNumPPC_DWARF_fr14:     return "fr14";
+            case eRegNumPPC_DWARF_fr15:     return "fr15";
+            case eRegNumPPC_DWARF_fr16:     return "fr16";
+            case eRegNumPPC_DWARF_fr17:     return "fr17";
+            case eRegNumPPC_DWARF_fr18:     return "fr18";
+            case eRegNumPPC_DWARF_fr19:     return "fr19";
+            case eRegNumPPC_DWARF_fr20:     return "fr20";
+            case eRegNumPPC_DWARF_fr21:     return "fr21";
+            case eRegNumPPC_DWARF_fr22:     return "fr22";
+            case eRegNumPPC_DWARF_fr23:     return "fr23";
+            case eRegNumPPC_DWARF_fr24:     return "fr24";
+            case eRegNumPPC_DWARF_fr25:     return "fr25";
+            case eRegNumPPC_DWARF_fr26:     return "fr26";
+            case eRegNumPPC_DWARF_fr27:     return "fr27";
+            case eRegNumPPC_DWARF_fr28:     return "fr28";
+            case eRegNumPPC_DWARF_fr29:     return "fr29";
+            case eRegNumPPC_DWARF_fr30:     return "fr30";
+            case eRegNumPPC_DWARF_fr31:     return "fr31";
+
+            case eRegNumPPC_DWARF_cr:       return "cr";
+            case eRegNumPPC_DWARF_fpscr:    return "fpscr";
+            case eRegNumPPC_DWARF_msr:      return "msr";
+            case eRegNumPPC_DWARF_vscr:     return "vscr";
+
+            case eRegNumPPC_DWARF_sr0:      return "sr0";
+            case eRegNumPPC_DWARF_sr1:      return "sr1";
+            case eRegNumPPC_DWARF_sr2:      return "sr2";
+            case eRegNumPPC_DWARF_sr3:      return "sr3";
+            case eRegNumPPC_DWARF_sr4:      return "sr4";
+            case eRegNumPPC_DWARF_sr5:      return "sr5";
+            case eRegNumPPC_DWARF_sr6:      return "sr6";
+            case eRegNumPPC_DWARF_sr7:      return "sr7";
+            case eRegNumPPC_DWARF_sr8:      return "sr8";
+            case eRegNumPPC_DWARF_sr9:      return "sr9";
+            case eRegNumPPC_DWARF_sr10:     return "sr10";
+            case eRegNumPPC_DWARF_sr11:     return "sr11";
+            case eRegNumPPC_DWARF_sr12:     return "sr12";
+            case eRegNumPPC_DWARF_sr13:     return "sr13";
+            case eRegNumPPC_DWARF_sr14:     return "sr14";
+            case eRegNumPPC_DWARF_sr15:     return "sr15";
+
+            case eRegNumPPC_DWARF_acc:      return "acc";
+            case eRegNumPPC_DWARF_mq:       return "mq";
+            case eRegNumPPC_DWARF_xer:      return "xer";
+            case eRegNumPPC_DWARF_rtcu:     return "rtcu";
+            case eRegNumPPC_DWARF_rtcl:     return "rtcl";
+
+            case eRegNumPPC_DWARF_lr:       return "lr";
+            case eRegNumPPC_DWARF_ctr:      return "ctr";
+
+            case eRegNumPPC_DWARF_dsisr:    return "dsisr";
+            case eRegNumPPC_DWARF_dar:      return "dar";
+            case eRegNumPPC_DWARF_dec:      return "dec";
+            case eRegNumPPC_DWARF_sdr1:     return "sdr1";
+            case eRegNumPPC_DWARF_srr0:     return "srr0";
+            case eRegNumPPC_DWARF_srr1:     return "srr1";
+
+            case eRegNumPPC_DWARF_vrsave:   return "vrsave";
+
+            case eRegNumPPC_DWARF_sprg0:    return "sprg0";
+            case eRegNumPPC_DWARF_sprg1:    return "sprg1";
+            case eRegNumPPC_DWARF_sprg2:    return "sprg2";
+            case eRegNumPPC_DWARF_sprg3:    return "sprg3";
+
+            case eRegNumPPC_DWARF_asr:      return "asr";
+            case eRegNumPPC_DWARF_ear:      return "ear";
+            case eRegNumPPC_DWARF_tb:       return "tb";
+            case eRegNumPPC_DWARF_tbu:      return "tbu";
+            case eRegNumPPC_DWARF_pvr:      return "pvr";
+
+            case eRegNumPPC_DWARF_spefscr:  return "spefscr";
+
+            case eRegNumPPC_DWARF_ibat0u:   return "ibat0u";
+            case eRegNumPPC_DWARF_ibat0l:   return "ibat0l";
+            case eRegNumPPC_DWARF_ibat1u:   return "ibat1u";
+            case eRegNumPPC_DWARF_ibat1l:   return "ibat1l";
+            case eRegNumPPC_DWARF_ibat2u:   return "ibat2u";
+            case eRegNumPPC_DWARF_ibat2l:   return "ibat2l";
+            case eRegNumPPC_DWARF_ibat3u:   return "ibat3u";
+            case eRegNumPPC_DWARF_ibat3l:   return "ibat3l";
+            case eRegNumPPC_DWARF_dbat0u:   return "dbat0u";
+            case eRegNumPPC_DWARF_dbat0l:   return "dbat0l";
+            case eRegNumPPC_DWARF_dbat1u:   return "dbat1u";
+            case eRegNumPPC_DWARF_dbat1l:   return "dbat1l";
+            case eRegNumPPC_DWARF_dbat2u:   return "dbat2u";
+            case eRegNumPPC_DWARF_dbat2l:   return "dbat2l";
+            case eRegNumPPC_DWARF_dbat3u:   return "dbat3u";
+            case eRegNumPPC_DWARF_dbat3l:   return "dbat3l";
+
+            case eRegNumPPC_DWARF_hid0:     return "hid0";
+            case eRegNumPPC_DWARF_hid1:     return "hid1";
+            case eRegNumPPC_DWARF_hid2:     return "hid2";
+            case eRegNumPPC_DWARF_hid3:     return "hid3";
+            case eRegNumPPC_DWARF_hid4:     return "hid4";
+            case eRegNumPPC_DWARF_hid5:     return "hid5";
+            case eRegNumPPC_DWARF_hid6:     return "hid6";
+            case eRegNumPPC_DWARF_hid7:     return "hid7";
+            case eRegNumPPC_DWARF_hid8:     return "hid8";
+            case eRegNumPPC_DWARF_hid9:     return "hid9";
+            case eRegNumPPC_DWARF_hid10:    return "hid10";
+            case eRegNumPPC_DWARF_hid11:    return "hid11";
+            case eRegNumPPC_DWARF_hid12:    return "hid12";
+            case eRegNumPPC_DWARF_hid13:    return "hid13";
+            case eRegNumPPC_DWARF_hid14:    return "hid14";
+            case eRegNumPPC_DWARF_hid15:    return "hid15";
+
+            case eRegNumPPC_DWARF_vr0:      return "vr0";
+            case eRegNumPPC_DWARF_vr1:      return "vr1";
+            case eRegNumPPC_DWARF_vr2:      return "vr2";
+            case eRegNumPPC_DWARF_vr3:      return "vr3";
+            case eRegNumPPC_DWARF_vr4:      return "vr4";
+            case eRegNumPPC_DWARF_vr5:      return "vr5";
+            case eRegNumPPC_DWARF_vr6:      return "vr6";
+            case eRegNumPPC_DWARF_vr7:      return "vr7";
+            case eRegNumPPC_DWARF_vr8:      return "vr8";
+            case eRegNumPPC_DWARF_vr9:      return "vr9";
+            case eRegNumPPC_DWARF_vr10:     return "vr10";
+            case eRegNumPPC_DWARF_vr11:     return "vr11";
+            case eRegNumPPC_DWARF_vr12:     return "vr12";
+            case eRegNumPPC_DWARF_vr13:     return "vr13";
+            case eRegNumPPC_DWARF_vr14:     return "vr14";
+            case eRegNumPPC_DWARF_vr15:     return "vr15";
+            case eRegNumPPC_DWARF_vr16:     return "vr16";
+            case eRegNumPPC_DWARF_vr17:     return "vr17";
+            case eRegNumPPC_DWARF_vr18:     return "vr18";
+            case eRegNumPPC_DWARF_vr19:     return "vr19";
+            case eRegNumPPC_DWARF_vr20:     return "vr20";
+            case eRegNumPPC_DWARF_vr21:     return "vr21";
+            case eRegNumPPC_DWARF_vr22:     return "vr22";
+            case eRegNumPPC_DWARF_vr23:     return "vr23";
+            case eRegNumPPC_DWARF_vr24:     return "vr24";
+            case eRegNumPPC_DWARF_vr25:     return "vr25";
+            case eRegNumPPC_DWARF_vr26:     return "vr26";
+            case eRegNumPPC_DWARF_vr27:     return "vr27";
+            case eRegNumPPC_DWARF_vr28:     return "vr28";
+            case eRegNumPPC_DWARF_vr29:     return "vr29";
+            case eRegNumPPC_DWARF_vr30:     return "vr30";
+            case eRegNumPPC_DWARF_vr31:     return "vr31";
+
+            case eRegNumPPC_DWARF_ev0:      return "ev0";
+            case eRegNumPPC_DWARF_ev1:      return "ev1";
+            case eRegNumPPC_DWARF_ev2:      return "ev2";
+            case eRegNumPPC_DWARF_ev3:      return "ev3";
+            case eRegNumPPC_DWARF_ev4:      return "ev4";
+            case eRegNumPPC_DWARF_ev5:      return "ev5";
+            case eRegNumPPC_DWARF_ev6:      return "ev6";
+            case eRegNumPPC_DWARF_ev7:      return "ev7";
+            case eRegNumPPC_DWARF_ev8:      return "ev8";
+            case eRegNumPPC_DWARF_ev9:      return "ev9";
+            case eRegNumPPC_DWARF_ev10:     return "ev10";
+            case eRegNumPPC_DWARF_ev11:     return "ev11";
+            case eRegNumPPC_DWARF_ev12:     return "ev12";
+            case eRegNumPPC_DWARF_ev13:     return "ev13";
+            case eRegNumPPC_DWARF_ev14:     return "ev14";
+            case eRegNumPPC_DWARF_ev15:     return "ev15";
+            case eRegNumPPC_DWARF_ev16:     return "ev16";
+            case eRegNumPPC_DWARF_ev17:     return "ev17";
+            case eRegNumPPC_DWARF_ev18:     return "ev18";
+            case eRegNumPPC_DWARF_ev19:     return "ev19";
+            case eRegNumPPC_DWARF_ev20:     return "ev20";
+            case eRegNumPPC_DWARF_ev21:     return "ev21";
+            case eRegNumPPC_DWARF_ev22:     return "ev22";
+            case eRegNumPPC_DWARF_ev23:     return "ev23";
+            case eRegNumPPC_DWARF_ev24:     return "ev24";
+            case eRegNumPPC_DWARF_ev25:     return "ev25";
+            case eRegNumPPC_DWARF_ev26:     return "ev26";
+            case eRegNumPPC_DWARF_ev27:     return "ev27";
+            case eRegNumPPC_DWARF_ev28:     return "ev28";
+            case eRegNumPPC_DWARF_ev29:     return "ev29";
+            case eRegNumPPC_DWARF_ev30:     return "ev30";
+            case eRegNumPPC_DWARF_ev31:     return "ev31";
+            default:
+                break;
+            }
+            break;
+        default:
+            break;
+        }
+
+    }
+    return NULL;
+}
+
+//----------------------------------------------------------------------
+// Returns true if this object contains a valid architecture, false
+// otherwise.
+//----------------------------------------------------------------------
+bool
+ArchSpec::IsValid() const
+{
+    return !(m_cpu == LLDB_INVALID_CPUTYPE);
+}
+
+//----------------------------------------------------------------------
+// Returns true if this architecture is 64 bit, otherwise 32 bit is
+// assumed and false is returned.
+//----------------------------------------------------------------------
+uint32_t
+ArchSpec::GetAddressByteSize() const
+{
+    if (GetCPUType() & CPU_ARCH_ABI64)
+        return 8;
+    return 4;
+}
+
+//----------------------------------------------------------------------
+// Returns the number of bytes that this object takes when an
+// instance exists in memory.
+//----------------------------------------------------------------------
+size_t
+ArchSpec::MemorySize() const
+{
+    return sizeof(ArchSpec);
+}
+
+bool
+ArchSpec::SetArchFromTargetTriple (const char *target_triple)
+{
+    if (target_triple)
+    {
+        const char *hyphen = strchr(target_triple, '-');
+        if (hyphen)
+        {
+            std::string arch_only (target_triple, hyphen);
+            return SetArch (arch_only.c_str());
+        }
+    }
+    return SetArch (target_triple);
+}
+
+//----------------------------------------------------------------------
+// Change the CPU type and subtype given an architecture name.
+//----------------------------------------------------------------------
+bool
+ArchSpec::SetArch(const char *arch_name)
+{
+    if (arch_name && arch_name[0] != '\0')
+    {
+        size_t i;
+        // Search for ARCH_NAME in our architecture definitions structure
+        for (i=0; i<k_num_arch_defs; ++i)
+        {
+            if (strcasecmp(arch_name, g_arch_defs[i].name) == 0)
+            {
+                // we found a match
+                m_cpu = g_arch_defs[i].cpu;
+                m_sub = g_arch_defs[i].sub;
+                return true;
+            }
+        }
+
+
+        const char *str = arch_name;
+        char *end = NULL;
+        // Check for a numeric cpu followed by an optional '.' and numeric subtype.
+        // This allows for support of new cpu type/subtypes without having to have
+        // a recompiled debug core.
+        // Examples:
+        //  "12.6" is armv6
+        //  "0x0000000c.0x00000006" is also armv6
+        m_cpu = strtoul(str, &end, 0);
+        if (str != end)
+        {
+            if (*end == '.')
+            {
+                // We have a cputype.cpusubtype format
+                str = end + 1;
+                if (*str != '\0')
+                {
+                    m_sub = strtoul(str, &end, 0);
+                    if (*end == '\0')
+                    {
+                        // We consumed the entire string and got a cpu type and subtype
+                        return true;
+                    }
+                }
+            }
+
+            // If we reach this point we have a valid cpu type, but no cpu subtype.
+            // Search for the first matching cpu type and use the corresponding cpu
+            // subtype. This setting should typically be the _ALL variant and should
+            // appear first in the list for each cpu type in the g_arch_defs
+            // structure.
+            for (i=0; i<k_num_arch_defs; ++i)
+            {
+                if (m_cpu == g_arch_defs[i].cpu)
+                {
+                    m_sub = g_arch_defs[i].sub;
+                    return true;
+                }
+            }
+
+            // Default the cpu subtype to zero when we don't have a matching
+            // cpu type in our architecture defs structure (g_arch_defs).
+            m_sub = 0;
+            return true;
+
+        }
+    }
+    m_cpu = LLDB_INVALID_CPUTYPE;
+    m_sub = 0;
+    return false;
+}
+
+//----------------------------------------------------------------------
+// CPU type and subtype set accessor.
+//----------------------------------------------------------------------
+void
+ArchSpec::SetArch (uint32_t cpu_type, uint32_t cpu_subtype)
+{
+    m_cpu = cpu_type;
+    m_sub = cpu_subtype;
+}
+
+//----------------------------------------------------------------------
+// CPU type set accessor.
+//----------------------------------------------------------------------
+void
+ArchSpec::SetCPUType (uint32_t cpu)
+{
+    m_cpu = cpu;
+}
+
+//----------------------------------------------------------------------
+// CPU subtype set accessor.
+//----------------------------------------------------------------------
+void
+ArchSpec::SetCPUSubtype (uint32_t subtype)
+{
+    m_sub = subtype;
+}
+
+ByteOrder
+ArchSpec::GetDefaultEndian () const
+{
+    switch (m_cpu)
+    {
+    case CPU_TYPE_POWERPC:
+    case CPU_TYPE_POWERPC64:
+        return eByteOrderBig;
+
+    case CPU_TYPE_ARM:
+    case CPU_TYPE_I386:
+    case CPU_TYPE_X86_64:
+        return eByteOrderLittle;
+
+    default:
+        break;
+    }
+    return eByteOrderInvalid;
+}
+
+//----------------------------------------------------------------------
+// Equal operator
+//----------------------------------------------------------------------
+bool
+lldb_private::operator== (const ArchSpec& lhs, const ArchSpec& rhs)
+{
+    uint32_t lhs_cpu = lhs.GetCPUType();
+    uint32_t rhs_cpu = rhs.GetCPUType();
+
+    if (lhs_cpu == CPU_TYPE_ANY || rhs_cpu == CPU_TYPE_ANY)
+        return true;
+
+    else if (lhs_cpu == rhs_cpu)
+    {
+        uint32_t lhs_subtype = lhs.GetCPUSubtype();
+        uint32_t rhs_subtype = rhs.GetCPUSubtype();
+        if (lhs_subtype == CPU_TYPE_ANY || rhs_subtype == CPU_TYPE_ANY)
+            return true;
+        return lhs_subtype == rhs_subtype;
+    }
+    return false;
+}
+
+
+//----------------------------------------------------------------------
+// Not Equal operator
+//----------------------------------------------------------------------
+bool
+lldb_private::operator!= (const ArchSpec& lhs, const ArchSpec& rhs)
+{
+    return !(lhs == rhs);
+}
+
+//----------------------------------------------------------------------
+// Less than operator
+//----------------------------------------------------------------------
+bool
+lldb_private::operator<(const ArchSpec& lhs, const ArchSpec& rhs)
+{
+    uint32_t lhs_cpu = lhs.GetCPUType();
+    uint32_t rhs_cpu = rhs.GetCPUType();
+
+    if (lhs_cpu == rhs_cpu)
+        return lhs.GetCPUSubtype() < rhs.GetCPUSubtype();
+
+    return lhs_cpu < rhs_cpu;
+}
+
diff --git a/source/Core/Args.cpp b/source/Core/Args.cpp
new file mode 100644
index 0000000..7cb1375
--- /dev/null
+++ b/source/Core/Args.cpp
@@ -0,0 +1,1179 @@
+//===-- Args.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 <getopt.h>
+#include <histedit.h>
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+namespace lldb_private {
+
+class Tokenizer
+{
+public:
+    Tokenizer (const char *separator_chars = NULL) :
+        m_tokenizer(NULL)
+    {
+        m_tokenizer = ::tok_init (separator_chars);
+    }
+
+    ~Tokenizer ()
+    {
+        if (m_tokenizer)
+        {
+            ::tok_end (m_tokenizer);
+            m_tokenizer = NULL;
+        }
+    }
+
+    void
+    Reset ()
+    {
+        assert (m_tokenizer);
+        ::tok_reset (m_tokenizer);
+    }
+
+    int
+    TokenizeLineInfo (const ::LineInfo *line_info)
+    {
+        assert (m_tokenizer);
+        return ::tok_line (m_tokenizer,
+                           line_info,
+                           &m_argc,
+                           &m_argv,
+                           &m_cursor_arg_index,
+                           &m_cursor_arg_offset);
+    }
+
+    int
+    TokenizeCString (const char *cstr)
+    {
+        assert (m_tokenizer);
+        m_cursor_arg_index = -1;
+        m_cursor_arg_offset = -1;
+        return ::tok_str (m_tokenizer,
+                          cstr,
+                          &m_argc,
+                          &m_argv);
+    }
+
+
+    int
+    GetArgCount () const
+    {
+        return m_argc;
+    }
+
+    const char **
+    GetArgVector () const
+    {
+        return m_argv;
+    }
+
+    int
+    GetCursoreArgIndex () const
+    {
+        return m_cursor_arg_index;
+    }
+
+    int
+    GetCursoreArgOffset () const
+    {
+        return m_cursor_arg_offset;
+    }
+
+
+protected:
+    struct tokenizer* m_tokenizer;
+    const char **m_argv;
+    int m_argc;
+    int m_cursor_arg_index;
+    int m_cursor_arg_offset;
+};
+
+} // namespace lldb_private
+
+using namespace lldb;
+using namespace lldb_private;
+
+static const char *k_space_characters = "\t\n\v\f\r ";
+static const char *k_space_characters_with_slash = "\t\n\v\f\r \\";
+
+
+//----------------------------------------------------------------------
+// Args constructor
+//----------------------------------------------------------------------
+Args::Args (const char *command) :
+    m_args(),
+    m_argv()
+{
+    SetCommandString (command);
+}
+
+
+Args::Args (const char *command, size_t len) :
+    m_args(),
+    m_argv()
+{
+    SetCommandString (command, len);
+}
+
+
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+Args::~Args ()
+{
+}
+
+void
+Args::Dump (Stream *s)
+{
+//    int argc = GetArgumentCount();
+//
+//    arg_sstr_collection::const_iterator pos, begin = m_args.begin(), end = m_args.end();
+//    for (pos = m_args.begin(); pos != end; ++pos)
+//    {
+//        s->Indent();
+//        s->Printf("args[%zu]=%s\n", std::distance(begin, pos), pos->c_str());
+//    }
+//    s->EOL();
+    const int argc = m_argv.size();
+    for (int i=0; i<argc; ++i)
+    {
+        s->Indent();
+        const char *arg_cstr = m_argv[i];
+        if (arg_cstr)
+            s->Printf("argv[%i]=\"%s\"\n", i, arg_cstr);
+        else
+            s->Printf("argv[%i]=NULL\n", i);
+    }
+    s->EOL();
+}
+
+bool
+Args::GetCommandString (std::string &command)
+{
+    command.clear();
+    int argc = GetArgumentCount();
+    for (int i=0; i<argc; ++i)
+    {
+        if (i > 0)
+            command += ' ';
+        command += m_argv[i];
+    }
+    return argc > 0;
+}
+
+void
+Args::SetCommandString (const char *command, size_t len)
+{
+    // Use std::string to make sure we get a NULL terminated string we can use
+    // as "command" could point to a string within a large string....
+    std::string null_terminated_command(command, len);
+    SetCommandString(null_terminated_command.c_str());
+}
+
+void
+Args::SetCommandString (const char *command)
+{
+    m_args.clear();
+    m_argv.clear();
+    if (command && command[0])
+    {
+        const char *arg_start;
+        const char *next_arg_start;
+        for (arg_start = command, next_arg_start = NULL;
+             arg_start && arg_start[0];
+             arg_start = next_arg_start, next_arg_start = NULL)
+        {
+            // Skip any leading space characters
+            arg_start = ::strspn (arg_start, k_space_characters) + arg_start;
+
+            // If there were only space characters to the end of the line, then
+            // we're done.
+            if (*arg_start == '\0')
+                break;
+
+            std::string arg;
+            const char *arg_end = NULL;
+
+            switch (*arg_start)
+            {
+            case '\'':
+            case '"':
+            case '`':
+                {
+                    // Look for either a quote character, or the backslash
+                    // character
+                    const char quote_char = *arg_start;
+                    char find_chars[3] = { quote_char, '\\' , '\0'};
+                    bool is_backtick = (quote_char == '`');
+                    if (quote_char == '"' || quote_char == '`')
+                        m_args_quote_char.push_back(quote_char);
+                    else
+                        m_args_quote_char.push_back('\0');
+
+                    while (*arg_start != '\0')
+                    {
+                        arg_end = ::strcspn (arg_start + 1, find_chars) + arg_start + 1;
+
+                        if (*arg_end == '\0')
+                        {
+                            arg.append (arg_start);
+                            break;
+                        }
+
+                        // Watch out for quote characters prefixed with '\'
+                        if (*arg_end == '\\')
+                        {
+                            if (arg_end[1] == quote_char)
+                            {
+                                // The character following the '\' is our quote
+                                // character so strip the backslash character
+                                arg.append (arg_start, arg_end);
+                            }
+                            else
+                            {
+                                // The character following the '\' is NOT our
+                                // quote character, so include the backslash
+                                // and continue
+                                arg.append (arg_start, arg_end + 1);
+                            }
+                            arg_start = arg_end + 1;
+                            continue;
+                        }
+                        else
+                        {
+                            arg.append (arg_start, arg_end + 1);
+                            next_arg_start = arg_end + 1;
+                            break;
+                        }
+                    }
+
+                    // Skip single and double quotes, but leave backtick quotes
+                    if (!is_backtick)
+                    {
+                        char first_c = arg[0];
+                        arg.erase(0,1);
+                        // Only erase the last character if it is the same as the first.
+                        // Otherwise, we're parsing an incomplete command line, and we
+                        // would be stripping off the last character of that string.
+                        if (arg[arg.size() - 1] == first_c)
+                            arg.erase(arg.size() - 1, 1);
+                    }
+                }
+                break;
+            default:
+                {
+                    m_args_quote_char.push_back('\0');
+                    // Look for the next non-escaped space character
+                    while (*arg_start != '\0')
+                    {
+                        arg_end = ::strcspn (arg_start, k_space_characters_with_slash) + arg_start;
+
+                        if (arg_end == NULL)
+                        {
+                            arg.append(arg_start);
+                            break;
+                        }
+
+                        if (*arg_end == '\\')
+                        {
+                            // Append up to the '\' char
+                            arg.append (arg_start, arg_end);
+
+                            if (arg_end[1] == '\0')
+                                break;
+
+                            // Append the character following the '\' if it isn't
+                            // the end of the string
+                            arg.append (1, arg_end[1]);
+                            arg_start = arg_end + 2;
+                            continue;
+                        }
+                        else
+                        {
+                            arg.append (arg_start, arg_end);
+                            next_arg_start = arg_end;
+                            break;
+                        }
+                    }
+                }
+                break;
+            }
+
+            m_args.push_back(arg);
+        }
+    }
+    UpdateArgvFromArgs();
+}
+
+void
+Args::UpdateArgsAfterOptionParsing()
+{
+    // Now m_argv might be out of date with m_args, so we need to fix that
+    arg_cstr_collection::const_iterator argv_pos, argv_end = m_argv.end();
+    arg_sstr_collection::iterator args_pos;
+    arg_quote_char_collection::iterator quotes_pos;
+
+    for (argv_pos = m_argv.begin(), args_pos = m_args.begin(), quotes_pos = m_args_quote_char.begin();
+         argv_pos != argv_end && args_pos != m_args.end();
+         ++argv_pos)
+    {
+        const char *argv_cstr = *argv_pos;
+        if (argv_cstr == NULL)
+            break;
+
+        while (args_pos != m_args.end())
+        {
+            const char *args_cstr = args_pos->c_str();
+            if (args_cstr == argv_cstr)
+            {
+                // We found the argument that matches the C string in the
+                // vector, so we can now look for the next one
+                ++args_pos;
+                ++quotes_pos;
+                break;
+            }
+            else
+            {
+                quotes_pos = m_args_quote_char.erase (quotes_pos);
+                args_pos = m_args.erase (args_pos);
+            }
+        }
+    }
+
+    if (args_pos != m_args.end())
+        m_args.erase (args_pos, m_args.end());
+
+    if (quotes_pos != m_args_quote_char.end())
+        m_args_quote_char.erase (quotes_pos, m_args_quote_char.end());
+}
+
+void
+Args::UpdateArgvFromArgs()
+{
+    m_argv.clear();
+    arg_sstr_collection::const_iterator pos, end = m_args.end();
+    for (pos = m_args.begin(); pos != end; ++pos)
+        m_argv.push_back(pos->c_str());
+    m_argv.push_back(NULL);
+}
+
+size_t
+Args::GetArgumentCount() const
+{
+    if (m_argv.empty())
+        return 0;
+    return m_argv.size() - 1;
+}
+
+const char *
+Args::GetArgumentAtIndex (size_t idx) const
+{
+    if (idx < m_argv.size())
+        return m_argv[idx];
+    return NULL;
+}
+
+char
+Args::GetArgumentQuoteCharAtIndex (size_t idx) const
+{
+    if (idx < m_args_quote_char.size())
+        return m_args_quote_char[idx];
+    return '\0';
+}
+
+char **
+Args::GetArgumentVector()
+{
+    if (!m_argv.empty())
+        return (char **)&m_argv[0];
+    return NULL;
+}
+
+const char **
+Args::GetConstArgumentVector() const
+{
+    if (!m_argv.empty())
+        return (const char **)&m_argv[0];
+    return NULL;
+}
+
+void
+Args::Shift ()
+{
+    // Don't pop the last NULL terminator from the argv array
+    if (m_argv.size() > 1)
+    {
+        m_argv.erase(m_argv.begin());
+        m_args.pop_front();
+        m_args_quote_char.erase(m_args_quote_char.begin());
+    }
+}
+
+const char *
+Args::Unshift (const char *arg_cstr, char quote_char)
+{
+    m_args.push_front(arg_cstr);
+    m_argv.insert(m_argv.begin(), m_args.front().c_str());
+    m_args_quote_char.insert(m_args_quote_char.begin(), quote_char);
+    return GetArgumentAtIndex (0);
+}
+
+void
+Args::AppendArguments (const Args &rhs)
+{
+    const size_t rhs_argc = rhs.GetArgumentCount();
+    for (size_t i=0; i<rhs_argc; ++i)
+        AppendArgument(rhs.GetArgumentAtIndex(i));
+}
+
+const char *
+Args::AppendArgument (const char *arg_cstr, char quote_char)
+{
+    return InsertArgumentAtIndex (GetArgumentCount(), arg_cstr, quote_char);
+}
+
+const char *
+Args::InsertArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char)
+{
+    // Since we are using a std::list to hold onto the copied C string and
+    // we don't have direct access to the elements, we have to iterate to
+    // find the value.
+    arg_sstr_collection::iterator pos, end = m_args.end();
+    size_t i = idx;
+    for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
+        --i;
+
+    pos = m_args.insert(pos, arg_cstr);
+    
+
+    m_args_quote_char.insert(m_args_quote_char.begin() + idx, quote_char);
+    
+    UpdateArgvFromArgs();
+    return GetArgumentAtIndex(idx);
+}
+
+const char *
+Args::ReplaceArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char)
+{
+    // Since we are using a std::list to hold onto the copied C string and
+    // we don't have direct access to the elements, we have to iterate to
+    // find the value.
+    arg_sstr_collection::iterator pos, end = m_args.end();
+    size_t i = idx;
+    for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
+        --i;
+
+    if (pos != end)
+    {
+        pos->assign(arg_cstr);
+        assert(idx < m_argv.size() - 1);
+        m_argv[idx] = pos->c_str();
+        m_args_quote_char[idx] = quote_char;
+        return GetArgumentAtIndex(idx);
+    }
+    return NULL;
+}
+
+void
+Args::DeleteArgumentAtIndex (size_t idx)
+{
+    // Since we are using a std::list to hold onto the copied C string and
+    // we don't have direct access to the elements, we have to iterate to
+    // find the value.
+    arg_sstr_collection::iterator pos, end = m_args.end();
+    size_t i = idx;
+    for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
+        --i;
+
+    if (pos != end)
+    {
+        m_args.erase (pos);
+        assert(idx < m_argv.size() - 1);
+        m_argv.erase(m_argv.begin() + idx);
+        m_args_quote_char.erase(m_args_quote_char.begin() + idx);
+    }
+}
+
+void
+Args::SetArguments (int argc, const char **argv)
+{
+    // m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is
+    // no need to clear it here.
+    m_args.clear();
+    m_args_quote_char.clear();
+
+    // Make a copy of the arguments in our internal buffer
+    size_t i;
+    // First copy each string
+    for (i=0; i<argc; ++i)
+    {
+        m_args.push_back (argv[i]);
+        if ((argv[i][0] == '"') || (argv[i][0] == '`'))
+            m_args_quote_char.push_back (argv[i][0]);
+        else
+            m_args_quote_char.push_back ('\0');
+    }
+
+    UpdateArgvFromArgs();
+}
+
+
+Error
+Args::ParseOptions (Options &options)
+{
+    StreamString sstr;
+    int i;
+    Error error;
+    struct option *long_options = options.GetLongOptions();
+    if (long_options == NULL)
+    {
+        error.SetErrorStringWithFormat("Invalid long options.\n");
+        return error;
+    }
+
+    for (i=0; long_options[i].name != NULL; ++i)
+    {
+        if (long_options[i].flag == NULL)
+        {
+            sstr << (char)long_options[i].val;
+            switch (long_options[i].has_arg)
+            {
+            default:
+            case no_argument:                       break;
+            case required_argument: sstr << ':';    break;
+            case optional_argument: sstr << "::";   break;
+            }
+        }
+    }
+    optreset = 1;
+    optind = 1;
+    int val;
+    while (1)
+    {
+        int long_options_index = -1;
+        val = ::getopt_long(GetArgumentCount(), GetArgumentVector(), sstr.GetData(), long_options,
+                            &long_options_index);
+        if (val == -1)
+            break;
+
+        // Did we get an error?
+        if (val == '?')
+        {
+            error.SetErrorStringWithFormat("Unknown or ambiguous option.\n");
+            break;
+        }
+        // The option auto-set itself
+        if (val == 0)
+            continue;
+
+        ((Options *) &options)->OptionSeen (val);
+
+        // Lookup the long option index
+        if (long_options_index == -1)
+        {
+            for (int i=0;
+                 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
+                 ++i)
+            {
+                if (long_options[i].val == val)
+                {
+                    long_options_index = i;
+                    break;
+                }
+            }
+        }
+        // Call the callback with the option
+        if (long_options_index >= 0)
+        {
+            error = options.SetOptionValue(long_options_index,
+                                           long_options[long_options_index].has_arg == no_argument ? NULL : optarg);
+        }
+        else
+        {
+            error.SetErrorStringWithFormat("Invalid option with value '%i'.\n", val);
+        }
+        if (error.Fail())
+            break;
+    }
+
+    // Update our ARGV now that get options has consumed all the options
+    m_argv.erase(m_argv.begin(), m_argv.begin() + optind);
+    UpdateArgsAfterOptionParsing ();
+    return error;
+}
+
+void
+Args::Clear ()
+{
+    m_args.clear ();
+    m_argv.clear ();
+    m_args_quote_char.clear();
+}
+
+int32_t
+Args::StringToSInt32 (const char *s, int32_t fail_value, int base, bool *success_ptr)
+{
+    if (s && s[0])
+    {
+        char *end = NULL;
+        int32_t uval = ::strtol (s, &end, base);
+        if (*end == '\0')
+        {
+            if (success_ptr) *success_ptr = true;
+            return uval; // All characters were used, return the result
+        }
+    }
+    if (success_ptr) *success_ptr = false;
+    return fail_value;
+}
+
+uint32_t
+Args::StringToUInt32 (const char *s, uint32_t fail_value, int base, bool *success_ptr)
+{
+    if (s && s[0])
+    {
+        char *end = NULL;
+        uint32_t uval = ::strtoul (s, &end, base);
+        if (*end == '\0')
+        {
+            if (success_ptr) *success_ptr = true;
+            return uval; // All characters were used, return the result
+        }
+    }
+    if (success_ptr) *success_ptr = false;
+    return fail_value;
+}
+
+
+int64_t
+Args::StringToSInt64 (const char *s, int64_t fail_value, int base, bool *success_ptr)
+{
+    if (s && s[0])
+    {
+        char *end = NULL;
+        int64_t uval = ::strtoll (s, &end, base);
+        if (*end == '\0')
+        {
+            if (success_ptr) *success_ptr = true;
+            return uval; // All characters were used, return the result
+        }
+    }
+    if (success_ptr) *success_ptr = false;
+    return fail_value;
+}
+
+uint64_t
+Args::StringToUInt64 (const char *s, uint64_t fail_value, int base, bool *success_ptr)
+{
+    if (s && s[0])
+    {
+        char *end = NULL;
+        uint64_t uval = ::strtoull (s, &end, base);
+        if (*end == '\0')
+        {
+            if (success_ptr) *success_ptr = true;
+            return uval; // All characters were used, return the result
+        }
+    }
+    if (success_ptr) *success_ptr = false;
+    return fail_value;
+}
+
+lldb::addr_t
+Args::StringToAddress (const char *s, lldb::addr_t fail_value, bool *success_ptr)
+{
+    if (s && s[0])
+    {
+        char *end = NULL;
+        lldb::addr_t addr = ::strtoull (s, &end, 0);
+        if (*end == '\0')
+        {
+            if (success_ptr) *success_ptr = true;
+            return addr; // All characters were used, return the result
+        }
+        // Try base 16 with no prefix...
+        addr = ::strtoull (s, &end, 16);
+        if (*end == '\0')
+        {
+            if (success_ptr) *success_ptr = true;
+            return addr; // All characters were used, return the result
+        }
+    }
+    if (success_ptr) *success_ptr = false;
+    return fail_value;
+}
+
+bool
+Args::StringToBoolean (const char *s, bool fail_value, bool *success_ptr)
+{
+    if (s && s[0])
+    {
+        if (::strcasecmp (s, "false") == 0 ||
+            ::strcasecmp (s, "off") == 0 ||
+            ::strcasecmp (s, "no") == 0 ||
+                ::strcmp (s, "0") == 0)
+        {
+            if (success_ptr)
+                *success_ptr = true;
+            return false;
+        }
+        else
+        if (::strcasecmp (s, "true") == 0 ||
+            ::strcasecmp (s, "on") == 0 ||
+            ::strcasecmp (s, "yes") == 0 ||
+                ::strcmp (s, "1") == 0)
+        {
+            if (success_ptr) *success_ptr = true;
+            return true;
+        }
+    }
+    if (success_ptr) *success_ptr = false;
+    return fail_value;
+}
+
+int32_t
+Args::StringToOptionEnum (const char *s, lldb::OptionEnumValueElement *enum_values, int32_t fail_value, bool *success_ptr)
+{    
+    if (enum_values && s && s[0])
+    {
+        for (int i = 0; enum_values[i].string_value != NULL ; i++) 
+        {
+            if (strstr(enum_values[i].string_value, s) == enum_values[i].string_value)
+            {
+                if (success_ptr) *success_ptr = true;
+                return enum_values[i].value;
+            }
+        }
+    }
+    if (success_ptr) *success_ptr = false;
+    
+    return fail_value;
+}
+
+ScriptLanguage
+Args::StringToScriptLanguage (const char *s, ScriptLanguage fail_value, bool *success_ptr)
+{
+    if (s && s[0])
+    {
+        if ((::strcasecmp (s, "python") == 0) ||
+            (::strcasecmp (s, "default") == 0 && eScriptLanguagePython == eScriptLanguageDefault))
+        {
+            if (success_ptr) *success_ptr = true;
+            return eScriptLanguagePython;
+        }
+        if (::strcasecmp (s, "none"))
+        {
+            if (success_ptr) *success_ptr = true;
+            return eScriptLanguageNone;
+        }
+    }
+    if (success_ptr) *success_ptr = false;
+    return fail_value;
+}
+
+Error
+Args::StringToFormat
+(
+    const char *s,
+    lldb::Format &format
+)
+{
+    format = eFormatInvalid;
+    Error error;
+
+    if (s && s[0])
+    {
+        switch (s[0])
+        {
+        case 'y': format = eFormatBytes;            break;
+        case 'Y': format = eFormatBytesWithASCII;   break;
+        case 'b': format = eFormatBinary;           break;
+        case 'B': format = eFormatBoolean;          break;
+        case 'c': format = eFormatChar;             break;
+        case 'C': format = eFormatCharPrintable;    break;
+        case 'o': format = eFormatOctal;            break;
+        case 'i':
+        case 'd': format = eFormatDecimal;          break;
+        case 'u': format = eFormatUnsigned;         break;
+        case 'x': format = eFormatHex;              break;
+        case 'f':
+        case 'e':
+        case 'g': format = eFormatFloat;            break;
+        case 'p': format = eFormatPointer;          break;
+        case 's': format = eFormatCString;          break;
+        default:
+            error.SetErrorStringWithFormat("Invalid format character '%c'. Valid values are:\n"
+                                            "  b - binary\n"
+                                            "  B - boolean\n"
+                                            "  c - char\n"
+                                            "  C - printable char\n"
+                                            "  d - signed decimal\n"
+                                            "  e - float\n"
+                                            "  f - float\n"
+                                            "  g - float\n"
+                                            "  i - signed decimal\n"
+                                            "  o - octal\n"
+                                            "  s - c-string\n"
+                                            "  u - unsigned decimal\n"
+                                            "  x - hex\n"
+                                            "  y - bytes\n"
+                                            "  Y - bytes with ASCII\n", s[0]);
+            break;
+        }
+
+        if (error.Fail())
+            return error;
+    }
+    else
+    {
+        error.SetErrorStringWithFormat("%s option string.\n", s ? "empty" : "invalid");
+    }
+    return error;
+}
+
+void
+Args::LongestCommonPrefix (std::string &common_prefix)
+{
+    arg_sstr_collection::iterator pos, end = m_args.end();
+    pos = m_args.begin();
+    if (pos == end)
+        common_prefix.clear();
+    else
+        common_prefix = (*pos);
+
+    for (++pos; pos != end; ++pos)
+    {
+        int new_size = (*pos).size();
+
+        // First trim common_prefix if it is longer than the current element:
+        if (common_prefix.size() > new_size)
+            common_prefix.erase (new_size);
+
+        // Then trim it at the first disparity:
+
+        for (int i = 0; i < common_prefix.size(); i++)
+        {
+            if ((*pos)[i]  != common_prefix[i])
+            {
+                common_prefix.erase(i);
+                break;
+            }
+        }
+
+        // If we've emptied the common prefix, we're done.
+        if (common_prefix.empty())
+            break;
+    }
+}
+
+void
+Args::ParseAliasOptions
+(
+    Options &options,
+    CommandReturnObject &result,
+    OptionArgVector *option_arg_vector
+)
+{
+    StreamString sstr;
+    int i;
+    struct option *long_options = options.GetLongOptions();
+
+    if (long_options == NULL)
+    {
+        result.AppendError ("invalid long options");
+        result.SetStatus (eReturnStatusFailed);
+        return;
+    }
+
+    for (i = 0; long_options[i].name != NULL; ++i)
+    {
+        if (long_options[i].flag == NULL)
+        {
+            sstr << (char) long_options[i].val;
+            switch (long_options[i].has_arg)
+            {
+                default:
+                case no_argument:
+                    break;
+                case required_argument:
+                    sstr << ":";
+                    break;
+                case optional_argument:
+                    sstr << "::";
+                    break;
+            }
+        }
+    }
+
+    optreset = 1;
+    optind = 1;
+    int val;
+    while (1)
+    {
+        int long_options_index = -1;
+        val = ::getopt_long (GetArgumentCount(), GetArgumentVector(), sstr.GetData(), long_options,
+                             &long_options_index);
+
+        if (val == -1)
+            break;
+
+        if (val == '?')
+        {
+            result.AppendError ("unknown or ambiguous option");
+            result.SetStatus (eReturnStatusFailed);
+            break;
+        }
+
+        if (val == 0)
+            continue;
+
+        ((Options *) &options)->OptionSeen (val);
+
+        // Look up the long option index
+        if (long_options_index == -1)
+        {
+            for (int j = 0;
+                 long_options[j].name || long_options[j].has_arg || long_options[j].flag || long_options[j].val;
+                 ++j)
+            {
+                if (long_options[j].val == val)
+                {
+                    long_options_index = j;
+                    break;
+                }
+            }
+        }
+
+        // See if the option takes an argument, and see if one was supplied.
+        if (long_options_index >= 0)
+        {
+            StreamString option_str;
+            option_str.Printf ("-%c", (char) val);
+
+            switch (long_options[long_options_index].has_arg)
+            {
+            case no_argument:
+                option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()), "<no-argument>"));
+                break;
+            case required_argument:
+                if (optarg != NULL)
+                {
+                    option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
+                                                                 std::string (optarg)));
+                    result.SetStatus (eReturnStatusSuccessFinishNoResult);
+                }
+                else
+                {
+                    result.AppendErrorWithFormat ("Option '%s' is missing argument specifier.\n",
+                                                 option_str.GetData());
+                    result.SetStatus (eReturnStatusFailed);
+                }
+                break;
+            case optional_argument:
+                if (optarg != NULL)
+                {
+                    option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
+                                                                 std::string (optarg)));
+                    result.SetStatus (eReturnStatusSuccessFinishNoResult);
+                }
+                else
+                {
+                    option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
+                                                                 "<no-argument>"));
+                    result.SetStatus (eReturnStatusSuccessFinishNoResult);
+                }
+                break;
+            default:
+                result.AppendErrorWithFormat
+                ("error with options table; invalid value in has_arg field for option '%c'.\n",
+                 (char) val);
+                result.SetStatus (eReturnStatusFailed);
+                break;
+            }
+        }
+        else
+        {
+            result.AppendErrorWithFormat ("Invalid option with value '%c'.\n", (char) val);
+            result.SetStatus (eReturnStatusFailed);
+        }
+        if (!result.Succeeded())
+            break;
+    }
+}
+
+void
+Args::ParseArgsForCompletion
+(
+    Options &options,
+    OptionElementVector &option_element_vector
+)
+{
+    StreamString sstr;
+    int i;
+    struct option *long_options = options.GetLongOptions();
+    option_element_vector.clear();
+
+    if (long_options == NULL)
+    {
+        return;
+    }
+
+    // Leading : tells getopt to return a : for a missing option argument AND
+    // to suppress error messages.
+
+    sstr << ":";
+    for (i = 0; long_options[i].name != NULL; ++i)
+    {
+        if (long_options[i].flag == NULL)
+        {
+            sstr << (char) long_options[i].val;
+            switch (long_options[i].has_arg)
+            {
+                default:
+                case no_argument:
+                    break;
+                case required_argument:
+                    sstr << ":";
+                    break;
+                case optional_argument:
+                    sstr << "::";
+                    break;
+            }
+        }
+    }
+
+    optreset = 1;
+    optind = 1;
+    opterr = 0;
+
+    int val;
+    const OptionDefinition *opt_defs = options.GetDefinitions();
+
+    // Fooey... getopt_long permutes the GetArgumentVector for no apparent reason.
+    // So we have to build another Arg and pass that to getopt_long so it doesn't
+    // screw up the one we have.
+
+    std::vector<const char *> dummy_vec(GetArgumentVector(), GetArgumentVector() + GetArgumentCount() + 1);
+
+    while (1)
+    {
+        bool missing_argument = false;
+        int parse_start = optind;
+        int long_options_index = -1;
+        val = ::getopt_long (dummy_vec.size() - 1,(char *const *) dummy_vec.data(), sstr.GetData(), long_options,
+                             &long_options_index);
+
+        if (val == -1)
+            break;
+
+        else if (val == '?')
+        {
+            option_element_vector.push_back (OptionArgElement (-1, parse_start, -1));
+            continue;
+        }
+        else if (val == 0)
+        {
+            continue;
+        }
+        else if (val == ':')
+        {
+            // This is a missing argument.
+            val = optopt;
+            missing_argument = true;
+        }
+
+        ((Options *) &options)->OptionSeen (val);
+
+        // Look up the long option index
+        if (long_options_index == -1)
+        {
+            for (int j = 0;
+                 long_options[j].name || long_options[j].has_arg || long_options[j].flag || long_options[j].val;
+                 ++j)
+            {
+                if (long_options[j].val == val)
+                {
+                    long_options_index = j;
+                    break;
+                }
+            }
+        }
+
+        // See if the option takes an argument, and see if one was supplied.
+        if (long_options_index >= 0)
+        {
+            int opt_defs_index = -1;
+            for (int i = 0; ; i++)
+            {
+                if (opt_defs[i].short_option == 0)
+                    break;
+                else if (opt_defs[i].short_option == val)
+                {
+                    opt_defs_index = i;
+                    break;
+                }
+            }
+
+            switch (long_options[long_options_index].has_arg)
+            {
+            case no_argument:
+                option_element_vector.push_back (OptionArgElement (opt_defs_index, parse_start, 0));
+                break;
+            case required_argument:
+                if (optarg != NULL)
+                {
+                    int arg_index;
+                    if (missing_argument)
+                        arg_index = -1;
+                    else
+                        arg_index = parse_start + 1;
+
+                    option_element_vector.push_back (OptionArgElement (opt_defs_index, parse_start, arg_index));
+                }
+                else
+                {
+                    option_element_vector.push_back (OptionArgElement (opt_defs_index, parse_start, -1));
+                }
+                break;
+            case optional_argument:
+                if (optarg != NULL)
+                {
+                    option_element_vector.push_back (OptionArgElement (opt_defs_index, parse_start, 0));
+                }
+                else
+                {
+                    option_element_vector.push_back (OptionArgElement (opt_defs_index, parse_start, parse_start + 1));
+                }
+                break;
+            default:
+                // The options table is messed up.  Here we'll just continue
+                option_element_vector.push_back (OptionArgElement (-1, parse_start, -1));
+                break;
+            }
+        }
+        else
+        {
+            option_element_vector.push_back (OptionArgElement (-1, parse_start, -1));
+        }
+    }
+}
diff --git a/source/Core/Baton.cpp b/source/Core/Baton.cpp
new file mode 100644
index 0000000..103e2e0
--- /dev/null
+++ b/source/Core/Baton.cpp
@@ -0,0 +1,25 @@
+//===-- Baton.cpp -----------------------------------------------*- 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/Baton.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Stream.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+Baton::GetDescription (Stream *s, lldb::DescriptionLevel level) const
+{
+    s->Printf("baton: %p", m_data);
+}
diff --git a/source/Core/Broadcaster.cpp b/source/Core/Broadcaster.cpp
new file mode 100644
index 0000000..b311a8b
--- /dev/null
+++ b/source/Core/Broadcaster.cpp
@@ -0,0 +1,219 @@
+//===-- Broadcaster.cpp -----------------------------------------*- 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/Broadcaster.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Event.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/lldb-private-log.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+Broadcaster::Broadcaster (const char *name) :
+    m_broadcaster_name (name),
+    m_broadcaster_listeners (),
+    m_broadcaster_listeners_mutex (Mutex::eMutexTypeRecursive)
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT);
+    if (log)
+        log->Printf ("%p Broadcaster::Broadcaster(\"%s\")", this, m_broadcaster_name.AsCString());
+
+}
+
+Broadcaster::~Broadcaster()
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT);
+    if (log)
+        log->Printf ("%p Broadcaster::~Broadcaster(\"%s\")", this, m_broadcaster_name.AsCString());
+
+    // Scope for "listeners_locker"
+    {
+        Mutex::Locker listeners_locker(m_broadcaster_listeners_mutex);
+
+        // Make sure the listener forgets about this broadcaster. We do
+        // this in the broadcaster in case the broadcaster object initiates
+        // the removal.
+
+        collection::iterator pos, end = m_broadcaster_listeners.end();
+        for (pos = m_broadcaster_listeners.begin(); pos != end; ++pos)
+            pos->first->BroadcasterWillDestruct (this);
+
+        m_broadcaster_listeners.clear();
+    }
+}
+
+const ConstString &
+Broadcaster::GetBroadcasterName ()
+{
+    return m_broadcaster_name;
+}
+
+void
+Broadcaster::AddInitialEventsToListener (Listener *listener, uint32_t requested_events)
+{
+
+}
+
+uint32_t
+Broadcaster::AddListener (Listener* listener, uint32_t event_mask)
+{
+    Mutex::Locker locker(m_broadcaster_listeners_mutex);
+    collection::iterator pos, end = m_broadcaster_listeners.end();
+
+    collection::iterator existing_pos = end;
+    // See if we already have this listener, and if so, update its mask
+    uint32_t taken_event_types = 0;
+    for (pos = m_broadcaster_listeners.begin(); pos != end; ++pos)
+    {
+        if (pos->first == listener)
+            existing_pos = pos;
+    // For now don't descriminate on who gets what
+    // FIXME: Implement "unique listener for this bit" mask
+    //  taken_event_types |= pos->second;
+    }
+
+    // Each event bit in a Broadcaster object can only be used
+    // by one listener
+    uint32_t available_event_types = ~taken_event_types & event_mask;
+
+    if (available_event_types)
+    {
+        // If we didn't find our listener, add it
+        if (existing_pos == end)
+        {
+            // Grant a new listener the available event bits
+            m_broadcaster_listeners.push_back(std::make_pair(listener, available_event_types));
+        }
+        else
+        {
+            // Grant the existing listener the available event bits
+            existing_pos->second |= available_event_types;
+        }
+
+        // Individual broadcasters decide whether they have outstanding data when a
+        // listener attaches, and insert it into the listener with this method.
+
+        AddInitialEventsToListener (listener, available_event_types);
+    }
+
+    // Return the event bits that were granted to the listener
+    return available_event_types;
+}
+
+bool
+Broadcaster::EventTypeHasListeners (uint32_t event_type)
+{
+    Mutex::Locker locker (m_broadcaster_listeners_mutex);
+    if (m_broadcaster_listeners.empty())
+        return false;
+
+    collection::iterator pos, end = m_broadcaster_listeners.end();
+    for (pos = m_broadcaster_listeners.begin(); pos != end; ++pos)
+    {
+        if (pos->second & event_type)
+            return true;
+    }
+    return false;
+}
+
+bool
+Broadcaster::RemoveListener (Listener* listener, uint32_t event_mask)
+{
+    Mutex::Locker locker(m_broadcaster_listeners_mutex);
+    collection::iterator pos, end = m_broadcaster_listeners.end();
+    // See if we already have this listener, and if so, update its mask
+    for (pos = m_broadcaster_listeners.begin(); pos != end; ++pos)
+    {
+        if (pos->first == listener)
+        {
+            // Relinquish all event bits in "event_mask"
+            pos->second &= ~event_mask;
+            // If all bits have been relinquished then remove this listener
+            if (pos->second == 0)
+                m_broadcaster_listeners.erase (pos);
+            return true;
+        }
+    }
+    return false;
+}
+
+void
+Broadcaster::BroadcastEvent (EventSP &event_sp)
+{
+    return PrivateBroadcastEvent (event_sp, false);
+}
+
+void
+Broadcaster::BroadcastEventIfUnique (EventSP &event_sp)
+{
+    return PrivateBroadcastEvent (event_sp, true);
+}
+
+void
+Broadcaster::PrivateBroadcastEvent (EventSP &event_sp, bool unique)
+{
+    // Can't add a NULL event...
+    if (event_sp.get() == NULL)
+        return;
+
+    // Update the broadcaster on this event
+    event_sp->SetBroadcaster (this);
+
+    const uint32_t event_type = event_sp->GetType();
+
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS);
+    if (log)
+    {
+        StreamString event_description;
+        event_sp->Dump  (&event_description);
+        log->Printf ("%p Broadcaster(\"%s\")::BroadcastEvent (event_sp = {%s}, unique =%i)",
+                     this,
+                     m_broadcaster_name.AsCString(""),
+                     event_description.GetData(),
+                     unique);
+    }
+
+    Mutex::Locker event_types_locker(m_broadcaster_listeners_mutex);
+    collection::iterator pos, end = m_broadcaster_listeners.end();
+
+
+    // Iterate through all listener/mask pairs
+    for (pos = m_broadcaster_listeners.begin(); pos != end; ++pos)
+    {
+        // If the listener's mask matches any bits that we just set, then
+        // put the new event on its event queue.
+        if (event_type & pos->second)
+        {
+            if (unique && pos->first->PeekAtNextEventForBroadcasterWithType (this, event_type))
+                continue;
+            pos->first->AddEvent (event_sp);
+        }
+    }
+}
+
+void
+Broadcaster::BroadcastEvent (uint32_t event_type, EventData *event_data)
+{
+    EventSP event_sp (new Event (event_type, event_data));
+    PrivateBroadcastEvent (event_sp, false);
+}
+
+void
+Broadcaster::BroadcastEventIfUnique (uint32_t event_type, EventData *event_data)
+{
+    EventSP event_sp (new Event (event_type, event_data));
+    PrivateBroadcastEvent (event_sp, true);
+}
+
diff --git a/source/Core/Communication.cpp b/source/Core/Communication.cpp
new file mode 100644
index 0000000..3ec3e0f
--- /dev/null
+++ b/source/Core/Communication.cpp
@@ -0,0 +1,363 @@
+//===-- Communication.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
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private-log.h"
+#include "lldb/Core/Communication.h"
+#include "lldb/Core/Connection.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Core/Event.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Constructor
+//----------------------------------------------------------------------
+Communication::Communication(const char *name) :
+    Broadcaster (name),
+    m_connection_ap (),
+    m_read_thread (NULL),
+    m_read_thread_enabled (false),
+    m_bytes(),
+    m_bytes_mutex (Mutex::eMutexTypeRecursive),
+    m_callback (NULL),
+    m_callback_baton (NULL)
+
+{
+    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION,
+                                 "%p Communication::Communication (name = %s)",
+                                 this, name);
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+Communication::~Communication()
+{
+    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION,
+                                 "%p Communication::~Communication (name = %s)",
+                                 this, m_broadcaster_name.AsCString(""));
+    Clear();
+}
+
+void
+Communication::Clear()
+{
+    StopReadThread (NULL);
+    Disconnect (NULL);
+}
+
+ConnectionStatus
+Communication::BytesAvailable (uint32_t timeout_usec, Error *error_ptr)
+{
+    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::BytesAvailable (timeout_usec = %u)", this, timeout_usec);
+
+    if (m_connection_ap.get())
+        return m_connection_ap->BytesAvailable (timeout_usec, error_ptr);
+    if (error_ptr)
+        error_ptr->SetErrorString("Invalid connection.");
+    return eConnectionStatusNoConnection;
+}
+
+ConnectionStatus
+Communication::Connect (const char *url, Error *error_ptr)
+{
+    Clear();
+
+    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Connect (url = %s)", this, url);
+
+    if (m_connection_ap.get())
+        return m_connection_ap->Connect (url, error_ptr);
+    if (error_ptr)
+        error_ptr->SetErrorString("Invalid connection.");
+    return eConnectionStatusNoConnection;
+}
+
+ConnectionStatus
+Communication::Disconnect (Error *error_ptr)
+{
+    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Disconnect ()", this);
+
+    if (m_connection_ap.get())
+    {
+        ConnectionStatus status = m_connection_ap->Disconnect (error_ptr);
+        m_connection_ap.reset();
+        return status;
+    }
+    return eConnectionStatusNoConnection;
+}
+
+bool
+Communication::IsConnected () const
+{
+    if (m_connection_ap.get())
+        return m_connection_ap->IsConnected ();
+    return false;
+}
+
+bool
+Communication::HasConnection () const
+{
+    return m_connection_ap.get() != NULL;
+}
+
+size_t
+Communication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr)
+{
+    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
+                                 "%p Communication::Write (dst = %p, dst_len = %zu, timeout_usec = %u) connection = %p",
+                                 this, dst, dst_len, timeout_usec, m_connection_ap.get());
+
+    if (m_read_thread != NULL)
+    {
+        // We have a dedicated read thread that is getting data for us
+        size_t cached_bytes = GetCachedBytes (dst, dst_len);
+        if (cached_bytes > 0 || timeout_usec == 0)
+        {
+            status = eConnectionStatusSuccess;
+            return cached_bytes;
+        }
+
+        if (m_connection_ap.get() == NULL)
+        {
+            if (error_ptr)
+                error_ptr->SetErrorString("Invalid connection.");
+            status = eConnectionStatusNoConnection;
+            return 0;
+        }
+        // Set the timeout appropriately
+        TimeValue timeout_time;
+        if (timeout_usec != UINT32_MAX)
+        {
+            timeout_time = TimeValue::Now();
+            timeout_time.OffsetWithMicroSeconds (timeout_usec);
+        }
+
+        Listener listener ("Communication::Read");
+        listener.StartListeningForEvents (this, eBroadcastBitReadThreadGotBytes | eBroadcastBitReadThreadDidExit);
+        EventSP event_sp;
+        while (listener.WaitForEvent (timeout_time.IsValid() ? &timeout_time : NULL, event_sp))
+        {
+            const uint32_t event_type = event_sp->GetType();
+            if (event_type & eBroadcastBitReadThreadGotBytes)
+            {
+                return GetCachedBytes (dst, dst_len);
+            }
+
+            if (event_type & eBroadcastBitReadThreadDidExit)
+            {
+                Disconnect (NULL);
+                break;
+            }
+        }
+        return 0;
+    }
+
+    // We aren't using a read thread, just read the data synchronously in this
+    // thread.
+    if (m_connection_ap.get())
+    {
+        status = m_connection_ap->BytesAvailable (timeout_usec, error_ptr);
+        if (status == eConnectionStatusSuccess)
+            return m_connection_ap->Read (dst, dst_len, status, error_ptr);
+    }
+
+    if (error_ptr)
+        error_ptr->SetErrorString("Invalid connection.");
+    status = eConnectionStatusNoConnection;
+    return 0;
+}
+
+
+size_t
+Communication::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr)
+{
+    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
+                                 "%p Communication::Write (src = %p, src_len = %zu) connection = %p",
+                                 this, src, src_len, m_connection_ap.get());
+
+    if (m_connection_ap.get())
+        return m_connection_ap->Write (src, src_len, status, error_ptr);
+
+    if (error_ptr)
+        error_ptr->SetErrorString("Invalid connection.");
+    status = eConnectionStatusNoConnection;
+    return 0;
+}
+
+
+bool
+Communication::StartReadThread (Error *error_ptr)
+{
+    if (m_read_thread != LLDB_INVALID_HOST_THREAD)
+        return true;
+
+    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
+                                 "%p Communication::StartReadThread ()", this);
+
+
+    char thread_name[1024];
+    snprintf(thread_name, sizeof(thread_name), "<lldb.comm.%s>", m_broadcaster_name.AsCString());
+
+    m_read_thread_enabled = true;
+    m_read_thread = Host::ThreadCreate (thread_name, Communication::ReadThread, this, error_ptr);
+    return m_read_thread != LLDB_INVALID_HOST_THREAD;
+}
+
+bool
+Communication::StopReadThread (Error *error_ptr)
+{
+    if (m_read_thread == NULL)
+        return true;
+
+    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
+                                 "%p Communication::StopReadThread ()", this);
+
+    m_read_thread_enabled = false;
+
+    BroadcastEvent (eBroadcastBitReadThreadShouldExit, NULL);
+
+    Host::ThreadCancel (m_read_thread, error_ptr);
+
+    return Host::ThreadJoin (m_read_thread, NULL, error_ptr);
+}
+
+
+size_t
+Communication::GetCachedBytes (void *dst, size_t dst_len)
+{
+    Mutex::Locker locker(m_bytes_mutex);
+    if (m_bytes.size() > 0)
+    {
+        // If DST is NULL and we have a thread, then return the number
+        // of bytes that are available so the caller can call again
+        if (dst == NULL)
+            return m_bytes.size();
+
+        const size_t len = std::min<size_t>(dst_len, m_bytes.size());
+
+        ::memcpy (dst, m_bytes.data(), len);
+        m_bytes.erase(m_bytes.begin(), m_bytes.begin() + len);
+
+        return len;
+    }
+    return 0;
+}
+
+void
+Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast)
+{
+    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
+                                 "%p Communication::AppendBytesToCache (src = %p, src_len = %zu, broadcast = %i)",
+                                 this, bytes, len, broadcast);
+    if (bytes == NULL || len == 0)
+        return;
+    if (m_callback)
+    {
+        // If the user registered a callback, then call it and do not broadcast
+        m_callback (m_callback_baton, bytes, len);
+    }
+    else
+    {
+        Mutex::Locker locker(m_bytes_mutex);
+        m_bytes.append ((const char *)bytes, len);
+        if (broadcast)
+            BroadcastEventIfUnique (eBroadcastBitReadThreadGotBytes);
+    }
+}
+
+size_t
+Communication::ReadFromConnection (void *dst, size_t dst_len, ConnectionStatus &status, Error *error_ptr)
+{
+    if (m_connection_ap.get())
+        return m_connection_ap->Read (dst, dst_len, status, error_ptr);
+    return 0;
+}
+
+
+bool
+Communication::ReadThreadIsRunning ()
+{
+    return m_read_thread != NULL;
+}
+
+void *
+Communication::ReadThread (void *p)
+{
+    Communication *comm = (Communication *)p;
+
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION);
+
+    if (log)
+        log->Printf ("%p Communication::ReadThread () thread starting...", p);
+
+    uint8_t buf[1024];
+
+    Error error;
+    ConnectionStatus status = eConnectionStatusSuccess;
+    bool done = false;
+    while (!done && comm->m_read_thread_enabled)
+    {
+        status = comm->BytesAvailable (UINT32_MAX, &error);
+
+        if (status == eConnectionStatusSuccess)
+        {
+            size_t bytes_read = comm->ReadFromConnection (buf, sizeof(buf), status, &error);
+            if (bytes_read > 0)
+                    comm->AppendBytesToCache (buf, bytes_read, true);
+        }
+
+        switch (status)
+        {
+        case eConnectionStatusSuccess:
+            break;
+
+        case eConnectionStatusNoConnection:     // No connection
+        case eConnectionStatusLostConnection:   // Lost connection while connected to a valid connection
+            done = true;
+            // Fall through...
+        default:
+        case eConnectionStatusError:            // Check GetError() for details
+        case eConnectionStatusTimedOut:         // Request timed out
+            error.LogIfError(log, "%p Communication::BytesAvailable () => status = %i", p, status);
+            break;
+        }
+    }
+    if (log)
+        log->Printf ("%p Communication::ReadThread () thread exiting...", p);
+
+    // Let clients know that this thread is exiting
+    comm->m_read_thread = LLDB_INVALID_HOST_THREAD;
+    comm->BroadcastEvent (eBroadcastBitReadThreadDidExit);
+    return NULL;
+}
+
+void
+Communication::SetReadThreadBytesReceivedCallback
+(
+    ReadThreadBytesReceived callback,
+    void *callback_baton
+)
+{
+    m_callback = callback;
+    m_callback_baton = callback_baton;
+}
+
+void
+Communication::SetConnection (Connection *connection)
+{
+    StopReadThread(NULL);
+    Disconnect (NULL);
+    m_connection_ap.reset(connection);
+}
diff --git a/source/Core/Connection.cpp b/source/Core/Connection.cpp
new file mode 100644
index 0000000..3c9bb8b
--- /dev/null
+++ b/source/Core/Connection.cpp
@@ -0,0 +1,24 @@
+//===-- Connection.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
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Connection.h"
+
+using namespace lldb_private;
+
+Connection::Connection ()
+{
+}
+
+Connection::~Connection ()
+{
+}
diff --git a/source/Core/ConnectionFileDescriptor.cpp b/source/Core/ConnectionFileDescriptor.cpp
new file mode 100644
index 0000000..b22f5ff
--- /dev/null
+++ b/source/Core/ConnectionFileDescriptor.cpp
@@ -0,0 +1,563 @@
+//===-- ConnectionFileDescriptor.cpp ----------------------------*- 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/ConnectionFileDescriptor.h"
+
+// C Includes
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private-log.h"
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Communication.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/Timer.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+ConnectionFileDescriptor::ConnectionFileDescriptor () :
+    Connection(),
+    m_fd (-1),
+    m_should_close_fd (false)
+{
+    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION |  LIBLLDB_LOG_OBJECT,
+                                 "%p ConnectionFileDescriptor::ConnectionFileDescriptor ()",
+                                 this);
+}
+
+ConnectionFileDescriptor::ConnectionFileDescriptor (int fd, bool owns_fd) :
+    Connection(),
+    m_fd (fd),
+    m_should_close_fd (owns_fd)
+{
+    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION |  LIBLLDB_LOG_OBJECT,
+                                 "%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = %i, owns_fd = %i)",
+                                 this, fd, owns_fd);
+}
+
+
+ConnectionFileDescriptor::~ConnectionFileDescriptor ()
+{
+    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION |  LIBLLDB_LOG_OBJECT,
+                                 "%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()",
+                                 this);
+    Disconnect (NULL);
+}
+
+bool
+ConnectionFileDescriptor::IsConnected () const
+{
+    return m_fd >= 0;
+}
+
+ConnectionStatus
+ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr)
+{
+    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION,
+                                 "%p ConnectionFileDescriptor::Connect (url = '%s')",
+                                 this, s);
+
+    if (s && s[0])
+    {
+        char *end = NULL;
+        if (strstr(s, "listen://"))
+        {
+            // listen://HOST:PORT
+            unsigned long listen_port = ::strtoul(s + strlen("listen://"), &end, 0);
+            return SocketListen (listen_port, error_ptr);
+        }
+        else if (strstr(s, "connect://"))
+        {
+            return SocketConnect (s + strlen("connect://"), error_ptr);
+        }
+        else if (strstr(s, "file://"))
+        {
+            // file:///PATH
+            const char *path = s + strlen("file://");
+            m_fd = ::open (path, O_RDWR);
+            if (m_fd == -1)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorToErrno();
+                return eConnectionStatusError;
+            }
+
+            int flags = ::fcntl (m_fd, F_GETFL, 0);
+            if (flags >= 0)
+            {
+                if ((flags & O_NONBLOCK) == 0)
+                {
+                    flags |= O_NONBLOCK;
+                    ::fcntl (m_fd, F_SETFL, flags);
+                }
+            }
+            m_should_close_fd = true;
+            return eConnectionStatusSuccess;
+        }
+        if (error_ptr)
+            error_ptr->SetErrorStringWithFormat ("Unsupported connection URL: '%s'.\n", s);
+        return eConnectionStatusError;
+    }
+    if (error_ptr)
+        error_ptr->SetErrorString("NULL connection URL.");
+    return eConnectionStatusError;
+}
+
+ConnectionStatus
+ConnectionFileDescriptor::Disconnect (Error *error_ptr)
+{
+    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION,
+                                 "%p ConnectionFileDescriptor::Disconnect ()",
+                                 this);
+    if (m_should_close_fd == false)
+    {
+        m_fd = -1;
+        return eConnectionStatusSuccess;
+    }
+    return Close (m_fd, error_ptr);
+}
+
+size_t
+ConnectionFileDescriptor::Read (void *dst, size_t dst_len, ConnectionStatus &status, Error *error_ptr)
+{
+    Log *log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION);
+    if (log)
+        log->Printf ("%p ConnectionFileDescriptor::Read () ::read (fd = %i, dst = %p, dst_len = %zu)...",
+                     this, m_fd, dst, dst_len);
+
+    Error error;
+    ssize_t bytes_read = ::read (m_fd, dst, dst_len);
+    if (bytes_read == 0)
+    {
+        error.SetErrorStringWithFormat("End-of-file.\n");
+        status = eConnectionStatusLostConnection;
+    }
+    else if (bytes_read < 0)
+    {
+        error.SetErrorToErrno();
+    }
+    else
+    {
+        error.Clear();
+    }
+
+    if (log)
+        log->Printf ("%p ConnectionFileDescriptor::Read () ::read (fd = %i, dst = %p, dst_len = %zu) => %zi, error = %s",
+                     this, 
+                     m_fd, 
+                     dst, 
+                     dst_len, 
+                     bytes_read, 
+                     error.AsCString());
+
+    if (error_ptr)
+        *error_ptr = error;
+
+    if (error.Fail())
+    {
+        uint32_t error_value = error.GetError();
+        switch (error_value)
+        {
+        case EAGAIN:    // The file was marked for non-blocking I/O, and no data were ready to be read.
+            status = eConnectionStatusSuccess;
+            return 0;
+
+        case EBADF:     // fildes is not a valid file or socket descriptor open for reading.
+        case EFAULT:    // Buf points outside the allocated address space.
+        case EINTR:     // A read from a slow device was interrupted before any data arrived by the delivery of a signal.
+        case EINVAL:    // The pointer associated with fildes was negative.
+        case EIO:       // An I/O error occurred while reading from the file system.
+                        // The process group is orphaned.
+                        // The file is a regular file, nbyte is greater than 0,
+                        // the starting position is before the end-of-file, and
+                        // the starting position is greater than or equal to the
+                        // offset maximum established for the open file
+                        // descriptor associated with fildes.
+        case EISDIR:    // An attempt is made to read a directory.
+        case ENOBUFS:   // An attempt to allocate a memory buffer fails.
+        case ENOMEM:    // Insufficient memory is available.
+            status = eConnectionStatusError;
+            break;  // Break to close....
+
+        case ENXIO:     // An action is requested of a device that does not exist..
+                        // A requested action cannot be performed by the device.
+        case ECONNRESET:// The connection is closed by the peer during a read attempt on a socket.
+        case ENOTCONN:  // A read is attempted on an unconnected socket.
+            status = eConnectionStatusLostConnection;
+            break;  // Break to close....
+
+        case ETIMEDOUT: // A transmission timeout occurs during a read attempt on a socket.
+            status = eConnectionStatusTimedOut;
+            return 0;
+        }
+
+//      if (log)
+//          error->Log(log, "::read ( %i, %p, %zu ) => %i", m_fd, dst, dst_len, bytesread);
+        Close (m_fd, NULL);
+        return 0;
+    }
+    return bytes_read;
+}
+
+size_t
+ConnectionFileDescriptor::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr)
+{
+    Log *log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION);
+    if (log)
+        log->Printf ("%p ConnectionFileDescriptor::Write (src = %p, src_len = %zu)", this, src, src_len);
+
+    if (!IsConnected ())
+    {
+        if (error_ptr)
+            error_ptr->SetErrorString("Not connected.");
+        status = eConnectionStatusNoConnection;
+        return 0;
+    }
+
+
+    Error error;
+
+    ssize_t bytes_sent = 0;
+
+    if (m_is_socket)
+        bytes_sent = ::send (m_fd, src, src_len, 0);
+    else
+        bytes_sent = ::write (m_fd, src, src_len);
+
+    if (bytes_sent < 0)
+        error.SetErrorToErrno ();
+    else
+        error.Clear ();
+
+    if (log)
+    {
+        if (m_is_socket)
+            log->Printf ("%p ConnectionFileDescriptor::Write()  ::send (socket = %i, src = %p, src_len = %zu, flags = 0) => %zi (error = %s)",
+                         this, m_fd, src, src_len, bytes_sent, error.AsCString());
+        else
+            log->Printf ("%p ConnectionFileDescriptor::Write()  ::write (fd = %i, src = %p, src_len = %zu) => %zi (error = %s)",
+                         this, m_fd, src, src_len, bytes_sent, error.AsCString());
+    }
+
+    if (error_ptr)
+        *error_ptr = error;
+
+    if (error.Fail())
+    {
+        switch (error.GetError())
+        {
+        case EAGAIN:
+        case EINTR:
+            status = eConnectionStatusSuccess;
+            return 0;
+
+        case ECONNRESET:// The connection is closed by the peer during a read attempt on a socket.
+        case ENOTCONN:  // A read is attempted on an unconnected socket.
+            status = eConnectionStatusLostConnection;
+            break;  // Break to close....
+
+        default:
+            status = eConnectionStatusError;
+            break;  // Break to close....
+        }
+
+        Close (m_fd, NULL);
+        return 0;
+    }
+
+    status = eConnectionStatusSuccess;
+    return bytes_sent;
+}
+
+ConnectionStatus
+ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_ptr)
+{
+    Log *log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION);
+    if (log)
+        log->Printf("%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %u)", this, timeout_usec);
+    struct timeval *tv_ptr;
+    struct timeval tv;
+    if (timeout_usec == UINT32_MAX)
+    {
+        // Infinite wait...
+        tv_ptr = NULL;
+    }
+    else
+    {
+        TimeValue time_value;
+        time_value.OffsetWithMicroSeconds (timeout_usec);
+        tv = time_value.GetAsTimeVal();
+        tv_ptr = &tv;
+    }
+
+    while (IsConnected())
+    {
+        fd_set read_fds;
+        FD_ZERO (&read_fds);
+        FD_SET (m_fd, &read_fds);
+        int nfds = m_fd + 1;
+        
+        Error error;
+
+
+        if (log)
+            log->Printf("%p ConnectionFileDescriptor::Write()  ::select (nfds = %i, fd = %i, NULL, NULL, timeout = %p)...",
+                        this, nfds, m_fd, tv_ptr);
+
+        const int num_set_fds = ::select (nfds, &read_fds, NULL, NULL, tv_ptr);
+        if (num_set_fds < 0)
+            error.SetErrorToErrno();
+        else
+            error.Clear();
+
+        if (log)
+            log->Printf("%p ConnectionFileDescriptor::Write()  ::select (nfds = %i, fd = %i, NULL, NULL, timeout = %p) => %d, error = %s",
+                        this, nfds, m_fd, tv_ptr, num_set_fds, error.AsCString());
+
+        if (error_ptr)
+            *error_ptr = error;
+
+        if (error.Fail())
+        {
+            switch (error.GetError())
+            {
+            case EBADF:     // One of the descriptor sets specified an invalid descriptor.
+            case EINVAL:    // The specified time limit is invalid. One of its components is negative or too large.
+            default:        // Other unknown error
+                return eConnectionStatusError;
+
+            case EAGAIN:    // The kernel was (perhaps temporarily) unable to
+                            // allocate the requested number of file descriptors,
+                            // or we have non-blocking IO
+            case EINTR:     // A signal was delivered before the time limit
+                            // expired and before any of the selected events
+                            // occurred.
+                break;      // Lets keep reading to until we timeout
+            }
+        }
+        else if (num_set_fds == 0)
+        {
+            return eConnectionStatusTimedOut;
+        }
+        else if (num_set_fds > 0)
+        {
+            return eConnectionStatusSuccess;
+        }
+    }
+
+    if (error_ptr)
+        error_ptr->SetErrorString("Not connected.");
+    return eConnectionStatusLostConnection;
+}
+
+ConnectionStatus
+ConnectionFileDescriptor::Close (int& fd, Error *error_ptr)
+{
+    if (error_ptr)
+        error_ptr->Clear();
+    bool success = true;
+    if (fd >= 0)
+    {
+        lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION,
+                                             "%p ConnectionFileDescriptor::Close (fd = %i)",
+                                             this,
+                                             fd);
+
+        success = ::close (fd) == 0;
+        if (!success && error_ptr)
+        {
+            // Only set the error if we have been asked to since something else
+            // might have caused us to try and shut down the connection and may
+            // have already set the error.
+            error_ptr->SetErrorToErrno();
+        }
+        fd = -1;
+    }
+    m_is_socket = false;
+    if (success)
+        return eConnectionStatusSuccess;
+    else
+        return eConnectionStatusError;
+}
+
+ConnectionStatus
+ConnectionFileDescriptor::SocketListen (uint16_t listen_port_num, Error *error_ptr)
+{
+    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION,
+                                 "%p ConnectionFileDescriptor::SocketListen (port = %i)",
+                                 this, listen_port_num);
+
+    Close (m_fd, false);
+    m_is_socket = true;
+    int listen_port = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+    if (listen_port == -1)
+    {
+        if (error_ptr)
+            error_ptr->SetErrorToErrno();
+        return eConnectionStatusError;
+    }
+
+    // enable local address reuse
+    SetSocketOption (listen_port, SOL_SOCKET, SO_REUSEADDR, 1);
+
+    struct sockaddr_in sa;
+    ::memset (&sa, 0, sizeof sa);
+    sa.sin_len = sizeof sa;
+    sa.sin_family = AF_INET;
+    sa.sin_port = htons (listen_port_num);
+    sa.sin_addr.s_addr = htonl (INADDR_ANY);
+
+    int err = ::bind (listen_port, (struct sockaddr *) &sa, sizeof(sa));
+    if (err == -1)
+    {
+        if (error_ptr)
+            error_ptr->SetErrorToErrno();
+        Close (listen_port, NULL);
+        return eConnectionStatusError;
+    }
+
+    err = ::listen (listen_port, 1);
+    if (err == -1)
+    {
+        if (error_ptr)
+            error_ptr->SetErrorToErrno();
+        Close (listen_port, NULL);
+        return eConnectionStatusError;
+    }
+
+    m_fd = ::accept (listen_port, NULL, 0);
+    if (m_fd == -1)
+    {
+        if (error_ptr)
+            error_ptr->SetErrorToErrno();
+        Close (listen_port, NULL);
+        return eConnectionStatusError;
+    }
+
+    // We are done with the listen port
+    Close (listen_port, NULL);
+
+    m_should_close_fd = true;
+
+    // Keep our TCP packets coming without any delays.
+    SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1);
+    if (error_ptr)
+        error_ptr->Clear();
+    return eConnectionStatusSuccess;
+}
+
+ConnectionStatus
+ConnectionFileDescriptor::SocketConnect (const char *host_and_port, Error *error_ptr)
+{
+    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION,
+                                 "%p ConnectionFileDescriptor::SocketConnect (host/port = %s)",
+                                 this, host_and_port);
+    Close (m_fd, false);
+    m_is_socket = true;
+
+    RegularExpression regex ("([^:]+):([0-9]+)");
+    if (regex.Execute (host_and_port, 2) == false)
+    {
+        if (error_ptr)
+            error_ptr->SetErrorStringWithFormat("Invalid host:port specification: '%s'.\n", host_and_port);
+        return eConnectionStatusError;
+    }
+    std::string host_str;
+    std::string port_str;
+    if (regex.GetMatchAtIndex (host_and_port, 1, host_str) == false ||
+        regex.GetMatchAtIndex (host_and_port, 2, port_str) == false)
+    {
+        if (error_ptr)
+            error_ptr->SetErrorStringWithFormat("Invalid host:port specification '%s'.\n", host_and_port);
+        return eConnectionStatusError;
+    }
+
+    int32_t port = Args::StringToSInt32 (port_str.c_str(), INT32_MIN);
+    if (port == INT32_MIN)
+    {
+        if (error_ptr)
+            error_ptr->SetErrorStringWithFormat("Invalid port '%s'.\n", port_str.c_str());
+        return eConnectionStatusError;
+    }
+    // Create the socket
+    m_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+    if (m_fd == -1)
+    {
+        if (error_ptr)
+            error_ptr->SetErrorToErrno();
+        return eConnectionStatusError;
+    }
+
+    m_should_close_fd = true;
+
+    // Enable local address reuse
+    SetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, 1);
+
+    struct sockaddr_in sa;
+    ::bzero (&sa, sizeof (sa));
+    sa.sin_len = sizeof sa;
+    sa.sin_family = AF_INET;
+    sa.sin_port = htons (port);
+
+    int inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr);
+
+    if (inet_pton_result <= 0)
+    {
+        struct hostent *host_entry = gethostbyname (host_str.c_str());
+        if (host_entry)
+            host_str = ::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list);
+        inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr);
+        if (inet_pton_result <= 0)
+        {
+
+            if (error_ptr)
+            {
+                if (inet_pton_result == -1)
+                    error_ptr->SetErrorToErrno();
+                else
+                    error_ptr->SetErrorStringWithFormat("Invalid host string: '%s'.\n", host_str.c_str());
+            }
+            Close (m_fd, false);
+            return eConnectionStatusError;
+        }
+    }
+
+    if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa)))
+    {
+        if (error_ptr)
+            error_ptr->SetErrorToErrno();
+        Close (m_fd, false);
+        return eConnectionStatusError;
+    }
+
+    // Keep our TCP packets coming without any delays.
+    SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1);
+    if (error_ptr)
+        error_ptr->Clear();
+    return eConnectionStatusSuccess;
+}
+
+int
+ConnectionFileDescriptor::SetSocketOption(int fd, int level, int option_name, int option_value)
+{
+    return ::setsockopt(fd, level, option_name, &option_value, sizeof(option_value));
+}
+
+
diff --git a/source/Core/ConstString.cpp b/source/Core/ConstString.cpp
new file mode 100644
index 0000000..c2d09c7
--- /dev/null
+++ b/source/Core/ConstString.cpp
@@ -0,0 +1,480 @@
+//===-- ConstString.cpp -----------------------------------------*- 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/ConstString.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Host/Mutex.h"
+#include "llvm/ADT/StringMap.h"
+
+using namespace lldb_private;
+
+
+//----------------------------------------------------------------------
+// The global string pool is implemented as a hash_map that maps
+// std::string objects to a uint32_t reference count.
+//
+// In debug builds the value that is stored in the ConstString objects is
+// a C string that is owned by one of the std::string objects in the
+// hash map. This was done for visibility purposes when debugging as
+// gcc was often generating insufficient debug info for the
+// iterator objects.
+//
+// In release builds, the value that is stored in the ConstString objects
+// is the iterator into the ConstString::HashMap. This is much faster when
+// it comes to modifying the reference count, and removing strings from
+// the pool.
+//----------------------------------------------------------------------
+class Pool
+{
+public:
+    //------------------------------------------------------------------
+    // Default constructor
+    //
+    // Initialize the member variables and create the empty string.
+    //------------------------------------------------------------------
+    Pool () :
+        m_mutex (Mutex::eMutexTypeRecursive),
+        m_string_map ()
+    {
+    }
+
+    //------------------------------------------------------------------
+    // Destructor
+    //------------------------------------------------------------------
+    ~Pool ()
+    {
+    }
+
+
+    static llvm::StringMapEntry<uint32_t> &
+    GetStringMapEntryFromKeyData (const char *keyData)
+    {
+        char *ptr = const_cast<char*>(keyData) - sizeof (llvm::StringMapEntry<uint32_t>);
+        return *reinterpret_cast<llvm::StringMapEntry<uint32_t>*>(ptr);
+    }
+
+    size_t
+    GetConstCStringLength (const char *ccstr)
+    {
+        if (ccstr)
+        {
+            llvm::StringMapEntry<uint32_t>&entry = GetStringMapEntryFromKeyData (ccstr);
+            return entry.getKey().size();
+        }
+        return 0;
+    }
+
+    const char *
+    GetConstCString (const char *cstr)
+    {
+        if (cstr)
+        {
+            Mutex::Locker locker (m_mutex);
+            llvm::StringRef string_ref (cstr);
+            llvm::StringMapEntry<uint32_t>& entry = m_string_map.GetOrCreateValue (string_ref);
+            const char *ccstr = entry.getKeyData();
+            llvm::StringMapEntry<uint32_t>&reconstituted_entry = GetStringMapEntryFromKeyData (ccstr);
+            assert (&entry == &reconstituted_entry);
+            return ccstr;
+        }
+        return NULL;
+    }
+
+    const char *
+    GetConstCStringWithLength (const char *cstr, int cstr_len)
+    {
+        if (cstr)
+        {
+            Mutex::Locker locker (m_mutex);
+            llvm::StringRef string_ref (cstr, cstr_len);
+            llvm::StringMapEntry<uint32_t>& entry = m_string_map.GetOrCreateValue (string_ref);
+            const char *ccstr = entry.getKeyData();
+            llvm::StringMapEntry<uint32_t>&reconstituted_entry = GetStringMapEntryFromKeyData (ccstr);
+            assert (&entry == &reconstituted_entry);
+            return ccstr;
+        }
+        return NULL;
+    }
+
+    const char *
+    GetConstTrimmedCStringWithLength (const char *cstr, int cstr_len)
+    {
+        if (cstr)
+        {
+            Mutex::Locker locker (m_mutex);
+            int actual_cstr_len = strlen (cstr);
+            llvm::StringRef string_ref (cstr, std::min<int>(actual_cstr_len, cstr_len));
+            llvm::StringMapEntry<uint32_t>& entry = m_string_map.GetOrCreateValue (string_ref);
+            const char *ccstr = entry.getKeyData();
+            llvm::StringMapEntry<uint32_t>&reconstituted_entry = GetStringMapEntryFromKeyData (ccstr);
+            assert (&entry == &reconstituted_entry);
+            return ccstr;
+        }
+        return NULL;
+    }
+
+    //------------------------------------------------------------------
+    // Return the size in bytes that this object and any items in its
+    // collection of uniqued strings + reference count values takes in
+    // memory.
+    //------------------------------------------------------------------
+    size_t
+    MemorySize() const
+    {
+        Mutex::Locker locker (m_mutex);
+        size_t mem_size = sizeof(Pool);
+        const_iterator end = m_string_map.end();
+        for (const_iterator pos = m_string_map.begin(); pos != end; ++pos)
+        {
+            mem_size += sizeof(llvm::StringMapEntry<uint32_t>) + pos->getKey().size();
+        }
+        return mem_size;
+    }
+
+protected:
+    //------------------------------------------------------------------
+    // Typedefs
+    //------------------------------------------------------------------
+    typedef llvm::StringMap<uint32_t, llvm::BumpPtrAllocator> StringPool;
+    typedef StringPool::iterator iterator;
+    typedef StringPool::const_iterator const_iterator;
+
+    //------------------------------------------------------------------
+    // Member variables
+    //------------------------------------------------------------------
+    mutable Mutex m_mutex;
+    StringPool m_string_map;
+};
+
+//----------------------------------------------------------------------
+// Frameworks and dylibs aren't supposed to have global C++
+// initializers so we hide the string pool in a static function so
+// that it will get initialized on the first call to this static
+// function.
+//----------------------------------------------------------------------
+static Pool &
+StringPool()
+{
+    static Pool string_pool;
+    return string_pool;
+}
+
+//----------------------------------------------------------------------
+// Default constructor
+//
+// Initializes the string to an empty string.
+//----------------------------------------------------------------------
+ConstString::ConstString () :
+    m_string (NULL)
+{
+}
+
+//----------------------------------------------------------------------
+// Copy constructor
+//
+// Copies the string value in "rhs" and retains an extra reference
+// to the string value in the string pool.
+//----------------------------------------------------------------------
+ConstString::ConstString (const ConstString& rhs) :
+    m_string (rhs.m_string)
+{
+}
+
+//----------------------------------------------------------------------
+// Construct with C String value
+//
+// Constructs this object with a C string by looking to see if the
+// C string already exists in the global string pool. If it does
+// exist, it retains an extra reference to the string in the string
+// pool. If it doesn't exist, it is added to the string pool with
+// a reference count of 1.
+//----------------------------------------------------------------------
+ConstString::ConstString (const char *cstr) :
+    m_string (StringPool().GetConstCString (cstr))
+{
+}
+
+//----------------------------------------------------------------------
+// Construct with C String value with max length
+//
+// Constructs this object with a C string with a length. If
+// the length of the string is greather than "cstr_len", the
+// string length will be truncated. This allows substrings to be
+// created without the need to NULL terminate the string as it
+// is passed into this function.
+//
+// If the C string already exists in the global string pool, it
+// retains an extra reference to the string in the string
+// pool. If it doesn't exist, it is added to the string pool with
+// a reference count of 1.
+//----------------------------------------------------------------------
+ConstString::ConstString (const char *cstr, size_t cstr_len) :
+    m_string (StringPool().GetConstCStringWithLength (cstr, cstr_len))
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//
+// Decrements the reference count on the contained string, and if
+// the resulting reference count is zero, then the string is removed
+// from the string pool. If the reference count is still greater
+// than zero, the string will remain in the string pool
+//----------------------------------------------------------------------
+ConstString::~ConstString ()
+{
+}
+
+//----------------------------------------------------------------------
+// Convert to pointer operator. This allows code to check any
+// ConstString objects to see if they contain anything (not empty)
+// valid using code such as:
+//
+//  ConstString str(...);
+//  if (str)
+//  { ...
+//----------------------------------------------------------------------
+ConstString::operator void*() const
+{
+    return IsEmpty() ? NULL : const_cast<ConstString*>(this);
+}
+
+//----------------------------------------------------------------------
+// Assignment operator
+//
+// Assigns the string in this object with the value from "rhs"
+// and increments the reference count of that string.
+//
+// The previously contained string will be get its reference count
+// decremented and removed from the string pool if its reference
+// count reaches zero.
+//----------------------------------------------------------------------
+const ConstString&
+ConstString::operator=(const ConstString& rhs)
+{
+    m_string = rhs.m_string;
+    return *this;
+}
+
+//----------------------------------------------------------------------
+// Equal to operator
+//
+// Returns true if this string is equal to that in "rhs". This is
+// very fast as it results in a pointer comparison since all strings
+// are in a uniqued and reference counted string pool.
+//------------------------------------------------------------------
+bool
+ConstString::operator == (const ConstString& rhs) const
+{
+    // We can do a pointer compare to compare these strings since they
+    // must come from the same pool in order to be equal.
+    return m_string == rhs.m_string;
+}
+
+bool
+ConstString::operator != (const ConstString& rhs) const
+{
+    return m_string != rhs.m_string;
+}
+
+bool
+ConstString::operator < (const ConstString& rhs) const
+{
+    if (m_string == rhs.m_string)
+        return false;
+
+    llvm::StringRef lhs_string_ref (m_string, StringPool().GetConstCStringLength (m_string));
+    llvm::StringRef rhs_string_ref (rhs.m_string, StringPool().GetConstCStringLength (rhs.m_string));
+
+    // If both have valid C strings, then return the comparison
+    if (lhs_string_ref.data() && rhs_string_ref.data())
+        return lhs_string_ref < rhs_string_ref;
+
+    // Else one of them was NULL, so if LHS is NULL then it is less than
+    return lhs_string_ref.data() == NULL;
+}
+
+//----------------------------------------------------------------------
+// Stream the string value "str" to the stream "s"
+//----------------------------------------------------------------------
+Stream&
+lldb_private::operator << (Stream& s, const ConstString& str)
+{
+    const char *cstr = str.GetCString();
+    if (cstr)
+        s << cstr;
+
+    return s;
+}
+
+//----------------------------------------------------------------------
+// Get the value of the contained string as a NULL terminated C
+// string value. Return "fail_value" if the string is empty.
+//----------------------------------------------------------------------
+const char *
+ConstString::AsCString(const char *fail_value) const
+{
+    if (m_string == NULL)
+        return fail_value;
+    return m_string;
+}
+
+const char *
+ConstString::GetCString () const
+{
+    return m_string;
+}
+
+size_t
+ConstString::GetLength () const
+{
+    return StringPool().GetConstCStringLength (m_string);
+}
+
+
+//----------------------------------------------------------------------
+// Clear any contained string and reset the value to the an empty
+// string value.
+//
+// The previously contained string will be get its reference count
+// decremented and removed from the string pool if its reference
+// count reaches zero.
+//----------------------------------------------------------------------
+void
+ConstString::Clear ()
+{
+    m_string = NULL;
+}
+
+//----------------------------------------------------------------------
+// Compare two string objects.
+//
+// Returns:
+//  -1 if a < b
+//   0 if a == b
+//   1 if a > b
+//----------------------------------------------------------------------
+int
+ConstString::Compare (const ConstString& lhs, const ConstString& rhs)
+{
+    // If the iterators are the same, this is the same string
+    register const char *lhs_cstr = lhs.m_string;
+    register const char *rhs_cstr = rhs.m_string;
+    if (lhs_cstr == rhs_cstr)
+        return 0;
+    if (lhs_cstr && rhs_cstr)
+    {
+        llvm::StringRef lhs_string_ref (lhs_cstr, StringPool().GetConstCStringLength (lhs_cstr));
+        llvm::StringRef rhs_string_ref (rhs_cstr, StringPool().GetConstCStringLength (rhs_cstr));
+        return lhs_string_ref.compare(rhs_string_ref);
+    }
+
+    if (lhs_cstr)
+        return +1;  // LHS isn't NULL but RHS is
+    else
+        return -1;  // LHS is NULL but RHS isn't
+}
+
+//----------------------------------------------------------------------
+// Dump the string value to the stream "s". If the contained string
+// is empty, print "fail_value" to the stream instead. If
+// "fail_value" is NULL, then nothing will be dumped to the
+// stream.
+//----------------------------------------------------------------------
+void
+ConstString::Dump(Stream *s, const char *fail_value) const
+{
+    const char *cstr = AsCString (fail_value);
+    if (cstr)
+        s->PutCString (cstr);
+}
+
+//----------------------------------------------------------------------
+// Dump extra debug information to the stream "s".
+//----------------------------------------------------------------------
+void
+ConstString::DumpDebug(Stream *s) const
+{
+    const char *cstr = GetCString ();
+    size_t cstr_len = GetLength();
+    // Only print the parens if we have a non-NULL string
+    const char *parens = cstr ? "\"" : "";
+    s->Printf("%*p: ConstString, string = %s%s%s, length = %zu", (int)sizeof(void*) * 2, this, parens, cstr, parens, cstr_len);
+}
+
+//----------------------------------------------------------------------
+// Returns true if the contained string is empty.
+//----------------------------------------------------------------------
+bool
+ConstString::IsEmpty() const
+{
+    return m_string == NULL || m_string[0] == '\0';
+}
+
+//----------------------------------------------------------------------
+// Set the string value in the object by uniquing the "cstr" string
+// value in our global string pool.
+//
+// If the C string already exists in the global string pool, it
+// retains an extra reference to the string in the string
+// pool. If it doesn't exist, it is added to the string pool with
+// a reference count of 1.
+//----------------------------------------------------------------------
+void
+ConstString::SetCString (const char *cstr)
+{
+    m_string = StringPool().GetConstCString (cstr);
+}
+
+//----------------------------------------------------------------------
+// Set the string value in the object by uniquing "cstr_len" bytes
+// starting at the "cstr" string value in our global string pool.
+// If trim is true, then "cstr_len" indicates a maximum length of
+// the CString and if the actual length of the string is less, then
+// it will be trimmed. If trim is false, then this allows strings
+// with NULL characters ('\0') to be added to the string pool.
+//
+// If the C string already exists in the global string pool, it
+// retains an extra reference to the string in the string
+// pool. If it doesn't exist, it is added to the string pool with
+// a reference count of 1.
+//----------------------------------------------------------------------
+void
+ConstString::SetCStringWithLength (const char *cstr, size_t cstr_len)
+{
+    m_string = StringPool().GetConstCStringWithLength(cstr, cstr_len);
+}
+
+void
+ConstString::SetTrimmedCStringWithLength (const char *cstr, size_t cstr_len)
+{
+    m_string = StringPool().GetConstTrimmedCStringWithLength (cstr, cstr_len);
+}
+
+//----------------------------------------------------------------------
+// Return the size in bytes that this object takes in memory. The
+// resulting size will not include any of the C string values from
+// the global string pool (see StaticMemorySize ()).
+//----------------------------------------------------------------------
+size_t
+ConstString::MemorySize() const
+{
+    return sizeof(ConstString);
+}
+
+//----------------------------------------------------------------------
+// Reports the the size in bytes of all shared C string values,
+// containers and reference count values as a byte size for the
+// entire string pool.
+//----------------------------------------------------------------------
+size_t
+ConstString::StaticMemorySize()
+{
+    // Get the size of the static string pool
+    return StringPool().MemorySize();
+}
diff --git a/source/Core/DataBufferHeap.cpp b/source/Core/DataBufferHeap.cpp
new file mode 100644
index 0000000..a93427f
--- /dev/null
+++ b/source/Core/DataBufferHeap.cpp
@@ -0,0 +1,105 @@
+//===-- DataBufferHeap.cpp --------------------------------------*- 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"
+
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Default constructor
+//----------------------------------------------------------------------
+DataBufferHeap::DataBufferHeap () :
+    m_data()
+{
+}
+
+//----------------------------------------------------------------------
+// Initialize this class with "n" characters and fill the buffer
+// with "ch".
+//----------------------------------------------------------------------
+DataBufferHeap::DataBufferHeap (size_t n, uint8_t ch) :
+    m_data(n, ch)
+{
+}
+
+//----------------------------------------------------------------------
+// Initialize this class with a copy of the "n" bytes from the "bytes"
+// buffer.
+//----------------------------------------------------------------------
+DataBufferHeap::DataBufferHeap (const void *src, size_t src_len) :
+    m_data()
+{
+    CopyData (src, src_len);
+}
+
+//----------------------------------------------------------------------
+// Virtual destructor since this class inherits from a pure virtual
+// base class.
+//----------------------------------------------------------------------
+DataBufferHeap::~DataBufferHeap ()
+{
+}
+
+//----------------------------------------------------------------------
+// Return a pointer to the bytes owned by this object, or NULL if
+// the object contains no bytes.
+//----------------------------------------------------------------------
+uint8_t *
+DataBufferHeap::GetBytes ()
+{
+    if (m_data.empty())
+        return NULL;
+    return &m_data[0];
+}
+
+//----------------------------------------------------------------------
+// Return a const pointer to the bytes owned by this object, or NULL
+// if the object contains no bytes.
+//----------------------------------------------------------------------
+const uint8_t *
+DataBufferHeap::GetBytes () const
+{
+    if (m_data.empty())
+        return NULL;
+    return &m_data[0];
+}
+
+//----------------------------------------------------------------------
+// Return the number of bytes this object currently contains.
+//----------------------------------------------------------------------
+size_t
+DataBufferHeap::GetByteSize () const
+{
+    return m_data.size();
+}
+
+
+//----------------------------------------------------------------------
+// Sets the number of bytes that this object should be able to
+// contain. This can be used prior to copying data into the buffer.
+//----------------------------------------------------------------------
+size_t
+DataBufferHeap::SetByteSize (size_t new_size)
+{
+    m_data.resize(new_size);
+    return m_data.size();
+}
+
+void
+DataBufferHeap::CopyData (const void *src, size_t src_len)
+{
+    const uint8_t *src_u8 = (const uint8_t *)src;
+    if (src && src_len > 0)
+        m_data.assign (src_u8, src_u8 + src_len);
+    else
+        m_data.clear();
+}
+
+
+
diff --git a/source/Core/DataBufferMemoryMap.cpp b/source/Core/DataBufferMemoryMap.cpp
new file mode 100644
index 0000000..c8ad549
--- /dev/null
+++ b/source/Core/DataBufferMemoryMap.cpp
@@ -0,0 +1,214 @@
+//===-- DataBufferMemoryMap.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include "lldb/Core/DataBufferMemoryMap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Host/Host.h"
+
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Default Constructor
+//----------------------------------------------------------------------
+DataBufferMemoryMap::DataBufferMemoryMap() :
+    m_mmap_addr(NULL),
+    m_mmap_size(0),
+    m_data(NULL),
+    m_size(0),
+    m_error()
+{
+}
+
+//----------------------------------------------------------------------
+// Virtual destructor since this class inherits from a pure virtual
+// base class.
+//----------------------------------------------------------------------
+DataBufferMemoryMap::~DataBufferMemoryMap()
+{
+    Clear();
+}
+
+//----------------------------------------------------------------------
+// Return a pointer to the bytes owned by this object, or NULL if
+// the object contains no bytes.
+//----------------------------------------------------------------------
+uint8_t *
+DataBufferMemoryMap::GetBytes()
+{
+    return m_data;
+}
+
+//----------------------------------------------------------------------
+// Return a const pointer to the bytes owned by this object, or NULL
+// if the object contains no bytes.
+//----------------------------------------------------------------------
+const uint8_t *
+DataBufferMemoryMap::GetBytes() const
+{
+    return m_data;
+}
+
+//----------------------------------------------------------------------
+// Return the number of bytes this object currently contains.
+//----------------------------------------------------------------------
+size_t
+DataBufferMemoryMap::GetByteSize() const
+{
+    return m_size;
+}
+
+//----------------------------------------------------------------------
+// Reverts this object to an empty state by unmapping any memory
+// that is currently owned.
+//----------------------------------------------------------------------
+void
+DataBufferMemoryMap::Clear()
+{
+    if (m_mmap_addr != NULL)
+    {
+        ::munmap((void *)m_mmap_addr, m_mmap_size);
+        m_mmap_addr = NULL;
+        m_mmap_size = 0;
+        m_data = NULL;
+        m_size = 0;
+    }
+    m_error.Clear();
+}
+
+
+const Error &
+DataBufferMemoryMap::GetError() const
+{
+    return m_error;
+}
+
+//----------------------------------------------------------------------
+// Memory map "length" bytes from "file" starting "offset"
+// bytes into the file. If "length" is set to SIZE_T_MAX, then
+// map as many bytes as possible.
+//
+// Returns the number of bytes mapped starting from the requested
+// offset.
+//----------------------------------------------------------------------
+size_t
+DataBufferMemoryMap::MemoryMapFromFileSpec (const FileSpec* file, off_t offset, size_t length)
+{
+    if (file != NULL)
+    {
+        char path[PATH_MAX];
+        if (file->GetPath(path, sizeof(path)))
+        {
+            int fd = ::open(path, O_RDONLY, 0);
+            if (fd >= 0)
+            {
+                MemoryMapFromFileDescriptor (fd, offset, length);
+                ::close(fd);
+                return GetByteSize();
+            }
+            else
+            {
+                m_error.SetErrorToErrno();
+                return 0;
+            }
+        }
+    }
+    // We should only get here if there was an error
+    Clear();
+    return 0;
+}
+
+
+//----------------------------------------------------------------------
+// The file descriptor FD is assumed to already be opened as read only
+// and the STAT structure is assumed to a valid pointer and already
+// containing valid data from a call to stat().
+//
+// Memory map FILE_LENGTH bytes in FILE starting FILE_OFFSET bytes into
+// the file. If FILE_LENGTH is set to SIZE_T_MAX, then map as many bytes
+// as possible.
+//
+// RETURNS
+//  Number of bytes mapped starting from the requested offset.
+//----------------------------------------------------------------------
+size_t
+DataBufferMemoryMap::MemoryMapFromFileDescriptor (int fd, off_t offset, size_t length)
+{
+    Clear();
+    if (fd >= 0)
+    {
+        struct stat stat;
+        if (::fstat(fd, &stat) == 0)
+        {
+            if ((stat.st_mode & S_IFREG) && (stat.st_size > offset))
+            {
+                if (length == SIZE_T_MAX)
+                    length = stat.st_size - offset;
+
+                // Cap the length if too much data was requested
+                if (length > stat.st_size - offset)
+                    length = stat.st_size - offset;
+
+                if (length > 0)
+                {
+                    m_mmap_addr = (uint8_t *)::mmap(NULL, length, PROT_READ, MAP_FILE | MAP_SHARED, fd, offset);
+
+                    if (m_mmap_addr == (void*)-1)
+                    {
+                        m_error.SetErrorToErrno ();
+                        if (m_error.GetError() == EINVAL)
+                        {
+                            // We may still have a shot at memory mapping if we align things correctly
+                            size_t page_offset = offset % Host::GetPageSize();
+                            if (page_offset != 0)
+                            {
+                                m_mmap_addr = (uint8_t *)::mmap(NULL, length + page_offset, PROT_READ, MAP_FILE | MAP_SHARED, fd, offset - page_offset);
+                                if (m_mmap_addr == (void*)-1)
+                                {
+                                    // Failed to map file
+                                    m_mmap_addr = NULL;
+                                }
+                                else if (m_mmap_addr != NULL)
+                                {
+                                    // We recovered and were able to memory map
+                                    // after we aligned things to page boundaries
+                                    m_error.Clear ();
+
+                                    // Save the actual mmap'ed size
+                                    m_mmap_size = length + page_offset;
+                                    // Our data is at an offset into the the mapped data
+                                    m_data = m_mmap_addr + page_offset;
+                                    // Our pretend size is the size that was requestd
+                                    m_size = length;
+                                }
+                            }
+                        }
+                    }
+                    else
+                    {
+                        // We were able to map the requested data in one chunk
+                        // where our mmap and actual data are the same.
+                        m_mmap_size = length;
+                        m_data = m_mmap_addr;
+                        m_size = length;
+                    }
+                }
+            }
+        }
+
+        ::close (fd);
+    }
+    return GetByteSize ();
+}
diff --git a/source/Core/DataExtractor.cpp b/source/Core/DataExtractor.cpp
new file mode 100644
index 0000000..236ec18
--- /dev/null
+++ b/source/Core/DataExtractor.cpp
@@ -0,0 +1,1517 @@
+//===-- DataExtractor.cpp ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <assert.h>
+#include <libkern/OSByteOrder.h>
+#include <stddef.h>
+
+#include <bitset>
+#include <string>
+
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/DataBuffer.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/UUID.h"
+#include "lldb/Core/dwarf.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+#define NON_PRINTABLE_CHAR '.'
+//----------------------------------------------------------------------
+// Default constructor.
+//----------------------------------------------------------------------
+DataExtractor::DataExtractor () :
+    m_start     (NULL),
+    m_end       (NULL),
+    m_byte_order(eByteOrderHost),
+    m_addr_size (4),
+    m_data_sp   ()
+{
+}
+
+//----------------------------------------------------------------------
+// This constructor allows us to use data that is owned by someone else.
+// The data must stay around as long as this object is valid.
+//----------------------------------------------------------------------
+DataExtractor::DataExtractor (const void* data, uint32_t length, ByteOrder endian, uint8_t addr_size) :
+    m_start     ((uint8_t*)data),
+    m_end       ((uint8_t*)data + length),
+    m_byte_order(endian),
+    m_addr_size (addr_size),
+    m_data_sp   ()
+{
+}
+
+//----------------------------------------------------------------------
+// Make a shared pointer reference to the shared data in "data_sp" and
+// set the endian swapping setting to "swap", and the address size to
+// "addr_size". The shared data reference will ensure the data lives
+// as long as any DataExtractor objects exist that have a reference to
+// this data.
+//----------------------------------------------------------------------
+DataExtractor::DataExtractor (DataBufferSP& data_sp, ByteOrder endian, uint8_t addr_size) :
+    m_start     (NULL),
+    m_end       (NULL),
+    m_byte_order(endian),
+    m_addr_size (addr_size),
+    m_data_sp   ()
+{
+    SetData (data_sp);
+}
+
+//----------------------------------------------------------------------
+// Initialize this object with a subset of the data bytes in "data".
+// If "data" contains shared data, then a reference to this shared
+// data will added and the shared data will stay around as long
+// as any object contains a reference to that data. The endian
+// swap and address size settings are copied from "data".
+//----------------------------------------------------------------------
+DataExtractor::DataExtractor (const DataExtractor& data, uint32_t offset, uint32_t length) :
+    m_start(NULL),
+    m_end(NULL),
+    m_byte_order(data.m_byte_order),
+    m_addr_size(data.m_addr_size),
+    m_data_sp()
+{
+    if (data.ValidOffset(offset))
+    {
+        uint32_t bytes_available = data.GetByteSize() - offset;
+        if (length > bytes_available)
+            length = bytes_available;
+        SetData(data, offset, length);
+    }
+}
+
+//----------------------------------------------------------------------
+// Assignment operator
+//----------------------------------------------------------------------
+const DataExtractor&
+DataExtractor::operator= (const DataExtractor& rhs)
+{
+    if (this != &rhs)
+    {
+        m_start     = rhs.m_start;
+        m_end       = rhs.m_end;
+        m_byte_order= rhs.m_byte_order;
+        m_addr_size = rhs.m_addr_size;
+        m_data_sp   = rhs.m_data_sp;
+    }
+    return *this;
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+DataExtractor::~DataExtractor ()
+{
+}
+
+//------------------------------------------------------------------
+// Clears the object contents back to a default invalid state, and
+// release any references to shared data that this object may
+// contain.
+//------------------------------------------------------------------
+void
+DataExtractor::Clear ()
+{
+    m_start = NULL;
+    m_end = NULL;
+    m_byte_order = eByteOrderHost;
+    m_addr_size = 4;
+    m_data_sp.reset();
+}
+
+//------------------------------------------------------------------
+// Returns the total number of bytes that this object refers to
+//------------------------------------------------------------------
+size_t
+DataExtractor::GetByteSize () const
+{
+    return m_end - m_start;
+}
+
+//------------------------------------------------------------------
+// If this object contains shared data, this function returns the
+// offset into that shared data. Else zero is returned.
+//------------------------------------------------------------------
+size_t
+DataExtractor::GetSharedDataOffset () const
+{
+    if (m_start != NULL)
+    {
+        const DataBuffer * data = m_data_sp.get();
+        if (data != NULL)
+        {
+            const uint8_t * data_bytes = data->GetBytes();
+            if (data_bytes != NULL)
+            {
+                assert(m_start >= data_bytes);
+                return m_start - data_bytes;
+            }
+        }
+    }
+    return 0;
+}
+
+//------------------------------------------------------------------
+// Returns true if OFFSET is a valid offset into the data in this
+// object.
+//------------------------------------------------------------------
+bool
+DataExtractor::ValidOffset (uint32_t offset) const
+{
+    return offset < GetByteSize();
+}
+
+//------------------------------------------------------------------
+// Returns true if there are LENGTH bytes availabe starting OFFSET
+// into the data that is in this object.
+//------------------------------------------------------------------
+bool
+DataExtractor::ValidOffsetForDataOfSize (uint32_t offset, uint32_t length) const
+{
+    size_t size = GetByteSize();
+    if (offset >= size)
+        return false;   // offset isn't valid
+
+    if (length == 0)
+        return true;    // No bytes requested at this offset, return true
+
+    // If we flip the bits in offset we can figure out how
+    // many bytes we have left before "offset + length"
+    // could overflow when doing unsigned arithmetic.
+    if (length > ~offset)
+        return false;   // unsigned overflow
+
+    // Make sure "offset + length" is a valid offset as well.
+    // length must be greater than zero for this to be a
+    // valid expression, and we have already checked for this.
+    return ((offset + length) <= size);
+}
+
+//------------------------------------------------------------------
+// Returns a pointer to the first byte contained in this object's
+// data, or NULL of there is no data in this object.
+//------------------------------------------------------------------
+const uint8_t *
+DataExtractor::GetDataStart () const
+{
+    return m_start;
+}
+//------------------------------------------------------------------
+// Returns a pointer to the byte past the last byte contained in
+// this object's data, or NULL of there is no data in this object.
+//------------------------------------------------------------------
+const uint8_t *
+DataExtractor::GetDataEnd () const
+{
+    return m_end;
+}
+
+//------------------------------------------------------------------
+// Returns true if this object will endian swap values as it
+// extracts data.
+//------------------------------------------------------------------
+ByteOrder
+DataExtractor::GetByteOrder () const
+{
+    return m_byte_order;
+}
+//------------------------------------------------------------------
+// Set wether this object will endian swap values as it extracts
+// data.
+//------------------------------------------------------------------
+void
+DataExtractor::SetByteOrder (ByteOrder endian)
+{
+    m_byte_order = endian;
+}
+
+
+//------------------------------------------------------------------
+// Return the size in bytes of any address values this object will
+// extract
+//------------------------------------------------------------------
+uint8_t
+DataExtractor::GetAddressByteSize () const
+{
+    return m_addr_size;
+}
+
+//------------------------------------------------------------------
+// Set the size in bytes that will be used when extracting any
+// address values from data contained in this object.
+//------------------------------------------------------------------
+void
+DataExtractor::SetAddressByteSize (uint8_t addr_size)
+{
+    m_addr_size = addr_size;
+}
+
+//----------------------------------------------------------------------
+// Set the data with which this object will extract from to data
+// starting at BYTES and set the length of the data to LENGTH bytes
+// long. The data is externally owned must be around at least as
+// long as this object points to the data. No copy of the data is
+// made, this object just refers to this data and can extract from
+// it. If this object refers to any shared data upon entry, the
+// reference to that data will be released. Is SWAP is set to true,
+// any data extracted will be endian swapped.
+//----------------------------------------------------------------------
+uint32_t
+DataExtractor::SetData (const void *bytes, uint32_t length, ByteOrder endian)
+{
+    m_byte_order = endian;
+    m_data_sp.reset();
+    if (bytes == NULL || length == 0)
+    {
+        m_start = NULL;
+        m_end = NULL;
+    }
+    else
+    {
+        m_start = (uint8_t *)bytes;
+        m_end = m_start + length;
+    }
+    return GetByteSize();
+}
+
+//----------------------------------------------------------------------
+// Assign the data for this object to be a subrange in "data"
+// starting "data_offset" bytes into "data" and ending "data_length"
+// bytes later. If "data_offset" is not a valid offset into "data",
+// then this object will contain no bytes. If "data_offset" is
+// within "data" yet "data_length" is too large, the length will be
+// capped at the number of bytes remaining in "data". If "data"
+// contains a shared pointer to other data, then a ref counted
+// pointer to that data will be made in this object. If "data"
+// doesn't contain a shared pointer to data, then the bytes referred
+// to in "data" will need to exist at least as long as this object
+// refers to those bytes. The address size and endian swap settings
+// are copied from the current values in "data".
+//----------------------------------------------------------------------
+uint32_t
+DataExtractor::SetData (const DataExtractor& data, uint32_t data_offset, uint32_t data_length)
+{
+    m_addr_size = data.m_addr_size;
+    // If "data" contains shared pointer to data, then we can use that
+    if (data.m_data_sp.get())
+    {
+        m_byte_order = data.m_byte_order;
+        return SetData(data.m_data_sp, data.GetSharedDataOffset() + data_offset, data_length);
+    }
+
+    // We have a DataExtractor object that just has a pointer to bytes
+    if (data.ValidOffset(data_offset))
+    {
+        if (data_length > data.GetByteSize() - data_offset)
+            data_length = data.GetByteSize() - data_offset;
+        return SetData (data.GetDataStart() + data_offset, data_length, data.GetByteOrder());
+    }
+    return 0;
+}
+
+//----------------------------------------------------------------------
+// Assign the data for this object to be a subrange of the shared
+// data in "data_sp" starting "data_offset" bytes into "data_sp"
+// and ending "data_length" bytes later. If "data_offset" is not
+// a valid offset into "data_sp", then this object will contain no
+// bytes. If "data_offset" is within "data_sp" yet "data_length" is
+// too large, the length will be capped at the number of bytes
+// remaining in "data_sp". A ref counted pointer to the data in
+// "data_sp" will be made in this object IF the number of bytes this
+// object refers to in greater than zero (if at least one byte was
+// available starting at "data_offset") to ensure the data stays
+// around as long as it is needed. The address size and endian swap
+// settings will remain unchanged from their current settings.
+//----------------------------------------------------------------------
+uint32_t
+DataExtractor::SetData (DataBufferSP& data_sp, uint32_t data_offset, uint32_t data_length)
+{
+    m_start = m_end = NULL;
+
+    if (data_length > 0)
+    {
+        m_data_sp = data_sp;
+        if (data_sp.get())
+        {
+            const size_t data_size = data_sp->GetByteSize();
+            if (data_offset < data_size)
+            {
+                m_start = data_sp->GetBytes() + data_offset;
+                const size_t bytes_left = data_size - data_offset;
+                // Cap the length of we asked for too many
+                if (data_length <= bytes_left)
+                    m_end = m_start + data_length;  // We got all the bytes we wanted
+                else
+                    m_end = m_start + bytes_left;   // Not all the bytes requested were available in the shared data
+            }
+        }
+    }
+
+    uint32_t new_size = GetByteSize();
+
+    // Don't hold a shared pointer to the data buffer if we don't share
+    // any valid bytes in the shared buffer.
+    if (new_size == 0)
+        m_data_sp.reset();
+
+    return new_size;
+}
+
+//----------------------------------------------------------------------
+// Extract a single unsigned char from the binary data and update
+// the offset pointed to by "offset_ptr".
+//
+// RETURNS the byte that was extracted, or zero on failure.
+//----------------------------------------------------------------------
+uint8_t
+DataExtractor::GetU8 (uint32_t *offset_ptr) const
+{
+    uint8_t val = 0;
+    if ( m_start < m_end )
+    {
+        val = m_start[*offset_ptr];
+        *offset_ptr += sizeof(val);
+    }
+    return val;
+}
+
+//----------------------------------------------------------------------
+// Extract "count" unsigned chars from the binary data and update the
+// offset pointed to by "offset_ptr". The extracted data is copied into
+// "dst".
+//
+// RETURNS the non-NULL buffer pointer upon successful extraction of
+// all the requested bytes, or NULL when the data is not available in
+// the buffer due to being out of bounds, or unsufficient data.
+//----------------------------------------------------------------------
+void *
+DataExtractor::GetU8 (uint32_t *offset_ptr, void *dst, uint32_t count) const
+{
+    register uint32_t offset = *offset_ptr;
+
+    if ((count > 0) && ValidOffsetForDataOfSize(offset, count) )
+    {
+        // Copy the data into the buffer
+        memcpy (dst, m_start + offset, count);
+        // Advance the offset
+        *offset_ptr += count;
+        // Return a non-NULL pointer to the converted data as an indicator of success
+        return dst;
+    }
+    return NULL;
+}
+
+//----------------------------------------------------------------------
+// Extract a single uint16_t from the data and update the offset
+// pointed to by "offset_ptr".
+//
+// RETURNS the uint16_t that was extracted, or zero on failure.
+//----------------------------------------------------------------------
+uint16_t
+DataExtractor::GetU16 (uint32_t *offset_ptr) const
+{
+    uint16_t val = 0;
+    register uint32_t offset = *offset_ptr;
+    if ( ValidOffsetForDataOfSize(offset, sizeof(val)) )
+    {
+        if (m_byte_order != eByteOrderHost)
+            val = OSReadSwapInt16(m_start, offset);
+        else
+            val = _OSReadInt16 (m_start, offset);
+
+        // Advance the offset
+        *offset_ptr += sizeof(val);
+    }
+    return val;
+}
+
+//----------------------------------------------------------------------
+// Extract "count" uint16_t values from the binary data and update
+// the offset pointed to by "offset_ptr". The extracted data is
+// copied into "dst".
+//
+// RETURNS the non-NULL buffer pointer upon successful extraction of
+// all the requested bytes, or NULL when the data is not available
+// in the buffer due to being out of bounds, or unsufficient data.
+//----------------------------------------------------------------------
+void *
+DataExtractor::GetU16 (uint32_t *offset_ptr, void *void_dst, uint32_t count) const
+{
+    uint16_t *dst = (uint16_t *)void_dst;
+    const size_t value_size = sizeof(*dst);
+    register uint32_t offset = *offset_ptr;
+
+    if ((count > 0) && ValidOffsetForDataOfSize(offset, value_size * count) )
+    {
+        uint16_t *value_ptr;
+        uint16_t *end = dst + count;
+        if (m_byte_order != eByteOrderHost)
+        {
+            for (value_ptr = dst; value_ptr < end; ++value_ptr, offset += value_size)
+                *value_ptr = OSReadSwapInt16 (m_start, offset);
+        }
+        else
+        {
+            for (value_ptr = dst; value_ptr < end; ++value_ptr, offset += value_size)
+                *value_ptr = _OSReadInt16 (m_start, offset);
+        }
+
+        // Advance the offset
+        *offset_ptr = offset;
+        // Return a non-NULL pointer to the converted data as an indicator of success
+        return dst;
+    }
+    return NULL;
+}
+
+//----------------------------------------------------------------------
+// Extract a single uint32_t from the data and update the offset
+// pointed to by "offset_ptr".
+//
+// RETURNS the uint32_t that was extracted, or zero on failure.
+//----------------------------------------------------------------------
+uint32_t
+DataExtractor::GetU32 (uint32_t *offset_ptr) const
+{
+    uint32_t val = 0;
+    register uint32_t offset = *offset_ptr;
+
+    if ( ValidOffsetForDataOfSize(offset, sizeof(val)) )
+    {
+        if (m_byte_order != eByteOrderHost)
+            val = OSReadSwapInt32 (m_start, offset);
+        else
+            val = _OSReadInt32 (m_start, offset);
+
+        // Advance the offset
+        *offset_ptr += sizeof(val);
+    }
+    return val;
+}
+
+//----------------------------------------------------------------------
+// Extract "count" uint32_t values from the binary data and update
+// the offset pointed to by "offset_ptr". The extracted data is
+// copied into "dst".
+//
+// RETURNS the non-NULL buffer pointer upon successful extraction of
+// all the requested bytes, or NULL when the data is not available
+// in the buffer due to being out of bounds, or unsufficient data.
+//----------------------------------------------------------------------
+void *
+DataExtractor::GetU32 (uint32_t *offset_ptr, void *void_dst, uint32_t count) const
+{
+    uint32_t *dst = (uint32_t *)void_dst;
+    const size_t value_size = sizeof(*dst);
+    register uint32_t offset = *offset_ptr;
+
+    if ((count > 0) && ValidOffsetForDataOfSize(offset, value_size * count))
+    {
+        uint32_t *value_ptr;
+        uint32_t *end = dst + count;
+        if (m_byte_order != eByteOrderHost)
+        {
+            for (value_ptr = dst; value_ptr < end; ++value_ptr, offset += value_size)
+                *value_ptr = OSReadSwapInt32 (m_start, offset);
+
+        }
+        else
+        {
+            for (value_ptr = dst; value_ptr < end; ++value_ptr, offset += value_size)
+                *value_ptr = _OSReadInt32 (m_start, offset);
+        }
+
+        // Advance the offset
+        *offset_ptr = offset;
+        // Return a non-NULL pointer to the converted data as an indicator of success
+        return dst;
+    }
+    return NULL;
+}
+
+//----------------------------------------------------------------------
+// Extract a single uint64_t from the data and update the offset
+// pointed to by "offset_ptr".
+//
+// RETURNS the uint64_t that was extracted, or zero on failure.
+//----------------------------------------------------------------------
+uint64_t
+DataExtractor::GetU64 (uint32_t *offset_ptr) const
+{
+    uint64_t val = 0;
+    register uint32_t offset = *offset_ptr;
+    if ( ValidOffsetForDataOfSize(offset, sizeof(val)) )
+    {
+        if (m_byte_order != eByteOrderHost)
+            val = OSReadSwapInt64 (m_start, offset);
+        else
+            val = _OSReadInt64 (m_start, offset);
+
+        // Advance the offset
+        *offset_ptr += sizeof(val);
+    }
+    return val;
+}
+
+//----------------------------------------------------------------------
+// GetU64
+//
+// Get multiple consecutive 64 bit values. Return true if the entire
+// read succeeds and increment the offset pointed to by offset_ptr, else
+// return false and leave the offset pointed to by offset_ptr unchanged.
+//----------------------------------------------------------------------
+void *
+DataExtractor::GetU64 (uint32_t *offset_ptr, void *void_dst, uint32_t count) const
+{
+    uint64_t *dst = (uint64_t *)void_dst;
+    const size_t value_size = sizeof(uint64_t);
+    register uint32_t offset = *offset_ptr;
+
+    if ((count > 0) && ValidOffsetForDataOfSize(offset, value_size * count))
+    {
+        uint64_t *value_ptr;
+        uint64_t *end = dst + count;
+        if (m_byte_order != eByteOrderHost)
+        {
+            for (value_ptr = dst; value_ptr < end; ++value_ptr, offset += value_size)
+                *value_ptr = OSReadSwapInt64 (m_start, offset);
+
+        }
+        else
+        {
+            for (value_ptr = dst; value_ptr < end; ++value_ptr, offset += value_size)
+                *value_ptr = _OSReadInt64 (m_start, offset);
+        }
+
+        // Advance the offset
+        *offset_ptr = offset;
+        // Return a non-NULL pointer to the converted data as an indicator of success
+        return dst;
+    }
+    return NULL;
+}
+
+//----------------------------------------------------------------------
+// Extract a single integer value from the data and update the offset
+// pointed to by "offset_ptr". The size of the extracted integer
+// is specified by the "byte_size" argument. "byte_size" should have
+// a value between 1 and 4 since the return value is only 32 bits
+// wide. Any "byte_size" values less than 1 or greater than 4 will
+// result in nothing being extracted, and zero being returned.
+//
+// RETURNS the integer value that was extracted, or zero on failure.
+//----------------------------------------------------------------------
+uint32_t
+DataExtractor::GetMaxU32 (uint32_t *offset_ptr, uint32_t byte_size) const
+{
+    switch (byte_size)
+    {
+    case 1: return GetU8 (offset_ptr); break;
+    case 2: return GetU16(offset_ptr); break;
+    case 4: return GetU32(offset_ptr); break;
+    default:
+        assert(!"GetMaxU32 unhandled case!");
+        break;
+    }
+    return 0;
+}
+
+//----------------------------------------------------------------------
+// Extract a single integer value from the data and update the offset
+// pointed to by "offset_ptr". The size of the extracted integer
+// is specified by the "byte_size" argument. "byte_size" should have
+// a value >= 1 and <= 8 since the return value is only 64 bits
+// wide. Any "byte_size" values less than 1 or greater than 8 will
+// result in nothing being extracted, and zero being returned.
+//
+// RETURNS the integer value that was extracted, or zero on failure.
+//----------------------------------------------------------------------
+uint64_t
+DataExtractor::GetMaxU64 (uint32_t *offset_ptr, uint32_t size) const
+{
+    switch (size)
+    {
+    case 1: return GetU8 (offset_ptr); break;
+    case 2: return GetU16(offset_ptr); break;
+    case 4: return GetU32(offset_ptr); break;
+    case 8: return GetU64(offset_ptr); break;
+    default:
+        assert(!"GetMax64 unhandled case!");
+        break;
+    }
+    return 0;
+}
+
+int64_t
+DataExtractor::GetMaxS64 (uint32_t *offset_ptr, uint32_t size) const
+{
+    switch (size)
+    {
+    case 1: return (int8_t)GetU8 (offset_ptr); break;
+    case 2: return (int16_t)GetU16(offset_ptr); break;
+    case 4: return (int32_t)GetU32(offset_ptr); break;
+    case 8: return (int64_t)GetU64(offset_ptr); break;
+    default:
+        assert(!"GetMax64 unhandled case!");
+        break;
+    }
+    return 0;
+}
+
+uint64_t
+DataExtractor::GetMaxU64Bitfield (uint32_t *offset_ptr, uint32_t size, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset) const
+{
+    uint64_t uval64 = GetMaxU64 (offset_ptr, size);
+    if (bitfield_bit_size > 0)
+    {
+        if (bitfield_bit_offset > 0)
+            uval64 >>= bitfield_bit_offset;
+        uint64_t bitfield_mask = ((1 << bitfield_bit_size) - 1);
+        uval64 &= bitfield_mask;
+    }
+    return uval64;
+}
+
+int64_t
+DataExtractor::GetMaxS64Bitfield (uint32_t *offset_ptr, uint32_t size, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset) const
+{
+    int64_t sval64 = GetMaxS64 (offset_ptr, size);
+    if (bitfield_bit_size > 0)
+    {
+        if (bitfield_bit_offset > 0)
+            sval64 >>= bitfield_bit_offset;
+        uint64_t bitfield_mask = ((1 << bitfield_bit_size) - 1);
+        sval64 &= bitfield_mask;
+        // sign extend if needed
+        if (sval64 & (1 << (bitfield_bit_size - 1)))
+            sval64 |= ~bitfield_mask;
+    }
+    return sval64;
+}
+
+
+float
+DataExtractor::GetFloat (uint32_t *offset_ptr) const
+{
+    uint32_t val = 0;
+    register uint32_t offset = *offset_ptr;
+
+    if ( ValidOffsetForDataOfSize(offset, sizeof(val)) )
+    {
+        if (m_byte_order != eByteOrderHost)
+            val = OSReadSwapInt32 (m_start, offset);
+        else
+            val = _OSReadInt32 (m_start, offset);
+
+        // Advance the offset
+        *offset_ptr += sizeof(val);
+    }
+    return *((float *)&val);
+}
+
+double
+DataExtractor::GetDouble (uint32_t *offset_ptr) const
+{
+    uint64_t val = 0;
+    register uint32_t offset = *offset_ptr;
+    if ( ValidOffsetForDataOfSize(offset, sizeof(val)) )
+    {
+        if (m_byte_order != eByteOrderHost)
+            val = OSReadSwapInt64 (m_start, offset);
+        else
+            val = _OSReadInt64 (m_start, offset);
+
+        // Advance the offset
+        *offset_ptr += sizeof(val);
+    }
+    return *((double *)&val);
+
+}
+
+
+long double
+DataExtractor::GetLongDouble (uint32_t *offset_ptr) const
+{
+    if (sizeof(long double) == sizeof(uint64_t))
+    {
+        uint64_t val = 0;
+        register uint32_t offset = *offset_ptr;
+        if ( ValidOffsetForDataOfSize(offset, sizeof(val)) )
+        {
+            if (m_byte_order != eByteOrderHost)
+                val = OSReadSwapInt64 (m_start, offset);
+            else
+                val = _OSReadInt64 (m_start, offset);
+
+            // Advance the offset
+            *offset_ptr += sizeof(val);
+        }
+        return *((long double *)&val);
+    }
+    return 0.0;
+}
+
+
+//------------------------------------------------------------------
+// Extract a single address from the data and update the offset
+// pointed to by "offset_ptr". The size of the extracted address
+// comes from the "this->m_addr_size" member variable and should be
+// set correctly prior to extracting any address values.
+//
+// RETURNS the address that was extracted, or zero on failure.
+//------------------------------------------------------------------
+uint64_t
+DataExtractor::GetAddress (uint32_t *offset_ptr) const
+{
+    return GetMaxU64 (offset_ptr, m_addr_size);
+}
+
+//------------------------------------------------------------------
+// Extract a single pointer from the data and update the offset
+// pointed to by "offset_ptr". The size of the extracted pointer
+// comes from the "this->m_addr_size" member variable and should be
+// set correctly prior to extracting any pointer values.
+//
+// RETURNS the pointer that was extracted, or zero on failure.
+//------------------------------------------------------------------
+uint64_t
+DataExtractor::GetPointer (uint32_t *offset_ptr) const
+{
+    return GetMaxU64 (offset_ptr, m_addr_size);
+}
+
+//----------------------------------------------------------------------
+// GetDwarfEHPtr
+//
+// Used for calls when the value type is specified by a DWARF EH Frame
+// pointer encoding.
+//----------------------------------------------------------------------
+
+uint64_t
+DataExtractor::GetGNUEHPointer (uint32_t *offset_ptr, uint32_t eh_ptr_enc, lldb::addr_t pc_rel_addr, lldb::addr_t text_addr, lldb::addr_t data_addr)//, BSDRelocs *data_relocs) const
+{
+    if (eh_ptr_enc == DW_GNU_EH_PE_omit)
+        return ULONG_LONG_MAX;  // Value isn't in the buffer...
+
+    uint64_t baseAddress = 0;
+    uint64_t addressValue = 0;
+    const uint32_t addr_size = GetAddressByteSize();
+
+    bool signExtendValue = false;
+    // Decode the base part or adjust our offset
+    switch (eh_ptr_enc & 0x70)
+    {
+    case DW_GNU_EH_PE_pcrel:
+        signExtendValue = true;
+        baseAddress = *offset_ptr;
+        if (pc_rel_addr != LLDB_INVALID_ADDRESS)
+            baseAddress += pc_rel_addr;
+//      else
+//          Log::GlobalWarning ("PC relative pointer encoding found with invalid pc relative address.");
+        break;
+
+    case DW_GNU_EH_PE_textrel:
+        signExtendValue = true;
+        if (text_addr != LLDB_INVALID_ADDRESS)
+            baseAddress = text_addr;
+//      else
+//          Log::GlobalWarning ("text relative pointer encoding being decoded with invalid text section address, setting base address to zero.");
+        break;
+
+    case DW_GNU_EH_PE_datarel:
+        signExtendValue = true;
+        if (data_addr != LLDB_INVALID_ADDRESS)
+            baseAddress = data_addr;
+//      else
+//          Log::GlobalWarning ("data relative pointer encoding being decoded with invalid data section address, setting base address to zero.");
+        break;
+
+    case DW_GNU_EH_PE_funcrel:
+        signExtendValue = true;
+        break;
+
+    case DW_GNU_EH_PE_aligned:
+        {
+            // SetPointerSize should be called prior to extracting these so the
+            // pointer size is cached
+            assert(addr_size != 0);
+            if (addr_size)
+            {
+                // Align to a address size boundary first
+                uint32_t alignOffset = *offset_ptr % addr_size;
+                if (alignOffset)
+                    offset_ptr += addr_size - alignOffset;
+            }
+        }
+        break;
+
+    default:
+    break;
+    }
+
+    // Decode the value part
+    switch (eh_ptr_enc & DW_GNU_EH_PE_MASK_ENCODING)
+    {
+    case DW_GNU_EH_PE_absptr    :
+        {
+            addressValue = GetAddress (offset_ptr);
+//          if (data_relocs)
+//              addressValue = data_relocs->Relocate(*offset_ptr - addr_size, *this, addressValue);
+        }
+        break;
+    case DW_GNU_EH_PE_uleb128   : addressValue = GetULEB128(offset_ptr);        break;
+    case DW_GNU_EH_PE_udata2    : addressValue = GetU16(offset_ptr);            break;
+    case DW_GNU_EH_PE_udata4    : addressValue = GetU32(offset_ptr);            break;
+    case DW_GNU_EH_PE_udata8    : addressValue = GetU64(offset_ptr);            break;
+    case DW_GNU_EH_PE_sleb128   : addressValue = GetSLEB128(offset_ptr);        break;
+    case DW_GNU_EH_PE_sdata2    : addressValue = (int16_t)GetU16(offset_ptr);   break;
+    case DW_GNU_EH_PE_sdata4    : addressValue = (int32_t)GetU32(offset_ptr);   break;
+    case DW_GNU_EH_PE_sdata8    : addressValue = (int64_t)GetU64(offset_ptr);   break;
+    default:
+    // Unhandled encoding type
+    assert(eh_ptr_enc);
+    break;
+    }
+
+    // Since we promote everything to 64 bit, we may need to sign extend
+    if (signExtendValue && addr_size < sizeof(baseAddress))
+    {
+        uint64_t sign_bit = 1ull << ((addr_size * 8ull) - 1ull);
+        if (sign_bit & addressValue)
+        {
+            uint64_t mask = ~sign_bit + 1;
+            addressValue |= mask;
+        }
+    }
+    return baseAddress + addressValue;
+}
+
+size_t
+DataExtractor::ExtractBytes (uint32_t offset, uint32_t length, ByteOrder dst_byte_order, void *dst) const
+{
+    const uint8_t *src = PeekData (offset, length);
+    if (src)
+    {
+        if (dst_byte_order != GetByteOrder())
+        {
+            for (uint32_t i=0; i<length; ++i)
+                ((uint8_t*)dst)[i] = src[length - i - 1];
+        }
+        else
+            ::memcpy (dst, src, length);
+        return length;
+    }
+    return 0;
+}
+//----------------------------------------------------------------------
+// Peeks at bytes in the contained data.
+//
+// Returns a valid pointer to bytes if "offset" is a valid offset in
+// and there are "length" bytes available, else NULL is returned.
+//----------------------------------------------------------------------
+const uint8_t*
+DataExtractor::PeekData (uint32_t offset, uint32_t length) const
+{
+    if ( length > 0 && ValidOffsetForDataOfSize(offset, length) )
+        return m_start + offset;
+    return NULL;
+}
+
+//----------------------------------------------------------------------
+// Returns a pointer to a bytes in this object's data at the offset
+// pointed to by "offset_ptr". If "length" is zero or too large,
+// then the offset pointed to by "offset_ptr" will not be updated
+// and NULL will be returned.
+//
+// Returns a pointer to the data if the offset and length are valid,
+// or NULL otherwise.
+//----------------------------------------------------------------------
+const void*
+DataExtractor::GetData (uint32_t *offset_ptr, uint32_t length) const
+{
+    const uint8_t* bytes = NULL;
+    register uint32_t offset = *offset_ptr;
+    if ( length > 0 && ValidOffsetForDataOfSize(offset, length) )
+    {
+        bytes = m_start + offset;
+        *offset_ptr = offset + length;
+    }
+    return bytes;
+}
+
+//----------------------------------------------------------------------
+// Extracts a AsCString (fixed length, or variable length) from
+// the data at the offset pointed to by "offset_ptr". If
+// "length" is zero, then a variable length NULL terminated C
+// string will be extracted from the data the "offset_ptr" will be
+// updated with the offset of the byte that follows the NULL
+// terminator byte. If "length" is greater than zero, then
+// the function will make sure there are "length" bytes
+// available in the current data and if so, return a valid pointer.
+//
+// If the offset pointed to by "offset_ptr" is out of bounds, or if
+// "length" is non-zero and there aren't enough avaialable
+// bytes, NULL will be returned and "offset_ptr" will not be
+// updated.
+//----------------------------------------------------------------------
+const char*
+DataExtractor::GetCStr (uint32_t *offset_ptr) const
+{
+    const char *s = NULL;
+    if ( m_start < m_end )
+    {
+        s = (char*)m_start + *offset_ptr;
+
+        size_t length = strlen(s) + 1;
+
+        if (!ValidOffsetForDataOfSize(*offset_ptr, length))
+            return NULL;
+
+        // Advance the offset
+        *offset_ptr += length;
+    }
+    return s;
+}
+
+//------------------------------------------------------------------
+// Peeks at a string in the contained data. No verification is done
+// to make sure the entire string lies within the bounds of this
+// object's data, only "offset" is verified to be a valid offset.
+//
+// Returns a valid C string pointer if "offset" is a valid offset in
+// this object's data, else NULL is returned.
+//------------------------------------------------------------------
+const char *
+DataExtractor::PeekCStr (uint32_t offset) const
+{
+    if (ValidOffset (offset))
+        return (const char*)m_start + offset;
+    return NULL;
+}
+
+//----------------------------------------------------------------------
+// Extracts an unsigned LEB128 number from this object's data
+// starting at the offset pointed to by "offset_ptr". The offset
+// pointed to by "offset_ptr" will be updated with the offset of the
+// byte following the last extracted byte.
+//
+// Returned the extracted integer value.
+//----------------------------------------------------------------------
+uint64_t
+DataExtractor::GetULEB128 (uint32_t *offset_ptr) const
+{
+    uint64_t result = 0;
+    if ( m_start < m_end )
+    {
+        int shift = 0;
+        const uint8_t *src = m_start + *offset_ptr;
+        uint8_t byte;
+        int bytecount = 0;
+
+        while (src < m_end)
+        {
+            bytecount++;
+            byte = *src++;
+            result |= (byte & 0x7f) << shift;
+            shift += 7;
+            if ((byte & 0x80) == 0)
+                break;
+        }
+
+        *offset_ptr += bytecount;
+    }
+    return result;
+}
+
+//----------------------------------------------------------------------
+// Extracts an signed LEB128 number from this object's data
+// starting at the offset pointed to by "offset_ptr". The offset
+// pointed to by "offset_ptr" will be updated with the offset of the
+// byte following the last extracted byte.
+//
+// Returned the extracted integer value.
+//----------------------------------------------------------------------
+int64_t
+DataExtractor::GetSLEB128 (uint32_t *offset_ptr) const
+{
+    int64_t result = 0;
+
+    if ( m_start < m_end )
+    {
+        int shift = 0;
+        int size = sizeof (uint32_t) * 8;
+        const uint8_t *src = m_start + *offset_ptr;
+
+        uint8_t byte;
+        int bytecount = 0;
+
+        while (src < m_end)
+        {
+            bytecount++;
+            byte = *src++;
+            result |= (byte & 0x7f) << shift;
+            shift += 7;
+            if ((byte & 0x80) == 0)
+                break;
+        }
+
+        // Sign bit of byte is 2nd high order bit (0x40)
+        if (shift < size && (byte & 0x40))
+            result |= - (1 << shift);
+
+        *offset_ptr += bytecount;
+    }
+    return result;
+}
+
+//----------------------------------------------------------------------
+// Skips a ULEB128 number (signed or unsigned) from this object's
+// data starting at the offset pointed to by "offset_ptr". The
+// offset pointed to by "offset_ptr" will be updated with the offset
+// of the byte following the last extracted byte.
+//
+// Returns the number of bytes consumed during the extraction.
+//----------------------------------------------------------------------
+uint32_t
+DataExtractor::Skip_LEB128 (uint32_t *offset_ptr) const
+{
+    uint32_t bytes_consumed = 0;
+    if ( m_start < m_end )
+    {
+        const uint8_t *start = m_start + *offset_ptr;
+        const uint8_t *src = start;
+
+        while ((src < m_end) && (*src++ & 0x80))
+            ++bytes_consumed;
+
+        *offset_ptr += src - start;
+    }
+    return bytes_consumed;
+}
+
+uint32_t
+DataExtractor::Dump
+(
+    Stream *s,
+    uint32_t start_offset,
+    lldb::Format item_format,
+    uint32_t item_byte_size,
+    uint32_t item_count,
+    uint32_t num_per_line,
+    uint64_t base_addr,
+    uint32_t item_bit_size,     // If zero, this is not a bitfield value, if non-zero, the value is a bitfield
+    uint32_t item_bit_offset    // If "item_bit_size" is non-zero, this is the shift amount to apply to a bitfield
+) const
+{
+    if (s == NULL)
+        return start_offset;
+
+    uint32_t offset;
+    uint32_t count;
+    uint32_t line_start_offset;
+
+    if (item_format == eFormatPointer)
+    {
+        if (item_byte_size != 4 && item_byte_size != 8)
+            item_byte_size = s->GetAddressByteSize();
+    }
+
+    for (offset = start_offset, line_start_offset = start_offset, count = 0; ValidOffset(offset) && count < item_count; ++count)
+    {
+        if ((count % num_per_line) == 0)
+        {
+            if (count > 0)
+            {
+                if (item_format == eFormatBytesWithASCII && offset > line_start_offset)
+                {
+                    s->Printf("%*s", (num_per_line - (offset - line_start_offset)) * 3 + 2, "");
+                    Dump(s, line_start_offset, eFormatCharPrintable, 1, offset - line_start_offset, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
+                }
+                s->EOL();
+            }
+            if (base_addr != LLDB_INVALID_ADDRESS)
+                s->Printf ("0x%8.8llx: ", (uint64_t)(base_addr + (offset - start_offset)));
+            line_start_offset = offset;
+        }
+        else
+        if (item_format != eFormatChar &&
+            item_format != eFormatCharPrintable &&
+            count > 0)
+        {
+            s->PutChar(' ');
+        }
+
+        uint32_t i;
+        switch (item_format)
+        {
+        case eFormatBoolean:
+            s->Printf ("%s", GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset) ? "true" : "false");
+            break;
+
+        case eFormatBinary:
+            {
+                uint64_t uval64 = GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset);
+                std::string binary_value(std::bitset<64>(uval64).to_string());
+                if (item_bit_size > 0)
+                    s->Printf("0b%s", binary_value.c_str() + 64 - item_bit_size);
+                else if (item_byte_size > 0 && item_byte_size <= 8)
+                    s->Printf("0b%s", binary_value.c_str() + 64 - item_byte_size * 8);
+            }
+            break;
+
+        case eFormatBytes:
+        case eFormatBytesWithASCII:
+            for (i=0; i<item_byte_size; ++i)
+            {
+                s->Printf ("%2.2x", GetU8(&offset));
+            }
+            // Put an extra space between the groups of bytes if more than one
+            // is being dumped in a group (item_byte_size is more than 1).
+            if (item_byte_size > 1)
+                s->PutChar(' ');
+            break;
+
+        case eFormatChar:
+        case eFormatCharPrintable:
+            {
+                // If we are only printing one character surround it with single
+                // quotes
+                if (item_count == 1 && item_format == eFormatChar)
+                    s->PutChar('\'');
+
+                uint8_t ch = GetU8(&offset);
+                if (isprint(ch))
+                    s->Printf ("%c", ch);
+                else if (item_format == eFormatChar)
+                {
+                    switch (ch)
+                    {
+                    case '\e': s->Printf ("\\e", (uint8_t)ch); break;
+                    case '\a': s->Printf ("\\a", ch); break;
+                    case '\b': s->Printf ("\\b", ch); break;
+                    case '\f': s->Printf ("\\f", ch); break;
+                    case '\n': s->Printf ("\\n", ch); break;
+                    case '\r': s->Printf ("\\r", ch); break;
+                    case '\t': s->Printf ("\\t", ch); break;
+                    case '\v': s->Printf ("\\v", ch); break;
+                    case '\0': s->Printf ("\\0", ch); break;
+                    default:   s->Printf ("\\x%2.2x", ch); break;
+                    }
+                }
+                else
+                {
+                    s->PutChar(NON_PRINTABLE_CHAR);
+                }
+
+                // If we are only printing one character surround it with single quotes
+                if (item_count == 1 && item_format == eFormatChar)
+                    s->PutChar('\'');
+            }
+            break;
+
+        case eFormatComplex:
+            if (sizeof(float) * 2 == item_byte_size)
+            {
+                uint32_t a32 = GetU32(&offset);
+                uint32_t b32 = GetU32(&offset);
+
+                s->Printf ("%g + %gi", a32, b32);
+            }
+            else if (sizeof(double) * 2 == item_byte_size)
+            {
+                uint64_t a64 = GetU64(&offset);
+                uint64_t b64 = GetU64(&offset);
+
+                s->Printf ("%lg + %lgi", a64, b64);
+            }
+            else if (sizeof(long double) * 2 == item_byte_size && sizeof(long double) <= sizeof(uint64_t))
+            {
+                uint64_t a64 = GetU64(&offset);
+                uint64_t b64 = GetU64(&offset);
+                s->Printf ("%Lg + %Lgi", a64, b64);
+            }
+            break;
+
+        case eFormatDecimal:
+            if (item_byte_size <= 8);
+                s->Printf ("%lld", GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset));
+            break;
+
+        case eFormatUnsigned:
+            if (item_byte_size <= 8);
+                s->Printf ("%llu", GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset));
+            break;
+
+        case eFormatOctal:
+            if (item_byte_size <= 8);
+                s->Printf ("0%llo", GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset));
+            break;
+
+        case eFormatEnum:
+            // Print enum value as a signed integer when we don't get the enum type
+            s->Printf ("%lld", GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset));
+            break;
+
+        case eFormatCString:
+            {
+                const char *cstr = GetCStr(&offset);
+                if (cstr)
+                    s->Printf("\"%s\"", cstr);
+                else
+                {
+                    s->Printf("NULL", cstr);
+                    offset = UINT32_MAX;
+                }
+            }
+            break;
+
+
+        case eFormatPointer:
+            s->Address(GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset), sizeof (addr_t));
+            break;
+
+        case eFormatHex:
+            if (item_byte_size <= 8)
+            {
+                s->Printf("0x%*.*llx", 2 * item_byte_size, 2 * item_byte_size, GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset));
+            }
+            else
+            {
+                assert (item_bit_size == 0 && item_bit_offset == 0);
+                s->PutCString("0x");
+                int32_t start_idx, end_idx, delta;
+                if (m_byte_order == eByteOrderBig)
+                {
+                    start_idx = offset;
+                    end_idx = offset + item_byte_size;
+                    delta = 1;
+                }
+                else
+                {
+                    start_idx = offset + item_byte_size - 1;
+                    end_idx = -1;
+                    delta = -1;
+                }
+                const uint8_t *bytes = (const uint8_t* )GetData(&offset, item_byte_size);
+                if (bytes)
+                {
+                    for (int32_t idx = start_idx; idx != end_idx; idx += delta)
+                        s->Printf("%2.2x", bytes[idx]);
+                }
+            }
+            break;
+
+        case eFormatFloat:
+            if (sizeof(float) == item_byte_size)
+            {
+                uint32_t a32 = GetU32(&offset);
+                s->Printf ("%g", (double)(*((float *)&a32)));
+            }
+            else if (sizeof(double) == item_byte_size)
+            {
+                uint64_t a64 = GetU64(&offset);
+                s->Printf ("%lg", (*((double *)&a64)));
+            }
+            else if (sizeof(long double) == item_byte_size && sizeof(long double) <= sizeof(uint64_t))
+            {
+                uint64_t a64 = GetU64(&offset);
+                s->Printf ("%Lg", (*((long double *)&a64)));
+            }
+            break;
+
+        case eFormatUnicode16:
+            s->Printf("0x%4.4x", GetU16 (&offset));
+            break;
+
+        case eFormatUnicode32:
+            s->Printf("0x%8.8x", GetU32 (&offset));
+            break;
+
+        case eFormatVectorOfChar:
+            s->PutChar('{');
+            offset = Dump (s, start_offset, eFormatChar, 1, item_byte_size, item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
+            s->PutChar('}');
+            break;
+
+        case eFormatVectorOfSInt8:
+            s->PutChar('{');
+            offset = Dump (s, start_offset, eFormatDecimal, 1, item_byte_size, item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
+            s->PutChar('}');
+            break;
+
+        case eFormatVectorOfUInt8:
+            s->PutChar('{');
+            offset = Dump (s, start_offset, eFormatHex, 1, item_byte_size, item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
+            s->PutChar('}');
+            break;
+
+        case eFormatVectorOfSInt16:
+            s->PutChar('{');
+            offset = Dump (s, start_offset, eFormatDecimal, sizeof(uint16_t), item_byte_size / sizeof(uint16_t), item_byte_size / sizeof(uint16_t), LLDB_INVALID_ADDRESS, 0, 0);
+            s->PutChar('}');
+            break;
+
+        case eFormatVectorOfUInt16:
+            s->PutChar('{');
+            offset = Dump (s, start_offset, eFormatHex,     sizeof(uint16_t), item_byte_size / sizeof(uint16_t), item_byte_size / sizeof(uint16_t), LLDB_INVALID_ADDRESS, 0, 0);
+            s->PutChar('}');
+            break;
+
+        case eFormatVectorOfSInt32:
+            s->PutChar('{');
+            offset = Dump (s, start_offset, eFormatDecimal, sizeof(uint32_t), item_byte_size / sizeof(uint32_t), item_byte_size / sizeof(uint32_t), LLDB_INVALID_ADDRESS, 0, 0);
+            s->PutChar('}');
+            break;
+
+        case eFormatVectorOfUInt32:
+            s->PutChar('{');
+            offset = Dump (s, start_offset, eFormatHex,     sizeof(uint32_t), item_byte_size / sizeof(uint32_t), item_byte_size / sizeof(uint32_t), LLDB_INVALID_ADDRESS, 0, 0);
+            s->PutChar('}');
+            break;
+
+        case eFormatVectorOfSInt64:
+            s->PutChar('{');
+            offset = Dump (s, start_offset, eFormatDecimal, sizeof(uint64_t), item_byte_size / sizeof(uint64_t), item_byte_size / sizeof(uint64_t), LLDB_INVALID_ADDRESS, 0, 0);
+            s->PutChar('}');
+            break;
+
+        case eFormatVectorOfUInt64:
+            s->PutChar('{');
+            offset = Dump (s, start_offset, eFormatHex,     sizeof(uint32_t), item_byte_size / sizeof(uint32_t), item_byte_size / sizeof(uint32_t), LLDB_INVALID_ADDRESS, 0, 0);
+            s->PutChar('}');
+            break;
+
+        case eFormatVectorOfFloat32:
+            s->PutChar('{');
+            offset = Dump (s, start_offset, eFormatFloat,       4, item_byte_size / 4, item_byte_size / 4, LLDB_INVALID_ADDRESS, 0, 0);
+            s->PutChar('}');
+            break;
+
+        case eFormatVectorOfFloat64:
+            s->PutChar('{');
+            offset = Dump (s, start_offset, eFormatFloat,       8, item_byte_size / 8, item_byte_size / 8, LLDB_INVALID_ADDRESS, 0, 0);
+            s->PutChar('}');
+            break;
+
+        case eFormatVectorOfUInt128:
+            s->PutChar('{');
+            offset = Dump (s, start_offset, eFormatHex, 16, item_byte_size / 16, item_byte_size / 16, LLDB_INVALID_ADDRESS, 0, 0);
+            s->PutChar('}');
+            break;
+        }
+    }
+
+    if (item_format == eFormatBytesWithASCII && offset > line_start_offset)
+    {
+        s->Printf("%*s", (num_per_line - (offset - line_start_offset)) * 3 + 2, "");
+        Dump(s, line_start_offset, eFormatCharPrintable, 1, offset - line_start_offset, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
+    }
+    return offset;  // Return the offset at which we ended up
+}
+
+//----------------------------------------------------------------------
+// Dumps bytes from this object's data to the stream "s" starting
+// "start_offset" bytes into this data, and ending with the byte
+// before "end_offset". "base_addr" will be added to the offset
+// into the dumped data when showing the offset into the data in the
+// output information. "num_per_line" objects of type "type" will
+// be dumped with the option to override the format for each object
+// with "type_format". "type_format" is a printf style formatting
+// string. If "type_format" is NULL, then an appropriate format
+// string will be used for the supplied "type". If the stream "s"
+// is NULL, then the output will be send to Log().
+//----------------------------------------------------------------------
+uint32_t
+DataExtractor::PutToLog
+(
+    Log *log,
+    uint32_t start_offset,
+    uint32_t length,
+    uint64_t base_addr,
+    uint32_t num_per_line,
+    DataExtractor::Type type,
+    const char *format
+) const
+{
+    if (log == NULL)
+        return start_offset;
+
+    uint32_t offset;
+    uint32_t end_offset = offset + length;
+    uint32_t count;
+    StreamString sstr;
+    for (offset = start_offset, count = 0; ValidOffset(offset) && offset < end_offset; ++count)
+    {
+        if ((count % num_per_line) == 0)
+        {
+            // Print out any previous string
+            if (sstr.GetSize() > 0)
+            {
+                log->Printf("%s", sstr.GetData());
+                sstr.Clear();
+            }
+            // Reset string offset and fill the current line string with address:
+            if (base_addr != LLDB_INVALID_ADDRESS)
+                sstr.Printf("0x%8.8llx:", (uint64_t)(base_addr + (offset - start_offset)));
+        }
+
+        switch (type)
+        {
+            default:
+            case TypeUInt8:   sstr.Printf (format ? format : " %2.2x", GetU8(&offset)); break;
+            case TypeChar:
+                {
+                    char ch = GetU8(&offset);
+                    sstr.Printf (format ? format : " %c",    isprint(ch) ? ch : ' ');
+                }
+                break;
+            case TypeUInt16:  sstr.Printf (format ? format : " %4.4x",       GetU16(&offset)); break;
+            case TypeUInt32:  sstr.Printf (format ? format : " %8.8x",       GetU32(&offset)); break;
+            case TypeUInt64:  sstr.Printf (format ? format : " %16.16llx",   GetU64(&offset)); break;
+            case TypePointer: sstr.Printf (format ? format : " 0x%llx",      GetAddress(&offset)); break;
+            case TypeULEB128: sstr.Printf (format ? format : " 0x%llx",      GetULEB128(&offset)); break;
+            case TypeSLEB128: sstr.Printf (format ? format : " %lld",        GetSLEB128(&offset)); break;
+        }
+    }
+
+    if (sstr.GetSize() > 0)
+        log->Printf("%s", sstr.GetData());
+
+    return offset;  // Return the offset at which we ended up
+}
+
+//----------------------------------------------------------------------
+// DumpUUID
+//
+// Dump out a UUID starting at 'offset' bytes into the buffer
+//----------------------------------------------------------------------
+void
+DataExtractor::DumpUUID (Stream *s, uint32_t offset) const
+{
+    if (s)
+    {
+        const uint8_t *uuid_data = PeekData(offset, 16);
+        if ( uuid_data )
+        {
+            UUID uuid(uuid_data, 16);
+            uuid.Dump(s);
+        }
+        else
+        {
+            s->Printf("<not enough data for UUID at offset 0x%8.8x>", offset);
+        }
+    }
+}
+
+
diff --git a/source/Core/Debugger.cpp b/source/Core/Debugger.cpp
new file mode 100644
index 0000000..c106d83
--- /dev/null
+++ b/source/Core/Debugger.cpp
@@ -0,0 +1,434 @@
+//===-- Debugger.cpp --------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ConnectionFileDescriptor.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/InputReader.h"
+#include "lldb/Core/State.h"
+#include "lldb/Core/Timer.h"
+
+#include "lldb/Target/TargetList.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+
+
+using namespace lldb;
+using namespace lldb_private;
+
+int Debugger::g_shared_debugger_refcount = 0;
+bool Debugger::g_in_terminate = false;
+
+Debugger::DebuggerSP &
+Debugger::GetDebuggerSP ()
+{
+    static DebuggerSP g_shared_debugger_sp;
+    return g_shared_debugger_sp;
+}
+
+void
+Debugger::Initialize ()
+{
+    g_shared_debugger_refcount++;
+    if (GetDebuggerSP().get() == NULL)
+    {
+        GetDebuggerSP().reset (new Debugger());
+        lldb_private::Initialize();
+        GetDebuggerSP()->GetCommandInterpreter().Initialize();
+    }
+}
+
+void
+Debugger::Terminate ()
+{
+    g_shared_debugger_refcount--;
+    if (g_shared_debugger_refcount == 0)
+    {
+        // Because Terminate is called also in the destructor, we need to make sure
+        // that none of the calls to GetSharedInstance leads to a call to Initialize,
+        // thus bumping the refcount back to 1 & causing Debugger::~Debugger to try to 
+        // re-terminate.  So we use g_in_terminate to indicate this condition.
+        // When we can require at least Initialize to be called, we won't have to do
+        // this since then the GetSharedInstance won't have to auto-call Initialize...
+        
+        g_in_terminate = true;
+        int num_targets = GetDebuggerSP()->GetTargetList().GetNumTargets();
+        for (int i = 0; i < num_targets; i++)
+        {
+            ProcessSP process_sp(GetDebuggerSP()->GetTargetList().GetTargetAtIndex (i)->GetProcessSP());
+            if (process_sp)
+                process_sp->Destroy();
+        }
+        GetDebuggerSP()->DisconnectInput();
+        lldb_private::WillTerminate();
+        GetDebuggerSP().reset();
+    }
+}
+
+Debugger &
+Debugger::GetSharedInstance()
+{
+    // Don't worry about thread race conditions with the code below as
+    // lldb_private::Initialize(); does this in a thread safe way. I just
+    // want to avoid having to lock and unlock a mutex in
+    // lldb_private::Initialize(); every time we want to access the
+    // Debugger shared instance.
+    
+    // FIXME: We intend to require clients to call Initialize by hand (since they
+    // will also have to call Terminate by hand.)  But for now it is not clear where
+    // we can reliably call these in JH.  So the present version initializes on first use
+    // here, and terminates in the destructor.
+    if (g_shared_debugger_refcount == 0 && !g_in_terminate)
+        Initialize();
+        
+    assert(GetDebuggerSP().get()!= NULL);
+    return *(GetDebuggerSP().get());
+}
+
+Debugger::Debugger () :
+    m_input_comm("debugger.input"),
+    m_input_file (),
+    m_output_file (),
+    m_error_file (),
+    m_async_execution (true),
+    m_target_list (),
+    m_listener ("lldb.Debugger"),
+    m_source_manager (),
+    m_command_interpreter (eScriptLanguageDefault, false, &m_listener, m_source_manager),
+    m_input_readers (),
+    m_input_reader_data ()
+{
+}
+
+Debugger::~Debugger ()
+{
+    // FIXME:
+    // Remove this once this version of lldb has made its way through a build.
+    Terminate();
+}
+
+
+bool
+Debugger::GetAsyncExecution ()
+{
+    return m_async_execution;
+}
+
+void
+Debugger::SetAsyncExecution (bool async_execution)
+{
+    static bool value_has_been_set = false;
+
+    if (!value_has_been_set)
+    {
+        value_has_been_set = true;
+        m_async_execution = async_execution;
+        m_command_interpreter.SetSynchronous (!async_execution);
+    }
+}
+
+void
+Debugger::DisconnectInput()
+{
+    m_input_comm.Clear ();
+}
+    
+void
+Debugger::SetInputFileHandle (FILE *fh, bool tranfer_ownership)
+{
+    m_input_file.SetFileHandle (fh, tranfer_ownership);
+    if (m_input_file.GetFileHandle() == NULL)
+        m_input_file.SetFileHandle (stdin, false);
+
+    // Disconnect from any old connection if we had one
+    m_input_comm.Disconnect ();
+    m_input_comm.SetConnection (new ConnectionFileDescriptor (::fileno (GetInputFileHandle()), true));
+    m_input_comm.SetReadThreadBytesReceivedCallback (Debugger::DispatchInputCallback, this);
+
+    Error error;
+    if (m_input_comm.StartReadThread (&error) == false)
+    {
+        FILE *err_fh = GetErrorFileHandle();
+        if (err_fh)
+        {
+            ::fprintf (err_fh, "error: failed to main input read thread: %s", error.AsCString() ? error.AsCString() : "unkown error");
+            exit(1);
+        }
+    }
+
+}
+
+FILE *
+Debugger::GetInputFileHandle ()
+{
+    return m_input_file.GetFileHandle();
+}
+
+
+void
+Debugger::SetOutputFileHandle (FILE *fh, bool tranfer_ownership)
+{
+    m_output_file.SetFileHandle (fh, tranfer_ownership);
+    if (m_output_file.GetFileHandle() == NULL)
+        m_output_file.SetFileHandle (stdin, false);
+}
+
+FILE *
+Debugger::GetOutputFileHandle ()
+{
+    return m_output_file.GetFileHandle();
+}
+
+void
+Debugger::SetErrorFileHandle (FILE *fh, bool tranfer_ownership)
+{
+    m_error_file.SetFileHandle (fh, tranfer_ownership);
+    if (m_error_file.GetFileHandle() == NULL)
+        m_error_file.SetFileHandle (stdin, false);
+}
+
+
+FILE *
+Debugger::GetErrorFileHandle ()
+{
+    return m_error_file.GetFileHandle();
+}
+
+CommandInterpreter &
+Debugger::GetCommandInterpreter ()
+{
+    return m_command_interpreter;
+}
+
+Listener &
+Debugger::GetListener ()
+{
+    return m_listener;
+}
+
+
+TargetSP
+Debugger::GetCurrentTarget ()
+{
+    return m_target_list.GetCurrentTarget ();
+}
+
+ExecutionContext
+Debugger::GetCurrentExecutionContext ()
+{
+    ExecutionContext exe_ctx;
+    exe_ctx.Clear();
+    
+    lldb::TargetSP target_sp = GetCurrentTarget();
+    exe_ctx.target = target_sp.get();
+    
+    if (target_sp)
+    {
+        exe_ctx.process = target_sp->GetProcessSP().get();
+        if (exe_ctx.process && exe_ctx.process->IsRunning() == false)
+        {
+            exe_ctx.thread = exe_ctx.process->GetThreadList().GetCurrentThread().get();
+            if (exe_ctx.thread == NULL)
+                exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
+            if (exe_ctx.thread)
+            {
+                exe_ctx.frame = exe_ctx.thread->GetCurrentFrame().get();
+                if (exe_ctx.frame == NULL)
+                    exe_ctx.frame = exe_ctx.thread->GetStackFrameAtIndex (0).get();
+            }
+        }
+    }
+    return exe_ctx;
+
+}
+
+SourceManager &
+Debugger::GetSourceManager ()
+{
+    return m_source_manager;
+}
+
+
+TargetList&
+Debugger::GetTargetList ()
+{
+    return m_target_list;
+}
+
+void
+Debugger::DispatchInputCallback (void *baton, const void *bytes, size_t bytes_len)
+{
+    ((Debugger *)baton)->DispatchInput ((char *)bytes, bytes_len);
+}
+
+
+void
+Debugger::DispatchInput (const char *bytes, size_t bytes_len)
+{
+    if (bytes == NULL || bytes_len == 0)
+        return;
+
+    // TODO: implement the STDIO to the process as an input reader...
+    TargetSP target = GetCurrentTarget();
+    if (target.get() != NULL)
+    {
+        ProcessSP process_sp = target->GetProcessSP();
+        if (process_sp.get() != NULL
+            && StateIsRunningState (process_sp->GetState()))
+        {
+            Error error;
+            if (process_sp->PutSTDIN (bytes, bytes_len, error) == bytes_len)
+                return;
+        }
+    }
+
+    WriteToDefaultReader (bytes, bytes_len);
+}
+
+void
+Debugger::WriteToDefaultReader (const char *bytes, size_t bytes_len)
+{
+    if (bytes && bytes_len)
+        m_input_reader_data.append (bytes, bytes_len);
+
+    if (m_input_reader_data.empty())
+        return;
+
+    while (!m_input_readers.empty() && !m_input_reader_data.empty())
+    {
+        while (CheckIfTopInputReaderIsDone ())
+            /* Do nothing. */;
+        
+        // Get the input reader from the top of the stack
+        InputReaderSP reader_sp(m_input_readers.top());
+        
+        if (!reader_sp)
+            break;
+
+        size_t bytes_handled = reader_sp->HandleRawBytes (m_input_reader_data.data(), 
+                                                          m_input_reader_data.size());
+        if (bytes_handled)
+        {
+            m_input_reader_data.erase (0, bytes_handled);
+        }
+        else
+        {
+            // No bytes were handled, we might not have reached our 
+            // granularity, just return and wait for more data
+            break;
+        }
+    }
+    
+    // Flush out any input readers that are donesvn
+    while (CheckIfTopInputReaderIsDone ())
+        /* Do nothing. */;
+
+}
+
+void
+Debugger::PushInputReader (const InputReaderSP& reader_sp)
+{
+    if (!reader_sp)
+        return;
+    if (!m_input_readers.empty())
+    {
+        // Deactivate the old top reader
+        InputReaderSP top_reader_sp (m_input_readers.top());
+        if (top_reader_sp)
+            top_reader_sp->Notify (eInputReaderDeactivate);
+    }
+    m_input_readers.push (reader_sp);
+    reader_sp->Notify (eInputReaderActivate);
+    ActivateInputReader (reader_sp);
+}
+
+bool
+Debugger::PopInputReader (const lldb::InputReaderSP& pop_reader_sp)
+{
+    bool result = false;
+
+    // The reader on the stop of the stack is done, so let the next
+    // read on the stack referesh its prompt and if there is one...
+    if (!m_input_readers.empty())
+    {
+        InputReaderSP reader_sp(m_input_readers.top());
+        
+        if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get())
+        {
+            m_input_readers.pop ();
+            reader_sp->Notify (eInputReaderDeactivate);
+            reader_sp->Notify (eInputReaderDone);
+            result = true;
+
+            if (!m_input_readers.empty())
+            {
+                reader_sp = m_input_readers.top();
+                if (reader_sp)
+                {
+                    ActivateInputReader (reader_sp);
+                    reader_sp->Notify (eInputReaderReactivate);
+                }
+            }
+        }
+    }
+    return result;
+}
+
+bool
+Debugger::CheckIfTopInputReaderIsDone ()
+{
+    bool result = false;
+    if (!m_input_readers.empty())
+    {
+        InputReaderSP reader_sp(m_input_readers.top());
+        
+        if (reader_sp && reader_sp->IsDone())
+        {
+            result = true;
+            PopInputReader (reader_sp);
+        }
+    }
+    return result;
+}
+
+void
+Debugger::ActivateInputReader (const InputReaderSP &reader_sp)
+{
+    FILE *in_fh = GetInputFileHandle();
+
+    if (in_fh)
+    {
+        struct termios in_fh_termios;
+        int in_fd = fileno (in_fh);
+        if (::tcgetattr(in_fd, &in_fh_termios) == 0)
+        {    
+            if (reader_sp->GetEcho())
+                in_fh_termios.c_lflag |= ECHO;  // Turn on echoing
+            else
+                in_fh_termios.c_lflag &= ~ECHO; // Turn off echoing
+                
+            switch (reader_sp->GetGranularity())
+            {
+            case eInputReaderGranularityByte:
+            case eInputReaderGranularityWord:
+                in_fh_termios.c_lflag &= ~ICANON;   // Get one char at a time
+                break;
+
+            case eInputReaderGranularityLine:
+            case eInputReaderGranularityAll:
+                in_fh_termios.c_lflag |= ICANON;   // Get lines at a time
+                break;
+
+            default:
+                break;
+            }
+            ::tcsetattr (in_fd, TCSANOW, &in_fh_termios);
+        }
+    }
+}
diff --git a/source/Core/Disassembler.cpp b/source/Core/Disassembler.cpp
new file mode 100644
index 0000000..570ff72
--- /dev/null
+++ b/source/Core/Disassembler.cpp
@@ -0,0 +1,299 @@
+//===-- Disassembler.cpp ----------------------------------------*- 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/Disassembler.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+
+#define DEFAULT_DISASM_BYTE_SIZE 32
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+Disassembler*
+Disassembler::FindPlugin (const ArchSpec &arch)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "Disassembler::FindPlugin (arch = %s)",
+                        arch.AsCString());
+
+    std::auto_ptr<Disassembler> disassembler_ap;
+    DisassemblerCreateInstance create_callback;
+    for (uint32_t idx = 0; (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(idx)) != NULL; ++idx)
+    {
+        disassembler_ap.reset (create_callback(arch));
+
+        if (disassembler_ap.get())
+            return disassembler_ap.release();
+    }
+    return NULL;
+}
+
+bool
+Disassembler::Disassemble
+(
+    const ArchSpec &arch,
+    const ExecutionContext &exe_ctx,
+    uint32_t mixed_context_lines,
+    Stream &strm
+)
+{
+    Disassembler *disassembler = Disassembler::FindPlugin(arch);
+
+    if (disassembler)
+    {
+        lldb::addr_t addr = LLDB_INVALID_ADDRESS;
+        size_t byte_size = 0;
+        if (exe_ctx.frame)
+        {
+            SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
+            if (sc.function)
+            {
+                addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(exe_ctx.process);
+                if (addr != LLDB_INVALID_ADDRESS)
+                    byte_size = sc.function->GetAddressRange().GetByteSize();
+            }
+            else if (sc.symbol && sc.symbol->GetAddressRangePtr())
+            {
+                addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress().GetLoadAddress(exe_ctx.process);
+                if (addr != LLDB_INVALID_ADDRESS)
+                {
+                    byte_size = sc.symbol->GetAddressRangePtr()->GetByteSize();
+                    if (byte_size == 0)
+                        byte_size = DEFAULT_DISASM_BYTE_SIZE;
+                }
+            }
+            else
+            {
+                addr = exe_ctx.frame->GetPC().GetLoadAddress(exe_ctx.process);
+                if (addr != LLDB_INVALID_ADDRESS)
+                    byte_size = DEFAULT_DISASM_BYTE_SIZE;
+            }
+        }
+
+        if (byte_size)
+        {
+            DataExtractor data;
+            size_t bytes_disassembled = disassembler->ParseInstructions (&exe_ctx, eAddressTypeLoad, addr, byte_size, data);
+            if (bytes_disassembled == 0)
+            {
+                return false;
+            }
+            else
+            {
+                // We got some things disassembled...
+                size_t num_instructions = disassembler->GetInstructionList().GetSize();
+                uint32_t offset = 0;
+                SymbolContext sc;
+                SymbolContext prev_sc;
+                AddressRange sc_range;
+                if (mixed_context_lines)
+                    strm.IndentMore ();
+
+                for (size_t i=0; i<num_instructions; ++i)
+                {
+                    Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i);
+                    if (inst)
+                    {
+                        lldb::addr_t curr_addr = addr + offset;
+                        if (mixed_context_lines)
+                        {
+                            if (!sc_range.ContainsLoadAddress (curr_addr, exe_ctx.process))
+                            {
+                                prev_sc = sc;
+                                Address curr_so_addr;
+                                Process *process = exe_ctx.process;
+                                if (process && process->ResolveLoadAddress (curr_addr, curr_so_addr))
+                                {
+                                    if (curr_so_addr.GetSection())
+                                    {
+                                        Module *module = curr_so_addr.GetSection()->GetModule();
+                                        uint32_t resolved_mask = module->ResolveSymbolContextForAddress(curr_so_addr, eSymbolContextEverything, sc);
+                                        if (resolved_mask)
+                                        {
+                                            sc.GetAddressRange (eSymbolContextEverything, sc_range);
+                                            if (sc != prev_sc)
+                                            {
+                                                if (offset != 0)
+                                                    strm.EOL();
+
+                                                sc.DumpStopContext(&strm, process, curr_so_addr);
+
+                                                if (sc.comp_unit && sc.line_entry.IsValid())
+                                                {
+                                                    Debugger::GetSharedInstance().GetSourceManager().DisplaySourceLinesWithLineNumbers (
+                                                            sc.line_entry.file,
+                                                            sc.line_entry.line,
+                                                            mixed_context_lines,
+                                                            mixed_context_lines,
+                                                            mixed_context_lines ? "->" : "",
+                                                            &strm);
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                        if (mixed_context_lines)
+                            strm.IndentMore ();
+                        strm.Indent();
+                        size_t inst_byte_size = inst->GetByteSize();
+                        //inst->Dump(&strm, curr_addr, &data, offset);  // Do dump opcode bytes
+                        inst->Dump(&strm, curr_addr, NULL, offset, exe_ctx, false); // Don't dump opcode bytes
+                        strm.EOL();
+                        offset += inst_byte_size;
+                        if (mixed_context_lines)
+                            strm.IndentLess ();
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+                if (mixed_context_lines)
+                    strm.IndentLess ();
+
+            }
+        }
+        return true;
+    }
+    return false;
+}
+
+Disassembler::Instruction::Instruction()
+{
+}
+
+Disassembler::Instruction::~Instruction()
+{
+}
+
+
+Disassembler::InstructionList::InstructionList() :
+    m_instructions()
+{
+}
+
+Disassembler::InstructionList::~InstructionList()
+{
+}
+
+size_t
+Disassembler::InstructionList::GetSize() const
+{
+    return m_instructions.size();
+}
+
+
+Disassembler::Instruction *
+Disassembler::InstructionList::GetInstructionAtIndex (uint32_t idx)
+{
+    if (idx < m_instructions.size())
+        return m_instructions[idx].get();
+    return NULL;
+}
+
+const Disassembler::Instruction *
+Disassembler::InstructionList::GetInstructionAtIndex (uint32_t idx) const
+{
+    if (idx < m_instructions.size())
+        return m_instructions[idx].get();
+    return NULL;
+}
+
+void
+Disassembler::InstructionList::Clear()
+{
+  m_instructions.clear();
+}
+
+void
+Disassembler::InstructionList::AppendInstruction (Instruction::shared_ptr &inst_sp)
+{
+    if (inst_sp)
+        m_instructions.push_back(inst_sp);
+}
+
+
+size_t
+Disassembler::ParseInstructions
+(
+    const ExecutionContext *exe_ctx,
+    lldb::AddressType addr_type,
+    lldb::addr_t addr,
+    size_t byte_size,
+    DataExtractor& data
+)
+{
+    Process *process = exe_ctx->process;
+
+    if (process == NULL)
+        return 0;
+
+    DataBufferSP data_sp(new DataBufferHeap (byte_size, '\0'));
+
+    Error error;
+    if (process->GetTarget().ReadMemory (addr_type, addr, data_sp->GetBytes(), data_sp->GetByteSize(), error, NULL))
+    {
+        data.SetData(data_sp);
+        data.SetByteOrder(process->GetByteOrder());
+        data.SetAddressByteSize(process->GetAddressByteSize());
+        return ParseInstructions (data, 0, UINT32_MAX, addr);
+    }
+
+    return 0;
+}
+
+//----------------------------------------------------------------------
+// Disassembler copy constructor
+//----------------------------------------------------------------------
+Disassembler::Disassembler(const ArchSpec& arch) :
+    m_arch (arch),
+    m_instruction_list(),
+    m_base_addr(LLDB_INVALID_ADDRESS)
+{
+
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+Disassembler::~Disassembler()
+{
+}
+
+Disassembler::InstructionList &
+Disassembler::GetInstructionList ()
+{
+    return m_instruction_list;
+}
+
+const Disassembler::InstructionList &
+Disassembler::GetInstructionList () const
+{
+    return m_instruction_list;
+}
diff --git a/source/Core/DynamicLoader.cpp b/source/Core/DynamicLoader.cpp
new file mode 100644
index 0000000..b6b2f27
--- /dev/null
+++ b/source/Core/DynamicLoader.cpp
@@ -0,0 +1,75 @@
+//===-- DynamicLoader.cpp ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-private.h"
+#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Core/PluginManager.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+DynamicLoader*
+DynamicLoader::FindPlugin (Process *process, const char *plugin_name)
+{
+    DynamicLoaderCreateInstance create_callback = NULL;
+    if (plugin_name)
+    {
+        create_callback  = PluginManager::GetDynamicLoaderCreateCallbackForPluginName (plugin_name);
+        if (create_callback)
+        {
+            std::auto_ptr<DynamicLoader> instance_ap(create_callback(process));
+            if (instance_ap.get())
+                return instance_ap.release();
+        }
+    }
+    else
+    {
+        for (uint32_t idx = 0; (create_callback = PluginManager::GetDynamicLoaderCreateCallbackAtIndex(idx)) != NULL; ++idx)
+        {
+            std::auto_ptr<DynamicLoader> instance_ap(create_callback(process));
+            if (instance_ap.get())
+                return instance_ap.release();
+        }
+    }
+    return NULL;
+}
+
+
+//----------------------------------------------------------------------
+// DynamicLoader constructor
+//----------------------------------------------------------------------
+DynamicLoader::DynamicLoader(Process *process) :
+    m_process (process),
+    m_stop_when_images_change(false)    // Stop the process by default when a process' images change
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+DynamicLoader::~DynamicLoader()
+{
+}
+
+//----------------------------------------------------------------------
+// Accessosors to the global setting as to wether to stop at image
+// (shared library) loading/unloading.
+//----------------------------------------------------------------------
+bool
+DynamicLoader::GetStopWhenImagesChange () const
+{
+    return m_stop_when_images_change;
+}
+
+void
+DynamicLoader::SetStopWhenImagesChange (bool stop)
+{
+    m_stop_when_images_change = stop;
+}
+
diff --git a/source/Core/Error.cpp b/source/Core/Error.cpp
new file mode 100644
index 0000000..c352209
--- /dev/null
+++ b/source/Core/Error.cpp
@@ -0,0 +1,365 @@
+//===-- Error.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 <sys/errno.h>
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+
+#if defined (__arm__)
+#include <SpringBoardServices/SpringBoardServer.h>
+#endif
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Default constructor
+//----------------------------------------------------------------------
+Error::Error(ValueType err, ErrorType type) :
+    m_code (err),
+    m_type (type),
+    m_string ()
+{
+}
+//----------------------------------------------------------------------
+// Assignment operator
+//----------------------------------------------------------------------
+const Error&
+Error::operator = (const Error& rhs)
+{
+    if (this != &rhs)
+    {
+        m_code = rhs.m_code;
+        m_type = rhs.m_type;
+        m_string = rhs.m_string;
+    }
+    return *this;
+}
+
+
+//----------------------------------------------------------------------
+// Assignment operator
+//----------------------------------------------------------------------
+const Error&
+Error::operator = (kern_return_t err)
+{
+    m_code = err;
+    m_type = eErrorTypeMachKernel;
+    m_string.clear();
+    return *this;
+}
+
+Error::~Error()
+{
+}
+
+//----------------------------------------------------------------------
+// Get the error value as a NULL C string. The error string will be
+// fetched and cached on demand. The cached error string value will
+// remain until the error value is changed or cleared.
+//----------------------------------------------------------------------
+const char *
+Error::AsCString(const char *default_error_str) const
+{
+    if (Success())
+        return NULL;
+
+    if (m_string.empty())
+    {
+        const char *s = NULL;
+        switch (m_type)
+        {
+        case eErrorTypeMachKernel:
+            s = ::mach_error_string (m_code);
+            break;
+
+        case eErrorTypePOSIX:
+            s = ::strerror (m_code);
+            break;
+
+        default:
+            break;
+        }
+        if (s)
+            m_string.assign(s);
+    }
+    if (m_string.empty())
+    {
+        if (default_error_str)
+            m_string.assign(default_error_str);
+        else
+            return NULL;    // User wanted a NULL string back...
+    }
+    return m_string.c_str();
+}
+
+
+//----------------------------------------------------------------------
+// Clear the error and any cached error string that it might contain.
+//----------------------------------------------------------------------
+void
+Error::Clear ()
+{
+    m_code = 0;
+    m_type = eErrorTypeGeneric;
+    m_string.clear();
+}
+
+//----------------------------------------------------------------------
+// Access the error value.
+//----------------------------------------------------------------------
+Error::ValueType
+Error::GetError () const
+{
+    return m_code;
+}
+
+//----------------------------------------------------------------------
+// Access the error type.
+//----------------------------------------------------------------------
+ErrorType
+Error::GetType () const
+{
+    return m_type;
+}
+
+//----------------------------------------------------------------------
+// Retuns true if this object contains an value that describes an
+// error or otherwise non-success result.
+//----------------------------------------------------------------------
+bool
+Error::Fail () const
+{
+    return m_code != 0;
+}
+
+//----------------------------------------------------------------------
+// Log the error given a string with format. If the this object
+// contains an error code, update the error string to contain the
+// "error: " followed by the formatted string, followed by the error
+// value and any string that describes the current error. This
+// allows more context to be given to an error string that remains
+// cached in this object. Logging always occurs even when the error
+// code contains a non-error value.
+//----------------------------------------------------------------------
+void
+Error::PutToLog (Log *log, const char *format, ...)
+{
+    char *arg_msg = NULL;
+    va_list args;
+    va_start (args, format);
+    ::vasprintf (&arg_msg, format, args);
+    va_end (args);
+
+    if (arg_msg != NULL)
+    {
+        if (Fail())
+        {
+            const char *err_str = AsCString();
+            if (err_str == NULL)
+                err_str = "???";
+
+            SetErrorStringWithFormat("error: %s err = %s (0x%8.8x)", arg_msg, err_str, m_code);
+            if (log)
+                log->Error("%s", m_string.c_str());
+        }
+        else
+        {
+            if (log)
+                log->Printf("%s err = 0x%8.8x", arg_msg, m_code);
+        }
+        ::free (arg_msg);
+    }
+}
+
+//----------------------------------------------------------------------
+// Log the error given a string with format. If the this object
+// contains an error code, update the error string to contain the
+// "error: " followed by the formatted string, followed by the error
+// value and any string that describes the current error. This
+// allows more context to be given to an error string that remains
+// cached in this object. Logging only occurs even when the error
+// code contains a error value.
+//----------------------------------------------------------------------
+void
+Error::LogIfError (Log *log, const char *format, ...)
+{
+    if (Fail())
+    {
+        char *arg_msg = NULL;
+        va_list args;
+        va_start (args, format);
+        ::vasprintf (&arg_msg, format, args);
+        va_end (args);
+
+        if (arg_msg != NULL)
+        {
+            const char *err_str = AsCString();
+            if (err_str == NULL)
+                err_str = "???";
+
+            SetErrorStringWithFormat("error: %s err = %s (0x%8.8x)", arg_msg, err_str, m_code);
+            if (log)
+                log->Error("%s", m_string.c_str());
+
+            ::free (arg_msg);
+        }
+    }
+}
+
+//----------------------------------------------------------------------
+// Set accesssor for the error value to "err" and the type to
+// "eErrorTypeMachKernel"
+//----------------------------------------------------------------------
+void
+Error::SetError (kern_return_t err)
+{
+    m_code = err;
+    m_type = eErrorTypeMachKernel;
+    m_string.clear();
+}
+
+//----------------------------------------------------------------------
+// Set accesssor for the error value and type.
+//----------------------------------------------------------------------
+void
+Error::SetError (ValueType err, ErrorType type)
+{
+    m_code = err;
+    m_type = type;
+    m_string.clear();
+}
+
+//----------------------------------------------------------------------
+// Update the error value to be "errno" and update the type to
+// be "POSIX".
+//----------------------------------------------------------------------
+void
+Error::SetErrorToErrno()
+{
+    m_code = errno;
+    m_type = eErrorTypePOSIX;
+    m_string.clear();
+}
+
+//----------------------------------------------------------------------
+// Update the error value to be LLDB_GENERIC_ERROR and update the type
+// to be "Generic".
+//----------------------------------------------------------------------
+void
+Error::SetErrorToGenericError ()
+{
+    m_code = LLDB_GENERIC_ERROR;
+    m_type = eErrorTypeGeneric;
+    m_string.clear();
+}
+
+//----------------------------------------------------------------------
+// Set accessor for the error string value for a specific error.
+// This allows any string to be supplied as an error explanation.
+// The error string value will remain until the error value is
+// cleared or a new error value/type is assigned.
+//----------------------------------------------------------------------
+void
+Error::SetErrorString (const char *err_str)
+{
+    if (err_str && err_str[0])
+    {
+        // If we have an error string, we should always at least have
+        // an error set to a generic value.
+        if (Success())
+            SetErrorToGenericError();
+        m_string = err_str;
+        m_string.append("\n");
+    }
+    else
+        m_string.clear();
+}
+
+//------------------------------------------------------------------
+/// Set the current error string to a formatted error string.
+///
+/// @param format
+///     A printf style format string
+//------------------------------------------------------------------
+int
+Error::SetErrorStringWithFormat (const char *format, ...)
+{
+    if (format && format[0])
+    {
+        va_list args;
+        va_start (args, format);
+        int length = SetErrorStringWithVarArg (format, args);
+        va_end (args);
+        return length;
+    }
+    else
+    {
+        m_string.clear();
+    }
+    return 0;
+}
+
+int
+Error::SetErrorStringWithVarArg (const char *format, va_list args)
+{
+    if (format && format[0])
+    {
+        // If we have an error string, we should always at least have
+        // an error set to a generic value.
+        if (Success())
+            SetErrorToGenericError();
+
+        // Try and fit our error into a 1024 byte buffer first...
+        m_string.resize(1024);
+        // Copy in case our first call to vsnprintf doesn't fit into our
+        // allocated buffer above
+        va_list copy_args;
+        va_copy (copy_args, args);
+        int length = ::vsnprintf (&m_string[0], m_string.size(), format, args);
+        if (length < m_string.size())
+        {
+            // The error formatted string fit into our buffer, just chop it down
+            // to size
+            m_string.erase (length);
+        }
+        else
+        {
+            // The error formatted string didn't fit into our buffer, resize it
+            // to the exact needed size, and retry
+            m_string.resize(length + 1);
+            length = ::vsnprintf (&m_string[0], m_string.size(), format, copy_args);
+            va_end (copy_args);
+            assert (length < m_string.size());
+        }
+        va_end (args);
+        return length;
+    }
+    else
+    {
+        m_string.clear();
+    }
+    return 0;
+}
+
+
+//----------------------------------------------------------------------
+// Returns true if the error code in this object is considered a
+// successful return value.
+//----------------------------------------------------------------------
+bool
+Error::Success() const
+{
+    return m_code == 0;
+}
diff --git a/source/Core/Event.cpp b/source/Core/Event.cpp
new file mode 100644
index 0000000..c2bf08d
--- /dev/null
+++ b/source/Core/Event.cpp
@@ -0,0 +1,241 @@
+//===-- Event.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
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Event.h"
+#include "lldb/Core/Broadcaster.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/State.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Event constructor
+//----------------------------------------------------------------------
+Event::Event (Broadcaster *broadcaster, uint32_t event_type, EventData *data) :
+    m_broadcaster (broadcaster),
+    m_type (event_type),
+    m_data_ap (data)
+{
+}
+
+Event::Event(uint32_t event_type, EventData *data) :
+    m_broadcaster (NULL),   // Set by the broadcaster when this event gets broadcast
+    m_type (event_type),
+    m_data_ap (data)
+{
+}
+
+
+//----------------------------------------------------------------------
+// Event destructor
+//----------------------------------------------------------------------
+Event::~Event ()
+{
+}
+
+void
+Event::Clear()
+{
+    m_data_ap.reset();
+}
+
+void
+Event::Dump (Stream *s) const
+{
+    s->Printf("%p Event: broadcaster = %p, type = 0x%8.8x, data = ", this, m_broadcaster, m_type);
+
+    if (m_data_ap.get() == NULL)
+        s->Printf ("<NULL>");
+    else
+    {
+        s->PutChar('{');
+        m_data_ap->Dump (s);
+        s->PutChar('}');
+    }
+}
+
+Broadcaster *
+Event::GetBroadcaster () const
+{
+    return m_broadcaster;
+}
+
+bool
+Event::BroadcasterIs (Broadcaster *broadcaster)
+{
+    return broadcaster == m_broadcaster;
+}
+
+uint32_t
+Event::GetType() const
+{
+    return m_type;
+}
+
+
+EventData *
+Event::GetData ()
+{
+    return m_data_ap.get();
+}
+
+const EventData *
+Event::GetData () const
+{
+    return m_data_ap.get();
+}
+
+void
+Event::DoOnRemoval ()
+{
+    if (m_data_ap.get())
+        m_data_ap->DoOnRemoval (this);
+}
+
+void
+Event::SetBroadcaster (Broadcaster *broadcaster)
+{
+    m_broadcaster = broadcaster;
+}
+
+EventData::EventData()
+{
+}
+
+EventData::~EventData()
+{
+}
+
+void
+EventData::Dump (Stream *s) const
+{
+    s->PutCString ("Generic Event Data");
+}
+
+EventDataBytes::EventDataBytes () :
+    m_bytes()
+{
+}
+
+EventDataBytes::EventDataBytes (const char *cstr) :
+    m_bytes()
+{
+    SetBytesFromCString (cstr);
+}
+
+EventDataBytes::EventDataBytes (const void *src, size_t src_len) :
+    m_bytes()
+{
+    SetBytes (src, src_len);
+}
+
+EventDataBytes::~EventDataBytes()
+{
+}
+
+const ConstString &
+EventDataBytes::GetFlavorString ()
+{
+    static ConstString g_flavor ("EventDataBytes");
+    return g_flavor;
+}
+
+const ConstString &
+EventDataBytes::GetFlavor () const
+{
+    return EventDataBytes::GetFlavorString ();
+}
+
+void
+EventDataBytes::Dump (Stream *s) const
+{
+    size_t num_printable_chars = std::count_if (m_bytes.begin(), m_bytes.end(), isprint);
+    if (num_printable_chars == m_bytes.size())
+    {
+        s->Printf("\"%s\"", m_bytes.c_str());
+    }
+    else
+    {
+        DataExtractor data;
+        data.SetData(m_bytes.data(), m_bytes.size(), eByteOrderHost);
+        data.Dump(s, 0, eFormatBytes, 1, m_bytes.size(), 32, LLDB_INVALID_ADDRESS, 0, 0);
+    }
+}
+
+const void *
+EventDataBytes::GetBytes() const
+{
+    if (m_bytes.empty())
+        return NULL;
+    return m_bytes.data();
+}
+
+size_t
+EventDataBytes::GetByteSize() const
+{
+    return m_bytes.size ();
+}
+
+void
+EventDataBytes::SetBytes (const void *src, size_t src_len)
+{
+    if (src && src_len > 0)
+        m_bytes.assign ((const char *)src, src_len);
+    else
+        m_bytes.clear();
+}
+
+void
+EventDataBytes::SetBytesFromCString (const char *cstr)
+{
+    if (cstr && cstr[0])
+        m_bytes.assign (cstr);
+    else
+        m_bytes.clear();
+}
+
+
+const void *
+EventDataBytes::GetBytesFromEvent (const Event *event_ptr)
+{
+    const EventDataBytes *e = GetEventDataFromEvent (event_ptr);
+    if (e)
+        return e->GetBytes();
+    return NULL;
+}
+
+size_t
+EventDataBytes::GetByteSizeFromEvent (const Event *event_ptr)
+{
+    const EventDataBytes *e = GetEventDataFromEvent (event_ptr);
+    if (e)
+        return e->GetByteSize();
+    return 0;
+}
+
+const EventDataBytes *
+EventDataBytes::GetEventDataFromEvent (const Event *event_ptr)
+{
+    if (event_ptr)
+    {
+        const EventData *event_data = event_ptr->GetData();
+        if (event_data && event_data->GetFlavor() == EventDataBytes::GetFlavorString())
+            return static_cast <const EventDataBytes *> (event_data);
+    }
+    return NULL;
+}
+
diff --git a/source/Core/FileSpec.cpp b/source/Core/FileSpec.cpp
new file mode 100644
index 0000000..305650d
--- /dev/null
+++ b/source/Core/FileSpec.cpp
@@ -0,0 +1,580 @@
+//===-- FileSpec.cpp --------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include <fcntl.h>
+#include <glob.h>
+#include <libgen.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <fstream>
+
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataBufferMemoryMap.h"
+#include "lldb/Core/Stream.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace std;
+
+static bool
+GetFileStats (const FileSpec *file_spec, struct stat *stats_ptr)
+{
+    char resolved_path[PATH_MAX];
+    if (file_spec->GetPath(&resolved_path[0], sizeof(resolved_path)))
+        return ::stat (resolved_path, stats_ptr) == 0;
+    return false;
+}
+
+static const char*
+GetCachedGlobTildeSlash()
+{
+    static std::string g_tilde;
+    if (g_tilde.empty())
+    {
+        glob_t globbuf;
+        if (::glob("~/", GLOB_TILDE, NULL, &globbuf) == 0) //success
+        {
+            g_tilde = globbuf.gl_pathv[0];
+            ::globfree (&globbuf);
+        }
+        if (g_tilde.empty())
+            return NULL;
+    }
+    return g_tilde.c_str();
+}
+
+int
+FileSpec::Resolve (const char *src_path, char *dst_path, size_t dst_len)
+{
+    if (src_path == NULL || src_path[0] == '\0')
+        return 0;
+
+    // Glob if needed for ~/, otherwise copy in case src_path is same as dst_path...
+    char unglobbed_path[PATH_MAX];
+    if (::strstr (src_path, "~/") == src_path)
+        ::snprintf(unglobbed_path, sizeof(unglobbed_path), "%s%s", GetCachedGlobTildeSlash(), src_path + 2);
+    else
+        ::snprintf(unglobbed_path, sizeof(unglobbed_path), "%s", src_path);
+
+    // Now resolve the path if needed
+    char resolved_path[PATH_MAX];
+    if (::realpath (unglobbed_path, resolved_path))
+    {
+        // Success, copy the resolved path
+        return ::snprintf(dst_path, dst_len, "%s", resolved_path);
+    }
+    else
+    {
+        // Failed, just copy the unglobbed path
+        return ::snprintf(dst_path, dst_len, "%s", unglobbed_path);
+    }
+}
+
+FileSpec::FileSpec() :
+    m_directory(),
+    m_filename()
+{
+}
+
+//------------------------------------------------------------------
+// Default constructor that can take an optional full path to a
+// file on disk.
+//------------------------------------------------------------------
+FileSpec::FileSpec(const char *pathname) :
+    m_directory(),
+    m_filename()
+{
+    if (pathname && pathname[0])
+        SetFile(pathname);
+}
+
+//------------------------------------------------------------------
+// Copy constructor
+//------------------------------------------------------------------
+FileSpec::FileSpec(const FileSpec& rhs) :
+    m_directory (rhs.m_directory),
+    m_filename (rhs.m_filename)
+{
+}
+
+//------------------------------------------------------------------
+// Copy constructor
+//------------------------------------------------------------------
+FileSpec::FileSpec(const FileSpec* rhs) :
+    m_directory(),
+    m_filename()
+{
+    if (rhs)
+        *this = *rhs;
+}
+
+//------------------------------------------------------------------
+// Virtual destrcuctor in case anyone inherits from this class.
+//------------------------------------------------------------------
+FileSpec::~FileSpec()
+{
+}
+
+//------------------------------------------------------------------
+// Assignment operator.
+//------------------------------------------------------------------
+const FileSpec&
+FileSpec::operator= (const FileSpec& rhs)
+{
+    if (this != &rhs)
+    {
+        m_directory = rhs.m_directory;
+        m_filename = rhs.m_filename;
+    }
+    return *this;
+}
+
+
+//------------------------------------------------------------------
+// Update the contents of this object with a new path. The path will
+// be split up into a directory and filename and stored as uniqued
+// string values for quick comparison and efficient memory usage.
+//------------------------------------------------------------------
+void
+FileSpec::SetFile(const char *pathname)
+{
+    m_filename.Clear();
+    m_directory.Clear();
+    if (pathname == NULL || pathname[0] == '\0')
+        return;
+
+    char resolved_path[PATH_MAX];
+
+    if (FileSpec::Resolve (pathname, resolved_path, sizeof(resolved_path)) < sizeof(resolved_path) - 1)
+    {
+        char *filename = ::basename (resolved_path);
+        if (filename)
+        {
+            m_filename.SetCString (filename);
+            // Truncate the basename off the end of the resolved path
+
+            // Only attempt to get the dirname if it looks like we have a path
+            if (strchr(resolved_path, '/'))
+            {
+                char *directory = ::dirname (resolved_path);
+
+                // Make sure we didn't get our directory resolved to "." without having
+                // specified
+                if (directory)
+                    m_directory.SetCString(directory);
+                else
+                {
+                    char *last_resolved_path_slash = strrchr(resolved_path, '/');
+                    if (last_resolved_path_slash)
+                    {
+                        *last_resolved_path_slash = '\0';
+                        m_directory.SetCString(resolved_path);
+                    }
+                }
+            }
+        }
+        else
+            m_directory.SetCString(resolved_path);
+    }
+}
+
+//----------------------------------------------------------------------
+// Convert to pointer operator. This allows code to check any FileSpec
+// objects to see if they contain anything valid using code such as:
+//
+//  if (file_spec)
+//  {}
+//----------------------------------------------------------------------
+FileSpec::operator
+void*() const
+{
+    return (m_directory || m_filename) ? const_cast<FileSpec*>(this) : NULL;
+}
+
+//----------------------------------------------------------------------
+// Logical NOT operator. This allows code to check any FileSpec
+// objects to see if they are invalid using code such as:
+//
+//  if (!file_spec)
+//  {}
+//----------------------------------------------------------------------
+bool
+FileSpec::operator!() const
+{
+    return !m_directory && !m_filename;
+}
+
+//------------------------------------------------------------------
+// Equal to operator
+//------------------------------------------------------------------
+bool
+FileSpec::operator== (const FileSpec& rhs) const
+{
+    return m_directory == rhs.m_directory && m_filename == rhs.m_filename;
+}
+
+//------------------------------------------------------------------
+// Not equal to operator
+//------------------------------------------------------------------
+bool
+FileSpec::operator!= (const FileSpec& rhs) const
+{
+    return m_filename != rhs.m_filename || m_directory != rhs.m_directory;
+}
+
+//------------------------------------------------------------------
+// Less than operator
+//------------------------------------------------------------------
+bool
+FileSpec::operator< (const FileSpec& rhs) const
+{
+    return FileSpec::Compare(*this, rhs, true) < 0;
+}
+
+//------------------------------------------------------------------
+// Dump a FileSpec object to a stream
+//------------------------------------------------------------------
+Stream&
+lldb_private::operator << (Stream &s, const FileSpec& f)
+{
+    f.Dump(&s);
+    return s;
+}
+
+//------------------------------------------------------------------
+// Clear this object by releasing both the directory and filename
+// string values and making them both the empty string.
+//------------------------------------------------------------------
+void
+FileSpec::Clear()
+{
+    m_directory.Clear();
+    m_filename.Clear();
+}
+
+//------------------------------------------------------------------
+// Compare two FileSpec objects. If "full" is true, then both
+// the directory and the filename must match. If "full" is false,
+// then the directory names for "a" and "b" are only compared if
+// they are both non-empty. This allows a FileSpec object to only
+// contain a filename and it can match FileSpec objects that have
+// matching filenames with different paths.
+//
+// Return -1 if the "a" is less than "b", 0 if "a" is equal to "b"
+// and "1" if "a" is greater than "b".
+//------------------------------------------------------------------
+int
+FileSpec::Compare(const FileSpec& a, const FileSpec& b, bool full)
+{
+    int result = 0;
+
+    // If full is true, then we must compare both the directory and filename.
+
+    // If full is false, then if either directory is empty, then we match on
+    // the basename only, and if both directories have valid values, we still
+    // do a full compare. This allows for matching when we just have a filename
+    // in one of the FileSpec objects.
+
+    if (full || (a.m_directory && b.m_directory))
+    {
+        result = ConstString::Compare(a.m_directory, b.m_directory);
+        if (result)
+            return result;
+    }
+    return ConstString::Compare (a.m_filename, b.m_filename);
+}
+
+bool
+FileSpec::Equal (const FileSpec& a, const FileSpec& b, bool full)
+{
+    if (full)
+        return a == b;
+    else
+        return a.m_filename == b.m_filename;
+}
+
+
+
+//------------------------------------------------------------------
+// Dump the object to the supplied stream. If the object contains
+// a valid directory name, it will be displayed followed by a
+// directory delimiter, and the filename.
+//------------------------------------------------------------------
+void
+FileSpec::Dump(Stream *s) const
+{
+    if (m_filename)
+        m_directory.Dump(s, "");    // Provide a default for m_directory when we dump it in case it is invalid
+
+    if (m_directory)
+    {
+        // If dirname was valid, then we need to print a slash between
+        // the directory and the filename
+        s->PutChar('/');
+    }
+    m_filename.Dump(s);
+}
+
+//------------------------------------------------------------------
+// Returns true if the file exists.
+//------------------------------------------------------------------
+bool
+FileSpec::Exists () const
+{
+    struct stat file_stats;
+    return GetFileStats (this, &file_stats);
+}
+
+uint64_t
+FileSpec::GetByteSize() const
+{
+    struct stat file_stats;
+    if (GetFileStats (this, &file_stats))
+        return file_stats.st_size;
+    return 0;
+}
+
+FileSpec::FileType
+FileSpec::GetFileType () const
+{
+    struct stat file_stats;
+    if (GetFileStats (this, &file_stats))
+    {
+        mode_t file_type = file_stats.st_mode & S_IFMT;
+        switch (file_type)
+        {
+        case S_IFDIR:   return eFileTypeDirectory;
+        case S_IFIFO:   return eFileTypePipe;
+        case S_IFREG:   return eFileTypeRegular;
+        case S_IFSOCK:  return eFileTypeSocket;
+        case S_IFLNK:   return eFileTypeSymbolicLink;
+        default:
+            break;
+        }
+        return eFileTypeUknown;
+    }
+    return eFileTypeInvalid;
+}
+
+TimeValue
+FileSpec::GetModificationTime () const
+{
+    TimeValue mod_time;
+    struct stat file_stats;
+    if (GetFileStats (this, &file_stats))
+        mod_time = file_stats.st_mtimespec;
+    return mod_time;
+}
+
+//------------------------------------------------------------------
+// Directory string get accessor.
+//------------------------------------------------------------------
+ConstString &
+FileSpec::GetDirectory()
+{
+    return m_directory;
+}
+
+//------------------------------------------------------------------
+// Directory string const get accessor.
+//------------------------------------------------------------------
+const ConstString &
+FileSpec::GetDirectory() const
+{
+    return m_directory;
+}
+
+//------------------------------------------------------------------
+// Filename string get accessor.
+//------------------------------------------------------------------
+ConstString &
+FileSpec::GetFilename()
+{
+    return m_filename;
+}
+
+//------------------------------------------------------------------
+// Filename string const get accessor.
+//------------------------------------------------------------------
+const ConstString &
+FileSpec::GetFilename() const
+{
+    return m_filename;
+}
+
+//------------------------------------------------------------------
+// Extract the directory and path into a fixed buffer. This is
+// needed as the directory and path are stored in separate string
+// values.
+//------------------------------------------------------------------
+bool
+FileSpec::GetPath(char *path, size_t max_path_length) const
+{
+    if (max_path_length == 0)
+        return false;
+
+    path[0] = '\0';
+    const char *dirname = m_directory.AsCString();
+    const char *filename = m_filename.AsCString();
+    if (dirname)
+    {
+        if (filename && filename[0])
+        {
+            return snprintf (path, max_path_length, "%s/%s", dirname, filename) < max_path_length;
+        }
+        else
+        {
+            strncpy (path, dirname, max_path_length);
+        }
+    }
+    else if (filename)
+    {
+        strncpy (path, filename, max_path_length);
+    }
+
+    // Any code paths that reach here assume that strncpy, or a similar function was called
+    // where any remaining bytes will be filled with NULLs and that the string won't be
+    // NULL terminated if it won't fit in the buffer.
+
+    // If the last character is NULL, then all went well
+    if (path[max_path_length-1] == '\0')
+        return true;
+
+        // Make sure the path is terminated, as it didn't fit into "path"
+    path[max_path_length-1] = '\0';
+    return false;
+}
+
+//------------------------------------------------------------------
+// Returns a shared pointer to a data buffer that contains all or
+// part of the contents of a file. The data is memory mapped and
+// will lazily page in data from the file as memory is accessed.
+// The data that is mappped will start "file_offset" bytes into the
+// file, and "file_size" bytes will be mapped. If "file_size" is
+// greater than the number of bytes available in the file starting
+// at "file_offset", the number of bytes will be appropriately
+// truncated. The final number of bytes that get mapped can be
+// verified using the DataBuffer::GetByteSize() function.
+//------------------------------------------------------------------
+DataBufferSP
+FileSpec::MemoryMapFileContents(off_t file_offset, size_t file_size) const
+{
+    DataBufferSP data_sp;
+    auto_ptr<DataBufferMemoryMap> mmap_data(new DataBufferMemoryMap());
+    if (mmap_data.get())
+    {
+        if (mmap_data->MemoryMapFromFileSpec (this, file_offset, file_size) >= file_size)
+            data_sp.reset(mmap_data.release());
+    }
+    return data_sp;
+}
+
+
+//------------------------------------------------------------------
+// Return the size in bytes that this object takes in memory. This
+// returns the size in bytes of this object, not any shared string
+// values it may refer to.
+//------------------------------------------------------------------
+size_t
+FileSpec::MemorySize() const
+{
+    return m_filename.MemorySize() + m_directory.MemorySize();
+}
+
+//------------------------------------------------------------------
+// Returns a shared pointer to a data buffer that contains all or
+// part of the contents of a file. The data copies into a heap based
+// buffer that lives in the DataBuffer shared pointer object returned.
+// The data that is cached will start "file_offset" bytes into the
+// file, and "file_size" bytes will be mapped. If "file_size" is
+// greater than the number of bytes available in the file starting
+// at "file_offset", the number of bytes will be appropriately
+// truncated. The final number of bytes that get mapped can be
+// verified using the DataBuffer::GetByteSize() function.
+//------------------------------------------------------------------
+DataBufferSP
+FileSpec::ReadFileContents(off_t file_offset, size_t file_size) const
+{
+    DataBufferSP data_sp;
+    char resolved_path[PATH_MAX];
+    if (GetPath(resolved_path, sizeof(resolved_path)))
+    {
+        int fd = ::open (resolved_path, O_RDONLY, 0);
+        if (fd != -1)
+        {
+            struct stat file_stats;
+            if (::fstat (fd, &file_stats) == 0)
+            {
+                // Read bytes directly into our basic_string buffer
+                if (file_stats.st_size > 0)
+                {
+                    off_t lseek_result = 0;
+                    if (file_offset > 0)
+                        lseek_result = ::lseek (fd, file_offset, SEEK_SET);
+
+                    if (lseek_result < 0)
+                    {
+                        // Get error from errno
+                    }
+                    else if (lseek_result == file_offset)
+                    {
+                        std::auto_ptr<DataBufferHeap> data_heap_ap;
+                        if (file_stats.st_size < file_size)
+                            data_heap_ap.reset(new DataBufferHeap(file_stats.st_size, '\0'));
+                        else
+                            data_heap_ap.reset(new DataBufferHeap(file_size, '\0'));
+
+                        if (data_heap_ap.get())
+                        {
+                            ssize_t bytesRead = ::read (fd, (void *)data_heap_ap->GetBytes(), data_heap_ap->GetByteSize());
+                            if (bytesRead >= 0)
+                            {
+                                // Make sure we read exactly what we asked for and if we got
+                                // less, adjust the array
+                                if (bytesRead < data_heap_ap->GetByteSize())
+                                    data_heap_ap->SetByteSize(bytesRead);
+                                data_sp.reset(data_heap_ap.release());
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        close(fd);
+    }
+    return data_sp;
+}
+
+bool
+FileSpec::ReadFileLines (STLStringArray &lines)
+{
+    bool ret_val = false;
+    lines.clear();
+
+    std::string dir_str (m_directory.AsCString());
+    std::string file_str (m_filename.AsCString());
+    std::string full_name = dir_str + "/" + file_str;
+
+    ifstream file_stream (full_name.c_str());
+
+    if (file_stream)
+    {
+        std::string line;
+        while (getline (file_stream, line))
+          lines.push_back (line);
+        ret_val = true;
+    }
+
+    return ret_val;
+}
diff --git a/source/Core/FileSpecList.cpp b/source/Core/FileSpecList.cpp
new file mode 100644
index 0000000..17abf4b
--- /dev/null
+++ b/source/Core/FileSpecList.cpp
@@ -0,0 +1,228 @@
+//===-- FileSpecList.cpp ----------------------------------------*- 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/FileSpecList.h"
+#include "lldb/Core/Stream.h"
+
+using namespace lldb_private;
+using namespace std;
+
+//------------------------------------------------------------------
+// Default constructor
+//------------------------------------------------------------------
+FileSpecList::FileSpecList() :
+    m_files()
+{
+}
+
+//------------------------------------------------------------------
+// Copy constructor
+//------------------------------------------------------------------
+FileSpecList::FileSpecList(const FileSpecList& rhs) :
+    m_files(rhs.m_files)
+{
+}
+
+//------------------------------------------------------------------
+// Destructor
+//------------------------------------------------------------------
+FileSpecList::~FileSpecList()
+{
+}
+
+//------------------------------------------------------------------
+// Assignment operator
+//------------------------------------------------------------------
+const FileSpecList&
+FileSpecList::operator= (const FileSpecList& rhs)
+{
+    if (this != &rhs)
+        m_files = rhs.m_files;
+    return *this;
+}
+
+//------------------------------------------------------------------
+// Append the "file_spec" to the end of the file spec list.
+//------------------------------------------------------------------
+void
+FileSpecList::Append(const FileSpec &file_spec)
+{
+    m_files.push_back(file_spec);
+}
+
+//------------------------------------------------------------------
+// Only append the "file_spec" if this list doesn't already contain
+// it.
+//
+// Returns true if "file_spec" was added, false if this list already
+// contained a copy of "file_spec".
+//------------------------------------------------------------------
+bool
+FileSpecList::AppendIfUnique(const FileSpec &file_spec)
+{
+    collection::iterator pos, end = m_files.end();
+    if (find(m_files.begin(), end, file_spec) == end)
+    {
+        m_files.push_back(file_spec);
+        return true;
+    }
+    return false;
+}
+
+//------------------------------------------------------------------
+// Clears the file list.
+//------------------------------------------------------------------
+void
+FileSpecList::Clear()
+{
+    m_files.clear();
+}
+
+//------------------------------------------------------------------
+// Dumps the file list to the supplied stream pointer "s".
+//------------------------------------------------------------------
+void
+FileSpecList::Dump(Stream *s) const
+{
+    for_each (m_files.begin(), m_files.end(), bind2nd(mem_fun_ref(&FileSpec::Dump),s));
+}
+
+//------------------------------------------------------------------
+// Find the index of the file in the file spec list that matches
+// "file_spec" starting "start_idx" entries into the file spec list.
+//
+// Returns the valid index of the file that matches "file_spec" if
+// it is found, else UINT32_MAX is returned.
+//------------------------------------------------------------------
+uint32_t
+FileSpecList::FindFileIndex (uint32_t start_idx, const FileSpec &file_spec) const
+{
+    const uint32_t num_files = m_files.size();
+    uint32_t idx;
+
+    // When looking for files, we will compare only the filename if the
+    // FILE_SPEC argument is empty
+    bool compare_filename_only = file_spec.GetDirectory().IsEmpty();
+
+    for (idx = start_idx; idx < num_files; ++idx)
+    {
+        if (compare_filename_only)
+        {
+            if (m_files[idx].GetFilename() == file_spec.GetFilename())
+                return idx;
+        }
+        else
+        {
+            if (m_files[idx] == file_spec)
+                return idx;
+        }
+    }
+
+    // We didn't find the file, return an invalid index
+    return UINT32_MAX;
+}
+
+//------------------------------------------------------------------
+// Returns the FileSpec object at index "idx". If "idx" is out of
+// range, then an empty FileSpec object will be returned.
+//------------------------------------------------------------------
+const FileSpec &
+FileSpecList::GetFileSpecAtIndex(uint32_t idx) const
+{
+
+    if (idx < m_files.size())
+        return m_files[idx];
+    static FileSpec g_empty_file_spec;
+    return g_empty_file_spec;
+}
+
+const FileSpec *
+FileSpecList::GetFileSpecPointerAtIndex(uint32_t idx) const
+{
+    if (idx < m_files.size())
+        return &m_files[idx];
+    return NULL;
+}
+
+//------------------------------------------------------------------
+// Return the size in bytes that this object takes in memory. This
+// returns the size in bytes of this object's member variables and
+// any FileSpec objects its member variables contain, the result
+// doesn't not include the string values for the directories any
+// filenames as those are in shared string pools.
+//------------------------------------------------------------------
+size_t
+FileSpecList::MemorySize () const
+{
+    size_t mem_size = sizeof(FileSpecList);
+    collection::const_iterator pos, end = m_files.end();
+    for (pos = m_files.begin(); pos != end; ++pos)
+    {
+        mem_size += pos->MemorySize();
+    }
+
+    return mem_size;
+}
+
+//------------------------------------------------------------------
+// Return the number of files in the file spec list.
+//------------------------------------------------------------------
+uint32_t
+FileSpecList::GetSize() const
+{
+    return m_files.size();
+}
+
+size_t
+FileSpecList::GetFilesMatchingPartialPath (const char *path, bool dir_okay, FileSpecList &matches)
+{
+#if 0  // FIXME: Just sketching...
+    matches.Clear();
+    FileSpec path_spec = FileSpec (path);
+    if (path_spec.Exists ())
+    {
+        FileSpec::FileType type = path_spec.GetFileType();
+        if (type == FileSpec::eFileTypeSymbolicLink)
+            // Shouldn't there be a Resolve on a file spec that real-path's it?
+        {
+        }
+
+        if (type == FileSpec::eFileTypeRegular
+            || (type == FileSpec::eFileTypeDirectory && dir_okay))
+        {
+            matches.Append (path_spec);
+            return 1;
+        }
+        else if (type == FileSpec::eFileTypeDirectory)
+        {
+            // Fill the match list with all the files in the directory:
+
+        }
+        else
+        {
+            return 0;
+        }
+
+    }
+    else
+    {
+        ConstString dir_name = path_spec.GetDirectory();
+        Constring file_name = GetFilename();
+        if (dir_name == NULL)
+        {
+            // Match files in the CWD.
+        }
+        else
+        {
+            // Match files in the given directory:
+
+        }
+    }
+#endif
+    return 0;
+}
diff --git a/source/Core/Flags.cpp b/source/Core/Flags.cpp
new file mode 100644
index 0000000..13cbd85
--- /dev/null
+++ b/source/Core/Flags.cpp
@@ -0,0 +1,122 @@
+//===-- Flags.cpp -----------------------------------------------*- 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/Flags.h"
+
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Default Constructor
+//----------------------------------------------------------------------
+Flags::Flags (ValueType flags) :
+    m_flags(flags)
+{
+}
+
+//----------------------------------------------------------------------
+// Copy Constructor
+//----------------------------------------------------------------------
+Flags::Flags (const Flags& rhs) :
+    m_flags(rhs.m_flags)
+{
+}
+
+//----------------------------------------------------------------------
+// Virtual destructor in case anyone inherits from this class.
+//----------------------------------------------------------------------
+Flags::~Flags ()
+{
+}
+
+//----------------------------------------------------------------------
+// Get accessor for all of the current flag bits.
+//----------------------------------------------------------------------
+Flags::ValueType
+Flags::GetAllFlagBits () const
+{
+    return m_flags;
+}
+
+size_t
+Flags::GetBitSize() const
+{
+    return sizeof (ValueType) * 8;
+}
+
+//----------------------------------------------------------------------
+// Set accessor for all of the current flag bits.
+//----------------------------------------------------------------------
+void
+Flags::SetAllFlagBits (ValueType flags)
+{
+    m_flags = flags;
+}
+
+//----------------------------------------------------------------------
+// Clear one or more bits in our flag bits
+//----------------------------------------------------------------------
+Flags::ValueType
+Flags::Clear (ValueType bits)
+{
+    m_flags &= ~bits;
+    return m_flags;
+}
+
+//----------------------------------------------------------------------
+// Set one or more bits in our flag bits
+//----------------------------------------------------------------------
+Flags::ValueType
+Flags::Set (ValueType bits)
+{
+    m_flags |= bits;
+    return m_flags;
+}
+
+//----------------------------------------------------------------------
+// Returns true if any flag bits in "bits" are set
+//----------------------------------------------------------------------
+bool
+Flags::IsSet (ValueType bits) const
+{
+    return (m_flags & bits) != 0;
+}
+
+//----------------------------------------------------------------------
+// Returns true if all flag bits in "bits" are clear
+//----------------------------------------------------------------------
+bool
+Flags::IsClear (ValueType bits) const
+{
+    return (m_flags & bits) == 0;
+}
+
+
+size_t
+Flags::SetCount () const
+{
+    size_t count = 0;
+    for (ValueType mask = m_flags; mask; mask >>= 1)
+    {
+        if (mask & 1)
+            ++count;
+    }
+    return count;
+}
+
+size_t
+Flags::ClearCount () const
+{
+    size_t count = 0;
+    for (ValueType shift = 0; shift < sizeof(ValueType)*8; ++shift)
+    {
+        if ((m_flags & (1u << shift)) == 0)
+            ++count;
+    }
+    return count;
+}
diff --git a/source/Core/InputReader.cpp b/source/Core/InputReader.cpp
new file mode 100644
index 0000000..c139a87
--- /dev/null
+++ b/source/Core/InputReader.cpp
@@ -0,0 +1,343 @@
+//===-- InputReader.cpp -----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string>
+
+#include "lldb/Core/InputReader.h"
+#include "lldb/Core/Debugger.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+InputReader::InputReader () :
+    m_callback (NULL),
+    m_callback_baton (NULL),
+    m_end_token (),
+    m_granularity (eInputReaderGranularityInvalid),
+    m_done (true),
+    m_echo (true),
+    m_active (false)
+{
+}
+
+InputReader::~InputReader ()
+{
+}
+
+Error
+InputReader::Initialize 
+(
+    Callback callback, 
+    void *baton,
+    lldb::InputReaderGranularity granularity,
+    const char *end_token,
+    const char *prompt,
+    bool echo
+)
+{
+    Error err;
+    m_callback = callback;
+    m_callback_baton = baton,
+    m_granularity = granularity;
+    if (end_token != NULL)
+        m_end_token = end_token;
+    if (prompt != NULL)
+        m_prompt = prompt;
+    m_done = true;
+    m_echo = echo;
+
+    if (m_granularity == eInputReaderGranularityInvalid)
+    {
+        err.SetErrorString ("Invalid read token size:  Reader must be initialized with a token size other than 'eInputReaderGranularityInvalid'.");
+    }
+    else
+    if (end_token != NULL && granularity != eInputReaderGranularityInvalid)
+    {
+        if (granularity == eInputReaderGranularityByte)
+        {
+            // Check to see if end_token is longer than one byte.
+            
+            if (strlen (end_token) > 1)
+            {
+                err.SetErrorString ("Invalid end token:  End token cannot be larger than specified token size (byte).");
+            }
+        }
+        else if (granularity == eInputReaderGranularityWord)
+        {
+            // Check to see if m_end_token contains any white space (i.e. is multiple words).
+            
+            const char *white_space = " \t\n";
+            size_t pos = m_end_token.find_first_of (white_space);
+            if (pos != std::string::npos)
+            {
+                err.SetErrorString ("Invalid end token:  End token cannot be larger than specified token size (word).");
+            }
+        }
+        else
+        {
+            // Check to see if m_end_token contains any newlines; cannot handle multi-line end tokens.
+            
+            size_t pos = m_end_token.find_first_of ('\n');
+            if (pos != std::string::npos)
+            {
+                err.SetErrorString ("Invalid end token:  End token cannot contain a newline.");
+            }
+        }
+    }
+    
+    m_done = err.Fail();
+
+    return err;
+}
+
+size_t
+InputReader::HandleRawBytes (const char *bytes, size_t bytes_len)
+{
+    const char *end_token = NULL;
+    
+    if (m_end_token.empty() == false)
+    {
+        end_token = ::strstr (bytes, m_end_token.c_str());
+        if (end_token >= bytes + bytes_len)
+            end_token = NULL;
+    }
+
+    const char *p = bytes;
+    const char *end = bytes + bytes_len;
+
+    switch (m_granularity)
+    {
+    case eInputReaderGranularityInvalid:
+        break;
+
+    case eInputReaderGranularityByte:
+        while (p < end)
+        {
+            if (end_token == p)
+            {
+                p += m_end_token.size();
+                SetIsDone(true);
+                break;
+            }
+
+            if (m_callback (m_callback_baton, this, eInputReaderGotToken, p, 1) == 0)
+                break;
+            ++p;
+            if (IsDone())
+                break;
+        }
+        // Return how many bytes were handled.
+        return p - bytes;
+        break;
+
+
+    case eInputReaderGranularityWord:
+        {
+            char quote = '\0';
+            const char *word_start = NULL;
+            bool send_word = false;
+            for (; p < end; ++p, send_word = false)
+            {
+                if (end_token && end_token == p)
+                {
+                    p += m_end_token.size();
+                    SetIsDone(true);
+                    break;
+                }
+
+                const char ch = *p;
+                if (isspace(ch) && (!quote || (quote == ch && p[-1] != '\\')))
+                {
+                    // We have a space character or the terminating quote
+                    send_word = word_start != NULL;
+                    quote = '\0';
+                }
+                else if (quote)
+                {
+                    // We are in the middle of a quoted character
+                    continue;
+                }
+                else if (ch == '"' || ch == '\'' || ch == '`')
+                    quote = ch;
+                else if (word_start == NULL)
+                {
+                    // We have the first character in a word
+                    word_start = p;
+                }
+                
+                if (send_word)
+                {
+                    const size_t word_len = p - word_start;
+                    size_t bytes_handled = m_callback (m_callback_baton, 
+                                                       this, 
+                                                       eInputReaderGotToken, 
+                                                       word_start,
+                                                       word_len);
+
+                    if (bytes_handled != word_len)
+                        return word_start - bytes + bytes_handled;
+                    
+                    if (IsDone())
+                        return p - bytes;
+                }
+            }
+        }
+        break;
+
+
+    case eInputReaderGranularityLine:
+        {
+            const char *line_start = bytes;
+            const char *end_line = NULL;
+            const char *end = bytes + bytes_len;
+            while (p < end)
+            {
+                const char ch = *p;
+                if (ch == '\n' || ch == '\r')
+                {
+                    size_t line_length = p - line_start;
+                    // Now skip the newline character
+                    ++p; 
+                    // Skip a complete DOS newline if we run into one
+                    if (ch == 0xd && p < end && *p == 0xa)
+                        ++p;
+
+                    if (line_start <= end_token && end_token < line_start + line_length)
+                    {
+                        SetIsDone(true);
+                        m_callback (m_callback_baton, 
+                                    this, 
+                                    eInputReaderGotToken, 
+                                    line_start, 
+                                    end_token - line_start);
+                        
+                        return p - bytes;
+                    }
+
+                    size_t bytes_handled = m_callback (m_callback_baton, 
+                                                       this, 
+                                                       eInputReaderGotToken, 
+                                                       line_start, 
+                                                       line_length);
+
+                    end_line = p;
+
+                    if (bytes_handled != line_length)
+                    {
+                        // The input reader wasn't able to handle all the data
+                        return line_start - bytes + bytes_handled;
+                    }
+
+
+                    if (IsDone())
+                        return p - bytes;
+
+                    line_start = p;
+                }
+                else
+                {
+                    ++p;
+                }                
+            }
+            
+            if (end_line)
+                return end_line - bytes;
+        }
+        break;
+
+    
+    case eInputReaderGranularityAll:
+        {
+            // Nothing should be handle unless we see our end token
+            if (end_token)
+            {
+                size_t length = end_token - bytes;
+                size_t bytes_handled = m_callback (m_callback_baton, 
+                                                   this, 
+                                                   eInputReaderGotToken, 
+                                                   bytes, 
+                                                   length);
+                m_done = true;
+
+                p += bytes_handled + m_end_token.size();
+
+                // Consume any white space, such as newlines, beyond the end token
+
+                while (p < end && isspace(*p))
+                    ++p;
+
+                if (bytes_handled != length)
+                    return bytes_handled;
+                else
+                {
+                    return p - bytes;
+                    //return bytes_handled + m_end_token.size();
+                }
+            }
+            return 0;
+        }
+        break;
+    }
+    return 0;
+}
+
+
+FILE *
+InputReader::GetInputFileHandle ()
+{
+    return Debugger::GetSharedInstance().GetInputFileHandle ();
+}
+
+FILE *
+InputReader::GetOutputFileHandle ()
+{
+    return Debugger::GetSharedInstance().GetOutputFileHandle ();
+}
+
+const char *
+InputReader::GetPrompt () const
+{
+    if (!m_prompt.empty())
+        return m_prompt.c_str();
+    else
+        return NULL;
+}
+
+void
+InputReader::RefreshPrompt ()
+{
+    if (!m_prompt.empty())
+    {
+        FILE *out_fh = GetOutputFileHandle();
+        if (out_fh)
+            ::fprintf (out_fh, "%s", m_prompt.c_str());
+    }
+}
+
+void
+InputReader::Notify (InputReaderAction notification)
+{
+    switch (notification)
+    {
+    case eInputReaderActivate:
+    case eInputReaderReactivate:
+        m_active = true;
+        break;
+
+    case eInputReaderDeactivate:
+    case eInputReaderDone:
+        m_active = false;
+        break;
+    
+    case eInputReaderGotToken:
+        return; // We don't notify the tokens here, it is done in HandleRawBytes
+    }
+    if (m_callback)
+        m_callback (m_callback_baton, this, notification, NULL, 0);
+}
diff --git a/source/Core/Language.cpp b/source/Core/Language.cpp
new file mode 100644
index 0000000..82b4e4f
--- /dev/null
+++ b/source/Core/Language.cpp
@@ -0,0 +1,150 @@
+//===-- Language.cpp --------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/Language.h"
+#include "lldb/Core/Stream.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+#define ENUM_TO_DCSTREAM(x) case x: s->PutCString(#x); return
+
+typedef struct LanguageStrings
+{
+    const char * names[3];
+};
+
+static LanguageStrings
+g_languages[] =
+{
+    { "unknown" , NULL          , NULL                  },
+    { "c89"     , NULL          , "ISO C:1989"          },
+    { NULL      , NULL          , "K&R C"               },
+    { "ada83"   , "Ada83"       , "ISO Ada:1983"        },
+    { "c++"     , "cxx"         , "ISO C++:1998"        },
+    { "cobol74" , "Cobol74"     , "ISO Cobol:1974"      },
+    { "cobol"   , "Cobol85"     , "ISO Cobol:1985."     },
+    { "f77"     , "Fortran77"   , "ISO Fortran 77."     },
+    { "f90"     , "Fortran90"   , "ISO Fortran 90"      },
+    { "pascal"  , "Pascal83"    , "ISO Pascal:1983"     },
+    { "modula2" , "Modula2"     , "ISO Modula-2:1996"   },
+    { "java"    , NULL          , "Java"                },
+    { "c"       , "C99"         , "ISO C:1999"          },
+    { "ada"     , "Ada95"       , "ISO Ada:1995"        },
+    { "f95"     , "Fortran95"   , "ISO Fortran 95"      },
+    { "PLI"     , NULL          , "ANSI PL/I:1976"      },
+    { "objc"    , NULL          , "Objective-C"         },
+    { "objc++"  , NULL          , "Objective-C++"       },
+    { "upc"     , NULL          , "Unified Parallel C"  },
+    { "d"       , NULL          , "D"                   },
+    { "python"  , NULL          , "Python"              }
+};
+
+static const uint32_t
+g_num_languages = sizeof(g_languages)/sizeof(LanguageStrings);
+
+Language::Language(Language::Type language) :
+    m_language (language)
+{
+}
+
+Language::~Language()
+{
+}
+
+Language::Type
+Language::GetLanguage() const
+{
+    return m_language;
+}
+
+void
+Language::Clear ()
+{
+    m_language = Unknown;
+}
+
+void
+Language::SetLanguage(Language::Type language)
+{
+    m_language = language;
+}
+
+bool
+Language::SetLanguageFromCString(const char *language_cstr)
+{
+    size_t i, desc_idx;
+    const char *name;
+
+    // First check the most common name for the languages
+    for (desc_idx=lldb::eDescriptionLevelBrief; desc_idx<kNumDescriptionLevels; ++desc_idx)
+    {
+        for (i=0; i<g_num_languages; ++i)
+        {
+            name = g_languages[i].names[desc_idx];
+            if (name == NULL)
+                continue;
+
+            if (::strcasecmp (language_cstr, name) == 0)
+            {
+                m_language = (Language::Type)i;
+                return true;
+            }
+        }
+    }
+
+    m_language = Unknown;
+    return false;
+}
+
+
+const char *
+Language::AsCString (lldb::DescriptionLevel level) const
+{
+    if (m_language < g_num_languages && level < kNumDescriptionLevels)
+    {
+        const char *name = g_languages[m_language].names[level];
+        if (name)
+            return name;
+        else if (level + 1 < kNumDescriptionLevels)
+            return AsCString ((lldb::DescriptionLevel)(level + 1));
+        else
+            return NULL;
+    }
+    return NULL;
+}
+
+void
+Language::Dump(Stream *s) const
+{
+    GetDescription(s, lldb::eDescriptionLevelVerbose);
+}
+
+void
+Language::GetDescription (Stream *s, lldb::DescriptionLevel level) const
+{
+    const char *lang_cstr = AsCString(level);
+
+    if (lang_cstr)
+        s->PutCString(lang_cstr);
+    else
+        s->Printf("Language(language = 0x%4.4x)", m_language);
+}
+
+
+
+
+Stream&
+lldb_private::operator << (Stream& s, const Language& language)
+{
+    language.Dump(&s);
+    return s;
+}
+
diff --git a/source/Core/Listener.cpp b/source/Core/Listener.cpp
new file mode 100644
index 0000000..639b74a
--- /dev/null
+++ b/source/Core/Listener.cpp
@@ -0,0 +1,480 @@
+//===-- Listener.cpp --------------------------------------------*- 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/Listener.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Broadcaster.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/Event.h"
+#include "lldb/Host/TimeValue.h"
+#include "lldb/lldb-private-log.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+Listener::Listener(const char *name) :
+    m_name (name),
+    m_broadcasters(),
+    m_broadcasters_mutex (Mutex::eMutexTypeRecursive),
+    m_events (),
+    m_events_mutex (Mutex::eMutexTypeRecursive),
+    m_cond_wait()
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT);
+    if (log)
+        log->Printf ("%p Listener::Listener('%s')", this, m_name.c_str());
+}
+
+Listener::~Listener()
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT);
+    if (log)
+        log->Printf ("%p Listener::~Listener('%s')", this, m_name.c_str());
+    Clear();
+}
+
+void
+Listener::Clear()
+{
+    Mutex::Locker locker(m_broadcasters_mutex);
+    broadcaster_collection::iterator pos, end = m_broadcasters.end();
+    for (pos = m_broadcasters.begin(); pos != end; ++pos)
+        pos->first->RemoveListener (this, pos->second.event_mask);
+    m_broadcasters.clear();
+    m_cond_wait.SetValue (false, eBroadcastNever);
+    m_broadcasters.clear();
+}
+
+uint32_t
+Listener::StartListeningForEvents (Broadcaster* broadcaster, uint32_t event_mask)
+{
+    if (broadcaster)
+    {
+        // Scope for "locker"
+        // Tell the broadcaster to add this object as a listener
+        {
+            Mutex::Locker locker(m_broadcasters_mutex);
+            m_broadcasters.insert(std::make_pair(broadcaster, BroadcasterInfo(event_mask)));
+        }
+
+        uint32_t acquired_mask = broadcaster->AddListener (this, event_mask);
+
+        if (event_mask != acquired_mask)
+        {
+
+        }
+        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS);
+        if (log)
+            log->Printf ("%p Listener::StartListeningForEvents (broadcaster = %p, mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s",
+                         this,
+                         broadcaster,
+                         event_mask,
+                         acquired_mask,
+                         m_name.c_str());
+
+        return acquired_mask;
+
+    }
+    return 0;
+}
+
+uint32_t
+Listener::StartListeningForEvents (Broadcaster* broadcaster, uint32_t event_mask, HandleBroadcastCallback callback, void *callback_user_data)
+{
+    if (broadcaster)
+    {
+        // Scope for "locker"
+        // Tell the broadcaster to add this object as a listener
+        {
+            Mutex::Locker locker(m_broadcasters_mutex);
+            m_broadcasters.insert(std::make_pair(broadcaster, BroadcasterInfo(event_mask, callback, callback_user_data)));
+        }
+
+        uint32_t acquired_mask = broadcaster->AddListener (this, event_mask);
+
+        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS);
+        if (log)
+            log->Printf ("%p Listener::StartListeningForEvents (broadcaster = %p, mask = 0x%8.8x, callback = %p, user_data = %p) acquired_mask = 0x%8.8x for %s",
+                        this, broadcaster, event_mask, callback, callback_user_data, acquired_mask, m_name.c_str());
+
+        return acquired_mask;
+    }
+    return 0;
+}
+
+bool
+Listener::StopListeningForEvents (Broadcaster* broadcaster, uint32_t event_mask)
+{
+    if (broadcaster)
+    {
+        // Scope for "locker"
+        {
+            Mutex::Locker locker(m_broadcasters_mutex);
+            m_broadcasters.erase (broadcaster);
+        }
+        // Remove the broadcaster from our set of broadcasters
+        return broadcaster->RemoveListener (this, event_mask);
+    }
+
+    return false;
+}
+
+// Called when a Broadcaster is in its destuctor. We need to remove all
+// knowledge of this broadcaster and any events that it may have queued up
+void
+Listener::BroadcasterWillDestruct (Broadcaster *broadcaster)
+{
+    // Scope for "broadcasters_locker"
+    {
+        Mutex::Locker broadcasters_locker(m_broadcasters_mutex);
+        m_broadcasters.erase (broadcaster);
+    }
+
+    // Scope for "event_locker"
+    {
+        Mutex::Locker event_locker(m_events_mutex);
+        // Remove all events for this broadcaster object.
+        event_collection::iterator pos = m_events.begin();
+        while (pos != m_events.end())
+        {
+            if ((*pos)->GetBroadcaster() == broadcaster)
+                pos = m_events.erase(pos);
+            else
+                ++pos;
+        }
+
+        if (m_events.empty())
+            m_cond_wait.SetValue (false, eBroadcastNever);
+
+    }
+}
+
+void
+Listener::AddEvent (EventSP &event_sp)
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS);
+    if (log)
+        log->Printf ("%p Listener('%s')::AddEvent (event_sp = {%p})", this, m_name.c_str(), event_sp.get());
+
+    // Scope for "locker"
+    {
+        Mutex::Locker locker(m_events_mutex);
+        m_events.push_back (event_sp);
+    }
+    m_cond_wait.SetValue (true, eBroadcastAlways);
+}
+
+class EventBroadcasterMatches
+{
+public:
+    EventBroadcasterMatches (Broadcaster *broadcaster) :
+        m_broadcaster (broadcaster)    {
+    }
+
+    bool operator() (const EventSP &event_sp) const
+    {
+        if (event_sp->BroadcasterIs(m_broadcaster))
+            return true;
+        else
+            return false;
+    }
+
+private:
+    Broadcaster *m_broadcaster;
+
+};
+
+class EventMatcher
+{
+public:
+    EventMatcher (Broadcaster *broadcaster, const ConstString *broadcaster_names, uint32_t num_broadcaster_names, uint32_t event_type_mask) :
+        m_broadcaster (broadcaster),
+        m_broadcaster_names (broadcaster_names),
+        m_num_broadcaster_names (num_broadcaster_names),
+        m_event_type_mask (event_type_mask)
+    {
+    }
+
+    bool operator() (const EventSP &event_sp) const
+    {
+        if (m_broadcaster && !event_sp->BroadcasterIs(m_broadcaster))
+            return false;
+
+        if (m_broadcaster_names)
+        {
+            bool found_source = false;
+            const ConstString &event_broadcaster_name = event_sp->GetBroadcaster()->GetBroadcasterName();
+            for (uint32_t i=0; i<m_num_broadcaster_names; ++i)
+            {
+                if (m_broadcaster_names[i] == event_broadcaster_name)
+                {
+                    found_source = true;
+                    break;
+                }
+            }
+            if (!found_source)
+                return false;
+        }
+
+        if (m_event_type_mask == 0 || m_event_type_mask & event_sp->GetType())
+            return true;
+        return false;
+    }
+
+private:
+    Broadcaster *m_broadcaster;
+    const ConstString *m_broadcaster_names;
+    const uint32_t m_num_broadcaster_names;
+    const uint32_t m_event_type_mask;
+};
+
+
+bool
+Listener::FindNextEventInternal
+(
+    Broadcaster *broadcaster,   // NULL for any broadcaster
+    const ConstString *broadcaster_names, // NULL for any event
+    uint32_t num_broadcaster_names,
+    uint32_t event_type_mask,
+    EventSP &event_sp,
+    bool remove)
+{
+    //Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS);
+
+    Mutex::Locker lock(m_events_mutex);
+
+    if (m_events.empty())
+        return false;
+
+
+    Listener::event_collection::iterator pos = m_events.end();
+
+    if (broadcaster == NULL && broadcaster_names == NULL && event_type_mask == 0)
+    {
+        pos = m_events.begin();
+    }
+    else
+    {
+        pos = std::find_if (m_events.begin(), m_events.end(), EventMatcher (broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask));
+    }
+
+    if (pos != m_events.end())
+    {
+        event_sp = *pos;
+        if (remove)
+        {
+            m_events.erase(pos);
+
+            if (m_events.empty())
+                m_cond_wait.SetValue (false, eBroadcastNever);
+        }
+        
+        // Unlock the event queue here.  We've removed this event and are about to return
+        // it so it should be okay to get the next event off the queue here - and it might
+        // be useful to do that in the "DoOnRemoval".
+        lock.Reset();
+        event_sp->DoOnRemoval();
+        return true;
+    }
+
+    event_sp.reset();
+    return false;
+}
+
+Event *
+Listener::PeekAtNextEvent ()
+{
+    EventSP event_sp;
+    if (FindNextEventInternal (NULL, NULL, 0, 0, event_sp, false))
+        return event_sp.get();
+    return NULL;
+}
+
+Event *
+Listener::PeekAtNextEventForBroadcaster (Broadcaster *broadcaster)
+{
+    EventSP event_sp;
+    if (FindNextEventInternal (broadcaster, NULL, 0, 0, event_sp, false))
+        return event_sp.get();
+    return NULL;
+}
+
+Event *
+Listener::PeekAtNextEventForBroadcasterWithType (Broadcaster *broadcaster, uint32_t event_type_mask)
+{
+    EventSP event_sp;
+    if (FindNextEventInternal (broadcaster, NULL, 0, event_type_mask, event_sp, false))
+        return event_sp.get();
+    return NULL;
+}
+
+
+bool
+Listener::GetNextEventInternal
+(
+    Broadcaster *broadcaster,   // NULL for any broadcaster
+    const ConstString *broadcaster_names, // NULL for any event
+    uint32_t num_broadcaster_names,
+    uint32_t event_type_mask,
+    EventSP &event_sp
+)
+{
+    return FindNextEventInternal (broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask, event_sp, true);
+}
+
+bool
+Listener::GetNextEvent (EventSP &event_sp)
+{
+    return GetNextEventInternal (NULL, NULL, 0, 0, event_sp);
+}
+
+
+bool
+Listener::GetNextEventForBroadcaster (Broadcaster *broadcaster, EventSP &event_sp)
+{
+    return GetNextEventInternal (broadcaster, NULL, 0, 0, event_sp);
+}
+
+bool
+Listener::GetNextEventForBroadcasterWithType (Broadcaster *broadcaster, uint32_t event_type_mask, EventSP &event_sp)
+{
+    return GetNextEventInternal (broadcaster, NULL, 0, event_type_mask, event_sp);
+}
+
+
+bool
+Listener::WaitForEventsInternal
+(
+    const TimeValue *timeout,
+    Broadcaster *broadcaster,   // NULL for any broadcaster
+    const ConstString *broadcaster_names, // NULL for any event
+    uint32_t num_broadcaster_names,
+    uint32_t event_type_mask,
+    EventSP &event_sp
+)
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS);
+    bool timed_out = false;
+
+    if (log)
+    {
+        log->Printf ("%p Listener::WaitForEventsInternal (timeout = { %p }) for %s",
+                    this, timeout, m_name.c_str());
+    }
+
+    while (1)
+    {
+        if (GetNextEventInternal (broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask, event_sp))
+            return true;
+
+        // Reset condition value to false, so we can wait for new events to be
+        // added that might meet our current filter
+        m_cond_wait.SetValue (false, eBroadcastNever);
+
+        if (m_cond_wait.WaitForValueEqualTo (true, timeout, &timed_out))
+            continue;
+
+        else if (timed_out)
+        {
+            if (log)
+                log->Printf ("%p Listener::WaitForEvents() timed out for %s", this, m_name.c_str());
+            break;
+        }
+        else
+        {
+            if (log)
+                log->Printf ("%p Listener::WaitForEvents() unknown error for %s", this, m_name.c_str());
+            break;
+        }
+    }
+
+    return false;
+}
+
+bool
+Listener::WaitForEventForBroadcasterWithType
+(
+    const TimeValue *timeout,
+    Broadcaster *broadcaster,
+    uint32_t event_type_mask,
+    EventSP &event_sp
+)
+{
+    return WaitForEventsInternal (timeout, broadcaster, NULL, 0, event_type_mask, event_sp);
+}
+
+bool
+Listener::WaitForEventForBroadcaster
+(
+    const TimeValue *timeout,
+    Broadcaster *broadcaster,
+    EventSP &event_sp
+)
+{
+    return WaitForEventsInternal (timeout, broadcaster, NULL, 0, 0, event_sp);
+}
+
+bool
+Listener::WaitForEvent (const TimeValue *timeout, EventSP &event_sp)
+{
+    return WaitForEventsInternal (timeout, NULL, NULL, 0, 0, event_sp);
+}
+
+//Listener::broadcaster_collection::iterator
+//Listener::FindBroadcasterWithMask (Broadcaster *broadcaster, uint32_t event_mask, bool exact)
+//{
+//    broadcaster_collection::iterator pos;
+//    broadcaster_collection::iterator end = m_broadcasters.end();
+//    for (pos = m_broadcasters.find (broadcaster);
+//        pos != end && pos->first == broadcaster;
+//        ++pos)
+//    {
+//        if (exact)
+//        {
+//            if ((event_mask & pos->second.event_mask) == event_mask)
+//                return pos;
+//        }
+//        else
+//        {
+//            if (event_mask & pos->second.event_mask)
+//                return pos;
+//        }
+//    }
+//    return end;
+//}
+
+size_t
+Listener::HandleBroadcastEvent (EventSP &event_sp)
+{
+    size_t num_handled = 0;
+    Mutex::Locker locker(m_broadcasters_mutex);
+    Broadcaster *broadcaster = event_sp->GetBroadcaster();
+    broadcaster_collection::iterator pos;
+    broadcaster_collection::iterator end = m_broadcasters.end();
+    for (pos = m_broadcasters.find (broadcaster);
+        pos != end && pos->first == broadcaster;
+        ++pos)
+    {
+        BroadcasterInfo info = pos->second;
+        if (event_sp->GetType () & info.event_mask)
+        {
+            if (info.callback != NULL)
+            {
+                info.callback (event_sp, info.callback_user_data);
+                ++num_handled;
+            }
+        }
+    }
+    return num_handled;
+}
diff --git a/source/Core/Log.cpp b/source/Core/Log.cpp
new file mode 100644
index 0000000..fe20716
--- /dev/null
+++ b/source/Core/Log.cpp
@@ -0,0 +1,590 @@
+//===-- Log.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 <mach/mach.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+// C++ Includes
+#include <map>
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/TimeValue.h"
+#include "lldb/Host/Mutex.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static Stream *
+StreamForSTDOUTAccess (bool set, StreamSP &stream_sp)
+{
+    // Since we are in a shared library and we can't have global
+    // constructors, we need to control access to this static variable
+    // through an accessor function to get and set the value.
+    static StreamSP g_stream_sp;
+
+    if (set)
+        g_stream_sp = stream_sp;
+    else
+    {
+        if (g_stream_sp)
+            stream_sp = g_stream_sp;
+        else
+        {
+            FILE *out_fh = Debugger::GetSharedInstance().GetOutputFileHandle();
+            if (out_fh)
+                stream_sp.reset(new StreamFile(out_fh));
+            else
+                stream_sp.reset();
+        }
+    }
+    return stream_sp.get();
+}
+
+StreamSP
+Log::GetStreamForSTDOUT ()
+{
+    StreamSP stream_sp;
+    StreamForSTDOUTAccess (false, stream_sp);
+    return stream_sp;
+}
+
+void
+Log::SetStreamForSTDOUT (StreamSP &stream_sp)
+{
+    StreamForSTDOUTAccess (true, stream_sp);
+}
+
+void
+Log::STDOUT (const char *format, ...)
+{
+    StreamSP stream_sp;
+    if (StreamForSTDOUTAccess(false, stream_sp))
+    {
+        va_list args;
+        va_start (args, format);
+        stream_sp->PrintfVarArg(format, args);
+        va_end (args);
+    }
+}
+
+static Stream *
+StreamForSTDERRAccess (bool set, StreamSP &stream_sp)
+{
+    // Since we are in a shared library and we can't have global
+    // constructors, we need to control access to this static variable
+    // through an accessor function to get and set the value.
+    static StreamSP g_stream_sp(new StreamFile(Debugger::GetSharedInstance().GetErrorFileHandle()));
+
+    if (set)
+        g_stream_sp = stream_sp;
+    else
+        stream_sp = g_stream_sp;
+    return stream_sp.get();
+}
+
+StreamSP
+Log::GetStreamForSTDERR ()
+{
+    StreamSP stream_sp;
+    StreamForSTDERRAccess (false, stream_sp);
+    return stream_sp;
+}
+
+void
+Log::SetStreamForSTDERR (StreamSP &stream_sp)
+{
+    StreamForSTDERRAccess (true, stream_sp);
+}
+
+void
+Log::STDERR (const char *format, ...)
+{
+    StreamSP stream_sp;
+    if (StreamForSTDERRAccess(false, stream_sp))
+    {
+        va_list args;
+        va_start (args, format);
+        stream_sp->PrintfVarArg(format, args);
+        va_end (args);
+    }
+}
+
+Log::Log () :
+    m_stream_sp(),
+    m_options(0),
+    m_mask_bits(0)
+{
+}
+
+Log::Log (StreamSP &stream_sp) :
+    m_stream_sp(stream_sp),
+    m_options(0),
+    m_mask_bits(0)
+{
+}
+
+Log::~Log ()
+{
+}
+
+Flags &
+Log::GetOptions()
+{
+    return m_options;
+}
+
+const Flags &
+Log::GetOptions() const
+{
+    return m_options;
+}
+
+Flags &
+Log::GetMask()
+{
+    return m_mask_bits;
+}
+
+const Flags &
+Log::GetMask() const
+{
+    return m_mask_bits;
+}
+
+
+//----------------------------------------------------------------------
+// All logging eventually boils down to this function call. If we have
+// a callback registered, then we call the logging callback. If we have
+// a valid file handle, we also log to the file.
+//----------------------------------------------------------------------
+void
+Log::PrintfWithFlagsVarArg (uint32_t flags, const char *format, va_list args)
+{
+    if (m_stream_sp)
+    {
+        static uint32_t g_sequence_id = 0;
+        StreamString header;
+        static Mutex g_LogThreadedMutex(Mutex::eMutexTypeRecursive);
+
+        Mutex::Locker locker;
+
+        uint32_t log_options = m_options.GetAllFlagBits();
+
+        // Lock the threaded logging mutex if we are doing thread safe logging
+        if (log_options & LLDB_LOG_OPTION_THREADSAFE)
+            locker.Reset(g_LogThreadedMutex.GetMutex());
+
+        // Add a sequence ID if requested
+        if (log_options & LLDB_LOG_OPTION_PREPEND_SEQUENCE)
+            header.Printf ("%u ", ++g_sequence_id);
+
+        // Timestamp if requested
+        if (log_options & LLDB_LOG_OPTION_PREPEND_TIMESTAMP)
+        {
+            struct timeval tv = TimeValue::Now().GetAsTimeVal();
+            header.Printf ("%9llu.%6.6llu ", tv.tv_sec, tv.tv_usec);
+        }
+
+        // Add the process and thread if requested
+        if (log_options & LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD)
+            header.Printf ("[%4.4x/%4.4x]: ", getpid(), mach_thread_self());
+
+        // Add the process and thread if requested
+        if (log_options & LLDB_LOG_OPTION_PREPEND_THREAD_NAME)
+        {
+            const char *thread_name_str = Host::GetThreadName (getpid(), mach_thread_self());
+            if (thread_name_str)
+                header.Printf ("%s ", thread_name_str);
+        }
+
+        header.PrintfVarArg (format, args);
+        m_stream_sp->Printf("%s\n", header.GetData());
+    }
+}
+
+
+void
+Log::PutCString (const char *cstr)
+{
+    Printf ("%s", cstr);
+}
+
+
+//----------------------------------------------------------------------
+// Simple variable argument logging with flags.
+//----------------------------------------------------------------------
+void
+Log::Printf(const char *format, ...)
+{
+    va_list args;
+    va_start (args, format);
+    PrintfWithFlagsVarArg (0, format, args);
+    va_end (args);
+}
+
+void
+Log::VAPrintf (const char *format, va_list args)
+{
+    PrintfWithFlagsVarArg (0, format, args);
+}
+
+
+//----------------------------------------------------------------------
+// Simple variable argument logging with flags.
+//----------------------------------------------------------------------
+void
+Log::PrintfWithFlags (uint32_t flags, const char *format, ...)
+{
+    va_list args;
+    va_start (args, format);
+    PrintfWithFlagsVarArg (flags, format, args);
+    va_end (args);
+}
+
+//----------------------------------------------------------------------
+// Print debug strings if and only if the global debug option is set to
+// a non-zero value.
+//----------------------------------------------------------------------
+void
+Log::Debug (const char *format, ...)
+{
+    if (GetOptions().IsSet(LLDB_LOG_OPTION_DEBUG))
+    {
+        va_list args;
+        va_start (args, format);
+        PrintfWithFlagsVarArg (LLDB_LOG_FLAG_DEBUG, format, args);
+        va_end (args);
+    }
+}
+
+
+//----------------------------------------------------------------------
+// Print debug strings if and only if the global debug option is set to
+// a non-zero value.
+//----------------------------------------------------------------------
+void
+Log::DebugVerbose (const char *format, ...)
+{
+    if (GetOptions().IsSet(LLDB_LOG_OPTION_DEBUG) && GetOptions().IsSet(LLDB_LOG_OPTION_VERBOSE))
+    {
+        va_list args;
+        va_start (args, format);
+        PrintfWithFlagsVarArg (LLDB_LOG_FLAG_DEBUG | LLDB_LOG_FLAG_VERBOSE, format, args);
+        va_end (args);
+    }
+}
+
+
+//----------------------------------------------------------------------
+// Log only if all of the bits are set
+//----------------------------------------------------------------------
+void
+Log::LogIf (uint32_t bits, const char *format, ...)
+{
+    if ((bits & m_options.GetAllFlagBits()) == bits)
+    {
+        va_list args;
+        va_start (args, format);
+        PrintfWithFlagsVarArg (0, format, args);
+        va_end (args);
+    }
+}
+
+
+//----------------------------------------------------------------------
+// Printing of errors that are not fatal.
+//----------------------------------------------------------------------
+void
+Log::Error (const char *format, ...)
+{
+    char *arg_msg = NULL;
+    va_list args;
+    va_start (args, format);
+    ::vasprintf (&arg_msg, format, args);
+    va_end (args);
+
+    if (arg_msg != NULL)
+    {
+        PrintfWithFlags (LLDB_LOG_FLAG_ERROR, "error: %s", arg_msg);
+        free (arg_msg);
+    }
+}
+
+//----------------------------------------------------------------------
+// Printing of errors that ARE fatal. Exit with ERR exit code
+// immediately.
+//----------------------------------------------------------------------
+void
+Log::FatalError (int err, const char *format, ...)
+{
+    char *arg_msg = NULL;
+    va_list args;
+    va_start (args, format);
+    ::vasprintf (&arg_msg, format, args);
+    va_end (args);
+
+    if (arg_msg != NULL)
+    {
+        PrintfWithFlags (LLDB_LOG_FLAG_ERROR | LLDB_LOG_FLAG_FATAL, "error: %s", arg_msg);
+        ::free (arg_msg);
+    }
+    ::exit (err);
+}
+
+
+//----------------------------------------------------------------------
+// Printing of warnings that are not fatal only if verbose mode is
+// enabled.
+//----------------------------------------------------------------------
+void
+Log::Verbose (const char *format, ...)
+{
+    if (m_options.IsSet(LLDB_LOG_OPTION_VERBOSE))
+    {
+        va_list args;
+        va_start (args, format);
+        PrintfWithFlagsVarArg (LLDB_LOG_FLAG_VERBOSE, format, args);
+        va_end (args);
+    }
+}
+
+//----------------------------------------------------------------------
+// Printing of warnings that are not fatal only if verbose mode is
+// enabled.
+//----------------------------------------------------------------------
+void
+Log::WarningVerbose (const char *format, ...)
+{
+    if (m_options.IsSet(LLDB_LOG_OPTION_VERBOSE))
+    {
+        char *arg_msg = NULL;
+        va_list args;
+        va_start (args, format);
+        ::vasprintf (&arg_msg, format, args);
+        va_end (args);
+
+        if (arg_msg != NULL)
+        {
+            PrintfWithFlags (LLDB_LOG_FLAG_WARNING | LLDB_LOG_FLAG_VERBOSE, "warning: %s", arg_msg);
+            free (arg_msg);
+        }
+    }
+}
+//----------------------------------------------------------------------
+// Printing of warnings that are not fatal.
+//----------------------------------------------------------------------
+void
+Log::Warning (const char *format, ...)
+{
+    char *arg_msg = NULL;
+    va_list args;
+    va_start (args, format);
+    ::vasprintf (&arg_msg, format, args);
+    va_end (args);
+
+    if (arg_msg != NULL)
+    {
+        PrintfWithFlags (LLDB_LOG_FLAG_WARNING, "warning: %s", arg_msg);
+        free (arg_msg);
+    }
+}
+
+typedef std::map <std::string, Log::Callbacks> CallbackMap;
+typedef CallbackMap::iterator CallbackMapIter;
+
+typedef std::map <ConstString, LogChannelSP> LogChannelMap;
+typedef LogChannelMap::iterator LogChannelMapIter;
+
+
+// Surround our callback map with a singleton function so we don't have any
+// global initializers.
+static CallbackMap &
+GetCallbackMap ()
+{
+    static CallbackMap g_callback_map;
+    return g_callback_map;
+}
+
+static LogChannelMap &
+GetChannelMap ()
+{
+    static LogChannelMap g_channel_map;
+    return g_channel_map;
+}
+
+void
+Log::RegisterLogChannel (const char *channel, const Log::Callbacks &log_callbacks)
+{
+    GetCallbackMap().insert(std::make_pair(channel, log_callbacks));
+}
+
+bool
+Log::UnregisterLogChannel (const char *channel)
+{
+    return GetCallbackMap().erase(channel) != 0;
+}
+
+bool
+Log::GetLogChannelCallbacks (const char *channel, Log::Callbacks &log_callbacks)
+{
+    CallbackMap &callback_map = GetCallbackMap ();
+    CallbackMapIter pos = callback_map.find(channel);
+    if (pos != callback_map.end())
+    {
+        log_callbacks = pos->second;
+        return true;
+    }
+    ::bzero (&log_callbacks, sizeof(log_callbacks));
+    return false;
+}
+
+void
+Log::EnableAllLogChannels
+(
+    StreamSP &log_stream_sp,
+    uint32_t log_options,
+    Args &args,
+    Stream *feedback_strm
+)
+{
+    CallbackMap &callback_map = GetCallbackMap ();
+    CallbackMapIter pos, end = callback_map.end();
+
+    for (pos = callback_map.begin(); pos != end; ++pos)
+        pos->second.enable (log_stream_sp, log_options, args, feedback_strm);
+
+    LogChannelMap &channel_map = GetChannelMap ();
+    LogChannelMapIter channel_pos, channel_end = channel_map.end();
+    for (channel_pos = channel_map.begin(); channel_pos != channel_end; ++channel_pos)
+    {
+        channel_pos->second->Enable (log_stream_sp, log_options, feedback_strm, args);
+    }
+
+}
+
+void
+Log::DisableAllLogChannels ()
+{
+    CallbackMap &callback_map = GetCallbackMap ();
+    CallbackMapIter pos, end = callback_map.end();
+
+    for (pos = callback_map.begin(); pos != end; ++pos)
+        pos->second.disable ();
+
+    LogChannelMap &channel_map = GetChannelMap ();
+    LogChannelMapIter channel_pos, channel_end = channel_map.end();
+    for (channel_pos = channel_map.begin(); channel_pos != channel_end; ++channel_pos)
+        channel_pos->second->Disable ();
+}
+
+void
+Log::ListAllLogChannels (Stream *strm)
+{
+    CallbackMap &callback_map = GetCallbackMap ();
+    LogChannelMap &channel_map = GetChannelMap ();
+
+    if (callback_map.empty() && channel_map.empty())
+    {
+        strm->PutCString ("No logging channels are currently registered.\n");
+        return;
+    }
+
+    CallbackMapIter pos, end = callback_map.end();
+    for (pos = callback_map.begin(); pos != end; ++pos)
+        pos->second.list_categories (strm);
+
+    uint32_t idx = 0;
+    const char *name;
+    for (idx = 0; (name = PluginManager::GetLogChannelCreateNameAtIndex (idx)) != NULL; ++idx)
+    {
+        LogChannelSP log_channel_sp(LogChannel::FindPlugin (name));
+        if (log_channel_sp)
+            log_channel_sp->ListCategories (strm);
+    }
+}
+
+bool
+Log::GetVerbose() const
+{
+    if (m_stream_sp)
+        return m_stream_sp->GetVerbose();
+    return false;
+}
+
+//------------------------------------------------------------------
+// Returns true if the debug flag bit is set in this stream.
+//------------------------------------------------------------------
+bool
+Log::GetDebug() const
+{
+    if (m_stream_sp)
+        return m_stream_sp->GetDebug();
+    return false;
+}
+
+
+LogChannelSP
+LogChannel::FindPlugin (const char *plugin_name)
+{
+    LogChannelSP log_channel_sp;
+    LogChannelMap &channel_map = GetChannelMap ();
+    ConstString log_channel_name (plugin_name);
+    LogChannelMapIter pos = channel_map.find (log_channel_name);
+    if (pos == channel_map.end())
+    {
+        LogChannelCreateInstance create_callback  = PluginManager::GetLogChannelCreateCallbackForPluginName (plugin_name);
+        if (create_callback)
+        {
+            log_channel_sp.reset(create_callback());
+            if (log_channel_sp)
+            {
+                // Cache the one and only loaded instance of each log channel
+                // plug-in after it has been loaded once.
+                channel_map[log_channel_name] = log_channel_sp;
+            }
+        }
+    }
+    else
+    {
+        // We have already loaded an instance of this log channel class,
+        // so just return the cached instance.
+        log_channel_sp = pos->second;
+    }
+    return log_channel_sp;
+}
+
+LogChannel::LogChannel () :
+    m_log_sp ()
+{
+}
+
+LogChannel::~LogChannel ()
+{
+}
+
+const char *
+LogChannel::GetPluginSuffix ()
+{
+    return ".log-channel";
+}
+
+
diff --git a/source/Core/Mangled.cpp b/source/Core/Mangled.cpp
new file mode 100644
index 0000000..38667a8
--- /dev/null
+++ b/source/Core/Mangled.cpp
@@ -0,0 +1,733 @@
+//===-- Mangled.cpp ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <cxxabi.h>
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Mangled.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/Timer.h"
+
+using namespace lldb_private;
+
+#pragma mark Mangled
+//----------------------------------------------------------------------
+// Default constructor
+//----------------------------------------------------------------------
+Mangled::Mangled () :
+    m_mangled(),
+    m_demangled()
+{
+}
+
+//----------------------------------------------------------------------
+// Constructor with an optional string and a boolean indicating if it is
+// the mangled version.
+//----------------------------------------------------------------------
+Mangled::Mangled (const char *s, bool mangled) :
+    m_mangled(),
+    m_demangled()
+{
+    if (s && s[0])
+    {
+        SetValue(s, mangled);
+    }
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+Mangled::~Mangled ()
+{
+}
+
+//----------------------------------------------------------------------
+// Convert to pointer operator. This allows code to check any Mangled
+// objects to see if they contain anything valid using code such as:
+//
+//  Mangled mangled(...);
+//  if (mangled)
+//  { ...
+//----------------------------------------------------------------------
+Mangled::operator void* () const
+{
+    return (m_mangled) ? const_cast<Mangled*>(this) : NULL;
+}
+
+//----------------------------------------------------------------------
+// Logical NOT operator. This allows code to check any Mangled
+// objects to see if they are invalid using code such as:
+//
+//  Mangled mangled(...);
+//  if (!file_spec)
+//  { ...
+//----------------------------------------------------------------------
+bool
+Mangled::operator! () const
+{
+    return !m_mangled;
+}
+
+//----------------------------------------------------------------------
+// Clear the mangled and demangled values.
+//----------------------------------------------------------------------
+void
+Mangled::Clear ()
+{
+    m_mangled.Clear();
+    m_demangled.Clear();
+}
+
+
+//----------------------------------------------------------------------
+// Compare the the string values.
+//----------------------------------------------------------------------
+int
+Mangled::Compare (const Mangled& a, const Mangled& b)
+{
+    return ConstString::Compare(a.GetName(), a.GetName());
+}
+
+
+
+//----------------------------------------------------------------------
+// Set the string value in this objects. If "mangled" is true, then
+// the mangled named is set with the new value in "s", else the
+// demangled name is set.
+//----------------------------------------------------------------------
+void
+Mangled::SetValue (const char *s, bool mangled)
+{
+    m_mangled.Clear();
+    m_demangled.Clear();
+
+    if (s)
+    {
+        if (mangled)
+            m_mangled.SetCString (s);
+        else
+            m_demangled.SetCString(s);
+    }
+}
+
+
+//----------------------------------------------------------------------
+// Generate the demangled name on demand using this accessor. Code in
+// this class will need to use this accessor if it wishes to decode
+// the demangled name. The result is cached and will be kept until a
+// new string value is supplied to this object, or until the end of the
+// object's lifetime.
+//----------------------------------------------------------------------
+const ConstString&
+Mangled::GetDemangledName () const
+{
+    // Check to make sure we have a valid mangled name and that we
+    // haven't already decoded our mangled name.
+    if (m_mangled && !m_demangled)
+    {
+        // We need to generate and cache the demangled name.
+        Timer scoped_timer (__PRETTY_FUNCTION__,
+                            "Mangled::GetDemangledName (m_mangled = %s)",
+                            m_mangled.GetCString());
+
+        // We already know mangled is valid from the above check,
+        // lets just make sure it isn't empty...
+        const char * mangled = m_mangled.AsCString();
+        if (mangled[0])
+        {
+            // The first time the demangling routine is called, it will
+            // return a buffer value and length and we will continue to
+            // re-use that buffer so we don't always have to malloc/free
+            // a buffer for each demangle. The buffer can be realloc'ed
+            // by abi::__cxa_demangle, so we may need to make it thread
+            // specific if we ever start doing multi-threaded calls to
+            // this function. g_demangle_buf will currently leak one
+            // malloc entry that can vary in size. If we need to reclaim
+            // this memory, we will need to add some code to free this
+            // buffer at exit time.
+            static char *g_demangle_buf = NULL;
+            static size_t g_demangle_buf_len = 0;
+            int status = 0;
+            g_demangle_buf = abi::__cxa_demangle(mangled, g_demangle_buf, &g_demangle_buf_len, &status);
+            if (g_demangle_buf != NULL)
+            {
+                m_demangled.SetCString(g_demangle_buf);
+            }
+            else
+            {
+                // Set the demangled string to the empty string to indicate we
+                // tried to parse it once and failed.
+                m_demangled.SetCString("");
+            }
+        }
+    }
+
+    return m_demangled;
+}
+
+//----------------------------------------------------------------------
+// Mangled name get accessor
+//----------------------------------------------------------------------
+ConstString&
+Mangled::GetMangledName ()
+{
+    return m_mangled;
+}
+
+//----------------------------------------------------------------------
+// Mangled name const get accessor
+//----------------------------------------------------------------------
+const ConstString&
+Mangled::GetMangledName () const
+{
+    return m_mangled;
+}
+
+//----------------------------------------------------------------------
+// Get the demangled name if there is one, else return the mangled name.
+//----------------------------------------------------------------------
+const ConstString&
+Mangled::GetName () const
+{
+    const ConstString& name = GetDemangledName();
+    if (name && !name.IsEmpty())
+        return name;
+    return m_mangled;
+}
+
+//----------------------------------------------------------------------
+// Generate the tokens from the demangled name.
+//
+// Returns the number of tokens that were parsed.
+//----------------------------------------------------------------------
+size_t
+Mangled::GetTokens (Mangled::TokenList &tokens) const
+{
+    tokens.Clear();
+    const ConstString& demangled = GetDemangledName();
+    if (demangled && !demangled.IsEmpty())
+        tokens.Parse(demangled.AsCString());
+
+    return tokens.Size();
+}
+
+//----------------------------------------------------------------------
+// Dump a Mangled object to stream "s". We don't force our
+// demangled name to be computed currently (we don't use the accessor).
+//----------------------------------------------------------------------
+void
+Mangled::Dump (Stream *s) const
+{
+    if (m_mangled)
+    {
+        *s << ", mangled = " << m_mangled;
+    }
+    if (m_demangled)
+    {
+        const char * demangled = m_demangled.AsCString();
+        s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>");
+    }
+}
+
+//----------------------------------------------------------------------
+// Dumps a debug version of this string with extra object and state
+// information to stream "s".
+//----------------------------------------------------------------------
+void
+Mangled::DumpDebug (Stream *s) const
+{
+    s->Printf("%*p: Mangled mangled = ", (int)sizeof(void*) * 2, this);
+    m_mangled.DumpDebug(s);
+    s->Printf(", demangled = ");
+    m_demangled.DumpDebug(s);
+}
+
+//----------------------------------------------------------------------
+// Return the size in byte that this object takes in memory. The size
+// includes the size of the objects it owns, and not the strings that
+// it references because they are shared strings.
+//----------------------------------------------------------------------
+size_t
+Mangled::MemorySize () const
+{
+    return m_mangled.MemorySize() + m_demangled.MemorySize();
+}
+
+//----------------------------------------------------------------------
+// Dump OBJ to the supplied stream S.
+//----------------------------------------------------------------------
+Stream&
+operator << (Stream& s, const Mangled& obj)
+{
+    if (obj.GetMangledName())
+        s << "mangled = '" << obj.GetMangledName() << "'";
+
+    const ConstString& demangled = obj.GetDemangledName();
+    if (demangled)
+        s << ", demangled = '" << demangled << '\'';
+    else
+        s << ", demangled = <error>";
+    return s;
+}
+
+
+
+
+#pragma mark Mangled::Token
+
+//--------------------------------------------------------------
+// Default constructor
+//--------------------------------------------------------------
+Mangled::Token::Token () :
+    type(eInvalid),
+    value()
+{
+}
+
+//--------------------------------------------------------------
+// Equal to operator
+//--------------------------------------------------------------
+bool
+Mangled::Token::operator== (const Token& rhs) const
+{
+    return type == rhs.type && value == rhs.value;
+}
+
+//--------------------------------------------------------------
+// Dump the token to a stream "s"
+//--------------------------------------------------------------
+void
+Mangled::Token::Dump (Stream *s) const
+{
+    switch (type)
+    {
+    case eInvalid:      s->PutCString("invalid    "); break;
+    case eNameSpace:    s->PutCString("namespace  "); break;
+    case eMethodName:   s->PutCString("method     "); break;
+    case eType:         s->PutCString("type       "); break;
+    case eTemplate:     s->PutCString("template   "); break;
+    case eTemplateBeg:  s->PutCString("template < "); break;
+    case eTemplateEnd:  s->PutCString("template > "); break;
+    case eParamsBeg:    s->PutCString("params   ( "); break;
+    case eParamsEnd:    s->PutCString("params   ) "); break;
+    case eQualifier:    s->PutCString("qualifier  "); break;
+    case eError:        s->PutCString("ERROR      "); break;
+    default:
+        s->Printf("type = %i", type);
+        break;
+    }
+    value.DumpDebug(s);
+}
+
+//--------------------------------------------------------------
+// Returns true if this token is a wildcard
+//--------------------------------------------------------------
+bool
+Mangled::Token::IsWildcard () const
+{
+    static ConstString g_wildcard_str("*");
+    return value == g_wildcard_str;
+}
+
+
+//----------------------------------------------------------------------
+// Dump "obj" to the supplied stream "s"
+//----------------------------------------------------------------------
+Stream&
+lldb_private::operator << (Stream& s, const Mangled::Token& obj)
+{
+    obj.Dump(&s);
+    return s;
+}
+
+
+#pragma mark Mangled::TokenList
+//----------------------------------------------------------------------
+// Mangled::TokenList
+//----------------------------------------------------------------------
+
+//--------------------------------------------------------------
+// Default constructor. If demangled is non-NULL and not-empty
+// the token list will parse up the demangled string it is
+// given, else the object will initialize an empty token list.
+//--------------------------------------------------------------
+Mangled::TokenList::TokenList (const char *demangled) :
+    m_tokens()
+{
+    if (demangled && demangled[0])
+    {
+        Parse(demangled);
+    }
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+Mangled::TokenList::~TokenList ()
+{
+}
+
+//----------------------------------------------------------------------
+// Parses "demangled" into tokens. This allows complex
+// comparisons to be done. Comparisons can include wildcards at
+// the namespace, method name, template, and template and
+// parameter type levels.
+//
+// Example queries include:
+// "std::basic_string<*>"   // Find all std::basic_string variants
+// "std::basic_string<*>::erase(*)" // Find all std::basic_string::erase variants with any number of parameters
+// "*::clear()"             // Find all functions with a method name of
+//                          // "clear" that are in any namespace that
+//                          // have no parameters
+// "::printf"               // Find the printf function in the global namespace
+// "printf"                 // Ditto
+// "foo::*(int)"            // Find all functions in the class or namespace "foo" that take a single integer argument
+//
+// Returns the number of tokens that were decoded, or zero when
+// we fail.
+//----------------------------------------------------------------------
+size_t
+Mangled::TokenList::Parse (const char *s)
+{
+    m_tokens.clear();
+
+    Token token;
+    token.type = eNameSpace;
+
+    TokenType max_type = eInvalid;
+    const char *p = s;
+    size_t span = 0;
+    size_t sep_size = 0;
+
+    while (*p != '\0')
+    {
+        p = p + span + sep_size;
+        while (isspace(*p))
+            ++p;
+
+        if (*p == '\0')
+            break;
+
+        span = strcspn(p, ":<>(),");
+        sep_size = 1;
+        token.type = eInvalid;
+        switch (p[span])
+        {
+        case '\0':
+            break;
+
+        case ':':
+            if (p[span+1] == ':')
+            {
+                sep_size = 2;
+                if (span > 0)
+                {
+                    token.type = eNameSpace;
+                    token.value.SetCStringWithLength (p, span);
+                    m_tokens.push_back(token);
+                }
+                else
+                    continue;
+            }
+            break;
+
+        case '(':
+            if (span > 0)
+            {
+                token.type = eMethodName;
+                token.value.SetCStringWithLength (p, span);
+                m_tokens.push_back(token);
+            }
+
+            token.type = eParamsBeg;
+            token.value.Clear();
+            m_tokens.push_back(token);
+            break;
+
+        case ',':
+            if (span > 0)
+            {
+                token.type = eType;
+                token.value.SetCStringWithLength (p, span);
+                m_tokens.push_back(token);
+            }
+            else
+            {
+                continue;
+            }
+            break;
+
+        case ')':
+            if (span > 0)
+            {
+                token.type = eType;
+                token.value.SetCStringWithLength (p, span);
+                m_tokens.push_back(token);
+            }
+
+            token.type = eParamsEnd;
+            token.value.Clear();
+            m_tokens.push_back(token);
+            break;
+
+        case '<':
+            if (span > 0)
+            {
+                token.type = eTemplate;
+                token.value.SetCStringWithLength (p, span);
+                m_tokens.push_back(token);
+            }
+
+            token.type = eTemplateBeg;
+            token.value.Clear();
+            m_tokens.push_back(token);
+            break;
+
+        case '>':
+            if (span > 0)
+            {
+                token.type = eType;
+                token.value.SetCStringWithLength (p, span);
+                m_tokens.push_back(token);
+            }
+
+            token.type = eTemplateEnd;
+            token.value.Clear();
+            m_tokens.push_back(token);
+            break;
+        }
+
+        if (max_type < token.type)
+            max_type = token.type;
+
+        if (token.type == eInvalid)
+        {
+            if (max_type >= eParamsEnd)
+            {
+                token.type = eQualifier;
+                token.value.SetCString(p);
+                m_tokens.push_back(token);
+            }
+            else if (max_type >= eParamsBeg)
+            {
+                token.type = eType;
+                token.value.SetCString(p);
+                m_tokens.push_back(token);
+            }
+            else
+            {
+                token.type = eMethodName;
+                token.value.SetCString(p);
+                m_tokens.push_back(token);
+            }
+            break;
+        }
+    }
+    return m_tokens.size();
+}
+
+
+//----------------------------------------------------------------------
+// Clear the token list.
+//----------------------------------------------------------------------
+void
+Mangled::TokenList::Clear ()
+{
+    m_tokens.clear();
+}
+
+//----------------------------------------------------------------------
+// Dump the token list to the stream "s"
+//----------------------------------------------------------------------
+void
+Mangled::TokenList::Dump (Stream *s) const
+{
+    collection::const_iterator pos;
+    collection::const_iterator beg = m_tokens.begin();
+    collection::const_iterator end = m_tokens.end();
+    for (pos = beg; pos != end; ++pos)
+    {
+        s->Indent("token[");
+        *s << (uint32_t)std::distance(beg, pos) << "] = " << *pos << "\n";
+    }
+}
+
+//----------------------------------------------------------------------
+// Find the first token in the list that has "token_type" as its
+// type
+//----------------------------------------------------------------------
+const Mangled::Token *
+Mangled::TokenList::Find (TokenType token_type) const
+{
+    collection::const_iterator pos;
+    collection::const_iterator beg = m_tokens.begin();
+    collection::const_iterator end = m_tokens.end();
+    for (pos = beg; pos != end; ++pos)
+    {
+        if (pos->type == token_type)
+            return &(*pos);
+    }
+    return NULL;
+}
+
+//----------------------------------------------------------------------
+// Return the token at index "idx", or NULL if the index is
+// out of range.
+//----------------------------------------------------------------------
+const Mangled::Token *
+Mangled::TokenList::GetTokenAtIndex (uint32_t idx) const
+{
+    if (idx < m_tokens.size())
+        return &m_tokens[idx];
+    return NULL;
+}
+
+
+//----------------------------------------------------------------------
+// Given a token list, see if it matches this object's tokens.
+// "token_list" can contain wild card values to enable powerful
+// matching. Matching the std::string::erase(*) example that was
+// tokenized above we could use a token list such as:
+//
+//      token           name
+//      -----------     ----------------------------------------
+//      eNameSpace      "std"
+//      eTemplate       "basic_string"
+//      eTemplateBeg
+//      eInvalid        "*"
+//      eTemplateEnd
+//      eMethodName     "erase"
+//      eParamsBeg
+//      eInvalid        "*"
+//      eParamsEnd
+//
+// Returns true if it "token_list" matches this object's tokens,
+// false otherwise.
+//----------------------------------------------------------------------
+bool
+Mangled::TokenList::MatchesQuery (const Mangled::TokenList &match) const
+{
+    size_t match_count = 0;
+    collection::const_iterator pos;
+    collection::const_iterator pos_end = m_tokens.end();
+
+    collection::const_iterator match_pos;
+    collection::const_iterator match_pos_end = match.m_tokens.end();
+    collection::const_iterator match_wildcard_pos = match_pos_end;
+    collection::const_iterator match_next_pos = match_pos_end;
+
+    size_t template_scope_depth = 0;
+
+    for (pos = m_tokens.begin(), match_pos = match.m_tokens.begin();
+         pos != pos_end && match_pos != match_pos_end;
+         ++match_pos)
+    {
+        match_next_pos = match_pos + 1;
+        // Is this a wildcard?
+        if (match_pos->IsWildcard())
+        {
+            if (match_wildcard_pos != match_pos_end)
+                return false;   // Can't have two wildcards in effect at once.
+
+            match_wildcard_pos = match_pos;
+            // Are we at the end of the MATCH token list?
+            if (match_next_pos == match_pos_end)
+            {
+                // There is nothing more to match, return if we have any matches so far...
+                return match_count > 0;
+            }
+        }
+
+        if (match_pos->type == eInvalid || match_pos->type == eError)
+        {
+            return false;
+        }
+        else
+        {
+            if (match_pos->type == eTemplateBeg)
+            {
+                ++template_scope_depth;
+            }
+            else if (match_pos->type == eTemplateEnd)
+            {
+                assert(template_scope_depth > 0);
+                --template_scope_depth;
+            }
+
+            // Do we have a wildcard going right now?
+            if (match_wildcard_pos == match_pos_end)
+            {
+                // No wildcard matching right now, just check and see if things match
+                if (*pos == *match_pos)
+                    ++match_count;
+                else
+                    return false;
+            }
+            else
+            {
+                // We have a wildcard match going
+
+                // For template types we need to make sure to match the template depths...
+                const size_t start_wildcard_template_scope_depth = template_scope_depth;
+                size_t curr_wildcard_template_scope_depth = template_scope_depth;
+                while (pos != pos_end)
+                {
+                    if (match_wildcard_pos->type == eNameSpace && pos->type == eParamsBeg)
+                        return false;
+
+                    if (start_wildcard_template_scope_depth == curr_wildcard_template_scope_depth)
+                    {
+                        if (*pos == *match_next_pos)
+                        {
+                            ++match_count;
+                            match_pos = match_next_pos;
+                            match_wildcard_pos = match_pos_end;
+                            break;
+                        }
+                    }
+                    if (pos->type == eTemplateBeg)
+                        ++curr_wildcard_template_scope_depth;
+                    else if (pos->type == eTemplateEnd)
+                        --curr_wildcard_template_scope_depth;
+
+
+                    ++pos;
+                }
+            }
+        }
+
+        if (pos != pos_end)
+            ++pos;
+    }
+    if (match_pos != match_pos_end)
+        return false;
+
+    return match_count > 0;
+}
+
+
+//----------------------------------------------------------------------
+// Return the number of tokens in the token collection
+//----------------------------------------------------------------------
+size_t
+Mangled::TokenList::Size () const
+{
+    return m_tokens.size();
+}
+
+
+//----------------------------------------------------------------------
+// Stream out the tokens
+//----------------------------------------------------------------------
+Stream&
+lldb_private::operator << (Stream& s, const Mangled::TokenList& obj)
+{
+    obj.Dump(&s);
+    return s;
+}
diff --git a/source/Core/Module.cpp b/source/Core/Module.cpp
new file mode 100644
index 0000000..c8e7d2f
--- /dev/null
+++ b/source/Core/Module.cpp
@@ -0,0 +1,515 @@
+//===-- Module.cpp ----------------------------------------------*- 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/Module.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/lldb-private-log.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/SymbolVendor.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+Module::Module(const FileSpec& file_spec, const ArchSpec& arch, const ConstString *object_name, off_t object_offset) :
+    m_mutex (Mutex::eMutexTypeRecursive),
+    m_mod_time (file_spec.GetModificationTime()),
+    m_arch (arch),
+    m_uuid (),
+    m_file (file_spec),
+    m_flags (),
+    m_object_name (),
+    m_objfile_ap (),
+    m_symfile_ap ()
+{
+    if (object_name)
+        m_object_name = *object_name;
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT);
+    if (log)
+        log->Printf ("%p Module::Module((%s) '%s/%s%s%s%s')",
+                     this,
+                     m_arch.AsCString(),
+                     m_file.GetDirectory().AsCString(""),
+                     m_file.GetFilename().AsCString(""),
+                     m_object_name.IsEmpty() ? "" : "(",
+                     m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""),
+                     m_object_name.IsEmpty() ? "" : ")");
+
+}
+
+Module::~Module()
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT);
+    if (log)
+        log->Printf ("%p Module::~Module((%s) '%s/%s%s%s%s')",
+                     this,
+                     m_arch.AsCString(),
+                     m_file.GetDirectory().AsCString(""),
+                     m_file.GetFilename().AsCString(""),
+                     m_object_name.IsEmpty() ? "" : "(",
+                     m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""),
+                     m_object_name.IsEmpty() ? "" : ")");
+}
+
+
+ModuleSP
+Module::GetSP ()
+{
+    return ModuleList::GetModuleSP (this);
+}
+
+const UUID&
+Module::GetUUID()
+{
+    Mutex::Locker locker (m_mutex);
+    if (m_flags.IsClear(flagsParsedUUID))
+    {
+        ObjectFile * obj_file = GetObjectFile ();
+
+        if (obj_file != NULL)
+        {
+            obj_file->GetUUID(&m_uuid);
+            m_flags.Set(flagsParsedUUID);
+        }
+    }
+    return m_uuid;
+}
+
+void
+Module::ParseAllDebugSymbols()
+{
+    Mutex::Locker locker (m_mutex);
+    uint32_t num_comp_units = GetNumCompileUnits();
+    if (num_comp_units == 0)
+        return;
+
+    TargetSP null_target;
+    SymbolContext sc(null_target, GetSP());
+    uint32_t cu_idx;
+    SymbolVendor *symbols = GetSymbolVendor ();
+
+    for (cu_idx = 0; cu_idx < num_comp_units; cu_idx++)
+    {
+        sc.comp_unit = symbols->GetCompileUnitAtIndex(cu_idx).get();
+        if (sc.comp_unit)
+        {
+            sc.function = NULL;
+            symbols->ParseVariablesForContext(sc);
+
+            symbols->ParseCompileUnitFunctions(sc);
+
+            uint32_t func_idx;
+            for (func_idx = 0; (sc.function = sc.comp_unit->GetFunctionAtIndex(func_idx).get()) != NULL; ++func_idx)
+            {
+                symbols->ParseFunctionBlocks(sc);
+
+                // Parse the variables for this function and all its blocks
+                symbols->ParseVariablesForContext(sc);
+            }
+
+
+            // Parse all types for this compile unit
+            sc.function = NULL;
+            symbols->ParseTypes(sc);
+        }
+    }
+}
+
+void
+Module::CalculateSymbolContext(SymbolContext* sc)
+{
+    sc->module_sp = GetSP();
+}
+
+void
+Module::DumpSymbolContext(Stream *s)
+{
+    s->Printf(", Module{0x%8.8x}", this);
+}
+
+uint32_t
+Module::GetNumCompileUnits()
+{
+    Mutex::Locker locker (m_mutex);
+    Timer scoped_timer(__PRETTY_FUNCTION__, "Module::GetNumCompileUnits (module = %p)", this);
+    SymbolVendor *symbols = GetSymbolVendor ();
+    if (symbols)
+        return symbols->GetNumCompileUnits();
+    return 0;
+}
+
+CompUnitSP
+Module::GetCompileUnitAtIndex (uint32_t index)
+{
+    Mutex::Locker locker (m_mutex);
+    uint32_t num_comp_units = GetNumCompileUnits ();
+    CompUnitSP cu_sp;
+
+    if (index < num_comp_units)
+    {
+        SymbolVendor *symbols = GetSymbolVendor ();
+        if (symbols)
+            cu_sp = symbols->GetCompileUnitAtIndex(index);
+    }
+    return cu_sp;
+}
+
+//CompUnitSP
+//Module::FindCompUnit(lldb::user_id_t uid)
+//{
+//  CompUnitSP cu_sp;
+//  SymbolVendor *symbols = GetSymbolVendor ();
+//  if (symbols)
+//      cu_sp = symbols->FindCompUnit(uid);
+//  return cu_sp;
+//}
+
+bool
+Module::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr)
+{
+    Mutex::Locker locker (m_mutex);
+    Timer scoped_timer(__PRETTY_FUNCTION__, "Module::ResolveFileAddress (vm_addr = 0x%llx)", vm_addr);
+    ObjectFile* ofile = GetObjectFile();
+    if (ofile)
+        return so_addr.ResolveAddressUsingFileSections(vm_addr, ofile->GetSectionList());
+    return false;
+}
+
+uint32_t
+Module::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
+{
+    Mutex::Locker locker (m_mutex);
+    uint32_t resolved_flags = 0;
+
+    // Clear the result symbol context in case we don't find anything
+    sc.Clear();
+
+    // Get the section from the section/offset address.
+    const Section *section = so_addr.GetSection();
+
+    // Make sure the section matches this module before we try and match anything
+    if (section && section->GetModule() == this)
+    {
+        // If the section offset based address resolved itself, then this
+        // is the right module.
+        sc.module_sp = GetSP();
+        resolved_flags |= eSymbolContextModule;
+
+        // Resolve the compile unit, function, block, line table or line
+        // entry if requested.
+        if (resolve_scope & eSymbolContextCompUnit    ||
+            resolve_scope & eSymbolContextFunction    ||
+            resolve_scope & eSymbolContextBlock       ||
+            resolve_scope & eSymbolContextLineEntry   )
+        {
+            SymbolVendor *symbols = GetSymbolVendor ();
+            if (symbols)
+                resolved_flags |= symbols->ResolveSymbolContext (so_addr, resolve_scope, sc);
+        }
+
+        // Resolve the symbol if requested
+        if (resolve_scope & eSymbolContextSymbol)
+        {
+            ObjectFile* ofile = GetObjectFile();
+            if (ofile)
+            {
+                Symtab *symtab = ofile->GetSymtab();
+                if (symtab)
+                {
+                    if (so_addr.IsSectionOffset())
+                    {
+                        sc.symbol = symtab->FindSymbolContainingFileAddress(so_addr.GetFileAddress());
+                        if (sc.symbol)
+                            resolved_flags |= eSymbolContextSymbol;
+                    }
+                }
+            }
+        }
+    }
+    return resolved_flags;
+}
+
+uint32_t
+Module::ResolveSymbolContextForFilePath (const char *file_path, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
+{
+    FileSpec file_spec(file_path);
+    return ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list);
+}
+
+uint32_t
+Module::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
+{
+    Mutex::Locker locker (m_mutex);
+    Timer scoped_timer(__PRETTY_FUNCTION__,
+                       "Module::ResolveSymbolContextForFilePath (%s%s%s:%u, check_inlines = %s, resolve_scope = 0x%8.8x)",
+                       file_spec.GetDirectory().AsCString(""),
+                       file_spec.GetDirectory() ? "/" : "",
+                       file_spec.GetFilename().AsCString(""),
+                       line,
+                       check_inlines ? "yes" : "no",
+                       resolve_scope);
+
+    const uint32_t initial_count = sc_list.GetSize();
+
+    SymbolVendor *symbols = GetSymbolVendor  ();
+    if (symbols)
+        symbols->ResolveSymbolContext (file_spec, line, check_inlines, resolve_scope, sc_list);
+
+    return sc_list.GetSize() - initial_count;
+}
+
+
+uint32_t
+Module::FindGlobalVariables(const ConstString &name, bool append, uint32_t max_matches, VariableList& variables)
+{
+    SymbolVendor *symbols = GetSymbolVendor ();
+    if (symbols)
+        return symbols->FindGlobalVariables(name, append, max_matches, variables);
+    return 0;
+}
+uint32_t
+Module::FindGlobalVariables(const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables)
+{
+    SymbolVendor *symbols = GetSymbolVendor ();
+    if (symbols)
+        return symbols->FindGlobalVariables(regex, append, max_matches, variables);
+    return 0;
+}
+
+uint32_t
+Module::FindFunctions(const ConstString &name, bool append, SymbolContextList& sc_list)
+{
+    SymbolVendor *symbols = GetSymbolVendor ();
+    if (symbols)
+        return symbols->FindFunctions(name, append, sc_list);
+    return 0;
+}
+
+uint32_t
+Module::FindFunctions(const RegularExpression& regex, bool append, SymbolContextList& sc_list)
+{
+    SymbolVendor *symbols = GetSymbolVendor ();
+    if (symbols)
+        return symbols->FindFunctions(regex, append, sc_list);
+    return 0;
+}
+
+//uint32_t
+//Module::FindTypes(const SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, Type::Encoding encoding, const char *udt_name, TypeList& types)
+//{
+//  Timer scoped_timer(__PRETTY_FUNCTION__);
+//  SymbolVendor *symbols = GetSymbolVendor ();
+//  if (symbols)
+//      return symbols->FindTypes(sc, name, append, max_matches, encoding, udt_name, types);
+//  return 0;
+//}
+//
+//uint32_t
+//Module::FindTypes(const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, Type::Encoding encoding, const char *udt_name, TypeList& types)
+//{
+//  Timer scoped_timer(__PRETTY_FUNCTION__);
+//  SymbolVendor *symbols = GetSymbolVendor ();
+//  if (symbols)
+//      return symbols->FindTypes(sc, regex, append, max_matches, encoding, udt_name, types);
+//  return 0;
+//
+//}
+
+SymbolVendor*
+Module::GetSymbolVendor (bool can_create)
+{
+    Mutex::Locker locker (m_mutex);
+    if (m_flags.IsClear(flagsSearchedForSymVendor) && can_create)
+    {
+        ObjectFile *obj_file = GetObjectFile ();
+        if (obj_file != NULL)
+        {
+            Timer scoped_timer(__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+            m_symfile_ap.reset(SymbolVendor::FindPlugin(this));
+            m_flags.Set (flagsSearchedForSymVendor);
+        }
+    }
+    return m_symfile_ap.get();
+}
+
+const FileSpec &
+Module::GetFileSpec () const
+{
+    return m_file;
+}
+
+void
+Module::SetFileSpecAndObjectName (const FileSpec &file, const ConstString &object_name)
+{
+    // Container objects whose paths do not specify a file directly can call
+    // this function to correct the file and object names.
+    m_file = file;
+    m_mod_time = file.GetModificationTime();
+    m_object_name = object_name;
+}
+
+const ArchSpec&
+Module::GetArchitecture () const
+{
+    return m_arch;
+}
+
+void
+Module::Dump(Stream *s)
+{
+    Mutex::Locker locker (m_mutex);
+    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+    s->Indent();
+    s->Printf("Module %s/%s%s%s%s\n",
+              m_file.GetDirectory().AsCString(),
+              m_file.GetFilename().AsCString(),
+              m_object_name ? "(" : "",
+              m_object_name ? m_object_name.GetCString() : "",
+              m_object_name ? ")" : "");
+
+    s->IndentMore();
+    ObjectFile *objfile = GetObjectFile ();
+
+    if (objfile)
+        objfile->Dump(s);
+
+    SymbolVendor *symbols = GetSymbolVendor ();
+
+    if (symbols)
+        symbols->Dump(s);
+
+    s->IndentLess();
+}
+
+
+TypeList*
+Module::GetTypeList ()
+{
+    SymbolVendor *symbols = GetSymbolVendor ();
+    if (symbols)
+        return &symbols->GetTypeList();
+    return NULL;
+}
+
+const ConstString &
+Module::GetObjectName() const
+{
+    return m_object_name;
+}
+
+ObjectFile *
+Module::GetObjectFile()
+{
+    Mutex::Locker locker (m_mutex);
+    if (m_flags.IsClear(flagsSearchedForObjParser))
+    {
+        m_flags.Set (flagsSearchedForObjParser);
+        Timer scoped_timer(__PRETTY_FUNCTION__,
+                           "Module::GetObjectFile () module = %s", GetFileSpec().GetFilename().AsCString(""));
+        m_objfile_ap.reset(ObjectFile::FindPlugin(this, &m_file, 0, m_file.GetByteSize()));
+    }
+    return m_objfile_ap.get();
+}
+
+
+const Symbol *
+Module::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type)
+{
+    Timer scoped_timer(__PRETTY_FUNCTION__,
+                       "Module::FindFirstSymbolWithNameAndType (name = %s, type = %i)",
+                       name.AsCString(),
+                       symbol_type);
+    ObjectFile *objfile = GetObjectFile();
+    if (objfile)
+    {
+        Symtab *symtab = objfile->GetSymtab();
+        if (symtab)
+            return symtab->FindFirstSymbolWithNameAndType (name, symbol_type);
+    }
+    return NULL;
+}
+void
+Module::SymbolIndicesToSymbolContextList (Symtab *symtab, std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list)
+{
+    // No need to protect this call using m_mutex all other method calls are
+    // already thread safe.
+
+    size_t num_indices = symbol_indexes.size();
+    if (num_indices > 0)
+    {
+        SymbolContext sc;
+        CalculateSymbolContext (&sc);
+        for (size_t i = 0; i < num_indices; i++)
+        {
+            sc.symbol = symtab->SymbolAtIndex (symbol_indexes[i]);
+            if (sc.symbol)
+                sc_list.Append (sc);
+        }
+    }
+}
+
+size_t
+Module::FindSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, SymbolContextList &sc_list)
+{
+    // No need to protect this call using m_mutex all other method calls are
+    // already thread safe.
+
+
+    Timer scoped_timer(__PRETTY_FUNCTION__,
+                       "Module::FindSymbolsWithNameAndType (name = %s, type = %i)",
+                       name.AsCString(),
+                       symbol_type);
+    const size_t initial_size = sc_list.GetSize();
+    ObjectFile *objfile = GetObjectFile ();
+    if (objfile)
+    {
+        Symtab *symtab = objfile->GetSymtab();
+        if (symtab)
+        {
+            std::vector<uint32_t> symbol_indexes;
+            symtab->FindAllSymbolsWithNameAndType (name, symbol_type, symbol_indexes);
+            SymbolIndicesToSymbolContextList (symtab, symbol_indexes, sc_list);
+        }
+    }
+    return sc_list.GetSize() - initial_size;
+}
+
+size_t
+Module::FindSymbolsMatchingRegExAndType (const RegularExpression &regex, SymbolType symbol_type, SymbolContextList &sc_list)
+{
+    // No need to protect this call using m_mutex all other method calls are
+    // already thread safe.
+
+    Timer scoped_timer(__PRETTY_FUNCTION__,
+                       "Module::FindSymbolsMatchingRegExAndType (regex = %s, type = %i)",
+                       regex.GetText(),
+                       symbol_type);
+    const size_t initial_size = sc_list.GetSize();
+    ObjectFile *objfile = GetObjectFile ();
+    if (objfile)
+    {
+        Symtab *symtab = objfile->GetSymtab();
+        if (symtab)
+        {
+            std::vector<uint32_t> symbol_indexes;
+            symtab->FindAllSymbolsMatchingRexExAndType (regex, symbol_type, symbol_indexes);
+            SymbolIndicesToSymbolContextList (symtab, symbol_indexes, sc_list);
+        }
+    }
+    return sc_list.GetSize() - initial_size;
+}
+
+const TimeValue &
+Module::GetModificationTime () const
+{
+    return m_mod_time;
+}
diff --git a/source/Core/ModuleChild.cpp b/source/Core/ModuleChild.cpp
new file mode 100644
index 0000000..f38fb4f
--- /dev/null
+++ b/source/Core/ModuleChild.cpp
@@ -0,0 +1,52 @@
+//===-- ModuleChild.cpp -----------------------------------------*- 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/ModuleChild.h"
+
+using namespace lldb_private;
+
+ModuleChild::ModuleChild (Module* module) :
+    m_module(module)
+{
+}
+
+ModuleChild::ModuleChild (const ModuleChild& rhs) :
+    m_module(rhs.m_module)
+{
+}
+
+ModuleChild::~ModuleChild()
+{
+}
+
+const ModuleChild&
+ModuleChild::operator= (const ModuleChild& rhs)
+{
+    if (this != &rhs)
+        m_module = rhs.m_module;
+    return *this;
+}
+
+Module *
+ModuleChild::GetModule ()
+{
+    return m_module;
+}
+
+Module *
+ModuleChild::GetModule () const
+{
+    return m_module;
+}
+
+void
+ModuleChild::SetModule (Module *module)
+{
+    m_module = module;
+}
diff --git a/source/Core/ModuleList.cpp b/source/Core/ModuleList.cpp
new file mode 100644
index 0000000..ae6e27b
--- /dev/null
+++ b/source/Core/ModuleList.cpp
@@ -0,0 +1,626 @@
+//===-- ModuleList.cpp ------------------------------------------*- 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/ModuleList.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Module.h"
+#include "lldb/Host/Symbols.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/VariableList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// ModuleList constructor
+//----------------------------------------------------------------------
+ModuleList::ModuleList() :
+    m_modules(),
+    m_modules_mutex (Mutex::eMutexTypeRecursive)
+{
+}
+
+//----------------------------------------------------------------------
+// Copy constructor
+//----------------------------------------------------------------------
+ModuleList::ModuleList(const ModuleList& rhs) :
+    m_modules(rhs.m_modules)
+{
+}
+
+//----------------------------------------------------------------------
+// Assignment operator
+//----------------------------------------------------------------------
+const ModuleList&
+ModuleList::operator= (const ModuleList& rhs)
+{
+    if (this != &rhs)
+    {
+        Mutex::Locker locker(m_modules_mutex);
+        m_modules = rhs.m_modules;
+    }
+    return *this;
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ModuleList::~ModuleList()
+{
+}
+
+void
+ModuleList::Append (ModuleSP &module_sp)
+{
+    Mutex::Locker locker(m_modules_mutex);
+    m_modules.push_back(module_sp);
+}
+
+bool
+ModuleList::AppendInNeeded (ModuleSP &module_sp)
+{
+    Mutex::Locker locker(m_modules_mutex);
+    collection::iterator pos, end = m_modules.end();
+    for (pos = m_modules.begin(); pos != end; ++pos)
+    {
+        if (pos->get() == module_sp.get())
+            return false; // Already in the list
+    }
+    // Only push module_sp on the list if it wasn't already in there.
+    m_modules.push_back(module_sp);
+    return true;
+}
+
+bool
+ModuleList::Remove (ModuleSP &module_sp)
+{
+    Mutex::Locker locker(m_modules_mutex);
+    collection::iterator pos, end = m_modules.end();
+    for (pos = m_modules.begin(); pos != end; ++pos)
+    {
+        if (pos->get() == module_sp.get())
+        {
+            m_modules.erase (pos);
+            return true;
+        }
+    }
+    return false;
+}
+
+
+
+void
+ModuleList::Clear()
+{
+    Mutex::Locker locker(m_modules_mutex);
+    m_modules.clear();
+}
+
+Module*
+ModuleList::GetModulePointerAtIndex (uint32_t idx) const
+{
+    Mutex::Locker locker(m_modules_mutex);
+    if (idx < m_modules.size())
+        return m_modules[idx].get();
+    return NULL;
+}
+
+ModuleSP
+ModuleList::GetModuleAtIndex(uint32_t idx)
+{
+    Mutex::Locker locker(m_modules_mutex);
+    ModuleSP module_sp;
+    if (idx < m_modules.size())
+        module_sp = m_modules[idx];
+    return module_sp;
+}
+
+size_t
+ModuleList::FindFunctions (const ConstString &name, SymbolContextList &sc_list)
+{
+    sc_list.Clear();
+    Mutex::Locker locker(m_modules_mutex);
+    collection::const_iterator pos, end = m_modules.end();
+    for (pos = m_modules.begin(); pos != end; ++pos)
+    {
+        (*pos)->FindFunctions (name, true, sc_list);
+    }
+    return sc_list.GetSize();
+}
+
+uint32_t
+ModuleList::FindGlobalVariables (const ConstString &name, bool append, uint32_t max_matches, VariableList& variable_list)
+{
+    size_t initial_size = variable_list.GetSize();
+    Mutex::Locker locker(m_modules_mutex);
+    collection::iterator pos, end = m_modules.end();
+    for (pos = m_modules.begin(); pos != end; ++pos)
+    {
+        (*pos)->FindGlobalVariables (name, append, max_matches, variable_list);
+    }
+    return variable_list.GetSize() - initial_size;
+}
+
+
+uint32_t
+ModuleList::FindGlobalVariables (const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variable_list)
+{
+    size_t initial_size = variable_list.GetSize();
+    Mutex::Locker locker(m_modules_mutex);
+    collection::iterator pos, end = m_modules.end();
+    for (pos = m_modules.begin(); pos != end; ++pos)
+    {
+        (*pos)->FindGlobalVariables (regex, append, max_matches, variable_list);
+    }
+    return variable_list.GetSize() - initial_size;
+}
+
+
+size_t
+ModuleList::FindSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, SymbolContextList &sc_list)
+{
+    Mutex::Locker locker(m_modules_mutex);
+    sc_list.Clear();
+    collection::iterator pos, end = m_modules.end();
+    for (pos = m_modules.begin(); pos != end; ++pos)
+        (*pos)->FindSymbolsWithNameAndType (name, symbol_type, sc_list);
+    return sc_list.GetSize();
+}
+
+class ModuleMatches
+{
+public:
+    //--------------------------------------------------------------
+    /// Construct with the user ID to look for.
+    //--------------------------------------------------------------
+    ModuleMatches (const FileSpec *file_spec_ptr,
+                   const ArchSpec *arch_ptr,
+                   const UUID *uuid_ptr,
+                   const ConstString *object_name) :
+        m_file_spec_ptr (file_spec_ptr),
+        m_arch_ptr (arch_ptr),
+        m_uuid_ptr (uuid_ptr),
+        m_object_name (object_name)
+    {
+    }
+
+    //--------------------------------------------------------------
+    /// Unary predicate function object callback.
+    //--------------------------------------------------------------
+    bool
+    operator () (const ModuleSP& module_sp) const
+    {
+        if (m_file_spec_ptr)
+        {
+            if (!FileSpec::Equal (*m_file_spec_ptr, module_sp->GetFileSpec(), m_file_spec_ptr->GetDirectory()))
+                return false;
+        }
+
+        if (m_arch_ptr)
+        {
+            if (module_sp->GetArchitecture() != *m_arch_ptr)
+                return false;
+        }
+
+        if (m_uuid_ptr)
+        {
+            if (module_sp->GetUUID() != *m_uuid_ptr)
+                return false;
+        }
+
+        if (m_object_name)
+        {
+            if (module_sp->GetObjectName() != *m_object_name)
+                return false;
+        }
+        return true;
+    }
+
+private:
+    //--------------------------------------------------------------
+    // Member variables.
+    //--------------------------------------------------------------
+    const FileSpec *    m_file_spec_ptr;
+    const ArchSpec *    m_arch_ptr;
+    const UUID *        m_uuid_ptr;
+    const ConstString * m_object_name;
+};
+
+size_t
+ModuleList::FindModules
+(
+    const FileSpec *file_spec_ptr,
+    const ArchSpec *arch_ptr,
+    const UUID *uuid_ptr,
+    const ConstString *object_name,
+    ModuleList& matching_module_list
+) const
+{
+    size_t existing_matches = matching_module_list.GetSize();
+    ModuleMatches matcher (file_spec_ptr, arch_ptr, uuid_ptr, object_name);
+
+    Mutex::Locker locker(m_modules_mutex);
+    collection::const_iterator end = m_modules.end();
+    collection::const_iterator pos;
+
+    for (pos = std::find_if (m_modules.begin(), end, matcher);
+         pos != end;
+         pos = std::find_if (++pos, end, matcher))
+    {
+        ModuleSP module_sp(*pos);
+        matching_module_list.Append(module_sp);
+    }
+    return matching_module_list.GetSize() - existing_matches;
+}
+
+ModuleSP
+ModuleList::FindModule (lldb_private::Module *module_ptr)
+{
+    ModuleSP module_sp;
+
+    // Scope for "locker"
+    {
+        Mutex::Locker locker(m_modules_mutex);
+        collection::const_iterator pos, end = m_modules.end();
+
+        for (pos = m_modules.begin(); pos != end; ++pos)
+        {
+            if ((*pos).get() == module_ptr)
+            {
+                module_sp = (*pos);
+                break;
+            }
+        }
+    }
+    return module_sp;
+
+}
+
+
+ModuleSP
+ModuleList::FindFirstModuleForFileSpec (const FileSpec &file_spec, const ConstString *object_name)
+{
+    ModuleSP module_sp;
+    ModuleMatches matcher (&file_spec, NULL, NULL, NULL);
+
+    // Scope for "locker"
+    {
+        Mutex::Locker locker(m_modules_mutex);
+        collection::const_iterator end = m_modules.end();
+        collection::const_iterator pos = m_modules.begin();
+
+        pos = std::find_if (pos, end, matcher);
+        if (pos != end)
+            module_sp = (*pos);
+    }
+    return module_sp;
+
+}
+
+
+size_t
+ModuleList::GetSize() const
+{
+    size_t size = 0;
+    {
+        Mutex::Locker locker(m_modules_mutex);
+        size = m_modules.size();
+    }
+    return size;
+}
+
+
+void
+ModuleList::Dump(Stream *s) const
+{
+//  s.Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+//  s.Indent();
+//  s << "ModuleList\n";
+
+    Mutex::Locker locker(m_modules_mutex);
+    collection::const_iterator pos, end = m_modules.end();
+    for (pos = m_modules.begin(); pos != end; ++pos)
+    {
+        (*pos)->Dump(s);
+    }
+}
+
+
+bool
+ModuleList::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr)
+{
+    Mutex::Locker locker(m_modules_mutex);
+    collection::const_iterator pos, end = m_modules.end();
+    for (pos = m_modules.begin(); pos != end; ++pos)
+    {
+        if ((*pos)->ResolveFileAddress (vm_addr, so_addr))
+            return true;
+    }
+
+    return false;
+}
+
+uint32_t
+ModuleList::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
+{
+    // The address is already section offset so it has a module
+    uint32_t resolved_flags = 0;
+    Module *module = so_addr.GetModule();
+    if (module)
+    {
+        resolved_flags = module->ResolveSymbolContextForAddress (so_addr,
+                                                                 resolve_scope,
+                                                                 sc);
+    }
+    else
+    {
+        Mutex::Locker locker(m_modules_mutex);
+        collection::const_iterator pos, end = m_modules.end();
+        for (pos = m_modules.begin(); pos != end; ++pos)
+        {
+            resolved_flags = (*pos)->ResolveSymbolContextForAddress (so_addr,
+                                                                     resolve_scope,
+                                                                     sc);
+            if (resolved_flags != 0)
+                break;
+        }
+    }
+
+    return resolved_flags;
+}
+
+uint32_t
+ModuleList::ResolveSymbolContextForFilePath (const char *file_path, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
+{
+    FileSpec file_spec(file_path);
+    return ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list);
+}
+
+uint32_t
+ModuleList::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
+{
+    Mutex::Locker locker(m_modules_mutex);
+    collection::const_iterator pos, end = m_modules.end();
+    for (pos = m_modules.begin(); pos != end; ++pos)
+    {
+        (*pos)->ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list);
+    }
+
+    return sc_list.GetSize();
+}
+
+uint32_t
+ModuleList::GetIndexForModule (const Module *module) const
+{
+    if (module)
+    {
+        Mutex::Locker locker(m_modules_mutex);
+        collection::const_iterator pos;
+        collection::const_iterator begin = m_modules.begin();
+        collection::const_iterator end = m_modules.end();
+        for (pos = begin; pos != end; ++pos)
+        {
+            if ((*pos).get() == module)
+                return std::distance (begin, pos);
+        }
+    }
+    return LLDB_INVALID_INDEX32;
+}
+
+static ModuleList &
+GetSharedModuleList ()
+{
+    static ModuleList g_shared_module_list;
+    return g_shared_module_list;
+}
+
+const lldb::ModuleSP
+ModuleList::GetModuleSP (lldb_private::Module *module_ptr)
+{
+    lldb::ModuleSP module_sp;
+    if (module_ptr)
+    {
+        ModuleList &shared_module_list = GetSharedModuleList ();
+        module_sp = shared_module_list.FindModule (module_ptr);
+        assert (module_sp.get());   // This might fire off a few times and we need to make sure it never fires...
+    }
+    return module_sp;
+}
+
+
+Error
+ModuleList::GetSharedModule
+(
+    const FileSpec& in_file_spec,
+    const ArchSpec& arch,
+    const UUID *uuid_ptr,
+    const ConstString *object_name_ptr,
+    off_t object_offset,
+    ModuleSP &module_sp,
+    ModuleSP *old_module_sp_ptr,
+    bool *did_create_ptr
+)
+{
+    ModuleList &shared_module_list = GetSharedModuleList ();
+    char path[PATH_MAX];
+    char uuid_cstr[64];
+
+    Error error;
+
+    module_sp.reset();
+
+    if (did_create_ptr)
+        *did_create_ptr = false;
+    if (old_module_sp_ptr)
+        old_module_sp_ptr->reset();
+
+
+    // First just try and get the file where it purports to be (path in
+    // in_file_spec), then check and uuid.
+
+    if (in_file_spec)
+    {
+        // Make sure no one else can try and get or create a module while this
+        // function is actively working on it by doing an extra lock on the
+        // global mutex list.
+        ModuleList matching_module_list;
+        Mutex::Locker locker(shared_module_list.m_modules_mutex);
+        if (shared_module_list.FindModules (&in_file_spec, &arch, uuid_ptr, object_name_ptr, matching_module_list) > 0)
+        {
+            module_sp = matching_module_list.GetModuleAtIndex(0);
+
+            // If we didn't have a UUID in mind when looking for the object file,
+            // then we should make sure the modification time hasn't changed!
+            if (uuid_ptr == NULL)
+            {
+                TimeValue file_spec_mod_time(in_file_spec.GetModificationTime());
+                if (file_spec_mod_time.IsValid())
+                {
+                    if (file_spec_mod_time != module_sp->GetModificationTime())
+                    {
+                        if (old_module_sp_ptr)
+                            *old_module_sp_ptr = module_sp;
+                        shared_module_list.Remove (module_sp);
+                        module_sp.reset();
+                    }
+                }
+            }
+        }
+
+        if (module_sp.get() == NULL)
+        {
+            module_sp.reset (new Module (in_file_spec, arch, object_name_ptr, object_offset));
+            if (module_sp)
+            {
+                // If we get in here we got the correct arch, now we just need
+                // to verify the UUID if one was given
+                if (uuid_ptr && *uuid_ptr != module_sp->GetUUID())
+                    module_sp.reset();
+                else
+                {
+                    if (did_create_ptr)
+                        *did_create_ptr = true;
+
+                    shared_module_list.Append(module_sp);
+                    return error;
+                }
+            }
+        }
+    }
+
+    // Either the file didn't exist where at the path, or no path was given, so
+    // we now have to use more extreme measures to try and find the appropriate
+    // module.
+
+    // Fixup the incoming path in case the path points to a valid file, yet
+    // the arch or UUID (if one was passed in) don't match.
+    FileSpec file_spec = Symbols::LocateExecutableObjectFile (&in_file_spec, arch.IsValid() ? &arch : NULL, uuid_ptr);
+
+    // Don't look for the file if it appears to be the same one we already
+    // checked for above...
+    if (file_spec != in_file_spec)
+    {
+        if (!file_spec.Exists())
+        {
+            file_spec.GetPath(path, sizeof(path));
+            if (file_spec.Exists())
+            {
+                if (uuid_ptr && uuid_ptr->IsValid())
+                    uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr));
+                else
+                    uuid_cstr[0] = '\0';
+
+
+                if (arch.IsValid())
+                {
+                    if (uuid_cstr[0])
+                        error.SetErrorStringWithFormat("'%s' does not contain the %s architecture and UUID %s.\n", path, arch.AsCString(), uuid_cstr[0]);
+                    else
+                        error.SetErrorStringWithFormat("'%s' does not contain the %s architecture.\n", path, arch.AsCString());
+                }
+            }
+            else
+            {
+                error.SetErrorStringWithFormat("'%s' does not exist.\n", path);
+            }
+            return error;
+        }
+
+
+        // Make sure no one else can try and get or create a module while this
+        // function is actively working on it by doing an extra lock on the
+        // global mutex list.
+        Mutex::Locker locker(shared_module_list.m_modules_mutex);
+        ModuleList matching_module_list;
+        if (shared_module_list.FindModules (&file_spec, &arch, uuid_ptr, object_name_ptr, matching_module_list) > 0)
+        {
+            module_sp = matching_module_list.GetModuleAtIndex(0);
+
+            // If we didn't have a UUID in mind when looking for the object file,
+            // then we should make sure the modification time hasn't changed!
+            if (uuid_ptr == NULL)
+            {
+                TimeValue file_spec_mod_time(file_spec.GetModificationTime());
+                if (file_spec_mod_time.IsValid())
+                {
+                    if (file_spec_mod_time != module_sp->GetModificationTime())
+                    {
+                        if (old_module_sp_ptr)
+                            *old_module_sp_ptr = module_sp;
+                        shared_module_list.Remove (module_sp);
+                        module_sp.reset();
+                    }
+                }
+            }
+        }
+
+        if (module_sp.get() == NULL)
+        {
+            module_sp.reset (new Module (file_spec, arch, object_name_ptr, object_offset));
+            if (module_sp)
+            {
+                if (did_create_ptr)
+                    *did_create_ptr = true;
+
+                shared_module_list.Append(module_sp);
+            }
+            else
+            {
+                file_spec.GetPath(path, sizeof(path));
+
+                if (file_spec)
+                {
+                    if (arch.IsValid())
+                        error.SetErrorStringWithFormat("Unable to open %s architecture in '%s'.\n", arch.AsCString(), path);
+                    else
+                        error.SetErrorStringWithFormat("Unable to open '%s'.\n", path);
+                }
+                else
+                {
+                    if (uuid_ptr && uuid_ptr->IsValid())
+                        uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr));
+                    else
+                        uuid_cstr[0] = '\0';
+
+                    if (uuid_cstr[0])
+                        error.SetErrorStringWithFormat("Cannot locate a module for UUID '%s'.\n", uuid_cstr[0]);
+                    else
+                        error.SetErrorStringWithFormat("Cannot locate a module.\n", path, arch.AsCString());
+                }
+            }
+        }
+    }
+
+    return error;
+}
+
diff --git a/source/Core/Options.cpp b/source/Core/Options.cpp
new file mode 100644
index 0000000..35a9fa4
--- /dev/null
+++ b/source/Core/Options.cpp
@@ -0,0 +1,700 @@
+//===-- Options.cpp ---------------------------------------------*- 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/Options.h"
+
+// C Includes
+// C++ Includes
+#include <bitset>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/CommandCompletions.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// Options
+//-------------------------------------------------------------------------
+Options::Options () :
+    m_getopt_table ()
+{
+}
+
+Options::~Options ()
+{
+}
+
+
+void
+Options::ResetOptionValues ()
+{
+    m_seen_options.clear();
+}
+
+void
+Options::OptionSeen (int option_idx)
+{
+    m_seen_options.insert ((char) option_idx);
+}
+
+// Returns true is set_a is a subset of set_b;  Otherwise returns false.
+
+bool
+Options::IsASubset (const OptionSet& set_a, const OptionSet& set_b)
+{
+    bool is_a_subset = true;
+    OptionSet::const_iterator pos_a;
+    OptionSet::const_iterator pos_b;
+
+    // set_a is a subset of set_b if every member of set_a is also a member of set_b
+
+    for (pos_a = set_a.begin(); pos_a != set_a.end() && is_a_subset; ++pos_a)
+    {
+        pos_b = set_b.find(*pos_a);
+        if (pos_b == set_b.end())
+            is_a_subset = false;
+    }
+
+    return is_a_subset;
+}
+
+// Returns the set difference set_a - set_b, i.e. { x | ElementOf (x, set_a) && !ElementOf (x, set_b) }
+
+size_t
+Options::OptionsSetDiff (const OptionSet& set_a, const OptionSet& set_b, OptionSet& diffs)
+{
+    size_t num_diffs = 0;
+    OptionSet::const_iterator pos_a;
+    OptionSet::const_iterator pos_b;
+
+    for (pos_a = set_a.begin(); pos_a != set_a.end(); ++pos_a)
+    {
+        pos_b = set_b.find(*pos_a);
+        if (pos_b == set_b.end())
+        {
+            ++num_diffs;
+            diffs.insert(*pos_a);
+        }
+    }
+
+    return num_diffs;
+}
+
+// Returns the union of set_a and set_b.  Does not put duplicate members into the union.
+
+void
+Options::OptionsSetUnion (const OptionSet &set_a, const OptionSet &set_b, OptionSet &union_set)
+{
+    OptionSet::const_iterator pos;
+    OptionSet::iterator pos_union;
+
+    // Put all the elements of set_a into the union.
+
+    for (pos = set_a.begin(); pos != set_a.end(); ++pos)
+        union_set.insert(*pos);
+
+    // Put all the elements of set_b that are not already there into the union.
+    for (pos = set_b.begin(); pos != set_b.end(); ++pos)
+    {
+        pos_union = union_set.find(*pos);
+        if (pos_union == union_set.end())
+            union_set.insert(*pos);
+    }
+}
+
+bool
+Options::VerifyOptions (CommandReturnObject &result)
+{
+    bool options_are_valid = false;
+
+    int num_levels = m_required_options.size();
+    if (num_levels)
+    {
+        for (int i = 0; i < num_levels && !options_are_valid; ++i)
+        {
+            // This is the correct set of options if:  1). m_seen_options contains all of m_required_options[i]
+            // (i.e. all the required options at this level are a subset of m_seen_options); AND
+            // 2). { m_seen_options - m_required_options[i] is a subset of m_options_options[i] (i.e. all the rest of
+            // m_seen_options are in the set of optional options at this level.
+
+            // Check to see if all of m_required_options[i] are a subset of m_seen_options
+            if (IsASubset (m_required_options[i], m_seen_options))
+            {
+                // Construct the set difference: remaining_options = {m_seen_options} - {m_required_options[i]}
+                OptionSet remaining_options;
+                OptionsSetDiff (m_seen_options, m_required_options[i], remaining_options);
+                // Check to see if remaining_options is a subset of m_optional_options[i]
+                if (IsASubset (remaining_options, m_optional_options[i]))
+                    options_are_valid = true;
+            }
+        }
+    }
+    else
+    {
+        options_are_valid = true;
+    }
+
+    if (options_are_valid)
+    {
+        result.SetStatus (eReturnStatusSuccessFinishNoResult);
+    }
+    else
+    {
+        result.AppendError ("invalid combination of options for the given command");
+        result.SetStatus (eReturnStatusFailed);
+    }
+
+    return options_are_valid;
+}
+
+void
+Options::BuildValidOptionSets ()
+{
+    // Check to see if we already did this.
+    if (m_required_options.size() != 0)
+        return;
+
+    // Check to see if there are any options.
+    int num_options = NumCommandOptions ();
+    if (num_options == 0)
+        return;
+
+    const lldb::OptionDefinition *full_options_table = GetDefinitions();
+    uint32_t usage_level = 0;
+    m_required_options.resize(1);
+    m_optional_options.resize(1);
+
+    for (int i = 0; i < num_options; ++i)
+    {
+        // NOTE:  Assumption:  The full options table is ordered with usage level growing monotonically.
+        assert (full_options_table[i].usage_level >= usage_level);
+
+        if (full_options_table[i].usage_level > usage_level)
+        {
+            // start a new level
+            usage_level = full_options_table[i].usage_level;
+            m_required_options.resize(m_required_options.size()+1);
+            m_optional_options.resize(m_optional_options.size()+1);
+        }
+        else
+        {
+            assert (m_required_options.empty() == false);
+            assert (m_optional_options.empty() == false);
+        }
+
+        if (full_options_table[i].required)
+            m_required_options.back().insert(full_options_table[i].short_option);
+        else
+            m_optional_options.back().insert(full_options_table[i].short_option);
+    }
+}
+
+uint32_t
+Options::NumCommandOptions ()
+{
+    const lldb::OptionDefinition *full_options_table = GetDefinitions ();
+    int i = 0;
+
+    if (full_options_table != NULL)
+    {
+        while (full_options_table[i].long_option != NULL)
+            ++i;
+    }
+
+    return i;
+}
+
+struct option *
+Options::GetLongOptions ()
+{
+    // Check to see if this has already been done.
+    if (m_getopt_table.empty())
+    {
+        // Check to see if there are any options.
+        const uint32_t num_options = NumCommandOptions();
+        if (num_options == 0)
+            return NULL;
+
+        uint32_t i;
+        uint32_t j;
+        const lldb::OptionDefinition *full_options_table = GetDefinitions();
+
+        std::bitset<256> option_seen;
+
+        m_getopt_table.resize(num_options + 1);
+        for (i = 0, j = 0; i < num_options; ++i)
+        {
+            char short_opt = full_options_table[i].short_option;
+
+            if (option_seen.test(short_opt) == false)
+            {
+                m_getopt_table[j].name    = full_options_table[i].long_option;
+                m_getopt_table[j].has_arg = full_options_table[i].option_has_arg;
+                m_getopt_table[j].flag    = NULL;
+                m_getopt_table[j].val     = full_options_table[i].short_option;
+                option_seen.set(short_opt);
+                ++j;
+            }
+        }
+
+        //getopt_long requires a NULL final entry in the table:
+
+        m_getopt_table[j].name    = NULL;
+        m_getopt_table[j].has_arg = 0;
+        m_getopt_table[j].flag    = NULL;
+        m_getopt_table[j].val     = 0;
+    }
+
+    return m_getopt_table.data();
+}
+
+
+// This function takes INDENT, which tells how many spaces to output at the front of each line; SPACES, which is
+// a string containing 80 spaces; and TEXT, which is the text that is to be output.   It outputs the text, on
+// multiple lines if necessary, to RESULT, with INDENT spaces at the front of each line.  It breaks lines on spaces,
+// tabs or newlines, shortening the line if necessary to not break in the middle of a word.  It assumes that each
+// output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
+
+
+void
+Options::OutputFormattedUsageText
+(
+    Stream &strm,
+    const char *text,
+    uint32_t output_max_columns
+)
+{
+    int len = strlen (text);
+
+    // Will it all fit on one line?
+
+    if ((len + strm.GetIndentLevel()) < output_max_columns)
+    {
+        // Output it as a single line.
+        strm.Indent (text);
+        strm.EOL();
+    }
+    else
+    {
+        // We need to break it up into multiple lines.
+
+        int text_width = output_max_columns - strm.GetIndentLevel() - 1;
+        int start = 0;
+        int end = start;
+        int final_end = strlen (text);
+        int sub_len;
+
+        while (end < final_end)
+        {
+            // Don't start the 'text' on a space, since we're already outputting the indentation.
+            while ((start < final_end) && (text[start] == ' '))
+                start++;
+
+            end = start + text_width;
+            if (end > final_end)
+                end = final_end;
+            else
+            {
+                // If we're not at the end of the text, make sure we break the line on white space.
+                while (end > start
+                       && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
+                    end--;
+            }
+
+            sub_len = end - start;
+            if (start != 0)
+                strm.EOL();
+            strm.Indent();
+            assert (start < final_end);
+            assert (start + sub_len <= final_end);
+            strm.Write(text + start, sub_len);
+            start = end + 1;
+        }
+        strm.EOL();
+    }
+}
+
+void
+Options::GenerateOptionUsage
+(
+    Stream &strm,
+    CommandObject *cmd,
+    const char *program_name)
+{
+    uint32_t screen_width = 80;
+    const lldb::OptionDefinition *full_options_table = GetDefinitions();
+    const uint32_t save_indent_level = strm.GetIndentLevel();
+    const char *name;
+
+    if (cmd)
+      name = cmd->GetCommandName();
+    else
+      name = program_name;
+
+    strm.PutCString ("\nCommand Options Usage:\n");
+
+    strm.IndentMore(2);
+
+    // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
+    //                                                   <cmd> [options-for-level-1]
+    //                                                   etc.
+
+    uint32_t usage_level = 0;
+    const uint32_t num_options = NumCommandOptions();
+    uint32_t i;
+    for (i = 0; i < num_options; ++i)
+    {
+        if (i==0 || full_options_table[i].usage_level > usage_level)
+        {
+            // start a new level
+            usage_level = full_options_table[i].usage_level;
+            if (usage_level > 0)
+            {
+                strm.Printf ("\n");
+            }
+            strm.Indent (name);
+        }
+
+        // Add current option to the end of out_stream.
+
+        if (full_options_table[i].required)
+        {
+            if (full_options_table[i].option_has_arg == required_argument)
+            {
+                strm.Printf (" -%c %s",
+                            full_options_table[i].short_option,
+                            full_options_table[i].argument_name);
+            }
+            else if (full_options_table[i].option_has_arg == optional_argument)
+            {
+                strm.Printf (" -%c [%s]",
+                             full_options_table[i].short_option,
+                             full_options_table[i].argument_name);
+            }
+            else
+                strm.Printf (" -%c", full_options_table[i].short_option);
+        }
+        else
+        {
+            if (full_options_table[i].option_has_arg == required_argument)
+                strm.Printf (" [-%c %s]", full_options_table[i].short_option,
+                                   full_options_table[i].argument_name);
+            else if (full_options_table[i].option_has_arg == optional_argument)
+                strm.Printf (" [-%c [%s]]", full_options_table[i].short_option,
+                                   full_options_table[i].argument_name);
+            else
+                strm.Printf (" [-%c]", full_options_table[i].short_option);
+        }
+    }
+
+    strm.Printf ("\n\n");
+
+    // Now print out all the detailed information about the various options:  long form, short form and help text:
+    //   -- long_name <argument>
+    //   - short <argument>
+    //   help text
+
+    // This variable is used to keep track of which options' info we've printed out, because some options can be in
+    // more than one usage level, but we only want to print the long form of its information once.
+
+    OptionSet options_seen;
+    OptionSet::iterator pos;
+    strm.IndentMore (5);
+
+    int first_option_printed = 1;
+    for (i = 0; i < num_options; ++i)
+    {
+        // Only print out this option if we haven't already seen it.
+        pos = options_seen.find (full_options_table[i].short_option);
+        if (pos == options_seen.end())
+        {
+            // Put a newline separation between arguments
+            if (first_option_printed)
+                first_option_printed = 0;
+            else
+                strm.EOL();
+      
+            options_seen.insert (full_options_table[i].short_option);
+            strm.Indent ();
+            strm.Printf ("-%c ", full_options_table[i].short_option);
+            if (full_options_table[i].argument_name != NULL)
+                strm.PutCString(full_options_table[i].argument_name);
+            strm.EOL();
+            strm.Indent ();
+            strm.Printf ("--%s ", full_options_table[i].long_option);
+            if (full_options_table[i].argument_name != NULL)
+                strm.PutCString(full_options_table[i].argument_name);
+            strm.EOL();
+
+            strm.IndentMore (5);
+            
+            if (full_options_table[i].usage_text)
+                    OutputFormattedUsageText (strm,
+                                              full_options_table[i].usage_text,
+                                              screen_width);
+            if (full_options_table[i].enum_values != NULL)
+            {
+                strm.Indent ();
+                strm.Printf("Values: ");
+                for (int j = 0; full_options_table[i].enum_values[j].string_value != NULL; j++) 
+                {
+                    if (j == 0)
+                        strm.Printf("%s", full_options_table[i].enum_values[j].string_value);
+                    else
+                        strm.Printf(" | %s", full_options_table[i].enum_values[j].string_value);
+                }
+                strm.EOL();
+            }
+            strm.IndentLess (5);
+        }
+    }
+
+    // Restore the indent level
+    strm.SetIndentLevel (save_indent_level);
+}
+
+// This function is called when we have been given a potentially incomplete set of
+// options, such as when an alias has been defined (more options might be added at
+// at the time the alias is invoked).  We need to verify that the options in the set
+// m_seen_options are all part of a set that may be used together, but m_seen_options
+// may be missing some of the "required" options.
+
+bool
+Options::VerifyPartialOptions (CommandReturnObject &result)
+{
+    bool options_are_valid = false;
+
+    int num_levels = m_required_options.size();
+    if (num_levels)
+      {
+        for (int i = 0; i < num_levels && !options_are_valid; ++i)
+          {
+            // In this case we are treating all options as optional rather than required.
+            // Therefore a set of options is correct if m_seen_options is a subset of the
+            // union of m_required_options and m_optional_options.
+            OptionSet union_set;
+            OptionsSetUnion (m_required_options[i], m_optional_options[i], union_set);
+            if (IsASubset (m_seen_options, union_set))
+                options_are_valid = true;
+          }
+      }
+
+    return options_are_valid;
+}
+
+bool
+Options::HandleOptionCompletion
+(
+    Args &input,
+    OptionElementVector &opt_element_vector,
+    int cursor_index,
+    int char_pos,
+    int match_start_point,
+    int max_return_elements,
+    lldb_private::CommandInterpreter *interpreter,
+    lldb_private::StringList &matches
+)
+{
+    // For now we just scan the completions to see if the cursor position is in
+    // an option or its argument.  Otherwise we'll call HandleArgumentCompletion.
+    // In the future we can use completion to validate options as well if we want.
+
+    const OptionDefinition *opt_defs = GetDefinitions();
+
+    std::string cur_opt_std_str (input.GetArgumentAtIndex(cursor_index));
+    cur_opt_std_str.erase(char_pos);
+    const char *cur_opt_str = cur_opt_std_str.c_str();
+
+    for (int i = 0; i < opt_element_vector.size(); i++)
+    {
+        int opt_pos = opt_element_vector[i].opt_pos;
+        int opt_arg_pos = opt_element_vector[i].opt_arg_pos;
+        int opt_defs_index = opt_element_vector[i].opt_defs_index;
+        if (opt_pos == cursor_index)
+        {
+            // We're completing the option itself.
+            if (opt_defs_index != -1)
+            {
+                // We recognized it, if it an incomplete long option, complete it anyway (getopt_long is
+                // happy with shortest unique string, but it's still a nice thing to do.)  Otherwise return
+                // The string so the upper level code will know this is a full match and add the " ".
+                if (cur_opt_str && strlen (cur_opt_str) > 2
+                    && cur_opt_str[0] == '-' && cur_opt_str[1] == '-'
+                    && strcmp (opt_defs[opt_defs_index].long_option, cur_opt_str) != 0)
+                {
+                        std::string full_name ("--");
+                        full_name.append (opt_defs[opt_defs_index].long_option);
+                        matches.AppendString(full_name.c_str());
+                        return true;
+                }
+                else
+                {
+                    matches.AppendString(input.GetArgumentAtIndex(cursor_index));
+                    return true;
+                }
+            }
+            else
+            {
+                // FIXME - not handling wrong options yet:
+                // Check to see if they are writing a long option & complete it.
+                // I think we will only get in here if the long option table has two elements
+                // that are not unique up to this point.  getopt_long does shortest unique match
+                // for long options already.
+
+                if (cur_opt_str && strlen (cur_opt_str) > 2
+                    && cur_opt_str[0] == '-' && cur_opt_str[1] == '-')
+                {
+                    for (int i = 0 ; opt_defs[i].short_option != 0 ; i++)
+                    {
+                        if (strstr(opt_defs[i].long_option, cur_opt_str + 2) == opt_defs[i].long_option)
+                        {
+                            std::string full_name ("--");
+                            full_name.append (opt_defs[i].long_option);
+                            // The options definitions table has duplicates because of the
+                            // way the grouping information is stored, so only add once.
+                            bool duplicate = false;
+                            for (int j = 0; j < matches.GetSize(); j++)
+                            {
+                                if (matches.GetStringAtIndex(j) == full_name)
+                                {
+                                    duplicate = true;
+                                    break;
+                                }
+                            }
+                            if (!duplicate)
+                                matches.AppendString(full_name.c_str());
+                        }
+                    }
+                }
+                return true;
+            }
+
+
+        }
+        else if (opt_arg_pos == cursor_index)
+        {
+            // Okay the cursor is on the completion of an argument.
+            // See if it has a completion, otherwise return no matches.
+
+            if (opt_defs_index != -1)
+            {
+                HandleOptionArgumentCompletion (input,
+                                                 cursor_index,
+                                                 strlen (input.GetArgumentAtIndex(cursor_index)),
+                                                 opt_element_vector,
+                                                 i,
+                                                 match_start_point,
+                                                 max_return_elements,
+                                                 interpreter,
+                                                 matches);
+                return true;
+            }
+            else
+            {
+                // No completion callback means no completions...
+                return true;
+            }
+
+        }
+        else
+        {
+            // Not the last element, keep going.
+            continue;
+        }
+    }
+    return false;
+}
+
+bool
+Options::HandleOptionArgumentCompletion
+(
+    Args &input,
+    int cursor_index,
+    int char_pos,
+    OptionElementVector &opt_element_vector,
+    int opt_element_index,
+    int match_start_point,
+    int max_return_elements,
+    lldb_private::CommandInterpreter *interpreter,
+    lldb_private::StringList &matches
+)
+{
+    const OptionDefinition *opt_defs = GetDefinitions();
+    std::auto_ptr<SearchFilter> filter_ap;
+
+    int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
+    int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
+    
+    // See if this is an enumeration type option, and if so complete it here:
+    
+    OptionEnumValueElement *enum_values = opt_defs[opt_defs_index].enum_values;
+    if (enum_values != NULL)
+    {
+        bool return_value = false;
+        std::string match_string(input.GetArgumentAtIndex (opt_arg_pos), input.GetArgumentAtIndex (opt_arg_pos) + char_pos);
+        for (int i = 0; enum_values[i].string_value != NULL; i++)
+        {
+            if (strstr(enum_values[i].string_value, match_string.c_str()) == enum_values[i].string_value)
+            {
+                matches.AppendString (enum_values[i].string_value);
+                return_value = true;
+            }
+        }
+        return return_value;
+    }
+
+    // If this is a source file or symbol type completion, and  there is a
+    // -shlib option somewhere in the supplied arguments, then make a search filter
+    // for that shared library.
+    // FIXME: Do we want to also have an "OptionType" so we don't have to match string names?
+
+    uint32_t completion_mask = opt_defs[opt_defs_index].completionType;
+    if (completion_mask & CommandCompletions::eSourceFileCompletion
+        || completion_mask & CommandCompletions::eSymbolCompletion)
+    {
+        for (int i = 0; i < opt_element_vector.size(); i++)
+        {
+            int cur_defs_index = opt_element_vector[i].opt_defs_index;
+            int cur_arg_pos    = opt_element_vector[i].opt_arg_pos;
+            const char *cur_opt_name = opt_defs[cur_defs_index].long_option;
+
+            // If this is the "shlib" option and there was an argument provided,
+            // restrict it to that shared library.
+            if (strcmp(cur_opt_name, "shlib") == 0 && cur_arg_pos != -1)
+            {
+                const char *module_name = input.GetArgumentAtIndex(cur_arg_pos);
+                if (module_name)
+                {
+                    FileSpec module_spec(module_name);
+                    lldb::TargetSP target_sp = interpreter->Context()->GetTarget()->GetSP();
+                    // Search filters require a target...
+                    if (target_sp != NULL)
+                        filter_ap.reset (new SearchFilterByModule (target_sp, module_spec));
+                }
+                break;
+            }
+        }
+    }
+
+    return CommandCompletions::InvokeCommonCompletionCallbacks (completion_mask,
+                                                                 input.GetArgumentAtIndex (opt_arg_pos),
+                                                                 match_start_point,
+                                                                 max_return_elements,
+                                                                 interpreter,
+                                                                 filter_ap.get(),
+                                                                 matches);
+
+}
diff --git a/source/Core/PluginManager.cpp b/source/Core/PluginManager.cpp
new file mode 100644
index 0000000..3723e7c
--- /dev/null
+++ b/source/Core/PluginManager.cpp
@@ -0,0 +1,1133 @@
+//===-- PluginManager.cpp ---------------------------------------*- 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/PluginManager.h"
+
+#include <string>
+#include <vector>
+
+using namespace lldb_private;
+
+typedef enum PluginAction
+{
+    ePluginRegisterInstance,
+    ePluginUnregisterInstance,
+    ePluginGetInstanceAtIndex
+};
+
+
+#pragma mark ABI
+
+
+typedef struct ABIInstance
+{
+    ABIInstance() :
+        name(),
+        description(),
+        create_callback(NULL)
+    {
+    }
+
+    std::string name;
+    std::string description;
+    ABICreateInstance create_callback;
+};
+
+typedef std::vector<ABIInstance> ABIInstances;
+
+static bool
+AccessABIInstances (PluginAction action, ABIInstance &instance, uint32_t index)
+{
+    static ABIInstances g_plugin_instances;
+
+    switch (action)
+    {
+        case ePluginRegisterInstance:
+            if (instance.create_callback)
+            {
+                g_plugin_instances.push_back (instance);
+                return true;
+            }
+            break;
+
+        case ePluginUnregisterInstance:
+            if (instance.create_callback)
+            {
+                ABIInstances::iterator pos, end = g_plugin_instances.end();
+                for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
+                {
+                    if (pos->create_callback == instance.create_callback)
+                    {
+                        g_plugin_instances.erase(pos);
+                        return true;
+                    }
+                }
+            }
+            break;
+
+        case ePluginGetInstanceAtIndex:
+            if (index < g_plugin_instances.size())
+            {
+                instance = g_plugin_instances[index];
+                return true;
+            }
+            break;
+
+        default:
+            break;
+    }
+    return false;
+}
+
+
+bool
+PluginManager::RegisterPlugin
+    (
+        const char *name,
+        const char *description,
+        ABICreateInstance create_callback
+     )
+{
+    if (create_callback)
+    {
+        ABIInstance instance;
+        assert (name && name[0]);
+        instance.name = name;
+        if (description && description[0])
+            instance.description = description;
+        instance.create_callback = create_callback;
+        return AccessABIInstances (ePluginRegisterInstance, instance, 0);
+    }
+    return false;
+}
+
+bool
+PluginManager::UnregisterPlugin (ABICreateInstance create_callback)
+{
+    if (create_callback)
+    {
+        ABIInstance instance;
+        instance.create_callback = create_callback;
+        return AccessABIInstances (ePluginUnregisterInstance, instance, 0);
+    }
+    return false;
+}
+
+ABICreateInstance
+PluginManager::GetABICreateCallbackAtIndex (uint32_t idx)
+{
+    ABIInstance instance;
+    if (AccessABIInstances (ePluginGetInstanceAtIndex, instance, idx))
+        return instance.create_callback;
+    return false;
+}
+
+ABICreateInstance
+PluginManager::GetABICreateCallbackForPluginName (const char *name)
+{
+    if (name && name[0])
+    {
+        ABIInstance instance;
+        std::string ss_name(name);
+        for (uint32_t idx = 0; AccessABIInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
+        {
+            if (instance.name == ss_name)
+                return instance.create_callback;
+        }
+    }
+    return NULL;
+}
+
+
+#pragma mark Disassembler
+
+
+typedef struct DisassemblerInstance
+{
+    DisassemblerInstance() :
+        name(),
+        description(),
+        create_callback(NULL)
+    {
+    }
+
+    std::string name;
+    std::string description;
+    DisassemblerCreateInstance create_callback;
+};
+
+typedef std::vector<DisassemblerInstance> DisassemblerInstances;
+
+static bool
+AccessDisassemblerInstances (PluginAction action, DisassemblerInstance &instance, uint32_t index)
+{
+    static DisassemblerInstances g_plugin_instances;
+
+    switch (action)
+    {
+    case ePluginRegisterInstance:
+        if (instance.create_callback)
+        {
+            g_plugin_instances.push_back (instance);
+            return true;
+        }
+        break;
+
+    case ePluginUnregisterInstance:
+        if (instance.create_callback)
+        {
+            DisassemblerInstances::iterator pos, end = g_plugin_instances.end();
+            for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
+            {
+                if (pos->create_callback == instance.create_callback)
+                {
+                    g_plugin_instances.erase(pos);
+                    return true;
+                }
+            }
+        }
+        break;
+
+    case ePluginGetInstanceAtIndex:
+        if (index < g_plugin_instances.size())
+        {
+            instance = g_plugin_instances[index];
+            return true;
+        }
+        break;
+
+    default:
+        break;
+    }
+    return false;
+}
+
+
+bool
+PluginManager::RegisterPlugin
+(
+    const char *name,
+    const char *description,
+    DisassemblerCreateInstance create_callback
+)
+{
+    if (create_callback)
+    {
+        DisassemblerInstance instance;
+        assert (name && name[0]);
+        instance.name = name;
+        if (description && description[0])
+            instance.description = description;
+        instance.create_callback = create_callback;
+        return AccessDisassemblerInstances (ePluginRegisterInstance, instance, 0);
+    }
+    return false;
+}
+
+bool
+PluginManager::UnregisterPlugin (DisassemblerCreateInstance create_callback)
+{
+    if (create_callback)
+    {
+        DisassemblerInstance instance;
+        instance.create_callback = create_callback;
+        return AccessDisassemblerInstances (ePluginUnregisterInstance, instance, 0);
+    }
+    return false;
+}
+
+DisassemblerCreateInstance
+PluginManager::GetDisassemblerCreateCallbackAtIndex (uint32_t idx)
+{
+    DisassemblerInstance instance;
+    if (AccessDisassemblerInstances (ePluginGetInstanceAtIndex, instance, idx))
+        return instance.create_callback;
+    return false;
+}
+
+DisassemblerCreateInstance
+PluginManager::GetDisassemblerCreateCallbackForPluginName (const char *name)
+{
+    if (name && name[0])
+    {
+        DisassemblerInstance instance;
+        std::string ss_name(name);
+        for (uint32_t idx = 0; AccessDisassemblerInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
+        {
+            if (instance.name == ss_name)
+                return instance.create_callback;
+        }
+    }
+    return NULL;
+}
+
+
+
+#pragma mark DynamicLoader
+
+
+typedef struct DynamicLoaderInstance
+{
+    DynamicLoaderInstance() :
+        name(),
+        description(),
+        create_callback(NULL)
+    {
+    }
+
+    std::string name;
+    std::string description;
+    DynamicLoaderCreateInstance create_callback;
+};
+
+typedef std::vector<DynamicLoaderInstance> DynamicLoaderInstances;
+
+static bool
+AccessDynamicLoaderInstances (PluginAction action, DynamicLoaderInstance &instance, uint32_t index)
+{
+    static DynamicLoaderInstances g_plugin_instances;
+
+    switch (action)
+    {
+    case ePluginRegisterInstance:
+        if (instance.create_callback)
+        {
+            g_plugin_instances.push_back (instance);
+            return true;
+        }
+        break;
+
+    case ePluginUnregisterInstance:
+        if (instance.create_callback)
+        {
+            DynamicLoaderInstances::iterator pos, end = g_plugin_instances.end();
+            for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
+            {
+                if (pos->create_callback == instance.create_callback)
+                {
+                    g_plugin_instances.erase(pos);
+                    return true;
+                }
+            }
+        }
+        break;
+
+    case ePluginGetInstanceAtIndex:
+        if (index < g_plugin_instances.size())
+        {
+            instance = g_plugin_instances[index];
+            return true;
+        }
+        break;
+
+    default:
+        break;
+    }
+    return false;
+}
+
+
+bool
+PluginManager::RegisterPlugin
+(
+    const char *name,
+    const char *description,
+    DynamicLoaderCreateInstance create_callback
+)
+{
+    if (create_callback)
+    {
+        DynamicLoaderInstance instance;
+        assert (name && name[0]);
+        instance.name = name;
+        if (description && description[0])
+            instance.description = description;
+        instance.create_callback = create_callback;
+        return AccessDynamicLoaderInstances (ePluginRegisterInstance, instance, 0);
+    }
+    return false;
+}
+
+bool
+PluginManager::UnregisterPlugin (DynamicLoaderCreateInstance create_callback)
+{
+    if (create_callback)
+    {
+        DynamicLoaderInstance instance;
+        instance.create_callback = create_callback;
+        return AccessDynamicLoaderInstances (ePluginUnregisterInstance, instance, 0);
+    }
+    return false;
+}
+
+DynamicLoaderCreateInstance
+PluginManager::GetDynamicLoaderCreateCallbackAtIndex (uint32_t idx)
+{
+    DynamicLoaderInstance instance;
+    if (AccessDynamicLoaderInstances (ePluginGetInstanceAtIndex, instance, idx))
+        return instance.create_callback;
+    return false;
+}
+
+DynamicLoaderCreateInstance
+PluginManager::GetDynamicLoaderCreateCallbackForPluginName (const char *name)
+{
+    if (name && name[0])
+    {
+        DynamicLoaderInstance instance;
+        std::string ss_name(name);
+        for (uint32_t idx = 0; AccessDynamicLoaderInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
+        {
+            if (instance.name == ss_name)
+                return instance.create_callback;
+        }
+    }
+    return NULL;
+}
+
+
+
+
+#pragma mark ObjectFile
+
+typedef struct ObjectFileInstance
+{
+    ObjectFileInstance() :
+        name(),
+        description(),
+        create_callback(NULL)
+    {
+    }
+
+    std::string name;
+    std::string description;
+    ObjectFileCreateInstance create_callback;
+};
+
+typedef std::vector<ObjectFileInstance> ObjectFileInstances;
+
+static bool
+AccessObjectFileInstances (PluginAction action, ObjectFileInstance &instance, uint32_t index)
+{
+    static ObjectFileInstances g_plugin_instances;
+
+    switch (action)
+    {
+    case ePluginRegisterInstance:
+        if (instance.create_callback)
+        {
+            g_plugin_instances.push_back (instance);
+            return true;
+        }
+        break;
+
+    case ePluginUnregisterInstance:
+        if (instance.create_callback)
+        {
+            ObjectFileInstances::iterator pos, end = g_plugin_instances.end();
+            for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
+            {
+                if (pos->create_callback == instance.create_callback)
+                {
+                    g_plugin_instances.erase(pos);
+                    return true;
+                }
+            }
+        }
+        break;
+
+    case ePluginGetInstanceAtIndex:
+        if (index < g_plugin_instances.size())
+        {
+            instance = g_plugin_instances[index];
+            return true;
+        }
+        break;
+
+    default:
+        break;
+    }
+    return false;
+}
+
+
+bool
+PluginManager::RegisterPlugin
+(
+    const char *name,
+    const char *description,
+    ObjectFileCreateInstance create_callback
+)
+{
+    if (create_callback)
+    {
+        ObjectFileInstance instance;
+        assert (name && name[0]);
+        instance.name = name;
+        if (description && description[0])
+            instance.description = description;
+        instance.create_callback = create_callback;
+        return AccessObjectFileInstances (ePluginRegisterInstance, instance, 0);
+    }
+    return false;
+}
+
+bool
+PluginManager::UnregisterPlugin (ObjectFileCreateInstance create_callback)
+{
+    if (create_callback)
+    {
+        ObjectFileInstance instance;
+        instance.create_callback = create_callback;
+        return AccessObjectFileInstances (ePluginUnregisterInstance, instance, 0);
+    }
+    return false;
+}
+
+ObjectFileCreateInstance
+PluginManager::GetObjectFileCreateCallbackAtIndex (uint32_t idx)
+{
+    ObjectFileInstance instance;
+    if (AccessObjectFileInstances (ePluginGetInstanceAtIndex, instance, idx))
+        return instance.create_callback;
+    return false;
+}
+ObjectFileCreateInstance
+PluginManager::GetObjectFileCreateCallbackForPluginName (const char *name)
+{
+    if (name && name[0])
+    {
+        ObjectFileInstance instance;
+        std::string ss_name(name);
+        for (uint32_t idx = 0; AccessObjectFileInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
+        {
+            if (instance.name == ss_name)
+                return instance.create_callback;
+        }
+    }
+    return NULL;
+}
+
+
+
+#pragma mark ObjectContainer
+
+typedef struct ObjectContainerInstance
+{
+    ObjectContainerInstance() :
+        name(),
+        description(),
+        create_callback(NULL)
+    {
+    }
+
+    std::string name;
+    std::string description;
+    ObjectContainerCreateInstance create_callback;
+};
+
+typedef std::vector<ObjectContainerInstance> ObjectContainerInstances;
+
+static bool
+AccessObjectContainerInstances (PluginAction action, ObjectContainerInstance &instance, uint32_t index)
+{
+    static ObjectContainerInstances g_plugin_instances;
+
+    switch (action)
+    {
+    case ePluginRegisterInstance:
+        if (instance.create_callback)
+        {
+            g_plugin_instances.push_back (instance);
+            return true;
+        }
+        break;
+
+    case ePluginUnregisterInstance:
+        if (instance.create_callback)
+        {
+            ObjectContainerInstances::iterator pos, end = g_plugin_instances.end();
+            for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
+            {
+                if (pos->create_callback == instance.create_callback)
+                {
+                    g_plugin_instances.erase(pos);
+                    return true;
+                }
+            }
+        }
+        break;
+
+    case ePluginGetInstanceAtIndex:
+        if (index < g_plugin_instances.size())
+        {
+            instance = g_plugin_instances[index];
+            return true;
+        }
+        break;
+
+    default:
+        break;
+    }
+    return false;
+}
+
+
+bool
+PluginManager::RegisterPlugin
+(
+    const char *name,
+    const char *description,
+    ObjectContainerCreateInstance create_callback
+)
+{
+    if (create_callback)
+    {
+        ObjectContainerInstance instance;
+        assert (name && name[0]);
+        instance.name = name;
+        if (description && description[0])
+            instance.description = description;
+        instance.create_callback = create_callback;
+        return AccessObjectContainerInstances (ePluginRegisterInstance, instance, 0);
+    }
+    return false;
+}
+
+bool
+PluginManager::UnregisterPlugin (ObjectContainerCreateInstance create_callback)
+{
+    if (create_callback)
+    {
+        ObjectContainerInstance instance;
+        instance.create_callback = create_callback;
+        return AccessObjectContainerInstances (ePluginUnregisterInstance, instance, 0);
+    }
+    return false;
+}
+
+ObjectContainerCreateInstance
+PluginManager::GetObjectContainerCreateCallbackAtIndex (uint32_t idx)
+{
+    ObjectContainerInstance instance;
+    if (AccessObjectContainerInstances (ePluginGetInstanceAtIndex, instance, idx))
+        return instance.create_callback;
+    return false;
+}
+ObjectContainerCreateInstance
+PluginManager::GetObjectContainerCreateCallbackForPluginName (const char *name)
+{
+    if (name && name[0])
+    {
+        ObjectContainerInstance instance;
+        std::string ss_name(name);
+        for (uint32_t idx = 0; AccessObjectContainerInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
+        {
+            if (instance.name == ss_name)
+                return instance.create_callback;
+        }
+    }
+    return NULL;
+}
+
+#pragma mark LogChannel
+
+typedef struct LogChannelInstance
+{
+    LogChannelInstance() :
+        name(),
+        description(),
+        create_callback(NULL)
+    {
+    }
+
+    std::string name;
+    std::string description;
+    LogChannelCreateInstance create_callback;
+};
+
+typedef std::vector<LogChannelInstance> LogChannelInstances;
+
+static bool
+AccessLogChannelInstances (PluginAction action, LogChannelInstance &instance, uint32_t index)
+{
+    static LogChannelInstances g_plugin_instances;
+
+    switch (action)
+    {
+    case ePluginRegisterInstance:
+        if (instance.create_callback)
+        {
+            g_plugin_instances.push_back (instance);
+            return true;
+        }
+        break;
+
+    case ePluginUnregisterInstance:
+        if (instance.create_callback)
+        {
+            LogChannelInstances::iterator pos, end = g_plugin_instances.end();
+            for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
+            {
+                if (pos->create_callback == instance.create_callback)
+                {
+                    g_plugin_instances.erase(pos);
+                    return true;
+                }
+            }
+        }
+        break;
+
+    case ePluginGetInstanceAtIndex:
+        if (index < g_plugin_instances.size())
+        {
+            instance = g_plugin_instances[index];
+            return true;
+        }
+        break;
+
+    default:
+        break;
+    }
+    return false;
+}
+
+
+bool
+PluginManager::RegisterPlugin
+(
+    const char *name,
+    const char *description,
+    LogChannelCreateInstance create_callback
+)
+{
+    if (create_callback)
+    {
+        LogChannelInstance instance;
+        assert (name && name[0]);
+        instance.name = name;
+        if (description && description[0])
+            instance.description = description;
+        instance.create_callback = create_callback;
+        return AccessLogChannelInstances (ePluginRegisterInstance, instance, 0);
+    }
+    return false;
+}
+
+bool
+PluginManager::UnregisterPlugin (LogChannelCreateInstance create_callback)
+{
+    if (create_callback)
+    {
+        LogChannelInstance instance;
+        instance.create_callback = create_callback;
+        return AccessLogChannelInstances (ePluginUnregisterInstance, instance, 0);
+    }
+    return false;
+}
+
+const char *
+PluginManager::GetLogChannelCreateNameAtIndex (uint32_t idx)
+{
+    LogChannelInstance instance;
+    if (AccessLogChannelInstances (ePluginGetInstanceAtIndex, instance, idx))
+        return instance.name.c_str();
+    return NULL;
+}
+
+
+LogChannelCreateInstance
+PluginManager::GetLogChannelCreateCallbackAtIndex (uint32_t idx)
+{
+    LogChannelInstance instance;
+    if (AccessLogChannelInstances (ePluginGetInstanceAtIndex, instance, idx))
+        return instance.create_callback;
+    return false;
+}
+
+LogChannelCreateInstance
+PluginManager::GetLogChannelCreateCallbackForPluginName (const char *name)
+{
+    if (name && name[0])
+    {
+        LogChannelInstance instance;
+        std::string ss_name(name);
+        for (uint32_t idx = 0; AccessLogChannelInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
+        {
+            if (instance.name == ss_name)
+                return instance.create_callback;
+        }
+    }
+    return NULL;
+}
+
+#pragma mark Process
+
+typedef struct ProcessInstance
+{
+    ProcessInstance() :
+        name(),
+        description(),
+        create_callback(NULL)
+    {
+    }
+
+    std::string name;
+    std::string description;
+    ProcessCreateInstance create_callback;
+};
+
+typedef std::vector<ProcessInstance> ProcessInstances;
+
+static bool
+AccessProcessInstances (PluginAction action, ProcessInstance &instance, uint32_t index)
+{
+    static ProcessInstances g_plugin_instances;
+
+    switch (action)
+    {
+    case ePluginRegisterInstance:
+        if (instance.create_callback)
+        {
+            g_plugin_instances.push_back (instance);
+            return true;
+        }
+        break;
+
+    case ePluginUnregisterInstance:
+        if (instance.create_callback)
+        {
+            ProcessInstances::iterator pos, end = g_plugin_instances.end();
+            for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
+            {
+                if (pos->create_callback == instance.create_callback)
+                {
+                    g_plugin_instances.erase(pos);
+                    return true;
+                }
+            }
+        }
+        break;
+
+    case ePluginGetInstanceAtIndex:
+        if (index < g_plugin_instances.size())
+        {
+            instance = g_plugin_instances[index];
+            return true;
+        }
+        break;
+
+    default:
+        break;
+    }
+    return false;
+}
+
+
+bool
+PluginManager::RegisterPlugin
+(
+    const char *name,
+    const char *description,
+    ProcessCreateInstance create_callback
+)
+{
+    if (create_callback)
+    {
+        ProcessInstance instance;
+        assert (name && name[0]);
+        instance.name = name;
+        if (description && description[0])
+            instance.description = description;
+        instance.create_callback = create_callback;
+        return AccessProcessInstances (ePluginRegisterInstance, instance, 0);
+    }
+    return false;
+}
+
+bool
+PluginManager::UnregisterPlugin (ProcessCreateInstance create_callback)
+{
+    if (create_callback)
+    {
+        ProcessInstance instance;
+        instance.create_callback = create_callback;
+        return AccessProcessInstances (ePluginUnregisterInstance, instance, 0);
+    }
+    return false;
+}
+
+ProcessCreateInstance
+PluginManager::GetProcessCreateCallbackAtIndex (uint32_t idx)
+{
+    ProcessInstance instance;
+    if (AccessProcessInstances (ePluginGetInstanceAtIndex, instance, idx))
+        return instance.create_callback;
+    return false;
+}
+
+ProcessCreateInstance
+PluginManager::GetProcessCreateCallbackForPluginName (const char *name)
+{
+    if (name && name[0])
+    {
+        ProcessInstance instance;
+        std::string ss_name(name);
+        for (uint32_t idx = 0; AccessProcessInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
+        {
+            if (instance.name == ss_name)
+                return instance.create_callback;
+        }
+    }
+    return NULL;
+}
+
+#pragma mark SymbolFile
+
+typedef struct SymbolFileInstance
+{
+    SymbolFileInstance() :
+        name(),
+        description(),
+        create_callback(NULL)
+    {
+    }
+
+    std::string name;
+    std::string description;
+    SymbolFileCreateInstance create_callback;
+};
+
+typedef std::vector<SymbolFileInstance> SymbolFileInstances;
+
+static bool
+AccessSymbolFileInstances (PluginAction action, SymbolFileInstance &instance, uint32_t index)
+{
+    static SymbolFileInstances g_plugin_instances;
+
+    switch (action)
+    {
+    case ePluginRegisterInstance:
+        if (instance.create_callback)
+        {
+            g_plugin_instances.push_back (instance);
+            return true;
+        }
+        break;
+
+    case ePluginUnregisterInstance:
+        if (instance.create_callback)
+        {
+            SymbolFileInstances::iterator pos, end = g_plugin_instances.end();
+            for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
+            {
+                if (pos->create_callback == instance.create_callback)
+                {
+                    g_plugin_instances.erase(pos);
+                    return true;
+                }
+            }
+        }
+        break;
+
+    case ePluginGetInstanceAtIndex:
+        if (index < g_plugin_instances.size())
+        {
+            instance = g_plugin_instances[index];
+            return true;
+        }
+        break;
+
+    default:
+        break;
+    }
+    return false;
+}
+
+
+bool
+PluginManager::RegisterPlugin
+(
+    const char *name,
+    const char *description,
+    SymbolFileCreateInstance create_callback
+)
+{
+    if (create_callback)
+    {
+        SymbolFileInstance instance;
+        assert (name && name[0]);
+        instance.name = name;
+        if (description && description[0])
+            instance.description = description;
+        instance.create_callback = create_callback;
+        return AccessSymbolFileInstances (ePluginRegisterInstance, instance, 0);
+    }
+    return false;
+}
+
+bool
+PluginManager::UnregisterPlugin (SymbolFileCreateInstance create_callback)
+{
+    if (create_callback)
+    {
+        SymbolFileInstance instance;
+        instance.create_callback = create_callback;
+        return AccessSymbolFileInstances (ePluginUnregisterInstance, instance, 0);
+    }
+    return false;
+}
+
+SymbolFileCreateInstance
+PluginManager::GetSymbolFileCreateCallbackAtIndex (uint32_t idx)
+{
+    SymbolFileInstance instance;
+    if (AccessSymbolFileInstances (ePluginGetInstanceAtIndex, instance, idx))
+        return instance.create_callback;
+    return false;
+}
+SymbolFileCreateInstance
+PluginManager::GetSymbolFileCreateCallbackForPluginName (const char *name)
+{
+    if (name && name[0])
+    {
+        SymbolFileInstance instance;
+        std::string ss_name(name);
+        for (uint32_t idx = 0; AccessSymbolFileInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
+        {
+            if (instance.name == ss_name)
+                return instance.create_callback;
+        }
+    }
+    return NULL;
+}
+
+
+
+#pragma mark SymbolVendor
+
+typedef struct SymbolVendorInstance
+{
+    SymbolVendorInstance() :
+        name(),
+        description(),
+        create_callback(NULL)
+    {
+    }
+
+    std::string name;
+    std::string description;
+    SymbolVendorCreateInstance create_callback;
+};
+
+typedef std::vector<SymbolVendorInstance> SymbolVendorInstances;
+
+static bool
+AccessSymbolVendorInstances (PluginAction action, SymbolVendorInstance &instance, uint32_t index)
+{
+    static SymbolVendorInstances g_plugin_instances;
+
+    switch (action)
+    {
+    case ePluginRegisterInstance:
+        if (instance.create_callback)
+        {
+            g_plugin_instances.push_back (instance);
+            return true;
+        }
+        break;
+
+    case ePluginUnregisterInstance:
+        if (instance.create_callback)
+        {
+            SymbolVendorInstances::iterator pos, end = g_plugin_instances.end();
+            for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
+            {
+                if (pos->create_callback == instance.create_callback)
+                {
+                    g_plugin_instances.erase(pos);
+                    return true;
+                }
+            }
+        }
+        break;
+
+    case ePluginGetInstanceAtIndex:
+        if (index < g_plugin_instances.size())
+        {
+            instance = g_plugin_instances[index];
+            return true;
+        }
+        break;
+
+    default:
+        break;
+    }
+    return false;
+}
+
+bool
+PluginManager::RegisterPlugin
+(
+    const char *name,
+    const char *description,
+    SymbolVendorCreateInstance create_callback
+)
+{
+    if (create_callback)
+    {
+        SymbolVendorInstance instance;
+        assert (name && name[0]);
+        instance.name = name;
+        if (description && description[0])
+            instance.description = description;
+        instance.create_callback = create_callback;
+        return AccessSymbolVendorInstances (ePluginRegisterInstance, instance, 0);
+    }
+    return false;
+}
+
+bool
+PluginManager::UnregisterPlugin (SymbolVendorCreateInstance create_callback)
+{
+    if (create_callback)
+    {
+        SymbolVendorInstance instance;
+        instance.create_callback = create_callback;
+        return AccessSymbolVendorInstances (ePluginUnregisterInstance, instance, 0);
+    }
+    return false;
+}
+
+SymbolVendorCreateInstance
+PluginManager::GetSymbolVendorCreateCallbackAtIndex (uint32_t idx)
+{
+    SymbolVendorInstance instance;
+    if (AccessSymbolVendorInstances (ePluginGetInstanceAtIndex, instance, idx))
+        return instance.create_callback;
+    return false;
+}
+
+SymbolVendorCreateInstance
+PluginManager::GetSymbolVendorCreateCallbackForPluginName (const char *name)
+{
+    if (name && name[0])
+    {
+        SymbolVendorInstance instance;
+        std::string ss_name(name);
+        for (uint32_t idx = 0; AccessSymbolVendorInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
+        {
+            if (instance.name == ss_name)
+                return instance.create_callback;
+        }
+    }
+    return NULL;
+}
+
+
diff --git a/source/Core/RegularExpression.cpp b/source/Core/RegularExpression.cpp
new file mode 100644
index 0000000..aca1671
--- /dev/null
+++ b/source/Core/RegularExpression.cpp
@@ -0,0 +1,154 @@
+//===-- RegularExpression.cpp -----------------------------------*- 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/RegularExpression.h"
+
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Default constructor
+//----------------------------------------------------------------------
+RegularExpression::RegularExpression() :
+    m_re(),
+    m_comp_err (1),
+    m_preg(),
+    m_matches()
+{
+    memset(&m_preg,0,sizeof(m_preg));
+}
+
+//----------------------------------------------------------------------
+// Constructor that compiles "re" using "flags" and stores the
+// resulting compiled regular expression into this object.
+//----------------------------------------------------------------------
+RegularExpression::RegularExpression(const char* re, int flags) :
+    m_re(),
+    m_comp_err (1),
+    m_preg()
+{
+    memset(&m_preg,0,sizeof(m_preg));
+    Compile(re, flags);
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//
+// Any previosuly compiled regular expression contained in this
+// object will be freed.
+//----------------------------------------------------------------------
+RegularExpression::~RegularExpression()
+{
+    Free();
+}
+
+//----------------------------------------------------------------------
+// Compile a regular expression using the supplied regular
+// expression text and flags. The compied regular expression lives
+// in this object so that it can be readily used for regular
+// expression matches. Execute() can be called after the regular
+// expression is compiled. Any previosuly compiled regular
+// expression contained in this object will be freed.
+//
+// RETURNS
+//  True of the refular expression compiles successfully, false
+//  otherwise.
+//----------------------------------------------------------------------
+bool
+RegularExpression::Compile(const char* re, int flags)
+{
+    Free();
+    if (re && re[0])
+    {
+        m_re = re;
+        m_comp_err = ::regcomp (&m_preg, re, flags);
+    }
+    else
+    {
+        // No valid regular expression
+        m_comp_err = 1;
+    }
+
+    return m_comp_err == 0;
+}
+
+//----------------------------------------------------------------------
+// Execute a regular expression match using the compiled regular
+// expression that is already in this object against the match
+// string "s". If any parens are used for regular expression
+// matches "match_count" should indicate the number of regmatch_t
+// values that are present in "match_ptr". The regular expression
+// will be executed using the "execute_flags".
+//----------------------------------------------------------------------
+bool
+RegularExpression::Execute(const char* s, size_t num_matches, int execute_flags) const
+{
+    int match_result = 1;
+    if (m_comp_err == 0)
+    {
+        if (num_matches > 0)
+            m_matches.resize(num_matches + 1);
+        else
+            m_matches.clear();
+
+        match_result = ::regexec (&m_preg,
+                                  s,
+                                  m_matches.size(),
+                                  const_cast<regmatch_t *>(m_matches.data()),
+                                  execute_flags);
+    }
+    return match_result == 0;
+}
+
+bool
+RegularExpression::GetMatchAtIndex (const char* s, uint32_t idx, std::string& match_str) const
+{
+    if (idx <= m_preg.re_nsub && idx < m_matches.size())
+    {
+        match_str.assign (s + m_matches[idx].rm_so,
+                          m_matches[idx].rm_eo - m_matches[idx].rm_so);
+        return true;
+    }
+    return false;
+}
+
+
+//----------------------------------------------------------------------
+// Returns true if the regular expression compiled and is ready
+// for execution.
+//----------------------------------------------------------------------
+bool
+RegularExpression::IsValid () const
+{
+    return m_comp_err == 0;
+}
+
+//----------------------------------------------------------------------
+// Returns the text that was used to compile the current regular
+// expression.
+//----------------------------------------------------------------------
+const char*
+RegularExpression::GetText () const
+{
+    return m_re.c_str();
+}
+
+//----------------------------------------------------------------------
+// Free any contained compiled regular expressions.
+//----------------------------------------------------------------------
+void
+RegularExpression::Free()
+{
+    if (m_comp_err == 0)
+    {
+        m_re.clear();
+        regfree(&m_preg);
+        // Set a compile error since we no longer have a valid regex
+        m_comp_err = 1;
+    }
+}
diff --git a/source/Core/Scalar.cpp b/source/Core/Scalar.cpp
new file mode 100644
index 0000000..56590b8
--- /dev/null
+++ b/source/Core/Scalar.cpp
@@ -0,0 +1,2084 @@
+//===-- Scalar.cpp ----------------------------------------------*- 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/Scalar.h"
+
+#include <math.h>
+
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/DataExtractor.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Promote to max type currently follows the ANSI C rule for type
+// promotion in expressions.
+//----------------------------------------------------------------------
+static Scalar::Type
+PromoteToMaxType
+(
+    const Scalar& lhs,                  // The const left hand side object
+    const Scalar& rhs,                  // The const right hand side object
+    Scalar& temp_value,             // A modifiable temp value than can be used to hold either the promoted lhs or rhs object
+    const Scalar* &promoted_lhs_ptr,    // Pointer to the resulting possibly promoted value of lhs (at most one of lhs/rhs will get promoted)
+    const Scalar* &promoted_rhs_ptr // Pointer to the resulting possibly promoted value of rhs (at most one of lhs/rhs will get promoted)
+)
+{
+    Scalar result;
+    // Initialize the promoted values for both the right and left hand side values
+    // to be the objects themselves. If no promotion is needed (both right and left
+    // have the same type), then the temp_value will not get used.
+    promoted_lhs_ptr = &lhs;
+    promoted_rhs_ptr = &rhs;
+    // Extract the types of both the right and left hand side values
+    Scalar::Type lhs_type = lhs.GetType();
+    Scalar::Type rhs_type = rhs.GetType();
+
+    if (lhs_type > rhs_type)
+    {
+        // Right hand side need to be promoted
+        temp_value = rhs;                   // Copy right hand side into the temp value
+        if (temp_value.Promote(lhs_type))   // Promote it
+            promoted_rhs_ptr = &temp_value; // Update the pointer for the promoted right hand side
+    }
+    else if (lhs_type < rhs_type)
+    {
+        // Left hand side need to be promoted
+        temp_value = lhs;                   // Copy left hand side value into the temp value
+        if (temp_value.Promote(rhs_type))   // Promote it
+            promoted_lhs_ptr = &temp_value; // Update the pointer for the promoted left hand side
+    }
+
+    // Make sure our type promotion worked as exptected
+    if (promoted_lhs_ptr->GetType() == promoted_rhs_ptr->GetType())
+        return promoted_lhs_ptr->GetType(); // Return the resulting max type
+
+    // Return the void type (zero) if we fail to promote either of the values.
+    return Scalar::e_void;
+}
+
+
+//----------------------------------------------------------------------
+// Scalar constructor
+//----------------------------------------------------------------------
+Scalar::Scalar() :
+    m_type(e_void),
+    m_data()
+{
+}
+
+//----------------------------------------------------------------------
+// Scalar copy constructor
+//----------------------------------------------------------------------
+Scalar::Scalar(const Scalar& rhs) :
+    m_type(rhs.m_type),
+    m_data(rhs.m_data)  // TODO: verify that for C++ this will correctly copy the union??
+{
+}
+
+//Scalar::Scalar(const RegisterValue& reg) :
+//  m_type(e_void),
+//  m_data()
+//{
+//  switch (reg.info.encoding)
+//  {
+//  case eEncodingUint:     // unsigned integer
+//      switch (reg.info.byte_size)
+//      {
+//      case 1: m_type = e_uint; m_data.uint = reg.value.uint8; break;
+//      case 2: m_type = e_uint; m_data.uint = reg.value.uint16; break;
+//      case 4: m_type = e_uint; m_data.uint = reg.value.uint32; break;
+//      case 8: m_type = e_ulonglong; m_data.ulonglong = reg.value.uint64; break;
+//      break;
+//      }
+//      break;
+//
+//  case eEncodingSint:     // signed integer
+//      switch (reg.info.byte_size)
+//      {
+//      case 1: m_type = e_sint; m_data.sint = reg.value.sint8; break;
+//      case 2: m_type = e_sint; m_data.sint = reg.value.sint16; break;
+//      case 4: m_type = e_sint; m_data.sint = reg.value.sint32; break;
+//      case 8: m_type = e_slonglong; m_data.slonglong = reg.value.sint64; break;
+//      break;
+//      }
+//      break;
+//
+//  case eEncodingIEEE754:  // float
+//      switch (reg.info.byte_size)
+//      {
+//      case 4: m_type = e_float; m_data.flt = reg.value.float32; break;
+//      case 8: m_type = e_double; m_data.dbl = reg.value.float64; break;
+//      break;
+//      }
+//      break;
+//    case eEncodingVector: // vector registers
+//      break;
+//  }
+//}
+
+bool
+Scalar::GetData (DataExtractor &data, size_t limit_byte_size) const
+{
+    size_t byte_size = GetByteSize();
+    if (byte_size > 0)
+    {
+        if (limit_byte_size < byte_size)
+        {
+            if (eByteOrderHost == eByteOrderLittle)
+            {
+                // On little endian systems if we want fewer bytes from the
+                // current type we just specify fewer bytes since the LSByte
+                // is first...
+                data.SetData((uint8_t*)&m_data, limit_byte_size, eByteOrderHost);
+            }
+            else if (eByteOrderHost == eByteOrderBig)
+            {
+                // On big endian systems if we want fewer bytes from the
+                // current type have to advance our initial byte pointer and
+                // trim down the number of bytes since the MSByte is first
+                data.SetData(((uint8_t*)&m_data) + byte_size - limit_byte_size, limit_byte_size, eByteOrderHost);
+            }
+        }
+        else
+        {
+            // We want all of the data
+            data.SetData((uint8_t*)&m_data, byte_size, eByteOrderHost);
+        }
+        return true;
+    }
+    data.Clear();
+    return false;
+}
+
+size_t
+Scalar::GetByteSize() const
+{
+    switch (m_type)
+    {
+    default:
+    case e_void:
+        break;
+    case e_sint:        return sizeof(m_data.sint);
+    case e_uint:        return sizeof(m_data.uint);
+    case e_slong:       return sizeof(m_data.slong);
+    case e_ulong:       return sizeof(m_data.ulong);
+    case e_slonglong:   return sizeof(m_data.slonglong);
+    case e_ulonglong:   return sizeof(m_data.ulonglong);
+    case e_float:       return sizeof(m_data.flt);
+    case e_double:      return sizeof(m_data.dbl);
+    case e_long_double: return sizeof(m_data.ldbl);
+    }
+    return 0;
+}
+
+bool
+Scalar::IsZero() const
+{
+    switch (m_type)
+    {
+    default:
+    case e_void:
+        break;
+    case e_sint:        return m_data.sint == 0;
+    case e_uint:        return m_data.uint == 0;
+    case e_slong:       return m_data.slong == 0;
+    case e_ulong:       return m_data.ulong == 0;
+    case e_slonglong:   return m_data.slonglong == 0;
+    case e_ulonglong:   return m_data.ulonglong == 0;
+    case e_float:       return m_data.flt == 0.0f;
+    case e_double:      return m_data.dbl == 0.0;
+    case e_long_double: return m_data.ldbl == 0.0;
+    }
+    return false;
+}
+
+void
+Scalar::GetValue (Stream *s, bool show_type) const
+{
+    if (show_type)
+        s->Printf("(%s) ", GetTypeAsCString());
+
+    switch (m_type)
+    {
+    case e_void:
+    default:
+        break;
+    case e_sint:        s->Printf("%i", m_data.sint);               break;
+    case e_uint:        s->Printf("0x%8.8x", m_data.uint);          break;
+    case e_slong:       s->Printf("%li", m_data.slong);             break;
+    case e_ulong:       s->Printf("0x%8.8lx", m_data.ulong);        break;
+    case e_slonglong:   s->Printf("%lli", m_data.slonglong);        break;
+    case e_ulonglong:   s->Printf("0x%16.16llx", m_data.ulonglong); break;
+    case e_float:       s->Printf("%f", m_data.flt);                break;
+    case e_double:      s->Printf("%g", m_data.dbl);                break;
+    case e_long_double: s->Printf("%Lg", m_data.ldbl);              break;
+    }
+}
+
+const char *
+Scalar::GetTypeAsCString() const
+{
+    switch (m_type)
+    {
+    default:
+        break;
+    case e_void:        return "void";
+    case e_sint:        return "int";
+    case e_uint:        return "unsigned int";
+    case e_slong:       return "long";
+    case e_ulong:       return "unsigned long";
+    case e_slonglong:   return "long long";
+    case e_ulonglong:   return "unsigned long long";
+    case e_float:       return "float";
+    case e_double:      return "double";
+    case e_long_double: return "long double";
+    }
+    return "<invalid Scalar type>";
+}
+
+
+
+//----------------------------------------------------------------------
+// Scalar copy constructor
+//----------------------------------------------------------------------
+Scalar&
+Scalar::operator=(const Scalar& rhs)
+{
+    if (this != &rhs)
+    {
+        m_type = rhs.m_type;
+        ::memcpy (&m_data, &rhs.m_data, sizeof(m_data));
+    }
+    return *this;
+}
+
+Scalar&
+Scalar::operator= (const int v)
+{
+    m_type = e_sint;
+    m_data.sint = v;
+    return *this;
+}
+
+
+Scalar&
+Scalar::operator= (unsigned int v)
+{
+    m_type = e_uint;
+    m_data.uint = v;
+    return *this;
+}
+
+Scalar&
+Scalar::operator= (long v)
+{
+    m_type = e_slong;
+    m_data.slong = v;
+    return *this;
+}
+
+Scalar&
+Scalar::operator= (unsigned long v)
+{
+    m_type = e_ulong;
+    m_data.ulong = v;
+    return *this;
+}
+
+Scalar&
+Scalar::operator= (long long v)
+{
+    m_type = e_slonglong;
+    m_data.slonglong = v;
+    return *this;
+}
+
+Scalar&
+Scalar::operator= (unsigned long long v)
+{
+    m_type = e_ulonglong;
+    m_data.ulonglong = v;
+    return *this;
+}
+
+Scalar&
+Scalar::operator= (float v)
+{
+    m_type = e_float;
+    m_data.flt = v;
+    return *this;
+}
+
+Scalar&
+Scalar::operator= (double v)
+{
+    m_type = e_double;
+    m_data.dbl = v;
+    return *this;
+}
+
+Scalar&
+Scalar::operator= (long double v)
+{
+    m_type = e_long_double;
+    m_data.ldbl = v;
+    return *this;
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+Scalar::~Scalar()
+{
+}
+
+bool
+Scalar::Promote(Scalar::Type type)
+{
+    bool success = false;
+    switch (m_type)
+    {
+    case e_void:
+        break;
+
+    case e_sint:
+        switch (type)
+        {
+        default:
+        case e_void:        break;
+        case e_sint:        success = true; break;
+        case e_uint:        m_data.uint         = m_data.sint;      success = true; break;
+        case e_slong:       m_data.slong        = m_data.sint;      success = true; break;
+        case e_ulong:       m_data.ulong        = m_data.sint;      success = true; break;
+        case e_slonglong:   m_data.slonglong    = m_data.sint;      success = true; break;
+        case e_ulonglong:   m_data.ulonglong    = m_data.sint;      success = true; break;
+        case e_float:       m_data.flt          = m_data.sint;      success = true; break;
+        case e_double:      m_data.dbl          = m_data.sint;      success = true; break;
+        case e_long_double: m_data.ldbl         = m_data.sint;      success = true; break;
+        }
+        break;
+
+    case e_uint:
+        switch (type)
+        {
+        default:
+        case e_void:
+        case e_sint:        break;
+        case e_uint:        success = true; break;
+        case e_slong:       m_data.slong        = m_data.uint;      success = true; break;
+        case e_ulong:       m_data.ulong        = m_data.uint;      success = true; break;
+        case e_slonglong:   m_data.slonglong    = m_data.uint;      success = true; break;
+        case e_ulonglong:   m_data.ulonglong    = m_data.uint;      success = true; break;
+        case e_float:       m_data.flt          = m_data.uint;      success = true; break;
+        case e_double:      m_data.dbl          = m_data.uint;      success = true; break;
+        case e_long_double: m_data.ldbl         = m_data.uint;      success = true; break;
+        }
+        break;
+
+    case e_slong:
+        switch (type)
+        {
+        default:
+        case e_void:
+        case e_sint:
+        case e_uint:        break;
+        case e_slong:       success = true; break;
+        case e_ulong:       m_data.ulong        = m_data.slong;     success = true; break;
+        case e_slonglong:   m_data.slonglong    = m_data.slong;     success = true; break;
+        case e_ulonglong:   m_data.ulonglong    = m_data.slong;     success = true; break;
+        case e_float:       m_data.flt          = m_data.slong;     success = true; break;
+        case e_double:      m_data.dbl          = m_data.slong;     success = true; break;
+        case e_long_double: m_data.ldbl         = m_data.slong;     success = true; break;
+        }
+        break;
+
+    case e_ulong:
+        switch (type)
+        {
+        default:
+        case e_void:
+        case e_sint:
+        case e_uint:
+        case e_slong:       break;
+        case e_ulong:       success = true; break;
+        case e_slonglong:   m_data.slonglong    = m_data.ulong;     success = true; break;
+        case e_ulonglong:   m_data.ulonglong    = m_data.ulong;     success = true; break;
+        case e_float:       m_data.flt          = m_data.ulong;     success = true; break;
+        case e_double:      m_data.dbl          = m_data.ulong;     success = true; break;
+        case e_long_double: m_data.ldbl         = m_data.ulong;     success = true; break;
+        }
+        break;
+
+    case e_slonglong:
+        switch (type)
+        {
+        default:
+        case e_void:
+        case e_sint:
+        case e_uint:
+        case e_slong:
+        case e_ulong:       break;
+        case e_slonglong:   success = true; break;
+        case e_ulonglong:   m_data.ulonglong    = m_data.slonglong;     success = true; break;
+        case e_float:       m_data.flt          = m_data.slonglong;     success = true; break;
+        case e_double:      m_data.dbl          = m_data.slonglong;     success = true; break;
+        case e_long_double: m_data.ldbl         = m_data.slonglong;     success = true; break;
+        }
+        break;
+
+    case e_ulonglong:
+        switch (type)
+        {
+        default:
+        case e_void:
+        case e_sint:
+        case e_uint:
+        case e_slong:
+        case e_ulong:
+        case e_slonglong:   break;
+        case e_ulonglong:   success = true; break;
+        case e_float:       m_data.flt          = m_data.ulonglong;     success = true; break;
+        case e_double:      m_data.dbl          = m_data.ulonglong;     success = true; break;
+        case e_long_double: m_data.ldbl         = m_data.ulonglong;     success = true; break;
+        }
+        break;
+
+    case e_float:
+        switch (type)
+        {
+        default:
+        case e_void:
+        case e_sint:
+        case e_uint:
+        case e_slong:
+        case e_ulong:
+        case e_slonglong:
+        case e_ulonglong:   break;
+        case e_float:       success = true; break;
+        case e_double:      m_data.dbl          = m_data.flt;           success = true; break;
+        case e_long_double: m_data.ldbl         = m_data.ulonglong;     success = true; break;
+        }
+        break;
+
+    case e_double:
+        switch (type)
+        {
+        default:
+        case e_void:
+        case e_sint:
+        case e_uint:
+        case e_slong:
+        case e_ulong:
+        case e_slonglong:
+        case e_ulonglong:
+        case e_float:       break;
+        case e_double:      success = true; break;
+        case e_long_double: m_data.ldbl         = m_data.dbl;       success = true; break;
+        }
+        break;
+
+    case e_long_double:
+        switch (type)
+        {
+        default:
+        case e_void:
+        case e_sint:
+        case e_uint:
+        case e_slong:
+        case e_ulong:
+        case e_slonglong:
+        case e_ulonglong:
+        case e_float:
+        case e_double:      break;
+        case e_long_double: success = true; break;
+        }
+        break;
+    }
+
+    if (success)
+        m_type = type;
+    return success;
+}
+
+const char *
+Scalar::GetValueTypeAsCString (Scalar::Type type)
+{
+    switch (type)
+    {
+    default:            break;
+    case e_void:        return "void";
+    case e_sint:        return "int";
+    case e_uint:        return "unsigned int";
+    case e_slong:       return "long";
+    case e_ulong:       return "unsigned long";
+    case e_slonglong:   return "long long";
+    case e_ulonglong:   return "unsigned long long";
+    case e_float:       return "float";
+    case e_double:      return "double";
+    case e_long_double: return "long double";
+    }
+    return "???";
+}
+
+
+Scalar::Type
+Scalar::GetValueTypeForSignedIntegerWithByteSize (size_t byte_size)
+{
+    if (byte_size <= sizeof(int))
+        return e_sint;
+    if (byte_size <= sizeof(long))
+        return e_slong;
+    if (byte_size <= sizeof(long long))
+        return e_slonglong;
+    return e_void;
+}
+
+Scalar::Type
+Scalar::GetValueTypeForUnsignedIntegerWithByteSize (size_t byte_size)
+{
+    if (byte_size <= sizeof(unsigned int))
+        return e_uint;
+    if (byte_size <= sizeof(unsigned long))
+        return e_ulong;
+    if (byte_size <= sizeof(unsigned long long))
+        return e_ulonglong;
+    return e_void;
+}
+
+Scalar::Type
+Scalar::GetValueTypeForFloatWithByteSize (size_t byte_size)
+{
+    if (byte_size == sizeof(float))
+        return e_float;
+    if (byte_size == sizeof(double))
+        return e_double;
+    if (byte_size == sizeof(long double))
+        return e_long_double;
+    return e_void;
+}
+
+bool
+Scalar::Cast(Scalar::Type type)
+{
+    bool success = false;
+    switch (m_type)
+    {
+    case e_void:
+        break;
+
+    case e_sint:
+        switch (type)
+        {
+        default:
+        case e_void:        break;
+        case e_sint:        success = true; break;
+        case e_uint:        m_data.uint         = m_data.sint;      success = true; break;
+        case e_slong:       m_data.slong        = m_data.sint;      success = true; break;
+        case e_ulong:       m_data.ulong        = m_data.sint;      success = true; break;
+        case e_slonglong:   m_data.slonglong    = m_data.sint;      success = true; break;
+        case e_ulonglong:   m_data.ulonglong    = m_data.sint;      success = true; break;
+        case e_float:       m_data.flt          = m_data.sint;      success = true; break;
+        case e_double:      m_data.dbl          = m_data.sint;      success = true; break;
+        case e_long_double: m_data.ldbl         = m_data.sint;      success = true; break;
+        }
+        break;
+
+    case e_uint:
+        switch (type)
+        {
+        default:
+        case e_void:
+        case e_sint:        m_data.sint         = m_data.uint;      success = true; break;
+        case e_uint:        success = true; break;
+        case e_slong:       m_data.slong        = m_data.uint;      success = true; break;
+        case e_ulong:       m_data.ulong        = m_data.uint;      success = true; break;
+        case e_slonglong:   m_data.slonglong    = m_data.uint;      success = true; break;
+        case e_ulonglong:   m_data.ulonglong    = m_data.uint;      success = true; break;
+        case e_float:       m_data.flt          = m_data.uint;      success = true; break;
+        case e_double:      m_data.dbl          = m_data.uint;      success = true; break;
+        case e_long_double: m_data.ldbl         = m_data.uint;      success = true; break;
+        }
+        break;
+
+    case e_slong:
+        switch (type)
+        {
+        default:
+        case e_void:
+        case e_sint:        m_data.sint         = m_data.slong;     success = true; break;
+        case e_uint:        m_data.uint         = m_data.slong;     success = true; break;
+        case e_slong:       success = true; break;
+        case e_ulong:       m_data.ulong        = m_data.slong;     success = true; break;
+        case e_slonglong:   m_data.slonglong    = m_data.slong;     success = true; break;
+        case e_ulonglong:   m_data.ulonglong    = m_data.slong;     success = true; break;
+        case e_float:       m_data.flt          = m_data.slong;     success = true; break;
+        case e_double:      m_data.dbl          = m_data.slong;     success = true; break;
+        case e_long_double: m_data.ldbl         = m_data.slong;     success = true; break;
+        }
+        break;
+
+    case e_ulong:
+        switch (type)
+        {
+        default:
+        case e_void:
+        case e_sint:        m_data.sint         = m_data.ulong;     success = true; break;
+        case e_uint:        m_data.uint         = m_data.ulong;     success = true; break;
+        case e_slong:       m_data.slong        = m_data.ulong;     success = true; break;
+        case e_ulong:       success = true; break;
+        case e_slonglong:   m_data.slonglong    = m_data.ulong;     success = true; break;
+        case e_ulonglong:   m_data.ulonglong    = m_data.ulong;     success = true; break;
+        case e_float:       m_data.flt          = m_data.ulong;     success = true; break;
+        case e_double:      m_data.dbl          = m_data.ulong;     success = true; break;
+        case e_long_double: m_data.ldbl         = m_data.ulong;     success = true; break;
+        }
+        break;
+
+    case e_slonglong:
+        switch (type)
+        {
+        default:
+        case e_void:
+        case e_sint:        m_data.sint         = m_data.slonglong;     success = true; break;
+        case e_uint:        m_data.uint         = m_data.slonglong;     success = true; break;
+        case e_slong:       m_data.slong        = m_data.slonglong;     success = true; break;
+        case e_ulong:       m_data.ulong        = m_data.slonglong;     success = true; break;
+        case e_slonglong:   success = true; break;
+        case e_ulonglong:   m_data.ulonglong    = m_data.slonglong;     success = true; break;
+        case e_float:       m_data.flt          = m_data.slonglong;     success = true; break;
+        case e_double:      m_data.dbl          = m_data.slonglong;     success = true; break;
+        case e_long_double: m_data.ldbl         = m_data.slonglong;     success = true; break;
+        }
+        break;
+
+    case e_ulonglong:
+        switch (type)
+        {
+        default:
+        case e_void:
+        case e_sint:        m_data.sint         = m_data.ulonglong;     success = true; break;
+        case e_uint:        m_data.uint         = m_data.ulonglong;     success = true; break;
+        case e_slong:       m_data.slong        = m_data.ulonglong;     success = true; break;
+        case e_ulong:       m_data.ulong        = m_data.ulonglong;     success = true; break;
+        case e_slonglong:   m_data.slonglong    = m_data.ulonglong;     success = true; break;
+        case e_ulonglong:   success = true; break;
+        case e_float:       m_data.flt          = m_data.ulonglong;     success = true; break;
+        case e_double:      m_data.dbl          = m_data.ulonglong;     success = true; break;
+        case e_long_double: m_data.ldbl         = m_data.ulonglong;     success = true; break;
+        }
+        break;
+
+    case e_float:
+        switch (type)
+        {
+        default:
+        case e_void:
+        case e_sint:        m_data.sint         = m_data.flt;       success = true; break;
+        case e_uint:        m_data.uint         = m_data.flt;       success = true; break;
+        case e_slong:       m_data.slong        = m_data.flt;       success = true; break;
+        case e_ulong:       m_data.ulong        = m_data.flt;       success = true; break;
+        case e_slonglong:   m_data.slonglong    = m_data.flt;       success = true; break;
+        case e_ulonglong:   m_data.ulonglong    = m_data.flt;       success = true; break;
+        case e_float:       success = true; break;
+        case e_double:      m_data.dbl          = m_data.flt;       success = true; break;
+        case e_long_double: m_data.ldbl         = m_data.flt;       success = true; break;
+        }
+        break;
+
+    case e_double:
+        switch (type)
+        {
+        default:
+        case e_void:
+        case e_sint:        m_data.sint         = m_data.dbl;       success = true; break;
+        case e_uint:        m_data.uint         = m_data.dbl;       success = true; break;
+        case e_slong:       m_data.slong        = m_data.dbl;       success = true; break;
+        case e_ulong:       m_data.ulong        = m_data.dbl;       success = true; break;
+        case e_slonglong:   m_data.slonglong    = m_data.dbl;       success = true; break;
+        case e_ulonglong:   m_data.ulonglong    = m_data.dbl;       success = true; break;
+        case e_float:       m_data.flt          = m_data.dbl;       success = true; break;
+        case e_double:      success = true; break;
+        case e_long_double: m_data.ldbl         = m_data.dbl;       success = true; break;
+        }
+        break;
+
+    case e_long_double:
+        switch (type)
+        {
+        default:
+        case e_void:
+        case e_sint:        m_data.sint         = m_data.ldbl;      success = true; break;
+        case e_uint:        m_data.uint         = m_data.ldbl;      success = true; break;
+        case e_slong:       m_data.slong        = m_data.ldbl;      success = true; break;
+        case e_ulong:       m_data.ulong        = m_data.ldbl;      success = true; break;
+        case e_slonglong:   m_data.slonglong    = m_data.ldbl;      success = true; break;
+        case e_ulonglong:   m_data.ulonglong    = m_data.ldbl;      success = true; break;
+        case e_float:       m_data.flt          = m_data.ldbl;      success = true; break;
+        case e_double:      m_data.dbl          = m_data.ldbl;      success = true; break;
+        case e_long_double: success = true; break;
+        }
+        break;
+    }
+
+    if (success)
+        m_type = type;
+    return success;
+}
+
+int
+Scalar::SInt(int fail_value) const
+{
+    switch (m_type)
+    {
+    default:
+    case e_void:        break;
+    case e_sint:        return m_data.sint;
+    case e_uint:        return (int)m_data.uint;
+    case e_slong:       return (int)m_data.slong;
+    case e_ulong:       return (int)m_data.ulong;
+    case e_slonglong:   return (int)m_data.slonglong;
+    case e_ulonglong:   return (int)m_data.ulonglong;
+    case e_float:       return (int)m_data.flt;
+    case e_double:      return (int)m_data.dbl;
+    case e_long_double: return (int)m_data.ldbl;
+    }
+    return fail_value;
+}
+
+unsigned int
+Scalar::UInt(unsigned int fail_value) const
+{
+    switch (m_type)
+    {
+    default:
+    case e_void:        break;
+    case e_sint:        return (unsigned int)m_data.sint;
+    case e_uint:        return (unsigned int)m_data.uint;
+    case e_slong:       return (unsigned int)m_data.slong;
+    case e_ulong:       return (unsigned int)m_data.ulong;
+    case e_slonglong:   return (unsigned int)m_data.slonglong;
+    case e_ulonglong:   return (unsigned int)m_data.ulonglong;
+    case e_float:       return (unsigned int)m_data.flt;
+    case e_double:      return (unsigned int)m_data.dbl;
+    case e_long_double: return (unsigned int)m_data.ldbl;
+    }
+    return fail_value;
+}
+
+
+long
+Scalar::SLong(long fail_value) const
+{
+    switch (m_type)
+    {
+    default:
+    case e_void:        break;
+    case e_sint:        return (long)m_data.sint;
+    case e_uint:        return (long)m_data.uint;
+    case e_slong:       return (long)m_data.slong;
+    case e_ulong:       return (long)m_data.ulong;
+    case e_slonglong:   return (long)m_data.slonglong;
+    case e_ulonglong:   return (long)m_data.ulonglong;
+    case e_float:       return (long)m_data.flt;
+    case e_double:      return (long)m_data.dbl;
+    case e_long_double: return (long)m_data.ldbl;
+    }
+    return fail_value;
+}
+
+
+
+unsigned long
+Scalar::ULong(unsigned long fail_value) const
+{
+    switch (m_type)
+    {
+    default:
+    case e_void:        break;
+    case e_sint:        return (unsigned long)m_data.sint;
+    case e_uint:        return (unsigned long)m_data.uint;
+    case e_slong:       return (unsigned long)m_data.slong;
+    case e_ulong:       return (unsigned long)m_data.ulong;
+    case e_slonglong:   return (unsigned long)m_data.slonglong;
+    case e_ulonglong:   return (unsigned long)m_data.ulonglong;
+    case e_float:       return (unsigned long)m_data.flt;
+    case e_double:      return (unsigned long)m_data.dbl;
+    case e_long_double: return (unsigned long)m_data.ldbl;
+    }
+    return fail_value;
+}
+
+uint64_t
+Scalar::GetRawBits64(uint64_t fail_value) const
+{
+    switch (m_type)
+    {
+    default:
+    case e_void:
+        break;
+
+    case e_sint:
+    case e_uint:
+        return m_data.uint;
+
+    case e_slong:
+    case e_ulong:
+        return m_data.ulong;
+
+    case e_slonglong:
+    case e_ulonglong:
+        return m_data.ulonglong;
+
+    case e_float:
+        if (sizeof(m_data.flt) == sizeof(int))
+            return m_data.uint;
+        else if (sizeof(m_data.flt) == sizeof(unsigned long))
+            return m_data.ulong;
+        else if (sizeof(m_data.flt) == sizeof(unsigned long long))
+            return m_data.ulonglong;
+        break;
+
+    case e_double:
+        if (sizeof(m_data.dbl) == sizeof(int))
+            return m_data.uint;
+        else if (sizeof(m_data.dbl) == sizeof(unsigned long))
+            return m_data.ulong;
+        else if (sizeof(m_data.dbl) == sizeof(unsigned long long))
+            return m_data.ulonglong;
+        break;
+
+    case e_long_double:
+        if (sizeof(m_data.ldbl) == sizeof(int))
+            return m_data.uint;
+        else if (sizeof(m_data.ldbl) == sizeof(unsigned long))
+            return m_data.ulong;
+        else if (sizeof(m_data.ldbl) == sizeof(unsigned long long))
+            return m_data.ulonglong;
+        break;
+    }
+    return fail_value;
+}
+
+
+
+long long
+Scalar::SLongLong(long long fail_value) const
+{
+    switch (m_type)
+    {
+    default:
+    case e_void:        break;
+    case e_sint:        return (long long)m_data.sint;
+    case e_uint:        return (long long)m_data.uint;
+    case e_slong:       return (long long)m_data.slong;
+    case e_ulong:       return (long long)m_data.ulong;
+    case e_slonglong:   return (long long)m_data.slonglong;
+    case e_ulonglong:   return (long long)m_data.ulonglong;
+    case e_float:       return (long long)m_data.flt;
+    case e_double:      return (long long)m_data.dbl;
+    case e_long_double: return (long long)m_data.ldbl;
+    }
+    return fail_value;
+}
+
+
+unsigned long long
+Scalar::ULongLong(unsigned long long fail_value) const
+{
+    switch (m_type)
+    {
+    default:
+    case e_void:        break;
+    case e_sint:        return (unsigned long long)m_data.sint;
+    case e_uint:        return (unsigned long long)m_data.uint;
+    case e_slong:       return (unsigned long long)m_data.slong;
+    case e_ulong:       return (unsigned long long)m_data.ulong;
+    case e_slonglong:   return (unsigned long long)m_data.slonglong;
+    case e_ulonglong:   return (unsigned long long)m_data.ulonglong;
+    case e_float:       return (unsigned long long)m_data.flt;
+    case e_double:      return (unsigned long long)m_data.dbl;
+    case e_long_double: return (unsigned long long)m_data.ldbl;
+    }
+    return fail_value;
+}
+
+
+float
+Scalar::Float(float fail_value) const
+{
+    switch (m_type)
+    {
+    default:
+    case e_void:        break;
+    case e_sint:        return (float)m_data.sint;
+    case e_uint:        return (float)m_data.uint;
+    case e_slong:       return (float)m_data.slong;
+    case e_ulong:       return (float)m_data.ulong;
+    case e_slonglong:   return (float)m_data.slonglong;
+    case e_ulonglong:   return (float)m_data.ulonglong;
+    case e_float:       return (float)m_data.flt;
+    case e_double:      return (float)m_data.dbl;
+    case e_long_double: return (float)m_data.ldbl;
+    }
+    return fail_value;
+}
+
+
+double
+Scalar::Double(double fail_value) const
+{
+    switch (m_type)
+    {
+    default:
+    case e_void:        break;
+    case e_sint:        return (double)m_data.sint;
+    case e_uint:        return (double)m_data.uint;
+    case e_slong:       return (double)m_data.slong;
+    case e_ulong:       return (double)m_data.ulong;
+    case e_slonglong:   return (double)m_data.slonglong;
+    case e_ulonglong:   return (double)m_data.ulonglong;
+    case e_float:       return (double)m_data.flt;
+    case e_double:      return (double)m_data.dbl;
+    case e_long_double: return (double)m_data.ldbl;
+    }
+    return fail_value;
+}
+
+
+long double
+Scalar::LongDouble(long double fail_value) const
+{
+    switch (m_type)
+    {
+    default:
+    case e_void:        break;
+    case e_sint:        return (long double)m_data.sint;
+    case e_uint:        return (long double)m_data.uint;
+    case e_slong:       return (long double)m_data.slong;
+    case e_ulong:       return (long double)m_data.ulong;
+    case e_slonglong:   return (long double)m_data.slonglong;
+    case e_ulonglong:   return (long double)m_data.ulonglong;
+    case e_float:       return (long double)m_data.flt;
+    case e_double:      return (long double)m_data.dbl;
+    case e_long_double: return (long double)m_data.ldbl;
+    }
+    return fail_value;
+}
+
+
+Scalar&
+Scalar::operator+= (const Scalar& rhs)
+{
+    Scalar temp_value;
+    const Scalar* a;
+    const Scalar* b;
+    if ((m_type = PromoteToMaxType(*this, rhs, temp_value, a, b)) != Scalar::e_void)
+    {
+        switch (m_type)
+        {
+        default:
+        case e_void:        break;
+        case e_sint:        m_data.sint         = a->m_data.sint        + b->m_data.sint;       break;
+        case e_uint:        m_data.uint         = a->m_data.uint        + b->m_data.uint;       break;
+        case e_slong:       m_data.slong        = a->m_data.slong       + b->m_data.slong;      break;
+        case e_ulong:       m_data.ulong        = a->m_data.ulong       + b->m_data.ulong;      break;
+        case e_slonglong:   m_data.slonglong    = a->m_data.slonglong   + b->m_data.slonglong;  break;
+        case e_ulonglong:   m_data.ulonglong    = a->m_data.ulonglong   + b->m_data.ulonglong;  break;
+        case e_float:       m_data.flt          = a->m_data.flt         + b->m_data.flt;        break;
+        case e_double:      m_data.dbl          = a->m_data.dbl         + b->m_data.dbl;        break;
+        case e_long_double: m_data.ldbl         = a->m_data.ldbl        + b->m_data.ldbl;       break;
+        }
+    }
+    return *this;
+}
+
+Scalar&
+Scalar::operator<<= (const Scalar& rhs)
+{
+    switch (m_type)
+    {
+    default:
+    case e_void:
+    case e_float:
+    case e_double:
+    case e_long_double:
+        m_type = e_void;
+        break;
+
+    case e_sint:
+        switch (rhs.m_type)
+        {
+        default:
+        case e_void:
+        case e_float:
+        case e_double:
+        case e_long_double:
+            m_type = e_void;
+            break;
+        case e_sint:            m_data.sint <<= rhs.m_data.sint;        break;
+        case e_uint:            m_data.sint <<= rhs.m_data.uint;        break;
+        case e_slong:           m_data.sint <<= rhs.m_data.slong;       break;
+        case e_ulong:           m_data.sint <<= rhs.m_data.ulong;       break;
+        case e_slonglong:       m_data.sint <<= rhs.m_data.slonglong;   break;
+        case e_ulonglong:       m_data.sint <<= rhs.m_data.ulonglong;   break;
+        }
+        break;
+
+    case e_uint:
+        switch (rhs.m_type)
+        {
+        default:
+        case e_void:
+        case e_float:
+        case e_double:
+        case e_long_double:
+            m_type = e_void;
+            break;
+        case e_sint:            m_data.uint <<= rhs.m_data.sint;        break;
+        case e_uint:            m_data.uint <<= rhs.m_data.uint;        break;
+        case e_slong:           m_data.uint <<= rhs.m_data.slong;       break;
+        case e_ulong:           m_data.uint <<= rhs.m_data.ulong;       break;
+        case e_slonglong:       m_data.uint <<= rhs.m_data.slonglong;   break;
+        case e_ulonglong:       m_data.uint <<= rhs.m_data.ulonglong;   break;
+        }
+        break;
+
+    case e_slong:
+        switch (rhs.m_type)
+        {
+        default:
+        case e_void:
+        case e_float:
+        case e_double:
+        case e_long_double:
+            m_type = e_void;
+            break;
+        case e_sint:            m_data.slong <<= rhs.m_data.sint;       break;
+        case e_uint:            m_data.slong <<= rhs.m_data.uint;       break;
+        case e_slong:           m_data.slong <<= rhs.m_data.slong;      break;
+        case e_ulong:           m_data.slong <<= rhs.m_data.ulong;      break;
+        case e_slonglong:       m_data.slong <<= rhs.m_data.slonglong;  break;
+        case e_ulonglong:       m_data.slong <<= rhs.m_data.ulonglong;  break;
+        }
+        break;
+
+    case e_ulong:
+        switch (rhs.m_type)
+        {
+        default:
+        case e_void:
+        case e_float:
+        case e_double:
+        case e_long_double:
+            m_type = e_void;
+            break;
+        case e_sint:            m_data.ulong <<= rhs.m_data.sint;       break;
+        case e_uint:            m_data.ulong <<= rhs.m_data.uint;       break;
+        case e_slong:           m_data.ulong <<= rhs.m_data.slong;      break;
+        case e_ulong:           m_data.ulong <<= rhs.m_data.ulong;      break;
+        case e_slonglong:       m_data.ulong <<= rhs.m_data.slonglong;  break;
+        case e_ulonglong:       m_data.ulong <<= rhs.m_data.ulonglong;  break;
+        }
+        break;
+    case e_slonglong:
+        switch (rhs.m_type)
+        {
+        default:
+        case e_void:
+        case e_float:
+        case e_double:
+        case e_long_double:
+            m_type = e_void;
+            break;
+        case e_sint:            m_data.slonglong <<= rhs.m_data.sint;       break;
+        case e_uint:            m_data.slonglong <<= rhs.m_data.uint;       break;
+        case e_slong:           m_data.slonglong <<= rhs.m_data.slong;      break;
+        case e_ulong:           m_data.slonglong <<= rhs.m_data.ulong;      break;
+        case e_slonglong:       m_data.slonglong <<= rhs.m_data.slonglong;  break;
+        case e_ulonglong:       m_data.slonglong <<= rhs.m_data.ulonglong;  break;
+        }
+        break;
+
+    case e_ulonglong:
+        switch (rhs.m_type)
+        {
+        default:
+        case e_void:
+        case e_float:
+        case e_double:
+        case e_long_double:
+            m_type = e_void;
+            break;
+        case e_sint:            m_data.ulonglong <<= rhs.m_data.sint;       break;
+        case e_uint:            m_data.ulonglong <<= rhs.m_data.uint;       break;
+        case e_slong:           m_data.ulonglong <<= rhs.m_data.slong;      break;
+        case e_ulong:           m_data.ulonglong <<= rhs.m_data.ulong;      break;
+        case e_slonglong:       m_data.ulonglong <<= rhs.m_data.slonglong;  break;
+        case e_ulonglong:       m_data.ulonglong <<= rhs.m_data.ulonglong;  break;
+        }
+        break;
+    }
+    return *this;
+}
+
+bool
+Scalar::ShiftRightLogical(const Scalar& rhs)
+{
+    switch (m_type)
+    {
+    default:
+    case e_void:
+    case e_float:
+    case e_double:
+    case e_long_double:
+        m_type = e_void;
+        break;
+
+    case e_sint:
+    case e_uint:
+        switch (rhs.m_type)
+        {
+        default:
+        case e_void:
+        case e_float:
+        case e_double:
+        case e_long_double:
+            m_type = e_void;
+            break;
+        case e_sint:            m_data.uint >>= rhs.m_data.sint;        break;
+        case e_uint:            m_data.uint >>= rhs.m_data.uint;        break;
+        case e_slong:           m_data.uint >>= rhs.m_data.slong;       break;
+        case e_ulong:           m_data.uint >>= rhs.m_data.ulong;       break;
+        case e_slonglong:       m_data.uint >>= rhs.m_data.slonglong;   break;
+        case e_ulonglong:       m_data.uint >>= rhs.m_data.ulonglong;   break;
+        }
+        break;
+
+    case e_slong:
+    case e_ulong:
+        switch (rhs.m_type)
+        {
+        default:
+        case e_void:
+        case e_float:
+        case e_double:
+        case e_long_double:
+            m_type = e_void;
+            break;
+        case e_sint:            m_data.ulong >>= rhs.m_data.sint;       break;
+        case e_uint:            m_data.ulong >>= rhs.m_data.uint;       break;
+        case e_slong:           m_data.ulong >>= rhs.m_data.slong;      break;
+        case e_ulong:           m_data.ulong >>= rhs.m_data.ulong;      break;
+        case e_slonglong:       m_data.ulong >>= rhs.m_data.slonglong;  break;
+        case e_ulonglong:       m_data.ulong >>= rhs.m_data.ulonglong;  break;
+        }
+        break;
+
+    case e_slonglong:
+    case e_ulonglong:
+        switch (rhs.m_type)
+        {
+        default:
+        case e_void:
+        case e_float:
+        case e_double:
+        case e_long_double:
+            m_type = e_void;
+            break;
+        case e_sint:            m_data.ulonglong >>= rhs.m_data.sint;       break;
+        case e_uint:            m_data.ulonglong >>= rhs.m_data.uint;       break;
+        case e_slong:           m_data.ulonglong >>= rhs.m_data.slong;      break;
+        case e_ulong:           m_data.ulonglong >>= rhs.m_data.ulong;      break;
+        case e_slonglong:       m_data.ulonglong >>= rhs.m_data.slonglong;  break;
+        case e_ulonglong:       m_data.ulonglong >>= rhs.m_data.ulonglong;  break;
+        }
+        break;
+    }
+    return m_type != e_void;
+}
+
+
+Scalar&
+Scalar::operator>>= (const Scalar& rhs)
+{
+    switch (m_type)
+    {
+    default:
+    case e_void:
+    case e_float:
+    case e_double:
+    case e_long_double:
+        m_type = e_void;
+        break;
+
+    case e_sint:
+        switch (rhs.m_type)
+        {
+        default:
+        case e_void:
+        case e_float:
+        case e_double:
+        case e_long_double:
+            m_type = e_void;
+            break;
+        case e_sint:            m_data.sint >>= rhs.m_data.sint;        break;
+        case e_uint:            m_data.sint >>= rhs.m_data.uint;        break;
+        case e_slong:           m_data.sint >>= rhs.m_data.slong;       break;
+        case e_ulong:           m_data.sint >>= rhs.m_data.ulong;       break;
+        case e_slonglong:       m_data.sint >>= rhs.m_data.slonglong;   break;
+        case e_ulonglong:       m_data.sint >>= rhs.m_data.ulonglong;   break;
+        }
+        break;
+
+    case e_uint:
+        switch (rhs.m_type)
+        {
+        default:
+        case e_void:
+        case e_float:
+        case e_double:
+        case e_long_double:
+            m_type = e_void;
+            break;
+        case e_sint:            m_data.uint >>= rhs.m_data.sint;        break;
+        case e_uint:            m_data.uint >>= rhs.m_data.uint;        break;
+        case e_slong:           m_data.uint >>= rhs.m_data.slong;       break;
+        case e_ulong:           m_data.uint >>= rhs.m_data.ulong;       break;
+        case e_slonglong:       m_data.uint >>= rhs.m_data.slonglong;   break;
+        case e_ulonglong:       m_data.uint >>= rhs.m_data.ulonglong;   break;
+        }
+        break;
+
+    case e_slong:
+        switch (rhs.m_type)
+        {
+        default:
+        case e_void:
+        case e_float:
+        case e_double:
+        case e_long_double:
+            m_type = e_void;
+            break;
+        case e_sint:            m_data.slong >>= rhs.m_data.sint;       break;
+        case e_uint:            m_data.slong >>= rhs.m_data.uint;       break;
+        case e_slong:           m_data.slong >>= rhs.m_data.slong;      break;
+        case e_ulong:           m_data.slong >>= rhs.m_data.ulong;      break;
+        case e_slonglong:       m_data.slong >>= rhs.m_data.slonglong;  break;
+        case e_ulonglong:       m_data.slong >>= rhs.m_data.ulonglong;  break;
+        }
+        break;
+
+    case e_ulong:
+        switch (rhs.m_type)
+        {
+        default:
+        case e_void:
+        case e_float:
+        case e_double:
+        case e_long_double:
+            m_type = e_void;
+            break;
+        case e_sint:            m_data.ulong >>= rhs.m_data.sint;       break;
+        case e_uint:            m_data.ulong >>= rhs.m_data.uint;       break;
+        case e_slong:           m_data.ulong >>= rhs.m_data.slong;      break;
+        case e_ulong:           m_data.ulong >>= rhs.m_data.ulong;      break;
+        case e_slonglong:       m_data.ulong >>= rhs.m_data.slonglong;  break;
+        case e_ulonglong:       m_data.ulong >>= rhs.m_data.ulonglong;  break;
+        }
+        break;
+    case e_slonglong:
+        switch (rhs.m_type)
+        {
+        default:
+        case e_void:
+        case e_float:
+        case e_double:
+        case e_long_double:
+            m_type = e_void;
+            break;
+        case e_sint:            m_data.slonglong >>= rhs.m_data.sint;       break;
+        case e_uint:            m_data.slonglong >>= rhs.m_data.uint;       break;
+        case e_slong:           m_data.slonglong >>= rhs.m_data.slong;      break;
+        case e_ulong:           m_data.slonglong >>= rhs.m_data.ulong;      break;
+        case e_slonglong:       m_data.slonglong >>= rhs.m_data.slonglong;  break;
+        case e_ulonglong:       m_data.slonglong >>= rhs.m_data.ulonglong;  break;
+        }
+        break;
+
+    case e_ulonglong:
+        switch (rhs.m_type)
+        {
+        default:
+        case e_void:
+        case e_float:
+        case e_double:
+        case e_long_double:
+            m_type = e_void;
+            break;
+        case e_sint:            m_data.ulonglong >>= rhs.m_data.sint;       break;
+        case e_uint:            m_data.ulonglong >>= rhs.m_data.uint;       break;
+        case e_slong:           m_data.ulonglong >>= rhs.m_data.slong;      break;
+        case e_ulong:           m_data.ulonglong >>= rhs.m_data.ulong;      break;
+        case e_slonglong:       m_data.ulonglong >>= rhs.m_data.slonglong;  break;
+        case e_ulonglong:       m_data.ulonglong >>= rhs.m_data.ulonglong;  break;
+        }
+        break;
+    }
+    return *this;
+}
+
+
+Scalar&
+Scalar::operator&= (const Scalar& rhs)
+{
+    switch (m_type)
+    {
+    default:
+    case e_void:
+    case e_float:
+    case e_double:
+    case e_long_double:
+        m_type = e_void;
+        break;
+
+    case e_sint:
+        switch (rhs.m_type)
+        {
+        default:
+        case e_void:
+        case e_float:
+        case e_double:
+        case e_long_double:
+            m_type = e_void;
+            break;
+        case e_sint:            m_data.sint &= rhs.m_data.sint;         break;
+        case e_uint:            m_data.sint &= rhs.m_data.uint;         break;
+        case e_slong:           m_data.sint &= rhs.m_data.slong;        break;
+        case e_ulong:           m_data.sint &= rhs.m_data.ulong;        break;
+        case e_slonglong:       m_data.sint &= rhs.m_data.slonglong;    break;
+        case e_ulonglong:       m_data.sint &= rhs.m_data.ulonglong;    break;
+        }
+        break;
+
+    case e_uint:
+        switch (rhs.m_type)
+        {
+        default:
+        case e_void:
+        case e_float:
+        case e_double:
+        case e_long_double:
+            m_type = e_void;
+            break;
+        case e_sint:            m_data.uint &= rhs.m_data.sint;         break;
+        case e_uint:            m_data.uint &= rhs.m_data.uint;         break;
+        case e_slong:           m_data.uint &= rhs.m_data.slong;        break;
+        case e_ulong:           m_data.uint &= rhs.m_data.ulong;        break;
+        case e_slonglong:       m_data.uint &= rhs.m_data.slonglong;    break;
+        case e_ulonglong:       m_data.uint &= rhs.m_data.ulonglong;    break;
+        }
+        break;
+
+    case e_slong:
+        switch (rhs.m_type)
+        {
+        default:
+        case e_void:
+        case e_float:
+        case e_double:
+        case e_long_double:
+            m_type = e_void;
+            break;
+        case e_sint:            m_data.slong &= rhs.m_data.sint;        break;
+        case e_uint:            m_data.slong &= rhs.m_data.uint;        break;
+        case e_slong:           m_data.slong &= rhs.m_data.slong;       break;
+        case e_ulong:           m_data.slong &= rhs.m_data.ulong;       break;
+        case e_slonglong:       m_data.slong &= rhs.m_data.slonglong;   break;
+        case e_ulonglong:       m_data.slong &= rhs.m_data.ulonglong;   break;
+        }
+        break;
+
+    case e_ulong:
+        switch (rhs.m_type)
+        {
+        default:
+        case e_void:
+        case e_float:
+        case e_double:
+        case e_long_double:
+            m_type = e_void;
+            break;
+        case e_sint:            m_data.ulong &= rhs.m_data.sint;        break;
+        case e_uint:            m_data.ulong &= rhs.m_data.uint;        break;
+        case e_slong:           m_data.ulong &= rhs.m_data.slong;       break;
+        case e_ulong:           m_data.ulong &= rhs.m_data.ulong;       break;
+        case e_slonglong:       m_data.ulong &= rhs.m_data.slonglong;   break;
+        case e_ulonglong:       m_data.ulong &= rhs.m_data.ulonglong;   break;
+        }
+        break;
+    case e_slonglong:
+        switch (rhs.m_type)
+        {
+        default:
+        case e_void:
+        case e_float:
+        case e_double:
+        case e_long_double:
+            m_type = e_void;
+            break;
+        case e_sint:            m_data.slonglong &= rhs.m_data.sint;        break;
+        case e_uint:            m_data.slonglong &= rhs.m_data.uint;        break;
+        case e_slong:           m_data.slonglong &= rhs.m_data.slong;       break;
+        case e_ulong:           m_data.slonglong &= rhs.m_data.ulong;       break;
+        case e_slonglong:       m_data.slonglong &= rhs.m_data.slonglong;   break;
+        case e_ulonglong:       m_data.slonglong &= rhs.m_data.ulonglong;   break;
+        }
+        break;
+
+    case e_ulonglong:
+        switch (rhs.m_type)
+        {
+        default:
+        case e_void:
+        case e_float:
+        case e_double:
+        case e_long_double:
+            m_type = e_void;
+            break;
+        case e_sint:            m_data.ulonglong &= rhs.m_data.sint;        break;
+        case e_uint:            m_data.ulonglong &= rhs.m_data.uint;        break;
+        case e_slong:           m_data.ulonglong &= rhs.m_data.slong;       break;
+        case e_ulong:           m_data.ulonglong &= rhs.m_data.ulong;       break;
+        case e_slonglong:       m_data.ulonglong &= rhs.m_data.slonglong;   break;
+        case e_ulonglong:       m_data.ulonglong &= rhs.m_data.ulonglong;   break;
+        }
+        break;
+    }
+    return *this;
+}
+
+
+
+bool
+Scalar::AbsoluteValue()
+{
+    switch (m_type)
+    {
+    default:
+    case e_void:
+        break;
+
+    case e_sint:
+        if (m_data.sint < 0)
+            m_data.sint = -m_data.sint;
+        return true;
+
+    case e_slong:
+        if (m_data.slong < 0)
+            m_data.slong = -m_data.slong;
+        return true;
+
+    case e_slonglong:
+        if (m_data.slonglong < 0)
+            m_data.slonglong = -m_data.slonglong;
+        return true;
+
+    case e_uint:
+    case e_ulong:
+    case e_ulonglong:   return true;
+    case e_float:       m_data.flt = fabsf(m_data.flt);     return true;
+    case e_double:      m_data.dbl = fabs(m_data.dbl);      return true;
+    case e_long_double: m_data.ldbl = fabsl(m_data.ldbl);   return true;
+    }
+    return false;
+}
+
+
+bool
+Scalar::UnaryNegate()
+{
+    switch (m_type)
+    {
+    default:
+    case e_void:        break;
+    case e_sint:        m_data.sint = -m_data.sint;             return true;
+    case e_uint:        m_data.uint = -m_data.uint;             return true;
+    case e_slong:       m_data.slong = -m_data.slong;           return true;
+    case e_ulong:       m_data.ulong = -m_data.ulong;           return true;
+    case e_slonglong:   m_data.slonglong = -m_data.slonglong;   return true;
+    case e_ulonglong:   m_data.ulonglong = -m_data.ulonglong;   return true;
+    case e_float:       m_data.flt = -m_data.flt;               return true;
+    case e_double:      m_data.dbl = -m_data.dbl;               return true;
+    case e_long_double: m_data.ldbl = -m_data.ldbl;             return true;
+    }
+    return false;
+}
+
+bool
+Scalar::OnesComplement()
+{
+    switch (m_type)
+    {
+    case e_sint:        m_data.sint = ~m_data.sint; return true;
+    case e_uint:        m_data.uint = ~m_data.uint; return true;
+    case e_slong:       m_data.slong = ~m_data.slong; return true;
+    case e_ulong:       m_data.ulong = ~m_data.ulong; return true;
+    case e_slonglong:   m_data.slonglong = ~m_data.slonglong; return true;
+    case e_ulonglong:   m_data.ulonglong = ~m_data.ulonglong; return true;
+
+    default:
+    case e_void:
+    case e_float:
+    case e_double:
+    case e_long_double:
+        break;
+    }
+    return false;
+}
+
+
+const Scalar
+lldb_private::operator+ (const Scalar& lhs, const Scalar& rhs)
+{
+    Scalar result;
+    Scalar temp_value;
+    const Scalar* a;
+    const Scalar* b;
+    if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != Scalar::e_void)
+    {
+        switch (result.m_type)
+        {
+        default:
+        case Scalar::e_void:            break;
+        case Scalar::e_sint:            result.m_data.sint      = a->m_data.sint        + b->m_data.sint;       break;
+        case Scalar::e_uint:            result.m_data.uint      = a->m_data.uint        + b->m_data.uint;       break;
+        case Scalar::e_slong:           result.m_data.slong     = a->m_data.slong       + b->m_data.slong;      break;
+        case Scalar::e_ulong:           result.m_data.ulong     = a->m_data.ulong       + b->m_data.ulong;      break;
+        case Scalar::e_slonglong:       result.m_data.slonglong = a->m_data.slonglong   + b->m_data.slonglong;  break;
+        case Scalar::e_ulonglong:       result.m_data.ulonglong = a->m_data.ulonglong   + b->m_data.ulonglong;  break;
+        case Scalar::e_float:           result.m_data.flt       = a->m_data.flt         + b->m_data.flt;        break;
+        case Scalar::e_double:      result.m_data.dbl       = a->m_data.dbl         + b->m_data.dbl;        break;
+        case Scalar::e_long_double: result.m_data.ldbl      = a->m_data.ldbl        + b->m_data.ldbl;       break;
+        }
+    }
+    return result;
+}
+
+
+const Scalar
+lldb_private::operator- (const Scalar& lhs, const Scalar& rhs)
+{
+    Scalar result;
+    Scalar temp_value;
+    const Scalar* a;
+    const Scalar* b;
+    if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != Scalar::e_void)
+    {
+        switch (result.m_type)
+        {
+        default:
+        case Scalar::e_void:            break;
+        case Scalar::e_sint:            result.m_data.sint      = a->m_data.sint        - b->m_data.sint;       break;
+        case Scalar::e_uint:            result.m_data.uint      = a->m_data.uint        - b->m_data.uint;       break;
+        case Scalar::e_slong:           result.m_data.slong     = a->m_data.slong       - b->m_data.slong;      break;
+        case Scalar::e_ulong:           result.m_data.ulong     = a->m_data.ulong       - b->m_data.ulong;      break;
+        case Scalar::e_slonglong:       result.m_data.slonglong = a->m_data.slonglong   - b->m_data.slonglong;  break;
+        case Scalar::e_ulonglong:       result.m_data.ulonglong = a->m_data.ulonglong   - b->m_data.ulonglong;  break;
+        case Scalar::e_float:           result.m_data.flt       = a->m_data.flt         - b->m_data.flt;        break;
+        case Scalar::e_double:      result.m_data.dbl       = a->m_data.dbl         - b->m_data.dbl;        break;
+        case Scalar::e_long_double: result.m_data.ldbl      = a->m_data.ldbl        - b->m_data.ldbl;       break;
+        }
+    }
+    return result;
+}
+
+const Scalar
+lldb_private::operator/ (const Scalar& lhs, const Scalar& rhs)
+{
+    Scalar result;
+    Scalar temp_value;
+    const Scalar* a;
+    const Scalar* b;
+    if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != Scalar::e_void)
+    {
+        switch (result.m_type)
+        {
+        default:
+        case Scalar::e_void:            break;
+
+        case Scalar::e_sint:            if (b->m_data.sint != 0)        { result.m_data.sint = a->m_data.sint/ b->m_data.sint; return result; } break;
+        case Scalar::e_uint:            if (b->m_data.uint != 0)        { result.m_data.uint = a->m_data.uint / b->m_data.uint; return result; } break;
+        case Scalar::e_slong:           if (b->m_data.slong != 0)       { result.m_data.slong = a->m_data.slong / b->m_data.slong; return result; } break;
+        case Scalar::e_ulong:           if (b->m_data.ulong != 0)       { result.m_data.ulong = a->m_data.ulong / b->m_data.ulong; return result; } break;
+        case Scalar::e_slonglong:       if (b->m_data.slonglong != 0)   { result.m_data.slonglong = a->m_data.slonglong / b->m_data.slonglong; return result; } break;
+        case Scalar::e_ulonglong:       if (b->m_data.ulonglong != 0)   { result.m_data.ulonglong = a->m_data.ulonglong / b->m_data.ulonglong; return result; } break;
+        case Scalar::e_float:           if (b->m_data.flt != 0.0f)      { result.m_data.flt = a->m_data.flt / b->m_data.flt; return result; } break;
+        case Scalar::e_double:      if (b->m_data.dbl != 0.0)       { result.m_data.dbl = a->m_data.dbl / b->m_data.dbl; return result; } break;
+        case Scalar::e_long_double: if (b->m_data.ldbl != 0.0)      { result.m_data.ldbl = a->m_data.ldbl / b->m_data.ldbl; return result; } break;
+        }
+    }
+    // For division only, the only way it should make it here is if a promotion failed,
+    // or if we are trying to do a divide by zero.
+    result.m_type = Scalar::e_void;
+    return result;
+}
+
+const Scalar
+lldb_private::operator* (const Scalar& lhs, const Scalar& rhs)
+{
+    Scalar result;
+    Scalar temp_value;
+    const Scalar* a;
+    const Scalar* b;
+    if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != Scalar::e_void)
+    {
+        switch (result.m_type)
+        {
+        default:
+        case Scalar::e_void:            break;
+        case Scalar::e_sint:            result.m_data.sint      = a->m_data.sint        * b->m_data.sint;       break;
+        case Scalar::e_uint:            result.m_data.uint      = a->m_data.uint        * b->m_data.uint;       break;
+        case Scalar::e_slong:           result.m_data.slong     = a->m_data.slong       * b->m_data.slong;      break;
+        case Scalar::e_ulong:           result.m_data.ulong     = a->m_data.ulong       * b->m_data.ulong;      break;
+        case Scalar::e_slonglong:       result.m_data.slonglong = a->m_data.slonglong   * b->m_data.slonglong;  break;
+        case Scalar::e_ulonglong:       result.m_data.ulonglong = a->m_data.ulonglong   * b->m_data.ulonglong;  break;
+        case Scalar::e_float:           result.m_data.flt       = a->m_data.flt         * b->m_data.flt;        break;
+        case Scalar::e_double:      result.m_data.dbl       = a->m_data.dbl         * b->m_data.dbl;        break;
+        case Scalar::e_long_double: result.m_data.ldbl      = a->m_data.ldbl        * b->m_data.ldbl;       break;
+        }
+    }
+    return result;
+}
+
+const Scalar
+lldb_private::operator& (const Scalar& lhs, const Scalar& rhs)
+{
+    Scalar result;
+    Scalar temp_value;
+    const Scalar* a;
+    const Scalar* b;
+    if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != Scalar::e_void)
+    {
+        switch (result.m_type)
+        {
+        case Scalar::e_sint:        result.m_data.sint      = a->m_data.sint        & b->m_data.sint;       break;
+        case Scalar::e_uint:        result.m_data.uint      = a->m_data.uint        & b->m_data.uint;       break;
+        case Scalar::e_slong:       result.m_data.slong     = a->m_data.slong       & b->m_data.slong;      break;
+        case Scalar::e_ulong:       result.m_data.ulong     = a->m_data.ulong       & b->m_data.ulong;      break;
+        case Scalar::e_slonglong:   result.m_data.slonglong = a->m_data.slonglong   & b->m_data.slonglong;  break;
+        case Scalar::e_ulonglong:   result.m_data.ulonglong = a->m_data.ulonglong   & b->m_data.ulonglong;  break;
+
+        default:
+        case Scalar::e_void:
+        case Scalar::e_float:
+        case Scalar::e_double:
+        case Scalar::e_long_double:
+            // No bitwise AND on floats, doubles of long doubles
+            result.m_type = Scalar::e_void;
+            break;
+        }
+    }
+    return result;
+}
+
+const Scalar
+lldb_private::operator| (const Scalar& lhs, const Scalar& rhs)
+{
+    Scalar result;
+    Scalar temp_value;
+    const Scalar* a;
+    const Scalar* b;
+    if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != Scalar::e_void)
+    {
+        switch (result.m_type)
+        {
+        case Scalar::e_sint:        result.m_data.sint      = a->m_data.sint        | b->m_data.sint;       break;
+        case Scalar::e_uint:        result.m_data.uint      = a->m_data.uint        | b->m_data.uint;       break;
+        case Scalar::e_slong:       result.m_data.slong     = a->m_data.slong       | b->m_data.slong;      break;
+        case Scalar::e_ulong:       result.m_data.ulong     = a->m_data.ulong       | b->m_data.ulong;      break;
+        case Scalar::e_slonglong:   result.m_data.slonglong = a->m_data.slonglong   | b->m_data.slonglong;  break;
+        case Scalar::e_ulonglong:   result.m_data.ulonglong = a->m_data.ulonglong   | b->m_data.ulonglong;  break;
+
+        default:
+        case Scalar::e_void:
+        case Scalar::e_float:
+        case Scalar::e_double:
+        case Scalar::e_long_double:
+            // No bitwise AND on floats, doubles of long doubles
+            result.m_type = Scalar::e_void;
+            break;
+        }
+    }
+    return result;
+}
+
+const Scalar
+lldb_private::operator% (const Scalar& lhs, const Scalar& rhs)
+{
+    Scalar result;
+    Scalar temp_value;
+    const Scalar* a;
+    const Scalar* b;
+    if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != Scalar::e_void)
+    {
+        switch (result.m_type)
+        {
+        case Scalar::e_sint:        result.m_data.sint      = a->m_data.sint        % b->m_data.sint;       break;
+        case Scalar::e_uint:        result.m_data.uint      = a->m_data.uint        % b->m_data.uint;       break;
+        case Scalar::e_slong:       result.m_data.slong     = a->m_data.slong       % b->m_data.slong;      break;
+        case Scalar::e_ulong:       result.m_data.ulong     = a->m_data.ulong       % b->m_data.ulong;      break;
+        case Scalar::e_slonglong:   result.m_data.slonglong = a->m_data.slonglong   % b->m_data.slonglong;  break;
+        case Scalar::e_ulonglong:   result.m_data.ulonglong = a->m_data.ulonglong   % b->m_data.ulonglong;  break;
+
+        default:
+        case Scalar::e_void:
+        case Scalar::e_float:
+        case Scalar::e_double:
+        case Scalar::e_long_double:
+            // No bitwise AND on floats, doubles of long doubles
+            result.m_type = Scalar::e_void;
+            break;
+        }
+    }
+    return result;
+}
+
+const Scalar
+lldb_private::operator^ (const Scalar& lhs, const Scalar& rhs)
+{
+    Scalar result;
+    Scalar temp_value;
+    const Scalar* a;
+    const Scalar* b;
+    if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != Scalar::e_void)
+    {
+        switch (result.m_type)
+        {
+        case Scalar::e_sint:        result.m_data.sint      = a->m_data.sint        ^ b->m_data.sint;       break;
+        case Scalar::e_uint:        result.m_data.uint      = a->m_data.uint        ^ b->m_data.uint;       break;
+        case Scalar::e_slong:       result.m_data.slong     = a->m_data.slong       ^ b->m_data.slong;      break;
+        case Scalar::e_ulong:       result.m_data.ulong     = a->m_data.ulong       ^ b->m_data.ulong;      break;
+        case Scalar::e_slonglong:   result.m_data.slonglong = a->m_data.slonglong   ^ b->m_data.slonglong;  break;
+        case Scalar::e_ulonglong:   result.m_data.ulonglong = a->m_data.ulonglong   ^ b->m_data.ulonglong;  break;
+
+        default:
+        case Scalar::e_void:
+        case Scalar::e_float:
+        case Scalar::e_double:
+        case Scalar::e_long_double:
+            // No bitwise AND on floats, doubles of long doubles
+            result.m_type = Scalar::e_void;
+            break;
+        }
+    }
+    return result;
+}
+
+// Return the raw unsigned integer without any casting or conversion
+unsigned int
+Scalar::RawUInt () const
+{
+    return m_data.uint;
+}
+
+// Return the raw unsigned long without any casting or conversion
+unsigned long
+Scalar::RawULong () const
+{
+    return m_data.ulong;
+}
+
+// Return the raw unsigned long long without any casting or conversion
+unsigned long long
+Scalar::RawULongLong () const
+{
+    return m_data.ulonglong;
+}
+
+
+Error
+Scalar::SetValueFromCString (const char *value_str, Encoding encoding, uint32_t byte_size)
+{
+    Error error;
+    if (value_str == NULL && value_str[0] == '\0')
+    {
+        error.SetErrorString ("Invalid c-string value string.");
+        return error;
+    }
+    bool success = false;
+    switch (encoding)
+    {
+    default:
+    case eEncodingInvalid:
+        error.SetErrorString ("Invalid encoding.");
+        break;
+
+    case eEncodingUint:
+        if (byte_size <= sizeof (unsigned long long))
+        {
+            uint64_t uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
+            if (!success)
+                error.SetErrorStringWithFormat ("'%s' is not a valid unsigned integer string value.\n", value_str);
+            else if (!UIntValueIsValidForSize (uval64, byte_size))
+                error.SetErrorStringWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, byte_size);
+            else
+            {
+                m_type = Scalar::GetValueTypeForUnsignedIntegerWithByteSize (byte_size);
+                switch (m_type)
+                {
+                case e_uint:        m_data.uint = uval64;       break;
+                case e_ulong:       m_data.ulong = uval64;      break;
+                case e_ulonglong:   m_data.ulonglong = uval64;  break;
+                default:
+                    error.SetErrorStringWithFormat ("Unsupported unsigned integer byte size: %u.\n", byte_size);
+                    break;
+                }
+            }
+        }
+        else
+        {
+            error.SetErrorStringWithFormat ("Unsupported unsigned integer byte size: %u.\n", byte_size);
+            return error;
+        }
+        break;
+
+    case eEncodingSint:
+        if (byte_size <= sizeof (long long))
+        {
+            uint64_t sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
+            if (!success)
+                error.SetErrorStringWithFormat ("'%s' is not a valid signed integer string value.\n", value_str);
+            else if (!SIntValueIsValidForSize (sval64, byte_size))
+                error.SetErrorStringWithFormat ("Value 0x%llx is too large to fit in a %u byte signed integer value.\n", sval64, byte_size);
+            else
+            {
+                m_type = Scalar::GetValueTypeForSignedIntegerWithByteSize (byte_size);
+                switch (m_type)
+                {
+                case e_sint:        m_data.sint = sval64;       break;
+                case e_slong:       m_data.slong = sval64;      break;
+                case e_slonglong:   m_data.slonglong = sval64;  break;
+                default:
+                    error.SetErrorStringWithFormat ("Unsupported signed integer byte size: %u.\n", byte_size);
+                    break;
+                }
+            }
+        }
+        else
+        {
+            error.SetErrorStringWithFormat ("Unsupported signed integer byte size: %u.\n", byte_size);
+            return error;
+        }
+        break;
+
+    case eEncodingIEEE754:
+        if (byte_size == sizeof (float))
+        {
+            if (::sscanf (value_str, "%f", &m_data.flt) == 1)
+                m_type = e_float;
+            else
+                error.SetErrorStringWithFormat ("'%s' is not a valid float string value.\n", value_str);
+        }
+        else if (byte_size == sizeof (double))
+        {
+            if (::sscanf (value_str, "%lf", &m_data.dbl) == 1)
+                m_type = e_double;
+            else
+                error.SetErrorStringWithFormat ("'%s' is not a valid float string value.\n", value_str);
+        }
+        else if (byte_size == sizeof (long double))
+        {
+            if (::sscanf (value_str, "%Lf", &m_data.ldbl) == 1)
+                m_type = e_long_double;
+            else
+                error.SetErrorStringWithFormat ("'%s' is not a valid float string value.\n", value_str);
+        }
+        else
+        {
+            error.SetErrorStringWithFormat ("Unsupported float byte size: %u.\n", byte_size);
+            return error;
+        }
+        break;
+
+    case eEncodingVector:
+        error.SetErrorString ("Vector encoding unsupported.");
+        break;
+    }
+    if (error.Fail())
+        m_type = e_void;
+
+    return error;
+}
+
+bool
+lldb_private::operator== (const Scalar& lhs, const Scalar& rhs)
+{
+    // If either entry is void then we can just compare the types
+    if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void)
+        return lhs.m_type == rhs.m_type;
+
+    Scalar temp_value;
+    const Scalar* a;
+    const Scalar* b;
+    switch (PromoteToMaxType(lhs, rhs, temp_value, a, b))
+    {
+    default:
+    case Scalar::e_void:            break;
+    case Scalar::e_sint:            return a->m_data.sint       == b->m_data.sint;
+    case Scalar::e_uint:            return a->m_data.uint       == b->m_data.uint;
+    case Scalar::e_slong:           return a->m_data.slong      == b->m_data.slong;
+    case Scalar::e_ulong:           return a->m_data.ulong      == b->m_data.ulong;
+    case Scalar::e_slonglong:       return a->m_data.slonglong  == b->m_data.slonglong;
+    case Scalar::e_ulonglong:       return a->m_data.ulonglong  == b->m_data.ulonglong;
+    case Scalar::e_float:           return a->m_data.flt        == b->m_data.flt;
+    case Scalar::e_double:      return a->m_data.dbl        == b->m_data.dbl;
+    case Scalar::e_long_double: return a->m_data.ldbl       == b->m_data.ldbl;
+    }
+    return false;
+}
+
+bool
+lldb_private::operator!= (const Scalar& lhs, const Scalar& rhs)
+{
+    // If either entry is void then we can just compare the types
+    if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void)
+        return lhs.m_type != rhs.m_type;
+
+    Scalar temp_value;  // A temp value that might get a copy of either promoted value
+    const Scalar* a;
+    const Scalar* b;
+    switch (PromoteToMaxType(lhs, rhs, temp_value, a, b))
+    {
+    default:
+    case Scalar::e_void:            break;
+    case Scalar::e_sint:            return a->m_data.sint       != b->m_data.sint;
+    case Scalar::e_uint:            return a->m_data.uint       != b->m_data.uint;
+    case Scalar::e_slong:           return a->m_data.slong      != b->m_data.slong;
+    case Scalar::e_ulong:           return a->m_data.ulong      != b->m_data.ulong;
+    case Scalar::e_slonglong:       return a->m_data.slonglong  != b->m_data.slonglong;
+    case Scalar::e_ulonglong:       return a->m_data.ulonglong  != b->m_data.ulonglong;
+    case Scalar::e_float:           return a->m_data.flt        != b->m_data.flt;
+    case Scalar::e_double:      return a->m_data.dbl        != b->m_data.dbl;
+    case Scalar::e_long_double: return a->m_data.ldbl       != b->m_data.ldbl;
+    }
+    return true;
+}
+
+bool
+lldb_private::operator< (const Scalar& lhs, const Scalar& rhs)
+{
+    if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void)
+        return false;
+
+    Scalar temp_value;
+    const Scalar* a;
+    const Scalar* b;
+    switch (PromoteToMaxType(lhs, rhs, temp_value, a, b))
+    {
+    default:
+    case Scalar::e_void:            break;
+    case Scalar::e_sint:            return a->m_data.sint       < b->m_data.sint;
+    case Scalar::e_uint:            return a->m_data.uint       < b->m_data.uint;
+    case Scalar::e_slong:           return a->m_data.slong      < b->m_data.slong;
+    case Scalar::e_ulong:           return a->m_data.ulong      < b->m_data.ulong;
+    case Scalar::e_slonglong:       return a->m_data.slonglong  < b->m_data.slonglong;
+    case Scalar::e_ulonglong:       return a->m_data.ulonglong  < b->m_data.ulonglong;
+    case Scalar::e_float:           return a->m_data.flt        < b->m_data.flt;
+    case Scalar::e_double:      return a->m_data.dbl        < b->m_data.dbl;
+    case Scalar::e_long_double: return a->m_data.ldbl       < b->m_data.ldbl;
+    }
+    return false;
+}
+
+bool
+lldb_private::operator<= (const Scalar& lhs, const Scalar& rhs)
+{
+    if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void)
+        return false;
+
+    Scalar temp_value;
+    const Scalar* a;
+    const Scalar* b;
+    switch (PromoteToMaxType(lhs, rhs, temp_value, a, b))
+    {
+    default:
+    case Scalar::e_void:            break;
+    case Scalar::e_sint:            return a->m_data.sint       <= b->m_data.sint;
+    case Scalar::e_uint:            return a->m_data.uint       <= b->m_data.uint;
+    case Scalar::e_slong:           return a->m_data.slong      <= b->m_data.slong;
+    case Scalar::e_ulong:           return a->m_data.ulong      <= b->m_data.ulong;
+    case Scalar::e_slonglong:       return a->m_data.slonglong  <= b->m_data.slonglong;
+    case Scalar::e_ulonglong:       return a->m_data.ulonglong  <= b->m_data.ulonglong;
+    case Scalar::e_float:           return a->m_data.flt        <= b->m_data.flt;
+    case Scalar::e_double:      return a->m_data.dbl        <= b->m_data.dbl;
+    case Scalar::e_long_double: return a->m_data.ldbl       <= b->m_data.ldbl;
+    }
+    return false;
+}
+
+
+bool
+lldb_private::operator> (const Scalar& lhs, const Scalar& rhs)
+{
+    if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void)
+        return false;
+
+    Scalar temp_value;
+    const Scalar* a;
+    const Scalar* b;
+    switch (PromoteToMaxType(lhs, rhs, temp_value, a, b))
+    {
+    default:
+    case Scalar::e_void:            break;
+    case Scalar::e_sint:            return a->m_data.sint       > b->m_data.sint;
+    case Scalar::e_uint:            return a->m_data.uint       > b->m_data.uint;
+    case Scalar::e_slong:           return a->m_data.slong      > b->m_data.slong;
+    case Scalar::e_ulong:           return a->m_data.ulong      > b->m_data.ulong;
+    case Scalar::e_slonglong:       return a->m_data.slonglong  > b->m_data.slonglong;
+    case Scalar::e_ulonglong:       return a->m_data.ulonglong  > b->m_data.ulonglong;
+    case Scalar::e_float:           return a->m_data.flt        > b->m_data.flt;
+    case Scalar::e_double:      return a->m_data.dbl        > b->m_data.dbl;
+    case Scalar::e_long_double: return a->m_data.ldbl       > b->m_data.ldbl;
+    }
+    return false;
+}
+
+bool
+lldb_private::operator>= (const Scalar& lhs, const Scalar& rhs)
+{
+    if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void)
+        return false;
+
+    Scalar temp_value;
+    const Scalar* a;
+    const Scalar* b;
+    switch (PromoteToMaxType(lhs, rhs, temp_value, a, b))
+    {
+    default:
+    case Scalar::e_void:            break;
+    case Scalar::e_sint:            return a->m_data.sint       >= b->m_data.sint;
+    case Scalar::e_uint:            return a->m_data.uint       >= b->m_data.uint;
+    case Scalar::e_slong:           return a->m_data.slong      >= b->m_data.slong;
+    case Scalar::e_ulong:           return a->m_data.ulong      >= b->m_data.ulong;
+    case Scalar::e_slonglong:       return a->m_data.slonglong  >= b->m_data.slonglong;
+    case Scalar::e_ulonglong:       return a->m_data.ulonglong  >= b->m_data.ulonglong;
+    case Scalar::e_float:           return a->m_data.flt        >= b->m_data.flt;
+    case Scalar::e_double:      return a->m_data.dbl        >= b->m_data.dbl;
+    case Scalar::e_long_double: return a->m_data.ldbl       >= b->m_data.ldbl;
+    }
+    return false;
+}
+
+
+
+
diff --git a/source/Core/SearchFilter.cpp b/source/Core/SearchFilter.cpp
new file mode 100644
index 0000000..4c54a91
--- /dev/null
+++ b/source/Core/SearchFilter.cpp
@@ -0,0 +1,435 @@
+//===-- SearchFilter.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
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/SearchFilter.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// SearchFilter constructor
+//----------------------------------------------------------------------
+Searcher::Searcher ()
+{
+
+}
+
+Searcher::~Searcher ()
+{
+
+}
+
+void
+Searcher::GetDescription (Stream *s)
+{
+}
+
+//----------------------------------------------------------------------
+// SearchFilter constructor
+//----------------------------------------------------------------------
+SearchFilter::SearchFilter(lldb::TargetSP &target_sp) :
+    m_target_sp (target_sp)
+{
+}
+
+//----------------------------------------------------------------------
+// SearchFilter copy constructor
+//----------------------------------------------------------------------
+SearchFilter::SearchFilter(const SearchFilter& rhs) :
+    m_target_sp (rhs.m_target_sp)
+{
+}
+
+//----------------------------------------------------------------------
+// SearchFilter assignment operator
+//----------------------------------------------------------------------
+const SearchFilter&
+SearchFilter::operator=(const SearchFilter& rhs)
+{
+    m_target_sp = rhs.m_target_sp;
+    return *this;
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+SearchFilter::~SearchFilter()
+{
+}
+
+bool
+SearchFilter::ModulePasses (const FileSpec &spec)
+{
+    return true;
+}
+
+bool
+SearchFilter::ModulePasses (const ModuleSP &module_sp)
+{
+    return true;
+}
+
+bool
+SearchFilter::SymbolContextPasses
+(
+    const SymbolContext &context,
+    lldb::SymbolContextItem scope
+)
+{
+    return true;
+}
+
+bool
+SearchFilter::AddressPasses (Address &address)
+{
+    return true;
+}
+
+bool
+SearchFilter::CompUnitPasses (FileSpec &fileSpec)
+{
+    return true;
+}
+
+bool
+SearchFilter::CompUnitPasses (CompileUnit &compUnit)
+{
+    return true;
+}
+
+void
+SearchFilter::GetDescription (Stream *s)
+{
+    s->PutCString("No Filter");
+}
+
+void
+SearchFilter::Dump (Stream *s) const
+{
+
+}
+
+//----------------------------------------------------------------------
+// UTILITY Functions to help iterate down through the elements of the
+// SymbolContext.
+//----------------------------------------------------------------------
+
+void
+SearchFilter::Search (Searcher &searcher)
+{
+    SymbolContext empty_sc;
+
+    if (m_target_sp == NULL)
+        return;
+    empty_sc.target_sp = m_target_sp;
+
+    if (searcher.GetDepth() == Searcher::eDepthTarget)
+        searcher.SearchCallback (*this, empty_sc, NULL, false);
+    else
+        DoModuleIteration(empty_sc, searcher);
+}
+
+void
+SearchFilter::SearchInModuleList (Searcher &searcher, ModuleList &modules)
+{
+    SymbolContext empty_sc;
+
+    if (m_target_sp == NULL)
+        return;
+    empty_sc.target_sp = m_target_sp;
+
+    if (searcher.GetDepth() == Searcher::eDepthTarget)
+        searcher.SearchCallback (*this, empty_sc, NULL, false);
+    else
+    {
+        size_t numModules = modules.GetSize();
+
+        for (int i = 0; i < numModules; i++)
+        {
+            ModuleSP module_sp(modules.GetModuleAtIndex(i));
+            if (ModulePasses(module_sp))
+            {
+                if (DoModuleIteration(module_sp, searcher) == Searcher::eCallbackReturnStop)
+                    return;
+            }
+        }
+    }
+}
+
+
+Searcher::CallbackReturn
+SearchFilter::DoModuleIteration (const lldb::ModuleSP& module_sp, Searcher &searcher)
+{
+    SymbolContext matchingContext (m_target_sp, module_sp);
+    return DoModuleIteration(matchingContext, searcher);
+}
+
+Searcher::CallbackReturn
+SearchFilter::DoModuleIteration (const SymbolContext &context, Searcher &searcher)
+{
+    Searcher::CallbackReturn shouldContinue;
+
+    if (searcher.GetDepth () >= Searcher::eDepthModule)
+    {
+        if (!context.module_sp)
+        {
+            size_t n_modules = m_target_sp->GetImages().GetSize();
+            for (int i = 0; i < n_modules; i++)
+            {
+                // If this is the last level supplied, then call the callback directly,
+                // otherwise descend.
+                ModuleSP module_sp(m_target_sp->GetImages().GetModuleAtIndex(i));
+                if (!ModulePasses (module_sp))
+                    continue;
+
+                if (searcher.GetDepth () == Searcher::eDepthModule)
+                {
+                    SymbolContext matchingContext(m_target_sp, module_sp);
+
+                    shouldContinue = searcher.SearchCallback (*this, matchingContext, NULL, false);
+                    if (shouldContinue == Searcher::eCallbackReturnStop
+                        || shouldContinue == Searcher::eCallbackReturnPop)
+                        return shouldContinue;
+                }
+                else
+                {
+                    shouldContinue = DoCUIteration(module_sp, context, searcher);
+                    if (shouldContinue == Searcher::eCallbackReturnStop)
+                        return shouldContinue;
+                    else if (shouldContinue == Searcher::eCallbackReturnPop)
+                        continue;
+                }
+            }
+        }
+        else
+        {
+            if (searcher.GetDepth () == Searcher::eDepthModule)
+            {
+                SymbolContext matchingContext(context.module_sp.get());
+
+                shouldContinue = searcher.SearchCallback (*this, matchingContext, NULL, false);
+            }
+            else
+            {
+                return DoCUIteration(context.module_sp, context, searcher);
+            }
+        }
+
+    }
+    return Searcher::eCallbackReturnContinue;
+}
+
+Searcher::CallbackReturn
+SearchFilter::DoCUIteration (const ModuleSP &module_sp, const SymbolContext &context, Searcher &searcher)
+{
+    Searcher::CallbackReturn shouldContinue;
+    if (context.comp_unit == NULL)
+    {
+        uint32_t num_comp_units = module_sp->GetNumCompileUnits();
+        for (uint32_t i = 0; i < num_comp_units; i++)
+        {
+            CompUnitSP cu_sp (module_sp->GetCompileUnitAtIndex (i));
+            if (!CompUnitPasses (*(cu_sp.get())))
+                continue;
+
+            if (searcher.GetDepth () == Searcher::eDepthCompUnit)
+            {
+                SymbolContext matchingContext(m_target_sp, module_sp, cu_sp.get());
+
+                shouldContinue = searcher.SearchCallback (*this, matchingContext, NULL, false);
+
+                if (shouldContinue == Searcher::eCallbackReturnPop)
+                    return Searcher::eCallbackReturnContinue;
+                else if (shouldContinue == Searcher::eCallbackReturnStop)
+                    return shouldContinue;
+            }
+            else
+            {
+                // FIXME Descend to block.
+            }
+
+        }
+    }
+    else
+    {
+        if (CompUnitPasses(*context.comp_unit))
+        {
+            SymbolContext matchingContext (m_target_sp, module_sp, context.comp_unit);
+            return searcher.SearchCallback (*this, matchingContext, NULL, false);
+        }
+    }
+    return Searcher::eCallbackReturnContinue;
+}
+
+Searcher::CallbackReturn
+SearchFilter::DoFunctionIteration (Function *function, const SymbolContext &context, Searcher &searcher)
+{
+    // FIXME: Implement...
+    return Searcher::eCallbackReturnContinue;
+}
+
+//----------------------------------------------------------------------
+//  SearchFilterByModule:
+//  Selects a shared library matching a given file spec
+//----------------------------------------------------------------------
+
+//----------------------------------------------------------------------
+// SearchFilterByModule constructors
+//----------------------------------------------------------------------
+
+SearchFilterByModule::SearchFilterByModule (lldb::TargetSP &target_sp, const FileSpec &module) :
+    SearchFilter (target_sp),
+    m_module_spec (module)
+{
+}
+
+
+//----------------------------------------------------------------------
+// SearchFilterByModule copy constructor
+//----------------------------------------------------------------------
+SearchFilterByModule::SearchFilterByModule(const SearchFilterByModule& rhs) :
+    SearchFilter (rhs),
+    m_module_spec (rhs.m_module_spec)
+{
+}
+
+//----------------------------------------------------------------------
+// SearchFilterByModule assignment operator
+//----------------------------------------------------------------------
+const SearchFilterByModule&
+SearchFilterByModule::operator=(const SearchFilterByModule& rhs)
+{
+    m_target_sp = rhs.m_target_sp;
+    m_module_spec = rhs.m_module_spec;
+    return *this;
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+SearchFilterByModule::~SearchFilterByModule()
+{
+}
+
+bool
+SearchFilterByModule::ModulePasses (const ModuleSP &module_sp)
+{
+    if (module_sp && FileSpec::Compare (module_sp->GetFileSpec(), m_module_spec, false) == 0)
+        return true;
+    else
+        return false;
+}
+
+bool
+SearchFilterByModule::ModulePasses (const FileSpec &spec)
+{
+    if (FileSpec::Compare(spec, m_module_spec, false) == 0)
+        return true;
+    else
+        return false;
+}
+
+bool
+SearchFilterByModule::SymbolContextPasses
+(
+ const SymbolContext &context,
+ lldb::SymbolContextItem scope
+ )
+{
+    if (!(scope & eSymbolContextModule))
+        return false;
+
+    if (context.module_sp && FileSpec::Compare (context.module_sp->GetFileSpec(), m_module_spec, false) == 0)
+        return true;
+    else
+        return false;
+}
+
+bool
+SearchFilterByModule::AddressPasses (Address &address)
+{
+    // FIXME: Not yet implemented
+    return true;
+}
+
+
+bool
+SearchFilterByModule::CompUnitPasses (FileSpec &fileSpec)
+{
+    return true;
+}
+
+bool
+SearchFilterByModule::CompUnitPasses (CompileUnit &compUnit)
+{
+    return true;
+}
+
+void
+SearchFilterByModule::Search (Searcher &searcher)
+{
+    if (!m_target_sp)
+        return;
+
+    if (searcher.GetDepth() == Searcher::eDepthTarget)
+    {
+        SymbolContext empty_sc;
+        empty_sc.target_sp = m_target_sp;
+        searcher.SearchCallback (*this, empty_sc, NULL, false);
+    }
+
+    // If the module file spec is a full path, then we can just find the one
+    // filespec that passes.  Otherwise, we need to go through all modules and
+    // find the ones that match the file name.
+
+    ModuleList matching_modules;
+    // const size_t num_matching_modules = m_target_sp->GetImages().FindModules(&m_module_spec, NULL, NULL, NULL, matching_modules);
+    for (int i = 0; i < m_target_sp->GetImages().GetSize (); i++)
+    {
+        Module* module = m_target_sp->GetImages().GetModulePointerAtIndex(i);
+        if (FileSpec::Compare (m_module_spec, module->GetFileSpec(), false) == 0)
+        {
+            SymbolContext matchingContext(m_target_sp, module->GetSP());
+            Searcher::CallbackReturn shouldContinue;
+
+            shouldContinue = DoModuleIteration(matchingContext, searcher);
+            if (shouldContinue == Searcher::eCallbackReturnStop)
+                return;
+        }
+    }
+}
+
+void
+SearchFilterByModule::GetDescription (Stream *s)
+{
+    s->PutCString("In module ");
+    if (s->GetVerbose())
+    {
+        char buffer[2048];
+        m_module_spec.GetPath(buffer, 2047);
+        s->PutCString(buffer);
+    }
+    else
+    {
+        s->PutCString(m_module_spec.GetFilename().AsCString("<unknown>"));
+    }
+}
+
+void
+SearchFilterByModule::Dump (Stream *s) const
+{
+
+}
diff --git a/source/Core/Section.cpp b/source/Core/Section.cpp
new file mode 100644
index 0000000..57c5199
--- /dev/null
+++ b/source/Core/Section.cpp
@@ -0,0 +1,791 @@
+//===-- Section.cpp ---------------------------------------------*- 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/Section.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+Section::Section
+(
+    Section *parent,
+    Module* module,
+    user_id_t sect_id,
+    const ConstString &name,
+    SectionType sect_type,
+    addr_t file_addr,
+    addr_t byte_size,
+    uint64_t file_offset,
+    uint64_t file_size,
+    uint32_t flags
+) :
+    ModuleChild     (module),
+    UserID          (sect_id),
+    Flags           (flags),
+    m_parent        (parent),
+    m_name          (name),
+    m_type          (sect_type),
+    m_file_addr     (file_addr),
+    m_byte_size     (byte_size),
+    m_file_offset   (file_offset),
+    m_file_size     (file_size),
+    m_children      (),
+    m_fake          (false),
+    m_linked_section(NULL),
+    m_linked_offset (0)
+{
+}
+
+//Section::Section
+//(
+//    Section *parent,
+//    Module* module,
+//    user_id_t sect_id,
+//    const ConstString &name,
+//    const AddressRange *file_vm_range,
+//    uint64_t file_offset,
+//    uint64_t file_size,
+//    uint32_t flags
+//) :
+//    ModuleChild     (module),
+//    UserID          (sect_id),
+//    Flags           (flags),
+//    m_parent        (parent),
+//    m_name          (name),
+//    m_range (),
+//    m_file_offset   (file_offset),
+//    m_file_size     (file_size),
+//    m_children      (),
+//    m_fake          (false)
+//{
+//    if (file_vm_range)
+//        m_range = *file_vm_range;
+//}
+
+Section::~Section()
+{
+}
+
+
+// Get a valid shared pointer to this section object
+SectionSP
+Section::GetSharedPointer() const
+{
+    SectionSP this_sp;
+    if (m_parent)
+        this_sp = m_parent->GetChildren().GetSharedPointer (this, false);
+    else
+    {
+        ObjectFile *objfile = m_module->GetObjectFile();
+        if (objfile)
+        {
+            SectionList *section_list = objfile->GetSectionList();
+            if (section_list)
+                this_sp = section_list->GetSharedPointer (this, false);
+        }
+    }
+    return this_sp;
+}
+
+
+
+ConstString&
+Section::GetName()
+{
+    if (m_linked_section)
+        return const_cast<Section *>(m_linked_section)->GetName();
+    return m_name;
+}
+
+const ConstString&
+Section::GetName() const
+{
+    if (m_linked_section)
+        return m_linked_section->GetName();
+    return m_name;
+}
+
+SectionList&
+Section::GetChildren()
+{
+    return m_children;
+}
+
+const SectionList&
+Section::GetChildren() const
+{
+    return m_children;
+}
+
+addr_t
+Section::GetFileAddress () const
+{
+    if (m_parent)
+    {
+        // This section has a parent which means m_file_addr is an offset into
+        // the parent section, so the file address for this section is the file
+        // address of the parent plus the offset
+        return m_parent->GetFileAddress() + m_file_addr;
+    }
+    // This section has no parent, so m_file_addr is the file base address
+    return m_file_addr;
+}
+
+addr_t
+Section::GetLinkedFileAddress () const
+{
+    if (m_linked_section)
+        return m_linked_section->GetFileAddress() + m_linked_offset;
+    return LLDB_INVALID_ADDRESS;
+}
+
+addr_t
+Section::GetOffset () const
+{
+    if (m_parent)
+    {
+        // This section has a parent which means m_file_addr is an offset.
+        return m_file_addr;
+    }
+
+    // This section has no parent, so there is no offset to be had
+    return 0;
+}
+
+addr_t
+Section::GetByteSize () const
+{
+    return m_byte_size;
+}
+
+void
+Section::SetByteSize (addr_t byte_size)
+{
+    m_byte_size = byte_size;
+}
+
+
+addr_t
+Section::GetLoadBaseAddress (Process *process) const
+{
+    addr_t load_base_addr = LLDB_INVALID_ADDRESS;
+    if (m_linked_section)
+    {
+        load_base_addr = m_linked_section->GetLoadBaseAddress(process) + m_linked_offset;
+    }
+    else
+    if (m_parent)
+    {
+        load_base_addr = m_parent->GetLoadBaseAddress (process);
+        if (load_base_addr != LLDB_INVALID_ADDRESS)
+            load_base_addr += GetOffset();
+    }
+    else
+    {
+        load_base_addr = process->GetSectionLoadAddress(this);
+    }
+
+    return load_base_addr;
+}
+
+bool
+Section::ResolveContainedAddress (addr_t offset, Address &so_addr) const
+{
+    const uint32_t num_children = m_children.GetSize();
+    if (num_children > 0)
+    {
+        for (uint32_t i=0; i<num_children; i++)
+        {
+            Section* child_section = m_children.GetSectionAtIndex (i).get();
+
+            addr_t child_offset = child_section->GetOffset();
+            if (child_offset <= offset && offset - child_offset < child_section->GetByteSize())
+                return child_section->ResolveContainedAddress (offset - child_offset, so_addr);
+        }
+    }
+    if (m_linked_section)
+    {
+        so_addr.SetOffset(m_linked_offset + offset);
+        so_addr.SetSection(m_linked_section);
+    }
+    else
+    {
+        so_addr.SetOffset(offset);
+        so_addr.SetSection(this);
+    }
+    return true;
+}
+
+uint64_t
+Section::GetFileOffset() const
+{
+    return m_file_offset;
+}
+
+uint64_t
+Section::GetFileSize() const
+{
+    return m_file_size;
+}
+
+bool
+Section::ContainsFileAddress (addr_t vm_addr) const
+{
+    const addr_t file_addr = GetFileAddress();
+    if (file_addr != LLDB_INVALID_ADDRESS)
+    {
+        if (file_addr <= vm_addr)
+        {
+            const addr_t offset = vm_addr - file_addr;
+            return offset < GetByteSize();
+        }
+    }
+    return false;
+}
+
+bool
+Section::ContainsLinkedFileAddress (addr_t vm_addr) const
+{
+    const addr_t linked_file_addr = GetLinkedFileAddress();
+    if (linked_file_addr != LLDB_INVALID_ADDRESS)
+    {
+        if (linked_file_addr <= vm_addr)
+        {
+            const addr_t offset = vm_addr - linked_file_addr;
+            return offset < GetByteSize();
+        }
+    }
+    return false;
+}
+
+int
+Section::Compare (const Section& a, const Section& b)
+{
+    if (&a == &b)
+        return 0;
+
+    const Module* a_module = a.GetModule();
+    const Module* b_module = b.GetModule();
+    if (a_module == b_module)
+    {
+        user_id_t a_sect_uid = a.GetID();
+        user_id_t b_sect_uid = b.GetID();
+        if (a_sect_uid < b_sect_uid)
+            return -1;
+        if (a_sect_uid > b_sect_uid)
+            return 1;
+        return 0;
+    }
+    else
+    {
+        // The modules are different, just compare the module pointers
+        if (a_module < b_module)
+            return -1;
+        else
+            return 1;   // We already know the modules aren't equal
+    }
+}
+
+
+void
+Section::Dump(Stream *s, Process *process) const
+{
+    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+    s->Indent();
+    s->Printf("0x%8.8x ", GetID());
+    bool resolved = true;
+    addr_t addr = LLDB_INVALID_ADDRESS;
+
+    if (GetByteSize() == 0)
+        s->Printf("%39s", "");
+    else
+    {
+        if (process)
+            addr = GetLoadBaseAddress (process);
+
+        if (addr == LLDB_INVALID_ADDRESS)
+        {
+            if (process)
+                resolved = false;
+            addr = GetFileAddress();
+        }
+
+        VMRange range(addr, addr + m_byte_size);
+        range.Dump (s, 0);
+    }
+
+    s->Printf("%c 0x%8.8llx 0x%8.8llx 0x%8.8x ", resolved ? ' ' : '*', m_file_offset, m_file_size, GetAllFlagBits());
+
+    DumpName (s);
+
+    s->EOL();
+
+    if (m_linked_section)
+    {
+        addr = LLDB_INVALID_ADDRESS;
+
+        if (process)
+        {
+            addr = m_linked_section->GetLoadBaseAddress(process);
+            if (addr != LLDB_INVALID_ADDRESS)
+                addr += m_linked_offset;
+        }
+
+        if (addr == LLDB_INVALID_ADDRESS)
+        {
+            if (process)
+                resolved = false;
+            addr = m_linked_section->GetFileAddress() + m_linked_offset;
+        }
+
+        int indent = (sizeof(void*) + 1 + sizeof(user_id_t) + 1) * 2 + 3 + s->GetIndentLevel();
+        s->Printf("%*.*s", indent, indent, "");
+        VMRange linked_range(addr, addr + m_byte_size);
+        linked_range.Dump (s, 0);
+        indent = 3 * (sizeof(uint32_t) * 2 + 2 + 1) + 1;
+        s->Printf("%c%*.*s", resolved ? ' ' : '*', indent, indent, "");
+
+        m_linked_section->DumpName(s);
+        s->Printf(" + 0x%llx\n", m_linked_offset);
+    }
+
+    m_children.Dump(s, process, false);
+}
+
+void
+Section::DumpName (Stream *s) const
+{
+    if (m_linked_section)
+        return m_linked_section->DumpName(s);
+    else if (m_parent == NULL)
+    {
+        // The top most section prints the module basename
+        const char *module_basename = m_module->GetFileSpec().GetFilename().AsCString();
+        if (module_basename && module_basename[0])
+            s->Printf("%s.", module_basename);
+    }
+    else
+    {
+        m_parent->DumpName (s);
+        s->PutChar('.');
+    }
+    m_name.Dump(s);
+}
+
+//----------------------------------------------------------------------
+// Get the section data from a complete contiguous copy of the
+// entire executable image.
+//----------------------------------------------------------------------
+size_t
+Section::GetSectionDataFromImage (const DataExtractor& image_data, DataExtractor& section_data) const
+{
+    size_t file_size = GetByteSize();
+    if (file_size > 0)
+    {
+        off_t file_offset = GetFileOffset();
+        if (section_data.SetData (image_data, file_offset, file_size) == file_size)
+            return true;
+    }
+    return false;
+}
+
+//----------------------------------------------------------------------
+// Get the section data the file on disk
+//----------------------------------------------------------------------
+size_t
+Section::ReadSectionDataFromObjectFile(const ObjectFile* objfile, DataExtractor& section_data) const
+{
+    if (objfile == NULL)
+        return 0;
+
+    const FileSpec& file = objfile->GetFileSpec();
+
+    if (file)
+    {
+        size_t section_file_size = GetByteSize();
+        if (section_file_size > 0)
+        {
+            off_t section_file_offset = GetFileOffset() + objfile->GetOffset();
+            DataBufferSP sectionDataSP(file.ReadFileContents(section_file_offset, section_file_size));
+
+            section_data.SetByteOrder(objfile->GetByteOrder());
+            section_data.SetAddressByteSize(objfile->GetAddressByteSize());
+            return section_data.SetData (sectionDataSP);
+        }
+    }
+    return 0;
+}
+
+size_t
+Section::MemoryMapSectionDataFromObjectFile(const ObjectFile* objfile, DataExtractor& section_data) const
+{
+    if (objfile == NULL)
+        return 0;
+
+    const FileSpec& file = objfile->GetFileSpec();
+
+    if (file)
+    {
+        size_t section_file_size = GetFileSize();
+        if (section_file_size > 0)
+        {
+            off_t section_file_offset = GetFileOffset() + objfile->GetOffset();
+            DataBufferSP sectionDataSP(file.MemoryMapFileContents(section_file_offset, section_file_size));
+            section_data.SetByteOrder(objfile->GetByteOrder());
+            section_data.SetAddressByteSize(objfile->GetAddressByteSize());
+            return section_data.SetData (sectionDataSP);
+        }
+    }
+    return 0;
+}
+
+bool
+Section::IsFake() const
+{
+    return m_fake;
+}
+
+void
+Section::SetIsFake(bool fake)
+{
+    m_fake = fake;
+}
+
+
+bool
+Section::IsDescendant (const Section *section)
+{
+    if (this == section)
+        return true;
+    if (m_parent)
+        return m_parent->IsDescendant (section);
+    return false;
+}
+
+bool
+Section::Slide (addr_t slide_amount, bool slide_children)
+{
+    if (m_file_addr != LLDB_INVALID_ADDRESS)
+    {
+        if (slide_amount == 0)
+            return true;
+
+        m_file_addr += slide_amount;
+
+        if (slide_children)
+            m_children.Slide (slide_amount, slide_children);
+
+        return true;
+    }
+    return false;
+}
+
+void
+Section::SetLinkedLocation (const Section *linked_section, uint64_t linked_offset)
+{
+    if (linked_section)
+        m_module = linked_section->GetModule();
+    m_linked_section = linked_section;
+    m_linked_offset  = linked_offset;
+}
+
+const Section *
+Section::GetLinkedSection () const
+{
+    return m_linked_section;
+}
+
+uint64_t
+Section::GetLinkedOffset () const
+{
+    return m_linked_offset;
+}
+
+#pragma mark SectionList
+
+SectionList::SectionList () :
+    m_sections()
+{
+}
+
+
+SectionList::~SectionList ()
+{
+}
+
+uint32_t
+SectionList::AddSection (SectionSP& sect_sp)
+{
+    uint32_t section_index = m_sections.size();
+    m_sections.push_back(sect_sp);
+    return section_index;
+}
+
+uint32_t
+SectionList::FindSectionIndex (const Section* sect)
+{
+    iterator sect_iter;
+    iterator begin = m_sections.begin();
+    iterator end = m_sections.end();
+    for (sect_iter = begin; sect_iter != end; ++sect_iter)
+    {
+        if (sect_iter->get() == sect)
+        {
+            // The secton was already in this section list
+            return std::distance (begin, sect_iter);
+        }
+    }
+    return UINT32_MAX;
+}
+
+uint32_t
+SectionList::AddUniqueSection (SectionSP& sect_sp)
+{
+    uint32_t sect_idx = FindSectionIndex (sect_sp.get());
+    if (sect_idx == UINT32_MAX)
+        sect_idx = AddSection (sect_sp);
+    return sect_idx;
+}
+
+
+bool
+SectionList::ReplaceSection (user_id_t sect_id, SectionSP& sect_sp, uint32_t depth)
+{
+    iterator sect_iter, end = m_sections.end();
+    for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter)
+    {
+        if ((*sect_iter)->GetID() == sect_id)
+        {
+            *sect_iter = sect_sp;
+            return true;
+        }
+        else if (depth > 0)
+        {
+            if ((*sect_iter)->GetChildren().ReplaceSection(sect_id, sect_sp, depth - 1))
+                return true;
+        }
+    }
+    return false;
+}
+
+
+size_t
+SectionList::GetSize () const
+{
+    return m_sections.size();
+}
+
+size_t
+SectionList::GetNumSections (uint32_t depth) const
+{
+    size_t count = m_sections.size();
+    if (depth > 0)
+    {
+        const_iterator sect_iter, end = m_sections.end();
+        for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter)
+        {
+            count += (*sect_iter)->GetChildren().GetNumSections(depth - 1);
+        }
+    }
+    return count;
+}
+
+SectionSP
+SectionList::GetSectionAtIndex (uint32_t idx) const
+{
+    SectionSP sect_sp;
+    if (idx < m_sections.size())
+        sect_sp = m_sections[idx];
+    return sect_sp;
+}
+
+SectionSP
+SectionList::FindSectionByName (const ConstString &section_dstr) const
+{
+    SectionSP sect_sp;
+    // Check if we have a valid section string
+    if (section_dstr)
+    {
+        const_iterator sect_iter;
+        const_iterator end = m_sections.end();
+        for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
+        {
+            if ((*sect_iter)->GetName() == section_dstr)
+            {
+                sect_sp = *sect_iter;
+            }
+            else
+            {
+                sect_sp = (*sect_iter)->GetChildren().FindSectionByName(section_dstr);
+            }
+        }
+    }
+    return sect_sp;
+}
+//
+//SectionSP
+//SectionList::FindSectionByNames (const char *s, ...) const
+//{
+//    SectionSP sect_sp;
+//    va_list ap;
+//    va_start(ap, s);
+//    uint32_t idx = 0;
+//    for (const char *sect_name = s; sect_name != NULL; sect_name = va_arg(ap, const char *))
+//    {
+//        printf("[%u] %s\n", idx++, sect_name);
+//    }
+//    va_end(ap);
+//    return sect_sp;
+//}
+
+SectionSP
+SectionList::FindSectionByID (user_id_t sect_id) const
+{
+    SectionSP sect_sp;
+    if (sect_id)
+    {
+        const_iterator sect_iter;
+        const_iterator end = m_sections.end();
+        for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
+        {
+            if ((*sect_iter)->GetID() == sect_id)
+            {
+                sect_sp = *sect_iter;
+                break;
+            }
+            else
+            {
+                sect_sp = (*sect_iter)->GetChildren().FindSectionByID (sect_id);
+            }
+        }
+    }
+    return sect_sp;
+}
+
+SectionSP
+SectionList::GetSharedPointer (const Section *section, bool check_children) const
+{
+    SectionSP sect_sp;
+    if (section)
+    {
+        const_iterator sect_iter;
+        const_iterator end = m_sections.end();
+        for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
+        {
+            if (sect_iter->get() == section)
+            {
+                sect_sp = *sect_iter;
+                break;
+            }
+            else if (check_children)
+            {
+                sect_sp = (*sect_iter)->GetChildren().GetSharedPointer (section, true);
+            }
+        }
+    }
+    return sect_sp;
+}
+
+
+
+SectionSP
+SectionList::FindSectionContainingFileAddress (addr_t vm_addr, uint32_t depth) const
+{
+    SectionSP sect_sp;
+    const_iterator sect_iter;
+    const_iterator end = m_sections.end();
+    for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
+    {
+        Section *sect = sect_iter->get();
+        if (sect->ContainsFileAddress (vm_addr))
+        {
+            // The file address is in this section. We need to make sure one of our child
+            // sections doesn't contain this address as well as obeying the depth limit
+            // that was passed in.
+            if (depth > 0)
+                sect_sp = sect->GetChildren().FindSectionContainingFileAddress(vm_addr, depth - 1);
+
+            if (sect_sp.get() == NULL && !sect->IsFake())
+                sect_sp = *sect_iter;
+        }
+    }
+    return sect_sp;
+}
+
+
+SectionSP
+SectionList::FindSectionContainingLinkedFileAddress (addr_t vm_addr) const
+{
+    SectionSP sect_sp;
+    const_iterator sect_iter;
+    const_iterator end = m_sections.end();
+    for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
+    {
+        Section *sect = sect_iter->get();
+        if (sect->ContainsLinkedFileAddress (vm_addr))
+        {
+            sect_sp = *sect_iter;
+            break;
+        }
+    }
+    return sect_sp;
+}
+
+bool
+SectionList::ContainsSection(user_id_t sect_id) const
+{
+    return FindSectionByID (sect_id).get() != NULL;
+}
+
+void
+SectionList::Dump (Stream *s, Process *process, bool show_header) const
+{
+    if (show_header && !m_sections.empty())
+    {
+        s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+        s->Indent();
+        s->PutCString(  "SectionList\n");
+        s->IndentMore();
+        s->Printf("%*s", 2*(sizeof(void *) + 2), "");
+        s->Indent();
+        s->Printf("SectID     %s Address                             File Off.  File Size  Flags      Section Name\n", process ? "Load" : "File");
+        s->Printf("%*s", 2*(sizeof(void *) + 2), "");
+        s->Indent();
+        s->PutCString("---------- ---------------------------------------  ---------- ---------- ---------- ----------------------------\n");
+    }
+
+
+    const_iterator sect_iter;
+    const_iterator end = m_sections.end();
+    for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter)
+    {
+        (*sect_iter)->Dump(s, process);
+    }
+
+    if (show_header && !m_sections.empty())
+        s->IndentLess();
+
+}
+
+size_t
+SectionList::Slide (addr_t slide_amount, bool slide_children)
+{
+    size_t count = 0;
+    const_iterator pos, end = m_sections.end();
+    for (pos = m_sections.begin(); pos != end; ++pos)
+    {
+        if ((*pos)->Slide(slide_amount, slide_children))
+            ++count;
+    }
+    return count;
+}
+
diff --git a/source/Core/SourceManager.cpp b/source/Core/SourceManager.cpp
new file mode 100644
index 0000000..2786fe4
--- /dev/null
+++ b/source/Core/SourceManager.cpp
@@ -0,0 +1,305 @@
+//===-- SourceManager.cpp ---------------------------------------*- 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/SourceManager.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/DataBuffer.h"
+#include "lldb/Core/Stream.h"
+
+using namespace lldb_private;
+
+static inline bool is_newline_char(char ch)
+{
+    return ch == '\n' || ch == '\r';
+}
+
+
+//----------------------------------------------------------------------
+// SourceManager constructor
+//----------------------------------------------------------------------
+SourceManager::SourceManager() :
+    m_file_cache (),
+    m_last_file_sp (),
+    m_last_file_line (0),
+    m_last_file_context_before (0),
+    m_last_file_context_after (0)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+SourceManager::~SourceManager()
+{
+}
+
+size_t
+SourceManager::DisplaySourceLines
+(
+    const FileSpec &file_spec,
+    uint32_t line,
+    uint32_t context_before,
+    uint32_t context_after,
+    Stream *s
+)
+{
+    m_last_file_sp = GetFile (file_spec);
+    m_last_file_line = line + context_after + 1;
+    m_last_file_context_before = context_before;
+    m_last_file_context_after = context_after;
+    if (m_last_file_sp.get())
+        return m_last_file_sp->DisplaySourceLines (line, context_before, context_after, s);
+
+    return 0;
+}
+
+SourceManager::FileSP
+SourceManager::GetFile (const FileSpec &file_spec)
+{
+    FileSP file_sp;
+    FileCache::iterator pos = m_file_cache.find(file_spec);
+    if (pos != m_file_cache.end())
+        file_sp = pos->second;
+    else
+    {
+        file_sp.reset (new File (file_spec));
+        m_file_cache[file_spec] = file_sp;
+    }
+    return file_sp;
+}
+
+size_t
+SourceManager::DisplaySourceLinesWithLineNumbersUsingLastFile
+(
+    uint32_t line,
+    uint32_t context_before,
+    uint32_t context_after,
+    const char* current_line_cstr,
+    Stream *s
+)
+{
+    if (line == 0)
+    {
+        if (m_last_file_line != 0
+            && m_last_file_line != UINT32_MAX)
+            line = m_last_file_line + context_before;
+        else
+            line = 1;
+    }
+
+    m_last_file_line = line + context_after + 1;
+    m_last_file_context_before = context_before;
+    m_last_file_context_after = context_after;
+
+    if (context_before == UINT32_MAX)
+        context_before = 0;
+    if (context_after == UINT32_MAX)
+        context_after = 10;
+
+    if (m_last_file_sp.get())
+    {
+        const uint32_t start_line = line <= context_before ? 1 : line - context_before;
+        const uint32_t end_line = line + context_after;
+        uint32_t curr_line;
+        for (curr_line = start_line; curr_line <= end_line; ++curr_line)
+        {
+            if (!m_last_file_sp->LineIsValid (curr_line))
+            {
+                m_last_file_line = UINT32_MAX;
+                break;
+            }
+
+            s->Printf("%4u %2.2s\t", curr_line, curr_line == line ? current_line_cstr : "");
+            if (m_last_file_sp->DisplaySourceLines (curr_line, 0, 0, s) == 0)
+            {
+                m_last_file_line = UINT32_MAX;
+                break;
+            }
+        }
+    }
+    return 0;
+}
+
+size_t
+SourceManager::DisplaySourceLinesWithLineNumbers
+(
+    const FileSpec &file_spec,
+    uint32_t line,
+    uint32_t context_before,
+    uint32_t context_after,
+    const char* current_line_cstr,
+    Stream *s
+)
+{
+    bool same_as_previous = m_last_file_sp && m_last_file_sp->FileSpecMatches (file_spec);
+
+    if (!same_as_previous)
+        m_last_file_sp = GetFile (file_spec);
+
+    if (line == 0)
+    {
+        if (!same_as_previous)
+            m_last_file_line = 0;
+    }
+
+    return DisplaySourceLinesWithLineNumbersUsingLastFile (line, context_before, context_after, current_line_cstr, s);
+}
+
+size_t
+SourceManager::DisplayMoreWithLineNumbers (Stream *s)
+{
+    if (m_last_file_sp)
+    {
+        if (m_last_file_line == UINT32_MAX)
+            return 0;
+        DisplaySourceLinesWithLineNumbersUsingLastFile (0, m_last_file_context_before, m_last_file_context_after, "", s);
+    }
+    return 0;
+}
+
+
+
+SourceManager::File::File(const FileSpec &file_spec) :
+    m_file_spec(file_spec),
+    m_data_sp(file_spec.ReadFileContents ()),
+    m_offsets()
+{
+}
+
+SourceManager::File::~File()
+{
+}
+
+uint32_t
+SourceManager::File::GetLineOffset (uint32_t line)
+{
+    if (line == 0)
+        return UINT32_MAX;
+
+    if (line == 1)
+        return 0;
+
+    if (CalculateLineOffsets (line))
+    {
+        if (line < m_offsets.size())
+            return m_offsets[line - 1]; // yes we want "line - 1" in the index
+    }
+    return UINT32_MAX;
+}
+
+bool
+SourceManager::File::LineIsValid (uint32_t line)
+{
+    if (line == 0)
+        return false;
+
+    if (CalculateLineOffsets (line))
+        return line < m_offsets.size();
+    return false;
+}
+
+size_t
+SourceManager::File::DisplaySourceLines (uint32_t line, uint32_t context_before, uint32_t context_after, Stream *s)
+{
+    const uint32_t start_line = line <= context_before ? 1 : line - context_before;
+    const uint32_t start_line_offset = GetLineOffset (start_line);
+    if (start_line_offset != UINT32_MAX)
+    {
+        const uint32_t end_line = line + context_after;
+        uint32_t end_line_offset = GetLineOffset (end_line + 1);
+        if (end_line_offset == UINT32_MAX)
+            end_line_offset = m_data_sp->GetByteSize();
+
+        assert (start_line_offset <= end_line_offset);
+        size_t bytes_written = 0;
+        if (start_line_offset < end_line_offset)
+        {
+            size_t count = end_line_offset - start_line_offset;
+            const uint8_t *cstr = m_data_sp->GetBytes() + start_line_offset;
+            bytes_written = s->Write(cstr, count);
+            if (!is_newline_char(cstr[count-1]))
+                bytes_written += s->EOL();
+        }
+        return bytes_written;
+    }
+    return 0;
+}
+
+bool
+SourceManager::File::FileSpecMatches (const FileSpec &file_spec)
+{
+    return FileSpec::Compare (m_file_spec, file_spec, false) == 0;
+}
+
+
+bool
+SourceManager::File::CalculateLineOffsets (uint32_t line)
+{
+    line = UINT32_MAX;  // TODO: take this line out when we support partial indexing
+    if (line == UINT32_MAX)
+    {
+        // Already done?
+        if (!m_offsets.empty() && m_offsets[0] == UINT32_MAX)
+            return true;
+
+        if (m_offsets.empty())
+        {
+            if (m_data_sp.get() == NULL)
+                return false;
+
+            const char *start = (char *)m_data_sp->GetBytes();
+            if (start)
+            {
+                const char *end = start + m_data_sp->GetByteSize();
+
+                // Calculate all line offsets from scratch
+
+                // Push a 1 at index zero to indicate the file has been completely indexed.
+                m_offsets.push_back(UINT32_MAX);
+                register const char *s;
+                for (s = start; s < end; ++s)
+                {
+                    register char curr_ch = *s;
+                    if (is_newline_char (curr_ch))
+                    {
+                        register char next_ch = s[1];
+                        if (is_newline_char (next_ch))
+                        {
+                            if (curr_ch != next_ch)
+                                ++s;
+                        }
+                        m_offsets.push_back(s + 1 - start);
+                    }
+                }
+                if (!m_offsets.empty())
+                {
+                    if (m_offsets.back() < end - start)
+                        m_offsets.push_back(end - start);
+                }
+                return true;
+            }
+        }
+        else
+        {
+            // Some lines have been populated, start where we last left off
+            assert(!"Not implemented yet");
+        }
+
+    }
+    else
+    {
+        // Calculate all line offsets up to "line"
+        assert(!"Not implemented yet");
+    }
+    return false;
+}
diff --git a/source/Core/State.cpp b/source/Core/State.cpp
new file mode 100644
index 0000000..cf9a834
--- /dev/null
+++ b/source/Core/State.cpp
@@ -0,0 +1,87 @@
+//===-- State.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
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/State.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+const char *
+lldb_private::StateAsCString (StateType state)
+{
+    switch (state)
+    {
+    case eStateInvalid:     return "Invalid";
+    case eStateUnloaded:    return "Unloaded";
+    case eStateAttaching:   return "Attaching";
+    case eStateLaunching:   return "Launching";
+    case eStateStopped:     return "Stopped";
+    case eStateRunning:     return "Running";
+    case eStateStepping:    return "Stepping";
+    case eStateCrashed:     return "Crashed";
+    case eStateDetached:    return "Detached";
+    case eStateExited:      return "Exited";
+    case eStateSuspended:   return "Suspended";
+    }
+    static char unknown_state_string[64];
+    snprintf(unknown_state_string, sizeof (unknown_state_string), "StateType = %i", state);
+    return unknown_state_string;
+}
+
+bool
+lldb_private::StateIsRunningState (StateType state)
+{
+    switch (state)
+    {
+    case eStateAttaching:
+    case eStateLaunching:
+    case eStateRunning:
+    case eStateStepping:
+        return true;
+
+    case eStateDetached:
+    case eStateInvalid:
+    case eStateUnloaded:
+    case eStateStopped:
+    case eStateCrashed:
+    case eStateExited:
+    case eStateSuspended:
+    default:
+        break;
+    }
+    return false;
+}
+
+bool
+lldb_private::StateIsStoppedState (StateType state)
+{
+    switch (state)
+    {
+    case eStateInvalid:
+    case eStateAttaching:
+    case eStateLaunching:
+    case eStateRunning:
+    case eStateStepping:
+    case eStateDetached:
+    default:
+        break;
+
+    case eStateUnloaded:
+    case eStateStopped:
+    case eStateCrashed:
+    case eStateExited:
+    case eStateSuspended:
+        return true;
+    }
+    return false;
+}
diff --git a/source/Core/Stream.cpp b/source/Core/Stream.cpp
new file mode 100644
index 0000000..a0de2d4
--- /dev/null
+++ b/source/Core/Stream.cpp
@@ -0,0 +1,776 @@
+//===-- Stream.cpp ----------------------------------------------*- 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/Stream.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+Stream::Stream (uint32_t flags, uint32_t addr_size, ByteOrder byte_order) :
+    m_flags (flags),
+    m_addr_size (addr_size),
+    m_byte_order (byte_order),
+    m_indent_level(0)
+{
+}
+
+Stream::Stream () :
+    m_flags (0),
+    m_addr_size (4),
+    m_byte_order (eByteOrderHost),
+    m_indent_level(0)
+{
+}
+
+//------------------------------------------------------------------
+// Destructor
+//------------------------------------------------------------------
+Stream::~Stream ()
+{
+}
+
+ByteOrder
+Stream::SetByteOrder (ByteOrder byte_order)
+{
+    ByteOrder old_byte_order = m_byte_order;
+    m_byte_order = byte_order;
+    return old_byte_order;
+}
+
+//------------------------------------------------------------------
+// Put an offset "uval" out to the stream using the printf format
+// in "format".
+//------------------------------------------------------------------
+void
+Stream::Offset (uint32_t uval, const char *format)
+{
+    Printf (format, uval);
+}
+
+//------------------------------------------------------------------
+// Put an SLEB128 "uval" out to the stream using the printf format
+// in "format".
+//------------------------------------------------------------------
+int
+Stream::PutSLEB128 (int64_t sval)
+{
+    int bytes_written = 0;
+    if (m_flags.IsSet(eBinary))
+    {
+        bool more = true;
+        bool negative = (sval < 0);
+        while (more)
+        {
+            uint8_t byte = sval & 0x7fu;
+            sval >>= 7;
+            assert((!negative && sval >= 0) || (negative && sval < 0));
+            /* sign bit of byte is 2nd high order bit (0x40) */
+            if ((sval ==  0 && !(byte & 0x40)) ||
+                (sval == -1 &&  (byte & 0x40)) )
+                more = false;
+            else
+                // more bytes to come
+                byte |= 0x80u;
+            bytes_written += Write(&byte, 1);
+        }
+    }
+    else
+    {
+        bytes_written = Printf ("0x%lli", sval);
+    }
+
+    return bytes_written;
+
+}
+
+//------------------------------------------------------------------
+// Put an ULEB128 "uval" out to the stream using the printf format
+// in "format".
+//------------------------------------------------------------------
+int
+Stream::PutULEB128 (uint64_t uval)
+{
+    int bytes_written = 0;
+    if (m_flags.IsSet(eBinary))
+    {
+        do
+        {
+
+            uint8_t byte = uval & 0x7fu;
+            uval >>= 7;
+            if (uval != 0)
+            {
+                // more bytes to come
+                byte |= 0x80u;
+            }
+            bytes_written += Write(&byte, 1);
+        } while (uval != 0);
+    }
+    else
+    {
+        bytes_written = Printf ("0x%llx", uval);
+    }
+    return bytes_written;
+}
+
+//------------------------------------------------------------------
+// Print a raw NULL terminated C string to the stream using the
+// printf format in "format".
+//------------------------------------------------------------------
+int
+Stream::PutCString (const char *cstr)
+{
+    int cstr_len = strlen(cstr);
+    // when in binary mode, emit the NULL terminator
+    if (m_flags.IsSet(eBinary))
+        ++cstr_len;
+    return Write (cstr, cstr_len);
+}
+
+//------------------------------------------------------------------
+// Print a double quoted NULL terminated C string to the stream
+// using the printf format in "format".
+//------------------------------------------------------------------
+void
+Stream::QuotedCString (const char *cstr, const char *format)
+{
+    Printf (format, cstr);
+}
+
+//------------------------------------------------------------------
+// Put an address "addr" out to the stream with optional prefix
+// and suffix strings.
+//------------------------------------------------------------------
+void
+Stream::Address (uint64_t addr, int addr_size, const char *prefix, const char *suffix)
+{
+    if (prefix == NULL)
+        prefix = "";
+    if (suffix == NULL)
+        suffix = "";
+//    int addr_width = m_addr_size << 1;
+//    Printf ("%s0x%0*llx%s", prefix, addr_width, addr, suffix);
+    Printf ("%s0x%0*llx%s", prefix, addr_size * 2, (uint64_t)addr, suffix);
+}
+
+//------------------------------------------------------------------
+// Put an address range out to the stream with optional prefix
+// and suffix strings.
+//------------------------------------------------------------------
+void
+Stream::AddressRange(uint64_t lo_addr, uint64_t hi_addr, int addr_size, const char *prefix, const char *suffix)
+{
+    if (prefix != NULL)
+        PutCString (prefix);
+    Address (lo_addr, addr_size, "[");
+    Address (hi_addr, addr_size, "-", ")");
+}
+
+
+int
+Stream::PutChar (char ch)
+{
+    return Write (&ch, 1);
+}
+
+
+//------------------------------------------------------------------
+// Print some formatted output to the stream.
+//------------------------------------------------------------------
+int
+Stream::Printf (const char *format, ...)
+{
+    va_list args;
+    va_start (args, format);
+    size_t result = PrintfVarArg(format, args);
+    va_end (args);
+    return result;
+}
+
+//------------------------------------------------------------------
+// Print some formatted output to the stream.
+//------------------------------------------------------------------
+int
+Stream::PrintfVarArg (const char *format, va_list args)
+{
+    char str[1024];
+    va_list args_copy;
+
+    va_copy (args_copy, args);
+
+    int bytes_written = 0;
+    // Try and format our string into a fixed buffer first and see if it fits
+    int length = vsnprintf (str, sizeof(str), format, args);
+    if (length < sizeof(str))
+    {
+        va_end (args);
+        // Include the NULL termination byte for binary output
+        if (m_flags.IsSet(eBinary))
+            length += 1;
+        // The formatted string fit into our stack based buffer, so we can just
+        // append that to our packet
+        bytes_written = Write (str, length);
+    }
+    else
+    {
+        // Our stack buffer wasn't big enough to contain the entire formatted
+        // string, so lets let vasprintf create the string for us!
+        char *str_ptr = NULL;
+        length = ::vasprintf (&str_ptr, format, args_copy);
+        if (str_ptr)
+        {
+            // Include the NULL termination byte for binary output
+            if (m_flags.IsSet(eBinary))
+                length += 1;
+            bytes_written = Write (str_ptr, length);
+            ::free (str_ptr);
+        }
+    }
+    va_end (args_copy);
+    return bytes_written;
+}
+
+//------------------------------------------------------------------
+// Print and End of Line character to the stream
+//------------------------------------------------------------------
+int
+Stream::EOL()
+{
+    return PutChar ('\n');
+}
+
+//------------------------------------------------------------------
+// Indent the current line using the current indentation level and
+// print an optional string following the idenatation spaces.
+//------------------------------------------------------------------
+int
+Stream::Indent(const char *s)
+{
+    return Printf ("%*.*s%s", m_indent_level, m_indent_level, "", s ? s : "");
+}
+
+//------------------------------------------------------------------
+// Stream a character "ch" out to this stream.
+//------------------------------------------------------------------
+Stream&
+Stream::operator<< (char ch)
+{
+    PutChar (ch);
+    return *this;
+}
+
+//------------------------------------------------------------------
+// Stream the NULL terminated C string out to this stream.
+//------------------------------------------------------------------
+Stream&
+Stream::operator<<  (const char *s)
+{
+    Printf ("%s", s);
+    return *this;
+}
+
+//------------------------------------------------------------------
+// Stream the pointer value out to this stream.
+//------------------------------------------------------------------
+Stream&
+Stream::operator<< (void *p)
+{
+    Printf ("0x%.*tx", (int)sizeof(void*) * 2, (ptrdiff_t)p);
+    return *this;
+}
+
+//------------------------------------------------------------------
+// Stream a uint8_t "uval" out to this stream.
+//------------------------------------------------------------------
+Stream&
+Stream::operator<< (uint8_t uval)
+{
+    PutHex8(uval);
+    return *this;
+}
+
+//------------------------------------------------------------------
+// Stream a uint16_t "uval" out to this stream.
+//------------------------------------------------------------------
+Stream&
+Stream::operator<< (uint16_t uval)
+{
+    PutHex16(uval, m_byte_order);
+    return *this;
+}
+
+//------------------------------------------------------------------
+// Stream a uint32_t "uval" out to this stream.
+//------------------------------------------------------------------
+Stream&
+Stream::operator<< (uint32_t uval)
+{
+    PutHex32(uval, m_byte_order);
+    return *this;
+}
+
+//------------------------------------------------------------------
+// Stream a uint64_t "uval" out to this stream.
+//------------------------------------------------------------------
+Stream&
+Stream::operator<< (uint64_t uval)
+{
+    PutHex64(uval, m_byte_order);
+    return *this;
+}
+
+//------------------------------------------------------------------
+// Stream a int8_t "sval" out to this stream.
+//------------------------------------------------------------------
+Stream&
+Stream::operator<< (int8_t sval)
+{
+    Printf ("%i", (int)sval);
+    return *this;
+}
+
+//------------------------------------------------------------------
+// Stream a int16_t "sval" out to this stream.
+//------------------------------------------------------------------
+Stream&
+Stream::operator<< (int16_t sval)
+{
+    Printf ("%i", (int)sval);
+    return *this;
+}
+
+//------------------------------------------------------------------
+// Stream a int32_t "sval" out to this stream.
+//------------------------------------------------------------------
+Stream&
+Stream::operator<< (int32_t sval)
+{
+    Printf ("%i", (int)sval);
+    return *this;
+}
+
+//------------------------------------------------------------------
+// Stream a int64_t "sval" out to this stream.
+//------------------------------------------------------------------
+Stream&
+Stream::operator<< (int64_t sval)
+{
+    Printf ("%lli", sval);
+    return *this;
+}
+
+//------------------------------------------------------------------
+// Get the current indentation level
+//------------------------------------------------------------------
+int
+Stream::GetIndentLevel() const
+{
+    return m_indent_level;
+}
+
+//------------------------------------------------------------------
+// Set the current indentation level
+//------------------------------------------------------------------
+void
+Stream::SetIndentLevel(int indent_level)
+{
+    m_indent_level = indent_level;
+}
+
+//------------------------------------------------------------------
+// Increment the current indentation level
+//------------------------------------------------------------------
+void
+Stream::IndentMore(int amount)
+{
+    m_indent_level += amount;
+}
+
+//------------------------------------------------------------------
+// Decrement the current indentation level
+//------------------------------------------------------------------
+void
+Stream::IndentLess (int amount)
+{
+    if (m_indent_level >= amount)
+        m_indent_level -= amount;
+    else
+        m_indent_level = 0;
+}
+
+//------------------------------------------------------------------
+// Get the address size in bytes
+//------------------------------------------------------------------
+uint8_t
+Stream::GetAddressByteSize() const
+{
+    return m_addr_size;
+}
+
+//------------------------------------------------------------------
+// Set the address size in bytes
+//------------------------------------------------------------------
+void
+Stream::SetAddressByteSize(uint8_t addr_size)
+{
+    m_addr_size = addr_size;
+}
+
+//------------------------------------------------------------------
+// Returns true if the verbose flag bit is set in this stream.
+//------------------------------------------------------------------
+bool
+Stream::GetVerbose() const
+{
+    return m_flags.IsSet(eVerbose);
+}
+
+//------------------------------------------------------------------
+// Returns true if the debug flag bit is set in this stream.
+//------------------------------------------------------------------
+bool
+Stream::GetDebug() const
+{
+    return m_flags.IsSet(eDebug);
+}
+
+//------------------------------------------------------------------
+// The flags get accessor
+//------------------------------------------------------------------
+Flags&
+Stream::GetFlags()
+{
+    return m_flags;
+}
+
+//------------------------------------------------------------------
+// The flags const get accessor
+//------------------------------------------------------------------
+const Flags&
+Stream::GetFlags() const
+{
+    return m_flags;
+}
+
+int
+Stream::PrintfAsRawHex8 (const char *format, ...)
+{
+    va_list args;
+    va_list args_copy;
+    va_start (args, format);
+    va_copy (args, args_copy); // Copy this so we
+
+    int i;
+    char str[1024];
+    int bytes_written = 0;
+    // Try and format our string into a fixed buffer first and see if it fits
+    int length = vsnprintf (str, sizeof(str), format, args);
+    if (length < sizeof(str))
+    {
+        // The formatted string fit into our stack based buffer, so we can just
+        // append that to our packet
+        for (i=0; i<length; ++i)
+            bytes_written += _PutHex8 (str[i], false);
+    }
+    else
+    {
+        // Our stack buffer wasn't big enough to contain the entire formatted
+        // string, so lets let vasprintf create the string for us!
+        char *str_ptr = NULL;
+        length = ::vasprintf (&str_ptr, format, args_copy);
+        if (str_ptr)
+        {
+            for (i=0; i<length; ++i)
+                bytes_written += _PutHex8 (str_ptr[i], false);
+            ::free (str_ptr);
+        }
+    }
+    va_end (args);
+    va_end (args_copy);
+
+    return bytes_written;
+}
+
+int
+Stream::PutNHex8 (size_t n, uint8_t uvalue)
+{
+    int bytes_written = 0;
+    for (int i=0; i<n; ++i)
+        bytes_written += _PutHex8 (uvalue, m_flags.IsSet(eAddPrefix));
+    return bytes_written;
+}
+
+int
+Stream::_PutHex8 (uint8_t uvalue, bool add_prefix)
+{
+    int bytes_written = 0;
+    if (m_flags.IsSet(eBinary))
+    {
+        bytes_written = Write (&uvalue, 1);
+    }
+    else
+    {
+        if (add_prefix)
+            PutCString("0x");
+
+        static char g_hex_to_ascii_hex_char[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+        char nibble_chars[2];
+        nibble_chars[0] = g_hex_to_ascii_hex_char[(uvalue >> 4) & 0xf];
+        nibble_chars[1] = g_hex_to_ascii_hex_char[(uvalue >> 0) & 0xf];
+        bytes_written = Write (nibble_chars, sizeof(nibble_chars));
+    }
+    return bytes_written;
+}
+
+int
+Stream::PutHex8 (uint8_t uvalue)
+{
+    return _PutHex8 (uvalue, m_flags.IsSet(eAddPrefix));
+}
+
+int
+Stream::PutHex16 (uint16_t uvalue, ByteOrder byte_order)
+{
+    if (byte_order == eByteOrderInvalid)
+        byte_order = m_byte_order;
+
+    bool add_prefix = m_flags.IsSet(eAddPrefix);
+    int bytes_written = 0;
+    int byte;
+    if (byte_order == eByteOrderLittle)
+    {
+        for (byte = 0; byte < sizeof(uvalue); ++byte, add_prefix = false)
+            bytes_written += _PutHex8 (uvalue >> (byte * 8), add_prefix);
+    }
+    else
+    {
+        for (byte = sizeof(uvalue)-1; byte >= 0; --byte, add_prefix = false)
+            bytes_written += _PutHex8 (uvalue >> (byte * 8), add_prefix);
+    }
+    return bytes_written;
+}
+
+int
+Stream::PutHex32(uint32_t uvalue, ByteOrder byte_order)
+{
+    if (byte_order == eByteOrderInvalid)
+        byte_order = m_byte_order;
+
+    bool add_prefix = m_flags.IsSet(eAddPrefix);
+    int bytes_written = 0;
+    int byte;
+    if (byte_order == eByteOrderLittle)
+    {
+        for (byte = 0; byte < sizeof(uvalue); ++byte, add_prefix = false)
+            bytes_written += _PutHex8 (uvalue >> (byte * 8), add_prefix);
+    }
+    else
+    {
+        for (byte = sizeof(uvalue)-1; byte >= 0; --byte, add_prefix = false)
+            bytes_written += _PutHex8 (uvalue >> (byte * 8), add_prefix);
+    }
+    return bytes_written;
+}
+
+int
+Stream::PutHex64(uint64_t uvalue, ByteOrder byte_order)
+{
+    if (byte_order == eByteOrderInvalid)
+        byte_order = m_byte_order;
+
+    bool add_prefix = m_flags.IsSet(eAddPrefix);
+    int bytes_written = 0;
+    int byte;
+    if (byte_order == eByteOrderLittle)
+    {
+        for (byte = 0; byte < sizeof(uvalue); ++byte, add_prefix = false)
+            bytes_written += _PutHex8 (uvalue >> (byte * 8), add_prefix);
+    }
+    else
+    {
+        for (byte = sizeof(uvalue)-1; byte >= 0; --byte, add_prefix = false)
+            bytes_written += _PutHex8 (uvalue >> (byte * 8), add_prefix);
+    }
+    return bytes_written;
+}
+
+int
+Stream::PutMaxHex64
+(
+    uint64_t uvalue,
+    size_t byte_size,
+    lldb::ByteOrder byte_order
+)
+{
+    switch (byte_size)
+    {
+    case 1: return PutHex8 (uvalue);
+    case 2: return PutHex16 (uvalue);
+    case 4: return PutHex32 (uvalue);
+    case 8: return PutHex64 (uvalue);
+    }
+    return 0;
+}
+
+int
+Stream::PutPointer (void *ptr)
+{
+    return PutRawBytes (&ptr, sizeof(ptr), eByteOrderHost, eByteOrderHost);
+}
+
+int
+Stream::PutFloat(float f, ByteOrder byte_order)
+{
+    if (byte_order == eByteOrderInvalid)
+        byte_order = m_byte_order;
+
+    return PutRawBytes (&f, sizeof(f), eByteOrderHost, byte_order);
+}
+
+int
+Stream::PutDouble(double d, ByteOrder byte_order)
+{
+    if (byte_order == eByteOrderInvalid)
+        byte_order = m_byte_order;
+
+    return PutRawBytes (&d, sizeof(d), eByteOrderHost, byte_order);
+}
+
+int
+Stream::PutLongDouble(long double ld, ByteOrder byte_order)
+{
+    if (byte_order == eByteOrderInvalid)
+        byte_order = m_byte_order;
+
+    return PutRawBytes (&ld, sizeof(ld), eByteOrderHost, byte_order);
+}
+
+int
+Stream::PutRawBytes (const void *s, size_t src_len, ByteOrder src_byte_order, ByteOrder dst_byte_order)
+{
+    if (src_byte_order == eByteOrderInvalid)
+        src_byte_order = m_byte_order;
+
+    if (dst_byte_order == eByteOrderInvalid)
+        dst_byte_order = m_byte_order;
+
+    int bytes_written = 0;
+    const uint8_t *src = (const uint8_t *)s;
+    int i;
+    bool binary_is_clear = m_flags.IsClear (eBinary);
+    m_flags.Set (eBinary);
+    if (src_byte_order == dst_byte_order)
+    {
+        for (i=0;i<src_len; ++i)
+            bytes_written += _PutHex8 (src[i], false);
+    }
+    else
+    {
+        for (i=src_len-1;i>=0; --i)
+            bytes_written += _PutHex8 (src[i], false);
+    }
+    if (binary_is_clear)
+        m_flags.Clear (eBinary);
+
+    return bytes_written;
+}
+
+int
+Stream::PutBytesAsRawHex8 (const void *s, size_t src_len, ByteOrder src_byte_order, ByteOrder dst_byte_order)
+{
+    if (src_byte_order == eByteOrderInvalid)
+        src_byte_order = m_byte_order;
+
+    if (dst_byte_order == eByteOrderInvalid)
+        dst_byte_order = m_byte_order;
+
+    int bytes_written = 0;
+    const uint8_t *src = (const uint8_t *)s;
+    int i;
+    bool binary_is_set = m_flags.IsSet(eBinary);
+    m_flags.Clear(eBinary);
+    if (src_byte_order == dst_byte_order)
+    {
+        for (i=0;i<src_len; ++i)
+            bytes_written += _PutHex8 (src[i], false);
+    }
+    else
+    {
+        for (i=src_len-1;i>=0; --i)
+            bytes_written += _PutHex8 (src[i], false);
+    }
+    if (binary_is_set)
+        m_flags.Set(eBinary);
+
+    return bytes_written;
+}
+
+int
+Stream::PutCStringAsRawHex8 (const char *s)
+{
+    int bytes_written = 0;
+    bool binary_is_set = m_flags.IsSet(eBinary);
+    m_flags.Clear(eBinary);
+    do
+    {
+        bytes_written += _PutHex8 (*s, false);
+        ++s;
+    } while (*s);
+    if (binary_is_set)
+        m_flags.Set(eBinary);
+    return bytes_written;
+}
+
+void
+Stream::UnitTest(Stream *s)
+{
+    s->PutHex8(0x12);
+
+    s->PutChar(' ');
+    s->PutHex16(0x3456, eByteOrderHost);
+    s->PutChar(' ');
+    s->PutHex16(0x3456, eByteOrderBig);
+    s->PutChar(' ');
+    s->PutHex16(0x3456, eByteOrderLittle);
+
+    s->PutChar(' ');
+    s->PutHex32(0x789abcde, eByteOrderHost);
+    s->PutChar(' ');
+    s->PutHex32(0x789abcde, eByteOrderBig);
+    s->PutChar(' ');
+    s->PutHex32(0x789abcde, eByteOrderLittle);
+
+    s->PutChar(' ');
+    s->PutHex64(0x1122334455667788ull, eByteOrderHost);
+    s->PutChar(' ');
+    s->PutHex64(0x1122334455667788ull, eByteOrderBig);
+    s->PutChar(' ');
+    s->PutHex64(0x1122334455667788ull, eByteOrderLittle);
+
+    const char *hola = "Hello World!!!";
+    s->PutChar(' ');
+    s->PutCString (hola);
+
+    s->PutChar(' ');
+    s->Write (hola, 5);
+
+    s->PutChar(' ');
+    s->PutCStringAsRawHex8 (hola);
+
+    s->PutChar(' ');
+    s->PutCStringAsRawHex8 ("01234");
+
+    s->PutChar(' ');
+    s->Printf ("pid=%i", 12733);
+
+    s->PutChar(' ');
+    s->PrintfAsRawHex8 ("pid=%i", 12733);
+    s->PutChar('\n');
+}
+
diff --git a/source/Core/StreamFile.cpp b/source/Core/StreamFile.cpp
new file mode 100644
index 0000000..9c6c508
--- /dev/null
+++ b/source/Core/StreamFile.cpp
@@ -0,0 +1,132 @@
+//===-- StreamFile.cpp ------------------------------------------*- 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/StreamFile.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// StreamFile constructor
+//----------------------------------------------------------------------
+StreamFile::StreamFile () :
+    Stream (),
+    m_file (NULL),
+    m_path_name (),
+    m_close_file (false)
+{
+}
+
+StreamFile::StreamFile(uint32_t flags, uint32_t addr_size, ByteOrder byte_order, FILE *f) :
+    Stream (flags, addr_size, byte_order),
+    m_file(f),
+    m_path_name (),
+    m_close_file(false)
+{
+}
+
+StreamFile::StreamFile(FILE *f) :
+    Stream (),
+    m_file(f),
+    m_path_name (),
+    m_close_file(false)
+{
+}
+
+StreamFile::StreamFile(uint32_t flags, uint32_t addr_size, ByteOrder byte_order, const char *path, const char *permissions) :
+    Stream (flags, addr_size, byte_order),
+    m_file (NULL),
+    m_path_name (path),
+    m_close_file(false)
+{
+    Open(path, permissions);
+}
+
+StreamFile::StreamFile(const char *path, const char *permissions) :
+    Stream (),
+    m_file (NULL),
+    m_path_name (path),
+    m_close_file(false)
+{
+    Open(path, permissions);
+}
+
+
+StreamFile::~StreamFile()
+{
+    Close ();
+}
+
+void
+StreamFile::Close ()
+{
+    if (m_close_file && m_file != NULL)
+        ::fclose (m_file);
+    m_file = NULL;
+    m_close_file = false;
+}
+
+bool
+StreamFile::Open (const char *path, const char *permissions)
+{
+    Close();
+    if (path && path[0])
+    {
+        if ((m_path_name.size() == 0)
+            || (m_path_name.compare(path) != 0))
+            m_path_name = path;
+        m_file = ::fopen (path, permissions);
+        if (m_file != NULL)
+            m_close_file = true;
+    }
+    return m_file != NULL;
+}
+
+void
+StreamFile::Flush ()
+{
+    if (m_file)
+        ::fflush (m_file);
+}
+
+int
+StreamFile::Write (const void *s, size_t length)
+{
+    if (m_file)
+        return ::fwrite (s, 1, length, m_file);
+    return 0;
+}
+
+FILE *
+StreamFile::GetFileHandle()
+{
+    return m_file;
+}
+
+void
+StreamFile::SetFileHandle (FILE *file, bool close_file)
+{
+    Close();
+    m_file = file;
+    m_close_file = close_file;
+}
+
+const char *
+StreamFile::GetFilePathname ()
+{
+    if (m_path_name.size() == 0)
+        return NULL;
+    else
+        return m_path_name.c_str();
+}
diff --git a/source/Core/StreamString.cpp b/source/Core/StreamString.cpp
new file mode 100644
index 0000000..ccd9f97
--- /dev/null
+++ b/source/Core/StreamString.cpp
@@ -0,0 +1,81 @@
+//===-- StreamString.cpp ----------------------------------------*- 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/StreamString.h"
+//#include <libkern/OSByteOrder.h>
+
+using namespace lldb;
+using namespace lldb_private;
+
+StreamString::StreamString () :
+    Stream (0, 4, eByteOrderBig)
+{
+}
+
+StreamString::StreamString(uint32_t flags, uint32_t addr_size, ByteOrder byte_order) :
+    Stream (flags, addr_size, byte_order),
+    m_packet ()
+{
+}
+
+StreamString::~StreamString()
+{
+}
+
+void
+StreamString::Flush ()
+{
+    // Nothing to do when flushing a buffer based stream...
+}
+
+int
+StreamString::Write (const void *s, size_t length)
+{
+    m_packet.append ((char *)s, length);
+    return length;
+}
+
+void
+StreamString::Clear()
+{
+    m_packet.clear();
+}
+
+void
+StreamString::Dump(FILE *f)
+{
+    int size = GetSize();
+    if (size > 0)
+        fprintf(f, "%*.*s", size, size, m_packet.c_str());
+}
+
+const char *
+StreamString::GetData () const
+{
+    return m_packet.c_str();
+}
+
+size_t
+StreamString::GetSize () const
+{
+    return m_packet.size();
+}
+
+std::string &
+StreamString::GetString()
+{
+    return m_packet;
+}
+
+const std::string &
+StreamString::GetString() const
+{
+    return m_packet;
+}
+
diff --git a/source/Core/StringList.cpp b/source/Core/StringList.cpp
new file mode 100644
index 0000000..cb96fb0
--- /dev/null
+++ b/source/Core/StringList.cpp
@@ -0,0 +1,200 @@
+//===-- StringList.cpp ------------------------------------------*- 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/StringList.h"
+
+#include <string>
+
+using namespace lldb_private;
+
+StringList::StringList () :
+    m_strings ()
+{
+}
+
+StringList::StringList (const char *str) :
+    m_strings ()
+{
+    if (str)
+        m_strings.push_back (str);
+}
+
+StringList::StringList (const char **strv, int strc) :
+    m_strings ()
+{
+    for (int i = 0; i < strc; ++i)
+    {
+        if (strv[i])
+            m_strings.push_back (strv[i]);
+    }
+}
+
+StringList::~StringList ()
+{
+}
+
+void
+StringList::AppendString (const char *str)
+{
+    if (str)
+        m_strings.push_back (str);
+}
+
+void
+StringList::AppendString (const char *str, size_t str_len)
+{
+    if (str)
+        m_strings.push_back (std::string (str, str_len));
+}
+
+void
+StringList::AppendList (const char **strv, int strc)
+{
+    for (int i = 0; i < strc; ++i)
+    {
+        if (strv[i])
+            m_strings.push_back (strv[i]);
+    }
+}
+
+void
+StringList::AppendList (StringList strings)
+{
+    uint32_t len = strings.GetSize();
+
+    for (int i = 0; i < len; ++i)
+        m_strings.push_back (strings.GetStringAtIndex(i));
+}
+
+uint32_t
+StringList::GetSize ()
+{
+    return m_strings.size();
+}
+
+const char *
+StringList::GetStringAtIndex (size_t idx)
+{
+    if (idx < m_strings.size())
+        return m_strings[idx].c_str();
+    return NULL;
+}
+
+void
+StringList::Clear ()
+{
+    m_strings.clear();
+}
+
+void
+StringList::LongestCommonPrefix (std::string &common_prefix)
+{
+    //arg_sstr_collection::iterator pos, end = m_args.end();
+    int pos = 0;
+    int end = m_strings.size();
+
+    if (pos == end)
+        common_prefix.clear();
+    else
+        common_prefix = m_strings[pos];
+
+    for (++pos; pos != end; ++pos)
+    {
+        int new_size = strlen (m_strings[pos].c_str());
+
+        // First trim common_prefix if it is longer than the current element:
+        if (common_prefix.size() > new_size)
+            common_prefix.erase (new_size);
+
+        // Then trim it at the first disparity:
+
+        for (int i = 0; i < common_prefix.size(); i++)
+        {
+            if (m_strings[pos][i]  != common_prefix[i])
+            {
+                common_prefix.erase(i);
+                break;
+            }
+        }
+
+        // If we've emptied the common prefix, we're done.
+        if (common_prefix.empty())
+            break;
+    }
+}
+
+void
+StringList::InsertStringAtIndex (size_t idx, const char *str)
+{
+    if (str)
+    {
+        if (idx < m_strings.size())
+            m_strings.insert (m_strings.begin() + idx, str);
+        else
+            m_strings.push_back (str);
+    }
+}
+
+void
+StringList::DeleteStringAtIndex (size_t idx)
+{
+    if (idx < m_strings.size())
+        m_strings.erase (m_strings.begin() + idx);
+}
+
+size_t
+StringList::SplitIntoLines (const char *lines, size_t len)
+{
+    const size_t orig_size = m_strings.size();
+
+    if (len == 0)
+        return 0;
+
+    const char *k_newline_chars = "\r\n";
+    const char *p = lines;
+    const char *end = lines + len;
+    while (p < end)
+    {
+        size_t count = strcspn (p, k_newline_chars);
+        if (count == 0)
+        {
+            if (p[count] == '\r' || p[count] == '\n')
+                m_strings.push_back(std::string());
+            else
+                break;
+        }
+        else
+        {
+            if (p + count > end)
+                count = end - p;
+            m_strings.push_back(std::string(p, count));
+        }
+        if (p[count] == '\r' && p[count+1] == '\n')
+            count++;    // Skip an extra newline char for the DOS newline
+        count++;    // Skip the newline character
+        p += count;
+    }
+    return m_strings.size() - orig_size;
+}
+
+void
+StringList::RemoveBlankLines ()
+{
+    if (GetSize() == 0)
+        return;
+
+    int idx = 0;
+    while (idx < m_strings.size())
+    {
+        if (m_strings[idx].empty())            
+            DeleteStringAtIndex(idx);
+        else
+            idx++;
+    }
+}
diff --git a/source/Core/TTYState.cpp b/source/Core/TTYState.cpp
new file mode 100644
index 0000000..6ba4158
--- /dev/null
+++ b/source/Core/TTYState.cpp
@@ -0,0 +1,203 @@
+//===-- TTYState.cpp --------------------------------------------*- 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/TTYState.h"
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/signal.h>
+
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Default constructor
+//----------------------------------------------------------------------
+TTYState::TTYState() :
+    m_fd(-1),
+    m_tflags(-1),
+    m_ttystate_err(-1),
+    m_ttystate(),
+    m_process_group(-1)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+TTYState::~TTYState()
+{
+}
+
+//----------------------------------------------------------------------
+// Save the current state of the TTY for the file descriptor "fd"
+// and if "save_process_group" is true, attempt to save the process
+// group info for the TTY.
+//----------------------------------------------------------------------
+bool
+TTYState::Save (int fd, bool save_process_group)
+{
+    if (fd >= 0 && ::isatty (fd))
+    {
+        m_fd = fd;
+        m_tflags = ::fcntl (fd, F_GETFL, 0);
+        m_ttystate_err = ::tcgetattr (fd, &m_ttystate);
+        if (save_process_group)
+            m_process_group = ::tcgetpgrp (0);
+        else
+            m_process_group = -1;
+    }
+    else
+    {
+        m_fd = -1;
+        m_tflags = -1;
+        m_ttystate_err = -1;
+        m_process_group = -1;
+    }
+    return m_ttystate_err == 0;
+}
+
+//----------------------------------------------------------------------
+// Restore the state of the TTY using the cached values from a
+// previous call to Save().
+//----------------------------------------------------------------------
+bool
+TTYState::Restore () const
+{
+    int result = 0;
+    if (IsValid())
+    {
+        if (TFlagsIsValid())
+            result = fcntl (m_fd, F_SETFL, m_tflags);
+
+        if (TTYStateIsValid())
+            result = tcsetattr (m_fd, TCSANOW, &m_ttystate);
+
+        if (ProcessGroupIsValid())
+        {
+            // Save the original signal handler.
+            void (*saved_sigttou_callback) (int) = NULL;
+            saved_sigttou_callback = (void (*)(int)) signal (SIGTTOU, SIG_IGN);
+            // Set the process group
+            result = tcsetpgrp (m_fd, m_process_group);
+            // Restore the original signal handler.
+            signal (SIGTTOU, saved_sigttou_callback);
+        }
+        return true;
+    }
+    return false;
+}
+
+
+
+
+//----------------------------------------------------------------------
+// Returns true if this object has valid saved TTY state settings
+// that can be used to restore a previous state.
+//----------------------------------------------------------------------
+bool
+TTYState::IsValid() const
+{
+    return (m_fd >= 0) && (TFlagsIsValid() || TTYStateIsValid());
+}
+
+//----------------------------------------------------------------------
+// Returns true if m_tflags is valid
+//----------------------------------------------------------------------
+bool
+TTYState::TFlagsIsValid() const
+{
+    return m_tflags != -1;
+}
+
+//----------------------------------------------------------------------
+// Returns true if m_ttystate is valid
+//----------------------------------------------------------------------
+bool
+TTYState::TTYStateIsValid() const
+{
+    return m_ttystate_err == 0;
+}
+
+//----------------------------------------------------------------------
+// Returns true if m_process_group is valid
+//----------------------------------------------------------------------
+bool
+TTYState::ProcessGroupIsValid() const
+{
+    return m_process_group != -1;
+}
+
+//------------------------------------------------------------------
+// Constructor
+//------------------------------------------------------------------
+TTYStateSwitcher::TTYStateSwitcher () :
+    m_currentState(UINT32_MAX)
+{
+}
+
+//------------------------------------------------------------------
+// Destructor
+//------------------------------------------------------------------
+TTYStateSwitcher::~TTYStateSwitcher ()
+{
+}
+
+//------------------------------------------------------------------
+// Returns the number of states that this switcher contains
+//------------------------------------------------------------------
+uint32_t
+TTYStateSwitcher::GetNumberOfStates() const
+{
+    return sizeof(m_ttystates)/sizeof(TTYState);
+}
+
+//------------------------------------------------------------------
+// Restore the state at index "idx".
+//
+// Returns true if the restore was successful, false otherwise.
+//------------------------------------------------------------------
+bool
+TTYStateSwitcher::Restore (uint32_t idx) const
+{
+    const uint32_t num_states = GetNumberOfStates();
+    if (idx >= num_states)
+        return false;
+
+    // See if we already are in this state?
+    if (m_currentState < num_states && (idx == m_currentState) && m_ttystates[idx].IsValid())
+        return true;
+
+    // Set the state to match the index passed in and only update the
+    // current state if there are no errors.
+    if (m_ttystates[idx].Restore())
+    {
+        m_currentState = idx;
+        return true;
+    }
+
+    // We failed to set the state. The tty state was invalid or not
+    // initialized.
+    return false;
+}
+
+//------------------------------------------------------------------
+// Save the state at index "idx" for file descriptor "fd" and
+// save the process group if requested.
+//
+// Returns true if the restore was successful, false otherwise.
+//------------------------------------------------------------------
+bool
+TTYStateSwitcher::Save (uint32_t idx, int fd, bool save_process_group)
+{
+    const uint32_t num_states = GetNumberOfStates();
+    if (idx < num_states)
+        return m_ttystates[idx].Save(fd, save_process_group);
+    return false;
+}
+
+
diff --git a/source/Core/Timer.cpp b/source/Core/Timer.cpp
new file mode 100644
index 0000000..e0d3bab
--- /dev/null
+++ b/source/Core/Timer.cpp
@@ -0,0 +1,235 @@
+//===-- Timer.cpp -----------------------------------------------*- 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/Timer.h"
+
+#include <map>
+#include <vector>
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Host/Mutex.h"
+
+using namespace lldb_private;
+
+#define TIMER_INDENT_AMOUNT 2
+uint32_t Timer::g_depth = 0;
+uint32_t Timer::g_display_depth = 0;
+FILE * Timer::g_file = NULL;
+typedef std::vector<Timer *> TimerStack;
+typedef std::map<const char *, uint64_t> CategoryMap;
+static pthread_key_t g_key;
+
+
+static Mutex &
+GetCategoryMutex()
+{
+    static Mutex g_category_mutex(Mutex::eMutexTypeNormal);
+    return g_category_mutex;
+}
+
+static CategoryMap &
+GetCategoryMap()
+{
+    static CategoryMap g_category_map;
+    return g_category_map;
+}
+
+
+static TimerStack *
+GetTimerStackForCurrentThread ()
+{
+    void *timer_stack = ::pthread_getspecific (g_key);
+    if (timer_stack == NULL)
+    {
+        ::pthread_setspecific (g_key, new TimerStack);
+        timer_stack = ::pthread_getspecific (g_key);
+    }
+    return (TimerStack *)timer_stack;
+}
+
+void
+ThreadSpecificCleanup (void *p)
+{
+    delete (TimerStack *)p;
+}
+
+void
+Timer::Initialize ()
+{
+    Timer::g_file = stdout;
+    ::pthread_key_create (&g_key, ThreadSpecificCleanup);
+
+}
+
+Timer::Timer (const char *category, const char *format, ...) :
+    m_category (category),
+    m_total_start (),
+    m_timer_start (),
+    m_total_ticks (0),
+    m_timer_ticks (0)
+{
+    if (g_depth++ < g_display_depth)
+    {
+        // Indent
+        ::fprintf (g_file, "%*s", g_depth * TIMER_INDENT_AMOUNT, "");
+        // Print formatted string
+        va_list args;
+        va_start (args, format);
+        ::vfprintf (g_file, format, args);
+        va_end (args);
+
+        // Newline
+        ::fprintf (g_file, "\n");
+        TimeValue start_time(TimeValue::Now());
+        m_total_start = start_time;
+        m_timer_start = start_time;
+        TimerStack *stack = GetTimerStackForCurrentThread ();
+        if (stack)
+        {
+            if (stack->empty() == false)
+                stack->back()->ChildStarted (start_time);
+            stack->push_back(this);
+        }
+    }
+}
+
+
+Timer::~Timer()
+{
+    if (m_total_start.IsValid())
+    {
+        TimeValue stop_time = TimeValue::Now();
+        bool notify = false;
+        if (m_total_start.IsValid())
+        {
+            m_total_ticks += (stop_time - m_total_start);
+            m_total_start.Clear();
+            notify = true;
+        }
+        if (m_timer_start.IsValid())
+        {
+            m_timer_ticks += (stop_time - m_timer_start);
+            m_timer_start.Clear();
+        }
+
+        TimerStack *stack = GetTimerStackForCurrentThread ();
+        if (stack)
+        {
+            assert (stack->back() == this);
+            stack->pop_back();
+            if (stack->empty() == false)
+                stack->back()->ChildStopped(stop_time);
+        }
+
+        const uint64_t total_nsec_uint = GetTotalElapsedNanoSeconds();
+        const uint64_t timer_nsec_uint = GetTimerElapsedNanoSeconds();
+        const double total_nsec = total_nsec_uint;
+        const double timer_nsec = timer_nsec_uint;
+        ::fprintf (g_file,
+                   "%*s%.9f sec (%.9f sec)\n",
+                   (g_depth - 1) *TIMER_INDENT_AMOUNT, "",
+                   total_nsec / 1000000000.0,
+                   timer_nsec / 1000000000.0);
+
+        // Keep total results for each category so we can dump results.
+        Mutex::Locker locker (GetCategoryMutex());
+        CategoryMap &category_map = GetCategoryMap();
+        category_map[m_category] += timer_nsec_uint;
+    }
+    if (g_depth > 0)
+        --g_depth;
+}
+
+uint64_t
+Timer::GetTotalElapsedNanoSeconds()
+{
+    uint64_t total_ticks = m_total_ticks;
+
+    // If we are currently running, we need to add the current
+    // elapsed time of the running timer...
+    if (m_total_start.IsValid())
+        total_ticks += (TimeValue::Now() - m_total_start);
+
+    return total_ticks;
+}
+
+uint64_t
+Timer::GetTimerElapsedNanoSeconds()
+{
+    uint64_t timer_ticks = m_timer_ticks;
+
+    // If we are currently running, we need to add the current
+    // elapsed time of the running timer...
+    if (m_timer_start.IsValid())
+        timer_ticks += (TimeValue::Now() - m_timer_start);
+
+    return timer_ticks;
+}
+
+void
+Timer::ChildStarted (const TimeValue& start_time)
+{
+    if (m_timer_start.IsValid())
+    {
+        m_timer_ticks += (start_time - m_timer_start);
+        m_timer_start.Clear();
+    }
+}
+
+void
+Timer::ChildStopped (const TimeValue& stop_time)
+{
+    if (!m_timer_start.IsValid())
+        m_timer_start = stop_time;
+}
+
+void
+Timer::SetDisplayDepth (uint32_t depth)
+{
+    g_display_depth = depth;
+}
+
+
+/* binary function predicate:
+ * - returns whether a person is less than another person
+ */
+static bool
+CategoryMapIteratorSortCriterion (const CategoryMap::const_iterator& lhs, const CategoryMap::const_iterator& rhs)
+{
+    return lhs->second > rhs->second;
+}
+
+
+void
+Timer::ResetCategoryTimes ()
+{
+    Mutex::Locker locker (GetCategoryMutex());
+    CategoryMap &category_map = GetCategoryMap();
+    category_map.clear();
+}
+
+void
+Timer::DumpCategoryTimes (Stream *s)
+{
+    Mutex::Locker locker (GetCategoryMutex());
+    CategoryMap &category_map = GetCategoryMap();
+    std::vector<CategoryMap::const_iterator> sorted_iterators;
+    CategoryMap::const_iterator pos, end = category_map.end();
+    for (pos = category_map.begin(); pos != end; ++pos)
+    {
+        sorted_iterators.push_back (pos);
+    }
+    std::sort (sorted_iterators.begin(), sorted_iterators.end(), CategoryMapIteratorSortCriterion);
+
+    const size_t count = sorted_iterators.size();
+    for (size_t i=0; i<count; ++i)
+    {
+        const double timer_nsec = sorted_iterators[i]->second;
+        s->Printf("%.9f sec for %s\n", timer_nsec / 1000000000.0, sorted_iterators[i]->first);
+    }
+}
\ No newline at end of file
diff --git a/source/Core/UUID.cpp b/source/Core/UUID.cpp
new file mode 100644
index 0000000..1ccfdcc
--- /dev/null
+++ b/source/Core/UUID.cpp
@@ -0,0 +1,218 @@
+//===-- UUID.cpp ------------------------------------------------*- 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/UUID.h"
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Stream.h"
+
+using namespace lldb_private;
+
+UUID::UUID()
+{
+    ::bzero (m_uuid, sizeof(m_uuid));
+}
+
+UUID::UUID(const UUID& rhs)
+{
+    ::memcpy (m_uuid, rhs.m_uuid, sizeof (m_uuid));
+}
+
+UUID::UUID (const void *uuid_bytes, uint32_t num_uuid_bytes)
+{
+    if (uuid_bytes && num_uuid_bytes >= 16)
+        ::memcpy (m_uuid, uuid_bytes, sizeof (m_uuid));
+    else
+        ::bzero (m_uuid, sizeof(m_uuid));
+}
+
+UUID::UUID (const uuid_t *uuid)
+{
+    if (uuid)
+        ::memcpy (m_uuid, uuid, sizeof (m_uuid));
+    else
+        ::bzero (m_uuid, sizeof(m_uuid));
+}
+
+const UUID&
+UUID::operator=(const UUID& rhs)
+{
+    if (this != &rhs)
+        ::memcpy (m_uuid, rhs.m_uuid, sizeof (m_uuid));
+    return *this;
+}
+
+UUID::~UUID()
+{
+}
+
+void
+UUID::Clear()
+{
+    ::bzero (m_uuid, sizeof(m_uuid));
+}
+
+const void *
+UUID::GetBytes() const
+{
+    return m_uuid;
+}
+
+char *
+UUID::GetAsCString (char *dst, size_t dst_len) const
+{
+    const uint8_t *u = (const uint8_t *)GetBytes();
+    snprintf(dst, dst_len, "%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
+             u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7],u[8],u[9],u[10],u[11],u[12],u[13],u[14],u[15]);
+    return dst;
+}
+
+void
+UUID::Dump (Stream *s) const
+{
+    const uint8_t *u = (const uint8_t *)GetBytes();
+    s->Printf ("%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
+              u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7],u[8],u[9],u[10],u[11],u[12],u[13],u[14],u[15]);
+}
+
+void
+UUID::SetBytes (const void *uuid_bytes)
+{
+    if (uuid_bytes)
+        ::memcpy (m_uuid, uuid_bytes, sizeof (m_uuid));
+    else
+        ::bzero (m_uuid, sizeof(m_uuid));
+}
+
+size_t
+UUID::GetByteSize()
+{
+    return sizeof(UUID::ValueType);
+}
+
+bool
+UUID::IsValid () const
+{
+    return  m_uuid[0]  ||
+            m_uuid[1]  ||
+            m_uuid[2]  ||
+            m_uuid[3]  ||
+            m_uuid[4]  ||
+            m_uuid[5]  ||
+            m_uuid[6]  ||
+            m_uuid[7]  ||
+            m_uuid[8]  ||
+            m_uuid[9]  ||
+            m_uuid[10] ||
+            m_uuid[11] ||
+            m_uuid[12] ||
+            m_uuid[13] ||
+            m_uuid[14] ||
+            m_uuid[15];
+}
+
+static inline int
+xdigit_to_int (char ch)
+{
+    ch = tolower(ch);
+    if (ch >= 'a' && ch <= 'f')
+        return 10 + ch - 'a';
+    return ch - '0';
+}
+
+size_t
+UUID::SetfromCString (const char *cstr)
+{
+    if (cstr == NULL)
+        return 0;
+
+    uint32_t uuid_byte_idx = 0;
+    const char *p = cstr;
+
+    // Skip leading whitespace characters
+    while (isspace(*p))
+        ++p;
+
+    // Try and decode a UUID
+    while (*p != '\0')
+    {
+        if (isxdigit(*p) && isxdigit(p[1]))
+        {
+            int hi_nibble = xdigit_to_int(p[0]);
+            int lo_nibble = xdigit_to_int(p[1]);
+            // Translate the two hex nibble characters into a byte
+            m_uuid[uuid_byte_idx] = (hi_nibble << 4) + lo_nibble;
+
+            // Skip both hex digits
+            p += 2;
+
+            // Increment the byte that we are decoding within the UUID value
+            // and break out if we are done
+            if (++uuid_byte_idx == 16)
+                break;
+        }
+        else if (*p == '-')
+        {
+            // Skip dashes
+            p++;
+        }
+        else
+        {
+            // UUID values can only consist of hex characters and '-' chars
+            return 0;
+        }
+    }
+    // If we successfully decoded a UUID, return the amount of characters that
+    // were consumed
+    if (uuid_byte_idx == 16)
+        return p - cstr;
+
+    // Else return zero to indicate we were not able to parse a UUID value
+    return 0;
+}
+
+
+
+bool
+lldb_private::operator == (const UUID &lhs, const UUID &rhs)
+{
+    return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), UUID::GetByteSize()) == 0;
+}
+
+bool
+lldb_private::operator != (const UUID &lhs, const UUID &rhs)
+{
+    return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), UUID::GetByteSize()) != 0;
+}
+
+bool
+lldb_private::operator <  (const UUID &lhs, const UUID &rhs)
+{
+    return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), UUID::GetByteSize()) <  0;
+}
+
+bool
+lldb_private::operator <= (const UUID &lhs, const UUID &rhs)
+{
+    return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), UUID::GetByteSize()) <= 0;
+}
+
+bool
+lldb_private::operator >  (const UUID &lhs, const UUID &rhs)
+{
+    return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), UUID::GetByteSize()) >  0;
+}
+
+bool
+lldb_private::operator >= (const UUID &lhs, const UUID &rhs)
+{
+    return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), UUID::GetByteSize()) >= 0;
+}
diff --git a/source/Core/UserID.cpp b/source/Core/UserID.cpp
new file mode 100644
index 0000000..b1dd5a6
--- /dev/null
+++ b/source/Core/UserID.cpp
@@ -0,0 +1,73 @@
+//===-- UserID.cpp ----------------------------------------------*- 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/UserID.h"
+#include "lldb/Core/Stream.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+UserID::UserID (user_id_t uid) :
+    m_uid(uid)
+{
+}
+
+UserID::~UserID ()
+{
+}
+
+void
+UserID::Clear ()
+{
+    m_uid = LLDB_INVALID_UID;
+}
+
+
+user_id_t
+UserID::GetID () const
+{
+    return m_uid;
+}
+
+void
+UserID::SetID (user_id_t uid)
+{
+    m_uid = uid;
+}
+
+UserID::IDMatches::IDMatches (user_id_t uid) :
+    m_uid(uid)
+{
+}
+
+bool
+UserID::IDMatches::operator() (const UserID& rhs) const
+{
+    return m_uid == rhs.GetID();
+}
+
+Stream&
+lldb_private::operator << (Stream& strm, const UserID& uid)
+{
+    strm.Printf("{0x%8.8x}", uid.GetID());
+    return strm;
+}
+
+bool
+lldb_private::operator== (const UserID& lhs, const UserID& rhs)
+{
+    return lhs.GetID() == rhs.GetID();
+}
+
+bool
+lldb_private::operator!= (const UserID& lhs, const UserID& rhs)
+{
+    return lhs.GetID() != rhs.GetID();
+}
+
diff --git a/source/Core/VMRange.cpp b/source/Core/VMRange.cpp
new file mode 100644
index 0000000..2f5d8ec
--- /dev/null
+++ b/source/Core/VMRange.cpp
@@ -0,0 +1,100 @@
+//===-- VMRange.cpp ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-private.h"
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/VMRange.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+bool
+VMRange::ContainsValue(const VMRange::collection& coll, lldb::addr_t value)
+{
+    ValueInRangeUnaryPredicate in_range_predicate(value);
+    VMRange::const_iterator pos;
+    VMRange::const_iterator end = coll.end();
+    pos = std::find_if( coll.begin(), end, in_range_predicate );
+    if (pos != end)
+        return true;
+    return false;
+}
+
+bool
+VMRange::ContainsRange(const VMRange::collection& coll, const VMRange& range)
+{
+    RangeInRangeUnaryPredicate in_range_predicate(range);
+    VMRange::const_iterator pos;
+    VMRange::const_iterator end = coll.end();
+    pos = std::find_if( coll.begin(), end, in_range_predicate );
+    if (pos != end)
+        return true;
+    return false;
+}
+
+
+void
+VMRange::Dump(Stream *s, lldb::addr_t offset) const
+{
+    s->AddressRange(offset + GetBaseAddress(), offset + GetEndAddress(), sizeof (addr_t));
+}
+
+bool
+lldb_private::operator== (const VMRange& lhs, const VMRange& rhs)
+{
+    return lhs.GetBaseAddress() == rhs.GetBaseAddress() && lhs.GetEndAddress() == rhs.GetEndAddress();
+}
+
+bool
+lldb_private::operator!= (const VMRange& lhs, const VMRange& rhs)
+{
+    return lhs.GetBaseAddress() != rhs.GetBaseAddress() || lhs.GetEndAddress() != rhs.GetEndAddress();
+}
+
+bool
+lldb_private::operator< (const VMRange& lhs, const VMRange& rhs)
+{
+    if (lhs.GetBaseAddress() < rhs.GetBaseAddress())
+        return true;
+    else if (lhs.GetBaseAddress() > rhs.GetBaseAddress())
+        return false;
+    return lhs.GetEndAddress() < rhs.GetEndAddress();
+}
+
+bool
+lldb_private::operator<= (const VMRange& lhs, const VMRange& rhs)
+{
+    if (lhs.GetBaseAddress() < rhs.GetBaseAddress())
+        return true;
+    else if (lhs.GetBaseAddress() > rhs.GetBaseAddress())
+        return false;
+    return lhs.GetEndAddress() <= rhs.GetEndAddress();
+}
+
+bool
+lldb_private::operator> (const VMRange& lhs, const VMRange& rhs)
+{
+    if (lhs.GetBaseAddress() > rhs.GetBaseAddress())
+        return true;
+    else if (lhs.GetBaseAddress() < rhs.GetBaseAddress())
+        return false;
+    return lhs.GetEndAddress() > rhs.GetEndAddress();
+}
+
+bool
+lldb_private::operator>= (const VMRange& lhs, const VMRange& rhs)
+{
+    if (lhs.GetBaseAddress() > rhs.GetBaseAddress())
+        return true;
+    else if (lhs.GetBaseAddress() < rhs.GetBaseAddress())
+        return false;
+    return lhs.GetEndAddress() >= rhs.GetEndAddress();
+}
+
diff --git a/source/Core/Value.cpp b/source/Core/Value.cpp
new file mode 100644
index 0000000..c4c17dd
--- /dev/null
+++ b/source/Core/Value.cpp
@@ -0,0 +1,803 @@
+//===-- Value.cpp -----------------------------------------------*- 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/Value.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/Variable.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+Value::Value() :
+    m_value(),
+    m_value_type(eValueTypeScalar),
+    m_context(NULL),
+    m_context_type(eContextTypeInvalid)
+{
+}
+
+Value::Value(const Scalar& scalar) :
+    m_value(scalar),
+    m_value_type(eValueTypeScalar),
+    m_context(NULL),
+    m_context_type(eContextTypeInvalid)
+{
+}
+
+Value::Value(int v) :
+    m_value(v),
+    m_value_type(eValueTypeScalar),
+    m_context(NULL),
+    m_context_type(eContextTypeInvalid)
+{
+}
+
+Value::Value(unsigned int v) :
+    m_value(v),
+    m_value_type(eValueTypeScalar),
+    m_context(NULL),
+    m_context_type(eContextTypeInvalid)
+{
+}
+
+Value::Value(long v) :
+    m_value(v),
+    m_value_type(eValueTypeScalar),
+    m_context(NULL),
+    m_context_type(eContextTypeInvalid)
+{
+}
+
+Value::Value(unsigned long v) :
+    m_value(v),
+    m_value_type(eValueTypeScalar),
+    m_context(NULL),
+    m_context_type(eContextTypeInvalid)
+{
+}
+
+Value::Value(long long v) :
+    m_value(v),
+    m_value_type(eValueTypeScalar),
+    m_context(NULL),
+    m_context_type(eContextTypeInvalid)
+{
+}
+
+Value::Value(unsigned long long v) :
+    m_value(v),
+    m_value_type(eValueTypeScalar),
+    m_context(NULL),
+    m_context_type(eContextTypeInvalid)
+{
+}
+
+Value::Value(float v) :
+    m_value(v),
+    m_value_type(eValueTypeScalar),
+    m_context(NULL),
+    m_context_type(eContextTypeInvalid)
+{
+}
+
+Value::Value(double v) :
+    m_value(v),
+    m_value_type(eValueTypeScalar),
+    m_context(NULL),
+    m_context_type(eContextTypeInvalid)
+{
+}
+
+Value::Value(long double v) :
+    m_value(v),
+    m_value_type(eValueTypeScalar),
+    m_context(NULL),
+    m_context_type(eContextTypeInvalid)
+{
+}
+
+Value::Value(const uint8_t *bytes, int len) :
+    m_value(),
+    m_value_type(eValueTypeHostAddress),
+    m_context(NULL),
+    m_context_type(eContextTypeInvalid)
+{
+    m_data_buffer.CopyData(bytes, len);
+    m_value = (uintptr_t)m_data_buffer.GetBytes();
+}
+
+Value::Value(const Value &v) :
+    m_value(v.m_value),
+    m_value_type(v.m_value_type),
+    m_context(v.m_context),
+    m_context_type(v.m_context_type)
+{
+    if ((uintptr_t)v.m_value.ULongLong(LLDB_INVALID_ADDRESS) == (uintptr_t)v.m_data_buffer.GetBytes())
+    {
+        m_data_buffer.CopyData(v.m_data_buffer.GetBytes(),
+                               v.m_data_buffer.GetByteSize());
+    
+        m_value = (uintptr_t)m_data_buffer.GetBytes();
+    }
+}
+
+Value *
+Value::CreateProxy()
+{
+    if (m_context_type == eContextTypeValue)
+        return ((Value*)m_context)->CreateProxy ();
+    
+    Value *ret = new Value;
+    ret->SetContext(eContextTypeValue, this);
+    return ret;
+}
+
+Value *
+Value::GetProxyTarget()
+{
+    if (m_context_type == eContextTypeValue)
+        return (Value*)m_context;
+    else
+        return NULL;
+}
+
+//#include "clang/Lex/LiteralSupport.h"
+//#include "clang/AST/ASTContext.h"
+//#include "clang/Frontend/CompilerInstance.h"
+//
+//Value::Value (const char *data, llvm::CompilerInstance *compiler)
+//{
+//    clang::NumericLiteralParser parser(data, data + strlen(data), clang::SourceLocation(),
+//                                compiler->getPreprocessor());
+//    if (parser.had_error)
+//    {
+//    }
+//    else if (parser.isBool)
+//    {
+//        APInt value;
+//        parser.GetIntegerValue(value);
+//    }
+//    else if (parser.isLong)
+//    {
+//    }
+//    else if (parser.isLongLong)
+//    {
+//    }
+//    else if (parser.isFloat)
+//    {
+//    }
+//
+//}
+//
+void
+Value::Dump (Stream* strm)
+{
+    if (m_context_type == eContextTypeValue)
+    {
+        ((Value*)m_context)->Dump (strm);
+        return;
+    }
+    
+    m_value.GetValue (strm, true);
+    strm->Printf(", value_type = %s, context = %p, context_type = %s",
+                Value::GetValueTypeAsCString(m_value_type),
+                m_context,
+                Value::GetContextTypeAsCString(m_context_type));
+}
+
+void *
+Value::GetOpaqueClangQualType()
+{
+    if (m_context_type == eContextTypeValue)
+        return ((Value*)m_context)->GetOpaqueClangQualType ();
+    
+    if (m_context_type == eContextTypeOpaqueClangQualType)
+        return m_context;
+    
+    return NULL;
+}
+
+Value::ValueType
+Value::GetValueType() const
+{
+    if (m_context_type == eContextTypeValue)
+        return ((Value*)m_context)->GetValueType ();
+    
+    return m_value_type;
+}
+
+lldb::AddressType
+Value::GetValueAddressType () const
+{
+    if (m_context_type == eContextTypeValue)
+        return ((Value*)m_context)->GetValueAddressType ();
+    
+    switch (m_value_type)
+    {
+    default:
+    case eValueTypeScalar:
+        break;
+    case eValueTypeLoadAddress: return eAddressTypeLoad;
+    case eValueTypeFileAddress: return eAddressTypeFile;
+    case eValueTypeHostAddress: return eAddressTypeHost;
+    }
+    return eAddressTypeInvalid;
+}
+
+
+Value::ContextType
+Value::GetContextType() const
+{
+    if (m_context_type == eContextTypeValue)
+        return ((Value*)m_context)->GetContextType ();
+    
+    return m_context_type;
+}
+
+void
+Value::SetValueType (Value::ValueType value_type)
+{
+    if (m_context_type == eContextTypeValue)
+    {
+        ((Value*)m_context)->SetValueType(value_type);
+        return;
+    }
+        
+    m_value_type = value_type;
+}
+
+void
+Value::ClearContext ()
+{
+    if (m_context_type == eContextTypeValue)
+    {
+        ((Value*)m_context)->ClearContext();
+        return;
+    }
+    
+    m_context = NULL;
+    m_context_type = eContextTypeInvalid;
+}
+
+void
+Value::SetContext (Value::ContextType context_type, void *p)
+{
+    if (m_context_type == eContextTypeValue)
+    {
+        ((Value*)m_context)->SetContext(context_type, p);
+        return;
+    }
+    
+    m_context_type = context_type;
+    m_context = p;
+}
+
+RegisterInfo *
+Value::GetRegisterInfo()
+{
+    if (m_context_type == eContextTypeValue)
+        return ((Value*)m_context)->GetRegisterInfo();
+        
+    if (m_context_type == eContextTypeDCRegisterInfo)
+        return static_cast<RegisterInfo *> (m_context);
+    return NULL;
+}
+
+Type *
+Value::GetType()
+{
+    if (m_context_type == eContextTypeValue)
+        return ((Value*)m_context)->GetType();
+    
+    if (m_context_type == eContextTypeDCType)
+        return static_cast<Type *> (m_context);
+    return NULL;
+}
+
+Scalar &
+Value::GetScalar()
+{
+    if (m_context_type == eContextTypeValue)
+        return ((Value*)m_context)->GetScalar();
+    
+    return m_value;
+}
+
+void
+Value::ResizeData(int len)
+{
+    if (m_context_type == eContextTypeValue)
+    {
+        ((Value*)m_context)->ResizeData(len);
+        return;
+    }
+    
+    m_value_type = eValueTypeHostAddress;
+    m_data_buffer.SetByteSize(len);
+    m_value = (uintptr_t)m_data_buffer.GetBytes();
+}
+
+bool
+Value::ValueOf(ExecutionContext *exe_ctx, clang::ASTContext *ast_context)
+{
+    if (m_context_type == eContextTypeValue)
+        return ((Value*)m_context)->ValueOf(exe_ctx, ast_context);
+    
+    switch (m_context_type)
+    {
+    default:
+    case eContextTypeInvalid:
+    case eContextTypeOpaqueClangQualType:          // clang::Type *
+    case eContextTypeDCRegisterInfo:     // RegisterInfo *
+    case eContextTypeDCType:             // Type *
+        break;
+
+    case eContextTypeDCVariable:         // Variable *
+        ResolveValue(exe_ctx, ast_context);
+        return true;
+    }
+    return false;
+}
+
+size_t
+Value::GetValueByteSize (clang::ASTContext *ast_context, Error *error_ptr)
+{
+    if (m_context_type == eContextTypeValue)
+        return ((Value*)m_context)->GetValueByteSize(ast_context, error_ptr);
+    
+    size_t byte_size = 0;
+
+    switch (m_context_type)
+    {
+    default:
+    case eContextTypeInvalid:
+        // If we have no context, there is no way to know how much memory to read
+        if (error_ptr)
+            error_ptr->SetErrorString ("Invalid context type, there is no way to know how much memory to read.");
+        break;
+
+    case eContextTypeOpaqueClangQualType:
+        if (ast_context == NULL)
+        {
+            if (error_ptr)
+                error_ptr->SetErrorString ("Can't determine size of opaque clang type with NULL ASTContext *.");
+        }
+        else
+        {
+            uint64_t bit_width = ClangASTContext::GetTypeBitSize (ast_context, m_context);
+            byte_size = (bit_width + 7 ) / 8;
+        }
+        break;
+
+    case eContextTypeDCRegisterInfo:     // RegisterInfo *
+        if (GetRegisterInfo())
+            byte_size = GetRegisterInfo()->byte_size;
+        else if (error_ptr)
+                error_ptr->SetErrorString ("Can't determine byte size with NULL RegisterInfo *.");
+
+        break;
+
+    case eContextTypeDCType:             // Type *
+        if (GetType())
+            byte_size = GetType()->GetByteSize();
+        else if (error_ptr)
+            error_ptr->SetErrorString ("Can't determine byte size with NULL Type *.");
+        break;
+
+    case eContextTypeDCVariable:         // Variable *
+        if (GetVariable())
+            byte_size = GetVariable()->GetType()->GetByteSize();
+        else if (error_ptr)
+            error_ptr->SetErrorString ("Can't determine byte size with NULL Variable *.");
+        break;
+    }
+
+    if (error_ptr)
+    {
+        if (byte_size == 0)
+        {
+            if (error_ptr->Success())
+                error_ptr->SetErrorString("Unable to determine byte size.");
+        }
+        else
+        {
+            error_ptr->Clear();
+        }
+    }
+    return byte_size;
+}
+
+void *
+Value::GetValueOpaqueClangQualType ()
+{
+    if (m_context_type == eContextTypeValue)
+        return ((Value*)m_context)->GetValueOpaqueClangQualType();
+    
+    switch (m_context_type)
+    {
+    default:
+    case eContextTypeInvalid:
+        break;
+
+    case eContextTypeOpaqueClangQualType:
+        return m_context;
+
+    case eContextTypeDCRegisterInfo:
+        break;    // TODO: Eventually convert into a clang type?
+
+    case eContextTypeDCType:
+        if (GetType())
+            return GetType()->GetOpaqueClangQualType();
+        break;
+
+    case eContextTypeDCVariable:
+        if (GetVariable())
+            return GetVariable()->GetType()->GetOpaqueClangQualType();
+        break;
+    }
+
+    return NULL;
+}
+
+lldb::Format
+Value::GetValueDefaultFormat ()
+{
+    if (m_context_type == eContextTypeValue)
+        return ((Value*)m_context)->GetValueDefaultFormat();
+    
+    switch (m_context_type)
+    {
+    default:
+    case eContextTypeInvalid:
+        break;
+
+    case eContextTypeOpaqueClangQualType:
+        return Type::GetFormat (m_context);
+
+    case eContextTypeDCRegisterInfo:
+        if (GetRegisterInfo())
+            return GetRegisterInfo()->format;
+        break;
+
+    case eContextTypeDCType:
+        if (GetType())
+            return GetType()->GetFormat();
+        break;
+
+    case eContextTypeDCVariable:
+        if (GetVariable())
+            return GetVariable()->GetType()->GetFormat();
+        break;
+
+    }
+
+    // Return a good default in case we can't figure anything out
+    return eFormatHex;
+}
+
+Error
+Value::GetValueAsData (ExecutionContext *exe_ctx, clang::ASTContext *ast_context, DataExtractor &data, uint32_t data_offset)
+{
+    if (m_context_type == eContextTypeValue)
+        return ((Value*)m_context)->GetValueAsData(exe_ctx, ast_context, data, data_offset);
+    
+    data.Clear();
+
+    Error error;
+    lldb::addr_t address = LLDB_INVALID_ADDRESS;
+    lldb::AddressType address_type = eAddressTypeFile;
+    switch (m_value_type)
+    {
+    default:
+        error.SetErrorStringWithFormat("Invalid value type %i.\n", m_value_type);
+        break;
+
+    case eValueTypeScalar:
+        data.SetByteOrder (eByteOrderHost);
+        data.SetAddressByteSize(sizeof(void *));
+        if (m_value.GetData (data))
+            return error;   // Success;
+        error.SetErrorStringWithFormat("Extracting data from value failed.\n");
+        break;
+
+    case eValueTypeLoadAddress:
+        if (exe_ctx == NULL)
+        {
+            error.SetErrorString ("Can't read memory (no execution context).");
+        }
+        else if (exe_ctx->process == NULL)
+        {
+            error.SetErrorString ("Can't read memory (invalid process).");
+        }
+        else
+        {
+            address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
+            address_type = eAddressTypeLoad;
+            data.SetByteOrder(exe_ctx->process->GetByteOrder());
+            data.SetAddressByteSize(exe_ctx->process->GetAddressByteSize());
+        }
+        break;
+
+    case eValueTypeFileAddress:
+        {
+            // The only thing we can currently lock down to a module so that
+            // we can resolve a file address, is a variable.
+            Variable *variable = GetVariable();
+
+            if (GetVariable())
+            {
+                lldb::addr_t file_addr = m_value.ULongLong(LLDB_INVALID_ADDRESS);
+                if (file_addr != LLDB_INVALID_ADDRESS)
+                {
+                    SymbolContext var_sc;
+                    variable->CalculateSymbolContext(&var_sc);
+                    if (var_sc.module_sp)
+                    {
+                        ObjectFile *objfile = var_sc.module_sp->GetObjectFile();
+                        if (objfile)
+                        {
+                            Address so_addr(file_addr, objfile->GetSectionList());
+                            address = so_addr.GetLoadAddress (exe_ctx->process);
+                            if (address != LLDB_INVALID_ADDRESS)
+                                address_type = eAddressTypeLoad;
+                        }
+                        if (address_type == eAddressTypeFile)
+                            error.SetErrorStringWithFormat ("%s is not loaded.\n", var_sc.module_sp->GetFileSpec().GetFilename().AsCString());
+                    }
+                    else
+                    {
+                        error.SetErrorStringWithFormat ("Unable to resolve the module for file address 0x%llx for variable '%s'.\n", file_addr, variable->GetName().AsCString(""));
+                    }
+                }
+                else
+                {
+                    error.SetErrorString ("Invalid file address.");
+                }
+            }
+            else
+            {
+                // Can't convert a file address to anything valid without more
+                // context (which Module it came from)
+                error.SetErrorString ("Can't read memory from file address without more context.");
+            }
+        }
+        break;
+
+    case eValueTypeHostAddress:
+        address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
+        data.SetByteOrder(eByteOrderHost);
+        data.SetAddressByteSize(sizeof(void *));
+        address_type = eAddressTypeHost;
+        break;
+    }
+
+    // Bail if we encountered any errors
+    if (error.Fail())
+        return error;
+
+    if (address == LLDB_INVALID_ADDRESS)
+    {
+        error.SetErrorStringWithFormat ("Invalid %s address.\n", address_type == eAddressTypeHost ? "host" : "load");
+        return error;
+    }
+
+    // If we got here, we need to read the value from memory
+    uint32_t byte_size = GetValueByteSize (ast_context, &error);
+
+    // Bail if we encountered any errors getting the byte size
+    if (error.Fail())
+        return error;
+
+    // Make sure we have enough room within "data", and if we don't make
+    // something large enough that does
+    if (!data.ValidOffsetForDataOfSize (data_offset, byte_size))
+    {
+        DataBufferSP data_sp(new DataBufferHeap (data_offset + byte_size, '\0'));
+        data.SetData(data_sp);
+    }
+
+    uint8_t* dst = (uint8_t*)data.PeekData (data_offset, byte_size);
+    if (dst != NULL)
+    {
+        if (address_type == eAddressTypeHost)
+        {
+            // The address is an address in this process, so just copy it
+            memcpy (dst, (uint8_t*)NULL + address, byte_size);
+        }
+        else if (address_type == eAddressTypeLoad)
+        {
+            if (exe_ctx->process->ReadMemory(address, dst, byte_size, error) != byte_size)
+            {
+                if (error.Success())
+                    error.SetErrorStringWithFormat("read %u bytes of memory from 0x%llx failed", (uint64_t)address, byte_size);
+            }
+        }
+        else
+        {
+            error.SetErrorStringWithFormat ("Unsupported lldb::AddressType value (%i).\n", address_type);
+        }
+    }
+    else
+    {
+        error.SetErrorStringWithFormat ("Out of memory.\n");
+    }
+
+    return error;
+}
+
+Scalar &
+Value::ResolveValue(ExecutionContext *exe_ctx, clang::ASTContext *ast_context)
+{    
+    Scalar scalar;
+    if (m_context_type == eContextTypeValue)
+    {
+        // Resolve the proxy
+        
+        Value * v = (Value*)m_context;
+        
+        m_value = v->m_value;
+        m_value_type = v->m_value_type;
+        m_context = v->m_context;
+        m_context_type = v->m_context_type;
+        
+        if ((uintptr_t)v->m_value.ULongLong(LLDB_INVALID_ADDRESS) == (uintptr_t)v->m_data_buffer.GetBytes())
+        {
+            m_data_buffer.CopyData(v->m_data_buffer.GetBytes(),
+                                   v->m_data_buffer.GetByteSize());
+            
+            m_value = (uintptr_t)m_data_buffer.GetBytes();
+        }
+    }
+    
+    if (m_context_type == eContextTypeOpaqueClangQualType)
+    {
+        void *opaque_clang_qual_type = GetOpaqueClangQualType();
+        switch (m_value_type)
+        {
+        case eValueTypeScalar:               // raw scalar value
+            break;
+
+        default:
+        case eValueTypeFileAddress:
+            m_value.Clear();
+            break;
+
+        case eValueTypeLoadAddress:          // load address value
+        case eValueTypeHostAddress:          // host address value (for memory in the process that is using liblldb)
+            {
+                lldb::AddressType address_type = m_value_type == eValueTypeLoadAddress ? eAddressTypeLoad : eAddressTypeHost;
+                lldb::addr_t addr = m_value.ULongLong(LLDB_INVALID_ADDRESS);
+                DataExtractor data;
+                if (Type::ReadFromMemory (exe_ctx, ast_context, opaque_clang_qual_type, addr, address_type, data))
+                {
+                    if (Type::GetValueAsScalar (ast_context, opaque_clang_qual_type, data, 0, data.GetByteSize(), scalar))
+                    {
+                        m_value = scalar;
+                        m_value_type = eValueTypeScalar;
+                    }
+                    else
+                    {
+                        if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes())
+                        {
+                            m_value.Clear();
+                            m_value_type = eValueTypeScalar;
+                        }
+                    }
+                }
+                else
+                {
+                    if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes())
+                    {
+                        m_value.Clear();
+                        m_value_type = eValueTypeScalar;
+                    }
+                }
+            }
+            break;
+        }
+
+
+    }
+    return m_value;
+}
+
+Variable *
+Value::GetVariable()
+{
+    if (m_context_type == eContextTypeValue)
+        return ((Value*)m_context)->GetVariable();
+    
+    if (m_context_type == eContextTypeDCVariable)
+        return static_cast<Variable *> (m_context);
+    return NULL;
+}
+
+
+
+const char *
+Value::GetValueTypeAsCString (ValueType value_type)
+{    
+    switch (value_type)
+    {
+    case eValueTypeScalar:      return "scalar";
+    case eValueTypeFileAddress: return "file address";
+    case eValueTypeLoadAddress: return "load address";
+    case eValueTypeHostAddress: return "host address";
+    };
+    return "???";
+}
+
+const char *
+Value::GetContextTypeAsCString (ContextType context_type)
+{
+    switch (context_type)
+    {
+    case eContextTypeInvalid:               return "invalid";
+    case eContextTypeOpaqueClangQualType:   return "clang::Type *";
+    case eContextTypeDCRegisterInfo:        return "RegisterInfo *";
+    case eContextTypeDCType:                return "Type *";
+    case eContextTypeDCVariable:            return "Variable *";
+    };
+    return "???";
+}
+
+ValueList::ValueList (const ValueList &rhs)
+{
+    m_values = rhs.m_values;
+}
+
+const ValueList &
+ValueList::operator= (const ValueList &rhs)
+{
+    m_values = rhs.m_values;
+    return *this;
+}
+
+void
+ValueList::PushValue (const Value &value)
+{
+    m_values.push_back (value);
+}
+
+size_t
+ValueList::GetSize()
+{
+    return m_values.size();
+}
+
+Value *
+ValueList::GetValueAtIndex (size_t idx)
+{
+    if (idx < GetSize())
+    {
+        return &(m_values[idx]);
+    }
+    else
+        return NULL;
+}
+
+void
+ValueList::Clear ()
+{
+    m_values.clear();
+}
diff --git a/source/Core/ValueObject.cpp b/source/Core/ValueObject.cpp
new file mode 100644
index 0000000..93511fe
--- /dev/null
+++ b/source/Core/ValueObject.cpp
@@ -0,0 +1,678 @@
+//===-- ValueObject.cpp -----------------------------------------*- 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/ValueObject.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "clang/AST/Type.h"
+#include "llvm/Support/raw_ostream.h"
+
+// Project includes
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObjectChild.h"
+#include "lldb/Core/ValueObjectList.h"
+
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/Type.h"
+
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static lldb::user_id_t g_value_obj_uid = 0;
+
+//----------------------------------------------------------------------
+// ValueObject constructor
+//----------------------------------------------------------------------
+ValueObject::ValueObject () :
+    UserID (++g_value_obj_uid), // Unique identifier for every value object
+    m_update_id (0),    // Value object lists always start at 1, value objects start at zero
+    m_name (),
+    m_data (),
+    m_value (),
+    m_error (),
+    m_flags (),
+    m_value_str(),
+    m_location_str(),
+    m_summary_str(),
+    m_children(),
+    m_synthetic_children()
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ValueObject::~ValueObject ()
+{
+}
+
+user_id_t
+ValueObject::GetUpdateID() const
+{
+    return m_update_id;
+}
+
+bool
+ValueObject::UpdateValueIfNeeded (ExecutionContextScope *exe_scope)
+{
+    if (exe_scope)
+    {
+        Process *process = exe_scope->CalculateProcess();
+        if (process)
+        {
+            const user_id_t stop_id = process->GetStopID();
+            if (m_update_id != stop_id)
+            {
+                m_value_str.clear();
+                m_location_str.clear();
+                m_summary_str.clear();
+
+                UpdateValue (exe_scope);
+                if (m_error.Success())
+                    m_update_id = stop_id;
+            }
+        }
+    }
+    return m_error.Success();
+}
+
+const DataExtractor &
+ValueObject::GetDataExtractor () const
+{
+    return m_data;
+}
+
+DataExtractor &
+ValueObject::GetDataExtractor ()
+{
+    return m_data;
+}
+
+const Error &
+ValueObject::GetError() const
+{
+    return m_error;
+}
+
+const ConstString &
+ValueObject::GetName() const
+{
+    return m_name;
+}
+
+const char *
+ValueObject::GetLocationAsCString (ExecutionContextScope *exe_scope)
+{
+    if (UpdateValueIfNeeded(exe_scope))
+    {
+        if (m_location_str.empty())
+        {
+            StreamString sstr;
+
+            switch (m_value.GetValueType())
+            {
+            default:
+                break;
+
+            case Value::eValueTypeScalar:
+                if (m_value.GetContextType() == Value::eContextTypeDCRegisterInfo)
+                {
+                    RegisterInfo *reg_info = m_value.GetRegisterInfo();
+                    if (reg_info)
+                    {
+                        if (reg_info->name)
+                            m_location_str = reg_info->name;
+                        else if (reg_info->alt_name)
+                            m_location_str = reg_info->alt_name;
+                        break;
+                    }
+                }
+                m_location_str = "scalar";
+                break;
+
+            case Value::eValueTypeLoadAddress:
+            case Value::eValueTypeFileAddress:
+            case Value::eValueTypeHostAddress:
+                {
+                    uint32_t addr_nibble_size = m_data.GetAddressByteSize() * 2;
+                    sstr.Printf("0x%*.*llx", addr_nibble_size, addr_nibble_size, m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS));
+                    m_location_str.swap(sstr.GetString());
+                }
+                break;
+            }
+        }
+    }
+    return m_location_str.c_str();
+}
+
+Value &
+ValueObject::GetValue()
+{
+    return m_value;
+}
+
+const Value &
+ValueObject::GetValue() const
+{
+    return m_value;
+}
+
+bool
+ValueObject::GetValueIsValid ()
+{
+    return m_flags.IsSet(eValueIsValid);
+}
+
+
+void
+ValueObject::SetValueIsValid (bool b)
+{
+    if (b)
+        m_flags.Set(eValueIsValid);
+    else
+        m_flags.Clear(eValueIsValid);
+}
+
+bool
+ValueObject::GetValueDidChange () const
+{
+    return m_flags.IsSet(eValueChanged);
+}
+
+void
+ValueObject::SetValueDidChange (bool value_changed)
+{
+    m_flags.Set(eValueChanged);
+}
+
+ValueObjectSP
+ValueObject::GetChildAtIndex (uint32_t idx, bool can_create)
+{
+    ValueObjectSP child_sp;
+    if (idx < GetNumChildren())
+    {
+        // Check if we have already made the child value object?
+        if (can_create && m_children[idx].get() == NULL)
+        {
+            // No we haven't created the child at this index, so lets have our
+            // subclass do it and cache the result for quick future access.
+            m_children[idx] = CreateChildAtIndex (idx, false, 0);
+        }
+
+        child_sp = m_children[idx];
+    }
+    return child_sp;
+}
+
+uint32_t
+ValueObject::GetIndexOfChildWithName (const ConstString &name)
+{
+    bool omit_empty_base_classes = true;
+    return ClangASTContext::GetIndexOfChildWithName (GetClangAST(),
+                                                     GetOpaqueClangQualType(),
+                                                     name.AsCString(),
+                                                     omit_empty_base_classes);
+}
+
+ValueObjectSP
+ValueObject::GetChildMemberWithName (const ConstString &name, bool can_create)
+{
+    // when getting a child by name, it could be burried inside some base
+    // classes (which really aren't part of the expression path), so we
+    // need a vector of indexes that can get us down to the correct child
+    std::vector<uint32_t> child_indexes;
+    clang::ASTContext *clang_ast = GetClangAST();
+    void *clang_type = GetOpaqueClangQualType();
+    bool omit_empty_base_classes = true;
+    const size_t num_child_indexes =  ClangASTContext::GetIndexOfChildMemberWithName (clang_ast,
+                                                                                      clang_type,
+                                                                                      name.AsCString(),
+                                                                                      omit_empty_base_classes,
+                                                                                      child_indexes);
+    ValueObjectSP child_sp;
+    if (num_child_indexes > 0)
+    {
+        std::vector<uint32_t>::const_iterator pos = child_indexes.begin ();
+        std::vector<uint32_t>::const_iterator end = child_indexes.end ();
+
+        child_sp = GetChildAtIndex(*pos, can_create);
+        for (++pos; pos != end; ++pos)
+        {
+            if (child_sp)
+            {
+                ValueObjectSP new_child_sp(child_sp->GetChildAtIndex (*pos, can_create));
+                child_sp = new_child_sp;
+            }
+            else
+            {
+                child_sp.reset();
+            }
+
+        }
+    }
+    return child_sp;
+}
+
+
+uint32_t
+ValueObject::GetNumChildren ()
+{
+    if (m_flags.IsClear(eNumChildrenHasBeenSet))
+    {
+        SetNumChildren (CalculateNumChildren());
+    }
+    return m_children.size();
+}
+void
+ValueObject::SetNumChildren (uint32_t num_children)
+{
+    m_flags.Set(eNumChildrenHasBeenSet);
+    m_children.resize(num_children);
+}
+
+void
+ValueObject::SetName (const char *name)
+{
+    m_name.SetCString(name);
+}
+
+void
+ValueObject::SetName (const ConstString &name)
+{
+    m_name = name;
+}
+
+ValueObjectSP
+ValueObject::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index)
+{
+    ValueObjectSP valobj_sp;
+    bool omit_empty_base_classes = true;
+
+    std::string child_name_str;
+    uint32_t child_byte_size = 0;
+    int32_t child_byte_offset = 0;
+    uint32_t child_bitfield_bit_size = 0;
+    uint32_t child_bitfield_bit_offset = 0;
+    const bool transparent_pointers = synthetic_array_member == false;
+    clang::ASTContext *clang_ast = GetClangAST();
+    void *clang_type = GetOpaqueClangQualType();
+    void *child_clang_type;
+    child_clang_type = ClangASTContext::GetChildClangTypeAtIndex (clang_ast,
+                                                                  GetName().AsCString(),
+                                                                  clang_type,
+                                                                  idx,
+                                                                  transparent_pointers,
+                                                                  omit_empty_base_classes,
+                                                                  child_name_str,
+                                                                  child_byte_size,
+                                                                  child_byte_offset,
+                                                                  child_bitfield_bit_size,
+                                                                  child_bitfield_bit_offset);
+    if (child_clang_type)
+    {
+        if (synthetic_index)
+            child_byte_offset += child_byte_size * synthetic_index;
+
+        ConstString child_name;
+        if (!child_name_str.empty())
+            child_name.SetCString (child_name_str.c_str());
+
+        valobj_sp.reset (new ValueObjectChild (this,
+                                               clang_ast,
+                                               child_clang_type,
+                                               child_name,
+                                               child_byte_size,
+                                               child_byte_offset,
+                                               child_bitfield_bit_size,
+                                               child_bitfield_bit_offset));
+    }
+    return valobj_sp;
+}
+
+const char *
+ValueObject::GetSummaryAsCString (ExecutionContextScope *exe_scope)
+{
+    if (UpdateValueIfNeeded (exe_scope))
+    {
+        if (m_summary_str.empty())
+        {
+            void *clang_type = GetOpaqueClangQualType();
+
+            // See if this is a pointer to a C string?
+            uint32_t fixed_length = 0;
+            if (clang_type && ClangASTContext::IsCStringType (clang_type, fixed_length))
+            {
+                Process *process = exe_scope->CalculateProcess();
+                if (process != NULL)
+                {
+                    StreamString sstr;
+                    lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS;
+                    lldb::AddressType cstr_address_type = eAddressTypeInvalid;
+                    switch (GetValue().GetValueType())
+                    {
+                    case Value::eValueTypeScalar:
+                        cstr_address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
+                        cstr_address_type = eAddressTypeLoad;
+                        break;
+
+                    case Value::eValueTypeLoadAddress:
+                    case Value::eValueTypeFileAddress:
+                    case Value::eValueTypeHostAddress:
+                        {
+                            uint32_t data_offset = 0;
+                            cstr_address = m_data.GetPointer(&data_offset);
+                            cstr_address_type = m_value.GetValueAddressType();
+                            if (cstr_address_type == eAddressTypeInvalid)
+                                cstr_address_type = eAddressTypeLoad;
+                        }
+                        break;
+                    }
+
+                    if (cstr_address != LLDB_INVALID_ADDRESS)
+                    {
+                        DataExtractor data;
+                        size_t bytes_read = 0;
+                        std::vector<char> data_buffer;
+                        std::vector<char> cstr_buffer;
+                        size_t cstr_length;
+                        Error error;
+                        if (fixed_length > 0)
+                        {
+                            data_buffer.resize(fixed_length);
+                            // Resize the formatted buffer in case every character
+                            // uses the "\xXX" format and one extra byte for a NULL
+                            cstr_buffer.resize(data_buffer.size() * 4 + 1);
+                            data.SetData (data_buffer.data(), data_buffer.size(), eByteOrderHost);
+                            bytes_read = process->ReadMemory (cstr_address, data_buffer.data(), fixed_length, error);
+                            if (bytes_read > 0)
+                            {
+                                sstr << '"';
+                                cstr_length = data.Dump (&sstr,
+                                                         0,                 // Start offset in "data"
+                                                         eFormatChar,       // Print as characters
+                                                         1,                 // Size of item (1 byte for a char!)
+                                                         bytes_read,        // How many bytes to print?
+                                                         UINT32_MAX,        // num per line
+                                                         LLDB_INVALID_ADDRESS,// base address
+                                                         0,                 // bitfield bit size
+                                                         0);                // bitfield bit offset
+                                sstr << '"';
+                            }
+                        }
+                        else
+                        {
+                            const size_t k_max_buf_size = 256;
+                            data_buffer.resize (k_max_buf_size + 1);
+                            // NULL terminate in case we don't get the entire C string
+                            data_buffer.back() = '\0';
+                            // Make a formatted buffer that can contain take 4
+                            // bytes per character in case each byte uses the
+                            // "\xXX" format and one extra byte for a NULL
+                            cstr_buffer.resize (k_max_buf_size * 4 + 1);
+
+                            data.SetData (data_buffer.data(), data_buffer.size(), eByteOrderHost);
+                            size_t total_cstr_len = 0;
+                            while ((bytes_read = process->ReadMemory (cstr_address, data_buffer.data(), k_max_buf_size, error)) > 0)
+                            {
+                                size_t len = strlen(data_buffer.data());
+                                if (len == 0)
+                                    break;
+                                if (len > bytes_read)
+                                    len = bytes_read;
+                                if (sstr.GetSize() == 0)
+                                    sstr << '"';
+
+                                cstr_length = data.Dump (&sstr,
+                                                         0,                 // Start offset in "data"
+                                                         eFormatChar,       // Print as characters
+                                                         1,                 // Size of item (1 byte for a char!)
+                                                         len,               // How many bytes to print?
+                                                         UINT32_MAX,        // num per line
+                                                         LLDB_INVALID_ADDRESS,// base address
+                                                         0,                 // bitfield bit size
+                                                         0);                // bitfield bit offset
+
+                                if (len < k_max_buf_size)
+                                    break;
+                                cstr_address += total_cstr_len;
+                            }
+                            if (sstr.GetSize() > 0)
+                                sstr << '"';
+                        }
+
+                        if (sstr.GetSize() > 0)
+                            m_summary_str.assign (sstr.GetData(), sstr.GetSize());
+                    }
+                }
+            }
+        }
+    }
+    if (m_summary_str.empty())
+        return NULL;
+    return m_summary_str.c_str();
+}
+
+
+const char *
+ValueObject::GetValueAsCString (ExecutionContextScope *exe_scope)
+{
+    // If our byte size is zero this is an aggregate type that has children
+    if (ClangASTContext::IsAggregateType (GetOpaqueClangQualType()) == false)
+    {
+        if (UpdateValueIfNeeded(exe_scope))
+        {
+            if (m_value_str.empty())
+            {
+                const Value::ContextType context_type = m_value.GetContextType();
+
+                switch (context_type)
+                {
+                case Value::eContextTypeOpaqueClangQualType:
+                case Value::eContextTypeDCType:
+                case Value::eContextTypeDCVariable:
+                    {
+                        void *clang_type = GetOpaqueClangQualType ();
+                        if (clang_type)
+                        {
+                            StreamString sstr;
+                            lldb::Format format = Type::GetFormat(clang_type);
+                            if (Type::DumpTypeValue(&sstr,
+                                                    GetClangAST(),            // The clang AST
+                                                    clang_type,               // The clang type to display
+                                                    format,                   // Format to display this type with
+                                                    m_data,                   // Data to extract from
+                                                    0,                        // Byte offset into "m_data"
+                                                    GetByteSize(),            // Byte size of item in "m_data"
+                                                    GetBitfieldBitSize(),     // Bitfield bit size
+                                                    GetBitfieldBitOffset()))  // Bitfield bit offset
+                                m_value_str.swap(sstr.GetString());
+                            else
+                                m_value_str.clear();
+                        }
+                    }
+                    break;
+
+                case Value::eContextTypeDCRegisterInfo:
+                    {
+                        const RegisterInfo *reg_info = m_value.GetRegisterInfo();
+                        if (reg_info)
+                        {
+                            StreamString reg_sstr;
+                            m_data.Dump(&reg_sstr, 0, reg_info->format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
+                            m_value_str.swap(reg_sstr.GetString());
+                        }
+                    }
+                    break;
+                }
+            }
+        }
+    }
+    if (m_value_str.empty())
+        return NULL;
+    return m_value_str.c_str();
+}
+
+bool
+ValueObject::SetValueFromCString (ExecutionContextScope *exe_scope, const char *value_str)
+{
+    // Make sure our value is up to date first so that our location and location
+    // type is valid.
+    if (!UpdateValueIfNeeded(exe_scope))
+        return false;
+
+    uint32_t count = 0;
+    lldb::Encoding encoding = Type::GetEncoding (GetOpaqueClangQualType(), count);
+
+    char *end = NULL;
+    size_t byte_size = GetByteSize();
+    switch (encoding)
+    {
+    case eEncodingInvalid:
+        return false;
+
+    case eEncodingUint:
+        if (byte_size > sizeof(unsigned long long))
+        {
+            return false;
+        }
+        else
+        {
+            unsigned long long ull_val = strtoull(value_str, &end, 0);
+            if (end && *end != '\0')
+                return false;
+            m_value = ull_val;
+            // Limit the bytes in our m_data appropriately.
+            m_value.GetScalar().GetData (m_data, byte_size);
+        }
+        break;
+
+    case eEncodingSint:
+        if (byte_size > sizeof(long long))
+        {
+            return false;
+        }
+        else
+        {
+            long long sll_val = strtoll(value_str, &end, 0);
+            if (end && *end != '\0')
+                return false;
+            m_value = sll_val;
+            // Limit the bytes in our m_data appropriately.
+            m_value.GetScalar().GetData (m_data, byte_size);
+        }
+        break;
+
+    case eEncodingIEEE754:
+        {
+            const size_t byte_size = GetByteSize();
+            const off_t byte_offset = GetByteOffset();
+            uint8_t *dst = (uint8_t *)m_data.PeekData(byte_offset, byte_size);
+            if (dst != NULL)
+            {
+                // We are decoding a float into host byte order below, so make
+                // sure m_data knows what it contains.
+                m_data.SetByteOrder(eByteOrderHost);
+                const size_t converted_byte_size = ClangASTContext::ConvertStringToFloatValue (
+                                                        GetClangAST(),
+                                                        GetOpaqueClangQualType(),
+                                                        value_str,
+                                                        dst,
+                                                        byte_size);
+
+                if (converted_byte_size == byte_size)
+                {
+                }
+            }
+        }
+        break;
+
+    case eEncodingVector:
+        return false;
+
+    default:
+        return false;
+    }
+
+    // If we have made it here the value is in m_data and we should write it
+    // out to the target
+    return Write ();
+}
+
+bool
+ValueObject::Write ()
+{
+    // Clear the update ID so the next time we try and read the value
+    // we try and read it again.
+    m_update_id = 0;
+
+    // TODO: when Value has a method to write a value back, call it from here.
+    return false;
+
+}
+
+void
+ValueObject::AddSyntheticChild (const ConstString &key, ValueObjectSP& valobj_sp)
+{
+    m_synthetic_children[key] = valobj_sp;
+}
+
+ValueObjectSP
+ValueObject::GetSyntheticChild (const ConstString &key) const
+{
+    ValueObjectSP synthetic_child_sp;
+    std::map<ConstString, ValueObjectSP>::const_iterator pos = m_synthetic_children.find (key);
+    if (pos != m_synthetic_children.end())
+        synthetic_child_sp = pos->second;
+    return synthetic_child_sp;
+}
+
+bool
+ValueObject::IsPointerType ()
+{
+    return ClangASTContext::IsPointerType (GetOpaqueClangQualType());
+}
+
+bool
+ValueObject::IsPointerOrReferenceType ()
+{
+    return ClangASTContext::IsPointerOrReferenceType(GetOpaqueClangQualType());
+}
+
+ValueObjectSP
+ValueObject::GetSyntheticArrayMemberFromPointer (int32_t index, bool can_create)
+{
+    ValueObjectSP synthetic_child_sp;
+    if (IsPointerType ())
+    {
+        char index_str[64];
+        snprintf(index_str, sizeof(index_str), "[%i]", index);
+        ConstString index_const_str(index_str);
+        // Check if we have already created a synthetic array member in this
+        // valid object. If we have we will re-use it.
+        synthetic_child_sp = GetSyntheticChild (index_const_str);
+        if (!synthetic_child_sp)
+        {
+            // We haven't made a synthetic array member for INDEX yet, so
+            // lets make one and cache it for any future reference.
+            synthetic_child_sp = CreateChildAtIndex(0, true, index);
+
+            // Cache the value if we got one back...
+            if (synthetic_child_sp)
+                AddSyntheticChild(index_const_str, synthetic_child_sp);
+        }
+    }
+    return synthetic_child_sp;
+}
diff --git a/source/Core/ValueObjectChild.cpp b/source/Core/ValueObjectChild.cpp
new file mode 100644
index 0000000..dc10bb0
--- /dev/null
+++ b/source/Core/ValueObjectChild.cpp
@@ -0,0 +1,207 @@
+//===-- ValueObjectChild.cpp ------------------------------------*- 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/ValueObjectChild.h"
+
+#include "lldb/Core/dwarf.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ValueObjectList.h"
+
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/Variable.h"
+
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb_private;
+
+ValueObjectChild::ValueObjectChild
+(
+    ValueObject* parent,
+    clang::ASTContext *clang_ast,
+    void *clang_type,
+    const ConstString &name,
+    uint32_t byte_size,
+    int32_t byte_offset,
+    uint32_t bitfield_bit_size,
+    uint32_t bitfield_bit_offset
+) :
+    ValueObject (),
+    m_parent (parent),
+    m_clang_ast (clang_ast),
+    m_clang_type (clang_type),
+    m_byte_size (byte_size),
+    m_byte_offset (byte_offset),
+    m_bitfield_bit_size (bitfield_bit_size),
+    m_bitfield_bit_offset (bitfield_bit_offset)
+{
+    m_name = name;
+}
+
+ValueObjectChild::~ValueObjectChild()
+{
+}
+
+void *
+ValueObjectChild::GetOpaqueClangQualType()
+{
+    return m_clang_type;
+}
+
+lldb::ValueType
+ValueObjectChild::GetValueType() const
+{
+    return m_parent->GetValueType();
+}
+
+uint32_t
+ValueObjectChild::CalculateNumChildren()
+{
+    return ClangASTContext::GetNumChildren (m_clang_type, true);
+}
+
+clang::ASTContext *
+ValueObjectChild::GetClangAST ()
+{
+    return m_clang_ast;
+}
+
+size_t
+ValueObjectChild::GetByteSize()
+{
+    return m_byte_size;
+}
+
+off_t
+ValueObjectChild::GetByteOffset()
+{
+    return m_byte_offset;
+}
+
+uint32_t
+ValueObjectChild::GetBitfieldBitSize()
+{
+    return m_bitfield_bit_size;
+}
+
+uint32_t
+ValueObjectChild::GetBitfieldBitOffset()
+{
+    return m_bitfield_bit_offset;
+}
+
+ConstString
+ValueObjectChild::GetTypeName()
+{
+    if (m_type_name.IsEmpty())
+    {
+        m_type_name = Type::GetClangTypeName (GetOpaqueClangQualType());
+        if (m_type_name)
+        {
+            if (m_bitfield_bit_size > 0)
+            {
+                const char *clang_type_name = m_type_name.AsCString();
+                if (clang_type_name)
+                {
+                    char bitfield_type_name[strlen(clang_type_name) + 32];
+                    ::snprintf (bitfield_type_name, sizeof(bitfield_type_name), "%s:%u", clang_type_name, m_bitfield_bit_size);
+                    m_type_name.SetCString(bitfield_type_name);
+                }
+            }
+        }
+    }
+    return m_type_name;
+}
+
+void
+ValueObjectChild::UpdateValue (ExecutionContextScope *exe_scope)
+{
+    m_error.Clear();
+    SetValueIsValid (false);
+    ValueObject* parent = m_parent;
+    if (parent)
+    {
+        if (parent->UpdateValueIfNeeded(exe_scope))
+        {
+            m_value.SetContext(Value::eContextTypeOpaqueClangQualType, m_clang_type);
+
+            // Copy the parent scalar value and the scalar value type
+            m_value.GetScalar() = parent->GetValue().GetScalar();
+            Value::ValueType value_type = parent->GetValue().GetValueType();
+            m_value.SetValueType (value_type);
+
+            if (ClangASTContext::IsPointerOrReferenceType (parent->GetOpaqueClangQualType()))
+            {
+                uint32_t offset = 0;
+                m_value.GetScalar() = parent->GetDataExtractor().GetPointer(&offset);
+                // For pointers, m_byte_offset should only ever be set if we
+                // ValueObject::GetSyntheticArrayMemberFromPointer() was called
+                if (ClangASTContext::IsPointerType (parent->GetOpaqueClangQualType()) && m_byte_offset)
+                    m_value.GetScalar() += m_byte_offset;
+                if (value_type == Value::eValueTypeScalar ||
+                    value_type == Value::eValueTypeFileAddress)
+                    m_value.SetValueType (Value::eValueTypeLoadAddress);
+            }
+            else
+            {
+                switch (value_type)
+                {
+                case Value::eValueTypeLoadAddress:
+                case Value::eValueTypeFileAddress:
+                case Value::eValueTypeHostAddress:
+                    {
+                        lldb::addr_t addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
+                        if (addr == LLDB_INVALID_ADDRESS || addr == 0)
+                        {
+                            m_error.SetErrorStringWithFormat("Parent address is invalid: 0x%llx.\n", addr);
+                            break;
+                        }
+                        // Set this object's scalar value to the address of its
+                        // value be adding its byte offset to the parent address
+                        m_value.GetScalar() += GetByteOffset();
+                    }
+                    break;
+
+                case Value::eValueTypeScalar:
+                    // TODO: What if this is a register value? Do we try and
+                    // extract the child value from within the parent data?
+                    // Probably...
+                default:
+                    m_error.SetErrorString ("Parent has invalid value.");
+                    break;
+                }
+            }
+
+            if (m_error.Success())
+            {
+                ExecutionContext exe_ctx (exe_scope);
+                m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST (), m_data, 0);
+            }
+        }
+        else
+        {
+            m_error.SetErrorStringWithFormat("Parent failed to evaluate: %s.\n", parent->GetError().AsCString());
+        }
+    }
+    else
+    {
+        m_error.SetErrorString("ValueObjectChild has a NULL parent ValueObject.");
+    }
+}
+
+
+bool
+ValueObjectChild::IsInScope (StackFrame *frame)
+{
+    return m_parent->IsInScope (frame);
+}
+
diff --git a/source/Core/ValueObjectList.cpp b/source/Core/ValueObjectList.cpp
new file mode 100644
index 0000000..50ae1de
--- /dev/null
+++ b/source/Core/ValueObjectList.cpp
@@ -0,0 +1,119 @@
+//===-- ValueObjectList.cpp -------------------------------------*- 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/ValueObjectList.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/ValueObjectChild.h"
+#include "lldb/Core/ValueObjectRegister.h"
+#include "lldb/Core/ValueObjectVariable.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+ValueObjectList::ValueObjectList () :
+    m_value_objects()
+{
+}
+
+ValueObjectList::ValueObjectList (const ValueObjectList &rhs) :
+    m_value_objects(rhs.m_value_objects)
+{
+}
+
+
+ValueObjectList::~ValueObjectList ()
+{
+}
+
+const ValueObjectList &
+ValueObjectList::operator = (const ValueObjectList &rhs)
+{
+    if (this != &rhs)
+        m_value_objects = rhs.m_value_objects;
+    return *this;
+}
+
+void
+ValueObjectList::Append (const ValueObjectSP &val_obj_sp)
+{
+    m_value_objects.push_back(val_obj_sp);
+}
+
+uint32_t
+ValueObjectList::GetSize() const
+{
+    return m_value_objects.size();
+}
+
+lldb::ValueObjectSP
+ValueObjectList::GetValueObjectAtIndex (uint32_t idx)
+{
+    lldb::ValueObjectSP valobj_sp;
+    if (idx < m_value_objects.size())
+        valobj_sp = m_value_objects[idx];
+    return valobj_sp;
+}
+
+ValueObjectSP
+ValueObjectList::FindValueObjectByValueName (const char *name)
+{
+    ConstString name_const_str(name);
+    ValueObjectSP val_obj_sp;
+    collection::iterator pos, end = m_value_objects.end();
+    for (pos = m_value_objects.begin(); pos != end; ++pos)
+    {
+        if ((*pos)->GetName() == name_const_str)
+        {
+            val_obj_sp = *pos;
+            break;
+        }
+    }
+    return val_obj_sp;
+}
+
+ValueObjectSP
+ValueObjectList::FindValueObjectByUID (lldb::user_id_t uid)
+{
+    ValueObjectSP valobj_sp;
+    collection::iterator pos, end = m_value_objects.end();
+
+    for (pos = m_value_objects.begin(); pos != end; ++pos)
+    {
+        if ((*pos)->GetID() == uid)
+        {
+            valobj_sp = *pos;
+            break;
+        }
+    }
+    return valobj_sp;
+}
+
+
+ValueObjectSP
+ValueObjectList::FindValueObjectByPointer (ValueObject *valobj)
+{
+    ValueObjectSP valobj_sp;
+    collection::iterator pos, end = m_value_objects.end();
+
+    for (pos = m_value_objects.begin(); pos != end; ++pos)
+    {
+        if ((*pos).get() == valobj)
+        {
+            valobj_sp = *pos;
+            break;
+        }
+    }
+    return valobj_sp;
+}
diff --git a/source/Core/ValueObjectRegister.cpp b/source/Core/ValueObjectRegister.cpp
new file mode 100644
index 0000000..aae818e
--- /dev/null
+++ b/source/Core/ValueObjectRegister.cpp
@@ -0,0 +1,331 @@
+//===-- ValueObjectRegister.cpp ---------------------------------*- 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/ValueObjectRegister.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Module.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/TypeList.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+#pragma mark ValueObjectRegisterContext
+
+ValueObjectRegisterContext::ValueObjectRegisterContext (RegisterContext *reg_ctx) :
+    ValueObject (),
+    m_reg_ctx (reg_ctx)
+{
+    assert (reg_ctx);
+    m_name.SetCString("Registers");
+    SetValueIsValid (true);
+}
+
+ValueObjectRegisterContext::~ValueObjectRegisterContext()
+{
+}
+
+void *
+ValueObjectRegisterContext::GetOpaqueClangQualType ()
+{
+    return NULL;
+}
+
+ConstString
+ValueObjectRegisterContext::GetTypeName()
+{
+    ConstString empty_type_name;
+    return empty_type_name;
+}
+
+uint32_t
+ValueObjectRegisterContext::CalculateNumChildren()
+{
+    return m_reg_ctx->GetRegisterSetCount();
+}
+
+clang::ASTContext *
+ValueObjectRegisterContext::GetClangAST ()
+{
+    return NULL;
+}
+
+size_t
+ValueObjectRegisterContext::GetByteSize()
+{
+    return 0;
+}
+
+void
+ValueObjectRegisterContext::UpdateValue (ExecutionContextScope *exe_scope)
+{
+    m_error.Clear();
+    StackFrame *frame = exe_scope->CalculateStackFrame();
+    if (frame)
+        m_reg_ctx = frame->GetRegisterContext();
+    else
+        m_reg_ctx = NULL;
+
+    SetValueIsValid (m_reg_ctx != NULL);
+}
+
+ValueObjectSP
+ValueObjectRegisterContext::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index)
+{
+    ValueObjectSP valobj_sp;
+
+    const uint32_t num_children = GetNumChildren();
+    if (idx < num_children)
+        valobj_sp.reset (new ValueObjectRegisterSet(m_reg_ctx, idx));
+    return valobj_sp;
+}
+
+
+#pragma mark -
+#pragma mark ValueObjectRegisterSet
+
+ValueObjectRegisterSet::ValueObjectRegisterSet (RegisterContext *reg_ctx, uint32_t reg_set_idx) :
+    ValueObject (),
+    m_reg_ctx (reg_ctx),
+    m_reg_set (NULL),
+    m_reg_set_idx (reg_set_idx)
+{
+    assert (reg_ctx);
+    m_reg_set = reg_ctx->GetRegisterSet(m_reg_set_idx);
+    if (m_reg_set)
+    {
+        m_name.SetCString (m_reg_set->name);
+    }
+}
+
+ValueObjectRegisterSet::~ValueObjectRegisterSet()
+{
+}
+
+void *
+ValueObjectRegisterSet::GetOpaqueClangQualType ()
+{
+    return NULL;
+}
+
+ConstString
+ValueObjectRegisterSet::GetTypeName()
+{
+    return ConstString();
+}
+
+uint32_t
+ValueObjectRegisterSet::CalculateNumChildren()
+{
+    const RegisterSet *reg_set = m_reg_ctx->GetRegisterSet(m_reg_set_idx);
+    if (reg_set)
+        return reg_set->num_registers;
+    return 0;
+}
+
+clang::ASTContext *
+ValueObjectRegisterSet::GetClangAST ()
+{
+    return NULL;
+}
+
+size_t
+ValueObjectRegisterSet::GetByteSize()
+{
+    return 0;
+}
+
+void
+ValueObjectRegisterSet::UpdateValue (ExecutionContextScope *exe_scope)
+{
+    m_error.Clear();
+    SetValueDidChange (false);
+    StackFrame *frame = exe_scope->CalculateStackFrame();
+    if (frame == NULL)
+        m_reg_ctx = NULL;
+    else
+    {
+        m_reg_ctx = frame->GetRegisterContext ();
+        if (m_reg_ctx)
+        {
+            const RegisterSet *reg_set = m_reg_ctx->GetRegisterSet (m_reg_set_idx);
+            if (reg_set == NULL)
+                m_reg_ctx = NULL;
+            else if (m_reg_set != reg_set)
+            {
+                SetValueDidChange (true);
+                m_name.SetCString(reg_set->name);
+            }
+        }
+    }
+    if (m_reg_ctx)
+    {
+        SetValueIsValid (true);
+    }
+    else
+    {
+        SetValueIsValid (false);
+        m_children.clear();
+    }
+}
+
+
+ValueObjectSP
+ValueObjectRegisterSet::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index)
+{
+    ValueObjectSP valobj_sp;
+    if (m_reg_ctx && m_reg_set)
+    {
+        const uint32_t num_children = GetNumChildren();
+        if (idx < num_children)
+            valobj_sp.reset (new ValueObjectRegister(m_reg_ctx, m_reg_set->registers[idx]));
+    }
+    return valobj_sp;
+}
+
+
+#pragma mark -
+#pragma mark ValueObjectRegister
+
+ValueObjectRegister::ValueObjectRegister (RegisterContext *reg_ctx, uint32_t reg_num) :
+    ValueObject (),
+    m_reg_ctx (reg_ctx),
+    m_reg_info (NULL),
+    m_reg_num (reg_num),
+    m_type_name (),
+    m_clang_type (NULL)
+{
+    assert (reg_ctx);
+    m_reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
+    if (m_reg_info)
+    {
+        if (m_reg_info->name)
+            m_name.SetCString(m_reg_info->name);
+        else if (m_reg_info->alt_name)
+            m_name.SetCString(m_reg_info->alt_name);
+    }
+}
+
+ValueObjectRegister::~ValueObjectRegister()
+{
+}
+
+void *
+ValueObjectRegister::GetOpaqueClangQualType ()
+{
+    if (m_clang_type == NULL && m_reg_info)
+    {
+        Process *process = m_reg_ctx->CalculateProcess ();
+        if (process)
+        {
+            Module *exe_module = process->GetTarget().GetExecutableModule ().get();
+            if (exe_module)
+            {
+                TypeList *type_list = exe_module->GetTypeList();
+                if (type_list)
+                    m_clang_type = type_list->GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize (m_reg_info->encoding, m_reg_info->byte_size * 8);
+            }
+        }
+    }
+    return m_clang_type;
+}
+
+ConstString
+ValueObjectRegister::GetTypeName()
+{
+    if (m_type_name.IsEmpty())
+        m_type_name = Type::GetClangTypeName (GetOpaqueClangQualType());
+    return m_type_name;
+}
+
+uint32_t
+ValueObjectRegister::CalculateNumChildren()
+{
+    return 0;
+}
+
+clang::ASTContext *
+ValueObjectRegister::GetClangAST ()
+{
+    Process *process = m_reg_ctx->CalculateProcess ();
+    if (process)
+    {
+        Module *exe_module = process->GetTarget().GetExecutableModule ().get();
+        if (exe_module)
+        {
+            TypeList *type_list = exe_module->GetTypeList();
+            if (type_list)
+                return type_list->GetClangASTContext().getASTContext();
+        }
+    }
+    return NULL;
+}
+
+size_t
+ValueObjectRegister::GetByteSize()
+{
+    return m_reg_info->byte_size;
+}
+
+void
+ValueObjectRegister::UpdateValue (ExecutionContextScope *exe_scope)
+{
+    m_error.Clear();
+    StackFrame *frame = exe_scope->CalculateStackFrame();
+    if (frame)
+    {
+        m_reg_ctx = frame->GetRegisterContext();
+        if (m_reg_ctx)
+        {
+            const RegisterInfo *reg_info = m_reg_ctx->GetRegisterInfoAtIndex(m_reg_num);
+            if (m_reg_info != reg_info)
+            {
+                m_reg_info = reg_info;
+                if (m_reg_info)
+                {
+                    if (m_reg_info->name)
+                        m_name.SetCString(m_reg_info->name);
+                    else if (m_reg_info->alt_name)
+                        m_name.SetCString(m_reg_info->alt_name);
+                }
+            }
+        }
+    }
+    else
+    {
+        m_reg_ctx = NULL;
+        m_reg_info = NULL;
+    }
+
+
+    if (m_reg_ctx && m_reg_info)
+    {
+        if (m_reg_ctx->ReadRegisterBytes (m_reg_num, m_data))
+        {
+            m_value.SetContext(Value::eContextTypeDCRegisterInfo, (void *)m_reg_info);
+            m_value.SetValueType(Value::eValueTypeHostAddress);
+            m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
+            SetValueIsValid (true);
+            return;
+        }
+    }
+    SetValueIsValid (false);
+}
+
+
diff --git a/source/Core/ValueObjectVariable.cpp b/source/Core/ValueObjectVariable.cpp
new file mode 100644
index 0000000..0b94535
--- /dev/null
+++ b/source/Core/ValueObjectVariable.cpp
@@ -0,0 +1,167 @@
+//===-- ValueObjectVariable.cpp ---------------------------------*- 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/ValueObjectVariable.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ValueObjectList.h"
+#include "lldb/Core/Value.h"
+
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/Variable.h"
+
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+#include "clang/AST/Type.h"
+
+
+using namespace lldb_private;
+
+ValueObjectVariable::ValueObjectVariable (lldb::VariableSP &var_sp) :
+    ValueObject(),
+    m_variable_sp(var_sp)
+{
+    // Do not attempt to construct one of these objects with no variable!
+    assert (m_variable_sp.get() != NULL);
+    m_name = var_sp->GetName();
+}
+
+ValueObjectVariable::~ValueObjectVariable()
+{
+}
+
+void *
+ValueObjectVariable::GetOpaqueClangQualType ()
+{
+    Type *var_type = m_variable_sp->GetType();
+    if (var_type)
+        return var_type->GetOpaqueClangQualType();
+    return NULL;
+}
+
+ConstString
+ValueObjectVariable::GetTypeName()
+{
+    Type * var_type = m_variable_sp->GetType();
+    if (var_type)
+        return var_type->GetName();
+    ConstString empty_type_name;
+    return empty_type_name;
+}
+
+uint32_t
+ValueObjectVariable::CalculateNumChildren()
+{
+    Type *var_type = m_variable_sp->GetType();
+    if (var_type)
+        return var_type->GetNumChildren(true);
+    return 0;
+}
+
+clang::ASTContext *
+ValueObjectVariable::GetClangAST ()
+{
+    return m_variable_sp->GetType()->GetClangAST();
+}
+
+size_t
+ValueObjectVariable::GetByteSize()
+{
+    return m_variable_sp->GetType()->GetByteSize();
+}
+
+lldb::ValueType
+ValueObjectVariable::GetValueType() const
+{
+    if (m_variable_sp)
+        return m_variable_sp->GetScope();
+    return lldb::eValueTypeInvalid;
+}
+
+
+
+void
+ValueObjectVariable::UpdateValue (ExecutionContextScope *exe_scope)
+{
+    SetValueIsValid (false);
+    m_error.Clear();
+
+    Variable *variable = m_variable_sp.get();
+    DWARFExpression &expr = variable->LocationExpression();
+    Value old_value(m_value);
+    ExecutionContext exe_ctx (exe_scope);
+    if (expr.Evaluate (&exe_ctx, GetClangAST(), NULL, m_value, &m_error))
+    {
+        m_value.SetContext(Value::eContextTypeDCVariable, variable);
+
+        Value::ValueType value_type = m_value.GetValueType();
+
+        switch (value_type)
+        {
+        default:
+            assert(!"Unhandled expression result value kind...");
+            break;
+
+        case Value::eValueTypeScalar:
+            // The variable value is in the Scalar value inside the m_value.
+            // We can point our m_data right to it.
+            m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0);
+            break;
+
+        case Value::eValueTypeFileAddress:
+        case Value::eValueTypeLoadAddress:
+        case Value::eValueTypeHostAddress:
+            // The DWARF expression result was an address in the inferior
+            // process. If this variable is an aggregate type, we just need
+            // the address as the main value as all child variable objects
+            // will rely upon this location and add an offset and then read
+            // their own values as needed. If this variable is a simple
+            // type, we read all data for it into m_data.
+            // Make sure this type has a value before we try and read it
+            if (ClangASTContext::IsAggregateType (GetOpaqueClangQualType()))
+            {
+                // this value object represents an aggregate type whose
+                // children have values, but this object does not. So we
+                // say we are changed if our location has changed.
+                SetValueDidChange (value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar());
+            }
+            else
+            {
+                // Copy the Value and set the context to use our Variable
+                // so it can extract read its value into m_data appropriately
+                Value value(m_value);
+                value.SetContext(Value::eContextTypeDCVariable, variable);
+                m_error = value.GetValueAsData(&exe_ctx, GetClangAST(), m_data, 0);
+            }
+            break;
+        }
+
+        SetValueIsValid (m_error.Success());
+    }
+}
+
+
+
+bool
+ValueObjectVariable::IsInScope (StackFrame *frame)
+{
+    return m_variable_sp->IsInScope (frame);
+}
+
diff --git a/source/Expression/ClangASTSource.cpp b/source/Expression/ClangASTSource.cpp
new file mode 100644
index 0000000..996c205
--- /dev/null
+++ b/source/Expression/ClangASTSource.cpp
@@ -0,0 +1,101 @@
+/*
+ *  ClangASTSource.cpp
+ *  lldb
+ *
+ *  Created by John McCall on 6/1/10.
+ *  Copyright 2010 Apple. All rights reserved.
+ *
+ */
+
+#define NO_RTTI
+
+#include "clang/AST/ASTContext.h"
+#include "lldb/Expression/ClangASTSource.h"
+#include "lldb/Expression/ClangExpression.h"
+#include "lldb/Expression/ClangExpressionDeclMap.h"
+
+using namespace clang;
+using namespace lldb_private;
+
+ClangASTSource::~ClangASTSource() {}
+
+void ClangASTSource::StartTranslationUnit(ASTConsumer *Consumer) {
+    // Tell Sema to ask us when looking into the translation unit's decl.
+    Context.getTranslationUnitDecl()->setHasExternalVisibleStorage();
+    Context.getTranslationUnitDecl()->setHasExternalLexicalStorage();
+}
+
+// These are only required for AST source that want to lazily load
+// the declarations (or parts thereof) that they return.
+Decl *ClangASTSource::GetExternalDecl(uint32_t) { return 0; }
+Stmt *ClangASTSource::GetExternalDeclStmt(uint64_t) { return 0; }
+
+// These are also optional, although it might help with ObjC
+// debugging if we have respectable signatures.  But a more
+// efficient interface (that didn't require scanning all files
+// for method signatures!) might help.
+Selector ClangASTSource::GetExternalSelector(uint32_t) { return Selector(); }
+uint32_t ClangASTSource::GetNumExternalSelectors() { return 0; }
+
+// The core lookup interface.
+DeclContext::lookup_result ClangASTSource::FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) {
+    switch (Name.getNameKind()) {
+    // Normal identifiers.
+    case DeclarationName::Identifier:
+      break;
+            
+    // Operator names.  Not important for now.
+    case DeclarationName::CXXOperatorName:
+    case DeclarationName::CXXLiteralOperatorName:
+      return DeclContext::lookup_result();
+            
+    // Using directives found in this context.
+    // Tell Sema we didn't find any or we'll end up getting asked a *lot*.
+    case DeclarationName::CXXUsingDirective:
+      return SetNoExternalVisibleDeclsForName(DC, Name);
+            
+    // These aren't looked up like this.
+    case DeclarationName::ObjCZeroArgSelector:
+    case DeclarationName::ObjCOneArgSelector:
+    case DeclarationName::ObjCMultiArgSelector:
+      return DeclContext::lookup_result();
+
+    // These aren't possible in the global context.
+    case DeclarationName::CXXConstructorName:
+    case DeclarationName::CXXDestructorName:
+    case DeclarationName::CXXConversionFunctionName:
+      return DeclContext::lookup_result();
+    }
+    
+	llvm::SmallVector<NamedDecl*, 4> Decls;
+    
+    NameSearchContext NSC(*this, Decls, Name, DC);
+    
+    DeclMap.GetDecls(NSC, Name.getAsString().c_str());
+    return SetExternalVisibleDeclsForName(DC, Name, Decls);
+}
+
+// This is used to support iterating through an entire lexical context,
+// which isn't something the debugger should ever need to do.
+bool ClangASTSource::FindExternalLexicalDecls(const DeclContext *DC, llvm::SmallVectorImpl<Decl*> &Decls) {
+	// true is for error, that's good enough for me
+	return true;
+}
+
+clang::ASTContext *NameSearchContext::GetASTContext() {
+    return &ASTSource.Context;
+}
+
+clang::NamedDecl *NameSearchContext::AddVarDecl(void *type) {
+    clang::NamedDecl *Decl = VarDecl::Create(ASTSource.Context, 
+                                             const_cast<DeclContext*>(DC), 
+                                             SourceLocation(), 
+                                             Name.getAsIdentifierInfo(), 
+                                             QualType::getFromOpaquePtr(type), 
+                                             0, 
+                                             VarDecl::Static, 
+                                             VarDecl::Static);
+    Decls.push_back(Decl);
+    
+    return Decl;
+}
diff --git a/source/Expression/ClangExpression.cpp b/source/Expression/ClangExpression.cpp
new file mode 100644
index 0000000..f7742c6
--- /dev/null
+++ b/source/Expression/ClangExpression.cpp
@@ -0,0 +1,633 @@
+//===-- ClangExpression.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 <stdio.h>
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+
+// C++ Includes
+#include <cstdlib>
+#include <string>
+#include <map>
+
+// Other libraries and framework includes
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Version.h"
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/Driver/CC1Options.h"
+#include "clang/Driver/OptTable.h"
+#include "clang/Frontend/CodeGenAction.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/FrontendPluginRegistry.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Frontend/VerifyDiagnosticsClient.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/ParseAST.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/JIT.h"
+#include "llvm/Module.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/System/DynamicLibrary.h"
+#include "llvm/System/Host.h"
+#include "llvm/System/Signals.h"
+#include "llvm/Target/TargetSelect.h"
+
+// Project includes
+#include "lldb/Expression/ClangExpression.h"
+#include "lldb/Expression/ClangASTSource.h"
+#include "lldb/Expression/ClangStmtVisitor.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Expression/RecordingMemoryManager.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+
+#define NO_RTTI
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Core/dwarf.h"
+
+
+using namespace lldb_private;
+using namespace clang;
+using namespace llvm;
+
+namespace clang {
+
+class AnalyzerOptions;
+class CodeGenOptions;
+class DependencyOutputOptions;
+class DiagnosticOptions;
+class FrontendOptions;
+class HeaderSearchOptions;
+class LangOptions;
+class PreprocessorOptions;
+class PreprocessorOutputOptions;
+class TargetInfo;
+class TargetOptions;
+
+} // end namespace clang
+
+
+
+//===----------------------------------------------------------------------===//
+// Utility Methods
+//===----------------------------------------------------------------------===//
+
+std::string GetBuiltinIncludePath(const char *Argv0) {
+  llvm::sys::Path P =
+    llvm::sys::Path::GetMainExecutable(Argv0,
+                                       (void*)(intptr_t) GetBuiltinIncludePath);
+
+  if (!P.isEmpty()) {
+    P.eraseComponent();  // Remove /clang from foo/bin/clang
+    P.eraseComponent();  // Remove /bin   from foo/bin
+
+    // Get foo/lib/clang/<version>/include
+    P.appendComponent("lib");
+    P.appendComponent("clang");
+    P.appendComponent(CLANG_VERSION_STRING);
+    P.appendComponent("include");
+  }
+
+  return P.str();
+}
+
+
+//===----------------------------------------------------------------------===//
+// Main driver
+//===----------------------------------------------------------------------===//
+
+void LLVMErrorHandler(void *UserData, const std::string &Message) {
+    Diagnostic &Diags = *static_cast<Diagnostic*>(UserData);
+
+    Diags.Report(diag::err_fe_error_backend) << Message;
+
+    // We cannot recover from llvm errors.
+    exit(1);
+}
+
+static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
+    using namespace clang::frontend;
+
+    switch (CI.getFrontendOpts().ProgramAction) {
+        default:
+            llvm_unreachable("Invalid program action!");
+
+        case ASTDump:                return new ASTDumpAction();
+        case ASTPrint:               return new ASTPrintAction();
+        case ASTPrintXML:            return new ASTPrintXMLAction();
+        case ASTView:                return new ASTViewAction();
+        case DumpRawTokens:          return new DumpRawTokensAction();
+        case DumpTokens:             return new DumpTokensAction();
+        case EmitAssembly:           return new EmitAssemblyAction();
+        case EmitBC:                 return new EmitBCAction();
+        case EmitHTML:               return new HTMLPrintAction();
+        case EmitLLVM:               return new EmitLLVMAction();
+        case EmitLLVMOnly:           return new EmitLLVMOnlyAction();
+        case EmitObj:                return new EmitObjAction();
+        case FixIt:                  return new FixItAction();
+        case GeneratePCH:            return new GeneratePCHAction();
+        case GeneratePTH:            return new GeneratePTHAction();
+        case InheritanceView:        return new InheritanceViewAction();
+        case InitOnly:               return new InitOnlyAction();
+        case ParseNoop:              return new ParseOnlyAction();
+        case ParsePrintCallbacks:    return new PrintParseAction();
+        case ParseSyntaxOnly:        return new SyntaxOnlyAction();
+
+        case PluginAction: {
+            if (CI.getFrontendOpts().ActionName == "help") {
+                llvm::errs() << "clang -cc1 plugins:\n";
+                for (FrontendPluginRegistry::iterator it =
+                     FrontendPluginRegistry::begin(),
+                     ie = FrontendPluginRegistry::end();
+                     it != ie; ++it)
+                    llvm::errs() << "  " << it->getName() << " - " << it->getDesc() << "\n";
+                return 0;
+            }
+
+            for (FrontendPluginRegistry::iterator it =
+                 FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end();
+                 it != ie; ++it) {
+                if (it->getName() == CI.getFrontendOpts().ActionName)
+                    return it->instantiate();
+            }
+
+            CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
+            << CI.getFrontendOpts().ActionName;
+            return 0;
+        }
+
+        case PrintDeclContext:       return new DeclContextPrintAction();
+        case PrintPreprocessedInput: return new PrintPreprocessedAction();
+        case RewriteMacros:          return new RewriteMacrosAction();
+        case RewriteObjC:            return new RewriteObjCAction();
+        case RewriteTest:            return new RewriteTestAction();
+        case RunAnalysis:            return new AnalysisAction();
+        case RunPreprocessorOnly:    return new PreprocessOnlyAction();
+    }
+}
+
+//----------------------------------------------------------------------
+// ClangExpression constructor
+//----------------------------------------------------------------------
+ClangExpression::ClangExpression(const char *target_triple,
+                                 ClangExpressionDeclMap *decl_map) :
+    m_target_triple (),
+    m_jit_mm_ptr (NULL),
+    m_code_generator_ptr (NULL),
+    m_decl_map (decl_map)
+{
+    if (target_triple && target_triple[0])
+        m_target_triple = target_triple;
+    else
+        m_target_triple = llvm::sys::getHostTriple();
+}
+
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ClangExpression::~ClangExpression()
+{
+    if (m_code_generator_ptr && !m_execution_engine.get())
+        delete m_code_generator_ptr;
+}
+
+bool
+ClangExpression::CreateCompilerInstance (bool &IsAST)
+{
+    // Initialize targets first, so that --version shows registered targets.
+    static struct InitializeLLVM {
+        InitializeLLVM() {
+            llvm::InitializeAllTargets();
+            llvm::InitializeAllAsmPrinters();
+        }
+    } InitializeLLVM;
+
+    // 1. Create a new compiler instance.
+    m_clang_ap.reset(new CompilerInstance());    
+    m_clang_ap->setLLVMContext(new LLVMContext());
+    
+    // 2. Set options.
+
+    // Parse expressions as Objective C++ regardless of context.
+    // Our hook into Clang's lookup mechanism only works in C++.
+    m_clang_ap->getLangOpts().CPlusPlus = true;
+    m_clang_ap->getLangOpts().ObjC1 = true;
+
+    // Disable some warnings.
+    m_clang_ap->getDiagnosticOpts().Warnings.push_back("no-unused-value");
+    
+    // Set the target triple.
+    m_clang_ap->getTargetOpts().Triple = m_target_triple;
+    
+    // 3. Set up various important bits of infrastructure.
+    
+    m_clang_ap->createDiagnostics(0, 0);
+    m_clang_ap->getLangOpts().CPlusPlus = true;
+
+    // Create the target instance.
+    m_clang_ap->setTarget(TargetInfo::CreateTargetInfo(m_clang_ap->getDiagnostics(),
+                                                       m_clang_ap->getTargetOpts()));
+    if (!m_clang_ap->hasTarget())
+    {
+        m_clang_ap.reset();
+        return false;
+    }
+
+    // Inform the target of the language options
+    //
+    // FIXME: We shouldn't need to do this, the target should be immutable once
+    // created. This complexity should be lifted elsewhere.
+    m_clang_ap->getTarget().setForcedLangOptions(m_clang_ap->getLangOpts());
+
+    return m_clang_ap.get();
+}
+
+Mutex &
+ClangExpression::GetClangMutex ()
+{
+    static Mutex g_clang_mutex(Mutex::eMutexTypeRecursive);  // Control access to the clang compiler
+    return g_clang_mutex;
+}
+
+
+clang::ASTContext *
+ClangExpression::GetASTContext ()
+{
+    CompilerInstance *compiler_instance = GetCompilerInstance();
+    if (compiler_instance)
+        return &compiler_instance->getASTContext();
+    return NULL;
+}
+
+unsigned
+ClangExpression::ParseExpression (const char *expr_text, Stream &stream)
+{
+    // HACK: for now we have to make a function body around our expression
+    // since there is no way to parse a single expression line in LLVM/Clang.
+    std::string func_expr("void ___clang_expr()\n{\n\t");
+    func_expr.append(expr_text);
+    func_expr.append(";\n}");
+    return ParseBareExpression (func_expr, stream);
+
+}
+
+unsigned
+ClangExpression::ParseBareExpression (llvm::StringRef expr_text, Stream &stream)
+{
+    Mutex::Locker locker(GetClangMutex ());
+
+    TextDiagnosticBuffer text_diagnostic_buffer;
+
+    bool IsAST = false;
+    if (!CreateCompilerInstance (IsAST))
+    {
+        stream.Printf("error: couldn't create compiler instance\n");
+        return 1;
+    }
+    
+    // This code is matched below by a setClient to NULL.
+    // We cannot return out of this code without doing that.
+    m_clang_ap->getDiagnostics().setClient(&text_diagnostic_buffer);
+    text_diagnostic_buffer.FlushDiagnostics (m_clang_ap->getDiagnostics());
+    
+    MemoryBuffer *memory_buffer = MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__);
+
+    if (!m_clang_ap->hasSourceManager())
+        m_clang_ap->createSourceManager();
+
+    m_clang_ap->createFileManager();
+    m_clang_ap->createPreprocessor();
+    
+    // Build the ASTContext.  Most of this we inherit from the
+    // CompilerInstance, but we also want to give the context
+    // an ExternalASTSource.
+    SelectorTable selector_table;
+    std::auto_ptr<Builtin::Context> builtin_ap(new Builtin::Context(m_clang_ap->getTarget()));
+    ASTContext *Context = new ASTContext(m_clang_ap->getLangOpts(),
+                                         m_clang_ap->getSourceManager(),
+                                         m_clang_ap->getTarget(),
+                                         m_clang_ap->getPreprocessor().getIdentifierTable(),
+                                         selector_table,
+                                         *builtin_ap.get());
+    
+    llvm::OwningPtr<ExternalASTSource> ASTSource(new ClangASTSource(*Context, *m_decl_map));
+
+    if (m_decl_map)
+    {
+        Context->setExternalSource(ASTSource);
+    }
+    
+    m_clang_ap->setASTContext(Context);
+
+    FileID memory_buffer_file_id = m_clang_ap->getSourceManager().createMainFileIDForMemBuffer (memory_buffer);
+    std::string module_name("test_func");
+    text_diagnostic_buffer.BeginSourceFile(m_clang_ap->getLangOpts(), &m_clang_ap->getPreprocessor());
+
+    if (m_code_generator_ptr)
+        delete m_code_generator_ptr;
+    
+    m_code_generator_ptr = CreateLLVMCodeGen(m_clang_ap->getDiagnostics(),
+                                             module_name,
+                                             m_clang_ap->getCodeGenOpts(),
+                                             m_clang_ap->getLLVMContext());
+
+
+    // - CodeGeneration ASTConsumer (include/clang/ModuleBuilder.h), which will be passed in when you call...
+    // - Call clang::ParseAST (in lib/Sema/ParseAST.cpp) to parse the buffer. The CodeGenerator will generate code for __dbg_expr.
+    // - Once ParseAST completes, you can grab the llvm::Module from the CodeGenerator, which will have an llvm::Function you can hand off to the JIT.
+    ParseAST(m_clang_ap->getPreprocessor(), m_code_generator_ptr, m_clang_ap->getASTContext());
+
+    text_diagnostic_buffer.EndSourceFile();
+
+    //compiler_instance->getASTContext().getTranslationUnitDecl()->dump();
+
+    //if (compiler_instance->getFrontendOpts().ShowStats) {
+    //    compiler_instance->getFileManager().PrintStats();
+    //    fprintf(stderr, "\n");
+    //}
+    
+    // This code resolves the setClient above.
+    m_clang_ap->getDiagnostics().setClient(0);
+    
+    TextDiagnosticBuffer::const_iterator diag_iterator;
+    
+    int num_errors = 0;
+
+#ifdef COUNT_WARNINGS_AND_ERRORS
+    int num_warnings = 0;
+    
+    for (diag_iterator = text_diagnostic_buffer.warn_begin();
+         diag_iterator != text_diagnostic_buffer.warn_end();
+         ++diag_iterator)
+        num_warnings++;
+    
+    for (diag_iterator = text_diagnostic_buffer.err_begin();
+         diag_iterator != text_diagnostic_buffer.err_end();
+         ++diag_iterator)
+        num_errors++;    
+    
+    if (num_warnings || num_errors)
+    {
+        if (num_warnings)
+            stream.Printf("%u warning%s%s", num_warnings, (num_warnings == 1 ? "" : "s"), (num_errors ? " and " : ""));
+        if (num_errors)
+            stream.Printf("%u error%s", num_errors, (num_errors == 1 ? "" : "s"));
+        stream.Printf("\n");
+    }
+#endif
+    
+    for (diag_iterator = text_diagnostic_buffer.warn_begin();
+         diag_iterator != text_diagnostic_buffer.warn_end();
+         ++diag_iterator)
+        stream.Printf("warning: %s\n", (*diag_iterator).second.c_str());
+    
+    num_errors = 0;
+    
+    for (diag_iterator = text_diagnostic_buffer.err_begin();
+         diag_iterator != text_diagnostic_buffer.err_end();
+         ++diag_iterator)
+    {
+        num_errors++;
+        stream.Printf("error: %s\n", (*diag_iterator).second.c_str());
+    }
+    
+    return num_errors;
+}
+
+
+static FrontendAction *
+CreateFrontendAction(CompilerInstance &CI)
+{
+    // Create the underlying action.
+    FrontendAction *Act = CreateFrontendBaseAction(CI);
+    if (!Act)
+        return 0;
+
+    // If there are any AST files to merge, create a frontend action
+    // adaptor to perform the merge.
+    if (!CI.getFrontendOpts().ASTMergeFiles.empty())
+        Act = new ASTMergeAction(Act, &CI.getFrontendOpts().ASTMergeFiles[0],
+                                 CI.getFrontendOpts().ASTMergeFiles.size());
+
+    return Act;
+}
+
+
+unsigned
+ClangExpression::ConvertExpressionToDWARF (ClangExpressionVariableList& expr_local_variable_list, 
+                                           StreamString &dwarf_opcode_strm)
+{
+    CompilerInstance *compiler_instance = GetCompilerInstance();
+
+    DeclarationName hack_func_name(&compiler_instance->getASTContext().Idents.get("___clang_expr"));
+    DeclContext::lookup_result result = compiler_instance->getASTContext().getTranslationUnitDecl()->lookup(hack_func_name);
+
+    if (result.first != result.second)
+    {
+        Decl *decl = *result.first;
+        Stmt *decl_stmt = decl->getBody();
+        if (decl_stmt)
+        {
+            ClangStmtVisitor visitor(compiler_instance->getASTContext(), expr_local_variable_list, m_decl_map, dwarf_opcode_strm);
+
+            visitor.Visit (decl_stmt);
+        }
+    }
+    return 0;
+}
+
+bool
+ClangExpression::JITFunction (const ExecutionContext &exc_context, const char *name)
+{
+
+    llvm::Module *module = m_code_generator_ptr->GetModule();
+
+    if (module)
+    {
+        std::string error;
+
+        if (m_jit_mm_ptr == NULL)
+            m_jit_mm_ptr = new RecordingMemoryManager();
+
+        //llvm::InitializeNativeTarget();
+        if (m_execution_engine.get() == 0)
+            m_execution_engine.reset(llvm::ExecutionEngine::createJIT (module, &error, m_jit_mm_ptr));
+        m_execution_engine->DisableLazyCompilation();
+        llvm::Function *function = module->getFunction (llvm::StringRef (name));
+
+        // We don't actually need the function pointer here, this just forces it to get resolved.
+        void *fun_ptr = m_execution_engine->getPointerToFunction(function);
+        // Note, you probably won't get here on error, since the LLVM JIT tends to just
+        // exit on error at present...  So be careful.
+        if (fun_ptr == 0)
+            return false;
+        m_jitted_functions.push_back(ClangExpression::JittedFunction(name, (lldb::addr_t) fun_ptr));
+
+    }
+    return true;
+}
+
+bool
+ClangExpression::WriteJITCode (const ExecutionContext &exc_context)
+{
+    if (m_jit_mm_ptr == NULL)
+        return false;
+
+    if (exc_context.process == NULL)
+        return false;
+
+    // Look over the regions allocated for the function compiled.  The JIT
+    // tries to allocate the functions & stubs close together, so we should try to
+    // write them that way too...
+    // For now I only write functions with no stubs, globals, exception tables,
+    // etc.  So I only need to write the functions.
+
+    size_t size = 0;
+    std::map<uint8_t *, uint8_t *>::iterator fun_pos, fun_end = m_jit_mm_ptr->m_functions.end();
+    for (fun_pos = m_jit_mm_ptr->m_functions.begin(); fun_pos != fun_end; fun_pos++)
+    {
+        size += (*fun_pos).second - (*fun_pos).first;
+    }
+
+    Error error;
+    lldb::addr_t target_addr = exc_context.process->AllocateMemory (size, lldb::ePermissionsReadable|lldb::ePermissionsExecutable, error);
+
+    if (target_addr == LLDB_INVALID_ADDRESS)
+        return false;
+
+    lldb::addr_t cursor = target_addr;
+    for (fun_pos = m_jit_mm_ptr->m_functions.begin(); fun_pos != fun_end; fun_pos++)
+    {
+        lldb::addr_t lstart = (lldb::addr_t) (*fun_pos).first;
+        lldb::addr_t lend = (lldb::addr_t) (*fun_pos).second;
+        size_t size = lend - lstart;
+        exc_context.process->WriteMemory(cursor, (void *) lstart, size, error);
+        m_jit_mm_ptr->AddToLocalToRemoteMap (lstart, size, cursor);
+        cursor += size;
+    }
+
+    std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
+
+    for (pos = m_jitted_functions.begin(); pos != end; pos++)
+    {
+        (*pos).m_remote_addr = m_jit_mm_ptr->GetRemoteAddressForLocal ((*pos).m_local_addr);
+    }
+    return true;
+}
+
+lldb::addr_t
+ClangExpression::GetFunctionAddress (const char *name)
+{
+    std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
+
+    for (pos = m_jitted_functions.begin(); pos < end; pos++)
+    {
+        if (strcmp ((*pos).m_name.c_str(), name) == 0)
+            return (*pos).m_remote_addr;
+    }
+    return LLDB_INVALID_ADDRESS;
+}
+
+unsigned
+ClangExpression::Compile()
+{
+    Mutex::Locker locker(GetClangMutex ());
+    bool IsAST = false;
+    
+    if (CreateCompilerInstance(IsAST))
+    {
+        // Validate/process some options
+        if (m_clang_ap->getHeaderSearchOpts().Verbose)
+            llvm::errs() << "clang-cc version " CLANG_VERSION_STRING
+            << " based upon " << PACKAGE_STRING
+            << " hosted on " << llvm::sys::getHostTriple() << "\n";
+
+        // Enforce certain implications.
+        if (!m_clang_ap->getFrontendOpts().ViewClassInheritance.empty())
+            m_clang_ap->getFrontendOpts().ProgramAction = frontend::InheritanceView;
+//        if (!compiler_instance->getFrontendOpts().FixItSuffix.empty())
+//            compiler_instance->getFrontendOpts().ProgramAction = frontend::FixIt;
+
+        for (unsigned i = 0, e = m_clang_ap->getFrontendOpts().Inputs.size(); i != e; ++i) {
+            const std::string &InFile = m_clang_ap->getFrontendOpts().Inputs[i].second;
+
+            // If we aren't using an AST file, setup the file and source managers and
+            // the preprocessor.
+            if (!IsAST) {
+                if (!i) {
+                    // Create a file manager object to provide access to and cache the
+                    // filesystem.
+                    m_clang_ap->createFileManager();
+
+                    // Create the source manager.
+                    m_clang_ap->createSourceManager();
+                } else {
+                    // Reset the ID tables if we are reusing the SourceManager.
+                    m_clang_ap->getSourceManager().clearIDTables();
+                }
+
+                // Create the preprocessor.
+                m_clang_ap->createPreprocessor();
+            }
+
+            llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(*m_clang_ap.get()));
+            if (!Act)
+                break;
+
+            if (Act->BeginSourceFile(*m_clang_ap, InFile, IsAST)) {
+                Act->Execute();
+                Act->EndSourceFile();
+            }
+        }
+
+        if (m_clang_ap->getDiagnosticOpts().ShowCarets)
+        {
+            unsigned NumWarnings = m_clang_ap->getDiagnostics().getNumWarnings();
+            unsigned NumErrors = m_clang_ap->getDiagnostics().getNumErrors() -
+            m_clang_ap->getDiagnostics().getNumErrorsSuppressed();
+
+            if (NumWarnings || NumErrors)
+            {
+                if (NumWarnings)
+                    fprintf (stderr, "%u warning%s%s", NumWarnings, (NumWarnings == 1 ? "" : "s"), (NumErrors ? " and " : ""));
+                if (NumErrors)
+                    fprintf (stderr, "%u error%s", NumErrors, (NumErrors == 1 ? "" : "s"));
+                fprintf (stderr, " generated.\n");
+            }
+        }
+
+        if (m_clang_ap->getFrontendOpts().ShowStats) {
+            m_clang_ap->getFileManager().PrintStats();
+            fprintf(stderr, "\n");
+        }
+
+        // Return the appropriate status when verifying diagnostics.
+        //
+        // FIXME: If we could make getNumErrors() do the right thing, we wouldn't need
+        // this.
+        if (m_clang_ap->getDiagnosticOpts().VerifyDiagnostics)
+            return static_cast<VerifyDiagnosticsClient&>(m_clang_ap->getDiagnosticClient()).HadErrors();
+
+        return m_clang_ap->getDiagnostics().getNumErrors();
+    }
+    return 1;
+}
diff --git a/source/Expression/ClangExpressionDeclMap.cpp b/source/Expression/ClangExpressionDeclMap.cpp
new file mode 100644
index 0000000..1065211
--- /dev/null
+++ b/source/Expression/ClangExpressionDeclMap.cpp
@@ -0,0 +1,246 @@
+//===-- ClangExpressionDeclMap.cpp -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Expression/ClangExpressionDeclMap.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Expression/ClangASTSource.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/TypeList.h"
+#include "lldb/Symbol/Variable.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/ExecutionContext.h"
+
+//#define DEBUG_CEDM
+#ifdef DEBUG_CEDM
+#define DEBUG_PRINTF(...) fprintf(stderr, __VA_ARGS__)
+#else
+#define DEBUG_PRINTF(...)
+#endif
+
+using namespace lldb_private;
+using namespace clang;
+
+ClangExpressionDeclMap::ClangExpressionDeclMap(ExecutionContext *exe_ctx) :
+    m_exe_ctx(exe_ctx)
+{
+    if (exe_ctx && exe_ctx->frame)
+        m_sym_ctx = new SymbolContext(exe_ctx->frame->GetSymbolContext(lldb::eSymbolContextEverything));
+    else
+        m_sym_ctx = NULL;
+}
+
+ClangExpressionDeclMap::~ClangExpressionDeclMap()
+{
+    uint32_t num_tuples = m_tuples.size ();
+    uint32_t tuple_index;
+    
+    for (tuple_index = 0; tuple_index < num_tuples; ++tuple_index)
+        delete m_tuples[tuple_index].m_value;
+    
+    if (m_sym_ctx)
+        delete m_sym_ctx;
+}
+
+bool 
+ClangExpressionDeclMap::GetIndexForDecl (uint32_t &index,
+                                         const clang::Decl *decl)
+{
+    uint32_t num_tuples = m_tuples.size ();
+    uint32_t tuple_index;
+    
+    for (tuple_index = 0; tuple_index < num_tuples; ++tuple_index)
+    {
+        if (m_tuples[tuple_index].m_decl == decl) 
+        {
+            index = tuple_index;
+            return true;
+        }
+    }
+    
+    return false;
+}
+
+// Interface for DwarfExpression
+Value 
+*ClangExpressionDeclMap::GetValueForIndex (uint32_t index)
+{
+    if (index >= m_tuples.size ())
+        return NULL;
+    
+    return m_tuples[index].m_value;
+}
+
+// Interface for ClangASTSource
+void 
+ClangExpressionDeclMap::GetDecls(NameSearchContext &context,
+                                 const char *name)
+{
+    DEBUG_PRINTF("Hunting for a definition for %s\n", name);
+    
+    // Back out in all cases where we're not fully initialized
+    if (!m_exe_ctx || !m_exe_ctx->frame || !m_sym_ctx)
+        return;
+    
+    Function *function = m_sym_ctx->function;
+    Block *block = m_sym_ctx->block;
+    
+    if (!function || !block)
+    {
+        DEBUG_PRINTF("function = %p, block = %p\n", function, block);
+        return;
+    }
+    
+    BlockList& blocks = function->GetBlocks(true);
+    
+    lldb::user_id_t current_block_id = block->GetID();
+    
+    ConstString name_cs(name);
+    
+    for (current_block_id = block->GetID();
+         current_block_id != Block::InvalidID;
+         current_block_id = blocks.GetParent(current_block_id))
+    {
+        Block *current_block = blocks.GetBlockByID(current_block_id);
+        
+        lldb::VariableListSP var_list = current_block->GetVariableList(false, true);
+        
+        if (!var_list)
+            continue;
+        
+        lldb::VariableSP var = var_list->FindVariable(name_cs);
+        
+        if (!var)
+            continue;
+        
+        AddOneVariable(context, var.get());
+        return;
+    }
+    
+    {
+        CompileUnit *compile_unit = m_sym_ctx->comp_unit;
+        
+        if (!compile_unit)
+        {
+            DEBUG_PRINTF("compile_unit = %p\n", compile_unit);
+            return;
+        }
+        
+        lldb::VariableListSP var_list = compile_unit->GetVariableList(true);
+        
+        if (!var_list)
+            return;
+        
+        lldb::VariableSP var = var_list->FindVariable(name_cs);
+        
+        if (!var)
+            return;
+        
+        AddOneVariable(context, var.get());
+        return;
+    }
+}
+
+void
+ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
+                                       Variable* var)
+{
+    Type *var_type = var->GetType();
+    
+    if (!var_type) 
+    {
+        DEBUG_PRINTF("Skipped a definition for %s because it has no type\n", name);
+        return;
+    }
+    
+    void *var_opaque_type = var_type->GetOpaqueClangQualType();
+    
+    if (!var_opaque_type)
+    {
+        DEBUG_PRINTF("Skipped a definition for %s because it has no Clang type\n", name);
+        return;
+    }
+    
+    DWARFExpression &var_location_expr = var->LocationExpression();
+    
+    TypeList *type_list = var_type->GetTypeList();
+    
+    if (!type_list)
+    {
+        DEBUG_PRINTF("Skipped a definition for %s because the type has no associated type list\n", name);
+        return;
+    }
+    
+    clang::ASTContext *exe_ast_ctx = type_list->GetClangASTContext().getASTContext();
+    
+    if (!exe_ast_ctx)
+    {
+        DEBUG_PRINTF("There is no AST context for the current execution context\n");
+        return;
+    }
+    
+    std::auto_ptr<Value> var_location(new Value);
+    
+    Error err;
+    
+    if (!var_location_expr.Evaluate(m_exe_ctx, exe_ast_ctx, NULL, *var_location.get(), &err))
+    {
+        DEBUG_PRINTF("Error evaluating the location of %s: %s\n", name, err.AsCString());
+        return;
+    }
+    
+    void *copied_type = ClangASTContext::CopyType(context.GetASTContext(), type_list->GetClangASTContext().getASTContext(), var_opaque_type);
+    
+    if (var_location.get()->GetContextType() == Value::eContextTypeInvalid)
+        var_location.get()->SetContext(Value::eContextTypeOpaqueClangQualType, copied_type);
+    
+    if (var_location.get()->GetValueType() == Value::eValueTypeFileAddress)
+    {
+        SymbolContext var_sc;
+        var->CalculateSymbolContext(&var_sc);
+    
+        if (!var_sc.module_sp)
+            return;
+        
+        ObjectFile *object_file = var_sc.module_sp->GetObjectFile();
+        
+        if (!object_file)
+            return;
+    
+        Address so_addr(var_location->GetScalar().ULongLong(), object_file->GetSectionList());
+        
+        lldb::addr_t load_addr = so_addr.GetLoadAddress(m_exe_ctx->process);
+        
+        var_location->GetScalar() = load_addr;
+        var_location->SetValueType(Value::eValueTypeLoadAddress);
+    }
+    
+    NamedDecl *var_decl = context.AddVarDecl(copied_type);
+    
+    Tuple tuple;
+    
+    tuple.m_decl  = var_decl;
+    tuple.m_value = var_location.release();
+    
+    m_tuples.push_back(tuple);
+    
+    DEBUG_PRINTF("Found for a definition for %s\n", name);    
+}
diff --git a/source/Expression/ClangExpressionVariable.cpp b/source/Expression/ClangExpressionVariable.cpp
new file mode 100644
index 0000000..40fee4b
--- /dev/null
+++ b/source/Expression/ClangExpressionVariable.cpp
@@ -0,0 +1,100 @@
+//===-- ClangExpressionVariable.cpp -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Expression/ClangExpressionVariable.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "clang/AST/ASTContext.h"
+
+using namespace lldb_private;
+using namespace clang;
+
+ClangExpressionVariableList::ClangExpressionVariableList() :
+    m_variables()
+{
+}
+
+ClangExpressionVariableList::~ClangExpressionVariableList()
+{
+    uint32_t num_variables = m_variables.size();
+    uint32_t var_index;
+        
+    for (var_index = 0; var_index < num_variables; ++var_index)
+        delete m_variables[var_index].m_value;
+}
+
+Value *
+ValueForDecl(ASTContext &ast_context, const VarDecl *var_decl)
+{
+    Value *ret = new Value;
+        
+    ret->SetContext(Value::eContextTypeOpaqueClangQualType, 
+                    var_decl->getType().getAsOpaquePtr());
+    
+    uint64_t bit_width = ast_context.getTypeSize(var_decl->getType());
+    
+    uint32_t byte_size = (bit_width + 7 ) / 8;
+    
+    ret->ResizeData(byte_size);
+    
+    return ret;
+}
+
+Value *
+ClangExpressionVariableList::GetVariableForVarDecl (ASTContext &ast_context, const VarDecl *var_decl, uint32_t& idx, bool can_create)
+{
+    uint32_t num_variables = m_variables.size();
+    uint32_t var_index;
+    
+    for (var_index = 0; var_index < num_variables; ++var_index)
+    {
+        if (m_variables[var_index].m_var_decl == var_decl)
+        {
+            idx = var_index;
+            return m_variables[var_index].m_value;
+        }
+    }
+
+    if (!can_create)
+        return NULL;
+    
+    idx = m_variables.size();
+    
+    ClangExpressionVariable val;
+    val.m_var_decl = var_decl;
+    val.m_value = ValueForDecl(ast_context, var_decl);
+    m_variables.push_back(val);
+    
+    return m_variables.back().m_value;
+}
+
+Value *
+ClangExpressionVariableList::GetVariableAtIndex (uint32_t idx)
+{
+    if (idx < m_variables.size())
+        return m_variables[idx].m_value;
+    
+    return NULL;
+}
+
+uint32_t
+ClangExpressionVariableList::AppendValue (Value *value)
+{
+    uint32_t idx = m_variables.size();
+    
+    ClangExpressionVariable val;
+    val.m_var_decl = NULL;
+    val.m_value = value;
+    
+    m_variables.push_back(val);
+    return idx;
+}
diff --git a/source/Expression/ClangFunction.cpp b/source/Expression/ClangFunction.cpp
new file mode 100644
index 0000000..e8713d0
--- /dev/null
+++ b/source/Expression/ClangFunction.cpp
@@ -0,0 +1,671 @@
+//===-- ClangFunction.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
+// C++ Includes
+// Other libraries and framework includes
+#include "clang/Frontend/CodeGenAction.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecordLayout.h"
+#include "llvm/ExecutionEngine/JIT.h"
+#include "llvm/Module.h"
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "llvm/ADT/StringRef.h"
+
+// Project includes
+#include "lldb/Expression/ClangFunction.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectList.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanCallFunction.h"
+#include "lldb/Core/Log.h"
+
+using namespace lldb_private;
+//----------------------------------------------------------------------
+// ClangFunction constructor
+//----------------------------------------------------------------------
+ClangFunction::ClangFunction(const char *target_triple, ClangASTContext *ast_context, void *return_qualtype, const Address& functionAddress, const ValueList &arg_value_list) :
+    ClangExpression (target_triple, NULL),
+    m_function_addr (functionAddress),
+    m_function_ptr (NULL),
+    m_arg_values (arg_value_list),
+    m_clang_ast_context (ast_context),
+    m_function_return_qual_type(return_qualtype),
+    m_wrapper_function_name ("__lldb_caller_function"),
+    m_wrapper_struct_name ("__lldb_caller_struct"),
+    m_return_offset(0),
+    m_compiled (false),
+    m_JITted (false)
+{
+}
+
+ClangFunction::ClangFunction(const char *target_triple, Function &function, ClangASTContext *ast_context, const ValueList &arg_value_list) :
+    ClangExpression (target_triple, NULL),
+    m_function_ptr (&function),
+    m_arg_values (arg_value_list),
+    m_clang_ast_context (ast_context),
+    m_function_return_qual_type (NULL),
+    m_wrapper_function_name ("__lldb_function_caller"),
+    m_wrapper_struct_name ("__lldb_caller_struct"),
+    m_return_offset(0),
+    m_compiled (false),
+    m_JITted (false)
+{
+    m_function_addr = m_function_ptr->GetAddressRange().GetBaseAddress();
+    m_function_return_qual_type = m_function_ptr->GetReturnType().GetOpaqueClangQualType();
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ClangFunction::~ClangFunction()
+{
+}
+
+unsigned
+ClangFunction::CompileFunction (Stream &errors)
+{
+    // FIXME: How does clang tell us there's no return value?  We need to handle that case.
+    unsigned num_errors = 0;
+    
+    if (!m_compiled)
+    {
+        std::string return_type_str = ClangASTContext::GetTypeName(m_function_return_qual_type);
+        
+        // Cons up the function we're going to wrap our call in, then compile it...
+        // We declare the function "extern "C"" because the compiler might be in C++
+        // mode which would mangle the name and then we couldn't find it again...
+        std::string expression;
+        expression.append ("extern \"C\" void ");
+        expression.append (m_wrapper_function_name);
+        expression.append (" (void *input)\n{\n    struct ");
+        expression.append (m_wrapper_struct_name);
+        expression.append (" \n  {\n");
+        expression.append ("    ");
+        expression.append (return_type_str);
+        expression.append (" (*fn_ptr) (");
+
+        // Get the number of arguments.  If we have a function type and it is prototyped,
+        // trust that, otherwise use the values we were given.
+
+        // FIXME: This will need to be extended to handle Variadic functions.  We'll need
+        // to pull the defined arguments out of the function, then add the types from the
+        // arguments list for the variable arguments.
+
+        size_t num_args = -1;
+        bool trust_function = false;
+        // GetArgumentCount returns -1 for an unprototyped function.
+        if (m_function_ptr)
+        {
+            num_args = m_function_ptr->GetArgumentCount();
+            if (num_args != -1)
+                trust_function = true;
+        }
+
+        if (num_args == -1)
+            num_args = m_arg_values.GetSize();
+
+        std::string args_buffer;  // This one stores the definition of all the args in "struct caller".
+        std::string args_list_buffer;  // This one stores the argument list called from the structure.
+        for (int i = 0; i < num_args; i++)
+        {
+            const char *type_string;
+            std::string type_stdstr;
+
+            if (trust_function)
+            {
+                type_string = m_function_ptr->GetArgumentTypeAtIndex(i).GetName().AsCString();
+            }
+            else
+            {
+                Value *arg_value = m_arg_values.GetValueAtIndex(i);
+                void *clang_qual_type = arg_value->GetOpaqueClangQualType ();
+                if (clang_qual_type != NULL)
+                {
+                    type_stdstr = ClangASTContext::GetTypeName(clang_qual_type);
+                    type_string = type_stdstr.c_str();
+                }
+                else
+                {   
+                    errors.Printf("Could not determine type of input value %d.", i);
+                    return 1;
+                }
+            }
+
+
+            expression.append (type_string);
+            if (i < num_args - 1)
+                expression.append (", ");
+
+            char arg_buf[32];
+            args_buffer.append ("    ");
+            args_buffer.append (type_string);
+            snprintf(arg_buf, 31, "arg_%d", i);
+            args_buffer.push_back (' ');
+            args_buffer.append (arg_buf);
+            args_buffer.append (";\n");
+
+            args_list_buffer.append ("__lldb_fn_data->");
+            args_list_buffer.append (arg_buf);
+            if (i < num_args - 1)
+                args_list_buffer.append (", ");
+
+        }
+        expression.append (");\n"); // Close off the function calling prototype.
+
+        expression.append (args_buffer);
+
+        expression.append ("    ");
+        expression.append (return_type_str);
+        expression.append (" return_value;");
+        expression.append ("\n  };\n  struct ");
+        expression.append (m_wrapper_struct_name);
+        expression.append ("* __lldb_fn_data = (struct ");
+        expression.append (m_wrapper_struct_name);
+        expression.append (" *) input;\n");
+
+        expression.append ("  __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr (");
+        expression.append (args_list_buffer);
+        expression.append (");\n}\n");
+
+        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+        if (log)
+            log->Printf ("Expression: \n\n%s\n\n", expression.c_str());
+            
+        // Okay, now compile this expression:
+        num_errors = ParseBareExpression (expression.c_str(), errors);
+        m_compiled = (num_errors == 0);
+        
+        if (m_compiled)
+        {
+            using namespace clang;
+            CompilerInstance *compiler_instance = GetCompilerInstance();
+            ASTContext &ast_context = compiler_instance->getASTContext();
+
+            DeclarationName wrapper_func_name(&ast_context.Idents.get(m_wrapper_function_name.c_str()));
+            FunctionDecl::lookup_result func_lookup = ast_context.getTranslationUnitDecl()->lookup(wrapper_func_name);
+            if (func_lookup.first == func_lookup.second)
+                return false;
+
+            FunctionDecl *wrapper_func = dyn_cast<FunctionDecl> (*(func_lookup.first));
+            if (!wrapper_func)
+                return false;
+
+            DeclarationName wrapper_struct_name(&ast_context.Idents.get(m_wrapper_struct_name.c_str()));
+            RecordDecl::lookup_result struct_lookup = wrapper_func->lookup(wrapper_struct_name);
+            if (struct_lookup.first == struct_lookup.second)
+                return false;
+
+            RecordDecl *wrapper_struct = dyn_cast<RecordDecl>(*(struct_lookup.first));
+
+            if (!wrapper_struct)
+                return false;
+
+            m_struct_layout = &ast_context.getASTRecordLayout (wrapper_struct);
+            if (!m_struct_layout)
+            {
+                m_compiled = false;
+                return 1;
+            }
+            m_return_offset = m_struct_layout->getFieldOffset(m_struct_layout->getFieldCount() - 1);
+            m_return_size = (m_struct_layout->getDataSize() - m_return_offset)/8;
+        }
+    }
+
+    return num_errors;
+}
+
+bool
+ClangFunction::WriteFunctionWrapper (ExecutionContext &exc_context, Stream &errors)
+{
+    Process *process = exc_context.process;
+
+    if (process == NULL)
+        return false;
+
+    if (!m_JITted)
+    {
+        // Next we should JIT it and insert the result into the target program.
+        if (!JITFunction (exc_context, m_wrapper_function_name.c_str()))
+            return false;
+
+        if (!WriteJITCode (exc_context))
+            return false;
+
+        m_JITted = true;
+    }
+
+    // Next get the call address for the function:
+    m_wrapper_fun_addr = GetFunctionAddress (m_wrapper_function_name.c_str());
+    if (m_wrapper_fun_addr == LLDB_INVALID_ADDRESS)
+        return false;
+
+    return true;
+}
+
+bool
+ClangFunction::WriteFunctionArguments (ExecutionContext &exc_context, lldb::addr_t &args_addr_ref, Stream &errors)
+{
+    return WriteFunctionArguments(exc_context, args_addr_ref, m_function_addr, m_arg_values, errors);    
+}
+
+// FIXME: Assure that the ValueList we were passed in is consistent with the one that defined this function.
+
+bool
+ClangFunction::WriteFunctionArguments (ExecutionContext &exc_context, lldb::addr_t &args_addr_ref, Address function_address, ValueList &arg_values, Stream &errors)
+{
+    // Otherwise, allocate space for the argument passing struct, and write it.
+    // We use the information in the expression parser AST to
+    // figure out how to do this...
+    // We should probably transcode this in this object so we can ditch the compiler instance
+    // and all its associated data, and just keep the JITTed bytes.
+
+    Error error;
+    using namespace clang;
+    ExecutionResults return_value = eExecutionSetupError;
+
+    Process *process = exc_context.process;
+
+    if (process == NULL)
+        return return_value;
+        
+    uint64_t struct_size = m_struct_layout->getSize()/8; // Clang returns sizes in bytes.
+    
+    if (args_addr_ref == LLDB_INVALID_ADDRESS)
+    {
+        args_addr_ref = process->AllocateMemory(struct_size, lldb::ePermissionsReadable|lldb::ePermissionsWritable, error);
+        if (args_addr_ref == LLDB_INVALID_ADDRESS)
+            return false;
+        m_wrapper_args_addrs.push_back (args_addr_ref);
+    } 
+    else 
+    {
+        // Make sure this is an address that we've already handed out.
+        if (find (m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr_ref) == m_wrapper_args_addrs.end())
+        {
+            return false;
+        }
+    }
+
+    // FIXME: This is fake, and just assumes that it matches that architecture.
+    // Make a data extractor and put the address into the right byte order & size.
+
+    uint64_t fun_addr = function_address.GetLoadAddress(exc_context.process);
+    int first_offset = m_struct_layout->getFieldOffset(0)/8;
+    process->WriteMemory(args_addr_ref + first_offset, &fun_addr, 8, error);
+
+    // FIXME: We will need to extend this for Variadic functions.
+
+    Error value_error;
+    
+    size_t num_args = arg_values.GetSize();
+    if (num_args != m_arg_values.GetSize())
+    {
+        errors.Printf ("Wrong number of arguments - was: %d should be: %d", num_args, m_arg_values.GetSize());
+        return false;
+    }
+    
+    for (int i = 0; i < num_args; i++)
+    {
+        // FIXME: We should sanity check sizes.
+
+        int offset = m_struct_layout->getFieldOffset(i+1)/8; // Clang sizes are in bytes.
+        Value *arg_value = arg_values.GetValueAtIndex(i);
+        
+        // FIXME: For now just do scalars:
+        
+        // Special case: if it's a pointer, don't do anything (the ABI supports passing cstrings)
+        
+        if (arg_value->GetValueType() == Value::eValueTypeHostAddress &&
+            arg_value->GetContextType() == Value::eContextTypeOpaqueClangQualType &&
+            ClangASTContext::IsPointerType(arg_value->GetValueOpaqueClangQualType()))
+            continue;
+        
+        const Scalar &arg_scalar = arg_value->ResolveValue(&exc_context, m_clang_ast_context->getASTContext());
+
+        int byte_size = arg_scalar.GetByteSize();
+        std::vector<uint8_t> buffer;
+        buffer.resize(byte_size);
+        DataExtractor value_data;
+        arg_scalar.GetData (value_data);
+        value_data.ExtractBytes(0, byte_size, process->GetByteOrder(), buffer.data());
+        process->WriteMemory(args_addr_ref + offset, buffer.data(), byte_size, error);
+    }
+
+    return true;
+}
+
+bool
+ClangFunction::InsertFunction (ExecutionContext &exc_context, lldb::addr_t &args_addr_ref, Stream &errors)
+{
+    using namespace clang;
+    
+    if (CompileFunction(errors) != 0)
+        return false;
+    if (!WriteFunctionWrapper(exc_context, errors))
+        return false;
+    if (!WriteFunctionArguments(exc_context, args_addr_ref, errors))
+        return false;
+
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+    if (log)
+        log->Printf ("Call Address: 0x%llx Struct Address: 0x%llx.\n", m_wrapper_fun_addr, args_addr_ref);
+        
+    return true;
+}
+
+ThreadPlan *
+ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exc_context, lldb::addr_t &args_addr, Stream &errors, bool stop_others, bool discard_on_error)
+{
+    // FIXME: Use the errors Stream for better error reporting.
+
+    Process *process = exc_context.process;
+
+    if (process == NULL)
+    {
+        errors.Printf("Can't call a function without a process.");
+        return NULL;
+    }
+
+    // Okay, now run the function:
+
+    Address wrapper_address (NULL, m_wrapper_fun_addr);
+    ThreadPlan *new_plan = new ThreadPlanCallFunction (*exc_context.thread, 
+                                          wrapper_address,
+                                          args_addr,
+                                          stop_others, discard_on_error);
+    return new_plan;
+}
+
+bool
+ClangFunction::FetchFunctionResults (ExecutionContext &exc_context, lldb::addr_t args_addr, Value &ret_value)
+{
+    // Read the return value - it is the last field in the struct:
+    // FIXME: How does clang tell us there's no return value?  We need to handle that case.
+    
+    std::vector<uint8_t> data_buffer;
+    data_buffer.resize(m_return_size);
+    Process *process = exc_context.process;
+    Error error;
+    size_t bytes_read = process->ReadMemory(args_addr + m_return_offset/8, data_buffer.data(), m_return_size, error);
+
+    if (bytes_read == 0)
+    {
+        return false;
+    }
+
+    if (bytes_read < m_return_size)
+        return false;
+
+    DataExtractor data(data_buffer.data(), m_return_size, process->GetByteOrder(), process->GetAddressByteSize());
+    // FIXME: Assuming an integer scalar for now:
+    
+    uint32_t offset = 0;
+    uint64_t return_integer = data.GetMaxU64(&offset, m_return_size);
+    
+    ret_value.SetContext (Value::eContextTypeOpaqueClangQualType, m_function_return_qual_type);
+    ret_value.SetValueType(Value::eValueTypeScalar);
+    ret_value.GetScalar() = return_integer;
+    return true;
+}
+
+void
+ClangFunction::DeallocateFunctionResults (ExecutionContext &exc_context, lldb::addr_t args_addr)
+{
+    std::list<lldb::addr_t>::iterator pos;
+    pos = std::find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr);
+    if (pos != m_wrapper_args_addrs.end())
+        m_wrapper_args_addrs.erase(pos);
+    
+    exc_context.process->DeallocateMemory(args_addr);
+}
+
+ClangFunction::ExecutionResults
+ClangFunction::ExecuteFunction(ExecutionContext &exc_context, Stream &errors, Value &results)
+{
+    return ExecuteFunction (exc_context, errors, 1000, true, results);
+}
+
+ClangFunction::ExecutionResults
+ClangFunction::ExecuteFunction(ExecutionContext &exc_context, Stream &errors, bool stop_others, Value &results)
+{
+    return ExecuteFunction (exc_context, NULL, errors, stop_others, NULL, false, results);
+}
+
+ClangFunction::ExecutionResults
+ClangFunction::ExecuteFunction(
+        ExecutionContext &exc_context, 
+        Stream &errors, 
+        uint32_t single_thread_timeout_usec, 
+        bool try_all_threads, 
+        Value &results)
+{
+    return ExecuteFunction (exc_context, NULL, errors, true, single_thread_timeout_usec, try_all_threads, results);
+}
+
+ClangFunction::ExecutionResults
+ClangFunction::ExecuteFunction(
+        ExecutionContext &exc_context, 
+        lldb::addr_t *args_addr_ptr, 
+        Stream &errors, 
+        bool stop_others, 
+        uint32_t single_thread_timeout_usec, 
+        bool try_all_threads, 
+        Value &results)
+{
+    using namespace clang;
+    ExecutionResults return_value = eExecutionSetupError;
+    Process *process = exc_context.process;
+    
+    lldb::addr_t args_addr;
+    
+    if (args_addr_ptr != NULL)
+        args_addr = *args_addr_ptr;
+    else
+        args_addr = LLDB_INVALID_ADDRESS;
+        
+    if (CompileFunction(errors) != 0)
+        return eExecutionSetupError;
+    
+    if (args_addr == LLDB_INVALID_ADDRESS)
+    {
+        if (!InsertFunction(exc_context, args_addr, errors))
+            return eExecutionSetupError;
+    }
+    
+    
+    lldb::ThreadPlanSP call_plan_sp(GetThreadPlanToCallFunction(exc_context, args_addr, errors, stop_others, false));
+    
+    ThreadPlanCallFunction *call_plan_ptr = static_cast<ThreadPlanCallFunction *> (call_plan_sp.get());
+    
+    if (args_addr_ptr != NULL)
+        *args_addr_ptr = args_addr;
+    
+    if (call_plan_sp == NULL)
+        return return_value;
+
+    call_plan_sp->SetPrivate(true);
+    exc_context.thread->QueueThreadPlan(call_plan_sp, true);
+
+    // We need to call the function synchronously, so spin waiting for it to return.
+    // If we get interrupted while executing, we're going to lose our context, and
+    // won't be able to gather the result at this point.
+
+    TimeValue* timeout_ptr = NULL;
+    TimeValue real_timeout;
+    if (single_thread_timeout_usec != 0)
+    {
+        real_timeout = TimeValue::Now();
+        real_timeout.OffsetWithMicroSeconds(single_thread_timeout_usec);
+        timeout_ptr = &real_timeout;
+    }
+    process->Resume ();
+
+    
+    while (1)
+    {
+        lldb::EventSP event_sp;
+
+        // Now wait for the process to stop again:
+        // FIXME: Probably want a time out.
+        lldb::StateType stop_state =  process->WaitForStateChangedEvents (timeout_ptr, event_sp);
+        if (stop_state == lldb::eStateInvalid && timeout_ptr != NULL)
+        {
+            // Right now this is the only way to tell we've timed out...
+            // We should interrupt the process here...
+            // Not really sure what to do if Halt fails here...
+            Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+            if (log)
+                log->Printf ("Running function with timeout: %d timed out, trying with all threads enabled.", single_thread_timeout_usec);
+
+            if (process->Halt().Success())
+            {
+                timeout_ptr = NULL;
+                
+                lldb::StateType stop_state =  process->WaitForStateChangedEvents (timeout_ptr, event_sp);
+                if (stop_state == lldb::eStateInvalid)
+                {
+                    errors.Printf ("Got an invalid stop state after halt.");
+                }
+                else if (stop_state != lldb::eStateStopped)
+                {
+                    StreamString s;
+                    event_sp->Dump (&s);
+                    
+                    errors.Printf("Didn't get a stopped event after Halting the target, got: \"%s\"", s.GetData());
+                }
+                
+                if (try_all_threads)
+                {
+                    // Between the time that we got the timeout and the time we halted, but target
+                    // might have actually completed the plan.  If so, we're done.
+                    if (exc_context.thread->IsThreadPlanDone (call_plan_sp.get()))
+                    {
+                        return_value = eExecutionCompleted;
+                        break;
+                    }
+                
+
+                    call_plan_ptr->SetStopOthers (false);
+                    process->Resume();
+                    continue;
+                }
+                else
+                    return eExecutionInterrupted;
+            }
+        }
+        if (stop_state == lldb::eStateRunning || stop_state == lldb::eStateStepping)
+            continue;
+
+        if (exc_context.thread->IsThreadPlanDone (call_plan_sp.get()))
+        {
+            return_value = eExecutionCompleted;
+            break;
+        }
+        else if (exc_context.thread->WasThreadPlanDiscarded (call_plan_sp.get()))
+        {
+            return_value = eExecutionDiscarded;
+            break;
+        }
+        else
+        {
+            return_value = eExecutionInterrupted;
+            break;
+        }
+
+    }
+
+    if (return_value != eExecutionCompleted)
+        return return_value;
+
+    FetchFunctionResults(exc_context, args_addr, results);
+    
+    if (args_addr_ptr == NULL)
+        DeallocateFunctionResults(exc_context, args_addr);
+        
+    return eExecutionCompleted;
+}
+
+ClangFunction::ExecutionResults
+ClangFunction::ExecuteFunctionWithABI(ExecutionContext &exc_context, Stream &errors, Value &results)
+{
+    // FIXME: Use the errors Stream for better error reporting. 
+    using namespace clang;
+    ExecutionResults return_value = eExecutionSetupError;
+    
+    Process *process = exc_context.process;
+    
+    if (process == NULL)
+    {
+        errors.Printf("Can't call a function without a process.");
+        return return_value;
+    }
+    
+    //unsigned int num_args = m_arg_values.GetSize();
+    //unsigned int arg_index;
+    
+    //for (arg_index = 0; arg_index < num_args; ++arg_index)
+    //    m_arg_values.GetValueAtIndex(arg_index)->ResolveValue(&exc_context, GetASTContext());
+    
+    ThreadPlan *call_plan = exc_context.thread->QueueThreadPlanForCallFunction (false,
+                                                                                m_function_addr,
+                                                                                m_arg_values,
+                                                                                true);
+    if (call_plan == NULL)
+        return return_value;
+    
+    call_plan->SetPrivate(true);
+    
+    // We need to call the function synchronously, so spin waiting for it to return.
+    // If we get interrupted while executing, we're going to lose our context, and 
+    // won't be able to gather the result at this point.
+    
+    process->Resume ();
+    
+    while (1)
+    {
+        lldb::EventSP event_sp;
+        
+        // Now wait for the process to stop again:
+        // FIXME: Probably want a time out.
+        lldb::StateType stop_state =  process->WaitForStateChangedEvents (NULL, event_sp);
+        if (stop_state == lldb::eStateRunning || stop_state == lldb::eStateStepping)
+            continue;
+        
+        if (exc_context.thread->IsThreadPlanDone (call_plan))
+        {
+            return_value = eExecutionCompleted;
+            break;
+        }
+        else if (exc_context.thread->WasThreadPlanDiscarded (call_plan))
+        {
+            return_value = eExecutionDiscarded;
+            break;
+        }
+        else
+        {
+            return_value = eExecutionInterrupted;
+            break;
+        }
+        
+    }
+    
+    return eExecutionCompleted;
+}
diff --git a/source/Expression/ClangStmtVisitor.cpp b/source/Expression/ClangStmtVisitor.cpp
new file mode 100644
index 0000000..1d2f53f
--- /dev/null
+++ b/source/Expression/ClangStmtVisitor.cpp
@@ -0,0 +1,1032 @@
+//===-- ClangStmtVisitor.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Expression/ClangStmtVisitor.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "clang/AST/RecordLayout.h"
+
+#define NO_RTTI
+#include "lldb/Core/dwarf.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Expression/ClangExpressionDeclMap.h"
+#include "lldb/Expression/ClangExpressionVariable.h"
+
+//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
+#ifdef ENABLE_DEBUG_PRINTF
+#include <stdio.h>
+#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
+#else
+#define DEBUG_PRINTF(fmt, ...)
+#endif
+
+// Project includes
+
+static lldb_private::Scalar::Type
+GetScalarTypeForClangType (clang::ASTContext &ast_context, clang::QualType clang_type, uint32_t &count)
+{
+    count = 1;
+
+    switch (clang_type->getTypeClass())
+    {
+    case clang::Type::FunctionNoProto:
+    case clang::Type::FunctionProto:
+        break;
+
+    case clang::Type::IncompleteArray:
+    case clang::Type::VariableArray:
+        break;
+
+    case clang::Type::ConstantArray:
+        break;
+
+    case clang::Type::ExtVector:
+    case clang::Type::Vector:
+        // TODO: Set this to more than one???
+        break;
+
+    case clang::Type::Builtin:
+        switch (cast<clang::BuiltinType>(clang_type)->getKind())
+        {
+        default: assert(0 && "Unknown builtin type!");
+        case clang::BuiltinType::Void:
+            break;
+
+        case clang::BuiltinType::Bool:
+        case clang::BuiltinType::Char_S:
+        case clang::BuiltinType::SChar:
+        case clang::BuiltinType::WChar:
+        case clang::BuiltinType::Char16:
+        case clang::BuiltinType::Char32:
+        case clang::BuiltinType::Short:
+        case clang::BuiltinType::Int:
+        case clang::BuiltinType::Long:
+        case clang::BuiltinType::LongLong:
+        case clang::BuiltinType::Int128:
+            return lldb_private::Scalar::GetValueTypeForSignedIntegerWithByteSize ((ast_context.getTypeSize(clang_type)/CHAR_BIT)/count);
+
+        case clang::BuiltinType::Char_U:
+        case clang::BuiltinType::UChar:
+        case clang::BuiltinType::UShort:
+        case clang::BuiltinType::UInt:
+        case clang::BuiltinType::ULong:
+        case clang::BuiltinType::ULongLong:
+        case clang::BuiltinType::UInt128:
+        case clang::BuiltinType::NullPtr:
+            return lldb_private::Scalar::GetValueTypeForUnsignedIntegerWithByteSize ((ast_context.getTypeSize(clang_type)/CHAR_BIT)/count);
+
+        case clang::BuiltinType::Float:
+        case clang::BuiltinType::Double:
+        case clang::BuiltinType::LongDouble:
+            return lldb_private::Scalar::GetValueTypeForFloatWithByteSize ((ast_context.getTypeSize(clang_type)/CHAR_BIT)/count);
+        }
+        break;
+    // All pointer types are represented as unsigned integer encodings.
+    // We may nee to add a eEncodingPointer if we ever need to know the
+    // difference
+    case clang::Type::ObjCObjectPointer:
+    case clang::Type::BlockPointer:
+    case clang::Type::Pointer:
+    case clang::Type::LValueReference:
+    case clang::Type::RValueReference:
+    case clang::Type::MemberPointer:
+        return lldb_private::Scalar::GetValueTypeForUnsignedIntegerWithByteSize ((ast_context.getTypeSize(clang_type)/CHAR_BIT)/count);
+
+    // Complex numbers are made up of floats
+    case clang::Type::Complex:
+        count = 2;
+        return lldb_private::Scalar::GetValueTypeForFloatWithByteSize ((ast_context.getTypeSize(clang_type)/CHAR_BIT) / count);
+
+    case clang::Type::ObjCInterface:            break;
+    case clang::Type::Record:                   break;
+    case clang::Type::Enum:
+        return lldb_private::Scalar::GetValueTypeForSignedIntegerWithByteSize ((ast_context.getTypeSize(clang_type)/CHAR_BIT)/count);
+
+    case clang::Type::Typedef:
+        return GetScalarTypeForClangType(ast_context, cast<clang::TypedefType>(clang_type)->LookThroughTypedefs(), count);
+        break;
+
+    case clang::Type::TypeOfExpr:
+    case clang::Type::TypeOf:
+    case clang::Type::Decltype:
+    //case clang::Type::QualifiedName:
+    case clang::Type::TemplateSpecialization:   break;
+    }
+    count = 0;
+    return lldb_private::Scalar::e_void;
+}
+
+//----------------------------------------------------------------------
+// ClangStmtVisitor constructor
+//----------------------------------------------------------------------
+lldb_private::ClangStmtVisitor::ClangStmtVisitor
+(
+    clang::ASTContext &ast_context,
+    lldb_private::ClangExpressionVariableList &variable_list,
+    lldb_private::ClangExpressionDeclMap *decl_map,
+    lldb_private::StreamString &strm
+) :
+    m_ast_context (ast_context),
+    m_variable_list (variable_list),
+    m_decl_map (decl_map),
+    m_stream (strm)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+lldb_private::ClangStmtVisitor::~ClangStmtVisitor()
+{
+}
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitStmt (clang::Stmt *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+
+    clang::Stmt::child_iterator pos;
+    clang::Stmt::child_iterator begin = Node->child_begin();
+    clang::Stmt::child_iterator end = Node->child_end();
+    bool clear_before_next_stmt = false;
+    for (pos = begin; pos != end; ++pos)
+    {
+#ifdef ENABLE_DEBUG_PRINTF
+        pos->dump();
+#endif
+        clang::Stmt *child_stmt = *pos;
+        uint32_t pre_visit_stream_offset = m_stream.GetSize();
+        bool not_null_stmt = dyn_cast<clang::NullStmt>(child_stmt) == NULL;
+        if (clear_before_next_stmt && not_null_stmt)
+            m_stream.PutHex8(DW_OP_APPLE_clear);
+        Visit (child_stmt);
+        if (not_null_stmt)
+            clear_before_next_stmt = pre_visit_stream_offset != m_stream.GetSize();
+    }
+}
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitDeclStmt (clang::DeclStmt *decl_stmt)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+    clang::DeclGroupRef decl_group_ref = decl_stmt->getDeclGroup();
+    clang::DeclGroupRef::iterator pos, end = decl_group_ref.end();
+    for (pos = decl_group_ref.begin(); pos != end; ++pos)
+    {
+        clang::Decl *decl = *pos;
+        if (decl)
+        {
+            clang::Decl::Kind decl_kind = decl->getKind();
+
+            switch (decl_kind)
+            {
+            case clang::Decl::Namespace:
+            case clang::Decl::Enum:
+            case clang::Decl::Record:
+            case clang::Decl::CXXRecord:
+            case clang::Decl::ObjCMethod:
+            case clang::Decl::ObjCInterface:
+            case clang::Decl::ObjCCategory:
+            case clang::Decl::ObjCProtocol:
+            case clang::Decl::ObjCImplementation:
+            case clang::Decl::ObjCCategoryImpl:
+            case clang::Decl::LinkageSpec:
+            case clang::Decl::Block:
+            case clang::Decl::Function:
+            case clang::Decl::CXXMethod:
+            case clang::Decl::CXXConstructor:
+            case clang::Decl::CXXDestructor:
+            case clang::Decl::CXXConversion:
+            case clang::Decl::Field:
+            case clang::Decl::Typedef:
+            case clang::Decl::EnumConstant:
+            case clang::Decl::ImplicitParam:
+            case clang::Decl::ParmVar:
+            case clang::Decl::ObjCProperty:
+                break;
+
+            case clang::Decl::Var:
+                {
+                    const clang::VarDecl *var_decl = cast<clang::VarDecl>(decl)->getCanonicalDecl();
+                    uint32_t expr_local_var_idx = UINT32_MAX;
+                    if (m_variable_list.GetVariableForVarDecl (m_ast_context, var_decl, expr_local_var_idx, true))
+                    {
+                        const clang::Expr* var_decl_expr = var_decl->getAnyInitializer();
+                        // If there is an inialization expression, then assign the
+                        // variable.
+                        if (var_decl_expr)
+                        {
+                            m_stream.PutHex8(DW_OP_APPLE_expr_local);
+                            m_stream.PutULEB128(expr_local_var_idx);
+                            Visit ((clang::Stmt *)var_decl_expr);
+                            m_stream.PutHex8(DW_OP_APPLE_assign);
+                        }
+                    }
+                }
+                break;
+
+            default:
+                assert(!"decl unhandled");
+                break;
+            }
+        }
+    }
+}
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitLabelStmt (clang::LabelStmt *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+}
+
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitGotoStmt (clang::GotoStmt *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+}
+
+
+// Exprs
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitExpr (clang::Expr *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+}
+
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitDeclRefExpr (clang::DeclRefExpr *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+    clang::NamedDecl *decl = Node->getDecl();
+    clang::QualType clang_type = Node->getType();
+
+#ifdef ENABLE_DEBUG_PRINTF
+    //decl->dump();
+    //clang_type.dump("lldb_private::ClangStmtVisitor::VisitDeclRefExpr() -> clang_type.dump() = ");
+#endif
+    uint32_t expr_local_var_idx = UINT32_MAX;
+    if (m_variable_list.GetVariableForVarDecl (m_ast_context, cast<clang::VarDecl>(decl)->getCanonicalDecl(), expr_local_var_idx, false) &&
+        expr_local_var_idx != UINT32_MAX)
+    {
+        m_stream.PutHex8(DW_OP_APPLE_expr_local);
+        m_stream.PutULEB128(expr_local_var_idx);
+    }
+    else if (m_decl_map &&
+             m_decl_map->GetIndexForDecl(expr_local_var_idx, decl->getCanonicalDecl()))
+    {
+        m_stream.PutHex8(DW_OP_APPLE_extern);
+        m_stream.PutULEB128(expr_local_var_idx);
+    }
+    else
+    {
+        m_stream.PutHex8 (DW_OP_APPLE_error);
+    }
+}
+
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitPredefinedExpr (clang::PredefinedExpr *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+}
+
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitCharacterLiteral (clang::CharacterLiteral *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+    clang::QualType clang_type = Node->getType();
+    uint64_t clang_type_size = m_ast_context.getTypeSize (clang_type);
+    if (clang_type_size <= 64)
+    {
+        // Encode the integer into our DWARF expression
+        if (clang_type->isSignedIntegerType())
+            EncodeSInt64(Node->getValue(), clang_type_size);
+        else
+            EncodeUInt64(Node->getValue(), clang_type_size);
+    }
+    else
+    {
+        // TODO: eventually support integer math over 64 bits, probably using
+        // APInt as the class.
+        m_stream.PutHex8(DW_OP_APPLE_error);
+    }
+}
+
+bool
+lldb_private::ClangStmtVisitor::EncodeUInt64 (uint64_t uval, uint32_t bit_size)
+{
+    // If "bit_size" is zero, then encode "uval" in the most efficient way
+    if (bit_size <= 8 || (bit_size == 0 && uval <= UINT8_MAX))
+    {
+        m_stream.PutHex8 (DW_OP_const1u);
+        m_stream.PutHex8 (uval);
+    }
+    else if (bit_size <= 16 || (bit_size == 0 && uval <= UINT16_MAX))
+    {
+        m_stream.PutHex8 (DW_OP_const2u);
+        m_stream.PutHex16 (uval);
+    }
+    else if (bit_size <= 32 || (bit_size == 0 && uval <= UINT32_MAX))
+    {
+        m_stream.PutHex8 (DW_OP_const4u);
+        m_stream.PutHex32 (uval);
+    }
+    else if (bit_size <= 64 || (bit_size == 0))
+    {
+        m_stream.PutHex8 (DW_OP_const8u);
+        m_stream.PutHex64 (uval);
+    }
+    else
+    {
+        m_stream.PutHex8 (DW_OP_APPLE_error);
+        return false;
+    }
+    return true;
+}
+
+bool
+lldb_private::ClangStmtVisitor::EncodeSInt64 (int64_t sval, uint32_t bit_size)
+{
+    if (bit_size <= 8 || (bit_size == 0 && INT8_MIN <= sval && sval <= INT8_MAX))
+    {
+        m_stream.PutHex8 (DW_OP_const1s);
+        m_stream.PutHex8 (sval);
+    }
+    else if (bit_size <= 16 || (bit_size == 0 && INT16_MIN <= sval && sval <= INT16_MAX))
+    {
+        m_stream.PutHex8 (DW_OP_const2s);
+        m_stream.PutHex16 (sval);
+    }
+    else if (bit_size <= 32 || (bit_size == 0 && INT32_MIN <= sval && sval <= INT32_MAX))
+    {
+        m_stream.PutHex8 (DW_OP_const4s);
+        m_stream.PutHex32 (sval);
+    }
+    else if (bit_size <= 64 || (bit_size == 0))
+    {
+        m_stream.PutHex8 (DW_OP_const8s);
+        m_stream.PutHex64 (sval);
+    }
+    else
+    {
+        m_stream.PutHex8 (DW_OP_APPLE_error);
+        return false;
+    }
+    return true;
+}
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitIntegerLiteral (clang::IntegerLiteral *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+    const llvm::APInt &ap_int = Node->getValue();
+    if (ap_int.getBitWidth() <= 64)
+    {
+        clang::QualType clang_type = Node->getType();
+        uint64_t clang_type_size = m_ast_context.getTypeSize (clang_type);
+        // Encode the integer into our DWARF expression
+        if (clang_type->isSignedIntegerType())
+            EncodeSInt64(ap_int.getLimitedValue(), clang_type_size);
+        else
+            EncodeUInt64(ap_int.getLimitedValue(), clang_type_size);
+    }
+    else
+    {
+        // TODO: eventually support integer math over 64 bits, probably using
+        // APInt as the class.
+        m_stream.PutHex8(DW_OP_APPLE_error);
+    }
+}
+
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitFloatingLiteral (clang::FloatingLiteral *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+    const llvm::APFloat &ap_float = Node->getValue();
+    // Put the length of the float in bytes into a single byte
+    llvm::APInt ap_int(ap_float.bitcastToAPInt());
+    const unsigned byte_size = ap_int.getBitWidth() / CHAR_BIT;
+    if (byte_size == sizeof(float))
+    {
+        if (sizeof(float) == 4)
+        {
+            m_stream.PutHex8(DW_OP_APPLE_constf);
+            m_stream.PutHex8 (byte_size);
+            m_stream.PutHex32 (ap_int.getLimitedValue());
+            return;
+        }
+        else if (sizeof(float) == 8)
+        {
+            m_stream.PutHex8(DW_OP_APPLE_constf);
+            m_stream.PutHex8 (byte_size);
+            m_stream.PutHex64 (ap_int.getLimitedValue());
+            return;
+        }
+    }
+    else if (byte_size == sizeof(double))
+    {
+        if (sizeof(double) == 4)
+        {
+            m_stream.PutHex8(DW_OP_APPLE_constf);
+            m_stream.PutHex8 (byte_size);
+            m_stream.PutHex32 (ap_int.getLimitedValue());
+            return;
+        }
+        else if (sizeof(double) == 8)
+        {
+            m_stream.PutHex8(DW_OP_APPLE_constf);
+            m_stream.PutHex8 (byte_size);
+            m_stream.PutHex64 (ap_int.getLimitedValue());
+            return;
+        }
+    }
+    else if (byte_size == sizeof(long double))
+    {
+        if (sizeof(long double) == 8)
+        {
+            m_stream.PutHex8(DW_OP_APPLE_constf);
+            m_stream.PutHex8 (byte_size);
+            m_stream.PutHex64 (ap_int.getLimitedValue());
+            return;
+        }
+    }
+    // TODO: eventually support float constants of all sizes using
+    // APFloat as the class.
+    m_stream.PutHex8(DW_OP_APPLE_error);
+}
+
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitStringLiteral (clang::StringLiteral *Str)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+    
+    size_t byte_length = Str->getByteLength();
+    bool is_wide = Str->isWide();
+    
+    size_t new_length = byte_length + (is_wide ? 1 : 2);
+    
+    uint8_t null_terminated_string[new_length];
+    
+    memcpy(&null_terminated_string[0], Str->getStrData(), byte_length);
+    
+    if(is_wide)
+    {
+        null_terminated_string[byte_length] = '\0';
+        null_terminated_string[byte_length + 1] = '\0';
+    }
+    else 
+    {
+        null_terminated_string[byte_length] = '\0';
+    }
+    
+    Value *val = new Value(null_terminated_string, new_length);
+    val->SetContext(Value::eContextTypeOpaqueClangQualType, Str->getType().getAsOpaquePtr());
+    
+    uint32_t val_idx = m_variable_list.AppendValue(val);
+    
+    m_stream.PutHex8(DW_OP_APPLE_expr_local);
+    m_stream.PutULEB128(val_idx);
+}
+
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitUnaryOperator (clang::UnaryOperator *unary_op)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+
+    Visit(unary_op->getSubExpr());
+
+    switch (unary_op->getOpcode())
+    {
+    case clang::UnaryOperator::PostInc:
+        // Duplciate the top of stack value (which must be something that can
+        // be assignable/incremented) and push its current value
+        m_stream.PutHex8 (DW_OP_dup);               // x, x
+        m_stream.PutHex8 (DW_OP_APPLE_value_of);    // x, val(x)
+        m_stream.PutHex8 (DW_OP_swap);              // val(x), x
+        m_stream.PutHex8 (DW_OP_dup);               // val(x), x, x
+        m_stream.PutHex8 (DW_OP_lit1);              // val(x), x, x, 1
+        m_stream.PutHex8 (DW_OP_plus);              // val(x), x, val(x)+1
+        m_stream.PutHex8 (DW_OP_APPLE_assign);      // val(x), x
+        m_stream.PutHex8 (DW_OP_drop);              // val(x)
+        break;
+
+    case clang::UnaryOperator::PostDec:
+        // Duplciate the top of stack value (which must be something that can
+        // be assignable/incremented) and push its current value
+        m_stream.PutHex8 (DW_OP_dup);               // x, x
+        m_stream.PutHex8 (DW_OP_APPLE_value_of);    // x, val(x)
+        m_stream.PutHex8 (DW_OP_swap);              // val(x), x
+        m_stream.PutHex8 (DW_OP_dup);               // val(x), x, x
+        m_stream.PutHex8 (DW_OP_lit1);              // val(x), x, x, 1
+        m_stream.PutHex8 (DW_OP_minus);             // val(x), x, val(x)-1
+        m_stream.PutHex8 (DW_OP_APPLE_assign);      // val(x), x
+        m_stream.PutHex8 (DW_OP_drop);              // val(x)
+        break;
+
+    case clang::UnaryOperator::PreInc:
+        m_stream.PutHex8 (DW_OP_dup);               // x, x
+        m_stream.PutHex8 (DW_OP_APPLE_value_of);    // x, val(x)
+        m_stream.PutHex8 (DW_OP_lit1);              // x, val(x), 1
+        m_stream.PutHex8 (DW_OP_plus);              // x, val(x)+1
+        m_stream.PutHex8 (DW_OP_APPLE_assign);      // x with new value
+        break;
+
+    case clang::UnaryOperator::PreDec:
+        m_stream.PutHex8 (DW_OP_dup);               // x, x
+        m_stream.PutHex8 (DW_OP_APPLE_value_of);    // x, val(x)
+        m_stream.PutHex8 (DW_OP_lit1);              // x, val(x), 1
+        m_stream.PutHex8 (DW_OP_minus);             // x, val(x)-1
+        m_stream.PutHex8 (DW_OP_APPLE_assign);      // x with new value
+        break;
+
+    case clang::UnaryOperator::AddrOf:
+        m_stream.PutHex8 (DW_OP_APPLE_address_of);
+        break;
+
+    case clang::UnaryOperator::Deref:
+        m_stream.PutHex8 (DW_OP_APPLE_deref_type);
+        break;
+
+    case clang::UnaryOperator::Plus:
+        m_stream.PutHex8 (DW_OP_abs);
+        break;
+
+    case clang::UnaryOperator::Minus:
+        m_stream.PutHex8 (DW_OP_neg);
+        break;
+
+    case clang::UnaryOperator::Not:
+        m_stream.PutHex8 (DW_OP_not);
+        break;
+
+    case clang::UnaryOperator::LNot:
+        m_stream.PutHex8 (DW_OP_lit0);
+        m_stream.PutHex8 (DW_OP_eq);
+        break;
+
+    case clang::UnaryOperator::Real:
+        m_stream.PutHex8(DW_OP_APPLE_error);
+        break;
+
+    case clang::UnaryOperator::Imag:
+        m_stream.PutHex8(DW_OP_APPLE_error);
+        break;
+
+    case clang::UnaryOperator::Extension:
+        m_stream.PutHex8(DW_OP_APPLE_error);
+        break;
+
+    case clang::UnaryOperator::OffsetOf:
+        break;
+
+    default:
+        assert(!"Unknown unary operator!");
+        break;
+    }
+}
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitCastExpr (clang::CastExpr *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+//    CastExpr::CastKind cast_kind = Node->getCastKind();
+//    switch (cast_kind)
+//    {
+//    case CastExpr::CK_Unknown:
+//    case CastExpr::CK_BitCast:        // Used for reinterpret_cast.
+//    case CastExpr::CK_NoOp:           // Used for const_cast.
+//    case CastExpr::CK_BaseToDerived: // Base to derived class casts.
+//    case CastExpr::CK_DerivedToBase: // Derived to base class casts.
+//    case CastExpr::CK_Dynamic: // Dynamic cast.
+//    case CastExpr::CK_ToUnion: // Cast to union (GCC extension).
+//    case CastExpr::CK_ArrayToPointerDecay: // Array to pointer decay.
+//    case CastExpr::CK_FunctionToPointerDecay: // Function to pointer decay.
+//    case CastExpr::CK_NullToMemberPointer: // Null pointer to member pointer.
+//    case CastExpr::CK_BaseToDerivedMemberPointer: // Member pointer in base class to member pointer in derived class.
+//    case CastExpr::CK_DerivedToBaseMemberPointer: // Member pointer in derived class to member pointer in base class.
+//    case CastExpr::CK_UserDefinedConversion: // Conversion using a user defined type conversion function.
+//    case CastExpr::CK_ConstructorConversion: // Conversion by constructor
+//    case CastExpr::CK_IntegralToPointer: // Integral to pointer
+//    case CastExpr::CK_PointerToIntegral: // Pointer to integral
+//    case CastExpr::CK_ToVoid: // Cast to void
+//    case CastExpr::CK_VectorSplat: // Casting from an integer/floating type to an extended
+//                         // vector type with the same element type as the src type. Splats the
+//                         // src expression into the destination expression.
+//    case CastExpr::CK_IntegralCast: // Casting between integral types of different size.
+//    case CastExpr::CK_IntegralToFloating: // Integral to floating point.
+//    case CastExpr::CK_FloatingToIntegral: // Floating point to integral.
+//    case CastExpr::CK_FloatingCast: // Casting between floating types of different size.
+//        m_stream.PutHex8(DW_OP_APPLE_error);
+//        break;
+//    }
+    uint32_t cast_type_count = 0;
+    lldb_private::Scalar::Type cast_type_encoding = GetScalarTypeForClangType (m_ast_context, Node->getType(), cast_type_count);
+
+
+    Visit (Node->getSubExpr());
+
+    // Simple scalar cast
+    if (cast_type_encoding != lldb_private::Scalar::e_void && cast_type_count == 1)
+    {
+        // Only cast if our scalar types mismatch
+        uint32_t castee_type_count = 0;
+        lldb_private::Scalar::Type castee_type_encoding = GetScalarTypeForClangType (m_ast_context, Node->getSubExpr()->getType(), castee_type_count);
+        if (cast_type_encoding != castee_type_encoding &&
+            castee_type_encoding != lldb_private::Scalar::e_void)
+        {
+            m_stream.PutHex8(DW_OP_APPLE_scalar_cast);
+            m_stream.PutHex8(cast_type_encoding);
+        }
+    }
+    else
+    {
+        // Handle more complex casts with clang types soon!
+        m_stream.PutHex8(DW_OP_APPLE_error);
+    }
+}
+
+CLANG_STMT_RESULT 
+lldb_private::ClangStmtVisitor::VisitArraySubscriptExpr (clang::ArraySubscriptExpr *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+    Visit (Node->getBase());
+    Visit (Node->getIdx());
+    m_stream.PutHex8(DW_OP_APPLE_array_ref);
+}
+
+//
+//CLANG_STMT_RESULT
+//lldb_private::ClangStmtVisitor::VisitImplicitCastExpr (clang::ImplicitCastExpr *Node)
+//{
+//    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+//    m_stream.PutHex8(DW_OP_APPLE_scalar_cast);
+//    Visit (Node->getSubExpr());
+//}
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitSizeOfAlignOfExpr (clang::SizeOfAlignOfExpr *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+}
+
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitMemberExpr (clang::MemberExpr *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+    clang::Expr *parent = Node->getBase();
+    Visit (parent);
+    clang::QualType parent_clang_type = parent->getType();
+    clang::NamedDecl *member_named_decl = cast<clang::NamedDecl>(Node->getMemberDecl()->getCanonicalDecl());
+
+//  DeclarationName member_name = member->getDeclName();
+
+    clang::Type::TypeClass parent_type_class = parent_clang_type->getTypeClass();
+    if (parent_type_class == clang::Type::Pointer)
+    {
+        clang::PointerType *pointer_type = cast<clang::PointerType>(parent_clang_type.getTypePtr());
+        parent_clang_type = pointer_type->getPointeeType();
+        parent_type_class = parent_clang_type->getTypeClass();
+    }
+
+    switch (parent_type_class)
+    {
+    case clang::Type::Record:
+        {
+            const clang::RecordType *record_type = cast<clang::RecordType>(parent_clang_type.getTypePtr());
+            const clang::RecordDecl *record_decl = record_type->getDecl();
+            assert(record_decl);
+            const clang::ASTRecordLayout &record_layout = m_ast_context.getASTRecordLayout(record_decl);
+            uint32_t field_idx = 0;
+            clang::RecordDecl::field_iterator field, field_end;
+            for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx)
+            {
+                clang::NamedDecl *field_named_decl = cast<clang::NamedDecl>(field->getCanonicalDecl());
+                if (field_named_decl == member_named_decl)
+                {
+                    std::pair<uint64_t, unsigned> field_type_info = m_ast_context.getTypeInfo(field->getType());
+                    uint64_t field_bit_offset = record_layout.getFieldOffset (field_idx);
+                    uint64_t field_byte_offset = field_bit_offset / 8;
+                    uint32_t field_bitfield_bit_size = 0;
+                    //uint32_t field_bitfield_bit_offset = field_bit_offset % 8;
+
+                    if (field->isBitField())
+                    {
+                        clang::Expr* bit_width_expr = field->getBitWidth();
+                        if (bit_width_expr)
+                        {
+                            llvm::APSInt bit_width_apsint;
+                            if (bit_width_expr->isIntegerConstantExpr(bit_width_apsint, m_ast_context))
+                            {
+                                field_bitfield_bit_size = bit_width_apsint.getLimitedValue(UINT32_MAX);
+                            }
+                        }
+                    }
+
+                    if (Node->isArrow())
+                    {
+                        m_stream.PutHex8(DW_OP_deref);
+                    }
+                    else
+                    {
+                        m_stream.PutHex8(DW_OP_APPLE_address_of);
+                    }
+
+                    if (field_byte_offset)
+                    {
+                        if (EncodeUInt64(field_byte_offset, 0))
+                        {
+                            m_stream.PutHex8(DW_OP_plus);
+                        }
+                    }
+                    m_stream.PutHex8(DW_OP_APPLE_clang_cast);
+                    m_stream.PutPointer(field->getType().getAsOpaquePtr());
+                    break;
+                }
+            }
+        }
+        break;
+
+    default:
+        assert(!"Unhandled MemberExpr");
+        break;
+    }
+}
+
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitExtVectorElementExpr (clang::ExtVectorElementExpr *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+}
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitParenExpr(clang::ParenExpr *paren_expr)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+    Visit (paren_expr->getSubExpr());
+}
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitInitListExpr (clang::InitListExpr *init_list_expr)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+}
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitBinaryOperator (clang::BinaryOperator *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+
+    Visit(Node->getLHS());
+    Visit(Node->getRHS());
+
+    switch (Node->getOpcode())
+    {
+        default: assert(0 && "Unknown binary operator!");
+        case clang::BinaryOperator::PtrMemD: m_stream.PutHex8(DW_OP_APPLE_error); break;
+        case clang::BinaryOperator::PtrMemI: m_stream.PutHex8(DW_OP_APPLE_error); break;
+        case clang::BinaryOperator::Mul:   m_stream.PutHex8(DW_OP_mul);    break;
+        case clang::BinaryOperator::Div:   m_stream.PutHex8(DW_OP_div);    break;
+        case clang::BinaryOperator::Rem:   m_stream.PutHex8(DW_OP_mod);    break;
+        case clang::BinaryOperator::Add:   m_stream.PutHex8(DW_OP_plus);   break;
+        case clang::BinaryOperator::Sub:   m_stream.PutHex8(DW_OP_minus);  break;
+        case clang::BinaryOperator::Shl:   m_stream.PutHex8(DW_OP_shl);    break;
+        case clang::BinaryOperator::Shr:   m_stream.PutHex8(DW_OP_shr);    break;
+        case clang::BinaryOperator::LT:    m_stream.PutHex8(DW_OP_lt);     break;
+        case clang::BinaryOperator::GT:    m_stream.PutHex8(DW_OP_gt);     break;
+        case clang::BinaryOperator::LE:    m_stream.PutHex8(DW_OP_le);     break;
+        case clang::BinaryOperator::GE:    m_stream.PutHex8(DW_OP_ge);     break;
+        case clang::BinaryOperator::EQ:    m_stream.PutHex8(DW_OP_eq);     break;
+        case clang::BinaryOperator::NE:    m_stream.PutHex8(DW_OP_ne);     break;
+        case clang::BinaryOperator::And:   m_stream.PutHex8(DW_OP_and);    break;
+        case clang::BinaryOperator::Xor:   m_stream.PutHex8(DW_OP_xor);    break;
+        case clang::BinaryOperator::Or :   m_stream.PutHex8(DW_OP_or);     break;
+        case clang::BinaryOperator::LAnd:
+            // Do we need to call an operator here on objects? If so
+            // we will need a DW_OP_apple_logical_and
+            m_stream.PutHex8(DW_OP_lit0);
+            m_stream.PutHex8(DW_OP_ne);
+            m_stream.PutHex8(DW_OP_swap);
+            m_stream.PutHex8(DW_OP_lit0);
+            m_stream.PutHex8(DW_OP_ne);
+            m_stream.PutHex8(DW_OP_and);
+            break;
+
+        case clang::BinaryOperator::LOr :
+            // Do we need to call an operator here on objects? If so
+            // we will need a DW_OP_apple_logical_or
+            m_stream.PutHex8(DW_OP_lit0);
+            m_stream.PutHex8(DW_OP_ne);
+            m_stream.PutHex8(DW_OP_swap);
+            m_stream.PutHex8(DW_OP_lit0);
+            m_stream.PutHex8(DW_OP_ne);
+            m_stream.PutHex8(DW_OP_or);
+            break;
+
+        case clang::BinaryOperator::Assign:
+            m_stream.PutHex8(DW_OP_APPLE_assign);
+            break;
+
+        case clang::BinaryOperator::MulAssign:
+            m_stream.PutHex8(DW_OP_over);
+            m_stream.PutHex8(DW_OP_swap);
+            m_stream.PutHex8(DW_OP_mul);
+            m_stream.PutHex8(DW_OP_APPLE_assign);
+            break;
+
+        case clang::BinaryOperator::DivAssign:
+            m_stream.PutHex8(DW_OP_over);
+            m_stream.PutHex8(DW_OP_swap);
+            m_stream.PutHex8(DW_OP_div);
+            m_stream.PutHex8(DW_OP_APPLE_assign);
+            break;
+
+        case clang::BinaryOperator::RemAssign:
+            m_stream.PutHex8(DW_OP_over);
+            m_stream.PutHex8(DW_OP_swap);
+            m_stream.PutHex8(DW_OP_mod);
+            m_stream.PutHex8(DW_OP_APPLE_assign);
+            break;
+
+        case clang::BinaryOperator::AddAssign:
+            m_stream.PutHex8(DW_OP_over);
+            m_stream.PutHex8(DW_OP_swap);
+            m_stream.PutHex8(DW_OP_plus);
+            m_stream.PutHex8(DW_OP_APPLE_assign);
+            break;
+
+        case clang::BinaryOperator::SubAssign:
+            m_stream.PutHex8(DW_OP_over);
+            m_stream.PutHex8(DW_OP_swap);
+            m_stream.PutHex8(DW_OP_minus);
+            m_stream.PutHex8(DW_OP_APPLE_assign);
+            break;
+
+        case clang::BinaryOperator::ShlAssign:
+            m_stream.PutHex8(DW_OP_over);
+            m_stream.PutHex8(DW_OP_swap);
+            m_stream.PutHex8(DW_OP_shl);
+            m_stream.PutHex8(DW_OP_APPLE_assign);
+            break;
+
+        case clang::BinaryOperator::ShrAssign:
+            m_stream.PutHex8(DW_OP_over);
+            m_stream.PutHex8(DW_OP_swap);
+            m_stream.PutHex8(DW_OP_shr);
+            m_stream.PutHex8(DW_OP_APPLE_assign);
+            break;
+
+        case clang::BinaryOperator::AndAssign:
+            m_stream.PutHex8(DW_OP_over);
+            m_stream.PutHex8(DW_OP_swap);
+            m_stream.PutHex8(DW_OP_and);
+            m_stream.PutHex8(DW_OP_APPLE_assign);
+            break;
+
+        case clang::BinaryOperator::OrAssign:
+            m_stream.PutHex8(DW_OP_over);
+            m_stream.PutHex8(DW_OP_swap);
+            m_stream.PutHex8(DW_OP_or);
+            m_stream.PutHex8(DW_OP_APPLE_assign);
+            break;
+
+        case clang::BinaryOperator::XorAssign:
+            m_stream.PutHex8(DW_OP_over);
+            m_stream.PutHex8(DW_OP_swap);
+            m_stream.PutHex8(DW_OP_xor);
+            m_stream.PutHex8(DW_OP_APPLE_assign);
+            break;
+
+        case clang::BinaryOperator::Comma:
+            // Nothing needs to be done here right?
+            break;
+    }
+}
+
+
+//CLANG_STMT_RESULT
+//lldb_private::ClangStmtVisitor::VisitCompoundAssignOperator (CompoundAssignOperator *Node)
+//{
+//    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+//
+//}
+
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitAddrLabelExpr (clang::AddrLabelExpr *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+}
+
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitTypesCompatibleExpr (clang::TypesCompatibleExpr *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+}
+
+
+
+    // C++
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitCXXNamedCastExpr (clang::CXXNamedCastExpr *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+}
+
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitCXXBoolLiteralExpr (clang::CXXBoolLiteralExpr *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+}
+
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitCXXThisExpr (clang::CXXThisExpr *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+}
+
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitCXXFunctionalCastExpr (clang::CXXFunctionalCastExpr *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+}
+
+
+
+    // ObjC
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitObjCEncodeExpr (clang::ObjCEncodeExpr *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+}
+
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitObjCMessageExpr (clang::ObjCMessageExpr* Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+}
+
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitObjCSelectorExpr (clang::ObjCSelectorExpr *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+}
+
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitObjCProtocolExpr (clang::ObjCProtocolExpr *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+}
+
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitObjCPropertyRefExpr (clang::ObjCPropertyRefExpr *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+}
+
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitObjCImplicitSetterGetterRefExpr (clang::ObjCImplicitSetterGetterRefExpr *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+}
+
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitObjCIvarRefExpr (clang::ObjCIvarRefExpr *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+}
+
+
+CLANG_STMT_RESULT
+lldb_private::ClangStmtVisitor::VisitObjCSuperExpr (clang::ObjCSuperExpr *Node)
+{
+    DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
+}
+
+
diff --git a/source/Expression/DWARFExpression.cpp b/source/Expression/DWARFExpression.cpp
new file mode 100644
index 0000000..d7afa36
--- /dev/null
+++ b/source/Expression/DWARFExpression.cpp
@@ -0,0 +1,2589 @@
+//===-- DWARFExpression.cpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Expression/DWARFExpression.h"
+
+#include <vector>
+
+#include "lldb/Core/dwarf.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/Value.h"
+
+#include "lldb/Expression/ClangExpressionDeclMap.h"
+#include "lldb/Expression/ClangExpressionVariable.h"
+
+#include "lldb/Host/Host.h"
+
+#include "lldb/lldb-private-log.h"
+
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/Type.h"
+
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+const char *
+DW_OP_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x03: return "DW_OP_addr";
+    case 0x06: return "DW_OP_deref";
+    case 0x08: return "DW_OP_const1u";
+    case 0x09: return "DW_OP_const1s";
+    case 0x0a: return "DW_OP_const2u";
+    case 0x0b: return "DW_OP_const2s";
+    case 0x0c: return "DW_OP_const4u";
+    case 0x0d: return "DW_OP_const4s";
+    case 0x0e: return "DW_OP_const8u";
+    case 0x0f: return "DW_OP_const8s";
+    case 0x10: return "DW_OP_constu";
+    case 0x11: return "DW_OP_consts";
+    case 0x12: return "DW_OP_dup";
+    case 0x13: return "DW_OP_drop";
+    case 0x14: return "DW_OP_over";
+    case 0x15: return "DW_OP_pick";
+    case 0x16: return "DW_OP_swap";
+    case 0x17: return "DW_OP_rot";
+    case 0x18: return "DW_OP_xderef";
+    case 0x19: return "DW_OP_abs";
+    case 0x1a: return "DW_OP_and";
+    case 0x1b: return "DW_OP_div";
+    case 0x1c: return "DW_OP_minus";
+    case 0x1d: return "DW_OP_mod";
+    case 0x1e: return "DW_OP_mul";
+    case 0x1f: return "DW_OP_neg";
+    case 0x20: return "DW_OP_not";
+    case 0x21: return "DW_OP_or";
+    case 0x22: return "DW_OP_plus";
+    case 0x23: return "DW_OP_plus_uconst";
+    case 0x24: return "DW_OP_shl";
+    case 0x25: return "DW_OP_shr";
+    case 0x26: return "DW_OP_shra";
+    case 0x27: return "DW_OP_xor";
+    case 0x2f: return "DW_OP_skip";
+    case 0x28: return "DW_OP_bra";
+    case 0x29: return "DW_OP_eq";
+    case 0x2a: return "DW_OP_ge";
+    case 0x2b: return "DW_OP_gt";
+    case 0x2c: return "DW_OP_le";
+    case 0x2d: return "DW_OP_lt";
+    case 0x2e: return "DW_OP_ne";
+    case 0x30: return "DW_OP_lit0";
+    case 0x31: return "DW_OP_lit1";
+    case 0x32: return "DW_OP_lit2";
+    case 0x33: return "DW_OP_lit3";
+    case 0x34: return "DW_OP_lit4";
+    case 0x35: return "DW_OP_lit5";
+    case 0x36: return "DW_OP_lit6";
+    case 0x37: return "DW_OP_lit7";
+    case 0x38: return "DW_OP_lit8";
+    case 0x39: return "DW_OP_lit9";
+    case 0x3a: return "DW_OP_lit10";
+    case 0x3b: return "DW_OP_lit11";
+    case 0x3c: return "DW_OP_lit12";
+    case 0x3d: return "DW_OP_lit13";
+    case 0x3e: return "DW_OP_lit14";
+    case 0x3f: return "DW_OP_lit15";
+    case 0x40: return "DW_OP_lit16";
+    case 0x41: return "DW_OP_lit17";
+    case 0x42: return "DW_OP_lit18";
+    case 0x43: return "DW_OP_lit19";
+    case 0x44: return "DW_OP_lit20";
+    case 0x45: return "DW_OP_lit21";
+    case 0x46: return "DW_OP_lit22";
+    case 0x47: return "DW_OP_lit23";
+    case 0x48: return "DW_OP_lit24";
+    case 0x49: return "DW_OP_lit25";
+    case 0x4a: return "DW_OP_lit26";
+    case 0x4b: return "DW_OP_lit27";
+    case 0x4c: return "DW_OP_lit28";
+    case 0x4d: return "DW_OP_lit29";
+    case 0x4e: return "DW_OP_lit30";
+    case 0x4f: return "DW_OP_lit31";
+    case 0x50: return "DW_OP_reg0";
+    case 0x51: return "DW_OP_reg1";
+    case 0x52: return "DW_OP_reg2";
+    case 0x53: return "DW_OP_reg3";
+    case 0x54: return "DW_OP_reg4";
+    case 0x55: return "DW_OP_reg5";
+    case 0x56: return "DW_OP_reg6";
+    case 0x57: return "DW_OP_reg7";
+    case 0x58: return "DW_OP_reg8";
+    case 0x59: return "DW_OP_reg9";
+    case 0x5a: return "DW_OP_reg10";
+    case 0x5b: return "DW_OP_reg11";
+    case 0x5c: return "DW_OP_reg12";
+    case 0x5d: return "DW_OP_reg13";
+    case 0x5e: return "DW_OP_reg14";
+    case 0x5f: return "DW_OP_reg15";
+    case 0x60: return "DW_OP_reg16";
+    case 0x61: return "DW_OP_reg17";
+    case 0x62: return "DW_OP_reg18";
+    case 0x63: return "DW_OP_reg19";
+    case 0x64: return "DW_OP_reg20";
+    case 0x65: return "DW_OP_reg21";
+    case 0x66: return "DW_OP_reg22";
+    case 0x67: return "DW_OP_reg23";
+    case 0x68: return "DW_OP_reg24";
+    case 0x69: return "DW_OP_reg25";
+    case 0x6a: return "DW_OP_reg26";
+    case 0x6b: return "DW_OP_reg27";
+    case 0x6c: return "DW_OP_reg28";
+    case 0x6d: return "DW_OP_reg29";
+    case 0x6e: return "DW_OP_reg30";
+    case 0x6f: return "DW_OP_reg31";
+    case 0x70: return "DW_OP_breg0";
+    case 0x71: return "DW_OP_breg1";
+    case 0x72: return "DW_OP_breg2";
+    case 0x73: return "DW_OP_breg3";
+    case 0x74: return "DW_OP_breg4";
+    case 0x75: return "DW_OP_breg5";
+    case 0x76: return "DW_OP_breg6";
+    case 0x77: return "DW_OP_breg7";
+    case 0x78: return "DW_OP_breg8";
+    case 0x79: return "DW_OP_breg9";
+    case 0x7a: return "DW_OP_breg10";
+    case 0x7b: return "DW_OP_breg11";
+    case 0x7c: return "DW_OP_breg12";
+    case 0x7d: return "DW_OP_breg13";
+    case 0x7e: return "DW_OP_breg14";
+    case 0x7f: return "DW_OP_breg15";
+    case 0x80: return "DW_OP_breg16";
+    case 0x81: return "DW_OP_breg17";
+    case 0x82: return "DW_OP_breg18";
+    case 0x83: return "DW_OP_breg19";
+    case 0x84: return "DW_OP_breg20";
+    case 0x85: return "DW_OP_breg21";
+    case 0x86: return "DW_OP_breg22";
+    case 0x87: return "DW_OP_breg23";
+    case 0x88: return "DW_OP_breg24";
+    case 0x89: return "DW_OP_breg25";
+    case 0x8a: return "DW_OP_breg26";
+    case 0x8b: return "DW_OP_breg27";
+    case 0x8c: return "DW_OP_breg28";
+    case 0x8d: return "DW_OP_breg29";
+    case 0x8e: return "DW_OP_breg30";
+    case 0x8f: return "DW_OP_breg31";
+    case 0x90: return "DW_OP_regx";
+    case 0x91: return "DW_OP_fbreg";
+    case 0x92: return "DW_OP_bregx";
+    case 0x93: return "DW_OP_piece";
+    case 0x94: return "DW_OP_deref_size";
+    case 0x95: return "DW_OP_xderef_size";
+    case 0x96: return "DW_OP_nop";
+    case 0x97: return "DW_OP_push_object_address";
+    case 0x98: return "DW_OP_call2";
+    case 0x99: return "DW_OP_call4";
+    case 0x9a: return "DW_OP_call_ref";
+    case DW_OP_APPLE_array_ref: return "DW_OP_APPLE_array_ref";
+    case DW_OP_APPLE_extern: return "DW_OP_APPLE_extern";
+    case DW_OP_APPLE_uninit: return "DW_OP_APPLE_uninit";
+    case DW_OP_APPLE_assign: return "DW_OP_APPLE_assign";
+    case DW_OP_APPLE_address_of: return "DW_OP_APPLE_address_of";
+    case DW_OP_APPLE_value_of: return "DW_OP_APPLE_value_of";
+    case DW_OP_APPLE_deref_type: return "DW_OP_APPLE_deref_type";
+    case DW_OP_APPLE_expr_local: return "DW_OP_APPLE_expr_local";
+    case DW_OP_APPLE_constf: return "DW_OP_APPLE_constf";
+    case DW_OP_APPLE_scalar_cast: return "DW_OP_APPLE_scalar_cast";
+    case DW_OP_APPLE_clang_cast: return "DW_OP_APPLE_clang_cast";
+    case DW_OP_APPLE_clear: return "DW_OP_APPLE_clear";
+    case DW_OP_APPLE_error: return "DW_OP_APPLE_error";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_OP constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+
+//----------------------------------------------------------------------
+// DWARFExpression constructor
+//----------------------------------------------------------------------
+DWARFExpression::DWARFExpression() :
+    m_data(),
+    m_reg_kind (eRegisterKindDWARF),
+    m_loclist_base_addr(),
+    m_expr_locals (NULL),
+    m_decl_map (NULL)
+{
+}
+
+DWARFExpression::DWARFExpression(const DWARFExpression& rhs) :
+    m_data(rhs.m_data),
+    m_reg_kind (rhs.m_reg_kind),
+    m_loclist_base_addr(rhs.m_loclist_base_addr),
+    m_expr_locals (rhs.m_expr_locals),
+    m_decl_map (rhs.m_decl_map)
+{
+}
+
+
+DWARFExpression::DWARFExpression(const DataExtractor& data, uint32_t data_offset, uint32_t data_length, const Address* loclist_base_addr_ptr) :
+    m_data(data, data_offset, data_length),
+    m_reg_kind (eRegisterKindDWARF),
+    m_loclist_base_addr(),
+    m_expr_locals (NULL),
+    m_decl_map (NULL)
+{
+    if (loclist_base_addr_ptr)
+        m_loclist_base_addr = *loclist_base_addr_ptr;
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+DWARFExpression::~DWARFExpression()
+{
+}
+
+
+bool
+DWARFExpression::IsValid() const
+{
+    return m_data.GetByteSize() > 0;
+}
+
+
+void
+DWARFExpression::SetExpressionLocalVariableList (ClangExpressionVariableList *locals)
+{
+    m_expr_locals = locals;
+}
+
+void
+DWARFExpression::SetExpressionDeclMap (ClangExpressionDeclMap *decl_map)
+{
+    m_decl_map = decl_map;
+}
+
+void
+DWARFExpression::SetOpcodeData (const DataExtractor& data, const Address* loclist_base_addr_ptr)
+{
+    m_data = data;
+    if (loclist_base_addr_ptr != NULL)
+        m_loclist_base_addr = *loclist_base_addr_ptr;
+    else
+        m_loclist_base_addr.Clear();
+}
+
+void
+DWARFExpression::SetOpcodeData (const DataExtractor& data, uint32_t data_offset, uint32_t data_length, const Address* loclist_base_addr_ptr)
+{
+    m_data.SetData(data, data_offset, data_length);
+    if (loclist_base_addr_ptr != NULL)
+        m_loclist_base_addr = *loclist_base_addr_ptr;
+    else
+        m_loclist_base_addr.Clear();
+}
+
+void
+DWARFExpression::DumpLocation (Stream *s, uint32_t offset, uint32_t length, lldb::DescriptionLevel level) const
+{
+    if (!m_data.ValidOffsetForDataOfSize(offset, length))
+        return;
+    const uint32_t start_offset = offset;
+    const uint32_t end_offset = offset + length;
+    while (m_data.ValidOffset(offset) && offset < end_offset)
+    {
+        const uint32_t op_offset = offset;
+        const uint8_t op = m_data.GetU8(&offset);
+
+        switch (level)
+        {
+        case lldb::eDescriptionLevelBrief:
+            if (offset > start_offset)
+                s->PutChar(' ');
+            break;
+
+        case lldb::eDescriptionLevelFull:
+        case lldb::eDescriptionLevelVerbose:
+            if (offset > start_offset)
+                s->EOL();
+            s->Indent();
+            if (level == lldb::eDescriptionLevelFull)
+                break;
+            // Fall through for verbose and print offset and DW_OP prefix..
+            s->Printf("0x%8.8x: %s", op_offset, op >= DW_OP_APPLE_uninit ? "DW_OP_APPLE_" : "DW_OP_");
+            break;
+        }
+
+        switch (op)
+        {
+        case DW_OP_addr:    *s << "addr(" << m_data.GetAddress(&offset) << ") "; break;         // 0x03 1 address
+        case DW_OP_deref:   *s << "deref"; break;                                               // 0x06
+        case DW_OP_const1u: s->Printf("const1u(0x%2.2x) ", m_data.GetU8(&offset)); break;       // 0x08 1 1-byte constant
+        case DW_OP_const1s: s->Printf("const1s(0x%2.2x) ", m_data.GetU8(&offset)); break;       // 0x09 1 1-byte constant
+        case DW_OP_const2u: s->Printf("const2u(0x%4.4x) ", m_data.GetU16(&offset)); break;      // 0x0a 1 2-byte constant
+        case DW_OP_const2s: s->Printf("const2s(0x%4.4x) ", m_data.GetU16(&offset)); break;      // 0x0b 1 2-byte constant
+        case DW_OP_const4u: s->Printf("const4u(0x%8.8x) ", m_data.GetU32(&offset)); break;      // 0x0c 1 4-byte constant
+        case DW_OP_const4s: s->Printf("const4s(0x%8.8x) ", m_data.GetU32(&offset)); break;      // 0x0d 1 4-byte constant
+        case DW_OP_const8u: s->Printf("const8u(0x%16.16llx) ", m_data.GetU64(&offset)); break;  // 0x0e 1 8-byte constant
+        case DW_OP_const8s: s->Printf("const8s(0x%16.16llx) ", m_data.GetU64(&offset)); break;  // 0x0f 1 8-byte constant
+        case DW_OP_constu:  s->Printf("constu(0x%x) ", m_data.GetULEB128(&offset)); break;      // 0x10 1 ULEB128 constant
+        case DW_OP_consts:  s->Printf("consts(0x%x) ", m_data.GetSLEB128(&offset)); break;      // 0x11 1 SLEB128 constant
+        case DW_OP_dup:     s->PutCString("dup"); break;                                        // 0x12
+        case DW_OP_drop:    s->PutCString("drop"); break;                                       // 0x13
+        case DW_OP_over:    s->PutCString("over"); break;                                       // 0x14
+        case DW_OP_pick:    s->Printf("pick(0x%2.2x) ", m_data.GetU8(&offset)); break;          // 0x15 1 1-byte stack index
+        case DW_OP_swap:    s->PutCString("swap"); break;                                       // 0x16
+        case DW_OP_rot:     s->PutCString("rot"); break;                                        // 0x17
+        case DW_OP_xderef:  s->PutCString("xderef"); break;                                     // 0x18
+        case DW_OP_abs:     s->PutCString("abs"); break;                                        // 0x19
+        case DW_OP_and:     s->PutCString("and"); break;                                        // 0x1a
+        case DW_OP_div:     s->PutCString("div"); break;                                        // 0x1b
+        case DW_OP_minus:   s->PutCString("minus"); break;                                      // 0x1c
+        case DW_OP_mod:     s->PutCString("mod"); break;                                        // 0x1d
+        case DW_OP_mul:     s->PutCString("mul"); break;                                        // 0x1e
+        case DW_OP_neg:     s->PutCString("neg"); break;                                        // 0x1f
+        case DW_OP_not:     s->PutCString("not"); break;                                        // 0x20
+        case DW_OP_or:      s->PutCString("or"); break;                                         // 0x21
+        case DW_OP_plus:    s->PutCString("plus"); break;                                       // 0x22
+        case DW_OP_plus_uconst:                                                                 // 0x23 1 ULEB128 addend
+            s->Printf("plus_uconst(0x%x) ", m_data.GetULEB128(&offset));
+            break;
+
+        case DW_OP_shl:     s->PutCString("shl"); break;                                        // 0x24
+        case DW_OP_shr:     s->PutCString("shr"); break;                                        // 0x25
+        case DW_OP_shra:    s->PutCString("shra"); break;                                       // 0x26
+        case DW_OP_xor:     s->PutCString("xor"); break;                                        // 0x27
+        case DW_OP_skip:    s->Printf("skip(0x%4.4x)", m_data.GetU16(&offset)); break;          // 0x2f 1 signed 2-byte constant
+        case DW_OP_bra:     s->Printf("bra(0x%4.4x)", m_data.GetU16(&offset)); break;           // 0x28 1 signed 2-byte constant
+        case DW_OP_eq:      s->PutCString("eq"); break;                                         // 0x29
+        case DW_OP_ge:      s->PutCString("ge"); break;                                         // 0x2a
+        case DW_OP_gt:      s->PutCString("gt"); break;                                         // 0x2b
+        case DW_OP_le:      s->PutCString("le"); break;                                         // 0x2c
+        case DW_OP_lt:      s->PutCString("lt"); break;                                         // 0x2d
+        case DW_OP_ne:      s->PutCString("ne"); break;                                         // 0x2e
+
+        case DW_OP_lit0:    // 0x30
+        case DW_OP_lit1:    // 0x31
+        case DW_OP_lit2:    // 0x32
+        case DW_OP_lit3:    // 0x33
+        case DW_OP_lit4:    // 0x34
+        case DW_OP_lit5:    // 0x35
+        case DW_OP_lit6:    // 0x36
+        case DW_OP_lit7:    // 0x37
+        case DW_OP_lit8:    // 0x38
+        case DW_OP_lit9:    // 0x39
+        case DW_OP_lit10:   // 0x3A
+        case DW_OP_lit11:   // 0x3B
+        case DW_OP_lit12:   // 0x3C
+        case DW_OP_lit13:   // 0x3D
+        case DW_OP_lit14:   // 0x3E
+        case DW_OP_lit15:   // 0x3F
+        case DW_OP_lit16:   // 0x40
+        case DW_OP_lit17:   // 0x41
+        case DW_OP_lit18:   // 0x42
+        case DW_OP_lit19:   // 0x43
+        case DW_OP_lit20:   // 0x44
+        case DW_OP_lit21:   // 0x45
+        case DW_OP_lit22:   // 0x46
+        case DW_OP_lit23:   // 0x47
+        case DW_OP_lit24:   // 0x48
+        case DW_OP_lit25:   // 0x49
+        case DW_OP_lit26:   // 0x4A
+        case DW_OP_lit27:   // 0x4B
+        case DW_OP_lit28:   // 0x4C
+        case DW_OP_lit29:   // 0x4D
+        case DW_OP_lit30:   // 0x4E
+        case DW_OP_lit31:   s->Printf("lit%i", op - DW_OP_lit0); break; // 0x4f
+
+        case DW_OP_reg0:    // 0x50
+        case DW_OP_reg1:    // 0x51
+        case DW_OP_reg2:    // 0x52
+        case DW_OP_reg3:    // 0x53
+        case DW_OP_reg4:    // 0x54
+        case DW_OP_reg5:    // 0x55
+        case DW_OP_reg6:    // 0x56
+        case DW_OP_reg7:    // 0x57
+        case DW_OP_reg8:    // 0x58
+        case DW_OP_reg9:    // 0x59
+        case DW_OP_reg10:   // 0x5A
+        case DW_OP_reg11:   // 0x5B
+        case DW_OP_reg12:   // 0x5C
+        case DW_OP_reg13:   // 0x5D
+        case DW_OP_reg14:   // 0x5E
+        case DW_OP_reg15:   // 0x5F
+        case DW_OP_reg16:   // 0x60
+        case DW_OP_reg17:   // 0x61
+        case DW_OP_reg18:   // 0x62
+        case DW_OP_reg19:   // 0x63
+        case DW_OP_reg20:   // 0x64
+        case DW_OP_reg21:   // 0x65
+        case DW_OP_reg22:   // 0x66
+        case DW_OP_reg23:   // 0x67
+        case DW_OP_reg24:   // 0x68
+        case DW_OP_reg25:   // 0x69
+        case DW_OP_reg26:   // 0x6A
+        case DW_OP_reg27:   // 0x6B
+        case DW_OP_reg28:   // 0x6C
+        case DW_OP_reg29:   // 0x6D
+        case DW_OP_reg30:   // 0x6E
+        case DW_OP_reg31:   s->Printf("reg%i", op - DW_OP_reg0); break; // 0x6f
+
+        case DW_OP_breg0:
+        case DW_OP_breg1:
+        case DW_OP_breg2:
+        case DW_OP_breg3:
+        case DW_OP_breg4:
+        case DW_OP_breg5:
+        case DW_OP_breg6:
+        case DW_OP_breg7:
+        case DW_OP_breg8:
+        case DW_OP_breg9:
+        case DW_OP_breg10:
+        case DW_OP_breg11:
+        case DW_OP_breg12:
+        case DW_OP_breg13:
+        case DW_OP_breg14:
+        case DW_OP_breg15:
+        case DW_OP_breg16:
+        case DW_OP_breg17:
+        case DW_OP_breg18:
+        case DW_OP_breg19:
+        case DW_OP_breg20:
+        case DW_OP_breg21:
+        case DW_OP_breg22:
+        case DW_OP_breg23:
+        case DW_OP_breg24:
+        case DW_OP_breg25:
+        case DW_OP_breg26:
+        case DW_OP_breg27:
+        case DW_OP_breg28:
+        case DW_OP_breg29:
+        case DW_OP_breg30:
+        case DW_OP_breg31:  s->Printf("breg%i(0x%x)", op - DW_OP_breg0, m_data.GetULEB128(&offset)); break;
+
+        case DW_OP_regx:                                                    // 0x90 1 ULEB128 register
+            s->Printf("regx(0x%x)", m_data.GetULEB128(&offset));
+            break;
+        case DW_OP_fbreg:                                                   // 0x91 1 SLEB128 offset
+            s->Printf("fbreg(0x%x)",m_data.GetSLEB128(&offset));
+            break;
+        case DW_OP_bregx:                                                   // 0x92 2 ULEB128 register followed by SLEB128 offset
+            s->Printf("bregx(0x%x, 0x%x)", m_data.GetULEB128(&offset), m_data.GetSLEB128(&offset));
+            break;
+        case DW_OP_piece:                                                   // 0x93 1 ULEB128 size of piece addressed
+            s->Printf("piece(0x%x)", m_data.GetULEB128(&offset));
+            break;
+        case DW_OP_deref_size:                                              // 0x94 1 1-byte size of data retrieved
+            s->Printf("deref_size(0x%2.2x)", m_data.GetU8(&offset));
+            break;
+        case DW_OP_xderef_size:                                             // 0x95 1 1-byte size of data retrieved
+            s->Printf("xderef_size(0x%2.2x)", m_data.GetU8(&offset));
+            break;
+        case DW_OP_nop: s->PutCString("nop"); break;                                    // 0x96
+        case DW_OP_push_object_address: s->PutCString("push_object_address"); break;    // 0x97 DWARF3
+        case DW_OP_call2:                                                   // 0x98 DWARF3 1 2-byte offset of DIE
+            s->Printf("call2(0x%4.4x)", m_data.GetU16(&offset));
+            break;
+        case DW_OP_call4:                                                   // 0x99 DWARF3 1 4-byte offset of DIE
+            s->Printf("call4(0x%8.8x)", m_data.GetU32(&offset));
+            break;
+        case DW_OP_call_ref:                                                // 0x9a DWARF3 1 4- or 8-byte offset of DIE
+            s->Printf("call_ref(0x%8.8llx)", m_data.GetAddress(&offset));
+            break;
+//      case DW_OP_form_tls_address: s << "form_tls_address"; break;        // 0x9b DWARF3
+//      case DW_OP_call_frame_cfa: s << "call_frame_cfa"; break;            // 0x9c DWARF3
+//      case DW_OP_bit_piece:                                               // 0x9d DWARF3 2
+//          s->Printf("bit_piece(0x%x, 0x%x)", m_data.GetULEB128(&offset), m_data.GetULEB128(&offset));
+//          break;
+//      case DW_OP_lo_user:     s->PutCString("lo_user"); break;                        // 0xe0
+//      case DW_OP_hi_user:     s->PutCString("hi_user"); break;                        // 0xff
+        case DW_OP_APPLE_extern:
+            s->Printf("extern(%u)", m_data.GetULEB128(&offset));
+            break;
+        case DW_OP_APPLE_array_ref:
+            s->PutCString("array_ref");
+            break;
+        case DW_OP_APPLE_uninit:
+            s->PutCString("uninit");  // 0xF0
+            break;
+        case DW_OP_APPLE_assign:        // 0xF1 - pops value off and assigns it to second item on stack (2nd item must have assignable context)
+            s->PutCString("assign");
+            break;
+        case DW_OP_APPLE_address_of:    // 0xF2 - gets the address of the top stack item (top item must be a variable, or have value_type that is an address already)
+            s->PutCString("address_of");
+            break;
+        case DW_OP_APPLE_value_of:      // 0xF3 - pops the value off the stack and pushes the value of that object (top item must be a variable, or expression local)
+            s->PutCString("value_of");
+            break;
+        case DW_OP_APPLE_deref_type:    // 0xF4 - gets the address of the top stack item (top item must be a variable, or a clang type)
+            s->PutCString("deref_type");
+            break;
+        case DW_OP_APPLE_expr_local:    // 0xF5 - ULEB128 expression local index
+            s->Printf("expr_local(%u)", m_data.GetULEB128(&offset));
+            break;
+        case DW_OP_APPLE_constf:        // 0xF6 - 1 byte float size, followed by constant float data
+            {
+                uint8_t float_length = m_data.GetU8(&offset);
+                s->Printf("constf(<%u> ", float_length);
+                m_data.Dump(s, offset, eFormatHex, float_length, 1, UINT32_MAX, DW_INVALID_ADDRESS, 0, 0);
+                s->PutChar(')');
+                // Consume the float data
+                m_data.GetData(&offset, float_length);
+            }
+            break;
+        case DW_OP_APPLE_scalar_cast:
+            s->Printf("scalar_cast(%s)", Scalar::GetValueTypeAsCString ((Scalar::Type)m_data.GetU8(&offset)));
+            break;
+        case DW_OP_APPLE_clang_cast:
+            {
+                clang::Type *clang_type = (clang::Type *)m_data.GetMaxU64(&offset, sizeof(void*));
+                s->Printf("clang_cast(%p)", clang_type);
+            }
+            break;
+        case DW_OP_APPLE_clear:
+            s->PutCString("clear");
+            break;
+        case DW_OP_APPLE_error:         // 0xFF - Stops expression evaluation and returns an error (no args)
+            s->PutCString("error");
+            break;
+        }
+    }
+}
+
+void
+DWARFExpression::SetLocationListBaseAddress(Address& base_addr)
+{
+    m_loclist_base_addr = base_addr;
+}
+
+int
+DWARFExpression::GetRegisterKind ()
+{
+    return m_reg_kind;
+}
+
+void
+DWARFExpression::SetRegisterKind (int reg_kind)
+{
+    m_reg_kind = reg_kind;
+}
+
+bool
+DWARFExpression::IsLocationList() const
+{
+    return m_loclist_base_addr.IsSectionOffset();
+}
+
+void
+DWARFExpression::GetDescription (Stream *s, lldb::DescriptionLevel level) const
+{
+    if (IsLocationList())
+    {
+        // We have a location list
+        uint32_t offset = 0;
+        uint32_t count = 0;
+        Address base_addr(m_loclist_base_addr);
+        while (m_data.ValidOffset(offset))
+        {
+            lldb::addr_t begin_addr_offset = m_data.GetAddress(&offset);
+            lldb::addr_t end_addr_offset = m_data.GetAddress(&offset);
+            if (begin_addr_offset < end_addr_offset)
+            {
+                if (count > 0)
+                    s->PutCString(", ");
+                AddressRange addr_range(base_addr, end_addr_offset - begin_addr_offset);
+                addr_range.GetBaseAddress().SetOffset(base_addr.GetOffset() + begin_addr_offset);
+                addr_range.Dump (s, NULL, Address::DumpStyleFileAddress);
+                s->PutChar('{');
+                uint32_t location_length = m_data.GetU16(&offset);
+                DumpLocation (s, offset, location_length, level);
+                s->PutChar('}');
+                offset += location_length;
+            }
+            else if (begin_addr_offset == 0 && end_addr_offset == 0)
+            {
+                // The end of the location list is marked by both the start and end offset being zero
+                break;
+            }
+            else
+            {
+                if (m_data.GetAddressByteSize() == 4 && begin_addr_offset == 0xFFFFFFFFull ||
+                    m_data.GetAddressByteSize() == 8 && begin_addr_offset == 0xFFFFFFFFFFFFFFFFull)
+                {
+                    // We have a new base address
+                    if (count > 0)
+                        s->PutCString(", ");
+                    *s << "base_addr = " << end_addr_offset;
+                }
+            }
+
+            count++;
+        }
+    }
+    else
+    {
+        // We have a normal location that contains DW_OP location opcodes
+        DumpLocation (s, 0, m_data.GetByteSize(), level);
+    }
+}
+
+static bool
+ReadRegisterValueAsScalar
+(
+    ExecutionContext *exe_ctx,
+    uint32_t reg_kind,
+    uint32_t reg_num,
+    Error *error_ptr,
+    Value &value
+)
+{
+    if (exe_ctx && exe_ctx->frame)
+    {
+        RegisterContext *reg_context = exe_ctx->frame->GetRegisterContext();
+
+        if (reg_context == NULL)
+        {
+            if (error_ptr)
+                error_ptr->SetErrorStringWithFormat("No register context in frame.\n");
+        }
+        else
+        {
+            uint32_t native_reg = reg_context->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
+            if (native_reg == LLDB_INVALID_REGNUM)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorStringWithFormat("Unable to convert register kind=%u reg_num=%u to a native register number.\n", reg_kind, reg_num);
+            }
+            else
+            {
+                value.SetValueType (Value::eValueTypeScalar);
+                value.SetContext (Value::eContextTypeDCRegisterInfo, const_cast<RegisterInfo *>(reg_context->GetRegisterInfoAtIndex(native_reg)));
+
+                if (reg_context->ReadRegisterValue (native_reg, value.GetScalar()))
+                    return true;
+
+                if (error_ptr)
+                    error_ptr->SetErrorStringWithFormat("Failed to read register %u.\n", native_reg);
+            }
+        }
+    }
+    else
+    {
+        if (error_ptr)
+            error_ptr->SetErrorStringWithFormat("Invalid frame in execution context.\n");
+    }
+    return false;
+}
+
+bool
+DWARFExpression::LocationListContainsLoadAddress (Process* process, const Address &addr) const
+{
+    if (IsLocationList())
+    {
+        uint32_t offset = 0;
+        const addr_t load_addr = addr.GetLoadAddress(process);
+
+        if (load_addr == LLDB_INVALID_ADDRESS)
+            return false;
+
+        addr_t loc_list_base_addr = m_loclist_base_addr.GetLoadAddress(process);
+
+        if (loc_list_base_addr == LLDB_INVALID_ADDRESS)
+            return false;
+
+        while (m_data.ValidOffset(offset))
+        {
+            // We need to figure out what the value is for the location.
+            addr_t lo_pc = m_data.GetAddress(&offset);
+            addr_t hi_pc = m_data.GetAddress(&offset);
+            if (lo_pc == 0 && hi_pc == 0)
+                break;
+            else
+            {
+                lo_pc += loc_list_base_addr;
+                hi_pc += loc_list_base_addr;
+
+                if (lo_pc <= load_addr && load_addr < hi_pc)
+                    return true;
+
+                offset += m_data.GetU16(&offset);
+            }
+        }
+    }
+    return false;
+}
+bool
+DWARFExpression::Evaluate
+(
+    ExecutionContextScope *exe_scope,
+    clang::ASTContext *ast_context,
+    const Value* initial_value_ptr,
+    Value& result,
+    Error *error_ptr
+) const
+{
+    ExecutionContext exe_ctx (exe_scope);
+    return Evaluate(&exe_ctx, ast_context, initial_value_ptr, result, error_ptr);
+}
+
+bool
+DWARFExpression::Evaluate
+(
+    ExecutionContext *exe_ctx,
+    clang::ASTContext *ast_context,
+    const Value* initial_value_ptr,
+    Value& result,
+    Error *error_ptr
+) const
+{
+    if (IsLocationList())
+    {
+        uint32_t offset = 0;
+        addr_t pc = exe_ctx->frame->GetPC().GetLoadAddress(exe_ctx->process);
+
+        if (pc == LLDB_INVALID_ADDRESS)
+        {
+            if (error_ptr)
+                error_ptr->SetErrorString("Invalid PC in frame.");
+            return false;
+        }
+
+        addr_t loc_list_base_addr = m_loclist_base_addr.GetLoadAddress(exe_ctx->process);
+
+        if (loc_list_base_addr == LLDB_INVALID_ADDRESS)
+        {
+            if (error_ptr)
+                error_ptr->SetErrorString("Out of scope.");
+            return false;
+        }
+
+        while (m_data.ValidOffset(offset))
+        {
+            // We need to figure out what the value is for the location.
+            addr_t lo_pc = m_data.GetAddress(&offset);
+            addr_t hi_pc = m_data.GetAddress(&offset);
+            if (lo_pc == 0 && hi_pc == 0)
+            {
+                break;
+            }
+            else
+            {
+                lo_pc += loc_list_base_addr;
+                hi_pc += loc_list_base_addr;
+
+                uint16_t length = m_data.GetU16(&offset);
+
+                if (length > 0 && lo_pc <= pc && pc < hi_pc)
+                {
+                    return DWARFExpression::Evaluate (exe_ctx, ast_context, m_data, m_expr_locals, m_decl_map, offset, length, m_reg_kind, initial_value_ptr, result, error_ptr);
+                }
+                offset += length;
+            }
+        }
+        if (error_ptr)
+            error_ptr->SetErrorStringWithFormat("Out of scope.\n", pc);
+        return false;
+    }
+
+    // Not a location list, just a single expression.
+    return DWARFExpression::Evaluate (exe_ctx, ast_context, m_data, m_expr_locals, m_decl_map, 0, m_data.GetByteSize(), m_reg_kind, initial_value_ptr, result, error_ptr);
+}
+
+
+
+bool
+DWARFExpression::Evaluate
+(
+    ExecutionContext *exe_ctx,
+    clang::ASTContext *ast_context,
+    const DataExtractor& opcodes,
+    ClangExpressionVariableList *expr_locals,
+    ClangExpressionDeclMap *decl_map,
+    const uint32_t opcodes_offset,
+    const uint32_t opcodes_length,
+    const uint32_t reg_kind,
+    const Value* initial_value_ptr,
+    Value& result,
+    Error *error_ptr
+)
+{
+    std::vector<Value> stack;
+
+    if (initial_value_ptr)
+        stack.push_back(*initial_value_ptr);
+
+    uint32_t offset = opcodes_offset;
+    const uint32_t end_offset = opcodes_offset + opcodes_length;
+    Value tmp;
+    uint32_t reg_num;
+
+    // Make sure all of the data is available in opcodes.
+    if (!opcodes.ValidOffsetForDataOfSize(opcodes_offset, opcodes_length))
+    {
+        if (error_ptr)
+            error_ptr->SetErrorString ("Invalid offset and/or length for opcodes buffer.");
+        return false;
+    }
+    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
+
+
+    while (opcodes.ValidOffset(offset) && offset < end_offset)
+    {
+        const uint32_t op_offset = offset;
+        const uint8_t op = opcodes.GetU8(&offset);
+
+        if (log)
+        {
+            log->Printf("\n");
+            size_t count = stack.size();
+            for (size_t i=0; i<count; ++i)
+            {
+                StreamString new_value;
+                new_value.Printf("[%zu]", i);
+                stack[i].Dump(&new_value);
+                log->Printf("%s", new_value.GetData());
+            }
+            log->Printf("0x%8.8x: %s", op_offset, DW_OP_value_to_name(op));
+        }
+        switch (op)
+        {
+        //----------------------------------------------------------------------
+        // The DW_OP_addr operation has a single operand that encodes a machine
+        // address and whose size is the size of an address on the target machine.
+        //----------------------------------------------------------------------
+        case DW_OP_addr:
+            stack.push_back(opcodes.GetAddress(&offset));
+            stack.back().SetValueType (Value::eValueTypeFileAddress);
+            break;
+
+        //----------------------------------------------------------------------
+        // The DW_OP_addr_sect_offset4 is used for any location expressions in
+        // shared libraries that have a location like:
+        //  DW_OP_addr(0x1000)
+        // If this address resides in a shared library, then this virtual
+        // address won't make sense when it is evaluated in the context of a
+        // running process where shared libraries have been slid. To account for
+        // this, this new address type where we can store the section pointer
+        // and a 4 byte offset.
+        //----------------------------------------------------------------------
+//      case DW_OP_addr_sect_offset4:
+//          {
+//              result_type = eResultTypeFileAddress;
+//              lldb::Section *sect = (lldb::Section *)opcodes.GetMaxU64(&offset, sizeof(void *));
+//              lldb::addr_t sect_offset = opcodes.GetU32(&offset);
+//
+//              Address so_addr (sect, sect_offset);
+//              lldb::addr_t load_addr = so_addr.GetLoadAddress();
+//              if (load_addr != LLDB_INVALID_ADDRESS)
+//              {
+//                  // We successfully resolve a file address to a load
+//                  // address.
+//                  stack.push_back(load_addr);
+//                  break;
+//              }
+//              else
+//              {
+//                  // We were able
+//                  if (error_ptr)
+//                      error_ptr->SetErrorStringWithFormat ("Section %s in %s is not currently loaded.\n", sect->GetName().AsCString(), sect->GetModule()->GetFileSpec().GetFilename().AsCString());
+//                  return false;
+//              }
+//          }
+//          break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_deref
+        // OPERANDS: none
+        // DESCRIPTION: Pops the top stack entry and treats it as an address.
+        // The value retrieved from that address is pushed. The size of the
+        // data retrieved from the dereferenced address is the size of an
+        // address on the target machine.
+        //----------------------------------------------------------------------
+        case DW_OP_deref:
+            {
+                Value::ValueType value_type = stack.back().GetValueType();
+                switch (value_type)
+                {
+                case Value::eValueTypeHostAddress:
+                    {
+                        void *src = (void *)stack.back().GetScalar().ULongLong();
+                        intptr_t ptr;
+                        ::memcpy (&ptr, src, sizeof(void *));
+                        stack.back().GetScalar() = ptr;
+                        stack.back().ClearContext();
+                    }
+                    break;
+                case Value::eValueTypeLoadAddress:
+                    if (exe_ctx)
+                    {
+                        if (exe_ctx->process)
+                        {
+                            lldb::addr_t pointer_addr = stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
+                            uint8_t addr_bytes[sizeof(lldb::addr_t)];
+                            uint32_t addr_size = exe_ctx->process->GetAddressByteSize();
+                            Error error;
+                            if (exe_ctx->process->ReadMemory(pointer_addr, &addr_bytes, addr_size, error) == addr_size)
+                            {
+                                DataExtractor addr_data(addr_bytes, sizeof(addr_bytes), exe_ctx->process->GetByteOrder(), addr_size);
+                                uint32_t addr_data_offset = 0;
+                                stack.back().GetScalar() = addr_data.GetPointer(&addr_data_offset);
+                                stack.back().ClearContext();
+                            }
+                            else
+                            {
+                                if (error_ptr)
+                                    error_ptr->SetErrorStringWithFormat ("Failed to dereference pointer from 0x%llx for DW_OP_deref: %s\n", 
+                                                                         pointer_addr,
+                                                                         error.AsCString());
+                                return false;
+                            }
+                        }
+                        else
+                        {
+                            if (error_ptr)
+                                error_ptr->SetErrorStringWithFormat ("NULL process for DW_OP_deref.\n");
+                            return false;
+                        }
+                    }
+                    else
+                    {
+                        if (error_ptr)
+                            error_ptr->SetErrorStringWithFormat ("NULL execution context for DW_OP_deref.\n");
+                        return false;
+                    }
+                    break;
+
+                default:
+                    break;
+                }
+
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_deref_size
+        // OPERANDS: 1
+        //  1 - uint8_t that specifies the size of the data to dereference.
+        // DESCRIPTION: Behaves like the DW_OP_deref operation: it pops the top
+        // stack entry and treats it as an address. The value retrieved from that
+        // address is pushed. In the DW_OP_deref_size operation, however, the
+        // size in bytes of the data retrieved from the dereferenced address is
+        // specified by the single operand. This operand is a 1-byte unsigned
+        // integral constant whose value may not be larger than the size of an
+        // address on the target machine. The data retrieved is zero extended
+        // to the size of an address on the target machine before being pushed
+        // on the expression stack.
+        //----------------------------------------------------------------------
+        case DW_OP_deref_size:
+            if (error_ptr)
+                error_ptr->SetErrorString("Unimplemented opcode: DW_OP_deref_size.");
+            return false;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_xderef_size
+        // OPERANDS: 1
+        //  1 - uint8_t that specifies the size of the data to dereference.
+        // DESCRIPTION: Behaves like the DW_OP_xderef operation: the entry at
+        // the top of the stack is treated as an address. The second stack
+        // entry is treated as an “address space identifier” for those
+        // architectures that support multiple address spaces. The top two
+        // stack elements are popped, a data item is retrieved through an
+        // implementation-defined address calculation and pushed as the new
+        // stack top. In the DW_OP_xderef_size operation, however, the size in
+        // bytes of the data retrieved from the dereferenced address is
+        // specified by the single operand. This operand is a 1-byte unsigned
+        // integral constant whose value may not be larger than the size of an
+        // address on the target machine. The data retrieved is zero extended
+        // to the size of an address on the target machine before being pushed
+        // on the expression stack.
+        //----------------------------------------------------------------------
+        case DW_OP_xderef_size:
+            if (error_ptr)
+                error_ptr->SetErrorString("Unimplemented opcode: DW_OP_xderef_size.");
+            return false;
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_xderef
+        // OPERANDS: none
+        // DESCRIPTION: Provides an extended dereference mechanism. The entry at
+        // the top of the stack is treated as an address. The second stack entry
+        // is treated as an "address space identifier" for those architectures
+        // that support multiple address spaces. The top two stack elements are
+        // popped, a data item is retrieved through an implementation-defined
+        // address calculation and pushed as the new stack top. The size of the
+        // data retrieved from the dereferenced address is the size of an address
+        // on the target machine.
+        //----------------------------------------------------------------------
+        case DW_OP_xderef:
+            if (error_ptr)
+                error_ptr->SetErrorString("Unimplemented opcode: DW_OP_xderef.");
+            return false;
+
+        //----------------------------------------------------------------------
+        // All DW_OP_constXXX opcodes have a single operand as noted below:
+        //
+        // Opcode           Operand 1
+        // ---------------  ----------------------------------------------------
+        // DW_OP_const1u    1-byte unsigned integer constant
+        // DW_OP_const1s    1-byte signed integer constant
+        // DW_OP_const2u    2-byte unsigned integer constant
+        // DW_OP_const2s    2-byte signed integer constant
+        // DW_OP_const4u    4-byte unsigned integer constant
+        // DW_OP_const4s    4-byte signed integer constant
+        // DW_OP_const8u    8-byte unsigned integer constant
+        // DW_OP_const8s    8-byte signed integer constant
+        // DW_OP_constu     unsigned LEB128 integer constant
+        // DW_OP_consts     signed LEB128 integer constant
+        //----------------------------------------------------------------------
+        case DW_OP_const1u             :    stack.push_back(( uint8_t)opcodes.GetU8(&offset)); break;
+        case DW_OP_const1s             :    stack.push_back((  int8_t)opcodes.GetU8(&offset)); break;
+        case DW_OP_const2u             :    stack.push_back((uint16_t)opcodes.GetU16(&offset)); break;
+        case DW_OP_const2s             :    stack.push_back(( int16_t)opcodes.GetU16(&offset)); break;
+        case DW_OP_const4u             :    stack.push_back((uint32_t)opcodes.GetU32(&offset)); break;
+        case DW_OP_const4s             :    stack.push_back(( int32_t)opcodes.GetU32(&offset)); break;
+        case DW_OP_const8u             :    stack.push_back((uint64_t)opcodes.GetU64(&offset)); break;
+        case DW_OP_const8s             :    stack.push_back(( int64_t)opcodes.GetU64(&offset)); break;
+        case DW_OP_constu              :    stack.push_back(opcodes.GetULEB128(&offset)); break;
+        case DW_OP_consts              :    stack.push_back(opcodes.GetSLEB128(&offset)); break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_dup
+        // OPERANDS: none
+        // DESCRIPTION: duplicates the value at the top of the stack
+        //----------------------------------------------------------------------
+        case DW_OP_dup:
+            if (stack.empty())
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack empty for DW_OP_dup.");
+                return false;
+            }
+            else
+                stack.push_back(stack.back());
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_drop
+        // OPERANDS: none
+        // DESCRIPTION: pops the value at the top of the stack
+        //----------------------------------------------------------------------
+        case DW_OP_drop:
+            if (stack.empty())
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack empty for DW_OP_drop.");
+                return false;
+            }
+            else
+                stack.pop_back();
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_over
+        // OPERANDS: none
+        // DESCRIPTION: Duplicates the entry currently second in the stack at
+        // the top of the stack.
+        //----------------------------------------------------------------------
+        case DW_OP_over:
+            if (stack.size() < 2)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_over.");
+                return false;
+            }
+            else
+                stack.push_back(stack[stack.size() - 2]);
+            break;
+
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_pick
+        // OPERANDS: uint8_t index into the current stack
+        // DESCRIPTION: The stack entry with the specified index (0 through 255,
+        // inclusive) is pushed on the stack
+        //----------------------------------------------------------------------
+        case DW_OP_pick:
+            {
+                uint8_t pick_idx = opcodes.GetU8(&offset);
+                if (pick_idx < stack.size())
+                    stack.push_back(stack[pick_idx]);
+                else
+                {
+                    if (error_ptr)
+                        error_ptr->SetErrorStringWithFormat("Index %u out of range for DW_OP_pick.\n", pick_idx);
+                    return false;
+                }
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_swap
+        // OPERANDS: none
+        // DESCRIPTION: swaps the top two stack entries. The entry at the top
+        // of the stack becomes the second stack entry, and the second entry
+        // becomes the top of the stack
+        //----------------------------------------------------------------------
+        case DW_OP_swap:
+            if (stack.size() < 2)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_swap.");
+                return false;
+            }
+            else
+            {
+                tmp = stack.back();
+                stack.back() = stack[stack.size() - 2];
+                stack[stack.size() - 2] = tmp;
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_rot
+        // OPERANDS: none
+        // DESCRIPTION: Rotates the first three stack entries. The entry at
+        // the top of the stack becomes the third stack entry, the second
+        // entry becomes the top of the stack, and the third entry becomes
+        // the second entry.
+        //----------------------------------------------------------------------
+        case DW_OP_rot:
+            if (stack.size() < 3)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 3 items for DW_OP_rot.");
+                return false;
+            }
+            else
+            {
+                size_t last_idx = stack.size() - 1;
+                Value old_top = stack[last_idx];
+                stack[last_idx] = stack[last_idx - 1];
+                stack[last_idx - 1] = stack[last_idx - 2];
+                stack[last_idx - 2] = old_top;
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_abs
+        // OPERANDS: none
+        // DESCRIPTION: pops the top stack entry, interprets it as a signed
+        // value and pushes its absolute value. If the absolute value can not be
+        // represented, the result is undefined.
+        //----------------------------------------------------------------------
+        case DW_OP_abs:
+            if (stack.empty())
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 1 item for DW_OP_abs.");
+                return false;
+            }
+            else if (stack.back().ResolveValue(exe_ctx, ast_context).AbsoluteValue() == false)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Failed to take the absolute value of the first stack item.");
+                return false;
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_and
+        // OPERANDS: none
+        // DESCRIPTION: pops the top two stack values, performs a bitwise and
+        // operation on the two, and pushes the result.
+        //----------------------------------------------------------------------
+        case DW_OP_and:
+            if (stack.size() < 2)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_and.");
+                return false;
+            }
+            else
+            {
+                tmp = stack.back();
+                stack.pop_back();
+                stack.back().ResolveValue(exe_ctx, ast_context) = stack.back().ResolveValue(exe_ctx, ast_context) & tmp.ResolveValue(exe_ctx, ast_context);
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_div
+        // OPERANDS: none
+        // DESCRIPTION: pops the top two stack values, divides the former second
+        // entry by the former top of the stack using signed division, and
+        // pushes the result.
+        //----------------------------------------------------------------------
+        case DW_OP_div:
+            if (stack.size() < 2)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_div.");
+                return false;
+            }
+            else
+            {
+                tmp = stack.back();
+                if (tmp.ResolveValue(exe_ctx, ast_context).IsZero())
+                {
+                    if (error_ptr)
+                        error_ptr->SetErrorString("Divide by zero.");
+                    return false;
+                }
+                else
+                {
+                    stack.pop_back();
+                    stack.back() = stack.back().ResolveValue(exe_ctx, ast_context) / tmp.ResolveValue(exe_ctx, ast_context);
+                    if (!stack.back().ResolveValue(exe_ctx, ast_context).IsValid())
+                    {
+                        if (error_ptr)
+                            error_ptr->SetErrorString("Divide failed.");
+                        return false;
+                    }
+                }
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_minus
+        // OPERANDS: none
+        // DESCRIPTION: pops the top two stack values, subtracts the former top
+        // of the stack from the former second entry, and pushes the result.
+        //----------------------------------------------------------------------
+        case DW_OP_minus:
+            if (stack.size() < 2)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_minus.");
+                return false;
+            }
+            else
+            {
+                tmp = stack.back();
+                stack.pop_back();
+                stack.back().ResolveValue(exe_ctx, ast_context) = stack.back().ResolveValue(exe_ctx, ast_context) - tmp.ResolveValue(exe_ctx, ast_context);
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_mod
+        // OPERANDS: none
+        // DESCRIPTION: pops the top two stack values and pushes the result of
+        // the calculation: former second stack entry modulo the former top of
+        // the stack.
+        //----------------------------------------------------------------------
+        case DW_OP_mod:
+            if (stack.size() < 2)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_mod.");
+                return false;
+            }
+            else
+            {
+                tmp = stack.back();
+                stack.pop_back();
+                stack.back().ResolveValue(exe_ctx, ast_context) = stack.back().ResolveValue(exe_ctx, ast_context) % tmp.ResolveValue(exe_ctx, ast_context);
+            }
+            break;
+
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_mul
+        // OPERANDS: none
+        // DESCRIPTION: pops the top two stack entries, multiplies them
+        // together, and pushes the result.
+        //----------------------------------------------------------------------
+        case DW_OP_mul:
+            if (stack.size() < 2)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_mul.");
+                return false;
+            }
+            else
+            {
+                tmp = stack.back();
+                stack.pop_back();
+                stack.back().ResolveValue(exe_ctx, ast_context) = stack.back().ResolveValue(exe_ctx, ast_context) * tmp.ResolveValue(exe_ctx, ast_context);
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_neg
+        // OPERANDS: none
+        // DESCRIPTION: pops the top stack entry, and pushes its negation.
+        //----------------------------------------------------------------------
+        case DW_OP_neg:
+            if (stack.empty())
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 1 item for DW_OP_neg.");
+                return false;
+            }
+            else
+            {
+                if (stack.back().ResolveValue(exe_ctx, ast_context).UnaryNegate() == false)
+                {
+                    if (error_ptr)
+                        error_ptr->SetErrorString("Unary negate failed.");
+                    return false;
+                }
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_not
+        // OPERANDS: none
+        // DESCRIPTION: pops the top stack entry, and pushes its bitwise
+        // complement
+        //----------------------------------------------------------------------
+        case DW_OP_not:
+            if (stack.empty())
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 1 item for DW_OP_not.");
+                return false;
+            }
+            else
+            {
+                if (stack.back().ResolveValue(exe_ctx, ast_context).OnesComplement() == false)
+                {
+                    if (error_ptr)
+                        error_ptr->SetErrorString("Logical NOT failed.");
+                    return false;
+                }
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_or
+        // OPERANDS: none
+        // DESCRIPTION: pops the top two stack entries, performs a bitwise or
+        // operation on the two, and pushes the result.
+        //----------------------------------------------------------------------
+        case DW_OP_or:
+            if (stack.size() < 2)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_or.");
+                return false;
+            }
+            else
+            {
+                tmp = stack.back();
+                stack.pop_back();
+                stack.back().ResolveValue(exe_ctx, ast_context) = stack.back().ResolveValue(exe_ctx, ast_context) | tmp.ResolveValue(exe_ctx, ast_context);
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_plus
+        // OPERANDS: none
+        // DESCRIPTION: pops the top two stack entries, adds them together, and
+        // pushes the result.
+        //----------------------------------------------------------------------
+        case DW_OP_plus:
+            if (stack.size() < 2)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_plus.");
+                return false;
+            }
+            else
+            {
+                tmp = stack.back();
+                stack.pop_back();
+                stack.back().ResolveValue(exe_ctx, ast_context) = stack.back().ResolveValue(exe_ctx, ast_context) + tmp.ResolveValue(exe_ctx, ast_context);
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_plus_uconst
+        // OPERANDS: none
+        // DESCRIPTION: pops the top stack entry, adds it to the unsigned LEB128
+        // constant operand and pushes the result.
+        //----------------------------------------------------------------------
+        case DW_OP_plus_uconst:
+            if (stack.empty())
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 1 item for DW_OP_plus_uconst.");
+                return false;
+            }
+            else
+            {
+                uint32_t uconst_value = opcodes.GetULEB128(&offset);
+                // Implicit conversion from a UINT to a Scalar...
+                stack.back().ResolveValue(exe_ctx, ast_context) += uconst_value;
+                if (!stack.back().ResolveValue(exe_ctx, ast_context).IsValid())
+                {
+                    if (error_ptr)
+                        error_ptr->SetErrorString("DW_OP_plus_uconst failed.");
+                    return false;
+                }
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_shl
+        // OPERANDS: none
+        // DESCRIPTION:  pops the top two stack entries, shifts the former
+        // second entry left by the number of bits specified by the former top
+        // of the stack, and pushes the result.
+        //----------------------------------------------------------------------
+        case DW_OP_shl:
+            if (stack.size() < 2)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_shl.");
+                return false;
+            }
+            else
+            {
+                tmp = stack.back();
+                stack.pop_back();
+                stack.back().ResolveValue(exe_ctx, ast_context) <<= tmp.ResolveValue(exe_ctx, ast_context);
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_shr
+        // OPERANDS: none
+        // DESCRIPTION: pops the top two stack entries, shifts the former second
+        // entry right logically (filling with zero bits) by the number of bits
+        // specified by the former top of the stack, and pushes the result.
+        //----------------------------------------------------------------------
+        case DW_OP_shr:
+            if (stack.size() < 2)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_shr.");
+                return false;
+            }
+            else
+            {
+                tmp = stack.back();
+                stack.pop_back();
+                if (stack.back().ResolveValue(exe_ctx, ast_context).ShiftRightLogical(tmp.ResolveValue(exe_ctx, ast_context)) == false)
+                {
+                    if (error_ptr)
+                        error_ptr->SetErrorString("DW_OP_shr failed.");
+                    return false;
+                }
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_shra
+        // OPERANDS: none
+        // DESCRIPTION: pops the top two stack entries, shifts the former second
+        // entry right arithmetically (divide the magnitude by 2, keep the same
+        // sign for the result) by the number of bits specified by the former
+        // top of the stack, and pushes the result.
+        //----------------------------------------------------------------------
+        case DW_OP_shra:
+            if (stack.size() < 2)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_shra.");
+                return false;
+            }
+            else
+            {
+                tmp = stack.back();
+                stack.pop_back();
+                stack.back().ResolveValue(exe_ctx, ast_context) >>= tmp.ResolveValue(exe_ctx, ast_context);
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_xor
+        // OPERANDS: none
+        // DESCRIPTION: pops the top two stack entries, performs the bitwise
+        // exclusive-or operation on the two, and pushes the result.
+        //----------------------------------------------------------------------
+        case DW_OP_xor:
+            if (stack.size() < 2)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_xor.");
+                return false;
+            }
+            else
+            {
+                tmp = stack.back();
+                stack.pop_back();
+                stack.back().ResolveValue(exe_ctx, ast_context) = stack.back().ResolveValue(exe_ctx, ast_context) ^ tmp.ResolveValue(exe_ctx, ast_context);
+            }
+            break;
+
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_skip
+        // OPERANDS: int16_t
+        // DESCRIPTION:  An unconditional branch. Its single operand is a 2-byte
+        // signed integer constant. The 2-byte constant is the number of bytes
+        // of the DWARF expression to skip forward or backward from the current
+        // operation, beginning after the 2-byte constant.
+        //----------------------------------------------------------------------
+        case DW_OP_skip:
+            {
+                int16_t skip_offset = (int16_t)opcodes.GetU16(&offset);
+                uint32_t new_offset = offset + skip_offset;
+                if (new_offset >= opcodes_offset && new_offset < end_offset)
+                    offset = new_offset;
+                else
+                {
+                    if (error_ptr)
+                        error_ptr->SetErrorString("Invalid opcode offset in DW_OP_skip.");
+                    return false;
+                }
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_bra
+        // OPERANDS: int16_t
+        // DESCRIPTION: A conditional branch. Its single operand is a 2-byte
+        // signed integer constant. This operation pops the top of stack. If
+        // the value popped is not the constant 0, the 2-byte constant operand
+        // is the number of bytes of the DWARF expression to skip forward or
+        // backward from the current operation, beginning after the 2-byte
+        // constant.
+        //----------------------------------------------------------------------
+        case DW_OP_bra:
+            {
+                tmp = stack.back();
+                stack.pop_back();
+                int16_t bra_offset = (int16_t)opcodes.GetU16(&offset);
+                Scalar zero(0);
+                if (tmp.ResolveValue(exe_ctx, ast_context) != zero)
+                {
+                    uint32_t new_offset = offset + bra_offset;
+                    if (new_offset >= opcodes_offset && new_offset < end_offset)
+                        offset = new_offset;
+                    else
+                    {
+                        if (error_ptr)
+                            error_ptr->SetErrorString("Invalid opcode offset in DW_OP_bra.");
+                        return false;
+                    }
+                }
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_eq
+        // OPERANDS: none
+        // DESCRIPTION: pops the top two stack values, compares using the
+        // equals (==) operator.
+        // STACK RESULT: push the constant value 1 onto the stack if the result
+        // of the operation is true or the constant value 0 if the result of the
+        // operation is false.
+        //----------------------------------------------------------------------
+        case DW_OP_eq:
+            if (stack.size() < 2)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_eq.");
+                return false;
+            }
+            else
+            {
+                tmp = stack.back();
+                stack.pop_back();
+                stack.back().ResolveValue(exe_ctx, ast_context) = stack.back().ResolveValue(exe_ctx, ast_context) == tmp.ResolveValue(exe_ctx, ast_context);
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_ge
+        // OPERANDS: none
+        // DESCRIPTION: pops the top two stack values, compares using the
+        // greater than or equal to (>=) operator.
+        // STACK RESULT: push the constant value 1 onto the stack if the result
+        // of the operation is true or the constant value 0 if the result of the
+        // operation is false.
+        //----------------------------------------------------------------------
+        case DW_OP_ge:
+            if (stack.size() < 2)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_ge.");
+                return false;
+            }
+            else
+            {
+                tmp = stack.back();
+                stack.pop_back();
+                stack.back().ResolveValue(exe_ctx, ast_context) = stack.back().ResolveValue(exe_ctx, ast_context) >= tmp.ResolveValue(exe_ctx, ast_context);
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_gt
+        // OPERANDS: none
+        // DESCRIPTION: pops the top two stack values, compares using the
+        // greater than (>) operator.
+        // STACK RESULT: push the constant value 1 onto the stack if the result
+        // of the operation is true or the constant value 0 if the result of the
+        // operation is false.
+        //----------------------------------------------------------------------
+        case DW_OP_gt:
+            if (stack.size() < 2)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_gt.");
+                return false;
+            }
+            else
+            {
+                tmp = stack.back();
+                stack.pop_back();
+                stack.back().ResolveValue(exe_ctx, ast_context) = stack.back().ResolveValue(exe_ctx, ast_context) > tmp.ResolveValue(exe_ctx, ast_context);
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_le
+        // OPERANDS: none
+        // DESCRIPTION: pops the top two stack values, compares using the
+        // less than or equal to (<=) operator.
+        // STACK RESULT: push the constant value 1 onto the stack if the result
+        // of the operation is true or the constant value 0 if the result of the
+        // operation is false.
+        //----------------------------------------------------------------------
+        case DW_OP_le:
+            if (stack.size() < 2)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_le.");
+                return false;
+            }
+            else
+            {
+                tmp = stack.back();
+                stack.pop_back();
+                stack.back().ResolveValue(exe_ctx, ast_context) = stack.back().ResolveValue(exe_ctx, ast_context) <= tmp.ResolveValue(exe_ctx, ast_context);
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_lt
+        // OPERANDS: none
+        // DESCRIPTION: pops the top two stack values, compares using the
+        // less than (<) operator.
+        // STACK RESULT: push the constant value 1 onto the stack if the result
+        // of the operation is true or the constant value 0 if the result of the
+        // operation is false.
+        //----------------------------------------------------------------------
+        case DW_OP_lt:
+            if (stack.size() < 2)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_lt.");
+                return false;
+            }
+            else
+            {
+                tmp = stack.back();
+                stack.pop_back();
+                stack.back().ResolveValue(exe_ctx, ast_context) = stack.back().ResolveValue(exe_ctx, ast_context) < tmp.ResolveValue(exe_ctx, ast_context);
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_ne
+        // OPERANDS: none
+        // DESCRIPTION: pops the top two stack values, compares using the
+        // not equal (!=) operator.
+        // STACK RESULT: push the constant value 1 onto the stack if the result
+        // of the operation is true or the constant value 0 if the result of the
+        // operation is false.
+        //----------------------------------------------------------------------
+        case DW_OP_ne:
+            if (stack.size() < 2)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_ne.");
+                return false;
+            }
+            else
+            {
+                tmp = stack.back();
+                stack.pop_back();
+                stack.back().ResolveValue(exe_ctx, ast_context) = stack.back().ResolveValue(exe_ctx, ast_context) != tmp.ResolveValue(exe_ctx, ast_context);
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_litn
+        // OPERANDS: none
+        // DESCRIPTION: encode the unsigned literal values from 0 through 31.
+        // STACK RESULT: push the unsigned literal constant value onto the top
+        // of the stack.
+        //----------------------------------------------------------------------
+        case DW_OP_lit0:
+        case DW_OP_lit1:
+        case DW_OP_lit2:
+        case DW_OP_lit3:
+        case DW_OP_lit4:
+        case DW_OP_lit5:
+        case DW_OP_lit6:
+        case DW_OP_lit7:
+        case DW_OP_lit8:
+        case DW_OP_lit9:
+        case DW_OP_lit10:
+        case DW_OP_lit11:
+        case DW_OP_lit12:
+        case DW_OP_lit13:
+        case DW_OP_lit14:
+        case DW_OP_lit15:
+        case DW_OP_lit16:
+        case DW_OP_lit17:
+        case DW_OP_lit18:
+        case DW_OP_lit19:
+        case DW_OP_lit20:
+        case DW_OP_lit21:
+        case DW_OP_lit22:
+        case DW_OP_lit23:
+        case DW_OP_lit24:
+        case DW_OP_lit25:
+        case DW_OP_lit26:
+        case DW_OP_lit27:
+        case DW_OP_lit28:
+        case DW_OP_lit29:
+        case DW_OP_lit30:
+        case DW_OP_lit31:
+            stack.push_back(op - DW_OP_lit0);
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_regN
+        // OPERANDS: none
+        // DESCRIPTION: Push the value in register n on the top of the stack.
+        //----------------------------------------------------------------------
+        case DW_OP_reg0:
+        case DW_OP_reg1:
+        case DW_OP_reg2:
+        case DW_OP_reg3:
+        case DW_OP_reg4:
+        case DW_OP_reg5:
+        case DW_OP_reg6:
+        case DW_OP_reg7:
+        case DW_OP_reg8:
+        case DW_OP_reg9:
+        case DW_OP_reg10:
+        case DW_OP_reg11:
+        case DW_OP_reg12:
+        case DW_OP_reg13:
+        case DW_OP_reg14:
+        case DW_OP_reg15:
+        case DW_OP_reg16:
+        case DW_OP_reg17:
+        case DW_OP_reg18:
+        case DW_OP_reg19:
+        case DW_OP_reg20:
+        case DW_OP_reg21:
+        case DW_OP_reg22:
+        case DW_OP_reg23:
+        case DW_OP_reg24:
+        case DW_OP_reg25:
+        case DW_OP_reg26:
+        case DW_OP_reg27:
+        case DW_OP_reg28:
+        case DW_OP_reg29:
+        case DW_OP_reg30:
+        case DW_OP_reg31:
+            {
+                reg_num = op - DW_OP_reg0;
+
+                if (ReadRegisterValueAsScalar (exe_ctx, reg_kind, reg_num, error_ptr, tmp))
+                    stack.push_back(tmp);
+                else
+                    return false;
+            }
+            break;
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_regx
+        // OPERANDS:
+        //      ULEB128 literal operand that encodes the register.
+        // DESCRIPTION: Push the value in register on the top of the stack.
+        //----------------------------------------------------------------------
+        case DW_OP_regx:
+            {
+                reg_num = opcodes.GetULEB128(&offset);
+                if (ReadRegisterValueAsScalar (exe_ctx, reg_kind, reg_num, error_ptr, tmp))
+                    stack.push_back(tmp);
+                else
+                    return false;
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_bregN
+        // OPERANDS:
+        //      SLEB128 offset from register N
+        // DESCRIPTION: Value is in memory at the address specified by register
+        // N plus an offset.
+        //----------------------------------------------------------------------
+        case DW_OP_breg0:
+        case DW_OP_breg1:
+        case DW_OP_breg2:
+        case DW_OP_breg3:
+        case DW_OP_breg4:
+        case DW_OP_breg5:
+        case DW_OP_breg6:
+        case DW_OP_breg7:
+        case DW_OP_breg8:
+        case DW_OP_breg9:
+        case DW_OP_breg10:
+        case DW_OP_breg11:
+        case DW_OP_breg12:
+        case DW_OP_breg13:
+        case DW_OP_breg14:
+        case DW_OP_breg15:
+        case DW_OP_breg16:
+        case DW_OP_breg17:
+        case DW_OP_breg18:
+        case DW_OP_breg19:
+        case DW_OP_breg20:
+        case DW_OP_breg21:
+        case DW_OP_breg22:
+        case DW_OP_breg23:
+        case DW_OP_breg24:
+        case DW_OP_breg25:
+        case DW_OP_breg26:
+        case DW_OP_breg27:
+        case DW_OP_breg28:
+        case DW_OP_breg29:
+        case DW_OP_breg30:
+        case DW_OP_breg31:
+            {
+                reg_num = op - DW_OP_breg0;
+
+                if (ReadRegisterValueAsScalar (exe_ctx, reg_kind, reg_num, error_ptr, tmp))
+                {
+                    int64_t breg_offset = opcodes.GetSLEB128(&offset);
+                    tmp.ResolveValue(exe_ctx, ast_context) += (uint64_t)breg_offset;
+                    stack.push_back(tmp);
+                    stack.back().SetValueType (Value::eValueTypeLoadAddress);
+                }
+                else
+                    return false;
+            }
+            break;
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_bregx
+        // OPERANDS: 2
+        //      ULEB128 literal operand that encodes the register.
+        //      SLEB128 offset from register N
+        // DESCRIPTION: Value is in memory at the address specified by register
+        // N plus an offset.
+        //----------------------------------------------------------------------
+        case DW_OP_bregx:
+            {
+                reg_num = opcodes.GetULEB128(&offset);
+
+                if (ReadRegisterValueAsScalar (exe_ctx, reg_kind, reg_num, error_ptr, tmp))
+                {
+                    int64_t breg_offset = opcodes.GetSLEB128(&offset);
+                    tmp.ResolveValue(exe_ctx, ast_context) += (uint64_t)breg_offset;
+                    stack.push_back(tmp);
+                    stack.back().SetValueType (Value::eValueTypeLoadAddress);
+                }
+                else
+                    return false;
+            }
+            break;
+
+        case DW_OP_fbreg:
+            if (exe_ctx && exe_ctx->frame)
+            {
+                Scalar value;
+                if (exe_ctx->frame->GetFrameBaseValue(value, error_ptr))
+                {
+                    int64_t fbreg_offset = opcodes.GetSLEB128(&offset);
+                    value += fbreg_offset;
+                    stack.push_back(value);
+                    stack.back().SetValueType (Value::eValueTypeLoadAddress);
+                }
+                else
+                    return false;
+            }
+            else
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString ("Invalid stack frame in context for DW_OP_fbreg opcode.");
+                return false;
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_nop
+        // OPERANDS: none
+        // DESCRIPTION: A place holder. It has no effect on the location stack
+        // or any of its values.
+        //----------------------------------------------------------------------
+        case DW_OP_nop:
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_piece
+        // OPERANDS: 1
+        //      ULEB128: byte size of the piece
+        // DESCRIPTION: The operand describes the size in bytes of the piece of
+        // the object referenced by the DWARF expression whose result is at the
+        // top of the stack. If the piece is located in a register, but does not
+        // occupy the entire register, the placement of the piece within that
+        // register is defined by the ABI.
+        //
+        // Many compilers store a single variable in sets of registers, or store
+        // a variable partially in memory and partially in registers.
+        // DW_OP_piece provides a way of describing how large a part of a
+        // variable a particular DWARF expression refers to.
+        //----------------------------------------------------------------------
+        case DW_OP_piece:
+            if (error_ptr)
+                error_ptr->SetErrorString ("Unimplemented opcode DW_OP_piece.");
+            return false;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_push_object_address
+        // OPERANDS: none
+        // DESCRIPTION: Pushes the address of the object currently being
+        // evaluated as part of evaluation of a user presented expression.
+        // This object may correspond to an independent variable described by
+        // its own DIE or it may be a component of an array, structure, or class
+        // whose address has been dynamically determined by an earlier step
+        // during user expression evaluation.
+        //----------------------------------------------------------------------
+        case DW_OP_push_object_address:
+            if (error_ptr)
+                error_ptr->SetErrorString ("Unimplemented opcode DW_OP_push_object_address.");
+            return false;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_call2
+        // OPERANDS:
+        //      uint16_t compile unit relative offset of a DIE
+        // DESCRIPTION: Performs subroutine calls during evaluation
+        // of a DWARF expression. The operand is the 2-byte unsigned offset
+        // of a debugging information entry in the current compilation unit.
+        //
+        // Operand interpretation is exactly like that for DW_FORM_ref2.
+        //
+        // This operation transfers control of DWARF expression evaluation
+        // to the DW_AT_location attribute of the referenced DIE. If there is
+        // no such attribute, then there is no effect. Execution of the DWARF
+        // expression of a DW_AT_location attribute may add to and/or remove from
+        // values on the stack. Execution returns to the point following the call
+        // when the end of the attribute is reached. Values on the stack at the
+        // time of the call may be used as parameters by the called expression
+        // and values left on the stack by the called expression may be used as
+        // return values by prior agreement between the calling and called
+        // expressions.
+        //----------------------------------------------------------------------
+        case DW_OP_call2:
+            if (error_ptr)
+                error_ptr->SetErrorString ("Unimplemented opcode DW_OP_call2.");
+            return false;
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_call4
+        // OPERANDS: 1
+        //      uint32_t compile unit relative offset of a DIE
+        // DESCRIPTION: Performs a subroutine call during evaluation of a DWARF
+        // expression. For DW_OP_call4, the operand is a 4-byte unsigned offset
+        // of a debugging information entry in  the current compilation unit.
+        //
+        // Operand interpretation DW_OP_call4 is exactly like that for
+        // DW_FORM_ref4.
+        //
+        // This operation transfers control of DWARF expression evaluation
+        // to the DW_AT_location attribute of the referenced DIE. If there is
+        // no such attribute, then there is no effect. Execution of the DWARF
+        // expression of a DW_AT_location attribute may add to and/or remove from
+        // values on the stack. Execution returns to the point following the call
+        // when the end of the attribute is reached. Values on the stack at the
+        // time of the call may be used as parameters by the called expression
+        // and values left on the stack by the called expression may be used as
+        // return values by prior agreement between the calling and called
+        // expressions.
+        //----------------------------------------------------------------------
+        case DW_OP_call4:
+            if (error_ptr)
+                error_ptr->SetErrorString ("Unimplemented opcode DW_OP_call4.");
+            return false;
+
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_call_ref
+        // OPERANDS:
+        //      uint32_t absolute DIE offset for 32-bit DWARF or a uint64_t
+        //               absolute DIE offset for 64 bit DWARF.
+        // DESCRIPTION: Performs a subroutine call during evaluation of a DWARF
+        // expression. Takes a single operand. In the 32-bit DWARF format, the
+        // operand is a 4-byte unsigned value; in the 64-bit DWARF format, it
+        // is an 8-byte unsigned value. The operand is used as the offset of a
+        // debugging information entry in a .debug_info section which may be
+        // contained in a shared object for executable other than that
+        // containing the operator. For references from one shared object or
+        // executable to another, the relocation must be performed by the
+        // consumer.
+        //
+        // Operand interpretation of DW_OP_call_ref is exactly like that for
+        // DW_FORM_ref_addr.
+        //
+        // This operation transfers control of DWARF expression evaluation
+        // to the DW_AT_location attribute of the referenced DIE. If there is
+        // no such attribute, then there is no effect. Execution of the DWARF
+        // expression of a DW_AT_location attribute may add to and/or remove from
+        // values on the stack. Execution returns to the point following the call
+        // when the end of the attribute is reached. Values on the stack at the
+        // time of the call may be used as parameters by the called expression
+        // and values left on the stack by the called expression may be used as
+        // return values by prior agreement between the calling and called
+        // expressions.
+        //----------------------------------------------------------------------
+        case DW_OP_call_ref:
+            if (error_ptr)
+                error_ptr->SetErrorString ("Unimplemented opcode DW_OP_call_ref.");
+            return false;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_APPLE_array_ref
+        // OPERANDS: none
+        // DESCRIPTION: Pops a value off the stack and uses it as the array 
+        // index.  Pops a second value off the stack and uses it as the array
+        // itself.  Pushes a value onto the stack representing the element of
+        // the array specified by the index.
+        //----------------------------------------------------------------------
+        case DW_OP_APPLE_array_ref:
+            {
+                if (stack.size() < 2)
+                {
+                    if (error_ptr)
+                        error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_APPLE_array_ref.");
+                    return false;
+                }
+                
+                Value index_val = stack.back();
+                stack.pop_back();
+                Value array_val = stack.back();
+                stack.pop_back();
+                
+                Scalar &index_scalar = index_val.ResolveValue(exe_ctx, ast_context);
+                int64_t index = index_scalar.SLongLong(LONG_LONG_MAX);
+                
+                if (index == LONG_LONG_MAX)
+                {
+                    if (error_ptr)
+                        error_ptr->SetErrorString("Invalid array index.");
+                    return false;
+                }
+            
+                if (array_val.GetContextType() != Value::eContextTypeOpaqueClangQualType)
+                {
+                    if (error_ptr)
+                        error_ptr->SetErrorString("Arrays without Clang types are unhandled at this time.");
+                    return false;
+                }
+                
+                if (array_val.GetValueType() != Value::eValueTypeLoadAddress &&
+                    array_val.GetValueType() != Value::eValueTypeHostAddress)
+                {
+                    if (error_ptr)
+                        error_ptr->SetErrorString("Array must be stored in memory.");
+                    return false;
+                }
+                
+                void *array_type = array_val.GetOpaqueClangQualType();
+                
+                void *member_type;
+                uint64_t size = 0;
+                
+                if ((!ClangASTContext::IsPointerType(array_type, &member_type)) &&
+                    (!ClangASTContext::IsArrayType(array_type, &member_type, &size)))
+                {
+                    if (error_ptr)
+                        error_ptr->SetErrorString("Array reference from something that is neither a pointer nor an array.");
+                    return false;
+                }
+                
+                if (size && (index >= size || index < 0))
+                {
+                    if (error_ptr)
+                        error_ptr->SetErrorStringWithFormat("Out of bounds array access.  %lld is not in [0, %llu]", index, size);
+                    return false;
+                }
+                
+                uint64_t member_bit_size = ClangASTContext::GetTypeBitSize(ast_context, member_type);
+                uint64_t member_bit_align = ClangASTContext::GetTypeBitAlign(ast_context, member_type);
+                uint64_t member_bit_incr = ((member_bit_size + member_bit_align - 1) / member_bit_align) * member_bit_align;
+                if (member_bit_incr % 8)
+                {
+                    if (error_ptr)
+                        error_ptr->SetErrorStringWithFormat("Array increment is not byte aligned", index, size);
+                    return false;
+                }
+                int64_t member_offset = (int64_t)(member_bit_incr / 8) * index;
+                
+                Value member;
+                
+                member.SetContext(Value::eContextTypeOpaqueClangQualType, member_type);
+                member.SetValueType(array_val.GetValueType());
+                
+                addr_t array_base = (addr_t)array_val.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
+                addr_t member_loc = array_base + member_offset;
+                member.GetScalar() = (uint64_t)member_loc;
+                
+                stack.push_back(member);
+            }
+            break;
+                
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_APPLE_uninit
+        // OPERANDS: none
+        // DESCRIPTION: Lets us know that the value is currently not initialized
+        //----------------------------------------------------------------------
+        case DW_OP_APPLE_uninit:
+            //return eResultTypeErrorUninitialized;
+            break;  // Ignore this as we have seen cases where this value is incorrectly added
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_APPLE_assign
+        // OPERANDS: none
+        // DESCRIPTION: Pops a value off of the stack and assigns it to the next
+        // item on the stack which must be something assignable (inferior
+        // Variable, inferior Type with address, inferior register, or
+        // expression local variable.
+        //----------------------------------------------------------------------
+        case DW_OP_APPLE_assign:
+            if (stack.size() < 2)
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_APPLE_assign.");
+                return false;
+            }
+            else
+            {
+                tmp = stack.back();
+                stack.pop_back();
+                Value::ContextType context_type = stack.back().GetContextType();
+                StreamString new_value(Stream::eBinary, 4, eByteOrderHost);
+                switch (context_type)
+                {
+                case Value::eContextTypeOpaqueClangQualType:
+                    {
+                        void *clang_type = stack.back().GetOpaqueClangQualType();
+                        
+                        if (ClangASTContext::IsAggregateType (clang_type))
+                        {
+                            Value::ValueType source_value_type = tmp.GetValueType();
+                            Value::ValueType target_value_type = stack.back().GetValueType();
+                            
+                            addr_t source_addr = (addr_t)tmp.GetScalar().ULongLong();
+                            addr_t target_addr = (addr_t)stack.back().GetScalar().ULongLong();
+                            
+                            size_t byte_size = (ClangASTContext::GetTypeBitSize(ast_context, clang_type) + 7) / 8;
+                            
+                            switch (source_value_type)
+                            {
+                            case Value::eValueTypeLoadAddress:
+                                switch (target_value_type)
+                                {
+                                case Value::eValueTypeLoadAddress:
+                                    {
+                                        DataBufferHeap data;
+                                        data.SetByteSize(byte_size);
+                                        
+                                        Error error;
+                                        if (exe_ctx->process->ReadMemory (source_addr, data.GetBytes(), byte_size, error) != byte_size)
+                                        {
+                                            if (error_ptr)
+                                                error_ptr->SetErrorStringWithFormat ("Couldn't read a composite type from the target: %s", error.AsCString());
+                                            return false;
+                                        }
+                                        
+                                        if (exe_ctx->process->WriteMemory (target_addr, data.GetBytes(), byte_size, error) != byte_size)
+                                        {
+                                            if (error_ptr)
+                                                error_ptr->SetErrorStringWithFormat ("Couldn't write a composite type to the target: %s", error.AsCString());
+                                            return false;
+                                        }
+                                    }
+                                    break;
+                                case Value::eValueTypeHostAddress:
+                                    if (exe_ctx->process->GetByteOrder() != Host::GetByteOrder())
+                                    {
+                                        if (error_ptr)
+                                            error_ptr->SetErrorStringWithFormat ("Copy of composite types between incompatible byte orders is unimplemented");
+                                        return false;
+                                    }
+                                    else
+                                    {
+                                        Error error;
+                                        if (exe_ctx->process->ReadMemory (source_addr, (uint8_t*)target_addr, byte_size, error) != byte_size)
+                                        {
+                                            if (error_ptr)
+                                                error_ptr->SetErrorStringWithFormat ("Couldn't read a composite type from the target: %s", error.AsCString());
+                                            return false;
+                                        }
+                                    }
+                                    break;
+                                default:
+                                    return false;
+                                }
+                                break;
+                            case Value::eValueTypeHostAddress:
+                                switch (target_value_type)
+                                {
+                                case Value::eValueTypeLoadAddress:
+                                    if (exe_ctx->process->GetByteOrder() != Host::GetByteOrder())
+                                    {
+                                        if (error_ptr)
+                                            error_ptr->SetErrorStringWithFormat ("Copy of composite types between incompatible byte orders is unimplemented");
+                                        return false;
+                                    }
+                                    else
+                                    {
+                                        Error error;
+                                        if (exe_ctx->process->WriteMemory (target_addr, (uint8_t*)source_addr, byte_size, error) != byte_size)
+                                        {
+                                            if (error_ptr)
+                                                error_ptr->SetErrorStringWithFormat ("Couldn't write a composite type to the target: %s", error.AsCString());
+                                            return false;
+                                        }
+                                    }
+                                case Value::eValueTypeHostAddress:
+                                    memcpy ((uint8_t*)target_addr, (uint8_t*)source_addr, byte_size);
+                                    break;
+                                default:
+                                    return false;
+                                }
+                            }
+                        }
+                        else
+                        {
+                            if (!Type::SetValueFromScalar(ast_context,
+                                                          clang_type,
+                                                          tmp.ResolveValue(exe_ctx, ast_context),
+                                                          new_value))
+                            {
+                                if (error_ptr)
+                                    error_ptr->SetErrorStringWithFormat ("Couldn't extract a value from an integral type.\n");
+                                return false;
+                            }
+                                
+                            Value::ValueType value_type = stack.back().GetValueType();
+                            
+                            switch (value_type)
+                            {
+                            case Value::eValueTypeLoadAddress:
+                            case Value::eValueTypeHostAddress:
+                                {
+                                    lldb::AddressType address_type = (value_type == Value::eValueTypeLoadAddress ? eAddressTypeLoad : eAddressTypeHost);
+                                    lldb::addr_t addr = stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
+                                    if (!Type::WriteToMemory (exe_ctx,
+                                                                ast_context,
+                                                                clang_type,
+                                                                addr,
+                                                                address_type,
+                                                                new_value))
+                                    {
+                                        if (error_ptr)
+                                            error_ptr->SetErrorStringWithFormat ("Failed to write value to memory at 0x%llx.\n", addr);
+                                        return false;
+                                    }
+                                }
+                                break;
+
+                            default:
+                                break;
+                            }
+                        }
+                    }
+                    break;
+
+                default:
+                    if (error_ptr)
+                        error_ptr->SetErrorString ("Assign failed.");
+                    return false;
+                }
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_APPLE_address_of
+        // OPERANDS: none
+        // DESCRIPTION: Pops a value off of the stack and pushed its address.
+        // The top item on the stack must be a variable, or already be a memory
+        // location.
+        //----------------------------------------------------------------------
+        case DW_OP_APPLE_address_of:
+            if (stack.empty())
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 1 item for DW_OP_APPLE_address_of.");
+                return false;
+            }
+            else
+            {
+                Value::ValueType value_type = stack.back().GetValueType();
+                switch (value_type)
+                {
+                default:
+                case Value::eValueTypeScalar:      // raw scalar value
+                    if (error_ptr)
+                        error_ptr->SetErrorString("Top stack item isn't a memory based object.");
+                    return false;
+
+                case Value::eValueTypeLoadAddress: // load address value
+                case Value::eValueTypeFileAddress: // file address value
+                case Value::eValueTypeHostAddress: // host address value (for memory in the process that is using liblldb)
+                    // Taking the address of an object reduces it to the address
+                    // of the value and removes any extra context it had.
+                    //stack.back().SetValueType(Value::eValueTypeScalar);
+                    stack.back().ClearContext();
+                    break;
+                }
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_APPLE_value_of
+        // OPERANDS: none
+        // DESCRIPTION: Pops a value off of the stack and pushed its value.
+        // The top item on the stack must be a variable, expression variable.
+        //----------------------------------------------------------------------
+        case DW_OP_APPLE_value_of:
+            if (stack.empty())
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 1 items for DW_OP_APPLE_value_of.");
+                return false;
+            }
+            else if (!stack.back().ValueOf(exe_ctx, ast_context))
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString ("Top stack item isn't a valid candidate for DW_OP_APPLE_value_of.");
+                return false;
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_APPLE_deref_type
+        // OPERANDS: none
+        // DESCRIPTION: gets the value pointed to by the top stack item
+        //----------------------------------------------------------------------
+        case DW_OP_APPLE_deref_type:
+            {
+                if (stack.empty())
+                {
+                    if (error_ptr)
+                        error_ptr->SetErrorString("Expression stack needs at least 1 items for DW_OP_APPLE_deref_type.");
+                    return false;
+                }
+                    
+                tmp = stack.back();
+                stack.pop_back();
+                
+                if (tmp.GetContextType() != Value::eContextTypeOpaqueClangQualType)
+                {
+                    if (error_ptr)
+                        error_ptr->SetErrorString("Item at top of expression stack must have a Clang type");
+                    return false;
+                }
+                    
+                void *ptr_type = tmp.GetOpaqueClangQualType();
+                void *target_type;
+            
+                if (!ClangASTContext::IsPointerType(ptr_type, &target_type))
+                {
+                    if (error_ptr)
+                        error_ptr->SetErrorString("Dereferencing a non-pointer type");
+                    return false;
+                }
+                
+                // TODO do we want all pointers to be dereferenced as load addresses?
+                Value::ValueType value_type = tmp.GetValueType();
+                
+                tmp.ResolveValue(exe_ctx, ast_context);
+                
+                tmp.SetValueType(value_type);
+                tmp.SetContext(Value::eContextTypeOpaqueClangQualType, target_type);
+                
+                stack.push_back(tmp);
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_APPLE_expr_local
+        // OPERANDS: ULEB128
+        // DESCRIPTION: pushes the expression local variable index onto the
+        // stack and set the appropriate context so we know the stack item is
+        // an expression local variable index.
+        //----------------------------------------------------------------------
+        case DW_OP_APPLE_expr_local:
+            {
+                uint32_t idx = opcodes.GetULEB128(&offset);
+                if (expr_locals == NULL)
+                {
+                    if (error_ptr)
+                        error_ptr->SetErrorStringWithFormat ("DW_OP_APPLE_expr_local(%u) opcode encountered with no local variable list.\n", idx);
+                    return false;
+                }
+                Value *expr_local_variable = expr_locals->GetVariableAtIndex(idx);
+                if (expr_local_variable == NULL)
+                {
+                    if (error_ptr)
+                        error_ptr->SetErrorStringWithFormat ("DW_OP_APPLE_expr_local(%u) with invalid index %u.\n", idx, idx);
+                    return false;
+                }
+                Value *proxy = expr_local_variable->CreateProxy();
+                stack.push_back(*proxy);
+                delete proxy;
+                //stack.back().SetContext (Value::eContextTypeOpaqueClangQualType, expr_local_variable->GetOpaqueClangQualType());
+            }
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_APPLE_extern
+        // OPERANDS: ULEB128
+        // DESCRIPTION: pushes a proxy for the extern object index onto the
+        // stack.
+        //----------------------------------------------------------------------
+        case DW_OP_APPLE_extern:
+            {
+                uint32_t idx = opcodes.GetULEB128(&offset);
+                if (!decl_map)
+                {
+                    if (error_ptr)
+                        error_ptr->SetErrorStringWithFormat ("DW_OP_APPLE_extern(%u) opcode encountered with no decl map.\n", idx);
+                    return false;
+                }
+                Value *extern_var = decl_map->GetValueForIndex(idx);
+                if (!extern_var)
+                {
+                    if (error_ptr)
+                        error_ptr->SetErrorStringWithFormat ("DW_OP_APPLE_extern(%u) with invalid index %u.\n", idx, idx);
+                    return false;
+                }
+                Value *proxy = extern_var->CreateProxy();
+                stack.push_back(*proxy);
+                delete proxy;
+            }
+            break;
+
+        case DW_OP_APPLE_scalar_cast:
+            if (stack.empty())
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 1 item for DW_OP_APPLE_scalar_cast.");
+                return false;
+            }
+            else
+            {
+                // Simple scalar cast
+                if (!stack.back().ResolveValue(exe_ctx, ast_context).Cast((Scalar::Type)opcodes.GetU8(&offset)))
+                {
+                    if (error_ptr)
+                        error_ptr->SetErrorString("Cast failed.");
+                    return false;
+                }
+            }
+            break;
+
+
+        case DW_OP_APPLE_clang_cast:
+            if (stack.empty())
+            {
+                if (error_ptr)
+                    error_ptr->SetErrorString("Expression stack needs at least 1 item for DW_OP_APPLE_clang_cast.");
+                return false;
+            }
+            else
+            {
+                void *clang_type = (void *)opcodes.GetMaxU64(&offset, sizeof(void*));
+                stack.back().SetContext (Value::eContextTypeOpaqueClangQualType, clang_type);
+            }
+            break;
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_APPLE_constf
+        // OPERANDS: 1 byte float length, followed by that many bytes containing
+        // the constant float data.
+        // DESCRIPTION: Push a float value onto the expression stack.
+        //----------------------------------------------------------------------
+        case DW_OP_APPLE_constf:        // 0xF6 - 1 byte float size, followed by constant float data
+            {
+                uint8_t float_length = opcodes.GetU8(&offset);
+                if (sizeof(float) == float_length)
+                    tmp.ResolveValue(exe_ctx, ast_context) = opcodes.GetFloat (&offset);
+                else if (sizeof(double) == float_length)
+                    tmp.ResolveValue(exe_ctx, ast_context) = opcodes.GetDouble (&offset);
+                else if (sizeof(long double) == float_length)
+                    tmp.ResolveValue(exe_ctx, ast_context) = opcodes.GetLongDouble (&offset);
+                else
+                {
+                    StreamString new_value;
+                    opcodes.Dump(&new_value, offset, eFormatBytes, 1, float_length, UINT32_MAX, DW_INVALID_ADDRESS, 0, 0);
+
+                     if (error_ptr)
+                        error_ptr->SetErrorStringWithFormat ("DW_OP_APPLE_constf(<%u> %s) unsupported float size.\n", float_length, new_value.GetData());
+                    return false;
+               }
+               tmp.SetValueType(Value::eValueTypeScalar);
+               tmp.ClearContext();
+               stack.push_back(tmp);
+            }
+            break;
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_APPLE_clear
+        // OPERANDS: none
+        // DESCRIPTION: Clears the expression stack.
+        //----------------------------------------------------------------------
+        case DW_OP_APPLE_clear:
+            stack.clear();
+            break;
+
+        //----------------------------------------------------------------------
+        // OPCODE: DW_OP_APPLE_error
+        // OPERANDS: none
+        // DESCRIPTION: Pops a value off of the stack and pushed its value.
+        // The top item on the stack must be a variable, expression variable.
+        //----------------------------------------------------------------------
+        case DW_OP_APPLE_error:         // 0xFF - Stops expression evaluation and returns an error (no args)
+            if (error_ptr)
+                error_ptr->SetErrorString ("Generic error.");
+            return false;
+        }
+    }
+
+    if (stack.empty())
+    {
+        if (error_ptr)
+            error_ptr->SetErrorString ("Stack empty after evaluation.");
+        return false;
+    }
+    else if (log)
+    {
+        log->Printf("\n");
+        size_t count = stack.size();
+        for (size_t i=0; i<count; ++i)
+        {
+            StreamString new_value;
+            new_value.Printf("[%zu]", i);
+            stack[i].Dump(&new_value);
+            log->Printf("%s", new_value.GetData());
+        }
+    }
+
+    result = stack.back();
+    return true;    // Return true on success
+}
+
diff --git a/source/Expression/RecordingMemoryManager.cpp b/source/Expression/RecordingMemoryManager.cpp
new file mode 100644
index 0000000..9f732b6
--- /dev/null
+++ b/source/Expression/RecordingMemoryManager.cpp
@@ -0,0 +1,131 @@
+//===-- RecordingMemoryManager.cpp ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#define NO_RTTI
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Expression/RecordingMemoryManager.h"
+
+using namespace lldb_private;
+
+RecordingMemoryManager::RecordingMemoryManager () :
+    llvm::JITMemoryManager(),
+    m_default_mm_ap (llvm::JITMemoryManager::CreateDefaultMemManager())
+{
+}
+
+RecordingMemoryManager::~RecordingMemoryManager ()
+{
+}
+
+void
+RecordingMemoryManager::setMemoryWritable ()
+{
+    m_default_mm_ap->setMemoryWritable();
+}
+
+void
+RecordingMemoryManager::setMemoryExecutable ()
+{
+    m_default_mm_ap->setMemoryExecutable();
+}
+
+
+uint8_t *
+RecordingMemoryManager::startFunctionBody(const llvm::Function *F,
+                     uintptr_t &ActualSize)
+{
+    uint8_t *return_value = m_default_mm_ap->startFunctionBody(F, ActualSize);
+    return return_value;
+}
+
+uint8_t *
+RecordingMemoryManager::allocateStub(const llvm::GlobalValue* F, unsigned StubSize,
+                unsigned Alignment)
+{
+    uint8_t *return_value = m_default_mm_ap->allocateStub(F, StubSize, Alignment);
+    m_stubs.insert (std::pair<uint8_t *,unsigned>(return_value, StubSize));
+    return return_value;
+}
+
+void
+RecordingMemoryManager::endFunctionBody(const llvm::Function *F, uint8_t *FunctionStart,
+               uint8_t *FunctionEnd)
+{
+    m_default_mm_ap->endFunctionBody(F, FunctionStart, FunctionEnd);
+    m_functions.insert(std::pair<uint8_t *, uint8_t *>(FunctionStart, FunctionEnd));
+}
+
+uint8_t *
+RecordingMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment)
+{
+    uint8_t *return_value = m_default_mm_ap->allocateSpace(Size, Alignment);
+    m_spaceBlocks.insert (std::pair<uint8_t *, intptr_t>(return_value, Size));
+    return return_value;
+}
+
+uint8_t *
+RecordingMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment)
+{
+    uint8_t *return_value = m_default_mm_ap->allocateGlobal(Size, Alignment);
+    m_globals.insert (std::pair<uint8_t *, uintptr_t>(return_value, Size));
+    return return_value;
+}
+
+void
+RecordingMemoryManager::deallocateFunctionBody(void *Body)
+{
+    m_default_mm_ap->deallocateFunctionBody(Body);
+}
+
+uint8_t*
+RecordingMemoryManager::startExceptionTable(const llvm::Function* F,
+                       uintptr_t &ActualSize)
+{
+    uint8_t *return_value = m_default_mm_ap->startExceptionTable(F, ActualSize);
+    return return_value;
+}
+
+void
+RecordingMemoryManager::endExceptionTable(const llvm::Function *F, uint8_t *TableStart,
+                 uint8_t *TableEnd, uint8_t* FrameRegister)
+{
+    m_default_mm_ap->endExceptionTable(F, TableStart, TableEnd, FrameRegister);
+    m_exception_tables.insert (std::pair<uint8_t *, uint8_t *>(TableStart, TableEnd));
+}
+
+void
+RecordingMemoryManager::deallocateExceptionTable(void *ET)
+{
+    m_default_mm_ap->deallocateExceptionTable (ET);
+}
+
+lldb::addr_t
+RecordingMemoryManager::GetRemoteAddressForLocal (lldb::addr_t local_address)
+{
+    std::vector<LocalToRemoteAddressRange>::iterator pos, end = m_address_map.end();
+    for (pos = m_address_map.begin(); pos < end; pos++)
+    {
+        lldb::addr_t lstart = (*pos).m_local_start;
+        if (local_address >= lstart && local_address < lstart + (*pos).m_size)
+        {
+            return (*pos).m_remote_start + (local_address - lstart);
+        }
+    }
+    return LLDB_INVALID_ADDRESS;
+}
+
+void
+RecordingMemoryManager::AddToLocalToRemoteMap (lldb::addr_t lstart, size_t size, lldb::addr_t rstart)
+{
+    m_address_map.push_back (LocalToRemoteAddressRange(lstart, size, rstart));
+}
+
diff --git a/source/Host/macosx/Condition.cpp b/source/Host/macosx/Condition.cpp
new file mode 100644
index 0000000..4e93db7
--- /dev/null
+++ b/source/Host/macosx/Condition.cpp
@@ -0,0 +1,106 @@
+//===-- Condition.cpp -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <errno.h>
+
+#include "lldb/Host/Condition.h"
+#include "lldb/Host/TimeValue.h"
+
+
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Default constructor
+//
+// The default constructor will initialize a new pthread condition
+// and maintain the condition in the object state.
+//----------------------------------------------------------------------
+Condition::Condition () :
+    m_condition()
+{
+    ::pthread_cond_init (&m_condition, NULL);
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//
+// Destroys the pthread condition that the object owns.
+//----------------------------------------------------------------------
+Condition::~Condition ()
+{
+    ::pthread_cond_destroy (&m_condition);
+}
+
+//----------------------------------------------------------------------
+// Unblock all threads waiting for a condition variable
+//----------------------------------------------------------------------
+int
+Condition::Broadcast ()
+{
+    return ::pthread_cond_broadcast (&m_condition);
+}
+
+//----------------------------------------------------------------------
+// Get accessor to the pthread condition object
+//----------------------------------------------------------------------
+pthread_cond_t *
+Condition::GetCondition ()
+{
+    return &m_condition;
+}
+
+//----------------------------------------------------------------------
+// Unblocks one thread waiting for the condition variable
+//----------------------------------------------------------------------
+int
+Condition::Signal ()
+{
+    return ::pthread_cond_signal (&m_condition);
+}
+
+//----------------------------------------------------------------------
+// The Wait() function atomically blocks the current thread
+// waiting on the owend condition variable, and unblocks the mutex
+// specified by "mutex".  The waiting thread unblocks only after
+// another thread calls Signal(), or Broadcast() with the same
+// condition variable, or if "abstime" is valid (non-NULL) this
+// function will return when the system time reaches the time
+// specified in "abstime". If "abstime" is NULL this function will
+// wait for an infinite amount of time for the condition variable
+// to be signaled or broadcasted.
+//
+// The current thread re-acquires the lock on "mutex".
+//----------------------------------------------------------------------
+int
+Condition::Wait (pthread_mutex_t *mutex, const TimeValue *abstime, bool *timed_out)
+{
+    int err = 0;
+    do
+    {
+        if (abstime && abstime->IsValid())
+        {
+            struct timespec abstime_ts = abstime->GetAsTimeSpec();
+            err = ::pthread_cond_timedwait (&m_condition, mutex, &abstime_ts);
+        }
+        else
+            err = ::pthread_cond_wait (&m_condition, mutex);
+    } while (err == EINTR);
+
+    if (timed_out != NULL)
+    {
+        if (err == ETIMEDOUT)
+            *timed_out = true;
+        else
+            *timed_out = false;
+    }
+
+
+    return err;
+}
+
diff --git a/source/Host/macosx/Host.mm b/source/Host/macosx/Host.mm
new file mode 100644
index 0000000..a18d45e
--- /dev/null
+++ b/source/Host/macosx/Host.mm
@@ -0,0 +1,803 @@
+//===-- Host.mm -------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <dlfcn.h>
+#include <libgen.h>
+#include <mach/mach.h>
+#include <mach-o/dyld.h>
+#include <signal.h>
+#include <stddef.h>
+#include <sys/sysctl.h>
+#include <unistd.h>
+
+#include <map>
+#include <string>
+
+#include <objc/objc-auto.h>
+
+#include <Foundation/Foundation.h>
+
+#include "CFCBundle.h"
+#include "CFCReleaser.h"
+#include "CFCString.h"
+
+#include "lldb/Host/Host.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/TargetList.h"
+#include "lldb/lldb-private-log.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//------------------------------------------------------------------
+// Return the size in bytes of a page on the host system
+//------------------------------------------------------------------
+size_t
+Host::GetPageSize()
+{
+    return ::getpagesize();
+}
+
+
+//------------------------------------------------------------------
+// Returns true if the host system is Big Endian.
+//------------------------------------------------------------------
+ByteOrder
+Host::GetByteOrder()
+{
+    union EndianTest
+    {
+        uint32_t num;
+        uint8_t  bytes[sizeof(uint32_t)];
+    } endian = { (uint16_t)0x11223344 };
+    switch (endian.bytes[0])
+    {
+    case 0x11: return eByteOrderLittle;
+    case 0x44: return eByteOrderBig;
+    case 0x33: return eByteOrderPDP;
+    }
+    return eByteOrderInvalid;
+}
+
+lldb::pid_t
+Host::GetCurrentProcessID()
+{
+    return ::getpid();
+}
+
+lldb::pid_t
+Host::GetCurrentThreadID()
+{
+    return ::mach_thread_self();
+}
+
+
+const ArchSpec &
+Host::GetArchitecture ()
+{
+    static ArchSpec g_host_arch;
+    if (!g_host_arch.IsValid())
+    {
+        uint32_t cputype, cpusubtype;
+        uint32_t is_64_bit_capable;
+        size_t len = sizeof(cputype);
+        if  (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0)
+        {
+            len = sizeof(cpusubtype);
+            if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
+                g_host_arch.SetArch(cputype, cpusubtype);
+            
+            len = sizeof (is_64_bit_capable);
+            if  (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0)
+            {
+                if (is_64_bit_capable)
+                {
+                    if (cputype == CPU_TYPE_I386 && cpusubtype == CPU_SUBTYPE_486)
+                        cpusubtype = CPU_SUBTYPE_I386_ALL;
+
+                    cputype |= CPU_ARCH_ABI64;
+                }
+            }
+        }
+    }
+    return g_host_arch;
+}
+
+const ConstString &
+Host::GetVendorString()
+{
+    static ConstString g_vendor;
+    if (!g_vendor)
+    {
+        char ostype[64];
+        size_t len = sizeof(ostype);
+        if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0)
+            g_vendor.SetCString (ostype);
+    }
+    return g_vendor;
+}
+
+const ConstString &
+Host::GetOSString()
+{
+    static ConstString g_os_string("apple");
+    return g_os_string;
+}
+
+const ConstString &
+Host::GetTargetTriple()
+{
+    static ConstString g_host_triple;
+    if (!(g_host_triple))
+    {
+        StreamString triple;
+        triple.Printf("%s-%s-%s", 
+                      GetArchitecture ().AsCString(),
+                      GetVendorString().AsCString("apple"),
+                      GetOSString().AsCString("darwin"));
+
+        std::transform (triple.GetString().begin(), 
+                        triple.GetString().end(), 
+                        triple.GetString().begin(), 
+                        ::tolower);
+
+        g_host_triple.SetCString(triple.GetString().c_str());
+    }
+    return g_host_triple;
+}
+
+class MacOSXDarwinThread
+{
+public:
+    MacOSXDarwinThread(const char *thread_name) :
+        m_pool (nil)
+    {
+        // Register our thread with the collector if garbage collection is enabled.
+        if (objc_collectingEnabled())
+        {
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
+            // On Leopard and earlier there is no way objc_registerThreadWithCollector
+            // function, so we do it manually.
+            auto_zone_register_thread(auto_zone());
+#else
+            // On SnowLoepard and later we just call the thread registration function.
+            objc_registerThreadWithCollector();
+#endif
+        }
+        else
+        {
+            m_pool = [[NSAutoreleasePool alloc] init];
+        }
+
+
+        Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name);
+    }
+
+    ~MacOSXDarwinThread()
+    {
+        if (m_pool)
+            [m_pool release];
+    }
+
+    static void PThreadDestructor (void *v)
+    {
+        delete (MacOSXDarwinThread*)v;
+    }
+
+protected:
+    NSAutoreleasePool * m_pool;
+private:
+    DISALLOW_COPY_AND_ASSIGN (MacOSXDarwinThread);
+};
+
+static pthread_once_t g_thread_create_once = PTHREAD_ONCE_INIT;
+static pthread_key_t g_thread_create_key = 0;
+
+static void
+InitThreadCreated()
+{
+    ::pthread_key_create (&g_thread_create_key, MacOSXDarwinThread::PThreadDestructor);
+}
+
+typedef struct HostThreadCreateInfo
+{
+    std::string thread_name;
+    thread_func_t thread_fptr;
+    thread_arg_t thread_arg;
+
+    HostThreadCreateInfo (const char *name, thread_func_t fptr, thread_arg_t arg) :
+        thread_name (name ? name : ""),
+        thread_fptr (fptr),
+        thread_arg (arg)
+    {
+    }
+};
+
+static thread_result_t
+ThreadCreateTrampoline (thread_arg_t arg)
+{
+    HostThreadCreateInfo *info = (HostThreadCreateInfo *)arg;
+    Host::ThreadCreated (info->thread_name.c_str());
+    thread_func_t thread_fptr = info->thread_fptr;
+    thread_arg_t thread_arg = info->thread_arg;
+
+    Log * log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD);
+    if (log)
+        log->Printf("thread created");
+
+    delete info;
+    return thread_fptr (thread_arg);
+}
+
+lldb::thread_t
+Host::ThreadCreate
+(
+    const char *thread_name,
+    thread_func_t thread_fptr,
+    thread_arg_t thread_arg,
+    Error *error
+)
+{
+    lldb::thread_t thread = LLDB_INVALID_HOST_THREAD;
+
+    // Host::ThreadCreateTrampoline will delete this pointer for us.
+    HostThreadCreateInfo *info_ptr = new HostThreadCreateInfo (thread_name, thread_fptr, thread_arg);
+
+    int err = ::pthread_create (&thread, NULL, ThreadCreateTrampoline, info_ptr);
+    if (err == 0)
+    {
+        if (error)
+            error->Clear();
+        return thread;
+    }
+
+    if (error)
+        error->SetError (err, eErrorTypePOSIX);
+
+    return LLDB_INVALID_HOST_THREAD;
+}
+
+bool
+Host::ThreadCancel (lldb::thread_t thread, Error *error)
+{
+
+    int err = ::pthread_cancel (thread);
+    if (error)
+        error->SetError(err, eErrorTypePOSIX);
+    return err == 0;
+}
+
+bool
+Host::ThreadDetach (lldb::thread_t thread, Error *error)
+{
+    int err = ::pthread_detach (thread);
+    if (error)
+        error->SetError(err, eErrorTypePOSIX);
+    return err == 0;
+}
+
+bool
+Host::ThreadJoin (lldb::thread_t thread, thread_result_t *thread_result_ptr, Error *error)
+{
+    int err = ::pthread_join (thread, thread_result_ptr);
+    if (error)
+        error->SetError(err, eErrorTypePOSIX);
+    return err == 0;
+}
+
+void
+Host::ThreadCreated (const char *thread_name)
+{
+    ::pthread_once (&g_thread_create_once, InitThreadCreated);
+    if (g_thread_create_key)
+    {
+        ::pthread_setspecific (g_thread_create_key, new MacOSXDarwinThread(thread_name));
+    }
+}
+
+//------------------------------------------------------------------
+// Control access to a static file thread name map using a single
+// static function to avoid a static constructor.
+//------------------------------------------------------------------
+static const char *
+ThreadNameAccessor (bool get, lldb::pid_t pid, lldb::tid_t tid, const char *name)
+{
+
+    uint64_t pid_tid = ((uint64_t)pid << 32) | (uint64_t)tid;
+
+    static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
+    Mutex::Locker locker(&g_mutex);
+
+    typedef std::map<uint64_t, std::string> thread_name_map;
+    static thread_name_map g_thread_names;
+
+    if (get)
+    {
+        // See if the thread name exists in our thread name pool
+        thread_name_map::iterator pos = g_thread_names.find(pid_tid);
+        if (pos != g_thread_names.end())
+            return pos->second.c_str();
+    }
+    else
+    {
+        // Set the thread name
+        g_thread_names[pid_tid] = name;
+    }
+    return NULL;
+}
+
+
+
+const char *
+Host::GetSignalAsCString (int signo)
+{
+    switch (signo)
+    {
+    case SIGHUP:    return "SIGHUP";    // 1    hangup
+    case SIGINT:    return "SIGINT";    // 2    interrupt
+    case SIGQUIT:   return "SIGQUIT";   // 3    quit
+    case SIGILL:    return "SIGILL";    // 4    illegal instruction (not reset when caught)
+    case SIGTRAP:   return "SIGTRAP";   // 5    trace trap (not reset when caught)
+    case SIGABRT:   return "SIGABRT";   // 6    abort()
+#if  defined(_POSIX_C_SOURCE)
+    case SIGPOLL:   return "SIGPOLL";   // 7    pollable event ([XSR] generated, not supported)
+#else    // !_POSIX_C_SOURCE
+    case SIGEMT:    return "SIGEMT";    // 7    EMT instruction
+#endif    // !_POSIX_C_SOURCE
+    case SIGFPE:    return "SIGFPE";    // 8    floating point exception
+    case SIGKILL:   return "SIGKILL";   // 9    kill (cannot be caught or ignored)
+    case SIGBUS:    return "SIGBUS";    // 10    bus error
+    case SIGSEGV:   return "SIGSEGV";   // 11    segmentation violation
+    case SIGSYS:    return "SIGSYS";    // 12    bad argument to system call
+    case SIGPIPE:   return "SIGPIPE";   // 13    write on a pipe with no one to read it
+    case SIGALRM:   return "SIGALRM";   // 14    alarm clock
+    case SIGTERM:   return "SIGTERM";   // 15    software termination signal from kill
+    case SIGURG:    return "SIGURG";    // 16    urgent condition on IO channel
+    case SIGSTOP:   return "SIGSTOP";   // 17    sendable stop signal not from tty
+    case SIGTSTP:   return "SIGTSTP";   // 18    stop signal from tty
+    case SIGCONT:   return "SIGCONT";   // 19    continue a stopped process
+    case SIGCHLD:   return "SIGCHLD";   // 20    to parent on child stop or exit
+    case SIGTTIN:   return "SIGTTIN";   // 21    to readers pgrp upon background tty read
+    case SIGTTOU:   return "SIGTTOU";   // 22    like TTIN for output if (tp->t_local&LTOSTOP)
+#if  !defined(_POSIX_C_SOURCE)
+    case SIGIO:     return "SIGIO";     // 23    input/output possible signal
+#endif
+    case SIGXCPU:   return "SIGXCPU";   // 24    exceeded CPU time limit
+    case SIGXFSZ:   return "SIGXFSZ";   // 25    exceeded file size limit
+    case SIGVTALRM: return "SIGVTALRM"; // 26    virtual time alarm
+    case SIGPROF:   return "SIGPROF";   // 27    profiling time alarm
+#if  !defined(_POSIX_C_SOURCE)
+    case SIGWINCH:  return "SIGWINCH";  // 28    window size changes
+    case SIGINFO:   return "SIGINFO";   // 29    information request
+#endif
+    case SIGUSR1:   return "SIGUSR1";   // 30    user defined signal 1
+    case SIGUSR2:   return "SIGUSR2";   // 31    user defined signal 2
+    default:
+        break;
+    }
+    return NULL;
+}
+
+const char *
+Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid)
+{
+    const char *name = ThreadNameAccessor (true, pid, tid, NULL);
+    if (name == NULL)
+    {
+        // We currently can only get the name of a thread in the current process.
+#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
+        if (pid == Host::GetCurrentProcessID())
+        {
+            char pthread_name[1024];
+            if (::pthread_getname_np (::pthread_from_mach_thread_np (tid), pthread_name, sizeof(pthread_name)) == 0)
+            {
+                if (pthread_name[0])
+                {
+                    // Set the thread in our string pool
+                    ThreadNameAccessor (false, pid, tid, pthread_name);
+                    // Get our copy of the thread name string
+                    name = ThreadNameAccessor (true, pid, tid, NULL);
+                }
+            }
+        }
+#endif
+    }
+    return name;
+}
+
+void
+Host::SetThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name)
+{
+    lldb::pid_t curr_pid = Host::GetCurrentProcessID();
+    lldb::tid_t curr_tid = Host::GetCurrentThreadID();
+    if (pid == LLDB_INVALID_PROCESS_ID)
+        pid = curr_pid;
+
+    if (tid == LLDB_INVALID_THREAD_ID)
+        tid = curr_tid;
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
+    // Set the pthread name if possible
+    if (pid == curr_pid && tid == curr_tid)
+    {
+        ::pthread_setname_np (name) == 0;
+    }
+#endif
+    ThreadNameAccessor (false, pid, tid, name);
+}
+
+FileSpec
+Host::GetProgramFileSpec ()
+{
+    static FileSpec g_program_filepsec;
+    if (!g_program_filepsec)
+    {
+        std::string program_fullpath;
+        program_fullpath.resize (PATH_MAX);
+        // If DST is NULL, then return the number of bytes needed.
+        uint32_t len = program_fullpath.size();
+        int err = _NSGetExecutablePath ((char *)program_fullpath.data(), &len);
+        if (err < 0)
+        {
+            // The path didn't fit in the buffer provided, increase its size
+            // and try again
+            program_fullpath.resize(len);
+            len = program_fullpath.size();
+            err = _NSGetExecutablePath ((char *)program_fullpath.data(), &len);
+        }
+        if (err == 0)
+            g_program_filepsec.SetFile(program_fullpath.data());
+    }
+    return g_program_filepsec;
+}
+
+
+FileSpec
+Host::GetModuleFileSpecForHostAddress (const void *host_addr)
+{
+    FileSpec module_filespec;
+    Dl_info info;
+    if (::dladdr (host_addr, &info))
+    {
+        if (info.dli_fname)
+            module_filespec.SetFile(info.dli_fname);
+    }
+    return module_filespec;
+}
+
+
+bool
+Host::ResolveExecutableInBundle (FileSpec *file)
+{
+    if (file->GetFileType () == FileSpec::eFileTypeDirectory)
+    {
+        char path[PATH_MAX];
+        if (file->GetPath(path, sizeof(path)))
+        {
+            CFCBundle bundle (path);
+            CFCReleaser<CFURLRef> url(bundle.CopyExecutableURL ());
+            if (url.get())
+            {
+                if (::CFURLGetFileSystemRepresentation (url.get(), YES, (UInt8*)path, sizeof(path)))
+                {
+                    file->SetFile(path);
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+typedef struct MonitorInfo
+{
+    int handle;
+    pthread_t thread;
+    Host::MonitorChildProcessCallback callback;
+    void *callback_baton;
+    bool monitor_signals;
+};
+
+typedef std::multimap<lldb::pid_t, MonitorInfo> MonitorInfoMap;
+static pthread_mutex_t g_monitor_map_mutex = PTHREAD_MUTEX_INITIALIZER;
+typedef lldb::SharedPtr<MonitorInfoMap>::Type MonitorInfoMapSP;
+
+static MonitorInfoMapSP&
+GetMonitorMap (bool can_create)
+{
+    static MonitorInfoMapSP g_monitor_map_sp;
+    if (can_create && g_monitor_map_sp.get() == NULL)
+    {
+        g_monitor_map_sp.reset (new MonitorInfoMap);
+    }
+    return g_monitor_map_sp;
+}
+
+static Predicate<bool>&
+GetChildProcessPredicate ()
+{
+    static Predicate<bool> g_has_child_processes;
+    return g_has_child_processes;
+}
+
+static void *
+MonitorChildProcessThreadFunction (void *arg);
+
+static pthread_t g_monitor_thread;
+
+uint32_t
+Host::StartMonitoringChildProcess
+(
+    MonitorChildProcessCallback callback,
+    void *callback_baton,
+    lldb::pid_t pid,
+    bool monitor_signals
+)
+{
+    static uint32_t g_handle = 0;
+    if (callback)
+    {
+        Mutex::Locker locker(&g_monitor_map_mutex);
+        if (!g_monitor_thread)
+        {
+            pid_t wait_pid = -1;
+            g_monitor_thread = ThreadCreate ("<lldb.host.wait4>",
+                                             MonitorChildProcessThreadFunction,
+                                             &wait_pid,
+                                             NULL);
+            if (g_monitor_thread)
+            {
+                //Host::ThreadDetach (g_monitor_thread, NULL);
+            }
+        }
+
+        if (g_monitor_thread)
+        {
+            MonitorInfo info = { ++g_handle, 0, callback, callback_baton, monitor_signals };
+            MonitorInfoMapSP monitor_map_sp (GetMonitorMap (true));
+            if (monitor_map_sp)
+            {
+                monitor_map_sp->insert(std::make_pair(pid, info));
+                GetChildProcessPredicate ().SetValue (true, eBroadcastOnChange);
+                return info.handle;
+            }
+        }
+    }
+    return 0;
+}
+
+bool
+Host::StopMonitoringChildProcess (uint32_t handle)
+{
+    Mutex::Locker locker(&g_monitor_map_mutex);
+    MonitorInfoMapSP monitor_map_sp (GetMonitorMap (false));
+    if (monitor_map_sp)
+    {
+        MonitorInfoMap::iterator pos, end = monitor_map_sp->end();
+        for (pos = monitor_map_sp->end(); pos != end; ++pos)
+        {
+            if (pos->second.handle == handle)
+            {
+                monitor_map_sp->erase(pos);
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+
+//------------------------------------------------------------------
+// Scoped class that will disable thread canceling when it is
+// constructed, and exception safely restore the previous value it
+// when it goes out of scope.
+//------------------------------------------------------------------
+class ScopedPThreadCancelDisabler
+{
+public:
+
+    ScopedPThreadCancelDisabler()
+    {
+        // Disable the ability for this thread to be cancelled
+        int err = ::pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &m_old_state);
+        if (err != 0)
+            m_old_state = -1;
+
+    }
+
+    ~ScopedPThreadCancelDisabler()
+    {
+        // Restore the ability for this thread to be cancelled to what it
+        // previously was.
+        if (m_old_state != -1)
+            ::pthread_setcancelstate (m_old_state, 0);
+    }
+private:
+    int m_old_state;    // Save the old cancelability state.
+};
+
+
+
+static void *
+MonitorChildProcessThreadFunction (void *arg)
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
+    const char *function = __FUNCTION__;
+    if (log)
+        log->Printf ("%s (arg = %p) thread starting...", function, arg);
+
+    const pid_t wait_pid = -1;//*((pid_t*)arg);
+    int status = -1;
+    const int options = 0;
+    struct rusage *rusage = NULL;
+    while (1)
+    {
+        if (log)
+            log->Printf("%s ::wait4 (pid = %i, &status, options = %i, rusage = %p)...", function, wait_pid, options, rusage);
+
+        // Wait for all child processes
+        ::pthread_testcancel ();
+        lldb::pid_t pid = ::wait4 (wait_pid, &status, options, rusage);
+        ::pthread_testcancel ();
+
+        if (pid < 0)
+        {
+            // No child processes to watch wait for the mutex to be cleared
+
+            // Scope for "locker"
+            {
+                ScopedPThreadCancelDisabler pthread_cancel_disabler;
+
+                // First clear out all monitor entries since we have no processes
+                // to watch.
+                Mutex::Locker locker(&g_monitor_map_mutex);
+                // Since we don't have any child processes, we can safely clear
+                // anyone with a valid pid.
+                MonitorInfoMapSP monitor_map_sp(GetMonitorMap (false));
+                if (monitor_map_sp)
+                {
+                    MonitorInfoMap::iterator pos = monitor_map_sp->begin();
+                    while (pos != monitor_map_sp->end())
+                    {
+                        // pid value of 0 and -1 are special (see man page on wait4...)
+                        if (pos->first > 0)
+                        {
+                            MonitorInfoMap::iterator next_pos = pos; ++next_pos;
+                            monitor_map_sp->erase (pos, next_pos);
+                            pos = next_pos;
+                        }
+                        else
+                            ++pos;
+                    }
+                }
+            }
+
+            if (log)
+                log->Printf("%s no child processes, wait for some...", function);
+            GetChildProcessPredicate ().SetValue (false, eBroadcastNever);
+            ::pthread_testcancel();
+            GetChildProcessPredicate ().WaitForValueEqualTo (true);
+            if (log)
+                log->Printf("%s resuming monitoring of child processes.", function);
+
+        }
+        else
+        {
+            ScopedPThreadCancelDisabler pthread_cancel_disabler;
+            bool exited = false;
+            int signal = 0;
+            int exit_status = 0;
+            const char *status_cstr = NULL;
+            if (WIFSTOPPED(status))
+            {
+                signal = WSTOPSIG(status);
+                status_cstr = "STOPPED";
+            }
+            else if (WIFEXITED(status))
+            {
+                exit_status = WEXITSTATUS(status);
+                status_cstr = "EXITED";
+                exited = true;
+            }
+            else if (WIFSIGNALED(status))
+            {
+                signal = WTERMSIG(status);
+                status_cstr = "SIGNALED";
+                exited = true;
+                exit_status = -1;
+            }
+            else
+            {
+                status_cstr = "(???)";
+            }
+
+            if (log)
+                log->Printf ("%s ::wait4 (pid = %i, &status, options = %i, rusage = %p) => pid = %i, status = 0x%8.8x (%s), signal = %i, exit_state = %i",
+                             function,
+                             wait_pid,
+                             options,
+                             rusage,
+                             pid,
+                             status,
+                             status_cstr,
+                             signal,
+                             exit_status);
+
+            // Scope for mutex locker
+            {
+                // Notify anyone listening to this process
+                Mutex::Locker locker(&g_monitor_map_mutex);
+                MonitorInfoMapSP monitor_map_sp(GetMonitorMap (false));
+                if (monitor_map_sp)
+                {
+                    std::pair<MonitorInfoMap::iterator, MonitorInfoMap::iterator> range;
+                    range = monitor_map_sp->equal_range(pid);
+                    MonitorInfoMap::iterator pos;
+                    for (pos = range.first; pos != range.second; ++pos)
+                    {
+                        if (exited || (signal != 0 && pos->second.monitor_signals))
+                        {
+                            bool callback_return = pos->second.callback (pos->second.callback_baton, pid, signal, exit_status);
+
+                            if (exited || callback_return)
+                            {
+                                // Make this entry as needing to be removed by
+                                // setting its handle to zero
+                                pos->second.handle = 0;
+                            }
+                        }
+                    }
+
+                    // Remove any entries that requested to be removed or any
+                    // entries for child processes that did exit. We know this
+                    // because we changed the handles to an invalid value.
+                    pos = monitor_map_sp->begin();
+                    while (pos != monitor_map_sp->end())
+                    {
+                        if (pos->second.handle == 0)
+                        {
+                            MonitorInfoMap::iterator next_pos = pos; ++next_pos;
+                            monitor_map_sp->erase (pos, next_pos);
+                            pos = next_pos;
+                        }
+                        else
+                            ++pos;
+                    }
+                }
+            }
+        }
+    }
+
+    if (log)
+        log->Printf ("ProcessMacOSX::%s (arg = %p) thread exiting...", __FUNCTION__, arg);
+
+    g_monitor_thread = NULL;
+    return NULL;
+}
+
+void
+Host::WillTerminate ()
+{
+    if (g_monitor_thread != NULL)
+    {
+        ThreadCancel (g_monitor_thread, NULL);
+        GetChildProcessPredicate ().SetValue (true, eBroadcastAlways);
+        ThreadJoin(g_monitor_thread, NULL, NULL);
+        g_monitor_thread = NULL;
+    }
+}
+
diff --git a/source/Host/macosx/Mutex.cpp b/source/Host/macosx/Mutex.cpp
new file mode 100644
index 0000000..ab0b67a
--- /dev/null
+++ b/source/Host/macosx/Mutex.cpp
@@ -0,0 +1,244 @@
+//===-- Mutex.cpp -----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/Mutex.h"
+#include "lldb/Core/Log.h"
+
+#if 0
+#include "lldb/Host/Host.h"
+#define DEBUG_LOG(fmt, ...) printf(fmt, ## __VA_ARGS__)
+#else
+#define DEBUG_LOG(fmt, ...)
+#endif
+
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Default constructor.
+//
+// This will create a scoped mutex locking object that doesn't have
+// a mutex to lock. One will need to be provided using the Reset()
+// method.
+//----------------------------------------------------------------------
+Mutex::Locker::Locker () :
+    m_mutex_ptr(NULL)
+{
+}
+
+//----------------------------------------------------------------------
+// Constructor with a Mutex object.
+//
+// This will create a scoped mutex locking object that extracts the
+// mutex owned by "m" and locks it.
+//----------------------------------------------------------------------
+Mutex::Locker::Locker (Mutex& m) :
+    m_mutex_ptr(m.GetMutex())
+{
+    if (m_mutex_ptr)
+        Mutex::Lock (m_mutex_ptr);
+}
+
+//----------------------------------------------------------------------
+// Constructor with a Mutex object pointer.
+//
+// This will create a scoped mutex locking object that extracts the
+// mutex owned by "m" and locks it.
+//----------------------------------------------------------------------
+Mutex::Locker::Locker (Mutex* m) :
+    m_mutex_ptr(m ? m->GetMutex() : NULL)
+{
+    if (m_mutex_ptr)
+        Mutex::Lock (m_mutex_ptr);
+}
+
+//----------------------------------------------------------------------
+// Constructor with a raw pthread mutex object pointer.
+//
+// This will create a scoped mutex locking object that locks "mutex"
+//----------------------------------------------------------------------
+Mutex::Locker::Locker (pthread_mutex_t *mutex_ptr) :
+    m_mutex_ptr(mutex_ptr)
+{
+    if (m_mutex_ptr)
+        Mutex::Lock (m_mutex_ptr);
+}
+
+//----------------------------------------------------------------------
+// Desstructor
+//
+// Unlocks any owned mutex object (if it is valid).
+//----------------------------------------------------------------------
+Mutex::Locker::~Locker ()
+{
+    if (m_mutex_ptr)
+        Mutex::Unlock (m_mutex_ptr);
+}
+
+//----------------------------------------------------------------------
+// Unlock the current mutex in this object (if this owns a valid
+// mutex) and lock the new "mutex" object if it is non-NULL.
+//----------------------------------------------------------------------
+void
+Mutex::Locker::Reset (pthread_mutex_t *mutex_ptr)
+{
+    if (m_mutex_ptr)
+        Mutex::Unlock (m_mutex_ptr);
+
+    m_mutex_ptr = mutex_ptr;
+    if (m_mutex_ptr)
+        Mutex::Lock (m_mutex_ptr);
+}
+
+bool
+Mutex::Locker::TryLock (pthread_mutex_t *mutex_ptr)
+{
+    if (m_mutex_ptr)
+        Mutex::Unlock (m_mutex_ptr);
+    m_mutex_ptr = NULL;
+    if (mutex_ptr)
+    {
+        if (Mutex::TryLock (mutex_ptr) == 0)
+            m_mutex_ptr = mutex_ptr;
+    }
+    return m_mutex_ptr != NULL;
+}
+
+//----------------------------------------------------------------------
+// Default constructor.
+//
+// Creates a pthread mutex with no attributes.
+//----------------------------------------------------------------------
+Mutex::Mutex () :
+    m_mutex()
+{
+    int err;
+    err = ::pthread_mutex_init (&m_mutex, NULL);
+    assert(err == 0);
+}
+
+//----------------------------------------------------------------------
+// Default constructor.
+//
+// Creates a pthread mutex with "type" as the mutex type.
+//----------------------------------------------------------------------
+Mutex::Mutex (Mutex::Type type) :
+    m_mutex()
+{
+    int err;
+    ::pthread_mutexattr_t attr;
+    err = ::pthread_mutexattr_init (&attr);
+    assert(err == 0);
+    switch (type)
+    {
+    case eMutexTypeNormal:
+        err = ::pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_NORMAL);
+        break;
+
+    case eMutexTypeRecursive:
+        err = ::pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
+        break;
+
+    default:
+        err = -1;
+        break;
+    }
+    assert(err == 0);
+    err = ::pthread_mutex_init (&m_mutex, &attr);
+    assert(err == 0);
+    err = ::pthread_mutexattr_destroy (&attr);
+    assert(err == 0);
+}
+
+//----------------------------------------------------------------------
+// Destructor.
+//
+// Destroys the mutex owned by this object.
+//----------------------------------------------------------------------
+Mutex::~Mutex()
+{
+    int err;
+    err = ::pthread_mutex_destroy (&m_mutex);
+}
+
+//----------------------------------------------------------------------
+// Mutex get accessor.
+//----------------------------------------------------------------------
+pthread_mutex_t *
+Mutex::GetMutex()
+{
+    return &m_mutex;
+}
+
+int
+Mutex::Lock (pthread_mutex_t *mutex_ptr)
+{
+    DEBUG_LOG ("[%4.4x/%4.4x] pthread_mutex_lock (%p)...\n", Host::GetCurrentProcessID(), Host::GetCurrentThreadID(), mutex_ptr);
+    int err = ::pthread_mutex_lock (mutex_ptr);
+    DEBUG_LOG ("[%4.4x/%4.4x] pthread_mutex_lock (%p) => %i\n", Host::GetCurrentProcessID(), Host::GetCurrentThreadID(), mutex_ptr, err);
+    return err;
+}
+
+int
+Mutex::TryLock (pthread_mutex_t *mutex_ptr)
+{
+    int err = ::pthread_mutex_trylock (mutex_ptr);
+    DEBUG_LOG ("[%4.4x/%4.4x] pthread_mutex_trylock (%p) => %i\n", Host::GetCurrentProcessID(), Host::GetCurrentThreadID(), mutex_ptr, err);
+    return err;
+}
+
+int
+Mutex::Unlock (pthread_mutex_t *mutex_ptr)
+{
+    int err = ::pthread_mutex_unlock (mutex_ptr);
+    DEBUG_LOG ("[%4.4x/%4.4x] pthread_mutex_unlock (%p) => %i\n", Host::GetCurrentProcessID(), Host::GetCurrentThreadID(), mutex_ptr, err);
+    return err;
+}
+
+//----------------------------------------------------------------------
+// Locks the mutex owned by this object, if the mutex is already
+// locked, the calling thread will block until the mutex becomes
+// available.
+//
+// RETURNS
+//  The error code from the pthread_mutex_lock() function call.
+//----------------------------------------------------------------------
+int
+Mutex::Lock()
+{
+    return Mutex::Lock (&m_mutex);
+}
+
+//----------------------------------------------------------------------
+// Attempts to lock the mutex owned by this object without blocking.
+// If the mutex is already locked, TryLock() will not block waiting
+// for the mutex, but will return an error condition.
+//
+// RETURNS
+//  The error code from the pthread_mutex_trylock() function call.
+//----------------------------------------------------------------------
+int
+Mutex::TryLock()
+{
+    return Mutex::TryLock (&m_mutex);
+}
+
+//----------------------------------------------------------------------
+// If the current thread holds the lock on the owned mutex, then
+// Unlock() will unlock the mutex. Calling Unlock() on this object
+// that the calling thread does not hold will result in undefined
+// behavior.
+//
+// RETURNS
+//  The error code from the pthread_mutex_unlock() function call.
+//----------------------------------------------------------------------
+int
+Mutex::Unlock()
+{
+    return Mutex::Unlock (&m_mutex);
+}
diff --git a/source/Host/macosx/Symbols.cpp b/source/Host/macosx/Symbols.cpp
new file mode 100644
index 0000000..ff28157
--- /dev/null
+++ b/source/Host/macosx/Symbols.cpp
@@ -0,0 +1,462 @@
+//===-- Symbols.cpp ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/Symbols.h"
+
+// C Includes
+#include <dirent.h>
+#include <mach-o/loader.h>
+#include <mach-o/fat.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include <CoreFoundation/CoreFoundation.h>
+
+// Project includes
+#include "CFCReleaser.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/DataBuffer.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Core/UUID.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+extern "C" {
+CFURLRef DBGCopyFullDSYMURLForUUID (CFUUIDRef uuid, CFURLRef exec_url);
+CFDictionaryRef DBGCopyDSYMPropertyLists (CFURLRef dsym_url);
+};
+
+static bool
+SkinnyMachOFileContainsArchAndUUID
+(
+    const FileSpec &file_spec,
+    const ArchSpec *arch,
+    const UUID *uuid,   // the UUID we are looking for
+    off_t file_offset,
+    DataExtractor& data,
+    uint32_t data_offset,
+    const uint32_t magic
+)
+{
+    assert(magic == MH_CIGAM || magic == MH_MAGIC || magic == MH_CIGAM_64 || magic == MH_MAGIC_64);
+    if (magic == MH_MAGIC || magic == MH_MAGIC_64)
+        data.SetByteOrder (eByteOrderHost);
+    else if (eByteOrderHost == eByteOrderBig)
+        data.SetByteOrder (eByteOrderLittle);
+    else
+        data.SetByteOrder (eByteOrderBig);
+
+    uint32_t i;
+    const uint32_t cputype      = data.GetU32(&data_offset);    // cpu specifier
+    const uint32_t cpusubtype   = data.GetU32(&data_offset);    // machine specifier
+    data_offset+=4; // Skip mach file type
+    const uint32_t ncmds        = data.GetU32(&data_offset);    // number of load commands
+    const uint32_t sizeofcmds   = data.GetU32(&data_offset);    // the size of all the load commands
+    data_offset+=4; // Skip flags
+
+    // Check the architecture if we have a valid arch pointer
+    if (arch)
+    {
+        ArchSpec file_arch(cputype, cpusubtype);
+
+        if (file_arch != *arch)
+            return false;
+    }
+
+    // The file exists, and if a valid arch pointer was passed in we know
+    // if already matches, so we can return if we aren't looking for a specific
+    // UUID
+    if (uuid == NULL)
+        return true;
+
+    if (magic == MH_CIGAM_64 || magic == MH_MAGIC_64)
+        data_offset += 4;   // Skip reserved field for in mach_header_64
+
+    // Make sure we have enough data for all the load commands
+    if (magic == MH_CIGAM_64 || magic == MH_MAGIC_64)
+    {
+        if (data.GetByteSize() < sizeof(struct mach_header_64) + sizeofcmds)
+        {
+            DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header_64) + sizeofcmds));
+            data.SetData (data_buffer_sp);
+        }
+    }
+    else
+    {
+        if (data.GetByteSize() < sizeof(struct mach_header) + sizeofcmds)
+        {
+            DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header) + sizeofcmds));
+            data.SetData (data_buffer_sp);
+        }
+    }
+
+    for (i=0; i<ncmds; i++)
+    {
+        const uint32_t cmd_offset = data_offset;    // Save this data_offset in case parsing of the segment goes awry!
+        uint32_t cmd        = data.GetU32(&data_offset);
+        uint32_t cmd_size   = data.GetU32(&data_offset);
+        if (cmd == LC_UUID)
+        {
+            UUID file_uuid (data.GetData(&data_offset, 16), 16);
+            return file_uuid == *uuid;
+        }
+        data_offset = cmd_offset + cmd_size;
+    }
+    return false;
+}
+
+bool
+UniversalMachOFileContainsArchAndUUID
+(
+    const FileSpec &file_spec,
+    const ArchSpec *arch,
+    const UUID *uuid,
+    off_t file_offset,
+    DataExtractor& data,
+    uint32_t data_offset,
+    const uint32_t magic
+)
+{
+    assert(magic == FAT_CIGAM || magic == FAT_MAGIC);
+
+    // Universal mach-o files always have their headers encoded as BIG endian
+    data.SetByteOrder(eByteOrderBig);
+
+    uint32_t i;
+    const uint32_t nfat_arch = data.GetU32(&data_offset);   // number of structs that follow
+    const uint32_t fat_header_and_arch_size = sizeof(struct fat_header) + nfat_arch * sizeof(struct fat_arch);
+    if (data.GetByteSize() < fat_header_and_arch_size)
+    {
+        DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, fat_header_and_arch_size));
+        data.SetData (data_buffer_sp);
+    }
+
+    for (i=0; i<nfat_arch; i++)
+    {
+        cpu_type_t      arch_cputype        = data.GetU32(&data_offset);    // cpu specifier (int)
+        cpu_subtype_t   arch_cpusubtype     = data.GetU32(&data_offset);    // machine specifier (int)
+        uint32_t        arch_offset         = data.GetU32(&data_offset);    // file offset to this object file
+    //  uint32_t        arch_size           = data.GetU32(&data_offset);    // size of this object file
+    //  uint32_t        arch_align          = data.GetU32(&data_offset);    // alignment as a power of 2
+        data_offset += 8;   // Skip size and align as we don't need those
+        // Only process this slice if the cpu type/subtype matches
+        if (arch)
+        {
+            ArchSpec fat_arch(arch_cputype, arch_cpusubtype);
+            if (fat_arch != *arch)
+                continue;
+        }
+
+        // Create a buffer with only the arch slice date in it
+        DataExtractor arch_data;
+        DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset + arch_offset, 0x1000));
+        arch_data.SetData(data_buffer_sp);
+        uint32_t arch_data_offset = 0;
+        uint32_t arch_magic = arch_data.GetU32(&arch_data_offset);
+
+        switch (arch_magic)
+        {
+        case MH_CIGAM:          // 32 bit mach-o file
+        case MH_MAGIC:          // 32 bit mach-o file
+        case MH_CIGAM_64:       // 64 bit mach-o file
+        case MH_MAGIC_64:       // 64 bit mach-o file
+            if (SkinnyMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset + arch_offset, arch_data, arch_data_offset, arch_magic))
+                return true;
+            break;
+        }
+    }
+    return false;
+}
+
+static bool
+FileAtPathContainsArchAndUUID
+(
+    const FileSpec &file_spec,
+    const ArchSpec *arch,
+    const UUID *uuid
+)
+{
+    DataExtractor data;
+    off_t file_offset = 0;
+    DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, 0x1000));
+
+    if (data_buffer_sp && data_buffer_sp->GetByteSize() > 0)
+    {
+        data.SetData(data_buffer_sp);
+
+        uint32_t data_offset = 0;
+        uint32_t magic = data.GetU32(&data_offset);
+
+        switch (magic)
+        {
+        // 32 bit mach-o file
+        case MH_CIGAM:
+        case MH_MAGIC:
+        case MH_CIGAM_64:
+        case MH_MAGIC_64:
+            return SkinnyMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset, data, data_offset, magic);
+
+        // fat mach-o file
+        case FAT_CIGAM:
+        case FAT_MAGIC:
+            return UniversalMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset, data, data_offset, magic);
+
+        default:
+            break;
+        }
+    }
+    return false;
+}
+
+static FileSpec
+LocateDSYMMachFileInDSYMBundle
+(
+    const FileSpec& dsym_bundle_fspec,
+    const UUID *uuid,
+    const ArchSpec *arch)
+{
+    char path[PATH_MAX];
+
+    FileSpec dsym_fspec;
+
+    if (dsym_bundle_fspec.GetPath(path, sizeof(path)))
+    {
+        ::strncat (path, "/Contents/Resources/DWARF", sizeof(path) - strlen(path) - 1);
+
+        DIR* dirp = ::opendir(path);
+        if (dirp != NULL)
+        {
+            const size_t path_len = strlen(path);
+            const int bytes_left = sizeof(path) - path_len - 1;
+            struct dirent* dp;
+            while ((dp = readdir(dirp)) != NULL)
+            {
+                // Only search directories
+                if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN)
+                {
+                    if (dp->d_namlen == 1 && dp->d_name[0] == '.')
+                        continue;
+
+                    if (dp->d_namlen == 2 && dp->d_name[0] == '.' && dp->d_name[1] == '.')
+                        continue;
+                }
+
+                if (dp->d_type == DT_REG || dp->d_type == DT_UNKNOWN)
+                {
+                    ::strncpy (&path[path_len], dp->d_name, bytes_left);
+
+                    dsym_fspec.SetFile(path);
+                    if (FileAtPathContainsArchAndUUID (dsym_fspec, arch, uuid))
+                        return dsym_fspec;
+                }
+            }
+        }
+    }
+    dsym_fspec.Clear();
+    return dsym_fspec;
+}
+
+static int
+LocateMacOSXFilesUsingDebugSymbols
+(
+    const FileSpec *exec_fspec, // An executable path that may or may not be correct if UUID is specified
+    const ArchSpec* arch,       // Limit the search to files with this architecture if non-NULL
+    const UUID *uuid,           // Match the UUID value if non-NULL,
+    FileSpec *out_exec_fspec,   // If non-NULL, try and find the executable
+    FileSpec *out_dsym_fspec    // If non-NULL try and find the debug symbol file
+)
+{
+    int items_found = 0;
+
+    if (out_exec_fspec)
+        out_exec_fspec->Clear();
+
+    if (out_dsym_fspec)
+        out_dsym_fspec->Clear();
+
+    if (uuid && uuid->IsValid())
+    {
+        // Try and locate the dSYM file using DebugSymbols first
+        const UInt8 *module_uuid = (const UInt8 *)uuid->GetBytes();
+        if (module_uuid != NULL)
+        {
+            CFCReleaser<CFUUIDRef> module_uuid_ref(::CFUUIDCreateWithBytes ( NULL,
+                                                                            module_uuid[0],
+                                                                            module_uuid[1],
+                                                                            module_uuid[2],
+                                                                            module_uuid[3],
+                                                                            module_uuid[4],
+                                                                            module_uuid[5],
+                                                                            module_uuid[6],
+                                                                            module_uuid[7],
+                                                                            module_uuid[8],
+                                                                            module_uuid[9],
+                                                                            module_uuid[10],
+                                                                            module_uuid[11],
+                                                                            module_uuid[12],
+                                                                            module_uuid[13],
+                                                                            module_uuid[14],
+                                                                            module_uuid[15]));
+
+            if (module_uuid_ref.get())
+            {
+                CFCReleaser<CFURLRef> exec_url;
+
+                if (exec_fspec)
+                {
+                    char exec_cf_path[PATH_MAX];
+                    if (exec_fspec->GetPath(exec_cf_path, sizeof(exec_cf_path)))
+                        exec_url.reset(::CFURLCreateFromFileSystemRepresentation (NULL,
+                                                                                  (const UInt8 *)exec_cf_path,
+                                                                                  strlen(exec_cf_path),
+                                                                                  FALSE));
+                }
+
+                CFCReleaser<CFURLRef> dsym_url (::DBGCopyFullDSYMURLForUUID(module_uuid_ref.get(), exec_url.get()));
+                char path[PATH_MAX];
+
+                if (dsym_url.get())
+                {
+                    if (out_dsym_fspec)
+                    {
+                        if (::CFURLGetFileSystemRepresentation (dsym_url.get(), true, (UInt8*)path, sizeof(path)-1))
+                        {
+                            out_dsym_fspec->SetFile(path);
+
+                            if (out_dsym_fspec->GetFileType () == FileSpec::eFileTypeDirectory)
+                            {
+                                *out_dsym_fspec = LocateDSYMMachFileInDSYMBundle (*out_dsym_fspec, uuid, arch);
+                                if (*out_dsym_fspec)
+                                    ++items_found;
+                            }
+                            else
+                            {
+                                ++items_found;
+                            }
+                        }
+                    }
+
+                    if (out_exec_fspec)
+                    {
+                        CFCReleaser<CFDictionaryRef> dict(::DBGCopyDSYMPropertyLists (dsym_url.get()));;
+                        if (dict.get())
+                        {
+                            CFStringRef exec_cf_path = static_cast<CFStringRef>(::CFDictionaryGetValue (dict.get(), CFSTR("DBGSymbolRichExecutable")));
+                            if (exec_cf_path && ::CFStringGetFileSystemRepresentation (exec_cf_path, path, sizeof(path)))
+                            {
+                                ++items_found;
+                                out_dsym_fspec->SetFile(path);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return items_found;
+}
+
+static bool
+LocateDSYMInVincinityOfExecutable (const FileSpec *exec_fspec, const ArchSpec* arch, const UUID *uuid, FileSpec &dsym_fspec)
+{
+    if (exec_fspec)
+    {
+        char path[PATH_MAX];
+        if (exec_fspec->GetPath(path, sizeof(path)))
+        {
+            // Make sure the module isn't already just a dSYM file...
+            if (strcasestr(path, ".dSYM/Contents/Resources/DWARF") == NULL)
+            {
+                size_t obj_file_path_length = strlen(path);
+                strncat(path, ".dSYM/Contents/Resources/DWARF/", sizeof(path));
+                strncat(path, exec_fspec->GetFilename().AsCString(), sizeof(path));
+
+                dsym_fspec.SetFile(path);
+
+                if (FileAtPathContainsArchAndUUID (dsym_fspec, arch, uuid))
+                {
+                    return true;
+                }
+                else
+                {
+                    path[obj_file_path_length] = '\0';
+
+                    char *last_dot = strrchr(path, '.');
+                    while (last_dot != NULL && last_dot[0])
+                    {
+                        char *next_slash = strchr(last_dot, '/');
+                        if (next_slash != NULL)
+                        {
+                            *next_slash = '\0';
+                            strncat(path, ".dSYM/Contents/Resources/DWARF/", sizeof(path));
+                            strncat(path, exec_fspec->GetFilename().AsCString(), sizeof(path));
+                            dsym_fspec.SetFile(path);
+                            if (dsym_fspec.Exists())
+                                return true;
+                            else
+                            {
+                                *last_dot = '\0';
+                                char *prev_slash = strrchr(path, '/');
+                                if (prev_slash != NULL)
+                                    *prev_slash = '\0';
+                                else
+                                    break;
+                            }
+                        }
+                        else
+                        {
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    dsym_fspec.Clear();
+    return false;
+}
+
+FileSpec
+Symbols::LocateExecutableObjectFile (const FileSpec *exec_fspec, const ArchSpec* arch, const UUID *uuid)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)",
+                        exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>",
+                        arch ? arch->AsCString() : "<NULL>",
+                        uuid);
+
+    FileSpec objfile_fspec;
+    if (exec_fspec && FileAtPathContainsArchAndUUID (*exec_fspec, arch, uuid))
+        objfile_fspec = *exec_fspec;
+    else
+        LocateMacOSXFilesUsingDebugSymbols (exec_fspec, arch, uuid, &objfile_fspec, NULL);
+    return objfile_fspec;
+}
+
+FileSpec
+Symbols::LocateExecutableSymbolFile (const FileSpec *exec_fspec, const ArchSpec* arch, const UUID *uuid)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "LocateExecutableSymbolFile (file = %s, arch = %s, uuid = %p)",
+                        exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>",
+                        arch ? arch->AsCString() : "<NULL>",
+                        uuid);
+
+    FileSpec symbol_fspec;
+    // First try and find the dSYM in the same directory as the executable or in
+    // an appropriate parent directory
+    if (LocateDSYMInVincinityOfExecutable (exec_fspec, arch, uuid, symbol_fspec) == false)
+    {
+        // We failed to easily find the dSYM above, so use DebugSymbols
+        LocateMacOSXFilesUsingDebugSymbols (exec_fspec, arch, uuid, NULL, &symbol_fspec);
+    }
+    return symbol_fspec;
+}
diff --git a/source/Host/macosx/TimeValue.cpp b/source/Host/macosx/TimeValue.cpp
new file mode 100644
index 0000000..27aad5f
--- /dev/null
+++ b/source/Host/macosx/TimeValue.cpp
@@ -0,0 +1,179 @@
+//===-- TimeValue.cpp -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TimeValue.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+#define NSEC_PER_USEC   1000ull
+#define USEC_PER_SEC    1000000ull
+#define NSEC_PER_SEC    1000000000ull
+
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// TimeValue constructor
+//----------------------------------------------------------------------
+TimeValue::TimeValue() :
+    m_nano_seconds (0)
+{
+}
+
+//----------------------------------------------------------------------
+// TimeValue copy constructor
+//----------------------------------------------------------------------
+TimeValue::TimeValue(const TimeValue& rhs) :
+    m_nano_seconds (rhs.m_nano_seconds)
+{
+}
+
+TimeValue::TimeValue(const struct timespec& ts) :
+    m_nano_seconds (ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec)
+{
+}
+
+TimeValue::TimeValue(const struct timeval& tv) :
+    m_nano_seconds (tv.tv_sec * NSEC_PER_SEC + tv.tv_usec * NSEC_PER_USEC)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+TimeValue::~TimeValue()
+{
+}
+
+
+uint64_t
+TimeValue::GetAsNanoSecondsSinceJan1_1970() const
+{
+    return m_nano_seconds;
+}
+
+uint64_t
+TimeValue::GetAsMicroSecondsSinceJan1_1970() const
+{
+    return m_nano_seconds / NSEC_PER_USEC;
+}
+
+struct timespec
+TimeValue::GetAsTimeSpec () const
+{
+    struct timespec ts;
+    ts.tv_sec = m_nano_seconds / NSEC_PER_SEC;
+    ts.tv_nsec = m_nano_seconds % NSEC_PER_SEC;
+    return ts;
+}
+
+struct timeval
+TimeValue::GetAsTimeVal () const
+{
+    struct timeval tv;
+    tv.tv_sec = m_nano_seconds / NSEC_PER_SEC;
+    tv.tv_usec = (m_nano_seconds % NSEC_PER_SEC) / NSEC_PER_USEC;
+    return tv;
+}
+
+void
+TimeValue::Clear ()
+{
+    m_nano_seconds = 0;
+}
+
+bool
+TimeValue::IsValid () const
+{
+    return m_nano_seconds != 0;
+}
+
+void
+TimeValue::OffsetWithSeconds (uint32_t sec)
+{
+    m_nano_seconds += sec * NSEC_PER_SEC;
+}
+
+void
+TimeValue::OffsetWithMicroSeconds (uint32_t usec)
+{
+    m_nano_seconds += usec * NSEC_PER_USEC;
+}
+
+void
+TimeValue::OffsetWithNanoSeconds (uint32_t nsec)
+{
+    m_nano_seconds += nsec;
+}
+
+TimeValue
+TimeValue::Now()
+{
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    TimeValue now(tv);
+    return now;
+}
+
+//----------------------------------------------------------------------
+// TimeValue assignment operator
+//----------------------------------------------------------------------
+const TimeValue&
+TimeValue::operator=(const TimeValue& rhs)
+{
+    m_nano_seconds = rhs.m_nano_seconds;
+    return *this;
+}
+
+
+bool
+lldb_private::operator == (const TimeValue &lhs, const TimeValue &rhs)
+{
+    return lhs.GetAsNanoSecondsSinceJan1_1970() == rhs.GetAsNanoSecondsSinceJan1_1970();
+}
+
+bool
+lldb_private::operator != (const TimeValue &lhs, const TimeValue &rhs)
+{
+    return lhs.GetAsNanoSecondsSinceJan1_1970() != rhs.GetAsNanoSecondsSinceJan1_1970();
+}
+
+bool
+lldb_private::operator <  (const TimeValue &lhs, const TimeValue &rhs)
+{
+    return lhs.GetAsNanoSecondsSinceJan1_1970() < rhs.GetAsNanoSecondsSinceJan1_1970();
+}
+
+bool
+lldb_private::operator <= (const TimeValue &lhs, const TimeValue &rhs)
+{
+    return lhs.GetAsNanoSecondsSinceJan1_1970() <= rhs.GetAsNanoSecondsSinceJan1_1970();
+}
+
+bool
+lldb_private::operator >  (const TimeValue &lhs, const TimeValue &rhs)
+{
+    return lhs.GetAsNanoSecondsSinceJan1_1970() > rhs.GetAsNanoSecondsSinceJan1_1970();
+}
+
+bool
+lldb_private::operator >= (const TimeValue &lhs, const TimeValue &rhs)
+{
+    return lhs.GetAsNanoSecondsSinceJan1_1970() >= rhs.GetAsNanoSecondsSinceJan1_1970();
+}
+
+uint64_t
+lldb_private::operator - (const TimeValue &lhs, const TimeValue &rhs)
+{
+    return lhs.GetAsNanoSecondsSinceJan1_1970() - rhs.GetAsNanoSecondsSinceJan1_1970();
+}
+
+
diff --git a/source/Host/macosx/cfcpp/CFCBundle.cpp b/source/Host/macosx/cfcpp/CFCBundle.cpp
new file mode 100644
index 0000000..6e68af5
--- /dev/null
+++ b/source/Host/macosx/cfcpp/CFCBundle.cpp
@@ -0,0 +1,83 @@
+//===-- CFCBundle.cpp -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CFCBundle.h"
+#include "CFCString.h"
+
+//----------------------------------------------------------------------
+// CFCBundle constructor
+//----------------------------------------------------------------------
+CFCBundle::CFCBundle(const char *path) :
+    CFCReleaser<CFBundleRef>()
+{
+    if (path && path[0])
+        SetPath(path);
+}
+
+CFCBundle::CFCBundle(CFURLRef url) :
+    CFCReleaser<CFBundleRef>(url ? CFBundleCreate(NULL, url) : NULL)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+CFCBundle::~CFCBundle()
+{
+}
+
+//----------------------------------------------------------------------
+// Set the path for a bundle by supplying a
+//----------------------------------------------------------------------
+bool
+CFCBundle::SetPath (const char *path)
+{
+    CFAllocatorRef alloc = kCFAllocatorDefault;
+    // Release our old bundle and URL
+    reset();
+
+    // Make a CFStringRef from the supplied path
+    CFCString cf_path;
+    cf_path.SetFileSystemRepresentation(path);
+    if (cf_path.get())
+    {
+        // Make our Bundle URL
+        CFCReleaser<CFURLRef> bundle_url (::CFURLCreateWithFileSystemPath (alloc, cf_path.get(), kCFURLPOSIXPathStyle, true));
+        if (bundle_url.get())
+            reset (::CFBundleCreate (alloc, bundle_url.get()));
+    }
+    return get() != NULL;
+}
+
+CFStringRef
+CFCBundle::GetIdentifier () const
+{
+    CFBundleRef bundle = get();
+    if (bundle != NULL)
+        return ::CFBundleGetIdentifier (bundle);
+    return NULL;
+}
+
+CFTypeRef
+CFCBundle::GetValueForInfoDictionaryKey(CFStringRef key) const
+{
+    CFBundleRef bundle = get();
+    if (bundle != NULL)
+        return ::CFBundleGetValueForInfoDictionaryKey(bundle, key);
+    return NULL;
+}
+
+CFURLRef
+CFCBundle::CopyExecutableURL () const
+{
+    CFBundleRef bundle = get();
+    if (bundle != NULL)
+        return CFBundleCopyExecutableURL(bundle);
+    return NULL;
+}
diff --git a/source/Host/macosx/cfcpp/CFCBundle.h b/source/Host/macosx/cfcpp/CFCBundle.h
new file mode 100644
index 0000000..c07a48c
--- /dev/null
+++ b/source/Host/macosx/cfcpp/CFCBundle.h
@@ -0,0 +1,47 @@
+//===-- CFCBundle.h ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CoreFoundationCPP_CFBundle_h_
+#define CoreFoundationCPP_CFBundle_h_
+
+#include "CFCReleaser.h"
+
+class CFCBundle : public CFCReleaser<CFBundleRef>
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    CFCBundle (const char *path = NULL);
+    CFCBundle (CFURLRef url);
+
+    virtual
+    ~CFCBundle();
+
+    CFURLRef
+    CopyExecutableURL () const;
+
+    CFStringRef
+    GetIdentifier () const;
+
+    CFTypeRef
+    GetValueForInfoDictionaryKey(CFStringRef key) const;
+
+    bool
+    SetPath (const char *path);
+
+private:
+    // Disallow copy and assignment constructors
+    CFCBundle(const CFCBundle&);
+
+    const CFCBundle&
+    operator=(const CFCBundle&);
+};
+
+#endif // #ifndef CoreFoundationCPP_CFBundle_h_
diff --git a/source/Host/macosx/cfcpp/CFCData.cpp b/source/Host/macosx/cfcpp/CFCData.cpp
new file mode 100644
index 0000000..4f49368
--- /dev/null
+++ b/source/Host/macosx/cfcpp/CFCData.cpp
@@ -0,0 +1,82 @@
+//===-- CFCData.cpp ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CFCData.h"
+
+//----------------------------------------------------------------------
+// CFCData constructor
+//----------------------------------------------------------------------
+CFCData::CFCData(CFDataRef data) :
+    CFCReleaser<CFDataRef>(data)
+{
+
+}
+
+//----------------------------------------------------------------------
+// CFCData copy constructor
+//----------------------------------------------------------------------
+CFCData::CFCData(const CFCData& rhs) :
+    CFCReleaser<CFDataRef>(rhs)
+{
+
+}
+
+//----------------------------------------------------------------------
+// CFCData copy constructor
+//----------------------------------------------------------------------
+CFCData&
+CFCData::operator=(const CFCData& rhs)
+
+{
+    if (this != &rhs)
+        *this = rhs;
+    return *this;
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+CFCData::~CFCData()
+{
+}
+
+
+CFIndex
+CFCData::GetLength() const
+{
+    CFDataRef data = get();
+    if (data)
+        return CFDataGetLength (data);
+    return 0;
+}
+
+
+const uint8_t*
+CFCData::GetBytePtr() const
+{
+    CFDataRef data = get();
+    if (data)
+        return CFDataGetBytePtr (data);
+    return NULL;
+}
+
+CFDataRef
+CFCData::Serialize(CFPropertyListRef plist, CFPropertyListFormat format)
+{
+    CFAllocatorRef alloc = kCFAllocatorDefault;
+    reset();
+    CFCReleaser<CFWriteStreamRef> stream (::CFWriteStreamCreateWithAllocatedBuffers (alloc, alloc));
+    ::CFWriteStreamOpen (stream.get());
+    CFIndex len = ::CFPropertyListWriteToStream (plist, stream.get(), format, NULL);
+    if (len > 0)
+        reset((CFDataRef)::CFWriteStreamCopyProperty (stream.get(), kCFStreamPropertyDataWritten));
+    ::CFWriteStreamClose (stream.get());
+    return get();
+}
+
diff --git a/source/Host/macosx/cfcpp/CFCData.h b/source/Host/macosx/cfcpp/CFCData.h
new file mode 100644
index 0000000..6a718f5
--- /dev/null
+++ b/source/Host/macosx/cfcpp/CFCData.h
@@ -0,0 +1,35 @@
+//===-- CFCData.h -----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CoreFoundationCPP_CFData_h_
+#define CoreFoundationCPP_CFData_h_
+
+#include "CFCReleaser.h"
+
+class CFCData : public CFCReleaser<CFDataRef>
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    CFCData(CFDataRef data = NULL);
+    CFCData(const CFCData& rhs);
+    CFCData& operator=(const CFCData& rhs);
+    virtual ~CFCData();
+
+        CFDataRef Serialize(CFPropertyListRef plist, CFPropertyListFormat format);
+        const uint8_t* GetBytePtr () const;
+        CFIndex GetLength () const;
+protected:
+    //------------------------------------------------------------------
+    // Classes that inherit from CFCData can see and modify these
+    //------------------------------------------------------------------
+};
+
+#endif // #ifndef CoreFoundationCPP_CFData_h_
diff --git a/source/Host/macosx/cfcpp/CFCMutableArray.cpp b/source/Host/macosx/cfcpp/CFCMutableArray.cpp
new file mode 100644
index 0000000..3b92f03
--- /dev/null
+++ b/source/Host/macosx/cfcpp/CFCMutableArray.cpp
@@ -0,0 +1,123 @@
+//===-- CFCMutableArray.cpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CFCMutableArray.h"
+
+//----------------------------------------------------------------------
+// CFCString constructor
+//----------------------------------------------------------------------
+CFCMutableArray::CFCMutableArray(CFMutableArrayRef s) :
+    CFCReleaser<CFMutableArrayRef> (s)
+{
+}
+
+//----------------------------------------------------------------------
+// CFCMutableArray copy constructor
+//----------------------------------------------------------------------
+CFCMutableArray::CFCMutableArray(const CFCMutableArray& rhs) :
+    CFCReleaser<CFMutableArrayRef> (rhs)    // NOTE: this won't make a copy of the array, just add a new reference to it
+{
+}
+
+//----------------------------------------------------------------------
+// CFCMutableArray copy constructor
+//----------------------------------------------------------------------
+CFCMutableArray&
+CFCMutableArray::operator=(const CFCMutableArray& rhs)
+{
+    if (this != &rhs)
+        *this = rhs;    // NOTE: this operator won't make a copy of the array, just add a new reference to it
+    return *this;
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+CFCMutableArray::~CFCMutableArray()
+{
+}
+
+
+CFIndex
+CFCMutableArray::GetCount() const
+{
+    CFMutableArrayRef array = get();
+    if (array)
+        return ::CFArrayGetCount (array);
+    return 0;
+}
+
+CFIndex
+CFCMutableArray::GetCountOfValue(CFRange range, const void *value) const
+{
+    CFMutableArrayRef array = get();
+    if (array)
+        return ::CFArrayGetCountOfValue (array, range, value);
+    return 0;
+}
+
+CFIndex
+CFCMutableArray::GetCountOfValue(const void *value) const
+{
+    CFMutableArrayRef array = get();
+    if (array)
+        return ::CFArrayGetCountOfValue (array, CFRangeMake(0, GetCount()), value);
+    return 0;
+}
+
+const void *
+CFCMutableArray::GetValueAtIndex(CFIndex idx) const
+{
+    CFMutableArrayRef array = get();
+    if (array)
+    {
+        const CFIndex num_array_items = ::CFArrayGetCount (array);
+        if (0 <= idx && idx < num_array_items)
+        {
+            return ::CFArrayGetValueAtIndex (array, idx);
+        }
+    }
+    return NULL;
+}
+
+bool
+CFCMutableArray::SetValueAtIndex(CFIndex idx, const void *value)
+{
+    CFMutableArrayRef array = get();
+    if (array != NULL)
+    {
+        const CFIndex num_array_items = ::CFArrayGetCount (array);
+        if (0 <= idx && idx < num_array_items)
+        {
+            ::CFArraySetValueAtIndex (array, idx, value);
+            return true;
+        }
+    }
+    return false;
+}
+
+
+bool
+CFCMutableArray::AppendValue(const void *value, bool can_create)
+{
+    CFMutableArrayRef array = get();
+    if (array == NULL)
+    {
+        if (can_create == false)
+            return false;
+        array = ::CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
+        reset ( array );
+    }
+    if (array != NULL)
+    {
+        ::CFArrayAppendValue(array, value);
+        return true;
+    }
+    return false;
+}
diff --git a/source/Host/macosx/cfcpp/CFCMutableArray.h b/source/Host/macosx/cfcpp/CFCMutableArray.h
new file mode 100644
index 0000000..eaadb8d
--- /dev/null
+++ b/source/Host/macosx/cfcpp/CFCMutableArray.h
@@ -0,0 +1,34 @@
+//===-- CFCMutableArray.h ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CoreFoundationCPP_CFMutableArray_h_
+#define CoreFoundationCPP_CFMutableArray_h_
+
+#include "CFCReleaser.h"
+
+class CFCMutableArray : public CFCReleaser<CFMutableArrayRef>
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    CFCMutableArray(CFMutableArrayRef array = NULL);
+    CFCMutableArray(const CFCMutableArray& rhs);                // This will copy the array contents into a new array
+    CFCMutableArray& operator=(const CFCMutableArray& rhs); // This will re-use the same array and just bump the ref count
+    virtual ~CFCMutableArray();
+
+    CFIndex         GetCount() const;
+    CFIndex         GetCountOfValue(const void *value) const;
+    CFIndex         GetCountOfValue(CFRange range, const void *value) const;
+    const void *    GetValueAtIndex(CFIndex idx) const;
+    bool            SetValueAtIndex(CFIndex idx, const void *value);
+    bool            AppendValue(const void *value, bool can_create = true); // Appends value and optionally creates a CFCMutableArray if this class doesn't contain one
+};
+
+#endif // #ifndef CoreFoundationCPP_CFMutableArray_h_
diff --git a/source/Host/macosx/cfcpp/CFCMutableDictionary.cpp b/source/Host/macosx/cfcpp/CFCMutableDictionary.cpp
new file mode 100644
index 0000000..963221a
--- /dev/null
+++ b/source/Host/macosx/cfcpp/CFCMutableDictionary.cpp
@@ -0,0 +1,491 @@
+//===-- CFCMutableDictionary.cpp --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CFCMutableDictionary.h"
+#include "CFCString.h"
+//----------------------------------------------------------------------
+// CFCString constructor
+//----------------------------------------------------------------------
+CFCMutableDictionary::CFCMutableDictionary(CFMutableDictionaryRef s) :
+    CFCReleaser<CFMutableDictionaryRef> (s)
+{
+}
+
+//----------------------------------------------------------------------
+// CFCMutableDictionary copy constructor
+//----------------------------------------------------------------------
+CFCMutableDictionary::CFCMutableDictionary(const CFCMutableDictionary& rhs) :
+    CFCReleaser<CFMutableDictionaryRef> (rhs)
+{
+}
+
+//----------------------------------------------------------------------
+// CFCMutableDictionary copy constructor
+//----------------------------------------------------------------------
+const CFCMutableDictionary&
+CFCMutableDictionary::operator=(const CFCMutableDictionary& rhs)
+{
+    if (this != &rhs)
+        *this = rhs;
+    return *this;
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+CFCMutableDictionary::~CFCMutableDictionary()
+{
+}
+
+
+CFIndex
+CFCMutableDictionary::GetCount() const
+{
+    CFMutableDictionaryRef dict = get();
+    if (dict)
+        return ::CFDictionaryGetCount (dict);
+    return 0;
+}
+
+CFIndex
+CFCMutableDictionary::GetCountOfKey(const void *key) const
+
+{
+    CFMutableDictionaryRef dict = get();
+    if (dict)
+        return ::CFDictionaryGetCountOfKey (dict, key);
+    return 0;
+}
+
+CFIndex
+CFCMutableDictionary::GetCountOfValue(const void *value) const
+
+{
+    CFMutableDictionaryRef dict = get();
+    if (dict)
+        return ::CFDictionaryGetCountOfValue (dict, value);
+    return 0;
+}
+
+void
+CFCMutableDictionary::GetKeysAndValues(const void **keys, const void **values) const
+{
+    CFMutableDictionaryRef dict = get();
+    if (dict)
+        ::CFDictionaryGetKeysAndValues (dict, keys, values);
+}
+
+
+const void *
+CFCMutableDictionary::GetValue(const void *key) const
+
+{
+    CFMutableDictionaryRef dict = get();
+    if (dict)
+        return ::CFDictionaryGetValue (dict, key);
+    return NULL;
+}
+
+Boolean
+CFCMutableDictionary::GetValueIfPresent(const void *key, const void **value_handle) const
+{
+    CFMutableDictionaryRef dict = get();
+    if (dict)
+        return ::CFDictionaryGetValueIfPresent (dict, key, value_handle);
+    return false;
+}
+
+
+CFMutableDictionaryRef
+CFCMutableDictionary::Dictionary(bool can_create)
+{
+    CFMutableDictionaryRef dict = get();
+    if (can_create && dict == NULL)
+    {
+        dict = ::CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+        reset ( dict );
+    }
+    return dict;
+}
+
+bool
+CFCMutableDictionary::AddValue(CFStringRef key, const void *value, bool can_create)
+{
+    CFMutableDictionaryRef dict = Dictionary(can_create);
+    if (dict != NULL)
+    {
+        // Let the dictionary own the CFNumber
+        ::CFDictionaryAddValue (dict, key, value);
+        return true;
+    }
+    return false;
+}
+
+bool
+CFCMutableDictionary::SetValue(CFStringRef key, const void *value, bool can_create)
+{
+    CFMutableDictionaryRef dict = Dictionary(can_create);
+    if (dict != NULL)
+    {
+        // Let the dictionary own the CFNumber
+        ::CFDictionarySetValue (dict, key, value);
+        return true;
+    }
+    return false;
+}
+
+bool
+CFCMutableDictionary::AddValueSInt8(CFStringRef key, int8_t value, bool can_create)
+{
+    CFMutableDictionaryRef dict = Dictionary(can_create);
+    if (dict != NULL)
+    {
+        CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt8Type, &value));
+        if (cf_number.get())
+        {
+            // Let the dictionary own the CFNumber
+            ::CFDictionaryAddValue (dict, key, cf_number.get());
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+CFCMutableDictionary::SetValueSInt8(CFStringRef key, int8_t value, bool can_create)
+{
+    CFMutableDictionaryRef dict = Dictionary(can_create);
+    if (dict != NULL)
+    {
+        CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt8Type, &value));
+        if (cf_number.get())
+        {
+            // Let the dictionary own the CFNumber
+            ::CFDictionarySetValue (dict, key, cf_number.get());
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+CFCMutableDictionary::AddValueSInt16(CFStringRef key, int16_t value, bool can_create)
+{
+    CFMutableDictionaryRef dict = Dictionary(can_create);
+    if (dict != NULL)
+    {
+        CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt16Type, &value));
+        if (cf_number.get())
+        {
+            // Let the dictionary own the CFNumber
+            ::CFDictionaryAddValue (dict, key, cf_number.get());
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+CFCMutableDictionary::SetValueSInt16(CFStringRef key, int16_t value, bool can_create)
+{
+    CFMutableDictionaryRef dict = Dictionary(can_create);
+    if (dict != NULL)
+    {
+        CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt16Type, &value));
+        if (cf_number.get())
+        {
+            // Let the dictionary own the CFNumber
+            ::CFDictionarySetValue (dict, key, cf_number.get());
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+CFCMutableDictionary::AddValueSInt32(CFStringRef key, int32_t value, bool can_create)
+{
+    CFMutableDictionaryRef dict = Dictionary(can_create);
+    if (dict != NULL)
+    {
+        CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt32Type, &value));
+        if (cf_number.get())
+        {
+            // Let the dictionary own the CFNumber
+            ::CFDictionaryAddValue (dict, key, cf_number.get());
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+CFCMutableDictionary::SetValueSInt32(CFStringRef key, int32_t value, bool can_create)
+{
+    CFMutableDictionaryRef dict = Dictionary(can_create);
+    if (dict != NULL)
+    {
+        CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt32Type, &value));
+        if (cf_number.get())
+        {
+            // Let the dictionary own the CFNumber
+            ::CFDictionarySetValue (dict, key, cf_number.get());
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+CFCMutableDictionary::AddValueSInt64(CFStringRef key, int64_t value, bool can_create)
+{
+    CFMutableDictionaryRef dict = Dictionary(can_create);
+    if (dict != NULL)
+    {
+        CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt64Type, &value));
+        if (cf_number.get())
+        {
+            // Let the dictionary own the CFNumber
+            ::CFDictionaryAddValue (dict, key, cf_number.get());
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+CFCMutableDictionary::SetValueSInt64(CFStringRef key, int64_t value, bool can_create)
+{
+    CFMutableDictionaryRef dict = Dictionary(can_create);
+    if (dict != NULL)
+    {
+        CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt64Type, &value));
+        if (cf_number.get())
+        {
+            // Let the dictionary own the CFNumber
+            ::CFDictionarySetValue (dict, key, cf_number.get());
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+CFCMutableDictionary::AddValueUInt8(CFStringRef key, uint8_t value, bool can_create)
+{
+    CFMutableDictionaryRef dict = Dictionary(can_create);
+    if (dict != NULL)
+    {
+        // Have to promote to the next size type so things don't appear negative of the MSBit is set...
+        int16_t sval = value;
+        CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt16Type, &sval));
+        if (cf_number.get())
+        {
+            // Let the dictionary own the CFNumber
+            ::CFDictionaryAddValue (dict, key, cf_number.get());
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+CFCMutableDictionary::SetValueUInt8(CFStringRef key, uint8_t value, bool can_create)
+{
+    CFMutableDictionaryRef dict = Dictionary(can_create);
+    if (dict != NULL)
+    {
+        // Have to promote to the next size type so things don't appear negative of the MSBit is set...
+        int16_t sval = value;
+        CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt16Type, &sval));
+        if (cf_number.get())
+        {
+            // Let the dictionary own the CFNumber
+            ::CFDictionarySetValue (dict, key, cf_number.get());
+            return true;
+        }
+    }
+    return false;
+}
+
+
+bool
+CFCMutableDictionary::AddValueUInt16(CFStringRef key, uint16_t value, bool can_create)
+{
+    CFMutableDictionaryRef dict = Dictionary(can_create);
+    if (dict != NULL)
+    {
+        // Have to promote to the next size type so things don't appear negative of the MSBit is set...
+        int32_t sval = value;
+        CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt32Type, &sval));
+        if (cf_number.get())
+        {
+            // Let the dictionary own the CFNumber
+            ::CFDictionaryAddValue (dict, key, cf_number.get());
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+CFCMutableDictionary::SetValueUInt16(CFStringRef key, uint16_t value, bool can_create)
+{
+    CFMutableDictionaryRef dict = Dictionary(can_create);
+    if (dict != NULL)
+    {
+        // Have to promote to the next size type so things don't appear negative of the MSBit is set...
+        int32_t sval = value;
+        CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt32Type, &sval));
+        if (cf_number.get())
+        {
+            // Let the dictionary own the CFNumber
+            ::CFDictionarySetValue (dict, key, cf_number.get());
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+CFCMutableDictionary::AddValueUInt32(CFStringRef key, uint32_t value, bool can_create)
+{
+    CFMutableDictionaryRef dict = Dictionary(can_create);
+    if (dict != NULL)
+    {
+        // Have to promote to the next size type so things don't appear negative of the MSBit is set...
+        int64_t sval = value;
+        CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt64Type, &sval));
+        if (cf_number.get())
+        {
+            // Let the dictionary own the CFNumber
+            ::CFDictionaryAddValue (dict, key, cf_number.get());
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+CFCMutableDictionary::SetValueUInt32(CFStringRef key, uint32_t value, bool can_create)
+{
+    CFMutableDictionaryRef dict = Dictionary(can_create);
+    if (dict != NULL)
+    {
+        // Have to promote to the next size type so things don't appear negative of the MSBit is set...
+        int64_t sval = value;
+        CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt64Type, &sval));
+        if (cf_number.get())
+        {
+            // Let the dictionary own the CFNumber
+            ::CFDictionarySetValue (dict, key, cf_number.get());
+            return true;
+        }
+    }
+    return false;
+}
+
+
+bool
+CFCMutableDictionary::AddValueUInt64(CFStringRef key, uint64_t value, bool can_create)
+{
+    CFMutableDictionaryRef dict = Dictionary(can_create);
+    if (dict != NULL)
+    {
+        // The number may appear negative if the MSBit is set in "value". Due to a limitation of
+        // CFNumber, there isn't a way to have it show up otherwise as of this writing.
+        CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt64Type, &value));
+        if (cf_number.get())
+        {
+            // Let the dictionary own the CFNumber
+            ::CFDictionaryAddValue (dict, key, cf_number.get());
+            return true;
+        }
+    }
+    return false;
+}
+
+
+bool
+CFCMutableDictionary::SetValueUInt64(CFStringRef key, uint64_t value, bool can_create)
+{
+    CFMutableDictionaryRef dict = Dictionary(can_create);
+    if (dict != NULL)
+    {
+        // The number may appear negative if the MSBit is set in "value". Due to a limitation of
+        // CFNumber, there isn't a way to have it show up otherwise as of this writing.
+        CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt64Type, &value));
+        if (cf_number.get())
+        {
+            // Let the dictionary own the CFNumber
+            ::CFDictionarySetValue (dict, key, cf_number.get());
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+CFCMutableDictionary::AddValueCString(CFStringRef key, const char *cstr, bool can_create)
+{
+    CFMutableDictionaryRef dict = Dictionary(can_create);
+    if (dict != NULL)
+    {
+        CFCString cf_str(cstr, kCFStringEncodingUTF8);
+        if (cf_str.get())
+        {
+            // Let the dictionary own the CFNumber
+            ::CFDictionaryAddValue (dict, key, cf_str.get());
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+CFCMutableDictionary::SetValueCString(CFStringRef key, const char *cstr, bool can_create)
+{
+    CFMutableDictionaryRef dict = Dictionary(can_create);
+    if (dict != NULL)
+    {
+        CFCString cf_str(cstr, kCFStringEncodingUTF8);
+        if (cf_str.get())
+        {
+            // Let the dictionary own the CFNumber
+            ::CFDictionarySetValue (dict, key, cf_str.get());
+            return true;
+        }
+    }
+    return false;
+}
+
+
+void
+CFCMutableDictionary::RemoveAllValues()
+{
+    CFMutableDictionaryRef dict = get();
+    if (dict)
+        ::CFDictionaryRemoveAllValues(dict);
+}
+
+void
+CFCMutableDictionary::RemoveValue(const void *value)
+{
+    CFMutableDictionaryRef dict = get();
+    if (dict)
+        ::CFDictionaryRemoveValue(dict, value);
+}
+void
+CFCMutableDictionary::ReplaceValue(const void *key, const void *value)
+{
+    CFMutableDictionaryRef dict = get();
+    if (dict)
+        ::CFDictionaryReplaceValue (dict, key, value);
+}
+
diff --git a/source/Host/macosx/cfcpp/CFCMutableDictionary.h b/source/Host/macosx/cfcpp/CFCMutableDictionary.h
new file mode 100644
index 0000000..de32ead
--- /dev/null
+++ b/source/Host/macosx/cfcpp/CFCMutableDictionary.h
@@ -0,0 +1,77 @@
+//===-- CFCMutableDictionary.h ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CoreFoundationCPP_CFMutableDictionary_h_
+#define CoreFoundationCPP_CFMutableDictionary_h_
+
+#include "CFCReleaser.h"
+
+class CFCMutableDictionary : public CFCReleaser<CFMutableDictionaryRef>
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    CFCMutableDictionary(CFMutableDictionaryRef s = NULL);
+    CFCMutableDictionary(const CFCMutableDictionary& rhs);
+    virtual ~CFCMutableDictionary();
+
+    //------------------------------------------------------------------
+    // Operators
+    //------------------------------------------------------------------
+    const CFCMutableDictionary&
+    operator=(const CFCMutableDictionary& rhs);
+
+
+    CFIndex GetCount() const;
+    CFIndex GetCountOfKey(const void *value) const;
+    CFIndex GetCountOfValue(const void *value) const;
+    void    GetKeysAndValues(const void **keys, const void **values) const;
+    const void * GetValue(const void *key) const;
+    Boolean GetValueIfPresent(const void *key, const void **value_handle) const;
+    bool    AddValue(CFStringRef key, const void *value, bool can_create = false);
+    bool    SetValue(CFStringRef key, const void *value, bool can_create = false);
+    bool    AddValueSInt8(CFStringRef key, int8_t value, bool can_create = false);
+    bool    SetValueSInt8(CFStringRef key, int8_t value, bool can_create = false);
+    bool    AddValueSInt16(CFStringRef key, int16_t value, bool can_create = false);
+    bool    SetValueSInt16(CFStringRef key, int16_t value, bool can_create = false);
+    bool    AddValueSInt32(CFStringRef key, int32_t value, bool can_create = false);
+    bool    SetValueSInt32(CFStringRef key, int32_t value, bool can_create = false);
+    bool    AddValueSInt64(CFStringRef key, int64_t value, bool can_create = false);
+    bool    SetValueSInt64(CFStringRef key, int64_t value, bool can_create = false);
+    bool    AddValueUInt8(CFStringRef key, uint8_t value, bool can_create = false);
+    bool    SetValueUInt8(CFStringRef key, uint8_t value, bool can_create = false);
+    bool    AddValueUInt16(CFStringRef key, uint16_t value, bool can_create = false);
+    bool    SetValueUInt16(CFStringRef key, uint16_t value, bool can_create = false);
+    bool    AddValueUInt32(CFStringRef key, uint32_t value, bool can_create = false);
+    bool    SetValueUInt32(CFStringRef key, uint32_t value, bool can_create = false);
+    bool    AddValueUInt64(CFStringRef key, uint64_t value, bool can_create = false);
+    bool    SetValueUInt64(CFStringRef key, uint64_t value, bool can_create = false);
+    bool    AddValueCString(CFStringRef key, const char *cstr, bool can_create = false);
+    bool    SetValueCString(CFStringRef key, const char *cstr, bool can_create = false);
+    void    RemoveValue(const void *value);
+    void    ReplaceValue(const void *key, const void *value);
+    void    RemoveAllValues();
+    CFMutableDictionaryRef Dictionary(bool can_create);
+
+
+protected:
+    //------------------------------------------------------------------
+    // Classes that inherit from CFCMutableDictionary can see and modify these
+    //------------------------------------------------------------------
+
+private:
+    //------------------------------------------------------------------
+    // For CFCMutableDictionary only
+    //------------------------------------------------------------------
+
+};
+
+
+#endif  // CoreFoundationCPP_CFMutableDictionary_h_
diff --git a/source/Host/macosx/cfcpp/CFCMutableSet.cpp b/source/Host/macosx/cfcpp/CFCMutableSet.cpp
new file mode 100644
index 0000000..cd25370
--- /dev/null
+++ b/source/Host/macosx/cfcpp/CFCMutableSet.cpp
@@ -0,0 +1,114 @@
+//===-- CFCMutableSet.cpp ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CFCMutableSet.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+//----------------------------------------------------------------------
+// CFCString constructor
+//----------------------------------------------------------------------
+CFCMutableSet::CFCMutableSet(CFMutableSetRef s) :
+    CFCReleaser<CFMutableSetRef> (s)
+{
+}
+
+//----------------------------------------------------------------------
+// CFCMutableSet copy constructor
+//----------------------------------------------------------------------
+CFCMutableSet::CFCMutableSet(const CFCMutableSet& rhs) :
+    CFCReleaser<CFMutableSetRef> (rhs)
+{
+}
+
+//----------------------------------------------------------------------
+// CFCMutableSet copy constructor
+//----------------------------------------------------------------------
+const CFCMutableSet&
+CFCMutableSet::operator=(const CFCMutableSet& rhs)
+{
+    if (this != &rhs)
+        *this = rhs;
+    return *this;
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+CFCMutableSet::~CFCMutableSet()
+{
+}
+
+
+CFIndex
+CFCMutableSet::GetCount() const
+{
+    CFMutableSetRef set = get();
+    if (set)
+        return ::CFSetGetCount (set);
+    return 0;
+}
+
+CFIndex
+CFCMutableSet::GetCountOfValue(const void *value) const
+{
+    CFMutableSetRef set = get();
+    if (set)
+        return ::CFSetGetCountOfValue (set, value);
+    return 0;
+}
+
+const void *
+CFCMutableSet::GetValue(const void *value) const
+{
+    CFMutableSetRef set = get();
+    if (set)
+        return ::CFSetGetValue(set, value);
+    return NULL;
+}
+
+
+const void *
+CFCMutableSet::AddValue(const void *value, bool can_create)
+{
+    CFMutableSetRef set = get();
+    if (set == NULL)
+    {
+        if (can_create == false)
+            return false;
+        set = ::CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks);
+        reset ( set );
+    }
+    if (set != NULL)
+    {
+        ::CFSetAddValue(set, value);
+        return value;
+    }
+    return NULL;
+}
+
+void
+CFCMutableSet::RemoveValue(const void *value)
+{
+    CFMutableSetRef set = get();
+    if (set)
+        ::CFSetRemoveValue(set, value);
+}
+
+void
+CFCMutableSet::RemoveAllValues()
+{
+    CFMutableSetRef set = get();
+    if (set)
+        ::CFSetRemoveAllValues(set);
+}
+
diff --git a/source/Host/macosx/cfcpp/CFCMutableSet.h b/source/Host/macosx/cfcpp/CFCMutableSet.h
new file mode 100644
index 0000000..78f7a8b
--- /dev/null
+++ b/source/Host/macosx/cfcpp/CFCMutableSet.h
@@ -0,0 +1,53 @@
+//===-- CFCMutableSet.h -----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CoreFoundationCPP_CFMutableSet_h_
+#define CoreFoundationCPP_CFMutableSet_h_
+
+#include "CFCReleaser.h"
+
+class CFCMutableSet : public CFCReleaser<CFMutableSetRef>
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    CFCMutableSet(CFMutableSetRef s = NULL);
+    CFCMutableSet(const CFCMutableSet& rhs);
+    virtual ~CFCMutableSet();
+
+    //------------------------------------------------------------------
+    // Operators
+    //------------------------------------------------------------------
+    const CFCMutableSet&
+    operator=(const CFCMutableSet& rhs);
+
+
+    CFIndex GetCount() const;
+    CFIndex GetCountOfValue(const void *value) const;
+    const void * GetValue(const void *value) const;
+    const void * AddValue(const void *value, bool can_create);
+    void RemoveValue(const void *value);
+    void RemoveAllValues();
+
+
+
+protected:
+    //------------------------------------------------------------------
+    // Classes that inherit from CFCMutableSet can see and modify these
+    //------------------------------------------------------------------
+
+private:
+    //------------------------------------------------------------------
+    // For CFCMutableSet only
+    //------------------------------------------------------------------
+
+};
+
+#endif  // CoreFoundationCPP_CFMutableSet_h_
diff --git a/source/Host/macosx/cfcpp/CFCReleaser.h b/source/Host/macosx/cfcpp/CFCReleaser.h
new file mode 100644
index 0000000..cd35de6
--- /dev/null
+++ b/source/Host/macosx/cfcpp/CFCReleaser.h
@@ -0,0 +1,155 @@
+//===-- CFCReleaser.h -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CoreFoundationCPP_CFReleaser_h_
+#define CoreFoundationCPP_CFReleaser_h_
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#ifdef __cplusplus
+
+#include <assert.h>
+
+//----------------------------------------------------------------------
+// Templatized CF helper class that can own any CF pointer and will
+// call CFRelease() on any valid pointer it owns unless that pointer is
+// explicitly released using the release() member function. This class
+// is designed to mimic the std::auto_ptr<T> class and has all of the
+// same functions. The one thing to watch out for is the
+// CFCReleaser<T>::release() function won't actually CFRelease any owned
+// pointer, it is designed to relinquish ownwership of the pointer just
+// like std:auto_ptr<T>::release() does.
+//----------------------------------------------------------------------
+template <class T>
+class CFCReleaser
+{
+public:
+    //----------------------------------------------------------
+    // Constructor that takes a pointer to a CF object that is
+    // to be released when this object goes out of scope
+    //----------------------------------------------------------
+    CFCReleaser(T ptr = NULL) :
+        _ptr(ptr)
+    {
+    }
+
+    //----------------------------------------------------------
+    // Copy constructor
+    //
+    // Note that copying a CFCReleaser will not transfer
+    // ownership of the contained pointer, but it will bump its
+    // reference count. This is where this class differs from
+    // std::auto_ptr.
+    //----------------------------------------------------------
+    CFCReleaser(const CFCReleaser& rhs) :
+        _ptr(rhs.get())
+    {
+        if (get())
+            ::CFRetain(get());
+    }
+
+
+    //----------------------------------------------------------
+    // The destructor will release the pointer that it contains
+    // if it has a valid pointer.
+    //----------------------------------------------------------
+    virtual ~CFCReleaser()
+    {
+        reset();
+    }
+
+    //----------------------------------------------------------
+    // Assignment operator.
+    //
+    // Note that assigning one CFCReleaser to another will
+    // not transfer ownership of the contained pointer, but it
+    // will bump its reference count. This is where this class
+    // differs from std::auto_ptr.
+    //----------------------------------------------------------
+    CFCReleaser&
+    operator= (const CFCReleaser<T>& rhs)
+    {
+        if (this != &rhs)
+        {
+            // Replace our owned pointer with the new one
+            reset(rhs.get());
+            // Retain the current pointer that we own
+            if (get())
+                ::CFRetain(get());
+        }
+        return *this;
+    }
+
+    //----------------------------------------------------------
+    // Get the address of the contained type in case it needs
+    // to be passed to a function that will fill in a pointer
+    // value. The function currently will assert if _ptr is not
+    // NULL because the only time this method should be used is
+    // if another function will modify the contents, and we
+    // could leak a pointer if this is not NULL. If the
+    // assertion fires, check the offending code, or call
+    // reset() prior to using the "ptr_address()" member to make
+    // sure any owned objects has CFRelease called on it.
+    //----------------------------------------------------------
+    T*
+    ptr_address()
+    {
+        assert (_ptr == NULL);
+        return &_ptr;
+    }
+
+    //----------------------------------------------------------
+    // Access the pointer itself
+    //----------------------------------------------------------
+    T
+    get()
+    {
+        return _ptr;
+    }
+
+    const T
+    get() const
+    {
+        return _ptr;
+    }
+
+
+    //----------------------------------------------------------
+    // Set a new value for the pointer and CFRelease our old
+    // value if we had a valid one.
+    //----------------------------------------------------------
+    void
+    reset(T ptr = NULL)
+    {
+        if ((_ptr != NULL) && (ptr != _ptr))
+            ::CFRelease(_ptr);
+        _ptr = ptr;
+    }
+
+    //----------------------------------------------------------
+    // Release ownership without calling CFRelease. This class
+    // is designed to mimic std::auto_ptr<T>, so the release
+    // method releases ownership of the contained pointer
+    // and does NOT call CFRelease.
+    //----------------------------------------------------------
+    T
+    release()
+    {
+        T tmp = _ptr;
+        _ptr = NULL;
+        return tmp;
+    }
+
+private:
+    T _ptr;
+};
+
+#endif  // #ifdef __cplusplus
+#endif  // #ifndef CoreFoundationCPP_CFReleaser_h_
+
diff --git a/source/Host/macosx/cfcpp/CFCString.cpp b/source/Host/macosx/cfcpp/CFCString.cpp
new file mode 100644
index 0000000..81a96b8
--- /dev/null
+++ b/source/Host/macosx/cfcpp/CFCString.cpp
@@ -0,0 +1,195 @@
+//===-- CFCString.cpp -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CFCString.h"
+#include <string>
+#include <glob.h>
+
+//----------------------------------------------------------------------
+// CFCString constructor
+//----------------------------------------------------------------------
+CFCString::CFCString(CFStringRef s) :
+    CFCReleaser<CFStringRef> (s)
+{
+}
+
+//----------------------------------------------------------------------
+// CFCString copy constructor
+//----------------------------------------------------------------------
+CFCString::CFCString(const CFCString& rhs) :
+    CFCReleaser<CFStringRef> (rhs)
+{
+
+}
+
+//----------------------------------------------------------------------
+// CFCString copy constructor
+//----------------------------------------------------------------------
+CFCString&
+CFCString::operator=(const CFCString& rhs)
+{
+    if (this != &rhs)
+        *this = rhs;
+    return *this;
+}
+
+CFCString::CFCString (const char *cstr, CFStringEncoding cstr_encoding) :
+    CFCReleaser<CFStringRef> ()
+{
+    if (cstr && cstr[0])
+    {
+        reset(::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding));
+    }
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+CFCString::~CFCString()
+{
+}
+
+const char *
+CFCString::GetFileSystemRepresentation(std::string& s)
+{
+    return CFCString::FileSystemRepresentation(get(), s);
+}
+
+CFStringRef
+CFCString::SetFileSystemRepresentation (const char *path)
+{
+    CFStringRef new_value = NULL;
+    if (path && path[0])
+        new_value = ::CFStringCreateWithFileSystemRepresentation (kCFAllocatorDefault, path);
+    reset(new_value);
+    return get();
+}
+
+
+CFStringRef
+CFCString::SetFileSystemRepresentationFromCFType (CFTypeRef cf_type)
+{
+    CFStringRef new_value = NULL;
+    if (cf_type != NULL)
+    {
+        CFTypeID cf_type_id = ::CFGetTypeID(cf_type);
+
+        if (cf_type_id == ::CFStringGetTypeID())
+        {
+            // Retain since we are using the existing object
+            new_value = (CFStringRef)::CFRetain(cf_type);
+        }
+        else if (cf_type_id == ::CFURLGetTypeID())
+        {
+            new_value = ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle);
+        }
+    }
+    reset(new_value);
+    return get();
+}
+
+CFStringRef
+CFCString::SetFileSystemRepresentationAndExpandTilde (const char *path)
+{
+    std::string expanded_path;
+    if (CFCString::ExpandTildeInPath(path, expanded_path))
+        SetFileSystemRepresentation(expanded_path.c_str());
+    else
+        reset();
+    return get();
+}
+
+const char *
+CFCString::UTF8(std::string& str)
+{
+    return CFCString::UTF8(get(), str);
+}
+
+// Static function that puts a copy of the UTF8 contents of CF_STR into STR
+// and returns the C string pointer that is contained in STR when successful, else
+// NULL is returned. This allows the std::string parameter to own the extracted string,
+// and also allows that string to be returned as a C string pointer that can be used.
+
+const char *
+CFCString::UTF8 (CFStringRef cf_str, std::string& str)
+{
+    if (cf_str)
+    {
+        const CFStringEncoding encoding = kCFStringEncodingUTF8;
+        CFIndex max_utf8_str_len = CFStringGetLength (cf_str);
+        max_utf8_str_len = CFStringGetMaximumSizeForEncoding (max_utf8_str_len, encoding);
+        if (max_utf8_str_len > 0)
+        {
+            str.resize(max_utf8_str_len);
+            if (!str.empty())
+            {
+                if (CFStringGetCString (cf_str, &str[0], str.size(), encoding))
+                {
+                    str.resize(strlen(str.c_str()));
+                    return str.c_str();
+                }
+            }
+        }
+    }
+    return NULL;
+}
+
+const char*
+CFCString::ExpandTildeInPath(const char* path, std::string &expanded_path)
+{
+    glob_t globbuf;
+    if (::glob (path, GLOB_TILDE, NULL, &globbuf) == 0)
+    {
+        expanded_path = globbuf.gl_pathv[0];
+        ::globfree (&globbuf);
+    }
+    else
+        expanded_path.clear();
+
+    return expanded_path.c_str();
+}
+
+// Static function that puts a copy of the file system representation of CF_STR
+// into STR and returns the C string pointer that is contained in STR when
+// successful, else NULL is returned. This allows the std::string parameter
+// to own the extracted string, and also allows that string to be returned as
+// a C string pointer that can be used.
+
+const char *
+CFCString::FileSystemRepresentation (CFStringRef cf_str, std::string& str)
+{
+    if (cf_str)
+    {
+        CFIndex max_length = ::CFStringGetMaximumSizeOfFileSystemRepresentation (cf_str);
+        if (max_length > 0)
+        {
+            str.resize(max_length);
+            if (!str.empty())
+            {
+                if (::CFStringGetFileSystemRepresentation (cf_str, &str[0], str.size()))
+                {
+                    str.erase(::strlen(str.c_str()));
+                    return str.c_str();
+                }
+            }
+        }
+    }
+    str.erase();
+    return NULL;
+}
+
+
+CFIndex
+CFCString::GetLength() const
+{
+    CFStringRef str = get();
+    if (str)
+        return CFStringGetLength (str);
+    return 0;
+}
diff --git a/source/Host/macosx/cfcpp/CFCString.h b/source/Host/macosx/cfcpp/CFCString.h
new file mode 100644
index 0000000..521d2c0
--- /dev/null
+++ b/source/Host/macosx/cfcpp/CFCString.h
@@ -0,0 +1,41 @@
+//===-- CFCString.h ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CoreFoundationCPP_CFString_h_
+#define CoreFoundationCPP_CFString_h_
+
+#include <iosfwd>
+
+#include "CFCReleaser.h"
+
+class CFCString : public CFCReleaser<CFStringRef>
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+                        CFCString (CFStringRef cf_str = NULL);
+                        CFCString (const char *s, CFStringEncoding encoding);
+                        CFCString (const CFCString& rhs);
+                        CFCString& operator= (const CFCString& rhs);
+                        virtual ~CFCString ();
+
+        const char *    GetFileSystemRepresentation (std::string& str);
+        CFStringRef     SetFileSystemRepresentation (const char *path);
+        CFStringRef     SetFileSystemRepresentationFromCFType (CFTypeRef cf_type);
+        CFStringRef     SetFileSystemRepresentationAndExpandTilde (const char *path);
+        const char *    UTF8 (std::string& str);
+        CFIndex         GetLength() const;
+        static const char *UTF8 (CFStringRef cf_str, std::string& str);
+        static const char *FileSystemRepresentation (CFStringRef cf_str, std::string& str);
+        static const char *ExpandTildeInPath(const char* path, std::string &expanded_path);
+
+};
+
+#endif // #ifndef CoreFoundationCPP_CFString_h_
diff --git a/source/Host/macosx/cfcpp/CoreFoundationCPP.h b/source/Host/macosx/cfcpp/CoreFoundationCPP.h
new file mode 100644
index 0000000..6843e26
--- /dev/null
+++ b/source/Host/macosx/cfcpp/CoreFoundationCPP.h
@@ -0,0 +1,30 @@
+//===-- CoreFoundationCPP.h -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//----------------------------------------------------------------------
+//
+//  CoreFoundationCPP.h
+//  CoreFoundationCPP
+//
+//  Created by Greg Clayton on 4/23/09.
+//
+//
+//----------------------------------------------------------------------
+
+#ifndef CoreFoundationCPP_CoreFoundationCPP_H_
+#define CoreFoundationCPP_CoreFoundationCPP_H_
+
+#include <CoreFoundationCPP/CFCBundle.h>
+#include <CoreFoundationCPP/CFCData.h>
+#include <CoreFoundationCPP/CFCReleaser.h>
+#include <CoreFoundationCPP/CFCMutableArray.h>
+#include <CoreFoundationCPP/CFCMutableDictionary.h>
+#include <CoreFoundationCPP/CFCMutableSet.h>
+#include <CoreFoundationCPP/CFCString.h>
+
+#endif  // CoreFoundationCPP_CoreFoundationCPP_H_
diff --git a/source/Interpreter/CommandCompletions.cpp b/source/Interpreter/CommandCompletions.cpp
new file mode 100644
index 0000000..a299ffb
--- /dev/null
+++ b/source/Interpreter/CommandCompletions.cpp
@@ -0,0 +1,414 @@
+//===-- CommandCompletions.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
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Core/FileSpecList.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Interpreter/CommandCompletions.h"
+
+
+using namespace lldb_private;
+
+CommandCompletions::CommonCompletionElement
+CommandCompletions::g_common_completions[] =
+{
+    {eCustomCompletion,     NULL},
+    {eSourceFileCompletion, CommandCompletions::SourceFiles},
+    {eDiskFileCompletion,   NULL},
+    {eSymbolCompletion,     CommandCompletions::Symbols},
+    {eModuleCompletion,     CommandCompletions::Modules},
+    {eNoCompletion,         NULL}      // This one has to be last in the list.
+};
+
+bool
+CommandCompletions::InvokeCommonCompletionCallbacks (uint32_t completion_mask,
+                                                const char *completion_str,
+                                                int match_start_point,
+                                                int max_return_elements,
+                                                lldb_private::CommandInterpreter *interpreter,
+                                                SearchFilter *searcher,
+                                                lldb_private::StringList &matches)
+{
+    bool handled = false;
+
+    if (completion_mask & eCustomCompletion)
+        return false;
+
+    for (int i = 0; ; i++)
+    {
+        if (g_common_completions[i].type == eNoCompletion)
+            break;
+         else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type
+                   && g_common_completions[i].callback != NULL)
+         {
+            handled = true;
+            g_common_completions[i].callback (completion_str,
+                                              match_start_point,
+                                              max_return_elements,
+                                              interpreter,
+                                              searcher,
+                                              matches);
+        }
+    }
+    return handled;
+}
+
+int
+CommandCompletions::SourceFiles (const char *partial_file_name,
+                    int match_start_point,
+                    int max_return_elements,
+                    lldb_private::CommandInterpreter *interpreter,
+                    SearchFilter *searcher,
+                    lldb_private::StringList &matches)
+{
+    // Find some way to switch "include support files..."
+    SourceFileCompleter completer (false, partial_file_name, match_start_point, max_return_elements, interpreter,
+                                   matches);
+
+    if (searcher == NULL)
+    {
+        lldb::TargetSP target_sp = interpreter->Context()->GetTarget()->GetSP();
+        SearchFilter null_searcher (target_sp);
+        completer.DoCompletion (&null_searcher);
+    }
+    else
+    {
+        completer.DoCompletion (searcher);
+    }
+    return matches.GetSize();
+}
+
+int
+CommandCompletions::Modules (const char *partial_file_name,
+                    int match_start_point,
+                    int max_return_elements,
+                    lldb_private::CommandInterpreter *interpreter,
+                    SearchFilter *searcher,
+                    lldb_private::StringList &matches)
+{
+    ModuleCompleter completer(partial_file_name, match_start_point, max_return_elements, interpreter, matches);
+
+    if (searcher == NULL)
+    {
+        lldb::TargetSP target_sp = interpreter->Context()->GetTarget()->GetSP();
+        SearchFilter null_searcher (target_sp);
+        completer.DoCompletion (&null_searcher);
+    }
+    else
+    {
+        completer.DoCompletion (searcher);
+    }
+    return matches.GetSize();
+}
+
+int
+CommandCompletions::Symbols (const char *partial_file_name,
+                    int match_start_point,
+                    int max_return_elements,
+                    lldb_private::CommandInterpreter *interpreter,
+                    SearchFilter *searcher,
+                    lldb_private::StringList &matches)
+{
+    SymbolCompleter completer(partial_file_name, match_start_point, max_return_elements, interpreter, matches);
+
+    if (searcher == NULL)
+    {
+        lldb::TargetSP target_sp = interpreter->Context()->GetTarget()->GetSP();
+        SearchFilter null_searcher (target_sp);
+        completer.DoCompletion (&null_searcher);
+    }
+    else
+    {
+        completer.DoCompletion (searcher);
+    }
+    return matches.GetSize();
+}
+
+CommandCompletions::Completer::Completer (
+    const char *completion_str,
+    int match_start_point,
+    int max_return_elements,
+    CommandInterpreter *interpreter,
+    StringList &matches
+) :
+    m_completion_str (completion_str),
+    m_match_start_point (match_start_point),
+    m_max_return_elements (max_return_elements),
+    m_interpreter (interpreter),
+    m_matches (matches)
+{
+}
+
+CommandCompletions::Completer::~Completer ()
+{
+
+}
+
+//----------------------------------------------------------------------
+// SourceFileCompleter
+//----------------------------------------------------------------------
+
+CommandCompletions::SourceFileCompleter::SourceFileCompleter (
+    bool include_support_files,
+    const char *completion_str,
+    int match_start_point,
+    int max_return_elements,
+    CommandInterpreter *interpreter,
+    StringList &matches
+) :
+    CommandCompletions::Completer (completion_str, match_start_point, max_return_elements, interpreter, matches),
+    m_include_support_files (include_support_files),
+    m_matching_files()
+{
+    FileSpec partial_spec (m_completion_str.c_str());
+    m_file_name = partial_spec.GetFilename().GetCString();
+    m_dir_name = partial_spec.GetDirectory().GetCString();
+}
+
+Searcher::Depth
+CommandCompletions::SourceFileCompleter::GetDepth()
+{
+    return eDepthCompUnit;
+}
+
+Searcher::CallbackReturn
+CommandCompletions::SourceFileCompleter::SearchCallback (
+    SearchFilter &filter,
+    SymbolContext &context,
+    Address *addr,
+    bool complete
+)
+{
+    if (context.comp_unit != NULL)
+    {
+        if (m_include_support_files)
+        {
+            FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
+            for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++)
+            {
+                const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles);
+                const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
+                const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
+                bool match = false;
+                if (m_file_name && sfile_file_name
+                    && strstr (sfile_file_name, m_file_name) == sfile_file_name)
+                    match = true;
+                if (match && m_dir_name && sfile_dir_name
+                    && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name)
+                    match = false;
+
+                if (match)
+                {
+                    m_matching_files.AppendIfUnique(sfile_spec);
+                }
+            }
+
+        }
+        else
+        {
+            const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
+            const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
+
+            bool match = false;
+            if (m_file_name && cur_file_name
+                && strstr (cur_file_name, m_file_name) == cur_file_name)
+                match = true;
+
+            if (match && m_dir_name && cur_dir_name
+                && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
+                match = false;
+
+            if (match)
+            {
+                m_matching_files.AppendIfUnique(context.comp_unit);
+            }
+        }
+    }
+    return Searcher::eCallbackReturnContinue;
+}
+
+size_t
+CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter)
+{
+    filter->Search (*this);
+    // Now convert the filelist to completions:
+    for (size_t i = 0; i < m_matching_files.GetSize(); i++)
+    {
+        m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
+    }
+    return m_matches.GetSize();
+
+}
+
+//----------------------------------------------------------------------
+// SymbolCompleter
+//----------------------------------------------------------------------
+
+static bool
+regex_chars (const char comp)
+{
+    if (comp == '[' || comp == ']' || comp == '(' || comp == ')')
+        return true;
+    else
+        return false;
+}
+CommandCompletions::SymbolCompleter::SymbolCompleter (
+    const char *completion_str,
+    int match_start_point,
+    int max_return_elements,
+    CommandInterpreter *interpreter,
+    StringList &matches
+) :
+    CommandCompletions::Completer (completion_str, match_start_point, max_return_elements, interpreter, matches)
+{
+    std::string regex_str ("^");
+    regex_str.append(completion_str);
+    regex_str.append(".*");
+    std::string::iterator pos;
+
+    pos = find_if(regex_str.begin(), regex_str.end(), regex_chars);
+    while (pos < regex_str.end()) {
+        pos = regex_str.insert(pos, '\\');
+        pos += 2;
+        pos = find_if(pos, regex_str.end(), regex_chars);
+    }
+    m_regex.Compile(regex_str.c_str());
+}
+
+Searcher::Depth
+CommandCompletions::SymbolCompleter::GetDepth()
+{
+    return eDepthModule;
+}
+
+Searcher::CallbackReturn
+CommandCompletions::SymbolCompleter::SearchCallback (
+    SearchFilter &filter,
+    SymbolContext &context,
+    Address *addr,
+    bool complete
+)
+{
+    SymbolContextList func_list;
+    SymbolContextList sym_list;
+
+    if (context.module_sp != NULL)
+    {
+        if (context.module_sp)
+        {
+            context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, lldb::eSymbolTypeCode, sym_list);
+            context.module_sp->FindFunctions (m_regex, true, func_list);
+        }
+
+        SymbolContext sc;
+        // Now add the functions & symbols to the list - only add if unique:
+        for (int i = 0; i < func_list.GetSize(); i++)
+        {
+            if (func_list.GetContextAtIndex(i, sc))
+            {
+                if (sc.function)
+                {
+                    m_match_set.insert (sc.function->GetMangled().GetDemangledName());
+                }
+            }
+        }
+
+        for (int i = 0; i < sym_list.GetSize(); i++)
+        {
+            if (sym_list.GetContextAtIndex(i, sc))
+            {
+                if (sc.symbol && sc.symbol->GetAddressRangePtr())
+                {
+                    m_match_set.insert (sc.symbol->GetMangled().GetDemangledName());
+                }
+            }
+        }
+    }
+    return Searcher::eCallbackReturnContinue;
+}
+
+size_t
+CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter)
+{
+    filter->Search (*this);
+    collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
+    for (pos = m_match_set.begin(); pos != end; pos++)
+        m_matches.AppendString((*pos).GetCString());
+
+    return m_matches.GetSize();
+}
+
+//----------------------------------------------------------------------
+// ModuleCompleter
+//----------------------------------------------------------------------
+CommandCompletions::ModuleCompleter::ModuleCompleter (
+    const char *completion_str,
+    int match_start_point,
+    int max_return_elements,
+    CommandInterpreter *interpreter,
+    StringList &matches
+) :
+    CommandCompletions::Completer (completion_str, match_start_point, max_return_elements, interpreter, matches)
+{
+    FileSpec partial_spec (m_completion_str.c_str());
+    m_file_name = partial_spec.GetFilename().GetCString();
+    m_dir_name = partial_spec.GetDirectory().GetCString();
+}
+
+Searcher::Depth
+CommandCompletions::ModuleCompleter::GetDepth()
+{
+    return eDepthModule;
+}
+
+Searcher::CallbackReturn
+CommandCompletions::ModuleCompleter::SearchCallback (
+    SearchFilter &filter,
+    SymbolContext &context,
+    Address *addr,
+    bool complete
+)
+{
+    if (context.module_sp != NULL)
+    {
+        const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString();
+        const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString();
+
+        bool match = false;
+        if (m_file_name && cur_file_name
+            && strstr (cur_file_name, m_file_name) == cur_file_name)
+            match = true;
+
+        if (match && m_dir_name && cur_dir_name
+            && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
+            match = false;
+
+        if (match)
+        {
+            m_matches.AppendString (cur_file_name);
+        }
+    }
+    return Searcher::eCallbackReturnContinue;
+}
+
+size_t
+CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter)
+{
+    filter->Search (*this);
+    return m_matches.GetSize();
+}
+
+
+
diff --git a/source/Interpreter/CommandContext.cpp b/source/Interpreter/CommandContext.cpp
new file mode 100644
index 0000000..012611c
--- /dev/null
+++ b/source/Interpreter/CommandContext.cpp
@@ -0,0 +1,77 @@
+//===-- CommandContext.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Interpreter/CommandContext.h"
+
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+CommandContext::CommandContext () :
+    m_exe_ctx ()
+{
+}
+
+CommandContext::~CommandContext ()
+{
+}
+
+Target *
+CommandContext::GetTarget()
+{
+    return Debugger::GetSharedInstance().GetCurrentTarget().get();
+}
+
+
+ExecutionContext &
+CommandContext::GetExecutionContext()
+{
+    return m_exe_ctx;
+}
+
+void
+CommandContext::Update (ExecutionContext *override_context)
+{
+    m_exe_ctx.Clear();
+
+    if (override_context != NULL)
+    {
+        m_exe_ctx.target = override_context->target;
+        m_exe_ctx.process = override_context->process;
+        m_exe_ctx.thread = override_context->thread;
+        m_exe_ctx.frame = override_context->frame;
+    }
+    else
+    {
+        TargetSP target_sp (Debugger::GetSharedInstance().GetCurrentTarget());
+        if (target_sp)
+        {
+            m_exe_ctx.process = target_sp->GetProcessSP().get();
+            if (m_exe_ctx.process && m_exe_ctx.process->IsRunning() == false)
+            {
+                m_exe_ctx.thread = m_exe_ctx.process->GetThreadList().GetCurrentThread().get();
+                if (m_exe_ctx.thread == NULL)
+                    m_exe_ctx.thread = m_exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
+                if (m_exe_ctx.thread)
+                {
+                    m_exe_ctx.frame = m_exe_ctx.thread->GetCurrentFrame().get();
+                    if (m_exe_ctx.frame == NULL)
+                        m_exe_ctx.frame = m_exe_ctx.thread->GetStackFrameAtIndex (0).get();
+                }
+            }
+        }
+    }
+}
diff --git a/source/Interpreter/CommandInterpreter.cpp b/source/Interpreter/CommandInterpreter.cpp
new file mode 100644
index 0000000..ed85b33
--- /dev/null
+++ b/source/Interpreter/CommandInterpreter.cpp
@@ -0,0 +1,1300 @@
+//===-- CommandInterpreter.cpp ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string>
+
+#include <getopt.h>
+#include <stdlib.h>
+
+#include "CommandObjectAdd.h"
+#include "CommandObjectAlias.h"
+#include "CommandObjectAppend.h"
+#include "CommandObjectApropos.h"
+#include "CommandObjectArgs.h"
+#include "CommandObjectBreakpoint.h"
+#include "CommandObjectCall.h"
+#include "CommandObjectDelete.h"
+#include "CommandObjectDisassemble.h"
+#include "CommandObjectExpression.h"
+#include "CommandObjectFile.h"
+#include "CommandObjectFrame.h"
+#include "CommandObjectHelp.h"
+#include "CommandObjectImage.h"
+#include "CommandObjectInfo.h"
+#include "CommandObjectLog.h"
+#include "CommandObjectMemory.h"
+#include "CommandObjectProcess.h"
+#include "CommandObjectQuit.h"
+#include "CommandObjectRegexCommand.h"
+#include "CommandObjectRegister.h"
+#include "CommandObjectRemove.h"
+#include "CommandObjectScript.h"
+#include "CommandObjectSelect.h"
+#include "CommandObjectSet.h"
+#include "CommandObjectSettings.h"
+#include "CommandObjectShow.h"
+#include "CommandObjectSource.h"
+#include "CommandObjectSourceFile.h"
+#include "CommandObjectStatus.h"
+#include "CommandObjectSyntax.h"
+#include "CommandObjectTarget.h"
+#include "CommandObjectThread.h"
+#include "CommandObjectTranslate.h"
+#include "CommandObjectUnalias.h"
+#include "CommandObjectVariable.h"
+
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/TargetList.h"
+
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+CommandInterpreter::CommandInterpreter
+(
+    ScriptLanguage script_language,
+    bool synchronous_execution,
+    Listener *listener,
+    SourceManager& source_manager
+) :
+    Broadcaster ("CommandInterpreter"),
+    m_script_language (script_language),
+    m_synchronous_execution (synchronous_execution),
+    m_listener (listener),
+    m_source_manager (source_manager)
+{
+}
+
+void
+CommandInterpreter::Initialize ()
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+
+    CommandReturnObject result;
+
+    LoadCommandDictionary ();
+
+    InitializeVariables ();
+
+    // Set up some initial aliases.
+    result.Clear(); HandleCommand ("alias q        quit", false, result);
+    result.Clear(); HandleCommand ("alias run      process launch", false, result);
+    result.Clear(); HandleCommand ("alias r        process launch", false, result);
+    result.Clear(); HandleCommand ("alias c        process continue", false, result);
+    result.Clear(); HandleCommand ("alias continue process continue", false, result);
+    result.Clear(); HandleCommand ("alias expr     expression", false, result);
+    result.Clear(); HandleCommand ("alias exit     quit", false, result);
+    result.Clear(); HandleCommand ("alias bt       thread backtrace", false, result);
+    result.Clear(); HandleCommand ("alias si       thread step-inst", false, result);
+    result.Clear(); HandleCommand ("alias step     thread step-in", false, result);
+    result.Clear(); HandleCommand ("alias s        thread step-in", false, result);
+    result.Clear(); HandleCommand ("alias next     thread step-over", false, result);
+    result.Clear(); HandleCommand ("alias n        thread step-over", false, result);
+    result.Clear(); HandleCommand ("alias finish   thread step-out", false, result);
+    result.Clear(); HandleCommand ("alias x        memory read", false, result);
+    result.Clear(); HandleCommand ("alias l        source-file", false, result);
+    result.Clear(); HandleCommand ("alias list     source-file", false, result);
+}
+
+void
+CommandInterpreter::InitializeVariables ()
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+
+    m_variables["prompt"] =
+            StateVariableSP (new StateVariable ("prompt",
+                                                "(lldb) ",
+                                                false,
+                                                "The debugger prompt displayed for the user.",
+                                                StateVariable::BroadcastPromptChange));
+
+    m_variables["run-args"] =
+            StateVariableSP (new StateVariable ("run-args",
+                                                (Args*)NULL,
+                                                "An argument list containing the arguments to be passed to the executable when it is launched."));
+
+
+    m_variables["env-vars"] =
+            StateVariableSP (new StateVariable ("env-vars",
+                                                (Args*)NULL,
+                                                "A list of strings containing the environment variables to be passed to the executable's environment."));
+
+    m_variables["input-path"] =
+            StateVariableSP (new StateVariable ("input-path",
+                                                "/dev/stdin",
+                                                false,
+                                                "The file/path to be used by the executable program for reading its input."));
+
+    m_variables["output-path"] =
+            StateVariableSP (new StateVariable ( "output-path",
+                                                "/dev/stdout",
+                                                false,
+                                                "The file/path to be used by the executable program for writing its output."));
+
+    m_variables["error-path"] =
+            StateVariableSP (new StateVariable ("error-path",
+                                                "/dev/stderr",
+                                                false,
+                                                "The file/path to be used by the executable program for writing its error messages."));
+
+    m_variables["arch"] =
+        StateVariableSP (new StateVariable ("arch",
+                                            "",
+                                            false,
+                                            "The architecture to be used for running the executable (e.g. i386, x86_64, etc)."));
+
+    m_variables["script-lang"] =
+        StateVariableSP (new StateVariable ("script-lang",
+                                            "Python",
+                                            false,
+                                            "The script language to be used for evaluating user-written scripts.",
+                                            StateVariable::VerifyScriptLanguage));
+
+    m_variables["term-width"] =
+    StateVariableSP (new StateVariable ("term-width",
+                                         80,
+                                        "The maximum number of columns to use for displaying text."));
+    
+}
+
+const char *
+CommandInterpreter::ProcessEmbeddedScriptCommands (const char *arg)
+{
+    // This function has not yet been implemented.
+
+    // Look for any embedded script command
+    // If found,
+    //    get interpreter object from the command dictionary,
+    //    call execute_one_command on it,
+    //    get the results as a string,
+    //    substitute that string for current stuff.
+
+    return arg;
+}
+
+
+void
+CommandInterpreter::LoadCommandDictionary ()
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+
+    // **** IMPORTANT **** IMPORTANT *** IMPORTANT *** **** IMPORTANT **** IMPORTANT *** IMPORTANT ***
+    //
+    // Command objects that are used as cross reference objects (i.e. they inherit from CommandObjectCrossref)
+    // *MUST* be created and put into the command dictionary *BEFORE* any multi-word commands (which may use
+    // the cross-referencing stuff) are created!!!
+    //
+    // **** IMPORTANT **** IMPORTANT *** IMPORTANT *** **** IMPORTANT **** IMPORTANT *** IMPORTANT ***
+
+
+    // Command objects that inherit from CommandObjectCrossref must be created before other command objects
+    // are created.  This is so that when another command is created that needs to go into a crossref object,
+    // the crossref object exists and is ready to take the cross reference. Put the cross referencing command
+    // objects into the CommandDictionary now, so they are ready for use when the other commands get created.
+
+    m_command_dict["select"] = CommandObjectSP (new CommandObjectSelect ());
+    m_command_dict["info"] = CommandObjectSP (new CommandObjectInfo ());
+    m_command_dict["delete"] = CommandObjectSP (new CommandObjectDelete ());
+
+    // Non-CommandObjectCrossref commands can now be created.
+
+    //m_command_dict["add"]       = CommandObjectSP (new CommandObjectAdd ());
+    m_command_dict["alias"]     = CommandObjectSP (new CommandObjectAlias ());
+    m_command_dict["append"]    = CommandObjectSP (new CommandObjectAppend ());
+    m_command_dict["apropos"]   = CommandObjectSP (new CommandObjectApropos ());
+    //m_command_dict["args"]      = CommandObjectSP (new CommandObjectArgs ());
+    m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (this));
+    m_command_dict["call"]      = CommandObjectSP (new CommandObjectCall ());
+    m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble ());
+    m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression ());
+    m_command_dict["file"]      = CommandObjectSP (new CommandObjectFile ());
+    m_command_dict["frame"]     = CommandObjectSP (new CommandObjectMultiwordFrame (this));
+    m_command_dict["help"]      = CommandObjectSP (new CommandObjectHelp ());
+    m_command_dict["image"]     = CommandObjectSP (new CommandObjectImage (this));
+    m_command_dict["log"]       = CommandObjectSP (new CommandObjectLog (this));
+    m_command_dict["memory"]    = CommandObjectSP (new CommandObjectMemory (this));
+    m_command_dict["process"]   = CommandObjectSP (new CommandObjectMultiwordProcess (this));
+    m_command_dict["quit"]      = CommandObjectSP (new CommandObjectQuit ());
+    m_command_dict["register"]  = CommandObjectSP (new CommandObjectRegister (this));
+    //m_command_dict["remove"]    = CommandObjectSP (new CommandObjectRemove ());
+    m_command_dict["script"]    = CommandObjectSP (new CommandObjectScript (m_script_language));
+    m_command_dict["set"]       = CommandObjectSP (new CommandObjectSet ());
+    m_command_dict["settings"]  = CommandObjectSP (new CommandObjectSettings ());
+    m_command_dict["show"]      = CommandObjectSP (new CommandObjectShow ());
+    m_command_dict["source"]    = CommandObjectSP (new CommandObjectSource ());
+    m_command_dict["source-file"] = CommandObjectSP (new CommandObjectSourceFile ());
+    //m_command_dict["syntax"]    = CommandObjectSP (new CommandObjectSyntax ());
+    m_command_dict["status"]    = CommandObjectSP (new CommandObjectStatus ());
+    m_command_dict["target"]    = CommandObjectSP (new CommandObjectMultiwordTarget (this));
+    m_command_dict["thread"]    = CommandObjectSP (new CommandObjectMultiwordThread (this));
+    //m_command_dict["translate"] = CommandObjectSP (new CommandObjectTranslate ());
+    m_command_dict["unalias"]   = CommandObjectSP (new CommandObjectUnalias ());
+    m_command_dict["variable"]  = CommandObjectSP (new CommandObjectVariable (this));
+
+    std::auto_ptr<CommandObjectRegexCommand>
+    break_regex_cmd_ap(new CommandObjectRegexCommand ("regexp-break",
+                                                      "Smart breakpoint command (using regular expressions).",
+                                                      "regexp-break [<file>:<line>]\nregexp-break [<address>]\nregexp-break <...>", 2));
+    if (break_regex_cmd_ap.get())
+    {
+        if (break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2") &&
+            break_regex_cmd_ap->AddRegexCommand("^(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1") &&
+            break_regex_cmd_ap->AddRegexCommand("^[\"']?([-+]\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'") &&
+            break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list") &&
+            break_regex_cmd_ap->AddRegexCommand("^(-.*)$", "breakpoint set %1") &&
+            break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1'"))
+        {
+            CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release());
+            m_command_dict[break_regex_cmd_sp->GetCommandName ()] = break_regex_cmd_sp;
+        }
+    }
+}
+
+int
+CommandInterpreter::GetCommandNamesMatchingPartialString (const char *cmd_str, bool include_aliases,
+                                                          StringList &matches)
+{
+    CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_str, matches);
+
+    if (include_aliases)
+    {
+        CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_str, matches);
+    }
+
+    return matches.GetSize();
+}
+
+CommandObjectSP
+CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches)
+{
+    CommandObject::CommandMap::iterator pos;
+    CommandObjectSP ret_val;
+
+    std::string cmd(cmd_cstr);
+
+    if (HasCommands())
+    {
+        pos = m_command_dict.find(cmd);
+        if (pos != m_command_dict.end())
+            ret_val = pos->second;
+    }
+
+    if (include_aliases && HasAliases())
+    {
+        pos = m_alias_dict.find(cmd);
+        if (pos != m_alias_dict.end())
+            ret_val = pos->second;
+    }
+
+    if (HasUserCommands())
+    {
+        pos = m_user_dict.find(cmd);
+        if (pos != m_user_dict.end())
+            ret_val = pos->second;
+    }
+
+    if (!exact && ret_val == NULL)
+    {
+        StringList local_matches;
+        if (matches == NULL)
+            matches = &local_matches;
+
+        int num_cmd_matches = 0;
+        int num_alias_matches = 0;
+        int num_user_matches = 0;
+        if (HasCommands())
+        {
+            num_cmd_matches = CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches);
+        }
+
+        if (num_cmd_matches == 1)
+        {
+            cmd.assign(matches->GetStringAtIndex(0));
+            pos = m_command_dict.find(cmd);
+            if (pos != m_command_dict.end())
+                ret_val = pos->second;
+        }
+
+        if (num_cmd_matches != 1 && include_aliases && HasAliases())
+        {
+            num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_cstr, *matches);
+
+        }
+
+        if (num_alias_matches == 1)
+        {
+            cmd.assign(matches->GetStringAtIndex (num_cmd_matches));
+            pos = m_alias_dict.find(cmd);
+            if (pos != m_alias_dict.end())
+            {
+                matches->Clear();
+                matches->AppendString (cmd.c_str());
+
+                ret_val = pos->second;
+            }
+        }
+
+        if (num_cmd_matches != 1 && num_alias_matches != 1 && HasUserCommands())
+        {
+            num_user_matches = CommandObject::AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches);
+        }
+
+        if (num_user_matches == 1)
+        {
+            cmd.assign (matches->GetStringAtIndex (num_cmd_matches + num_alias_matches));
+
+            pos = m_user_dict.find (cmd);
+            if (pos != m_user_dict.end())
+            {
+                matches->Clear();
+                matches->AppendString (cmd.c_str());
+
+                ret_val = pos->second;
+            }
+        }
+    }
+    else {
+        if (matches)
+            matches->AppendString (cmd_cstr);
+    }
+
+
+    return ret_val;
+}
+
+CommandObject *
+CommandInterpreter::GetCommandObject (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches)
+{
+    return GetCommandSP (cmd_cstr, include_aliases, exact, matches).get();
+}
+
+bool
+CommandInterpreter::CommandExists (const char *cmd)
+{
+    return m_command_dict.find(cmd) != m_command_dict.end();
+}
+
+bool
+CommandInterpreter::AliasExists (const char *cmd)
+{
+    return m_alias_dict.find(cmd) != m_alias_dict.end();
+}
+
+bool
+CommandInterpreter::UserCommandExists (const char *cmd)
+{
+    return m_user_dict.find(cmd) != m_user_dict.end();
+}
+
+void
+CommandInterpreter::AddAlias (const char *alias_name, CommandObjectSP& command_obj_sp)
+{
+    m_alias_dict[alias_name] = command_obj_sp;
+}
+
+bool
+CommandInterpreter::RemoveAlias (const char *alias_name)
+{
+    CommandObject::CommandMap::iterator pos = m_alias_dict.find(alias_name);
+    if (pos != m_alias_dict.end())
+    {
+        m_alias_dict.erase(pos);
+        return true;
+    }
+    return false;
+}
+bool
+CommandInterpreter::RemoveUser (const char *alias_name)
+{
+    CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name);
+    if (pos != m_user_dict.end())
+    {
+        m_user_dict.erase(pos);
+        return true;
+    }
+    return false;
+}
+
+StateVariable *
+CommandInterpreter::GetStateVariable(const char *name)
+{
+    VariableMap::const_iterator pos = m_variables.find(name);
+    if (pos != m_variables.end())
+        return pos->second.get();
+    return NULL;
+}
+
+void
+CommandInterpreter::GetAliasHelp (const char *alias_name, const char *command_name, StreamString &help_string)
+{
+    help_string.Printf ("'%s", command_name);
+    OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
+
+    if (option_arg_vector_sp != NULL)
+    {
+        OptionArgVector *options = option_arg_vector_sp.get();
+        for (int i = 0; i < options->size(); ++i)
+        {
+            OptionArgPair cur_option = (*options)[i];
+            std::string opt = cur_option.first;
+            std::string value = cur_option.second;
+            if (opt.compare("<argument>") == 0)
+            {
+                help_string.Printf (" %s", value.c_str());
+            }
+            else
+            {
+                help_string.Printf (" %s", opt.c_str());
+                if ((value.compare ("<no-argument>") != 0)
+                    && (value.compare ("<need-argument") != 0))
+                {
+                    help_string.Printf (" %s", value.c_str());
+                }
+            }
+        }
+    }
+
+    help_string.Printf ("'");
+}
+
+std::string
+CommandInterpreter::FindLongestCommandWord (CommandObject::CommandMap &dict)
+{
+    CommandObject::CommandMap::const_iterator pos;
+    int max_len = 0;
+    CommandObjectSP cmd_sp;
+    std::string longest_word;
+
+    for (pos = dict.begin(); pos != dict.end(); ++pos)
+      {
+        if ((max_len == 0)
+            || (strlen (pos->first.c_str()) > max_len))
+          {
+            longest_word = pos->first;
+            max_len = strlen (longest_word.c_str());
+          }
+    }
+
+    return longest_word;
+}
+
+void
+CommandInterpreter::GetHelp (CommandReturnObject &result)
+{
+    CommandObject::CommandMap::const_iterator pos;
+    result.AppendMessage("The following is a list of built-in, permanent debugger commands:");
+    result.AppendMessage("");
+    std::string longest_word  = FindLongestCommandWord (m_command_dict);
+    uint32_t max_len = strlen (longest_word.c_str());
+
+    for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
+    {
+        OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
+                                 max_len);
+    }
+    result.AppendMessage("");
+
+    if (m_alias_dict.size() > 0)
+    {
+        result.AppendMessage("The following is a list of your current command abbreviations (see 'alias' for more info):");
+        result.AppendMessage("");
+        longest_word = FindLongestCommandWord (m_alias_dict);
+        max_len = strlen (longest_word.c_str());
+        for (pos = m_alias_dict.begin(); pos != m_alias_dict.end(); ++pos)
+        {
+            StreamString sstr;
+            StreamString translation_and_help;
+            std::string entry_name = pos->first;
+            std::string second_entry = pos->second.get()->GetCommandName();
+            GetAliasHelp (pos->first.c_str(), pos->second->GetCommandName(), sstr);
+            
+            translation_and_help.Printf ("(%s)  %s", sstr.GetData(), pos->second->GetHelp());
+            OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", 
+                                     translation_and_help.GetData(), max_len);
+        }
+        result.AppendMessage("");
+    }
+
+    if (m_user_dict.size() > 0)
+    {
+        result.AppendMessage ("The following is a list of your current user-defined commands:");
+        result.AppendMessage("");
+        for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
+        {
+            result.AppendMessageWithFormat ("%s  --  %s\n", pos->first.c_str(), pos->second->GetHelp());
+        }
+        result.AppendMessage("");
+    }
+
+    result.AppendMessage("For more information on any particular command, try 'help <command-name>'.");
+}
+
+void
+CommandInterpreter::ShowVariableValues (CommandReturnObject &result)
+{
+    result.AppendMessage ("Below is a list of all the debugger setting variables and their values:");
+
+    for (VariableMap::const_iterator pos = m_variables.begin(); pos != m_variables.end(); ++pos)
+    {
+        StateVariable *var = pos->second.get();
+        var->AppendVariableInformation (result);
+    }
+}
+
+void
+CommandInterpreter::ShowVariableHelp (CommandReturnObject &result)
+{
+    result.AppendMessage ("Below is a list of all the internal debugger variables that are settable:");
+    for (VariableMap::const_iterator pos = m_variables.begin(); pos != m_variables.end(); ++pos)
+    {
+        StateVariable *var = pos->second.get();
+        result.AppendMessageWithFormat ("    %s  --  %s \n", var->GetName(), var->GetHelp());
+    }
+}
+
+// Main entry point into the command_interpreter; this function takes a text
+// line containing a debugger command, with all its flags, options, etc,
+// parses the line and takes the appropriate actions.
+
+bool
+CommandInterpreter::HandleCommand (const char *command_line, bool add_to_history, CommandReturnObject &result,
+                                   ExecutionContext *override_context)
+{
+    // FIXME: there should probably be a mutex to make sure only one thread can
+    // run the interpreter at a time.
+
+    // TODO: this should be a logging channel in lldb.
+//    if (DebugSelf())
+//    {
+//        result.AppendMessageWithFormat ("Processing command: %s\n", command_line);
+//    }
+
+    m_current_context.Update (override_context);
+
+    if (command_line == NULL || command_line[0] == '\0')
+    {
+        if (m_command_history.empty())
+        {
+            result.AppendError ("empty command");
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        else
+        {
+            command_line = m_command_history.back().c_str();
+        }
+        add_to_history = false;
+    }
+
+    Args command_args(command_line);
+
+    if (command_args.GetArgumentCount() > 0)
+    {
+        const char *command_cstr = command_args.GetArgumentAtIndex(0);
+        if (command_cstr)
+        {
+
+            // We're looking up the command object here.  So first find an exact match to the
+            // command in the commands.
+
+            CommandObject *command_obj = GetCommandObject (command_cstr, false, true);
+
+            // If we didn't find an exact match to the command string in the commands, look in
+            // the aliases.
+
+            if (command_obj == NULL)
+            {
+                command_obj = GetCommandObject (command_cstr, true, true);
+                if (command_obj != NULL)
+                {
+                    BuildAliasCommandArgs (command_obj, command_cstr, command_args, result);
+                    if (!result.Succeeded())
+                        return false;
+                }
+            }
+
+            // Finally, if there wasn't an exact match among the aliases, look for an inexact match.
+
+            if (command_obj == NULL)
+                command_obj = GetCommandObject(command_cstr, false, false);
+
+            if (command_obj)
+            {
+                if (command_obj->WantsRawCommandString())
+                {
+                    const char *stripped_command = ::strstr (command_line, command_cstr);
+                    if (stripped_command)
+                    {
+                        stripped_command += strlen(command_cstr);
+                        while (isspace(*stripped_command))
+                            ++stripped_command;
+                        command_obj->ExecuteRawCommandString(stripped_command, Context(), this, result);
+                    }
+                }
+                else
+                {
+                    if (add_to_history)
+                        m_command_history.push_back (command_line);
+
+                    // Remove the command from the args.
+                    command_args.Shift();
+                    command_obj->ExecuteWithOptions (command_args, Context(), this, result);
+                }
+            }
+            else
+            {
+                StringList matches;
+                int num_matches;
+                int cursor_index = command_args.GetArgumentCount() - 1;
+                int cursor_char_position = strlen (command_args.GetArgumentAtIndex(command_args.GetArgumentCount() - 1));
+                num_matches = HandleCompletionMatches (command_args, cursor_index,
+                                                        cursor_char_position,
+                                                       0, -1, matches);
+
+                if (num_matches > 0)
+                {
+                    std::string error_msg;
+                    error_msg.assign ("ambiguous command '");
+                    error_msg.append(command_cstr);
+                    error_msg.append ("'.");
+
+                    error_msg.append (" Possible completions:");
+                    for (int i = 0; i < num_matches; i++)
+                    {
+                        error_msg.append ("\n\t");
+                        error_msg.append (matches.GetStringAtIndex (i));
+                    }
+                    error_msg.append ("\n");
+                    result.AppendRawError (error_msg.c_str(), error_msg.size());
+                }
+                else
+                    result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_cstr);
+
+                result.SetStatus (eReturnStatusFailed);
+            }
+        }
+    }
+    return result.Succeeded();
+}
+
+int
+CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
+                                             int &cursor_index,
+                                             int &cursor_char_position,
+                                             int match_start_point,
+                                             int max_return_elements,
+                                             StringList &matches)
+{
+    int num_command_matches = 0;
+    bool include_aliases = true;
+    bool look_for_subcommand = false;
+
+    if (cursor_index == -1)
+    {
+        // We got nothing on the command line, so return the list of commands
+        num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches);
+    }
+    else if (cursor_index == 0)
+    {
+        // The cursor is in the first argument, so just do a lookup in the dictionary.
+        CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), include_aliases, false,
+                                                   &matches);
+        num_command_matches = matches.GetSize();
+
+        if (num_command_matches == 1
+            && cmd_obj && cmd_obj->IsMultiwordObject()
+            && matches.GetStringAtIndex(0) != NULL
+            && strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
+        {
+            look_for_subcommand = true;
+            num_command_matches = 0;
+            matches.DeleteStringAtIndex(0);
+            parsed_line.AppendArgument ("");
+            cursor_index++;
+            cursor_char_position = 0;
+        }
+    }
+
+    if (cursor_index > 0 || look_for_subcommand)
+    {
+        // We are completing further on into a commands arguments, so find the command and tell it
+        // to complete the command.
+        // First see if there is a matching initial command:
+        CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0), include_aliases, false);
+        if (command_object == NULL)
+        {
+            return 0;
+        }
+        else
+        {
+            parsed_line.Shift();
+            cursor_index--;
+            num_command_matches = command_object->HandleCompletion (parsed_line, cursor_index, cursor_char_position,
+                                                                    match_start_point, max_return_elements, this,
+                                                                    matches);
+        }
+    }
+
+    return num_command_matches;
+
+}
+
+int
+CommandInterpreter::HandleCompletion (const char *current_line,
+                                      const char *cursor,
+                                      const char *last_char,
+                                      int match_start_point,
+                                      int max_return_elements,
+                                      StringList &matches)
+{
+    // We parse the argument up to the cursor, so the last argument in parsed_line is
+    // the one containing the cursor, and the cursor is after the last character.
+
+    Args parsed_line(current_line, last_char - current_line);
+    Args partial_parsed_line(current_line, cursor - current_line);
+
+    int num_args = partial_parsed_line.GetArgumentCount();
+    int cursor_index = partial_parsed_line.GetArgumentCount() - 1;
+    int cursor_char_position;
+
+    if (cursor_index == -1)
+        cursor_char_position = 0;
+    else
+        cursor_char_position = strlen (partial_parsed_line.GetArgumentAtIndex(cursor_index));
+
+    int num_command_matches;
+
+    matches.Clear();
+
+    // Only max_return_elements == -1 is supported at present:
+    assert (max_return_elements == -1);
+    num_command_matches = HandleCompletionMatches (parsed_line, cursor_index, cursor_char_position, match_start_point,
+                                                   max_return_elements, matches);
+
+    if (num_command_matches <= 0)
+            return num_command_matches;
+
+    if (num_args == 0)
+    {
+        // If we got an empty string, insert nothing.
+        matches.InsertStringAtIndex(0, "");
+    }
+    else
+    {
+        // Now figure out if there is a common substring, and if so put that in element 0, otherwise
+        // put an empty string in element 0.
+        std::string command_partial_str;
+        if (cursor_index >= 0)
+            command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index), parsed_line.GetArgumentAtIndex(cursor_index) + cursor_char_position);
+
+        std::string common_prefix;
+        matches.LongestCommonPrefix (common_prefix);
+        int partial_name_len = command_partial_str.size();
+
+        // If we matched a unique single command, add a space...
+        if (num_command_matches == 1)
+        {
+            char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index);
+            if (quote_char != '\0')
+                common_prefix.push_back(quote_char);
+
+            common_prefix.push_back(' ');
+        }
+        common_prefix.erase (0, partial_name_len);
+        matches.InsertStringAtIndex(0, common_prefix.c_str());
+    }
+    return num_command_matches;
+}
+
+CommandContext *
+CommandInterpreter::Context ()
+{
+    return &m_current_context;
+}
+
+const Args *
+CommandInterpreter::GetProgramArguments ()
+{
+    if (! HasInterpreterVariables())
+        return NULL;
+
+    VariableMap::const_iterator pos = m_variables.find("run-args");
+    if (pos == m_variables.end())
+        return NULL;
+
+    StateVariable *var = pos->second.get();
+
+    if (var)
+        return &var->GetArgs();
+    return NULL;
+}
+
+const Args *
+CommandInterpreter::GetEnvironmentVariables ()
+{
+    if (! HasInterpreterVariables())
+        return NULL;
+
+    VariableMap::const_iterator pos = m_variables.find("env-vars");
+    if (pos == m_variables.end())
+        return NULL;
+
+    StateVariable *var = pos->second.get();
+    if (var)
+        return &var->GetArgs();
+    return NULL;
+}
+
+
+CommandInterpreter::~CommandInterpreter ()
+{
+}
+
+const char *
+CommandInterpreter::GetPrompt ()
+{
+    VariableMap::iterator pos;
+
+    if (! HasInterpreterVariables())
+        return NULL;
+
+    pos = m_variables.find("prompt");
+    if (pos == m_variables.end())
+        return NULL;
+
+    StateVariable *var = pos->second.get();
+
+    return ((char *) var->GetStringValue());
+}
+
+void
+CommandInterpreter::SetPrompt (const char *new_prompt)
+{
+    VariableMap::iterator pos;
+    CommandReturnObject result;
+
+    if (! HasInterpreterVariables())
+        return;
+
+    pos = m_variables.find ("prompt");
+    if (pos == m_variables.end())
+        return;
+
+    StateVariable *var = pos->second.get();
+
+    if (var->VerifyValue (this, (void *) new_prompt, result))
+       var->SetStringValue (new_prompt);
+}
+
+void
+CommandInterpreter::CrossRegisterCommand (const char * dest_cmd, const char * object_type)
+{
+    CommandObjectSP cmd_obj_sp = GetCommandSP (dest_cmd);
+
+    if (cmd_obj_sp != NULL)
+    {
+        CommandObject *cmd_obj = cmd_obj_sp.get();
+        if (cmd_obj->IsCrossRefObject ())
+            cmd_obj->AddObject (object_type);
+    }
+}
+
+void
+CommandInterpreter::SetScriptLanguage (ScriptLanguage lang)
+{
+    m_script_language = lang;
+}
+
+Listener *
+CommandInterpreter::GetListener ()
+{
+    return m_listener;
+}
+
+SourceManager &
+CommandInterpreter::GetSourceManager ()
+{
+    return m_source_manager;
+}
+
+
+
+OptionArgVectorSP
+CommandInterpreter::GetAliasOptions (const char *alias_name)
+{
+    OptionArgMap::iterator pos;
+    OptionArgVectorSP ret_val;
+
+    std::string alias (alias_name);
+
+    if (HasAliasOptions())
+    {
+        pos = m_alias_options.find (alias);
+        if (pos != m_alias_options.end())
+          ret_val = pos->second;
+    }
+
+    return ret_val;
+}
+
+void
+CommandInterpreter::RemoveAliasOptions (const char *alias_name)
+{
+    OptionArgMap::iterator pos = m_alias_options.find(alias_name);
+    if (pos != m_alias_options.end())
+    {
+        m_alias_options.erase (pos);
+    }
+}
+
+void
+CommandInterpreter::AddOrReplaceAliasOptions (const char *alias_name, OptionArgVectorSP &option_arg_vector_sp)
+{
+    m_alias_options[alias_name] = option_arg_vector_sp;
+}
+
+bool
+CommandInterpreter::HasCommands ()
+{
+    return (!m_command_dict.empty());
+}
+
+bool
+CommandInterpreter::HasAliases ()
+{
+    return (!m_alias_dict.empty());
+}
+
+bool
+CommandInterpreter::HasUserCommands ()
+{
+    return (!m_user_dict.empty());
+}
+
+bool
+CommandInterpreter::HasAliasOptions ()
+{
+    return (!m_alias_options.empty());
+}
+
+bool
+CommandInterpreter::HasInterpreterVariables ()
+{
+    return (!m_variables.empty());
+}
+
+void
+CommandInterpreter::BuildAliasCommandArgs
+(
+    CommandObject *alias_cmd_obj,
+    const char *alias_name,
+    Args &cmd_args,
+    CommandReturnObject &result
+)
+{
+    OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
+
+    if (option_arg_vector_sp.get())
+    {
+        // Make sure that the alias name is the 0th element in cmd_args
+        std::string alias_name_str = alias_name;
+        if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0)
+            cmd_args.Unshift (alias_name);
+
+        Args new_args (alias_cmd_obj->GetCommandName());
+        if (new_args.GetArgumentCount() == 2)
+            new_args.Shift();
+
+        OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
+        int old_size = cmd_args.GetArgumentCount();
+        int *used = (int *) malloc ((old_size + 1) * sizeof (int));
+
+        memset (used, 0, (old_size + 1) * sizeof (int));
+        used[0] = 1;
+
+        for (int i = 0; i < option_arg_vector->size(); ++i)
+        {
+            OptionArgPair option_pair = (*option_arg_vector)[i];
+            std::string option = option_pair.first;
+            std::string value = option_pair.second;
+            if (option.compare ("<argument>") == 0)
+                new_args.AppendArgument (value.c_str());
+            else
+            {
+                new_args.AppendArgument (option.c_str());
+                if (value.compare ("<no-argument>") != 0)
+                {
+                    int index = GetOptionArgumentPosition (value.c_str());
+                    if (index == 0)
+                        // value was NOT a positional argument; must be a real value
+                        new_args.AppendArgument (value.c_str());
+                    else if (index >= cmd_args.GetArgumentCount())
+                    {
+                        result.AppendErrorWithFormat
+                                    ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
+                                     index);
+                        result.SetStatus (eReturnStatusFailed);
+                        return;
+                    }
+                    else
+                    {
+                        new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index));
+                        used[index] = 1;
+                    }
+                }
+            }
+        }
+
+        for (int j = 0; j < cmd_args.GetArgumentCount(); ++j)
+        {
+            if (!used[j])
+                new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j));
+        }
+
+        cmd_args.Clear();
+        cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
+    }
+    else
+    {
+        result.SetStatus (eReturnStatusSuccessFinishNoResult);
+        // This alias was not created with any options; nothing further needs to be done.
+        return;
+    }
+
+    result.SetStatus (eReturnStatusSuccessFinishNoResult);
+    return;
+}
+
+
+int
+CommandInterpreter::GetOptionArgumentPosition (const char *in_string)
+{
+    int position = 0;   // Any string that isn't an argument position, i.e. '%' followed by an integer, gets a position
+                        // of zero.
+
+    char *cptr = (char *) in_string;
+
+    // Does it start with '%'
+    if (cptr[0] == '%')
+    {
+        ++cptr;
+
+        // Is the rest of it entirely digits?
+        if (isdigit (cptr[0]))
+        {
+            const char *start = cptr;
+            while (isdigit (cptr[0]))
+                ++cptr;
+
+            // We've gotten to the end of the digits; are we at the end of the string?
+            if (cptr[0] == '\0')
+                position = atoi (start);
+        }
+    }
+
+    return position;
+}
+
+void
+CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)
+{
+    const char *init_file_path = in_cwd ? "./.lldbinit" : "~/.lldbinit";
+    FileSpec init_file (init_file_path);
+    // If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting
+    // of the commands back to any appropriate listener (see CommandObjectSource::Execute for more details).
+
+    if (init_file.Exists())
+    {
+        char path[PATH_MAX];
+        init_file.GetPath(path, sizeof(path));
+        StreamString source_command;
+        source_command.Printf ("source '%s'", path);
+        HandleCommand (source_command.GetData(), false, result);
+    }
+    else
+    {
+        // nothing to be done if the file doesn't exist
+        result.SetStatus(eReturnStatusSuccessFinishNoResult);
+    }
+}
+
+ScriptInterpreter *
+CommandInterpreter::GetScriptInterpreter ()
+{
+  CommandObject::CommandMap::iterator pos;
+
+  pos = m_command_dict.find ("script");
+  if (pos != m_command_dict.end())
+    {
+      CommandObject *script_cmd_obj = pos->second.get();
+      return ((CommandObjectScript *) script_cmd_obj)->GetInterpreter ();
+    }
+  else
+      return NULL;
+}
+
+
+
+bool
+CommandInterpreter::GetSynchronous ()
+{
+    return m_synchronous_execution;
+}
+
+void
+CommandInterpreter::SetSynchronous (bool value)
+{
+    static bool value_set_once = false;
+    if (!value_set_once)
+    {
+        value_set_once = true;
+        m_synchronous_execution  = value;
+    }
+}
+
+void
+CommandInterpreter::OutputFormattedHelpText (Stream &strm,
+                                             const char *word_text,
+                                             const char *separator,
+                                             const char *help_text,
+                                             uint32_t max_word_len)
+{
+    StateVariable *var = GetStateVariable ("term-width");
+    int max_columns = var->GetIntValue();
+    // Sanity check max_columns, to cope with emacs shell mode with TERM=dumb
+    // (0 rows; 0 columns;).
+    if (max_columns <= 0) max_columns = 80;
+    
+    int indent_size = max_word_len + strlen (separator) + 2;
+
+    strm.IndentMore (indent_size);
+
+    int len = indent_size + strlen (help_text) + 1;
+    char *text  = (char *) malloc (len);
+    sprintf (text, "%-*s %s %s",  max_word_len, word_text, separator, help_text);
+    if (text[len - 1] == '\n')
+        text[--len] = '\0';
+
+    if (len  < max_columns)
+    {
+        // Output it as a single line.
+        strm.Printf ("%s", text);
+    }
+    else
+    {
+        // We need to break it up into multiple lines.
+        bool first_line = true;
+        int text_width;
+        int start = 0;
+        int end = start;
+        int final_end = strlen (text);
+        int sub_len;
+        
+        while (end < final_end)
+        {
+            if (first_line)
+                text_width = max_columns - 1;
+            else
+                text_width = max_columns - indent_size - 1;
+
+            // Don't start the 'text' on a space, since we're already outputting the indentation.
+            if (!first_line)
+            {
+                while ((start < final_end) && (text[start] == ' '))
+                  start++;
+            }
+
+            end = start + text_width;
+            if (end > final_end)
+                end = final_end;
+            else
+            {
+                // If we're not at the end of the text, make sure we break the line on white space.
+                while (end > start
+                       && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
+                    end--;
+            }
+
+            sub_len = end - start;
+            if (start != 0)
+              strm.EOL();
+            if (!first_line)
+                strm.Indent();
+            else
+                first_line = false;
+            assert (start <= final_end);
+            assert (start + sub_len <= final_end);
+            if (sub_len > 0)
+                strm.Write (text + start, sub_len);
+            start = end + 1;
+        }
+    }
+    strm.EOL();
+    strm.IndentLess(indent_size);
+    free (text);
+}
+
+void
+CommandInterpreter::AproposAllSubCommands (CommandObject *cmd_obj, const char *prefix, const char *search_word,
+                                           StringList &commands_found, StringList &commands_help)
+{
+    CommandObject::CommandMap::const_iterator pos;
+    CommandObject::CommandMap sub_cmd_dict = ((CommandObjectMultiword *) cmd_obj)->m_subcommand_dict;
+    CommandObject *sub_cmd_obj;
+
+    for (pos = sub_cmd_dict.begin(); pos != sub_cmd_dict.end(); ++pos)
+    {
+          const char * command_name = pos->first.c_str();
+          sub_cmd_obj = pos->second.get();
+          StreamString complete_command_name;
+          
+          complete_command_name.Printf ("%s %s", prefix, command_name);
+
+          if (sub_cmd_obj->HelpTextContainsWord (search_word))
+          {
+              commands_found.AppendString (complete_command_name.GetData());
+              commands_help.AppendString (sub_cmd_obj->GetHelp());
+          }
+
+          if (sub_cmd_obj->IsMultiwordObject())
+              AproposAllSubCommands (sub_cmd_obj, complete_command_name.GetData(), search_word, commands_found,
+                                     commands_help);
+    }
+
+}
+
+void
+CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found,
+                                            StringList &commands_help)
+{
+    CommandObject::CommandMap::const_iterator pos;
+
+    for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
+    {
+        const char *command_name = pos->first.c_str();
+        CommandObject *cmd_obj = pos->second.get();
+
+        if (cmd_obj->HelpTextContainsWord (search_word))
+        {
+            commands_found.AppendString (command_name);
+            commands_help.AppendString (cmd_obj->GetHelp());
+        }
+
+        if (cmd_obj->IsMultiwordObject())
+          AproposAllSubCommands (cmd_obj, command_name, search_word, commands_found, commands_help);
+      
+    }
+}
diff --git a/source/Interpreter/CommandObject.cpp b/source/Interpreter/CommandObject.cpp
new file mode 100644
index 0000000..080b5b0
--- /dev/null
+++ b/source/Interpreter/CommandObject.cpp
@@ -0,0 +1,448 @@
+//===-- CommandObject.cpp ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Interpreter/CommandObject.h"
+
+#include <string>
+#include <map>
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "lldb/Core/Address.h"
+#include "lldb/Core/Options.h"
+
+// These are for the Sourcename completers.
+// FIXME: Make a separate file for the completers.
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Core/FileSpecList.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Interpreter/ScriptInterpreterPython.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObject
+//-------------------------------------------------------------------------
+
+CommandObject::CommandObject (const char *name, const char *help, const char *syntax, uint32_t flags) :
+    m_cmd_name (name),
+    m_cmd_help_short (),
+    m_cmd_help_long (),
+    m_cmd_syntax (),
+    m_flags (flags)
+{
+    if (help && help[0])
+        m_cmd_help_short = help;
+    if (syntax && syntax[0])
+        m_cmd_syntax = syntax;
+}
+
+CommandObject::~CommandObject ()
+{
+}
+
+const char *
+CommandObject::GetHelp ()
+{
+    return m_cmd_help_short.c_str();
+}
+
+const char *
+CommandObject::GetHelpLong ()
+{
+    return m_cmd_help_long.c_str();
+}
+
+const char *
+CommandObject::GetSyntax ()
+{
+    return m_cmd_syntax.c_str();
+}
+
+const char *
+CommandObject::Translate ()
+{
+    //return m_cmd_func_name.c_str();
+    return "This function is currently not implemented.";
+}
+
+const char *
+CommandObject::GetCommandName ()
+{
+    return m_cmd_name.c_str();
+}
+
+void
+CommandObject::SetCommandName (const char *name)
+{
+    m_cmd_name = name;
+}
+
+void
+CommandObject::SetHelp (const char *cstr)
+{
+    m_cmd_help_short = cstr;
+}
+
+void
+CommandObject::SetHelpLong (const char *cstr)
+{
+    m_cmd_help_long = cstr;
+}
+
+void
+CommandObject::SetSyntax (const char *cstr)
+{
+    m_cmd_syntax = cstr;
+}
+
+Options *
+CommandObject::GetOptions ()
+{
+    // By default commands don't have options unless this virtual function
+    // is overridden by base classes.
+    return NULL;
+}
+
+Flags&
+CommandObject::GetFlags()
+{
+    return m_flags;
+}
+
+const Flags&
+CommandObject::GetFlags() const
+{
+    return m_flags;
+}
+
+bool
+CommandObject::ExecuteCommandString
+(
+    const char *command_line,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    Args command_args(command_line);
+    return ExecuteWithOptions (command_args, context, interpreter, result);
+}
+
+bool
+CommandObject::ParseOptions
+(
+    Args& args,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    // See if the subclass has options?
+    Options *options = GetOptions();
+    if (options != NULL)
+    {
+        Error error;
+        options->ResetOptionValues();
+
+        // ParseOptions calls getopt_long, which always skips the zero'th item in the array and starts at position 1,
+        // so we need to push a dummy value into position zero.
+        args.Unshift("dummy_string");
+        error = args.ParseOptions (*options);
+
+        // The "dummy_string" will have already been removed by ParseOptions,
+        // so no need to remove it.
+
+        if (error.Fail() || !options->VerifyOptions (result))
+        {
+            const char *error_cstr = error.AsCString();
+            if (error_cstr)
+            {
+                // We got an error string, lets use that
+                result.GetErrorStream().PutCString(error_cstr);
+            }
+            else
+            {
+                // No error string, output the usage information into result
+                options->GenerateOptionUsage (result.GetErrorStream(), this);
+            }
+            // Set the return status to failed (this was an error).
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+    }
+    return true;
+}
+bool
+CommandObject::ExecuteWithOptions
+(
+    Args& args,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    for (size_t i = 0; i < args.GetArgumentCount();  ++i)
+    {
+        const char *tmp_str = args.GetArgumentAtIndex (i);
+        if (tmp_str[0] == '`')  // back-quote
+            args.ReplaceArgumentAtIndex (i, interpreter->ProcessEmbeddedScriptCommands (tmp_str));
+    }
+
+    Process *process = context->GetExecutionContext().process;
+    if (process == NULL)
+    {
+        if (GetFlags().IsSet(CommandObject::eFlagProcessMustBeLaunched | CommandObject::eFlagProcessMustBePaused))
+        {
+            result.AppendError ("Process must exist.");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+    }
+    else
+    {
+        StateType state = process->GetState();
+        
+        switch (state)
+        {
+        
+        case eStateAttaching:
+        case eStateLaunching:
+        case eStateSuspended:
+        case eStateCrashed:
+        case eStateStopped:
+            break;
+        
+        case eStateDetached:
+        case eStateExited:
+        case eStateUnloaded:
+            if (GetFlags().IsSet(CommandObject::eFlagProcessMustBeLaunched))
+            {
+                result.AppendError ("Process must be launched.");
+                result.SetStatus (eReturnStatusFailed);
+                return false;
+            }
+            break;
+
+        case eStateRunning:
+        case eStateStepping:
+            if (GetFlags().IsSet(CommandObject::eFlagProcessMustBePaused))
+            {
+                result.AppendError ("Process is running.  Use 'process interrupt' to pause execution.");
+                result.SetStatus (eReturnStatusFailed);
+                return false;
+            }
+        }
+    }
+    
+    if (!ParseOptions (args, interpreter, result))
+        return false;
+
+    // Call the command-specific version of 'Execute', passing it the already processed arguments.
+    return Execute (args, context, interpreter, result);
+}
+
+class CommandDictCommandPartialMatch
+{
+    public:
+        CommandDictCommandPartialMatch (const char *match_str)
+        {
+            m_match_str = match_str;
+        }
+        bool operator() (const std::pair<std::string, lldb::CommandObjectSP> map_element) const
+        {
+            // A NULL or empty string matches everything.
+            if (m_match_str == NULL || *m_match_str == '\0')
+                return 1;
+
+            size_t found = map_element.first.find (m_match_str, 0);
+            if (found == std::string::npos)
+                return 0;
+            else
+                return found == 0;
+        }
+
+    private:
+        const char *m_match_str;
+};
+
+int
+CommandObject::AddNamesMatchingPartialString (CommandObject::CommandMap &in_map, const char *cmd_str,
+                                              StringList &matches)
+{
+    int number_added = 0;
+    CommandDictCommandPartialMatch matcher(cmd_str);
+
+    CommandObject::CommandMap::iterator matching_cmds = std::find_if (in_map.begin(), in_map.end(), matcher);
+
+    while (matching_cmds != in_map.end())
+    {
+        ++number_added;
+        matches.AppendString((*matching_cmds).first.c_str());
+        matching_cmds = std::find_if (++matching_cmds, in_map.end(), matcher);;
+    }
+    return number_added;
+}
+
+int
+CommandObject::HandleCompletion
+(
+    Args &input,
+    int &cursor_index,
+    int &cursor_char_position,
+    int match_start_point,
+    int max_return_elements,
+    CommandInterpreter *interpreter,
+    StringList &matches
+)
+{
+    if (WantsRawCommandString())
+    {
+        // FIXME: Abstract telling the completion to insert the completion character.
+        matches.Clear();
+        return -1;
+    }
+    else
+    {
+        // Can we do anything generic with the options?
+        Options *cur_options = GetOptions();
+        CommandReturnObject result;
+        OptionElementVector opt_element_vector;
+
+        if (cur_options != NULL)
+        {
+            // Re-insert the dummy command name string which will have been
+            // stripped off:
+            input.Unshift ("dummy-string");
+            cursor_index++;
+
+
+            // I stick an element on the end of the input, because if the last element is
+            // option that requires an argument, getopt_long will freak out.
+
+            input.AppendArgument ("<FAKE-VALUE>");
+
+            input.ParseArgsForCompletion (*cur_options, opt_element_vector);
+
+            input.DeleteArgumentAtIndex(input.GetArgumentCount() - 1);
+
+            bool handled_by_options;
+            handled_by_options = cur_options->HandleOptionCompletion(input,
+                                                                     opt_element_vector,
+                                                                     cursor_index,
+                                                                     cursor_char_position,
+                                                                     match_start_point,
+                                                                     max_return_elements,
+                                                                     interpreter,
+                                                                     matches);
+            if (handled_by_options)
+                return matches.GetSize();
+        }
+
+        // If we got here, the last word is not an option or an option argument.
+        return HandleArgumentCompletion(input,
+                                        cursor_index,
+                                        cursor_char_position,
+                                        opt_element_vector,
+                                        match_start_point,
+                                        max_return_elements,
+                                        interpreter,
+                                        matches);
+    }
+}
+
+int
+CommandObject::HandleArgumentCompletion
+(
+    Args &input,
+    int &cursor_index,
+    int &cursor_char_position,
+    OptionElementVector &opt_element_vector,
+    int match_start_point,
+    int max_return_elements,
+    CommandInterpreter *interpreter,
+    StringList &matches
+)
+{
+    return 0;
+}
+
+// Case insensitive version of ::strstr()
+// Returns true if s2 is contained within s1.
+
+static bool
+contains_string (const char *s1, const char *s2)
+{
+  char *locase_s1 = (char *) malloc (strlen (s1) + 1);
+  char *locase_s2 = (char *) malloc (strlen (s2) + 1);
+  int i;
+  for (i = 0; s1 && s1[i] != '\0'; i++)
+    locase_s1[i] = ::tolower (s1[i]);
+  locase_s1[i] = '\0';
+  for (i = 0; s2 && s2[i] != '\0'; i++)
+    locase_s2[i] = ::tolower (s2[i]);
+  locase_s2[i] = '\0';
+
+  const char *result = ::strstr (locase_s1, locase_s2);
+  free (locase_s1);
+  free (locase_s2);
+  // 'result' points into freed memory - but we're not
+  // deref'ing it so hopefully current/future compilers
+  // won't complain..
+
+  if (result == NULL)
+      return false;
+  else
+      return true;
+}
+
+bool
+CommandObject::HelpTextContainsWord (const char *search_word)
+{
+    const char *short_help;
+    const char *long_help;
+    const char *syntax_help;
+    std::string options_usage_help;
+
+
+    bool found_word = false;
+
+    short_help = GetHelp();
+    long_help = GetHelpLong();
+    syntax_help = GetSyntax();
+    
+    if (contains_string (short_help, search_word))
+        found_word = true;
+    else if (contains_string (long_help, search_word))
+        found_word = true;
+    else if (contains_string (syntax_help, search_word))
+        found_word = true;
+
+    if (!found_word
+        && GetOptions() != NULL)
+    {
+        StreamString usage_help;
+        GetOptions()->GenerateOptionUsage (usage_help, this);
+        if (usage_help.GetSize() > 0)
+        {
+            const char *usage_text = usage_help.GetData();
+            if (contains_string (usage_text, search_word))
+              found_word = true;
+        }
+    }
+
+    return found_word;
+}
diff --git a/source/Interpreter/CommandObjectCrossref.cpp b/source/Interpreter/CommandObjectCrossref.cpp
new file mode 100644
index 0000000..27b6637
--- /dev/null
+++ b/source/Interpreter/CommandObjectCrossref.cpp
@@ -0,0 +1,92 @@
+//===-- CommandObjectCrossref.cpp -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Interpreter/CommandObjectCrossref.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectCrossref
+//-------------------------------------------------------------------------
+
+CommandObjectCrossref::CommandObjectCrossref
+(
+    const char *name,
+    const char *help,
+    const char *syntax
+) :
+    CommandObject (name, help, syntax),
+    m_crossref_object_types()
+{
+}
+
+CommandObjectCrossref::~CommandObjectCrossref ()
+{
+}
+
+bool
+CommandObjectCrossref::Execute
+(
+    Args& command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    if (m_crossref_object_types.GetArgumentCount() == 0)
+    {
+        result.AppendErrorWithFormat ("There are no objects for which you can call '%s'.\n", GetCommandName());
+        result.SetStatus (eReturnStatusFailed);
+    }
+    else
+    {
+        GenerateHelpText (result);
+    }
+    return result.Succeeded();
+}
+
+void
+CommandObjectCrossref::AddObject (const char *obj_name)
+{
+    m_crossref_object_types.AppendArgument (obj_name);
+}
+
+const char **
+CommandObjectCrossref::GetObjectTypes () const
+{
+    return m_crossref_object_types.GetConstArgumentVector();
+}
+
+void
+CommandObjectCrossref::GenerateHelpText (CommandReturnObject &result)
+{
+    result.AppendMessage ("This command can be called on the following types of objects:");
+
+    for (int i = 0; i < m_crossref_object_types.GetArgumentCount(); ++i)
+    {
+        const char *obj_name = m_crossref_object_types.GetArgumentAtIndex(i);
+        result.AppendMessageWithFormat ("    %s    (e.g.  '%s %s')\n", obj_name,
+                                        obj_name, GetCommandName());
+    }
+
+    result.SetStatus (eReturnStatusSuccessFinishNoResult);
+}
+
+bool
+CommandObjectCrossref::IsCrossRefObject ()
+{
+    return true;
+}
diff --git a/source/Interpreter/CommandObjectMultiword.cpp b/source/Interpreter/CommandObjectMultiword.cpp
new file mode 100644
index 0000000..874be0e
--- /dev/null
+++ b/source/Interpreter/CommandObjectMultiword.cpp
@@ -0,0 +1,263 @@
+//===-- CommandObjectMultiword.cpp ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiword
+//-------------------------------------------------------------------------
+
+CommandObjectMultiword::CommandObjectMultiword
+(
+    const char *name,
+    const char *help,
+    const char *syntax,
+    uint32_t flags
+) :
+    CommandObject (name, help, syntax, flags)
+{
+}
+
+CommandObjectMultiword::~CommandObjectMultiword ()
+{
+}
+
+CommandObjectSP
+CommandObjectMultiword::GetSubcommandSP (const char *sub_cmd, StringList *matches)
+{
+    CommandObjectSP return_cmd_sp;
+    CommandObject::CommandMap::iterator pos;
+
+    if (!m_subcommand_dict.empty())
+    {
+        pos = m_subcommand_dict.find (sub_cmd);
+        if (pos != m_subcommand_dict.end())
+            return_cmd_sp = pos->second;
+        else
+        {
+
+            StringList local_matches;
+            if (matches == NULL)
+                matches = &local_matches;
+            int num_matches = CommandObject::AddNamesMatchingPartialString (m_subcommand_dict, sub_cmd, *matches);
+
+            if (num_matches == 1)
+            {
+                // Cleaner, but slightly less efficient would be to call back into this function, since I now
+                // know I have an exact match...
+
+                sub_cmd = matches->GetStringAtIndex(0);
+                pos = m_subcommand_dict.find(sub_cmd);
+                if (pos != m_subcommand_dict.end())
+                    return_cmd_sp = pos->second;
+            }
+        }
+    }
+    return return_cmd_sp;
+}
+
+CommandObject *
+CommandObjectMultiword::GetSubcommandObject (const char *sub_cmd, StringList *matches)
+{
+    return GetSubcommandSP(sub_cmd, matches).get();
+}
+
+bool
+CommandObjectMultiword::LoadSubCommand (CommandObjectSP cmd_obj, const char *name,
+                                          CommandInterpreter *interpreter)
+{
+    CommandMap::iterator pos;
+    bool success = true;
+
+    pos = m_subcommand_dict.find(name);
+    if (pos == m_subcommand_dict.end())
+    {
+        m_subcommand_dict[name] = cmd_obj;
+        interpreter->CrossRegisterCommand (name, GetCommandName());
+    }
+    else
+        success = false;
+
+    return success;
+}
+
+bool
+CommandObjectMultiword::Execute
+(
+    Args& args,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    const size_t argc = args.GetArgumentCount();
+    if (argc == 0)
+    {
+        GenerateHelpText (result, interpreter);
+    }
+    else
+    {
+        const char *sub_command = args.GetArgumentAtIndex (0);
+
+        if (sub_command)
+        {
+            if (::strcasecmp (sub_command, "help") == 0)
+            {
+                GenerateHelpText (result, interpreter);
+            }
+            else if (!m_subcommand_dict.empty())
+            {
+                StringList matches;
+                CommandObject *sub_cmd_obj = GetSubcommandObject(sub_command, &matches);
+                if (sub_cmd_obj != NULL)
+                {
+                    // Now call CommandObject::Execute to process and options in 'rest_of_line'.  From there
+                    // the command-specific version of Execute will be called, with the processed arguments.
+
+                    args.Shift();
+
+                    sub_cmd_obj->ExecuteWithOptions (args, context, interpreter, result);
+                }
+                else
+                {
+                    std::string error_msg;
+                    int num_subcmd_matches = matches.GetSize();
+                    if (num_subcmd_matches > 0)
+                        error_msg.assign ("ambiguous command ");
+                    else
+                        error_msg.assign ("invalid command ");
+
+                    error_msg.append ("'");
+                    error_msg.append (GetCommandName());
+                    error_msg.append (" ");
+                    error_msg.append (sub_command);
+                    error_msg.append ("'");
+
+                    if (num_subcmd_matches > 0)
+                    {
+                        error_msg.append (" Possible completions:");
+                        for (int i = 0; i < num_subcmd_matches; i++)
+                        {
+                            error_msg.append ("\n\t");
+                            error_msg.append (matches.GetStringAtIndex (i));
+                        }
+                    }
+                    error_msg.append ("\n");
+                    result.AppendRawError (error_msg.c_str(), error_msg.size());
+                    result.SetStatus (eReturnStatusFailed);
+                }
+            }
+            else
+            {
+                result.AppendErrorWithFormat ("'%s' does not have any subcommands.\n", GetCommandName());
+                result.SetStatus (eReturnStatusFailed);
+            }
+        }
+    }
+
+    return result.Succeeded();
+}
+
+void
+CommandObjectMultiword::GenerateHelpText (CommandReturnObject &result, CommandInterpreter *interpreter)
+{
+    // First time through here, generate the help text for the object and
+    // push it to the return result object as well
+
+    StreamString &output_stream = result.GetOutputStream();
+    output_stream.PutCString ("The following subcommands are supported:\n\n");
+
+    CommandMap::iterator pos;
+    std::string longest_word = interpreter->FindLongestCommandWord (m_subcommand_dict);
+    uint32_t max_len = 0;
+
+    if (! longest_word.empty())
+        max_len = strlen (longest_word.c_str()) + 4; // Indent the output by 4 spaces.
+
+    for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos)
+    {
+        std::string indented_command ("    ");
+        indented_command.append (pos->first);
+        interpreter->OutputFormattedHelpText (result.GetOutputStream(), indented_command.c_str(), "--", 
+                                              pos->second->GetHelp(), max_len);
+    }
+
+    output_stream.PutCString ("\nFor more help on any particular subcommand, type 'help <command> <subcommand>'.\n");
+
+    result.SetStatus (eReturnStatusSuccessFinishNoResult);
+}
+
+int
+CommandObjectMultiword::HandleCompletion
+(
+    Args &input,
+    int &cursor_index,
+    int &cursor_char_position,
+    int match_start_point,
+    int max_return_elements,
+    CommandInterpreter *interpreter,
+    StringList &matches
+)
+{
+    if (cursor_index == 0)
+    {
+        CommandObject::AddNamesMatchingPartialString (m_subcommand_dict, input.GetArgumentAtIndex(0), matches);
+
+        if (matches.GetSize() == 1
+            && matches.GetStringAtIndex(0) != NULL
+            && strcmp (input.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
+        {
+            StringList temp_matches;
+            CommandObject *cmd_obj = GetSubcommandObject (input.GetArgumentAtIndex(0), &temp_matches);
+            if (cmd_obj != NULL)
+            {
+                matches.DeleteStringAtIndex (0);
+                input.Shift();
+                cursor_char_position = 0;
+                input.AppendArgument ("");
+                return cmd_obj->HandleCompletion (input, cursor_index, cursor_char_position, match_start_point,
+                                                  max_return_elements, interpreter, matches);
+            }
+            else
+                return matches.GetSize();
+        }
+        else
+            return matches.GetSize();
+    }
+    else
+    {
+        CommandObject *sub_command_object = GetSubcommandObject (input.GetArgumentAtIndex(0), &matches);
+        if (sub_command_object == NULL)
+        {
+            return matches.GetSize();
+        }
+        else
+        {
+            // Remove the one match that we got from calling GetSubcommandObject.
+            matches.DeleteStringAtIndex(0);
+            input.Shift();
+            cursor_index--;
+            return sub_command_object->HandleCompletion (input, cursor_index, cursor_char_position, match_start_point,
+                                                         max_return_elements, interpreter, matches);
+        }
+
+    }
+}
+
diff --git a/source/Interpreter/CommandObjectRegexCommand.cpp b/source/Interpreter/CommandObjectRegexCommand.cpp
new file mode 100644
index 0000000..b3fa6a4
--- /dev/null
+++ b/source/Interpreter/CommandObjectRegexCommand.cpp
@@ -0,0 +1,123 @@
+//===-- CommandObjectRegexCommand.cpp ---------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Interpreter/CommandObjectRegexCommand.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// CommandObjectRegexCommand constructor
+//----------------------------------------------------------------------
+CommandObjectRegexCommand::CommandObjectRegexCommand
+(
+    const char *name,
+    const char *help,
+    const char *syntax,
+    uint32_t max_matches
+) :
+    CommandObject (name, help, syntax),
+    m_entries(),
+    m_max_matches (max_matches)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+CommandObjectRegexCommand::~CommandObjectRegexCommand()
+{
+}
+
+
+bool
+CommandObjectRegexCommand::Execute
+(
+    Args& command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    return false;
+}
+
+
+bool
+CommandObjectRegexCommand::ExecuteRawCommandString
+(
+    const char *command,
+    CommandContext *context,
+    CommandInterpreter *interpreter,
+    CommandReturnObject &result
+)
+{
+    if (command)
+    {
+        EntryCollection::const_iterator pos, end = m_entries.end();
+        for (pos = m_entries.begin(); pos != end; ++pos)
+        {
+            if (pos->regex.Execute (command, m_max_matches))
+            {
+                std::string new_command(pos->command);
+                std::string match_str;
+                char percent_var[8];
+                size_t idx, percent_var_idx;
+                for (uint32_t match_idx=1; match_idx <= m_max_matches; ++match_idx)
+                {
+                    if (pos->regex.GetMatchAtIndex (command, match_idx, match_str))
+                    {
+                        const int percent_var_len = ::snprintf (percent_var, sizeof(percent_var), "%%%u", match_idx);
+                        for (idx = 0; (percent_var_idx = new_command.find(percent_var, idx)) != std::string::npos; )
+                        {
+                            new_command.erase(percent_var_idx, percent_var_len);
+                            new_command.insert(percent_var_idx, match_str);
+                            idx += percent_var_idx + match_str.size();
+                        }
+                    }
+                }
+                // Interpret the new command and return this as the result!
+//                if (m_options.verbose)
+//                    result.GetOutputStream().Printf("%s\n", new_command.c_str());
+                return interpreter->HandleCommand(new_command.c_str(), true, result);
+            }
+        }
+        result.SetStatus(eReturnStatusFailed);
+        result.AppendErrorWithFormat("Command contents '%s' failed to match any regular expression in the '%s' regex command.\n",
+                                    command,
+                                    m_cmd_name.c_str());
+        return false;
+    }
+    result.AppendError("empty command passed to regular exression command");
+    result.SetStatus(eReturnStatusFailed);
+    return false;
+}
+
+
+bool
+CommandObjectRegexCommand::AddRegexCommand (const char *re_cstr, const char *command_cstr)
+{
+    m_entries.resize(m_entries.size() + 1);
+    // Only add the regular expression if it compiles
+    if (m_entries.back().regex.Compile (re_cstr, REG_EXTENDED))
+    {
+        m_entries.back().command.assign (command_cstr);
+        return true;
+    }
+    // The regex didn't compile...
+    m_entries.pop_back();
+    return false;
+}
diff --git a/source/Interpreter/CommandReturnObject.cpp b/source/Interpreter/CommandReturnObject.cpp
new file mode 100644
index 0000000..f634e3c
--- /dev/null
+++ b/source/Interpreter/CommandReturnObject.cpp
@@ -0,0 +1,175 @@
+//===-- CommandReturnObject.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/StreamString.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+CommandReturnObject::CommandReturnObject () :
+    m_output_stream (),
+    m_error_stream (),
+    m_status (eReturnStatusStarted),
+    m_did_change_process_state (false)
+{
+}
+
+CommandReturnObject::~CommandReturnObject ()
+{
+}
+
+StreamString &
+CommandReturnObject::GetOutputStream ()
+{
+    return m_output_stream;
+}
+
+StreamString &
+CommandReturnObject::GetErrorStream ()
+{
+    return m_error_stream;
+}
+
+void
+CommandReturnObject::AppendErrorWithFormat (const char *format, ...)
+{
+    va_list args;
+    va_start (args, format);
+    StreamString sstrm;
+    sstrm.PrintfVarArg(format, args);
+    va_end (args);
+
+    m_error_stream.Printf("error: %s", sstrm.GetData());
+}
+
+
+void
+CommandReturnObject::AppendMessageWithFormat (const char *format, ...)
+{
+    va_list args;
+    va_start (args, format);
+    StreamString sstrm;
+    sstrm.PrintfVarArg(format, args);
+    va_end (args);
+
+    m_output_stream.Printf("%s", sstrm.GetData());
+}
+
+void
+CommandReturnObject::AppendWarningWithFormat (const char *format, ...)
+{
+    va_list args;
+    va_start (args, format);
+    StreamString sstrm;
+    sstrm.PrintfVarArg(format, args);
+    va_end (args);
+
+    m_error_stream.Printf("warning: %s", sstrm.GetData());
+}
+
+void
+CommandReturnObject::AppendMessage (const char *in_string, int len)
+{
+    if (len < 0)
+        len = ::strlen (in_string);
+    m_output_stream.Printf("%*.*s\n", len, len, in_string);
+}
+
+void
+CommandReturnObject::AppendWarning (const char *in_string, int len)
+{
+    if (len < 0)
+        len = ::strlen (in_string);
+    m_error_stream.Printf("warning: %*.*s\n", len, len, in_string);
+}
+
+// Similar to AppendWarning, but do not prepend 'warning: ' to message, and
+// don't append "\n" to the end of it.
+
+void
+CommandReturnObject::AppendRawWarning (const char *in_string, int len)
+{
+    if (len < 0)
+        len = ::strlen (in_string);
+    m_error_stream.Printf("%*.*s", len, len, in_string);
+}
+
+void
+CommandReturnObject::AppendError (const char *in_string, int len)
+{
+    if (!in_string)
+        return;
+
+    if (len < 0)
+        len = ::strlen (in_string);
+    m_error_stream.Printf ("error: %*.*s\n", len, len, in_string);
+}
+
+// Similar to AppendError, but do not prepend 'Error: ' to message, and
+// don't append "\n" to the end of it.
+
+void
+CommandReturnObject::AppendRawError (const char *in_string, int len)
+{
+    if (len < 0)
+        len = ::strlen (in_string);
+    m_error_stream.Printf ("%*.*s", len, len, in_string);
+}
+
+void
+CommandReturnObject::SetStatus (ReturnStatus status)
+{
+    m_status = status;
+}
+
+ReturnStatus
+CommandReturnObject::GetStatus ()
+{
+    return m_status;
+}
+
+bool
+CommandReturnObject::Succeeded ()
+{
+    return m_status <= eReturnStatusSuccessContinuingResult;
+}
+
+bool
+CommandReturnObject::HasResult ()
+{
+    return (m_status == eReturnStatusSuccessFinishResult ||
+            m_status == eReturnStatusSuccessContinuingResult);
+}
+
+void
+CommandReturnObject::Clear()
+{
+    m_output_stream.Clear();
+    m_error_stream.Clear();
+    m_status = eReturnStatusStarted;
+}
+
+bool
+CommandReturnObject::GetDidChangeProcessState ()
+{
+    return m_did_change_process_state;
+}
+
+void
+CommandReturnObject::SetDidChangeProcessState (bool b)
+{
+    m_did_change_process_state = b;
+}
+
diff --git a/source/Interpreter/ScriptInterpreter.cpp b/source/Interpreter/ScriptInterpreter.cpp
new file mode 100644
index 0000000..fa3ac31
--- /dev/null
+++ b/source/Interpreter/ScriptInterpreter.cpp
@@ -0,0 +1,66 @@
+//===-- ScriptInterpreter.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Interpreter/ScriptInterpreter.h"
+
+#include <string>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StringList.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+#include "PseudoTerminal.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+ScriptInterpreter::ScriptInterpreter (ScriptLanguage script_lang) :
+    m_script_lang (script_lang),
+    m_interpreter_pty ()
+{
+    if (m_interpreter_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, NULL, 0))
+    {
+        const char *slave_name = m_interpreter_pty.GetSlaveName(NULL, 0);
+        if (slave_name)
+            m_pty_slave_name.assign(slave_name);
+    }
+}
+
+ScriptInterpreter::~ScriptInterpreter ()
+{
+    m_interpreter_pty.CloseMasterFileDescriptor();
+}
+
+const char *
+ScriptInterpreter::GetScriptInterpreterPtyName ()
+{
+    return m_pty_slave_name.c_str();
+}
+
+int
+ScriptInterpreter::GetMasterFileDescriptor ()
+{
+    return m_interpreter_pty.GetMasterFileDescriptor();
+}
+
+void 
+ScriptInterpreter::CollectDataForBreakpointCommandCallback 
+(
+    BreakpointOptions *bp_options,
+    CommandReturnObject &result
+)
+{
+    result.SetStatus (eReturnStatusFailed);
+    result.AppendError ("ScriptInterpreter::GetScriptCommands(StringList &) is not implemented.");
+}
+
+
diff --git a/source/Interpreter/ScriptInterpreterNone.cpp b/source/Interpreter/ScriptInterpreterNone.cpp
new file mode 100644
index 0000000..cdc399e
--- /dev/null
+++ b/source/Interpreter/ScriptInterpreterNone.cpp
@@ -0,0 +1,38 @@
+//===-- ScriptInterpreterNone.cpp -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Interpreter/ScriptInterpreterNone.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StringList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+ScriptInterpreterNone::ScriptInterpreterNone () :
+    ScriptInterpreter (eScriptLanguageNone)
+{
+}
+
+ScriptInterpreterNone::~ScriptInterpreterNone ()
+{
+}
+
+void
+ScriptInterpreterNone::ExecuteOneLine (const std::string &line, FILE *out, FILE *err)
+{
+    ::fprintf (err, "error: there is no embedded script interpreter in this mode.\n");
+}
+
+void
+ScriptInterpreterNone::ExecuteInterpreterLoop (FILE *out, FILE *err)
+{
+    fprintf (err, "error: there is no embedded script interpreter in this mode.\n");
+}
+
+
diff --git a/source/Interpreter/ScriptInterpreterPython.cpp b/source/Interpreter/ScriptInterpreterPython.cpp
new file mode 100644
index 0000000..6b2e3b2
--- /dev/null
+++ b/source/Interpreter/ScriptInterpreterPython.cpp
@@ -0,0 +1,830 @@
+//===-- ScriptInterpreterPython.cpp -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// In order to guarantee correct working with Python, Python.h *MUST* be
+// the *FIRST* header file included:
+
+#include <Python.h>
+
+#include "lldb/Interpreter/ScriptInterpreterPython.h"
+
+
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <string>
+
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Core/InputReader.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Process.h"
+
+extern "C" void init_lldb (void);
+
+using namespace lldb;
+using namespace lldb_private;
+
+const char embedded_interpreter_string[] =
+"import readline\n\
+import code\n\
+import sys\n\
+import traceback\n\
+\n\
+class SimpleREPL(code.InteractiveConsole):\n\
+   def __init__(self, prompt, dict):\n\
+       code.InteractiveConsole.__init__(self,dict)\n\
+       self.prompt = prompt\n\
+       self.loop_exit = False\n\
+       self.dict = dict\n\
+\n\
+   def interact(self):\n\
+       try:\n\
+           sys.ps1\n\
+       except AttributeError:\n\
+           sys.ps1 = \">>> \"\n\
+       try:\n\
+           sys.ps2\n\
+       except AttributeError:\n\
+           sys.ps2 = \"... \"\n\
+\n\
+       while not self.loop_exit:\n\
+           try:\n\
+               self.read_py_command()\n\
+           except (SystemExit, EOFError):\n\
+               # EOF while in Python just breaks out to top level.\n\
+               self.write('\\n')\n\
+               self.loop_exit = True\n\
+               break\n\
+           except KeyboardInterrupt:\n\
+               self.write(\"\\nKeyboardInterrupt\\n\")\n\
+               self.resetbuffer()\n\
+               more = 0\n\
+           except:\n\
+               traceback.print_exc()\n\
+\n\
+   def process_input (self, in_str):\n\
+      # Canonicalize the format of the input string\n\
+      temp_str = in_str\n\
+      temp_str.strip(' \t')\n\
+      words = temp_str.split()\n\
+      temp_str = ('').join(words)\n\
+\n\
+      # Check the input string to see if it was the quit\n\
+      # command.  If so, intercept it, so that it doesn't\n\
+      # close stdin on us!\n\
+      if (temp_str.lower() == \"quit()\"):\n\
+         self.loop_exit = True\n\
+         in_str = \"raise SystemExit \"\n\
+      return in_str\n\
+\n\
+   def my_raw_input (self, prompt):\n\
+      stream = sys.stdout\n\
+      stream.write (prompt)\n\
+      stream.flush ()\n\
+      try:\n\
+         line = sys.stdin.readline()\n\
+      except KeyboardInterrupt:\n\
+         line = \" \\n\"\n\
+      except (SystemExit, EOFError):\n\
+         line = \"quit()\\n\"\n\
+      if not line:\n\
+         raise EOFError\n\
+      if line[-1] == '\\n':\n\
+         line = line[:-1]\n\
+      return line\n\
+\n\
+   def read_py_command(self):\n\
+       # Read off a complete Python command.\n\
+       more = 0\n\
+       while 1:\n\
+           if more:\n\
+               prompt = sys.ps2\n\
+           else:\n\
+               prompt = sys.ps1\n\
+           line = self.my_raw_input(prompt)\n\
+           # Can be None if sys.stdin was redefined\n\
+           encoding = getattr(sys.stdin, \"encoding\", None)\n\
+           if encoding and not isinstance(line, unicode):\n\
+               line = line.decode(encoding)\n\
+           line = self.process_input (line)\n\
+           more = self.push(line)\n\
+           if not more:\n\
+               break\n\
+\n\
+def run_python_interpreter (dict):\n\
+   # Pass in the dictionary, for continuity from one session to the next.\n\
+   repl = SimpleREPL('>>> ', dict)\n\
+   repl.interact()\n";
+
+static int
+_check_and_flush (FILE *stream)
+{
+  int prev_fail = ferror (stream);
+  return fflush (stream) || prev_fail ? EOF : 0;
+}
+
+ScriptInterpreterPython::ScriptInterpreterPython () :
+    ScriptInterpreter (eScriptLanguagePython),
+    m_compiled_module (NULL),
+    m_termios_valid (false)
+{
+
+    Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+    // Find the module that owns this code and use that path we get to
+    // set the PYTHONPATH appropriately.
+
+    FileSpec this_module (Host::GetModuleFileSpecForHostAddress ((void *)init_lldb));
+    std::string python_path;
+
+    if (this_module.GetDirectory())
+    {
+        // Append the directory that the module that loaded this code
+        // belongs to
+        python_path += this_module.GetDirectory().AsCString("");
+
+#if defined (__APPLE__)
+        // If we are running on MacOSX we might be in a framework and should
+        // add an appropriate path so Resource can be found in a bundle
+
+        if (::strstr(this_module.GetDirectory().AsCString(""), ".framework"))
+        {
+            python_path.append(1, ':');
+            python_path.append(this_module.GetDirectory().AsCString(""));
+            python_path.append("/Resources/Python");
+        }
+#endif
+        // The the PYTHONPATH environment variable so that Python can find
+        // our lldb.py module and our _lldb.so.
+        ::setenv ("PYTHONPATH", python_path.c_str(), 1);
+    }
+
+    Py_Initialize ();
+
+    PyObject *compiled_module = Py_CompileString (embedded_interpreter_string, "embedded_interpreter.py",
+                                                  Py_file_input);
+
+    m_compiled_module = compiled_module;
+
+    init_lldb ();
+
+    // Update the path python uses to search for modules to include the current directory.
+
+    int success = PyRun_SimpleString ("import sys");
+    success = PyRun_SimpleString ("sys.path.append ('.')");
+    if (success == 0)
+    {
+        // Import the Script Bridge module.
+        success =  PyRun_SimpleString ("from lldb import *");
+    }
+
+    const char *pty_slave_name = GetScriptInterpreterPtyName ();
+    FILE *out_fh = Debugger::GetSharedInstance().GetOutputFileHandle();
+    
+    PyObject *pmod = PyImport_ExecCodeModule((char *)"embedded_interpreter", m_compiled_module);
+    if (pmod != NULL)
+    {
+        PyRun_SimpleString ("ConsoleDict = locals()");
+        PyRun_SimpleString ("from embedded_interpreter import run_python_interpreter");
+        PyRun_SimpleString ("import sys");
+        PyRun_SimpleString ("from termios import *");
+        PyRun_SimpleString ("old_stdin = sys.stdin");
+      
+        StreamString run_string;
+        run_string.Printf ("new_stdin = open('%s', 'r')", pty_slave_name);
+        PyRun_SimpleString (run_string.GetData());
+        PyRun_SimpleString ("sys.stdin = new_stdin");
+
+        PyRun_SimpleString ("old_stdout = sys.stdout");
+        
+        if (out_fh != NULL)
+        {
+            PyObject *new_sysout = PyFile_FromFile (out_fh, (char *) "", (char *) "w", 
+                                                        _check_and_flush);
+            PyObject *sysmod = PyImport_AddModule ("sys");
+            PyObject *sysdict = PyModule_GetDict (sysmod);
+
+            if ((new_sysout != NULL)
+                && (sysmod != NULL)
+                && (sysdict != NULL))
+            {
+                PyDict_SetItemString (sysdict, "stdout", new_sysout);
+            }
+
+            if (PyErr_Occurred())
+                PyErr_Clear();
+        }
+
+        PyRun_SimpleString ("new_mode = tcgetattr(new_stdin)");
+        PyRun_SimpleString ("new_mode[3] = new_mode[3] | ECHO | ICANON");
+        PyRun_SimpleString ("new_mode[6][VEOF] = 255");
+        PyRun_SimpleString ("tcsetattr (new_stdin, TCSANOW, new_mode)");
+    }
+
+
+}
+
+ScriptInterpreterPython::~ScriptInterpreterPython ()
+{
+    PyRun_SimpleString ("sys.stdin = old_stdin");
+    PyRun_SimpleString ("sys.stdout = old_stdout");
+    Py_Finalize ();
+}
+
+void
+ScriptInterpreterPython::ExecuteOneLine (const std::string& line, FILE *out, FILE *err)
+{
+    int success;
+
+    success = PyRun_SimpleString (line.c_str());
+    if (success != 0)
+    {
+        fprintf (err, "error: python failed attempting to evaluate '%s'\n", line.c_str());
+    }
+}
+
+
+
+size_t
+ScriptInterpreterPython::InputReaderCallback
+(
+    void *baton, 
+    InputReader *reader, 
+    lldb::InputReaderAction notification,
+    const char *bytes, 
+    size_t bytes_len
+)
+{
+    if (baton == NULL)
+        return 0;
+
+    ScriptInterpreterPython *interpreter = (ScriptInterpreterPython *) baton;            
+    switch (notification)
+    {
+    case eInputReaderActivate:
+        {
+            // Save terminal settings if we can
+            interpreter->m_termios_valid = ::tcgetattr (::fileno (reader->GetInputFileHandle()), 
+                                                        &interpreter->m_termios) == 0;
+            struct termios tmp_termios;
+            if (::tcgetattr (::fileno (reader->GetInputFileHandle()), &tmp_termios) == 0)
+            {
+                tmp_termios.c_cc[VEOF] = _POSIX_VDISABLE;
+                ::tcsetattr (::fileno (reader->GetInputFileHandle()), TCSANOW, &tmp_termios);
+            }
+        }
+        break;
+
+    case eInputReaderDeactivate:
+        break;
+
+    case eInputReaderReactivate:
+        break;
+
+    case eInputReaderGotToken:
+        if (bytes && bytes_len)
+        {
+            if ((int) bytes[0] == 4)
+                ::write (interpreter->GetMasterFileDescriptor(), "quit()", 6);
+            else
+                ::write (interpreter->GetMasterFileDescriptor(), bytes, bytes_len);
+        }
+        ::write (interpreter->GetMasterFileDescriptor(), "\n", 1);
+        break;
+        
+    case eInputReaderDone:
+        // Send a control D to the script interpreter
+        //::write (interpreter->GetMasterFileDescriptor(), "\nquit()\n", strlen("\nquit()\n"));
+        // Write a newline out to the reader output
+        //::fwrite ("\n", 1, 1, out_fh);
+        // Restore terminal settings if they were validly saved
+        if (interpreter->m_termios_valid)
+        {
+            ::tcsetattr (::fileno (reader->GetInputFileHandle()), 
+                         TCSANOW,
+                         &interpreter->m_termios);
+        }
+        break;
+    }
+
+    return bytes_len;
+}
+
+
+void
+ScriptInterpreterPython::ExecuteInterpreterLoop (FILE *out, FILE *err)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+
+    InputReaderSP reader_sp (new InputReader());
+    if (reader_sp)
+    {
+        Error error (reader_sp->Initialize (ScriptInterpreterPython::InputReaderCallback,
+                                            this,                         // baton
+                                            eInputReaderGranularityLine,  // token size, to pass to callback function
+                                            NULL,                         // end token
+                                            NULL,                         // prompt
+                                            true));                       // echo input
+     
+        if (error.Success())
+        {
+            Debugger::GetSharedInstance().PushInputReader (reader_sp);
+            ExecuteOneLine ("run_python_interpreter(ConsoleDict)", out, err);
+            Debugger::GetSharedInstance().PopInputReader (reader_sp);
+        }
+    }
+}
+
+bool
+ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string,
+                                                   ScriptInterpreter::ReturnType return_type,
+                                                   void *ret_value)
+{
+    PyObject *py_return = NULL;
+    PyObject *mainmod = PyImport_AddModule ("__main__");
+    PyObject *globals = PyModule_GetDict (mainmod);
+    PyObject *locals = globals;
+    PyObject *py_error = NULL;
+    bool ret_success;
+    int success;
+
+    if (in_string != NULL)
+    {
+        py_return = PyRun_String (in_string, Py_eval_input, globals, locals);
+        if (py_return == NULL)
+        {
+            py_error = PyErr_Occurred ();
+            if (py_error != NULL)
+                PyErr_Clear ();
+
+            py_return = PyRun_String (in_string, Py_single_input, globals, locals);
+        }
+
+        if (py_return != NULL)
+        {
+            switch (return_type)
+            {
+                case eCharPtr: // "char *"
+                {
+                    const char format[3] = "s#";
+                    success = PyArg_Parse (py_return, format, (char **) &ret_value);
+                    break;
+                }
+                case eBool:
+                {
+                    const char format[2] = "b";
+                    success = PyArg_Parse (py_return, format, (bool *) ret_value);
+                    break;
+                }
+                case eShortInt:
+                {
+                    const char format[2] = "h";
+                    success = PyArg_Parse (py_return, format, (short *) ret_value);
+                    break;
+                }
+                case eShortIntUnsigned:
+                {
+                    const char format[2] = "H";
+                    success = PyArg_Parse (py_return, format, (unsigned short *) ret_value);
+                    break;
+                }
+                case eInt:
+                {
+                    const char format[2] = "i";
+                    success = PyArg_Parse (py_return, format, (int *) ret_value);
+                    break;
+                }
+                case eIntUnsigned:
+                {
+                    const char format[2] = "I";
+                    success = PyArg_Parse (py_return, format, (unsigned int *) ret_value);
+                    break;
+                }
+                case eLongInt:
+                {
+                    const char format[2] = "l";
+                    success = PyArg_Parse (py_return, format, (long *) ret_value);
+                    break;
+                }
+                case eLongIntUnsigned:
+                {
+                    const char format[2] = "k";
+                    success = PyArg_Parse (py_return, format, (unsigned long *) ret_value);
+                    break;
+                }
+                case eLongLong:
+                {
+                    const char format[2] = "L";
+                    success = PyArg_Parse (py_return, format, (long long *) ret_value);
+                    break;
+                }
+                case eLongLongUnsigned:
+                {
+                    const char format[2] = "K";
+                    success = PyArg_Parse (py_return, format, (unsigned long long *) ret_value);
+                    break;
+                }
+                case eFloat:
+                {
+                    const char format[2] = "f";
+                    success = PyArg_Parse (py_return, format, (float *) ret_value);
+                    break;
+                }
+                case eDouble:
+                {
+                    const char format[2] = "d";
+                    success = PyArg_Parse (py_return, format, (double *) ret_value);
+                    break;
+                }
+                case eChar:
+                {
+                    const char format[2] = "c";
+                    success = PyArg_Parse (py_return, format, (char *) ret_value);
+                    break;
+                }
+                default:
+                  {}
+            }
+            Py_DECREF (py_return);
+            if (success)
+                ret_success = true;
+            else
+                ret_success = false;
+        }
+    }
+
+    py_error = PyErr_Occurred();
+    if (py_error != NULL)
+    {
+        if (PyErr_GivenExceptionMatches (py_error, PyExc_SyntaxError))
+            PyErr_Print ();
+        PyErr_Clear();
+        ret_success = false;
+    }
+
+    return ret_success;
+}
+
+bool
+ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string)
+{
+    bool success = false;
+    PyObject *py_return = NULL;
+    PyObject *mainmod = PyImport_AddModule ("__main__");
+    PyObject *globals = PyModule_GetDict (mainmod);
+    PyObject *locals = globals;
+    PyObject *py_error = NULL;
+
+    if (in_string != NULL)
+    {
+        struct _node *compiled_node = PyParser_SimpleParseString (in_string, Py_file_input);
+        if (compiled_node)
+        {
+            PyCodeObject *compiled_code = PyNode_Compile (compiled_node, "temp.py");
+            if (compiled_code)
+            {
+                py_return = PyEval_EvalCode (compiled_code, globals, locals);
+                if (py_return != NULL)
+                {
+                    success = true;
+                    Py_DECREF (py_return);
+                }
+            }
+        }
+    }
+
+    py_error = PyErr_Occurred ();
+    if (py_error != NULL)
+    {
+        if (PyErr_GivenExceptionMatches (py_error, PyExc_SyntaxError))
+            PyErr_Print ();
+        PyErr_Clear();
+        success = false;
+    }
+
+    return success;
+}
+
+static const char *g_reader_instructions = "Enter your Python command(s). Type 'DONE' to end.";
+
+size_t
+ScriptInterpreterPython::GenerateBreakpointOptionsCommandCallback
+(
+    void *baton, 
+    InputReader *reader, 
+    lldb::InputReaderAction notification,
+    const char *bytes, 
+    size_t bytes_len
+)
+{
+  static StringList commands_in_progress;
+
+    FILE *out_fh = reader->GetOutputFileHandle();
+    switch (notification)
+    {
+    case eInputReaderActivate:
+        {
+            commands_in_progress.Clear();
+            if (out_fh)
+            {
+                ::fprintf (out_fh, "%s\n", g_reader_instructions);
+                if (reader->GetPrompt())
+                    ::fprintf (out_fh, "%s", reader->GetPrompt());
+            }
+        }
+        break;
+
+    case eInputReaderDeactivate:
+        break;
+
+    case eInputReaderReactivate:
+        if (reader->GetPrompt() && out_fh)
+            ::fprintf (out_fh, "%s", reader->GetPrompt());
+        break;
+
+    case eInputReaderGotToken:
+        {
+            std::string temp_string (bytes, bytes_len);
+            commands_in_progress.AppendString (temp_string.c_str());
+            if (out_fh && !reader->IsDone() && reader->GetPrompt())
+                ::fprintf (out_fh, "%s", reader->GetPrompt());
+        }
+        break;
+
+    case eInputReaderDone:
+        {
+            BreakpointOptions *bp_options = (BreakpointOptions *)baton;
+            std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
+            data_ap->user_source.AppendList (commands_in_progress);
+            if (data_ap.get())
+            {
+                ScriptInterpreter *interpreter = Debugger::GetSharedInstance().GetCommandInterpreter().GetScriptInterpreter();
+                if (interpreter)
+                {
+                    if (interpreter->GenerateBreakpointCommandCallbackData (data_ap->user_source, 
+                                                                            data_ap->script_source))
+                    {
+                        if (data_ap->script_source.GetSize() == 1)
+                        {
+                            BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
+                            bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp);
+                        }
+                    }
+                }
+                else
+                {
+                    // FIXME:  Error processing.
+                }
+            }
+        }
+        break;
+        
+    }
+
+    return bytes_len;
+}
+
+void
+ScriptInterpreterPython::CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options,
+                                                                  CommandReturnObject &result)
+{
+    InputReaderSP reader_sp (new InputReader ());
+
+    if (reader_sp)
+    {
+        Error err = reader_sp->Initialize (
+                ScriptInterpreterPython::GenerateBreakpointOptionsCommandCallback,
+                bp_options,                 // baton
+                eInputReaderGranularityLine, // token size, for feeding data to callback function
+                "DONE",                     // end token
+                "> ",                       // prompt
+                true);                      // echo input
+    
+        if (err.Success())
+            Debugger::GetSharedInstance().PushInputReader (reader_sp);
+        else
+        {
+            result.AppendError (err.AsCString());
+            result.SetStatus (eReturnStatusFailed);
+        }
+    }
+    else
+    {
+        result.AppendError("out of memory");
+        result.SetStatus (eReturnStatusFailed);
+    }
+}
+
+bool
+ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter (StringList &function_def)
+{
+    // Convert StringList to one long, newline delimited, const char *.
+    std::string function_def_string;
+
+    int num_lines = function_def.GetSize();
+
+    for (int i = 0; i < num_lines; ++i)
+    {
+        function_def_string.append (function_def.GetStringAtIndex(i));
+        if (function_def_string.at (function_def_string.length() - 1) != '\n')
+            function_def_string.append ("\n");
+
+    }
+
+    return ExecuteMultipleLines (function_def_string.c_str());
+}
+
+bool
+ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user_input, StringList &callback_data)
+{
+    static int num_created_functions = 0;
+
+    user_input.RemoveBlankLines ();
+    int num_lines = user_input.GetSize();
+    std::string last_function_call;
+
+    // Go through lines of input looking for any function definitions. For each function definition found,
+    // export the function definition to Python, create a potential function call for the function, and
+    // mark the lines of the function to be removed from the user input.
+
+    for (int i = 0; i < num_lines; ++i)
+    {
+        int function_start = i;
+        std::string current_str = user_input.GetStringAtIndex (i);
+        const char *current_line = current_str.c_str();
+        int len = 0;
+        if (current_line)
+            len = strlen (current_line);
+
+        // Check to see if the current line is the start of a Python function definition.
+        if (len > 4 && strncmp (current_line, "def ", 4) == 0)
+        {
+            // We've found the first line of a function. First, get the function name.
+
+            // Skip over the 'def '.
+            char *start = (char *) current_line + 4;
+
+            // Skip over white space.
+            while (start[0] == ' ' || start[0] == '\t')
+              ++start;
+
+            // Find the end of the function name.
+            char *end = start;
+            while (isalnum (end[0]) || end[0] == '_')
+              ++end;
+
+            int name_len = end - start;
+            std::string func_name = current_str.substr (4, name_len);
+
+            // Now to find the last line of the function.  That will be the first line that does not begin with
+            // any white space (thanks to Python's indentation rules).
+            ++i;
+            bool found = false;
+            while (i < num_lines && !found)
+            {
+                std::string next_str = user_input.GetStringAtIndex (i);
+                const char *next_line = next_str.c_str();
+                if (next_line[0] != ' ' && next_line[0] != '\t')
+                    found = true;
+                else
+                    ++i;
+            }
+            if (found)
+                --i;  // Make 'i' correspond to the last line of the function.
+            int function_end = i;
+
+            // Special case:  All of user_input is one big function definition.
+            if ((function_start == 0) && (function_end == (num_lines - 1)))
+            {
+                ExportFunctionDefinitionToInterpreter (user_input);
+                last_function_call = func_name + " ()";
+                callback_data.AppendString (last_function_call.c_str());
+                return callback_data.GetSize() > 0;
+            }
+            else
+              {
+                // Make a copy of the function definition:
+                StringList new_function;
+                for (int k = function_start; k <= function_end; ++k)
+                {
+                    new_function.AppendString (user_input.GetStringAtIndex (k));
+                    // Mark the string to be deleted from user_input.
+                    user_input.DeleteStringAtIndex (k);
+                    user_input.InsertStringAtIndex (k, "<lldb_delete>");
+                }
+                ExportFunctionDefinitionToInterpreter (new_function);
+                last_function_call = func_name + " ()";
+            }
+        }
+    }
+
+    // Now instead of trying to really delete the marked lines from user_input, we will just copy all the
+    // unmarked lines into a new StringList.
+
+    StringList new_user_input;
+
+    for (int i = 0; i < num_lines; ++i)
+    {
+        std::string current_string = user_input.GetStringAtIndex (i);
+        if (current_string.compare (0, 13, "<lldb_delete>") == 0)
+            continue;
+
+        new_user_input.AppendString (current_string.c_str());
+    }
+
+    num_lines = new_user_input.GetSize();
+
+    if (num_lines > 0)
+    {
+        if (num_lines == 1
+            && strchr (new_user_input.GetStringAtIndex(0), '\n') == NULL)
+        {
+            // If there's only one line of input, and it doesn't contain any newline characters....
+            callback_data.AppendString (new_user_input.GetStringAtIndex (0));
+        }
+        else
+        {
+            // Create the new function name.
+            StreamString func_name;
+            func_name.Printf ("lldb_bp_callback_func_%d", num_created_functions);
+            //std::string func_name = "lldb_bp_callback_func_" + num_created_functions;
+            ++num_created_functions;
+
+            // Create the function call for the new function.
+            last_function_call = func_name.GetString() + " ()";
+
+            // Create the Python function definition line (which will have to be inserted at the beginning of
+            // the function).
+            std::string def_line = "def " + func_name.GetString() + " ():";
+
+
+            // Indent all lines an additional four spaces (as they are now being put inside a function definition).
+            for (int i = 0; i < num_lines; ++i)
+              {
+                const char *temp_cstring = new_user_input.GetStringAtIndex(i);
+                std::string temp2 = "    ";
+                temp2.append(temp_cstring);
+                new_user_input.DeleteStringAtIndex (i);
+                new_user_input.InsertStringAtIndex (i, temp2.c_str());
+              }
+
+            // Insert the function definition line at the top of the new function.
+            new_user_input.InsertStringAtIndex (0, def_line.c_str());
+
+            ExportFunctionDefinitionToInterpreter (new_user_input);
+            callback_data.AppendString (last_function_call.c_str());
+        }
+    }
+    else
+    {
+        if (!last_function_call.empty())
+          callback_data.AppendString (last_function_call.c_str());
+    }
+
+    return callback_data.GetSize() > 0;
+}
+
+bool
+ScriptInterpreterPython::BreakpointCallbackFunction 
+(
+    void *baton, 
+    StoppointCallbackContext *context,
+    lldb::user_id_t break_id, 
+    lldb::user_id_t break_loc_id
+)
+{
+    bool ret_value = true;
+    bool temp_bool;
+
+    BreakpointOptions::CommandData *bp_option_data =  (BreakpointOptions::CommandData *) baton;
+
+    const char *python_string = bp_option_data->script_source.GetStringAtIndex(0);
+
+    if (python_string != NULL)
+    {
+        bool success =
+          Debugger::GetSharedInstance().GetCommandInterpreter().GetScriptInterpreter()->ExecuteOneLineWithReturn
+                                                                                            (python_string,
+                                                                                             ScriptInterpreter::eBool,
+                                                                                             (void *) &temp_bool);
+        if (success)
+          ret_value = temp_bool;
+    }
+
+    return ret_value;
+}
diff --git a/source/Interpreter/StateVariable.cpp b/source/Interpreter/StateVariable.cpp
new file mode 100644
index 0000000..3f3c3fd
--- /dev/null
+++ b/source/Interpreter/StateVariable.cpp
@@ -0,0 +1,320 @@
+//===-- StateVariable.cpp ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+
+
+#include "lldb/Interpreter/StateVariable.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+// Variables with integer values.
+
+StateVariable::StateVariable
+(
+    const char *name,
+    int value,
+    const char *help,
+    Callback func_ptr
+) :
+    m_name (name),
+    m_type (eTypeInteger),
+    m_help_text (help),
+    m_verification_func_ptr (func_ptr)
+{
+    m_int_value = value;
+}
+
+// Variables with boolean values.
+
+StateVariable::StateVariable
+(
+    const char *name,
+    bool value,
+    const char *help,
+    Callback func_ptr
+ ) :
+    m_name (name),
+    m_type (eTypeBoolean),
+    m_help_text (help),
+    m_verification_func_ptr (func_ptr)
+{
+    m_int_value = value;
+}
+
+// Variables with string values.
+
+StateVariable::StateVariable
+(
+    const char *name,
+    const char *value,
+    bool can_append,
+    const char *help,
+    Callback func_ptr
+ ) :
+    m_name (name),
+    m_type (eTypeString),
+    m_int_value (0),
+    m_string_values (),
+    m_help_text (help),
+    m_verification_func_ptr (func_ptr)
+{
+    m_string_values.AppendArgument(value);
+}
+
+// Variables with array of strings values.
+
+StateVariable::StateVariable
+(
+    const char *name,
+    const Args *args,
+    const char *help,
+    Callback func_ptr
+ ) :
+    m_name (name),
+    m_type (eTypeStringArray),
+    m_help_text (help),
+    m_string_values(),
+    m_verification_func_ptr (func_ptr)
+{
+    if (args)
+        m_string_values = *args;
+}
+
+StateVariable::~StateVariable ()
+{
+}
+
+const char *
+StateVariable::GetName () const
+{
+    return m_name.c_str();
+}
+
+StateVariable::Type
+StateVariable::GetType () const
+{
+    return m_type;
+}
+
+int
+StateVariable::GetIntValue () const
+{
+    return m_int_value;
+}
+
+bool
+StateVariable::GetBoolValue () const
+{
+    return m_int_value;
+}
+
+const char *
+StateVariable::GetStringValue () const
+{
+    return m_string_values.GetArgumentAtIndex(0);
+}
+
+const Args &
+StateVariable::GetArgs () const
+{
+    return m_string_values;
+}
+
+Args &
+StateVariable::GetArgs ()
+{
+    return m_string_values;
+}
+
+const char *
+StateVariable::GetHelp () const
+{
+    return m_help_text.c_str();
+}
+
+void
+StateVariable::SetHelp (const char *help)
+{
+    m_help_text = help;
+}
+
+void
+StateVariable::AppendVariableInformation (CommandReturnObject &result)
+{
+    switch (m_type)
+    {
+    case eTypeBoolean:
+        if (m_int_value)
+            result.AppendMessageWithFormat ("    %s (bool) = True\n", m_name.c_str());
+        else
+            result.AppendMessageWithFormat ("    %s (bool) = False\n", m_name.c_str());
+        break;
+
+    case eTypeInteger:
+        result.AppendMessageWithFormat ("    %s (int)  = %d\n", m_name.c_str(), m_int_value);
+        break;
+
+    case eTypeString:
+        {
+            const char *cstr = m_string_values.GetArgumentAtIndex(0);
+            if (cstr && cstr[0])
+                result.AppendMessageWithFormat ("    %s (str)  = '%s'\n", m_name.c_str(), cstr);
+            else
+                result.AppendMessageWithFormat ("    %s (str)  = <no value>\n", m_name.c_str());
+        }
+        break;
+
+    case eTypeStringArray:
+        {
+            const size_t argc = m_string_values.GetArgumentCount();
+            result.AppendMessageWithFormat ("    %s (string vector):\n", m_name.c_str());
+            for (size_t i = 0; i < argc; ++i)
+                result.AppendMessageWithFormat ("      [%d] %s\n", i, m_string_values.GetArgumentAtIndex(i));
+        }
+        break;
+
+    default:
+        break;
+    }
+}
+
+void
+StateVariable::SetStringValue (const char *new_value)
+{
+    if (m_string_values.GetArgumentCount() > 0)
+        m_string_values.ReplaceArgumentAtIndex(0, new_value);
+    else
+        m_string_values.AppendArgument(new_value);
+}
+
+void
+StateVariable::SetIntValue (int new_value)
+{
+    m_int_value = new_value;
+}
+
+void
+StateVariable::SetBoolValue (bool new_value)
+{
+    m_int_value = new_value;
+}
+
+void
+StateVariable::AppendStringValue (const char *cstr)
+{
+    if (cstr && cstr[0])
+    {
+        if (m_string_values.GetArgumentCount() == 0)
+        {
+            m_string_values.AppendArgument(cstr);
+        }
+        else
+        {
+            const char *curr_arg = m_string_values.GetArgumentAtIndex(0);
+            if (curr_arg != NULL)
+            {
+                std::string new_arg_str(curr_arg);
+                new_arg_str += " ";
+                new_arg_str += cstr;
+                m_string_values.ReplaceArgumentAtIndex(0, new_arg_str.c_str());
+            }
+            else
+            {
+                m_string_values.ReplaceArgumentAtIndex(0, cstr);
+            }
+        }
+    }
+}
+
+bool
+StateVariable::VerifyValue (CommandInterpreter *interpreter, void *data, CommandReturnObject &result)
+{
+    return (*m_verification_func_ptr) (interpreter, data, result);
+}
+
+//void
+//StateVariable::SetArrayValue (STLStringArray &new_value)
+//{
+//    m_string_values.AppendArgument.append(cstr);
+//
+//    if (m_array_value != NULL)
+//    {
+//      if (m_array_value->size() > 0)
+//      {
+//          m_array_value->clear();
+//      }
+//    }
+//    else
+//        m_array_value = new STLStringArray;
+//
+//    for (int i = 0; i < new_value.size(); ++i)
+//        m_array_value->push_back (new_value[i]);
+//}
+//
+
+void
+StateVariable::ArrayClearValues ()
+{
+    m_string_values.Clear();
+}
+
+
+void
+StateVariable::ArrayAppendValue (const char *cstr)
+{
+    m_string_values.AppendArgument(cstr);
+}
+
+
+bool
+StateVariable::HasVerifyFunction ()
+{
+    return (m_verification_func_ptr != NULL);
+}
+
+// Verification functions for various command interpreter variables.
+
+bool
+StateVariable::VerifyScriptLanguage (CommandInterpreter *interpreter, void *data, CommandReturnObject &result)
+{
+    bool valid_lang = true;
+    interpreter->SetScriptLanguage (Args::StringToScriptLanguage((char *) data, eScriptLanguageDefault, &valid_lang));
+    return valid_lang;
+}
+
+bool
+StateVariable::BroadcastPromptChange (CommandInterpreter *interpreter, void *data, CommandReturnObject &result)
+{
+    char *prompt = (char *) data;
+    if (prompt != NULL)
+    {
+        std::string tmp_prompt = prompt ;
+        int len = tmp_prompt.size();
+        if (len > 1
+            && (tmp_prompt[0] == '\'' || tmp_prompt[0] == '"')
+            && (tmp_prompt[len-1] == tmp_prompt[0]))
+        {
+            tmp_prompt = tmp_prompt.substr(1,len-2);
+        }
+        len = tmp_prompt.size();
+        if (tmp_prompt[len-1] != ' ')
+            tmp_prompt.append(" ");
+        strcpy (prompt, tmp_prompt.c_str());
+        data = (void *) prompt;
+    }
+    EventSP new_event_sp;
+    new_event_sp.reset (new Event(CommandInterpreter::eBroadcastBitResetPrompt, new EventDataBytes (prompt)));
+    interpreter->BroadcastEvent (new_event_sp);
+
+    return true;
+}
+
diff --git a/source/Interpreter/embedded_interpreter.py b/source/Interpreter/embedded_interpreter.py
new file mode 100644
index 0000000..38b2f9e
--- /dev/null
+++ b/source/Interpreter/embedded_interpreter.py
@@ -0,0 +1,90 @@
+import readline
+import code
+import sys
+import traceback
+
+class SimpleREPL(code.InteractiveConsole):
+   def __init__(self, prompt, dict):
+       code.InteractiveConsole.__init__(self,dict)
+       self.prompt = prompt
+       self.loop_exit = False
+       self.dict = dict
+
+   def interact(self):
+       try:
+           sys.ps1
+       except AttributeError:
+           sys.ps1 = ">>> "
+       try:
+           sys.ps2
+       except AttributeError:
+           sys.ps2 = "... "
+
+       while not self.loop_exit:
+           try:
+               self.read_py_command()
+           except (SystemExit, EOFError):
+               # EOF while in Python just breaks out to top level.
+               self.write('\n')
+               self.loop_exit = True
+               break
+           except KeyboardInterrupt:
+               self.write("\nKeyboardInterrupt\n")
+               self.resetbuffer()
+               more = 0
+           except:
+               traceback.print_exc()
+
+   def process_input (self, in_str):
+      # Canonicalize the format of the input string
+      temp_str = in_str
+      temp_str.strip(' \t')
+      words = temp_str.split()
+      temp_str = ('').join(words)
+
+      # Check the input string to see if it was the quit
+      # command.  If so, intercept it, so that it doesn't
+      # close stdin on us!
+      if (temp_str.lower() == "quit()"):
+         self.loop_exit = True
+         in_str = "raise SystemExit "
+      return in_str
+
+   def my_raw_input (self, prompt):
+      stream = sys.stdout
+      stream.write (prompt)
+      stream.flush ()
+      try:
+         line = sys.stdin.readline()
+      except KeyboardInterrupt:
+         line = " \n"
+      except (SystemExit, EOFError):
+         line = "quit()\n"
+      if not line:
+         raise EOFError
+      if line[-1] == '\n':
+         line = line[:-1]
+      return line
+
+   def read_py_command(self):
+       # Read off a complete Python command.
+       more = 0
+       while 1:
+           if more:
+               prompt = sys.ps2
+           else:
+               prompt = sys.ps1
+           line = self.my_raw_input(prompt)
+           # Can be None if sys.stdin was redefined
+           encoding = getattr(sys.stdin, "encoding", None)
+           if encoding and not isinstance(line, unicode):
+               line = line.decode(encoding)
+           line = self.process_input (line)
+           more = self.push(line)
+           if not more:
+               break
+
+def run_python_interpreter (dict):
+   # Pass in the dictionary, for continuity from one session to the next.
+   repl = SimpleREPL('>>> ', dict)
+   repl.interact()
diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
new file mode 100644
index 0000000..09cc09d
--- /dev/null
+++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
@@ -0,0 +1,578 @@
+//===-- ABIMacOSX_i386.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ABIMacOSX_i386.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+#include "llvm/ADT/Triple.h"
+
+#include <vector>
+
+using namespace lldb;
+using namespace lldb_private;
+
+static const char *pluginName = "ABIMacOSX_i386";
+static const char *pluginDesc = "Mac OS X ABI for i386 targets";
+static const char *pluginShort = "abi.macosx-i386";
+
+size_t
+ABIMacOSX_i386::GetRedZoneSize () const
+{
+    return 0;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+lldb_private::ABI *
+ABIMacOSX_i386::CreateInstance (const ConstString &triple)
+{
+    llvm::StringRef tripleStr(triple.GetCString());
+    llvm::Triple llvmTriple(tripleStr);
+    
+    if (llvmTriple.getArch() != llvm::Triple::x86)
+        return NULL;
+    
+    return new ABIMacOSX_i386;
+}
+
+bool
+ABIMacOSX_i386::PrepareTrivialCall (Thread &thread, 
+                                    lldb::addr_t sp, 
+                                    lldb::addr_t functionAddress, 
+                                    lldb::addr_t returnAddress, 
+                                    lldb::addr_t arg) const
+{
+    RegisterContext *reg_ctx = thread.GetRegisterContext();
+    if (!reg_ctx)
+        return false;
+    
+    uint32_t ebpID = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
+    uint32_t eipID = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+    uint32_t espID = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+    
+    // Make room for the argument on the stack
+    
+    sp -= 4;
+    
+    // Align the SP
+    
+    sp &= ~(0xfull); // 16-byte alignment
+    
+    // Write the argument on the stack
+    
+    uint32_t argU32 = arg & 0xffffffffull;
+    Error error;
+    if (thread.GetProcess().WriteMemory (sp, &argU32, sizeof(argU32), error) != sizeof(argU32))
+        return false;
+    
+    // The return address is pushed onto the stack.
+    
+    sp -= 4;
+    uint32_t returnAddressU32 = returnAddress;
+    if (thread.GetProcess().WriteMemory (sp, &returnAddressU32, sizeof(returnAddressU32), error) != sizeof(returnAddressU32))
+        return false;
+    
+    // %esp is set to the actual stack value.
+    
+    if (!reg_ctx->WriteRegisterFromUnsigned(espID, sp))
+        return false;
+    
+    // %ebp is set to a fake value, in our case 0x0x00000000
+    
+    if (!reg_ctx->WriteRegisterFromUnsigned(ebpID, 0x00000000))
+        return false;
+    
+    // %eip is set to the address of the called function.
+    
+    if (!reg_ctx->WriteRegisterFromUnsigned(eipID, functionAddress))
+        return false;
+    
+    return true;
+}
+
+bool
+ABIMacOSX_i386::PrepareNormalCall (Thread &thread,
+                                   lldb::addr_t sp,
+                                   lldb::addr_t functionAddress,
+                                   lldb::addr_t returnAddress,
+                                   ValueList &args) const
+{
+    RegisterContext *reg_ctx = thread.GetRegisterContext();
+    if (!reg_ctx)
+        return false;
+    Error error;
+    uint32_t ebpID = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
+    uint32_t eipID = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+    uint32_t espID = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+    
+    // Do the argument layout
+    
+    std::vector <uint32_t> argLayout;   // 4-byte chunks, as discussed in the ABI Function Call Guide
+    
+    size_t numArgs = args.GetSize();
+    size_t index;
+    
+    for (index = 0; index < numArgs; ++index)
+    {
+        Value *val = args.GetValueAtIndex(index);
+        
+        if (!val)
+            return false;
+        
+        switch (val->GetValueType())
+        {
+        case Value::eValueTypeScalar:
+            {
+                Scalar &scalar = val->GetScalar();
+                switch (scalar.GetType())
+                {
+                case Scalar::e_void:
+                default:
+                    return false;
+                case Scalar::e_sint: 
+                case Scalar::e_uint:
+                case Scalar::e_slong:
+                case Scalar::e_ulong:
+                case Scalar::e_slonglong:
+                case Scalar::e_ulonglong:
+                    {
+                        uint64_t data = scalar.ULongLong();
+                        
+                        switch (scalar.GetByteSize())
+                        {
+                        default:
+                            return false;
+                        case 1:
+                            argLayout.push_back((uint32_t)(data & 0xffull));
+                            break;
+                        case 2:
+                            argLayout.push_back((uint32_t)(data & 0xffffull));
+                            break;
+                        case 4:
+                            argLayout.push_back((uint32_t)(data & 0xffffffffull));
+                            break;
+                        case 8:
+                            argLayout.push_back((uint32_t)(data & 0xffffffffull));
+                            argLayout.push_back((uint32_t)(data >> 32));
+                            break;
+                        }
+                    }
+                    break;
+                case Scalar::e_float:
+                    {
+                        float data = scalar.Float();
+                        uint32_t dataRaw = *((uint32_t*)(&data));
+                        argLayout.push_back(dataRaw);
+                    }
+                    break;
+                case Scalar::e_double:
+                    {
+                        double data = scalar.Double();
+                        uint32_t *dataRaw = ((uint32_t*)(&data));
+                        argLayout.push_back(dataRaw[0]);
+                        argLayout.push_back(dataRaw[1]);
+                    }
+                    break;
+                case Scalar::e_long_double:
+                    {
+                        long double data = scalar.Double();
+                        uint32_t *dataRaw = ((uint32_t*)(&data));
+                        while ((argLayout.size() * 4) & 0xf)
+                            argLayout.push_back(0);
+                        argLayout.push_back(dataRaw[0]);
+                        argLayout.push_back(dataRaw[1]);
+                        argLayout.push_back(dataRaw[2]);
+                        argLayout.push_back(dataRaw[3]);
+                    }
+                    break;
+                }
+            }
+            break;
+        case Value::eValueTypeHostAddress:
+            switch (val->GetContextType()) 
+            {
+            default:
+                return false;
+            case Value::eContextTypeOpaqueClangQualType:
+                {
+                    void *val_type = val->GetOpaqueClangQualType();
+                    uint32_t cstr_length;
+                    
+                    if (ClangASTContext::IsCStringType (val_type, cstr_length))
+                    {
+                        const char *cstr = (const char*)val->GetScalar().ULongLong();
+                        cstr_length = strlen(cstr);
+                        
+                        // Push the string onto the stack immediately.
+                        
+                        sp -= (cstr_length + 1);
+                        
+                        if (thread.GetProcess().WriteMemory(sp, cstr, cstr_length + 1, error) != (cstr_length + 1))
+                            return false;
+                        
+                        // Put the address of the string into the argument array.
+                        
+                        argLayout.push_back((uint32_t)(sp & 0xffffffff));
+                    }
+                    else
+                    {
+                        return false;
+                    }
+                }
+                break;
+            }
+            break;
+        case Value::eValueTypeFileAddress:
+        case Value::eValueTypeLoadAddress:
+        default:
+            return false;
+        }
+    }
+    
+    // Make room for the arguments on the stack
+    
+    sp -= 4 * argLayout.size();
+    
+    // Align the SP
+    
+    sp &= ~(0xfull); // 16-byte alignment
+    
+    // Write the arguments on the stack
+    
+    size_t numChunks = argLayout.size();
+
+    for (index = 0; index < numChunks; ++index)
+        if (thread.GetProcess().WriteMemory(sp + (index * 4), &argLayout[index], sizeof(uint32_t), error) != sizeof(uint32_t))
+            return false;
+    
+    // The return address is pushed onto the stack.
+    
+    sp -= 4;
+    uint32_t returnAddressU32 = returnAddress;
+    if (thread.GetProcess().WriteMemory (sp, &returnAddressU32, sizeof(returnAddressU32), error) != sizeof(returnAddressU32))
+        return false;
+    
+    // %esp is set to the actual stack value.
+    
+    if (!reg_ctx->WriteRegisterFromUnsigned(espID, sp))
+        return false;
+    
+    // %ebp is set to a fake value, in our case 0x0x00000000
+    
+    if (!reg_ctx->WriteRegisterFromUnsigned(ebpID, 0x00000000))
+        return false;
+    
+    // %eip is set to the address of the called function.
+    
+    if (!reg_ctx->WriteRegisterFromUnsigned(eipID, functionAddress))
+        return false;
+    
+    return true;    
+}
+
+static bool ReadIntegerArgument(Scalar           &scalar,
+                                unsigned int     bit_width,
+                                bool             is_signed,
+                                Process          &process,
+                                addr_t           &current_stack_argument)
+{
+    if (bit_width > 64)
+        return false; // Scalar can't hold large integer arguments
+    
+    uint64_t arg_contents;
+    uint32_t read_data;
+    Error error;
+    
+    if (bit_width > 32)
+    {
+        if (process.ReadMemory(current_stack_argument, &read_data, sizeof(read_data), error) != sizeof(read_data))
+            return false;
+        
+        arg_contents = read_data;
+        
+        if (process.ReadMemory(current_stack_argument + 4, &read_data, sizeof(read_data), error) != sizeof(read_data))
+            return false;
+        
+        arg_contents |= ((uint64_t)read_data) << 32;
+        
+        current_stack_argument += 8;
+    }
+    else {
+        if (process.ReadMemory(current_stack_argument, &read_data, sizeof(read_data), error) != sizeof(read_data))
+            return false;
+        
+        arg_contents = read_data;
+        
+        current_stack_argument += 4;
+    }
+    
+    if (is_signed)
+    {
+        switch (bit_width)
+        {
+        default:
+            return false;
+        case 8:
+            scalar = (int8_t)(arg_contents & 0xff);
+            break;
+        case 16:
+            scalar = (int16_t)(arg_contents & 0xffff);
+            break;
+        case 32:
+            scalar = (int32_t)(arg_contents & 0xffffffff);
+            break;
+        case 64:
+            scalar = (int64_t)arg_contents;
+            break;
+        }
+    }
+    else
+    {
+        switch (bit_width)
+        {
+        default:
+            return false;
+        case 8:
+            scalar = (uint8_t)(arg_contents & 0xff);
+            break;
+        case 16:
+            scalar = (uint16_t)(arg_contents & 0xffff);
+            break;
+        case 32:
+            scalar = (uint32_t)(arg_contents & 0xffffffff);
+            break;
+        case 64:
+            scalar = (uint64_t)arg_contents;
+            break;
+        }
+    }
+    
+    return true;
+}
+
+bool
+ABIMacOSX_i386::GetArgumentValues (Thread &thread,
+                                   ValueList &values) const
+{
+    unsigned int num_values = values.GetSize();
+    unsigned int value_index;
+    
+    // Extract the Clang AST context from the PC so that we can figure out type
+    // sizes
+    
+    clang::ASTContext *ast_context = thread.CalculateTarget()->GetScratchClangASTContext()->getASTContext();
+    
+    // Get the pointer to the first stack argument so we have a place to start 
+    // when reading data
+    
+    RegisterContext *reg_ctx = thread.GetRegisterContext();
+    
+    if (!reg_ctx)
+        return false;
+    
+    addr_t sp = reg_ctx->GetSP(0);
+    
+    if (!sp)
+        return false;
+    
+    addr_t current_stack_argument = sp + 4; // jump over return address
+    
+    for (value_index = 0;
+         value_index < num_values;
+         ++value_index)
+    {
+        Value *value = values.GetValueAtIndex(value_index);
+        
+        if (!value)
+            return false;
+        
+        // We currently only support extracting values with Clang QualTypes.
+        // Do we care about others?
+        switch (value->GetContextType())
+        {
+            default:
+                return false;
+            case Value::eContextTypeOpaqueClangQualType:
+            {
+                void *value_type = value->GetOpaqueClangQualType();
+                bool is_signed;
+                
+                if (ClangASTContext::IsIntegerType (value_type, is_signed))
+                {
+                    size_t bit_width = ClangASTContext::GetTypeBitSize(ast_context, value_type);
+                    
+                    ReadIntegerArgument(value->GetScalar(),
+                                        bit_width, 
+                                        is_signed,
+                                        thread.GetProcess(), 
+                                        current_stack_argument);
+                }
+                else if (ClangASTContext::IsPointerType (value_type))
+                {
+                    ReadIntegerArgument(value->GetScalar(),
+                                        32,
+                                        false,
+                                        thread.GetProcess(),
+                                        current_stack_argument);
+                }
+            }
+                break;
+        }
+    }
+    
+    return true;
+}
+
+bool
+ABIMacOSX_i386::GetReturnValue (Thread &thread,
+                                Value &value) const
+{
+    switch (value.GetContextType())
+    {
+        default:
+            return false;
+        case Value::eContextTypeOpaqueClangQualType:
+        {
+            // Extract the Clang AST context from the PC so that we can figure out type
+            // sizes
+            
+            clang::ASTContext *ast_context = thread.CalculateTarget()->GetScratchClangASTContext()->getASTContext();
+            
+            // Get the pointer to the first stack argument so we have a place to start 
+            // when reading data
+            
+            RegisterContext *reg_ctx = thread.GetRegisterContext();
+            
+            void *value_type = value.GetOpaqueClangQualType();
+            bool is_signed;
+            
+            if (ClangASTContext::IsIntegerType (value_type, is_signed))
+            {
+                size_t bit_width = ClangASTContext::GetTypeBitSize(ast_context, value_type);
+                
+                unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->reg;
+                unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->reg;
+                
+                switch (bit_width)
+                {
+                    default:
+                    case 128:
+                        // Scalar can't hold 128-bit literals, so we don't handle this
+                        return false;
+                    case 64:
+                        uint64_t raw_value;
+                        raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff;
+                        raw_value |= (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) & 0xffffffff) << 32;
+                        if (is_signed)
+                            value.GetScalar() = (int64_t)raw_value;
+                        else
+                            value.GetScalar() = (uint64_t)raw_value;
+                        break;
+                    case 32:
+                        if (is_signed)
+                            value.GetScalar() = (int32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
+                        else
+                            value.GetScalar() = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
+                        break;
+                    case 16:
+                        if (is_signed)
+                            value.GetScalar() = (int16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff);
+                        else
+                            value.GetScalar() = (uint16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff);
+                        break;
+                    case 8:
+                        if (is_signed)
+                            value.GetScalar() = (int8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff);
+                        else
+                            value.GetScalar() = (uint8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff);
+                        break;
+                }
+            }
+            else if (ClangASTContext::IsPointerType (value_type))
+            {
+                unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->reg;
+                uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff;
+                value.GetScalar() = ptr;
+            }
+            else
+            {
+                // not handled yet
+                return false;
+            }
+        }
+            break;
+    }
+    
+    return true;
+}
+
+void
+ABIMacOSX_i386::Initialize()
+{
+    PluginManager::RegisterPlugin (pluginName,
+                                   pluginDesc,
+                                   CreateInstance);    
+}
+
+void
+ABIMacOSX_i386::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+const char *
+ABIMacOSX_i386::GetPluginName()
+{
+    return pluginName;
+}
+
+const char *
+ABIMacOSX_i386::GetShortPluginName()
+{
+    return pluginShort;
+}
+
+uint32_t
+ABIMacOSX_i386::GetPluginVersion()
+{
+    return 1;
+}
+
+void
+ABIMacOSX_i386::GetPluginCommandHelp (const char *command, Stream *strm)
+{
+}
+
+Error
+ABIMacOSX_i386::ExecutePluginCommand (Args &command, Stream *strm)
+{
+    Error error;
+    error.SetErrorString("No plug-in command are currently supported.");
+    return error;
+}
+
+Log *
+ABIMacOSX_i386::EnablePluginLogging (Stream *strm, Args &command)
+{
+    return NULL;
+}
diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
new file mode 100644
index 0000000..c27569b
--- /dev/null
+++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
@@ -0,0 +1,93 @@
+//===-- ABIMacOSX_i386.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_ABIMacOSX_i386_h_
+#define liblldb_ABIMacOSX_i386_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ABI.h"
+#include "lldb/Core/Value.h"
+
+namespace lldb_private {
+    
+    class ABIMacOSX_i386 :
+    public lldb_private::ABI
+    {
+    public:
+        ~ABIMacOSX_i386() { }
+        
+        virtual size_t 
+        GetRedZoneSize () const;
+        
+        virtual bool
+        PrepareTrivialCall (Thread &thread, 
+                            lldb::addr_t sp,
+                            lldb::addr_t functionAddress,
+                            lldb::addr_t returnAddress, 
+                            lldb::addr_t arg) const;
+        
+        virtual bool
+        PrepareNormalCall (Thread &thread,
+                           lldb::addr_t sp,
+                           lldb::addr_t functionAddress,
+                           lldb::addr_t returnAddress,
+                           ValueList &args) const;
+        
+        virtual bool
+        GetArgumentValues (Thread &thread,
+                           ValueList &values) const;
+        
+        virtual bool
+        GetReturnValue (Thread &thread,
+                        Value &value) const;
+        
+        //------------------------------------------------------------------
+        // Static Functions
+        //------------------------------------------------------------------
+        static void
+        Initialize();
+        
+        static void
+        Terminate();
+        
+        static lldb_private::ABI *
+        CreateInstance (const ConstString &triple);
+        
+        //------------------------------------------------------------------
+        // PluginInterface protocol
+        //------------------------------------------------------------------
+        virtual const char *
+        GetPluginName();
+        
+        virtual const char *
+        GetShortPluginName();
+        
+        virtual uint32_t
+        GetPluginVersion();
+        
+        virtual void
+        GetPluginCommandHelp (const char *command, lldb_private::Stream *strm);
+        
+        virtual lldb_private::Error
+        ExecutePluginCommand (lldb_private::Args &command, lldb_private::Stream *strm);
+        
+        virtual lldb_private::Log *
+        EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
+    protected:
+    private:
+        ABIMacOSX_i386() : lldb_private::ABI() { } // Call CreateInstance instead.
+    };
+    
+} // namespace lldb_private
+
+#endif  // liblldb_ABI_h_
diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
new file mode 100644
index 0000000..004be60
--- /dev/null
+++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
@@ -0,0 +1,412 @@
+//===-- ABISysV_x86_64.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ABISysV_x86_64.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Thread.h"
+
+#include "llvm/ADT/Triple.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static const char *pluginName = "ABISysV_x86_64";
+static const char *pluginDesc = "System V ABI for x86_64 targets";
+static const char *pluginShort = "abi.sysv-x86_64";
+
+size_t
+ABISysV_x86_64::GetRedZoneSize () const
+{
+    return 128;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+lldb_private::ABI *
+ABISysV_x86_64::CreateInstance (const ConstString &triple)
+{
+    llvm::StringRef tripleStr(triple.GetCString());
+    llvm::Triple llvmTriple(tripleStr);
+
+    if (llvmTriple.getArch() != llvm::Triple::x86_64)
+        return NULL;
+
+    return new ABISysV_x86_64;
+}
+
+bool
+ABISysV_x86_64::PrepareTrivialCall (Thread &thread, 
+                                    lldb::addr_t sp, 
+                                    lldb::addr_t functionAddress, 
+                                    lldb::addr_t returnAddress, 
+                                    lldb::addr_t arg) const
+{
+    RegisterContext *reg_ctx = thread.GetRegisterContext();
+    if (!reg_ctx)
+        return false;
+
+    uint32_t rdiID = reg_ctx->GetRegisterInfoByName("rdi", 0)->reg;
+    uint32_t rbpID = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
+    uint32_t ripID = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+    uint32_t rspID = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+
+    // The argument is in %rdi, and not on the stack.
+
+    if (!reg_ctx->WriteRegisterFromUnsigned(rdiID, arg))
+        return false;
+
+    // First, align the SP
+
+    sp &= ~(0xfull); // 16-byte alignment
+
+    // The return address is pushed onto the stack.
+
+    sp -= 8;
+    uint64_t returnAddressU64 = returnAddress;
+    Error error;
+    if (thread.GetProcess().WriteMemory (sp, &returnAddressU64, sizeof(returnAddressU64), error) != sizeof(returnAddressU64))
+        return false;
+
+    // %rsp is set to the actual stack value.
+
+    if (!reg_ctx->WriteRegisterFromUnsigned(rspID, sp))
+        return false;
+
+    // %rbp is set to a fake value, in our case 0x0000000000000000.
+
+    if (!reg_ctx->WriteRegisterFromUnsigned(rbpID, 0x000000000000000))
+        return false;
+
+    // %rip is set to the address of the called function.
+
+    if (!reg_ctx->WriteRegisterFromUnsigned(ripID, functionAddress))
+        return false;
+
+    return true;
+}
+
+bool
+ABISysV_x86_64::PrepareNormalCall (Thread &thread,
+                                   lldb::addr_t sp,
+                                   lldb::addr_t functionAddress,
+                                   lldb::addr_t returnAddress,
+                                   ValueList &args) const
+{
+    return false;    
+}
+
+static bool ReadIntegerArgument(Scalar           &scalar,
+                                unsigned int     bit_width,
+                                bool             is_signed,
+                                Thread           &thread,
+                                uint32_t         *argument_register_ids,
+                                unsigned int     &current_argument_register,
+                                addr_t           &current_stack_argument)
+{
+    if (bit_width > 64)
+        return false; // Scalar can't hold large integer arguments
+    
+    uint64_t arg_contents;
+    
+    if (current_argument_register < 6)
+    {
+        arg_contents = thread.GetRegisterContext()->ReadRegisterAsUnsigned(argument_register_ids[current_argument_register], 0);
+        current_argument_register++;
+    }
+    else
+    {
+        uint8_t arg_data[sizeof(arg_contents)];
+        Error error;
+        thread.GetProcess().ReadMemory(current_stack_argument, arg_data, sizeof(arg_contents), error);
+        DataExtractor arg_data_extractor(arg_data, sizeof(arg_contents), thread.GetProcess().GetByteOrder(), thread.GetProcess().GetAddressByteSize());
+        uint32_t offset = 0;
+        arg_contents = arg_data_extractor.GetMaxU64(&offset, bit_width / 8);
+        if (!offset)
+            return false;
+        current_stack_argument += (bit_width / 8);
+    }
+    
+    if (is_signed)
+    {
+        switch (bit_width)
+        {
+        default:
+            return false;
+        case 8:
+            scalar = (int8_t)(arg_contents & 0xff);
+            break;
+        case 16:
+            scalar = (int16_t)(arg_contents & 0xffff);
+            break;
+        case 32:
+            scalar = (int32_t)(arg_contents & 0xffffffff);
+            break;
+        case 64:
+            scalar = (int64_t)arg_contents;
+            break;
+        }
+    }
+    else
+    {
+        switch (bit_width)
+        {
+        default:
+            return false;
+        case 8:
+            scalar = (uint8_t)(arg_contents & 0xff);
+            break;
+        case 16:
+            scalar = (uint16_t)(arg_contents & 0xffff);
+            break;
+        case 32:
+            scalar = (uint32_t)(arg_contents & 0xffffffff);
+            break;
+        case 64:
+            scalar = (uint64_t)arg_contents;
+            break;
+        }
+    }
+    
+    return true;
+}
+
+bool
+ABISysV_x86_64::GetArgumentValues (Thread &thread,
+                                   ValueList &values) const
+{
+    unsigned int num_values = values.GetSize();
+    unsigned int value_index;
+    
+    // For now, assume that the types in the AST values come from the Target's 
+    // scratch AST.    
+    
+    clang::ASTContext *ast_context = thread.CalculateTarget()->GetScratchClangASTContext()->getASTContext();
+    
+    // Extract the register context so we can read arguments from registers
+    
+    RegisterContext *reg_ctx = thread.GetRegisterContext();
+    
+    if (!reg_ctx)
+        return false;
+    
+    // Get the pointer to the first stack argument so we have a place to start 
+    // when reading data
+    
+    addr_t sp = reg_ctx->GetSP(0);
+    
+    if (!sp)
+        return false;
+    
+    addr_t current_stack_argument = sp + 8; // jump over return address
+    
+    uint32_t argument_register_ids[6];
+    
+    argument_register_ids[0] = reg_ctx->GetRegisterInfoByName("rdi", 0)->reg;
+    argument_register_ids[1] = reg_ctx->GetRegisterInfoByName("rsi", 0)->reg;
+    argument_register_ids[2] = reg_ctx->GetRegisterInfoByName("rdx", 0)->reg;
+    argument_register_ids[3] = reg_ctx->GetRegisterInfoByName("rcx", 0)->reg;
+    argument_register_ids[4] = reg_ctx->GetRegisterInfoByName("r8", 0)->reg;
+    argument_register_ids[5] = reg_ctx->GetRegisterInfoByName("r9", 0)->reg;
+    
+    unsigned int current_argument_register = 0;
+    
+    for (value_index = 0;
+         value_index < num_values;
+         ++value_index)
+    {
+        Value *value = values.GetValueAtIndex(value_index);
+    
+        if (!value)
+            return false;
+        
+        // We currently only support extracting values with Clang QualTypes.
+        // Do we care about others?
+        switch (value->GetContextType())
+        {
+        default:
+            return false;
+        case Value::eContextTypeOpaqueClangQualType:
+            {
+                void *value_type = value->GetOpaqueClangQualType();
+                bool is_signed;
+                
+                if (ClangASTContext::IsIntegerType (value_type, is_signed))
+                {
+                    size_t bit_width = ClangASTContext::GetTypeBitSize(ast_context, value_type);
+                    
+                    ReadIntegerArgument(value->GetScalar(),
+                                        bit_width, 
+                                        is_signed,
+                                        thread, 
+                                        argument_register_ids, 
+                                        current_argument_register,
+                                        current_stack_argument);
+                }
+                else if (ClangASTContext::IsPointerType (value_type))
+                {
+                    ReadIntegerArgument(value->GetScalar(),
+                                        64,
+                                        false,
+                                        thread,
+                                        argument_register_ids, 
+                                        current_argument_register,
+                                        current_stack_argument);
+                }
+            }
+            break;
+        }
+    }
+    
+    return true;
+}
+
+bool
+ABISysV_x86_64::GetReturnValue (Thread &thread,
+                                Value &value) const
+{
+    switch (value.GetContextType())
+    {
+        default:
+            return false;
+        case Value::eContextTypeOpaqueClangQualType:
+        {
+            void *value_type = value.GetOpaqueClangQualType();
+            bool is_signed;
+            
+            RegisterContext *reg_ctx = thread.GetRegisterContext();
+            
+            if (!reg_ctx)
+                return false;
+            
+            if (ClangASTContext::IsIntegerType (value_type, is_signed))
+            {
+                // For now, assume that the types in the AST values come from the Target's 
+                // scratch AST.    
+                
+                clang::ASTContext *ast_context = thread.CalculateTarget()->GetScratchClangASTContext()->getASTContext();
+                
+                // Extract the register context so we can read arguments from registers
+                
+                size_t bit_width = ClangASTContext::GetTypeBitSize(ast_context, value_type);
+                unsigned rax_id = reg_ctx->GetRegisterInfoByName("rax", 0)->reg;
+                
+                switch (bit_width)
+                {
+                default:
+                case 128:
+                    // Scalar can't hold 128-bit literals, so we don't handle this
+                    return false;
+                case 64:
+                    if (is_signed)
+                        value.GetScalar() = (int64_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0));
+                    else
+                        value.GetScalar() = (uint64_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0));
+                    break;
+                case 32:
+                    if (is_signed)
+                        value.GetScalar() = (int32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffffffff);
+                    else
+                        value.GetScalar() = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffffffff);
+                    break;
+                case 16:
+                    if (is_signed)
+                        value.GetScalar() = (int16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffff);
+                    else
+                        value.GetScalar() = (uint16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffff);
+                    break;
+                case 8:
+                    if (is_signed)
+                        value.GetScalar() = (int8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xff);
+                    else
+                        value.GetScalar() = (uint8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xff);
+                    break;
+                }
+            }
+            else if (ClangASTContext::IsPointerType (value_type))
+            {
+                unsigned rax_id = reg_ctx->GetRegisterInfoByName("rax", 0)->reg;
+                value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0);
+            }
+            else
+            {
+                // not handled yet
+                return false;
+            }
+        }
+        break;
+    }
+    
+    return true;
+}
+
+void
+ABISysV_x86_64::Initialize()
+{
+    PluginManager::RegisterPlugin (pluginName,
+                                   pluginDesc,
+                                   CreateInstance);
+}
+
+void
+ABISysV_x86_64::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+const char *
+ABISysV_x86_64::GetPluginName()
+{
+    return pluginName;
+}
+
+const char *
+ABISysV_x86_64::GetShortPluginName()
+{
+    return pluginShort;
+}
+
+uint32_t
+ABISysV_x86_64::GetPluginVersion()
+{
+    return 1;
+}
+
+void
+ABISysV_x86_64::GetPluginCommandHelp (const char *command, Stream *strm)
+{
+}
+
+Error
+ABISysV_x86_64::ExecutePluginCommand (Args &command, Stream *strm)
+{
+    Error error;
+    error.SetErrorString("No plug-in command are currently supported.");
+    return error;
+}
+
+Log *
+ABISysV_x86_64::EnablePluginLogging (Stream *strm, Args &command)
+{
+    return NULL;
+}
diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
new file mode 100644
index 0000000..b89d7c6
--- /dev/null
+++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
@@ -0,0 +1,92 @@
+//===-- ABISysV_x86_64.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_ABISysV_x86_64_h_
+#define liblldb_ABISysV_x86_64_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ABI.h"
+
+namespace lldb_private {
+
+class ABISysV_x86_64 :
+    public lldb_private::ABI
+{
+public:
+   ~ABISysV_x86_64() { }
+
+    virtual size_t
+    GetRedZoneSize () const;
+
+    virtual bool
+    PrepareTrivialCall (Thread &thread, 
+                        lldb::addr_t sp,
+                        lldb::addr_t functionAddress,
+                        lldb::addr_t returnAddress, 
+                        lldb::addr_t arg) const;
+    
+    virtual bool
+    PrepareNormalCall (Thread &thread,
+                       lldb::addr_t sp,
+                       lldb::addr_t functionAddress,
+                       lldb::addr_t returnAddress,
+                       ValueList &args) const;
+    
+    virtual bool
+    GetArgumentValues (Thread &thread,
+                       ValueList &values) const;
+    
+    virtual bool
+    GetReturnValue (Thread &thread,
+                    Value &value) const;
+    
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static lldb_private::ABI *
+    CreateInstance (const ConstString &triple);
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual const char *
+    GetPluginName();
+
+    virtual const char *
+    GetShortPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+    virtual void
+    GetPluginCommandHelp (const char *command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Error
+    ExecutePluginCommand (lldb_private::Args &command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Log *
+    EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
+protected:
+private:
+    ABISysV_x86_64() : lldb_private::ABI() { } // Call CreateInstance instead.
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_ABI_h_
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp
new file mode 100644
index 0000000..db2d561
--- /dev/null
+++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp
@@ -0,0 +1,468 @@
+//===-- DisassemblerLLVM.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DisassemblerLLVM.h"
+
+#include "llvm-c/EnhancedDisassembly.h"
+
+#include "lldb/Core/Address.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Symbol/SymbolContext.h"
+
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+
+#include <memory>
+#include <string>
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+static
+int DataExtractorByteReader(uint8_t *byte, uint64_t address, void *arg)
+{
+    DataExtractor &extractor = *((DataExtractor *)arg);
+
+    if (extractor.ValidOffset(address))
+    {
+        *byte = *(extractor.GetDataStart() + address);
+        return 0;
+    }
+    else
+    {
+        return -1;
+    }
+}
+
+namespace {
+    struct RegisterReaderArg {
+        const lldb::addr_t instructionPointer;
+        const EDDisassemblerRef disassembler;
+
+        RegisterReaderArg(lldb::addr_t ip,
+                          EDDisassemblerRef dis) :
+            instructionPointer(ip),
+            disassembler(dis)
+        {
+        }
+    };
+}
+
+static int IPRegisterReader(uint64_t *value, unsigned regID, void* arg)
+{
+    uint64_t instructionPointer = ((RegisterReaderArg*)arg)->instructionPointer;
+    EDDisassemblerRef disassembler = ((RegisterReaderArg*)arg)->disassembler;
+
+    if(EDRegisterIsProgramCounter(disassembler, regID)) {
+        *value = instructionPointer;
+        return 0;
+    }
+
+    return -1;
+}
+
+DisassemblerLLVM::Instruction::Instruction(EDDisassemblerRef disassembler) :
+    Disassembler::Instruction (),
+    m_disassembler (disassembler)
+{
+}
+
+DisassemblerLLVM::Instruction::~Instruction()
+{
+}
+
+static void
+PadString(Stream *s, const std::string &str, size_t width)
+{
+    int diff = width - str.length();
+
+    if (diff > 0)
+        s->Printf("%s%*.*s", str.c_str(), diff, diff, "");
+    else
+        s->Printf("%s ", str.c_str());
+}
+
+void
+DisassemblerLLVM::Instruction::Dump
+(
+    Stream *s,
+    lldb::addr_t base_address,
+    DataExtractor *bytes,
+    uint32_t bytes_offset,
+    const lldb_private::ExecutionContext exe_ctx,
+    bool raw
+)
+{
+    const size_t opcodeColumnWidth = 7;
+    const size_t operandColumnWidth = 25;
+
+    // If we have an address, print it out
+    if (base_address != LLDB_INVALID_ADDRESS)
+        s->Printf("0x%llx:  ", base_address);
+
+    // If we are supposed to show bytes, "bytes" will be non-NULL.
+    if (bytes)
+    {
+        uint32_t bytes_dumped = bytes->Dump(s, bytes_offset, eFormatBytes, 1, EDInstByteSize(m_inst), UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0) - bytes_offset;
+        // Allow for 8 bytes of opcodes normally
+        const uint32_t default_num_opcode_bytes = 9;
+        if (bytes_dumped * 3 < (default_num_opcode_bytes*3))
+        {
+            uint32_t indent_level = (default_num_opcode_bytes*3) - (bytes_dumped * 3);
+            s->Printf("%*.*s", indent_level, indent_level, "");
+        }
+    }
+
+    int numTokens = EDNumTokens(m_inst);
+
+    int currentOpIndex = -1;
+
+    RegisterReaderArg rra(base_address + EDInstByteSize(m_inst), m_disassembler);
+
+    lldb_private::Process *process = exe_ctx.process;
+
+    bool printTokenized = false;
+
+    if (numTokens != -1)
+    {
+        printTokenized = true;
+
+        // Handle the opcode column.
+
+        StreamString opcode;
+
+        int tokenIndex = 0;
+
+        EDTokenRef token;
+        const char *tokenStr;
+
+        if (EDGetToken(&token, m_inst, tokenIndex))
+            printTokenized = false;
+
+        if (!printTokenized || !EDTokenIsOpcode(token))
+            printTokenized = false;
+
+        if (!printTokenized || EDGetTokenString(&tokenStr, token))
+            printTokenized = false;
+
+        // Put the token string into our opcode string
+        opcode.PutCString(tokenStr);
+
+        // If anything follows, it probably starts with some whitespace.  Skip it.
+
+        tokenIndex++;
+
+        if (printTokenized && tokenIndex < numTokens)
+        {
+            if(!printTokenized || EDGetToken(&token, m_inst, tokenIndex))
+                printTokenized = false;
+
+            if(!printTokenized || !EDTokenIsWhitespace(token))
+                printTokenized = false;
+        }
+
+        tokenIndex++;
+
+        // Handle the operands and the comment.
+
+        StreamString operands;
+        StreamString comment;
+
+        if (printTokenized)
+        {
+            bool show_token;
+
+            for (; tokenIndex < numTokens; ++tokenIndex)
+            {
+                if (EDGetToken(&token, m_inst, tokenIndex))
+                    return;
+
+                if (raw)
+                {
+                    show_token = true;
+                }
+                else
+                {
+                    int operandIndex = EDOperandIndexForToken(token);
+
+                    if (operandIndex >= 0)
+                    {
+                        if (operandIndex != currentOpIndex)
+                        {
+                            show_token = true;
+
+                            currentOpIndex = operandIndex;
+                            EDOperandRef operand;
+
+                            if (!EDGetOperand(&operand, m_inst, currentOpIndex))
+                            {
+                                if (EDOperandIsMemory(operand))
+                                {
+                                    uint64_t operand_value;
+
+                                    if (!EDEvaluateOperand(&operand_value, operand, IPRegisterReader, &rra))
+                                    {
+                                        if (EDInstIsBranch(m_inst))
+                                        {
+                                            operands.Printf("0x%llx ", operand_value);
+                                            show_token = false;
+                                        }
+                                        else
+                                        {
+                                            // Put the address value into the comment
+                                            comment.Printf("0x%llx ", operand_value);
+                                        }
+
+                                        lldb_private::Address so_addr;
+                                        if (process)
+                                        {
+                                            if (process->ResolveLoadAddress(operand_value, so_addr))
+                                            {
+                                                so_addr.Dump(&comment, process, Address::DumpStyleResolvedDescription, Address::DumpStyleSectionNameOffset);
+                                            }
+                                        }
+                                    } // EDEvaluateOperand
+                                } // EDOperandIsMemory
+                            } // EDGetOperand
+                        } // operandIndex != currentOpIndex
+                    } // operandIndex >= 0
+                } // else(raw)
+
+                if (show_token)
+                {
+                    if(EDGetTokenString(&tokenStr, token))
+                    {
+                        printTokenized = false;
+                        break;
+                    }
+
+                    operands.PutCString(tokenStr);
+                }
+            } // for (tokenIndex)
+
+            if (printTokenized)
+            {
+                if (operands.GetString().empty())
+                {
+                    s->PutCString(opcode.GetString().c_str());
+                }
+                else
+                {
+                    PadString(s, opcode.GetString(), opcodeColumnWidth);
+
+                    if (comment.GetString().empty())
+                    {
+                        s->PutCString(operands.GetString().c_str());
+                    }
+                    else
+                    {
+                        PadString(s, operands.GetString(), operandColumnWidth);
+
+                        s->PutCString("; ");
+                        s->PutCString(comment.GetString().c_str());
+                    } // else (comment.GetString().empty())
+                } // else (operands.GetString().empty())
+            } // printTokenized
+        } // for (tokenIndex)
+    } // numTokens != -1
+
+    if (!printTokenized)
+    {
+        const char *str;
+
+        if (EDGetInstString(&str, m_inst))
+            return;
+        else
+            s->PutCString(str);
+    }
+}
+
+bool
+DisassemblerLLVM::Instruction::DoesBranch() const
+{
+    return EDInstIsBranch(m_inst);
+}
+
+size_t
+DisassemblerLLVM::Instruction::GetByteSize() const
+{
+    return EDInstByteSize(m_inst);
+}
+
+size_t
+DisassemblerLLVM::Instruction::Extract(const DataExtractor &data, uint32_t data_offset)
+{
+    if (EDCreateInsts(&m_inst, 1, m_disassembler, DataExtractorByteReader, data_offset, (void*)(&data)))
+        return EDInstByteSize(m_inst);
+    else
+        return 0;
+}
+
+static inline const char *
+TripleForCPU(cpu_type_t cpuType)
+{
+    switch (cpuType)
+    {
+    default:
+        return NULL;
+    case CPU_TYPE_X86:
+        return "i386-unknown-unknown";
+    case CPU_TYPE_X86_64:
+        return "x86_64-unknown-unknown";
+    }
+}
+
+static inline EDAssemblySyntax_t
+SyntaxForCPU(cpu_type_t cpuType)
+{
+    switch (cpuType)
+    {
+    default:
+        return (EDAssemblySyntax_t)0;   // default
+    case CPU_TYPE_X86:
+    case CPU_TYPE_X86_64:
+        return kEDAssemblySyntaxX86ATT;
+    }
+}
+
+Disassembler *
+DisassemblerLLVM::CreateInstance(const ArchSpec &arch)
+{
+    cpu_type_t cpuType = arch.GetCPUType();
+
+    if (TripleForCPU(cpuType))
+        return new DisassemblerLLVM(arch);
+    else
+        return NULL;
+}
+
+DisassemblerLLVM::DisassemblerLLVM(const ArchSpec &arch) :
+    Disassembler(arch)
+{
+    cpu_type_t cpuType = arch.GetCPUType();
+
+    const char *triple = TripleForCPU(cpuType);
+    assert(triple && "Unhandled CPU type!");
+
+    EDAssemblySyntax_t syntax = SyntaxForCPU(cpuType);
+
+    assert(!EDGetDisassembler(&m_disassembler, triple, syntax) && "No disassembler created!");
+}
+
+DisassemblerLLVM::~DisassemblerLLVM()
+{
+}
+
+size_t
+DisassemblerLLVM::ParseInstructions
+(
+    const DataExtractor& data,
+    uint32_t data_offset,
+    uint32_t num_instructions,
+    lldb::addr_t base_addr
+)
+{
+    size_t total_inst_byte_size = 0;
+
+    m_instruction_list.Clear();
+
+    while (data.ValidOffset(data_offset) && num_instructions)
+    {
+        Instruction::shared_ptr inst_sp (new Instruction(m_disassembler));
+
+        size_t inst_byte_size = inst_sp->Extract(data, data_offset);
+
+        if (inst_byte_size == 0)
+            break;
+
+        m_instruction_list.AppendInstruction(inst_sp);
+
+        total_inst_byte_size += inst_byte_size;
+        data_offset += inst_byte_size;
+        num_instructions--;
+    }
+
+    return total_inst_byte_size;
+}
+
+void
+DisassemblerLLVM::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance);
+}
+
+void
+DisassemblerLLVM::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+const char *
+DisassemblerLLVM::GetPluginNameStatic()
+{
+    return "disassembler.llvm";
+}
+
+const char *
+DisassemblerLLVM::GetPluginDescriptionStatic()
+{
+    return "Disassembler that uses LLVM opcode tables to disassemble i386 and x86_64.";
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+const char *
+DisassemblerLLVM::GetPluginName()
+{
+    return "DisassemblerLLVM";
+}
+
+const char *
+DisassemblerLLVM::GetShortPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+DisassemblerLLVM::GetPluginVersion()
+{
+    return 1;
+}
+
+void
+DisassemblerLLVM::GetPluginCommandHelp (const char *command, Stream *strm)
+{
+}
+
+Error
+DisassemblerLLVM::ExecutePluginCommand (Args &command, Stream *strm)
+{
+    Error error;
+    error.SetErrorString("No plug-in command are currently supported.");
+    return error;
+}
+
+Log *
+DisassemblerLLVM::EnablePluginLogging (Stream *strm, Args &command)
+{
+    return NULL;
+}
+
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVM.h b/source/Plugins/Disassembler/llvm/DisassemblerLLVM.h
new file mode 100644
index 0000000..98166cb
--- /dev/null
+++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVM.h
@@ -0,0 +1,111 @@
+//===-- DisassemblerLLVM.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_DisassemblerLLVM_h_
+#define liblldb_DisassemblerLLVM_h_
+
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Host/Mutex.h"
+
+struct EDDisassembler;
+typedef EDDisassembler *EDDisassemblerRef;
+
+struct EDInst;
+typedef EDInst *EDInstRef;
+
+class DisassemblerLLVM : public lldb_private::Disassembler
+{
+public:
+    class Instruction : public lldb_private::Disassembler::Instruction
+    {
+    public:
+        Instruction(EDDisassemblerRef disassembler);
+
+        virtual
+        ~Instruction();
+
+        void
+        Dump (lldb_private::Stream *s,
+              lldb::addr_t base_address,
+              lldb_private::DataExtractor *bytes,
+              uint32_t bytes_offset,
+              const lldb_private::ExecutionContext exe_ctx,
+              bool raw);
+
+        bool
+        DoesBranch () const;
+
+        size_t
+        GetByteSize() const;
+
+        size_t
+        Extract (const lldb_private::DataExtractor &data,
+                 uint32_t data_offset);
+
+    protected:
+        EDDisassemblerRef m_disassembler;
+        EDInstRef m_inst;
+    };
+
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static const char *
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb_private::Disassembler *
+    CreateInstance(const lldb_private::ArchSpec &arch);
+
+
+    DisassemblerLLVM(const lldb_private::ArchSpec &arch);
+
+    virtual
+    ~DisassemblerLLVM();
+
+    size_t
+    ParseInstructions (const lldb_private::DataExtractor& data,
+                       uint32_t data_offset,
+                       uint32_t num_instructions,
+                       lldb::addr_t base_addr);
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual const char *
+    GetPluginName();
+
+    virtual const char *
+    GetShortPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+    virtual void
+    GetPluginCommandHelp (const char *command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Error
+    ExecutePluginCommand (lldb_private::Args &command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Log *
+    EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
+
+protected:
+    EDDisassemblerRef m_disassembler;
+};
+
+#endif  // liblldb_DisassemblerLLVM_h_
diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
new file mode 100644
index 0000000..a8dbf05
--- /dev/null
+++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
@@ -0,0 +1,1129 @@
+//===-- DynamicLoaderMacOSXDYLD.cpp -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Core/DataBuffer.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/State.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlanRunToAddress.h"
+#include "lldb/Target/StackFrame.h"
+
+#include "DynamicLoaderMacOSXDYLD.h"
+#include "DynamicLoaderMacOSXDYLDLog.h"
+
+//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
+#ifdef ENABLE_DEBUG_PRINTF
+#include <stdio.h>
+#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
+#else
+#define DEBUG_PRINTF(fmt, ...)
+#endif
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+/// FIXME - The ObjC Runtime trampoline handler doesn't really belong here.
+/// I am putting it here so I can invoke it in the Trampoline code here, but
+/// it should be moved to the ObjC Runtime support when it is set up.
+
+//----------------------------------------------------------------------
+// Create an instance of this class. This function is filled into
+// the plugin info class that gets handed out by the plugin factory and
+// allows the lldb to instantiate an instance of this class.
+//----------------------------------------------------------------------
+DynamicLoader *
+DynamicLoaderMacOSXDYLD::CreateInstance (Process* process)
+{
+    return new DynamicLoaderMacOSXDYLD (process);
+}
+
+//----------------------------------------------------------------------
+// Constructor
+//----------------------------------------------------------------------
+DynamicLoaderMacOSXDYLD::DynamicLoaderMacOSXDYLD (Process* process) :
+    DynamicLoader(process),
+    m_dyld(),
+    m_dyld_all_image_infos_addr(LLDB_INVALID_ADDRESS),
+    m_dyld_all_image_infos(),
+    m_break_id(LLDB_INVALID_BREAK_ID),
+    m_dyld_image_infos(),
+    m_mutex(Mutex::eMutexTypeRecursive),
+    m_objc_trampoline_handler_ap(NULL)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+DynamicLoaderMacOSXDYLD::~DynamicLoaderMacOSXDYLD()
+{
+    Clear(true);
+}
+
+//------------------------------------------------------------------
+/// Called after attaching a process.
+///
+/// Allow DynamicLoader plug-ins to execute some code after
+/// attaching to a process.
+//------------------------------------------------------------------
+void
+DynamicLoaderMacOSXDYLD::DidAttach ()
+{
+    PrivateInitialize(m_process);
+    if (NeedToLocateDYLD ())
+        LocateDYLD ();
+    SetNotificationBreakpoint ();
+    UpdateAllImageInfos();
+}
+
+//------------------------------------------------------------------
+/// Called after attaching a process.
+///
+/// Allow DynamicLoader plug-ins to execute some code after
+/// attaching to a process.
+//------------------------------------------------------------------
+void
+DynamicLoaderMacOSXDYLD::DidLaunch ()
+{
+    PrivateInitialize(m_process);
+    if (NeedToLocateDYLD ())
+        LocateDYLD ();
+    SetNotificationBreakpoint ();
+    UpdateAllImageInfos();
+}
+
+
+//----------------------------------------------------------------------
+// Clear out the state of this class.
+//----------------------------------------------------------------------
+void
+DynamicLoaderMacOSXDYLD::Clear (bool clear_process)
+{
+    Mutex::Locker locker(m_mutex);
+
+    if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id))
+        m_process->ClearBreakpointSiteByID(m_break_id);
+
+    if (clear_process)
+        m_process = NULL;
+    m_dyld.Clear(false);
+    m_dyld_all_image_infos_addr = LLDB_INVALID_ADDRESS;
+    m_dyld_all_image_infos.Clear();
+    m_break_id = LLDB_INVALID_BREAK_ID;
+    m_dyld_image_infos.clear();
+}
+
+//----------------------------------------------------------------------
+// Check if we have found DYLD yet
+//----------------------------------------------------------------------
+bool
+DynamicLoaderMacOSXDYLD::DidSetNotificationBreakpoint() const
+{
+    return LLDB_BREAK_ID_IS_VALID (m_break_id);
+}
+
+//----------------------------------------------------------------------
+// Try and figure out where dyld is by first asking the Process
+// if it knows (which currently calls down in the the lldb::Process
+// to get the DYLD info (available on SnowLeopard only). If that fails,
+// then check in the default addresses.
+//----------------------------------------------------------------------
+bool
+DynamicLoaderMacOSXDYLD::LocateDYLD()
+{
+    if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS)
+        m_dyld_all_image_infos_addr = m_process->GetImageInfoAddress ();
+
+    if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS)
+    {
+        if (ReadAllImageInfosStructure ())
+        {
+            if (m_dyld_all_image_infos.dyldImageLoadAddress != LLDB_INVALID_ADDRESS)
+                return ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos.dyldImageLoadAddress);
+            else
+                return ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos_addr & 0xfffffffffff00000ull);
+        }
+    }
+
+    // Check some default values
+    Module *executable = m_process->GetTarget().GetExecutableModule().get();
+
+    if (executable)
+    {
+        if (executable->GetArchitecture().GetAddressByteSize() == 8)
+        {
+            return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x7fff5fc00000ull);
+        }
+#if defined (__arm__)
+        else
+        {
+            ArchSpec arm_arch("arm");
+            if (arm_arch == executable->Arch())
+                return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x2fe00000);
+        }
+#endif
+        return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x8fe00000);
+    }
+    return false;
+}
+
+//----------------------------------------------------------------------
+// Assume that dyld is in memory at ADDR and try to parse it's load
+// commands
+//----------------------------------------------------------------------
+bool
+DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb::addr_t addr)
+{
+    DataExtractor data; // Load command data
+    if (ReadMachHeader (addr, &m_dyld.header, &data))
+    {
+        if (m_dyld.header.filetype == MH_DYLINKER)
+        {
+            m_dyld.address = addr;
+            ModuleSP dyld_module_sp;
+            if (ParseLoadCommands (data, m_dyld, &m_dyld.file_spec))
+            {
+                if (m_dyld.file_spec)
+                {
+                    ArchSpec dyld_arch(m_dyld.header.cputype, m_dyld.header.cpusubtype);
+                    dyld_module_sp = m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (m_dyld.file_spec);
+
+                    if (dyld_module_sp.get() == NULL || dyld_module_sp->GetArchitecture() != dyld_arch)
+                    {
+                        dyld_module_sp = m_process->GetTarget().GetSharedModule (m_dyld.file_spec,
+                                                                                 dyld_arch,
+                                                                                 &m_dyld.uuid);
+                    }
+
+                    UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld);
+                }
+            }
+
+            if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS && dyld_module_sp.get())
+            {
+                static ConstString g_dyld_all_image_infos ("dyld_all_image_infos");
+                const Symbol *symbol = dyld_module_sp->FindFirstSymbolWithNameAndType (g_dyld_all_image_infos, eSymbolTypeData);
+                if (symbol)
+                    m_dyld_all_image_infos_addr = symbol->GetValue().GetLoadAddress(m_process);
+            }
+
+            // Update all image infos
+            UpdateAllImageInfos();
+
+            // If we didn't have an executable before, but now we do, then the
+            // dyld module shared pointer might be unique and we may need to add
+            // it again (since Target::SetExecutableModule() will clear the
+            // images). So append the dyld module back to the list if it is
+            /// unique!
+            if (m_process->GetTarget().GetImages().AppendInNeeded (dyld_module_sp))
+                UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld);
+
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+DynamicLoaderMacOSXDYLD::NeedToLocateDYLD () const
+{
+    return m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS;
+}
+
+bool
+DynamicLoaderMacOSXDYLD::UpdateCommPageLoadAddress(Module *module)
+{
+    bool changed = false;
+    if (module)
+    {
+        ObjectFile *image_object_file = module->GetObjectFile();
+        if (image_object_file)
+        {
+            SectionList *section_list = image_object_file->GetSectionList ();
+            if (section_list)
+            {
+                uint32_t num_sections = section_list->GetSize();
+                for (uint32_t i=0; i<num_sections; ++i)
+                {
+                    Section* section = section_list->GetSectionAtIndex (i).get();
+                    if (section)
+                    {
+                        const addr_t new_section_load_addr = section->GetFileAddress ();
+                        const addr_t old_section_load_addr = m_process->GetSectionLoadAddress (section);
+                        if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
+                            old_section_load_addr != new_section_load_addr)
+                        {
+                            if (m_process->SectionLoaded (section, section->GetFileAddress ()))
+                                changed = true;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return changed;
+}
+
+//----------------------------------------------------------------------
+// Update the load addresses for all segments in MODULE using the
+// updated INFO that is passed in.
+//----------------------------------------------------------------------
+bool
+DynamicLoaderMacOSXDYLD::UpdateImageLoadAddress (Module *module, struct DYLDImageInfo& info)
+{
+    bool changed = false;
+    if (module)
+    {
+        ObjectFile *image_object_file = module->GetObjectFile();
+        if (image_object_file)
+        {
+            SectionList *section_list = image_object_file->GetSectionList ();
+            if (section_list)
+            {
+                // All sections listed in the dyld image info structure will all
+                // either be fixed up already, or they will all be off by a single
+                // slide amount that is determined by finding the first segment
+                // that is at file offset zero which also has bytes (a file size
+                // that is greater than zero) in the object file.
+
+                // Determine the slide amount (if any)
+                info.slide = 0;
+                const size_t num_sections = section_list->GetSize();
+                size_t sect_idx = 0;
+                for (sect_idx = 0; sect_idx < num_sections; ++sect_idx)
+                {
+                    // Iterate through the object file sections to find the
+                    // first section that starts of file offset zero and that
+                    // has bytes in the file...
+                    Section *section = section_list->GetSectionAtIndex (sect_idx).get();
+                    if (section)
+                    {
+                        // Find the first section that begins at file offset zero
+                        // a file size (skip page zero).
+                        if (section->GetFileOffset() == 0 && section->GetFileSize() > 0)
+                        {
+                            // We have now found the section, lets match it up
+                            // with the section in the dyld image info structure.
+                            const Segment *dyld_segment = info.FindSegment (section->GetName());
+                            if (dyld_segment)
+                                info.slide = info.address - dyld_segment->addr;
+                            // We have found the slide amount, so we can exit
+                            // this for loop.
+                            break;
+                        }
+                    }
+                }
+
+                // We now know the slide amount, so go through all sections
+                // and update the load addresses with the correct values.
+                uint32_t num_segments = info.segments.size();
+                for (uint32_t i=0; i<num_segments; ++i)
+                {
+                    SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
+                    assert (section_sp.get() != NULL);
+                    const addr_t new_section_load_addr = info.segments[i].addr + info.slide;
+                    const addr_t old_section_load_addr = m_process->GetSectionLoadAddress (section_sp.get());
+                    if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
+                        old_section_load_addr != new_section_load_addr)
+                    {
+                        if (m_process->SectionLoaded (section_sp.get(), new_section_load_addr))
+                            changed = true;
+                    }
+                }
+            }
+        }
+    }
+    return changed;
+}
+
+//----------------------------------------------------------------------
+// Update the load addresses for all segments in MODULE using the
+// updated INFO that is passed in.
+//----------------------------------------------------------------------
+bool
+DynamicLoaderMacOSXDYLD::UnloadImageLoadAddress (Module *module, struct DYLDImageInfo& info)
+{
+    bool changed = false;
+    if (module)
+    {
+        ObjectFile *image_object_file = module->GetObjectFile();
+        if (image_object_file)
+        {
+            SectionList *section_list = image_object_file->GetSectionList ();
+            if (section_list)
+            {
+                uint32_t num_segments = info.segments.size();
+                for (uint32_t i=0; i<num_segments; ++i)
+                {
+                    SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
+                    assert (section_sp.get() != NULL);
+                    const addr_t old_section_load_addr = info.segments[i].addr + info.slide;
+                    if (m_process->SectionUnloaded (section_sp.get(), old_section_load_addr))
+                        changed = true;
+                }
+            }
+        }
+    }
+    return changed;
+}
+
+
+//----------------------------------------------------------------------
+// Static callback function that gets called when our DYLD notification
+// breakpoint gets hit. We update all of our image infos and then
+// let our super class DynamicLoader class decide if we should stop
+// or not (based on global preference).
+//----------------------------------------------------------------------
+bool
+DynamicLoaderMacOSXDYLD::NotifyBreakpointHit (void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
+{
+    // Let the event know that the images have changed
+    DynamicLoaderMacOSXDYLD* dyld_instance = (DynamicLoaderMacOSXDYLD*) baton;
+    dyld_instance->UpdateAllImageInfos();
+    // Return true to stop the target, false to just let the target run
+    return dyld_instance->GetStopWhenImagesChange();
+}
+
+bool
+DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure ()
+{
+    Mutex::Locker locker(m_mutex);
+    m_dyld_all_image_infos.Clear();
+    if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS)
+    {
+        const ByteOrder endian = m_process->GetByteOrder();
+        const uint32_t addr_size = m_process->GetAddressByteSize();
+        uint8_t buf[256];
+        const size_t count = 2 * sizeof(uint32_t) + // version + dylib_info_count
+                             addr_size * 2 +        // dylib_info_addr + notification
+                             2 + addr_size - 2 +    // processDetachedFromSharedRegion + libSystemInitialized + pad
+                             addr_size;             // dyldImageLoadAddress
+        Error error;
+        const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, count, error);
+        if (bytes_read == count)
+        {
+            DataExtractor data(buf, count, endian, addr_size);
+            uint32_t offset = 0;
+            m_dyld_all_image_infos.version = data.GetU32(&offset);
+            m_dyld_all_image_infos.dylib_info_count = data.GetU32(&offset);
+            m_dyld_all_image_infos.dylib_info_addr = data.GetPointer(&offset);
+            m_dyld_all_image_infos.notification = data.GetPointer(&offset);
+            m_dyld_all_image_infos.processDetachedFromSharedRegion = data.GetU8(&offset);
+            if (m_dyld_all_image_infos.version >= 2)
+            {
+                m_dyld_all_image_infos.libSystemInitialized = data.GetU8(&offset);
+                // Adjust for padding.
+                offset += addr_size - 2;
+                m_dyld_all_image_infos.dyldImageLoadAddress = data.GetPointer(&offset);
+            }
+            return true;
+        }
+    }
+    return false;
+}
+
+//----------------------------------------------------------------------
+// If we have found where the "_dyld_all_image_infos" lives in memory,
+// read the current info from it, and then update all image load
+// addresses (or lack thereof).
+//----------------------------------------------------------------------
+uint32_t
+DynamicLoaderMacOSXDYLD::UpdateAllImageInfos()
+{
+    if (ReadAllImageInfosStructure ())
+    {
+        Mutex::Locker locker(m_mutex);
+        uint32_t idx;
+        Error error;
+        uint32_t i = 0;
+        DYLDImageInfo::collection old_dyld_all_image_infos;
+        old_dyld_all_image_infos.swap(m_dyld_image_infos);
+
+        // If we made it here, we are assuming that the all dylib info data should
+        // be valid, lets read the info array.
+        const ByteOrder endian = m_process->GetByteOrder();
+        const uint32_t addr_size = m_process->GetAddressByteSize();
+
+        if (m_dyld_all_image_infos.dylib_info_count > 0)
+        {
+            if (m_dyld_all_image_infos.dylib_info_addr == 0)
+            {
+                // DYLD is updating the images right now...
+            }
+            else
+            {
+                m_dyld_image_infos.resize(m_dyld_all_image_infos.dylib_info_count);
+                const size_t count = m_dyld_image_infos.size() * 3 * addr_size;
+                DataBufferHeap info_data(count, 0);
+                Error error;
+                const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos.dylib_info_addr, 
+                                                                 info_data.GetBytes(), 
+                                                                 info_data.GetByteSize(),
+                                                                 error);
+                if (bytes_read == count)
+                {
+                    uint32_t info_data_offset = 0;
+                    DataExtractor info_data_ref(info_data.GetBytes(), info_data.GetByteSize(), endian, addr_size);
+                    for (i = 0; info_data_ref.ValidOffset(info_data_offset); i++)
+                    {
+                        assert (i < m_dyld_image_infos.size());
+                        m_dyld_image_infos[i].address = info_data_ref.GetPointer(&info_data_offset);
+                        lldb::addr_t path_addr = info_data_ref.GetPointer(&info_data_offset);
+                        m_dyld_image_infos[i].mod_date = info_data_ref.GetPointer(&info_data_offset);
+
+                        char raw_path[PATH_MAX];
+                        m_process->ReadMemory (path_addr, raw_path, sizeof(raw_path), error);
+                        m_dyld_image_infos[i].file_spec.SetFile(raw_path);
+                    }
+                    assert(i == m_dyld_all_image_infos.dylib_info_count);
+
+                    UpdateAllImageInfosHeaderAndLoadCommands();
+                }
+                else
+                {
+                    DEBUG_PRINTF( "unable to read all data for all_dylib_infos.");
+                    m_dyld_image_infos.clear();
+                }
+            }
+        }
+        else
+        {
+            m_dyld_image_infos.clear();
+        }
+
+        // If our new list is smaller than our old list, we have unloaded
+        // some shared libraries
+        if (m_dyld_image_infos.size() < old_dyld_all_image_infos.size())
+        {
+            ModuleList unloaded_module_list;
+            for (idx = m_dyld_image_infos.size(); idx < old_dyld_all_image_infos.size(); ++idx)
+            {
+                ModuleSP unload_image_module_sp(m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (old_dyld_all_image_infos[idx].file_spec));
+                if (unload_image_module_sp.get())
+                {
+                    if (UnloadImageLoadAddress (unload_image_module_sp.get(), old_dyld_all_image_infos[idx]))
+                        unloaded_module_list.AppendInNeeded (unload_image_module_sp);
+                }
+            }
+            if (unloaded_module_list.GetSize() > 0)
+                m_process->GetTarget().ModulesDidUnload (unloaded_module_list);
+        }
+    }
+    else
+    {
+        m_dyld_image_infos.clear();
+    }
+
+    const uint32_t num_dylibs = m_dyld_image_infos.size();
+    if (num_dylibs > 0)
+    {
+        ModuleList loaded_module_list;
+        for (uint32_t idx = 0; idx<num_dylibs; ++idx)
+        {
+            ArchSpec arch_spec(m_dyld_image_infos[idx].header.cputype, m_dyld_image_infos[idx].header.cpusubtype);
+            ModuleSP image_module_sp(m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (m_dyld_image_infos[idx].file_spec));
+            if (image_module_sp.get() == NULL || image_module_sp->GetArchitecture() != arch_spec)
+            {
+                image_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[idx].file_spec,
+                                                                          arch_spec,
+                                                                          &m_dyld_image_infos[idx].uuid);
+            }
+
+            if (image_module_sp)
+            {
+                ObjectFile *objfile = image_module_sp->GetObjectFile ();
+                if (objfile)
+                {
+                    SectionList *sections = objfile->GetSectionList();
+                    if (sections)
+                    {
+                        ConstString commpage_dbstr("__commpage");
+                        Section *commpage_section = sections->FindSectionByName(commpage_dbstr).get();
+                        if (commpage_section)
+                        {
+                            FileSpec objfile_file_spec(objfile->GetFileSpec());
+                            ModuleSP commpage_image_module_sp(m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (objfile_file_spec, &commpage_dbstr));
+                            if (commpage_image_module_sp.get() == NULL)
+                            {
+                                commpage_image_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[idx].file_spec,
+                                                                                                   arch_spec,
+                                                                                                   &m_dyld_image_infos[idx].uuid,
+                                                                                                   &commpage_dbstr,
+                                                                                                   objfile->GetOffset() + commpage_section->GetOffset());
+                                UpdateCommPageLoadAddress(commpage_image_module_sp.get());
+                            }
+                        }
+                    }
+                }
+
+                // UpdateImageLoadAddress will return true if any segments
+                // change load address. We need to check this so we don't
+                // mention that all loaded shared libraries are newly loaded
+                // each time we hit out dyld breakpoint since dyld will list all
+                // shared libraries each time.
+                if (UpdateImageLoadAddress (image_module_sp.get(), m_dyld_image_infos[idx]))
+                {
+                    loaded_module_list.AppendInNeeded (image_module_sp);
+                }
+            }
+        }
+        PutToLog(DynamicLoaderMacOSXDYLDLog::GetLogIfAllCategoriesSet (1));
+        if (loaded_module_list.GetSize() > 0)
+        {
+            // FIXME: This should really be in the Runtime handlers class, which should get
+            // called by the target's ModulesDidLoad, but we're doing it all locally for now 
+            // to save time.
+            // Also, I'm assuming there can be only one libobjc dylib loaded...
+            
+            if (m_objc_trampoline_handler_ap.get() == NULL)
+            {
+                size_t num_modules = loaded_module_list.GetSize();
+                for (int i = 0; i < num_modules; i++)
+                {
+                    if (ObjCTrampolineHandler::ModuleIsObjCLibrary (loaded_module_list.GetModuleAtIndex (i)))
+                    {
+                        m_objc_trampoline_handler_ap.reset (new ObjCTrampolineHandler(m_process->GetSP(), loaded_module_list.GetModuleAtIndex (i)));
+                        break;
+                    }
+                }
+            }
+            m_process->GetTarget().ModulesDidLoad (loaded_module_list);
+        }
+    }
+    return m_dyld_image_infos.size();
+}
+
+//----------------------------------------------------------------------
+// Read a mach_header at ADDR into HEADER, and also fill in the load
+// command data into LOAD_COMMAND_DATA if it is non-NULL.
+//
+// Returns true if we succeed, false if we fail for any reason.
+//----------------------------------------------------------------------
+bool
+DynamicLoaderMacOSXDYLD::ReadMachHeader (lldb::addr_t addr, struct mach_header *header, DataExtractor *load_command_data)
+{
+    DataBufferHeap header_bytes(sizeof(struct mach_header), 0);
+    Error error;
+    size_t bytes_read = m_process->ReadMemory (addr, 
+                                               header_bytes.GetBytes(), 
+                                               header_bytes.GetByteSize(), 
+                                               error);
+    if (bytes_read == sizeof(struct mach_header))
+    {
+        uint32_t offset = 0;
+        ::memset (header, 0, sizeof(header));
+
+        // Get the magic byte unswapped so we can figure out what we are dealing with
+        DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), eByteOrderHost, 4);
+        header->magic = data.GetU32(&offset);
+        lldb::addr_t load_cmd_addr = addr;
+        data.SetByteOrder(DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(header->magic));
+        switch (header->magic)
+        {
+        case MH_MAGIC:
+        case MH_CIGAM:
+            data.SetAddressByteSize(4);
+            load_cmd_addr += sizeof(struct mach_header);
+            break;
+
+        case MH_MAGIC_64:
+        case MH_CIGAM_64:
+            data.SetAddressByteSize(8);
+            load_cmd_addr += sizeof(struct mach_header_64);
+            break;
+
+        default:
+            return false;
+        }
+
+        // Read the rest of dyld's mach header
+        if (data.GetU32(&offset, &header->cputype, (sizeof(struct mach_header)/sizeof(uint32_t)) - 1))
+        {
+            if (load_command_data == NULL)
+                return true; // We were able to read the mach_header and weren't asked to read the load command bytes
+
+            DataBufferSP load_cmd_data_sp(new DataBufferHeap(header->sizeofcmds, 0));
+
+            size_t load_cmd_bytes_read = m_process->ReadMemory (load_cmd_addr, 
+                                                                load_cmd_data_sp->GetBytes(), 
+                                                                load_cmd_data_sp->GetByteSize(),
+                                                                error);
+            
+            if (load_cmd_bytes_read == header->sizeofcmds)
+            {
+                // Set the load command data and also set the correct endian
+                // swap settings and the correct address size
+                load_command_data->SetData(load_cmd_data_sp, 0, header->sizeofcmds);
+                load_command_data->SetByteOrder(data.GetByteOrder());
+                load_command_data->SetAddressByteSize(data.GetAddressByteSize());
+                return true; // We successfully read the mach_header and the load command data
+            }
+
+            return false; // We weren't able to read the load command data
+        }
+    }
+    return false; // We failed the read the mach_header
+}
+
+
+//----------------------------------------------------------------------
+// Parse the load commands for an image
+//----------------------------------------------------------------------
+uint32_t
+DynamicLoaderMacOSXDYLD::ParseLoadCommands (const DataExtractor& data, struct DYLDImageInfo& dylib_info, FileSpec *lc_id_dylinker)
+{
+    uint32_t offset = 0;
+    uint32_t cmd_idx;
+    Segment segment;
+    dylib_info.Clear (true);
+
+    for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++)
+    {
+        // Clear out any load command specific data from DYLIB_INFO since
+        // we are about to read it.
+
+        if (data.ValidOffsetForDataOfSize (offset, sizeof(struct load_command)))
+        {
+            struct load_command load_cmd;
+            uint32_t load_cmd_offset = offset;
+            load_cmd.cmd = data.GetU32 (&offset);
+            load_cmd.cmdsize = data.GetU32 (&offset);
+            switch (load_cmd.cmd)
+            {
+            case LC_SEGMENT:
+                {
+                    segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
+                    segment.addr = data.GetU32 (&offset);
+                    segment.size = data.GetU32 (&offset);
+                    dylib_info.segments.push_back (segment);
+                }
+                break;
+
+            case LC_SEGMENT_64:
+                {
+                    segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
+                    segment.addr = data.GetU64 (&offset);
+                    segment.size = data.GetU64 (&offset);
+                    dylib_info.segments.push_back (segment);
+                }
+                break;
+
+            case LC_ID_DYLINKER:
+                if (lc_id_dylinker)
+                {
+                    uint32_t name_offset = load_cmd_offset + data.GetU32 (&offset);
+                    const char *path = data.PeekCStr (name_offset);
+                    lc_id_dylinker->SetFile (path);
+                }
+                break;
+
+            case LC_UUID:
+                dylib_info.uuid.SetBytes(data.GetData (&offset, 16));
+                break;
+
+            default:
+                break;
+            }
+            // Set offset to be the beginning of the next load command.
+            offset = load_cmd_offset + load_cmd.cmdsize;
+        }
+    }
+    return cmd_idx;
+}
+
+//----------------------------------------------------------------------
+// Read the mach_header and load commands for each image that the
+// _dyld_all_image_infos structure points to and cache the results.
+//----------------------------------------------------------------------
+void
+DynamicLoaderMacOSXDYLD::UpdateAllImageInfosHeaderAndLoadCommands()
+{
+    uint32_t exe_idx = UINT32_MAX;
+    // Read any UUID values that we can get
+    for (uint32_t i = 0; i < m_dyld_all_image_infos.dylib_info_count; i++)
+    {
+        if (!m_dyld_image_infos[i].UUIDValid())
+        {
+            DataExtractor data; // Load command data
+            if (!ReadMachHeader (m_dyld_image_infos[i].address, &m_dyld_image_infos[i].header, &data))
+                continue;
+
+            ParseLoadCommands (data, m_dyld_image_infos[i], NULL);
+
+            if (m_dyld_image_infos[i].header.filetype == MH_EXECUTE)
+                exe_idx = i;
+        }
+    }
+
+    if (exe_idx < m_dyld_image_infos.size())
+    {
+        bool set_executable = false;
+        ArchSpec dyld_exe_arch_spec(m_dyld_image_infos[exe_idx].header.cputype, m_dyld_image_infos[exe_idx].header.cpusubtype);
+        ModuleSP exe_module_sp(m_process->GetTarget().GetExecutableModule());
+        if (exe_module_sp.get())
+        {
+            if (exe_module_sp->GetFileSpec() != m_dyld_image_infos[exe_idx].file_spec ||
+                exe_module_sp->GetArchitecture() != dyld_exe_arch_spec)
+                set_executable = true;
+        }
+        else
+            set_executable = true;
+
+        if (set_executable)
+        {
+            exe_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[exe_idx].file_spec,
+                                                                    dyld_exe_arch_spec,
+                                                                    &m_dyld_image_infos[exe_idx].uuid);
+            if (exe_module_sp.get())
+            {
+                // If we found the file where it purported to be, then it should
+                // be safe to load dependent images.
+                bool get_dependent_images = exe_module_sp->GetFileSpec() == m_dyld_image_infos[exe_idx].file_spec;
+
+                m_process->GetTarget().SetExecutableModule (exe_module_sp, get_dependent_images);
+            }
+        }
+    }
+}
+
+//----------------------------------------------------------------------
+// Dump a Segment to the file handle provided.
+//----------------------------------------------------------------------
+void
+DynamicLoaderMacOSXDYLD::Segment::PutToLog (Log *log, lldb::addr_t slide) const
+{
+    if (log)
+        log->Printf("\t\t%16s [0x%16.16llx - 0x%16.16llx)", name.AsCString(""), addr + slide, addr + slide + size);
+}
+
+const DynamicLoaderMacOSXDYLD::Segment *
+DynamicLoaderMacOSXDYLD::DYLDImageInfo::FindSegment (const ConstString &name) const
+{
+    const size_t num_segments = segments.size();
+    for (size_t i=0; i<num_segments; ++i)
+    {
+        if (segments[i].name == name)
+            return &segments[i];
+    }
+    return NULL;
+}
+
+
+//----------------------------------------------------------------------
+// Dump an image info structure to the file handle provided.
+//----------------------------------------------------------------------
+void
+DynamicLoaderMacOSXDYLD::DYLDImageInfo::PutToLog (Log *log) const
+{
+    if (log == NULL)
+        return;
+    uint8_t *u = (uint8_t *)uuid.GetBytes();
+
+    if (address == LLDB_INVALID_ADDRESS)
+    {
+        if (u)
+        {
+            log->Printf("\t                           modtime=0x%8.8llx uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X path='%s/%s' (UNLOADED)",
+                        mod_date,
+                        u[ 0], u[ 1], u[ 2], u[ 3],
+                        u[ 4], u[ 5], u[ 6], u[ 7],
+                        u[ 8], u[ 9], u[10], u[11],
+                        u[12], u[13], u[14], u[15],
+                        file_spec.GetDirectory().AsCString(),
+                        file_spec.GetFilename().AsCString());
+        }
+        else
+            log->Printf("\t                           modtime=0x%8.8llx path='%s/%s' (UNLOADED)",
+                        mod_date,
+                        file_spec.GetDirectory().AsCString(),
+                        file_spec.GetFilename().AsCString());
+    }
+    else
+    {
+        if (u)
+        {
+            log->Printf("\taddress=0x%16.16llx modtime=0x%8.8llx uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X path='%s/%s'",
+                        address,
+                        mod_date,
+                        u[ 0], u[ 1], u[ 2], u[ 3],
+                        u[ 4], u[ 5], u[ 6], u[ 7],
+                        u[ 8], u[ 9], u[10], u[11],
+                        u[12], u[13], u[14], u[15],
+                        file_spec.GetDirectory().AsCString(),
+                        file_spec.GetFilename().AsCString());
+        }
+        else
+        {
+            log->Printf("\taddress=0x%16.16llx modtime=0x%8.8llx path='%s/%s'",
+                        address,
+                        mod_date,
+                        file_spec.GetDirectory().AsCString(),
+                        file_spec.GetFilename().AsCString());
+
+        }
+        for (uint32_t i=0; i<segments.size(); ++i)
+            segments[i].PutToLog(log, slide);
+    }
+}
+
+//----------------------------------------------------------------------
+// Dump the _dyld_all_image_infos members and all current image infos
+// that we have parsed to the file handle provided.
+//----------------------------------------------------------------------
+void
+DynamicLoaderMacOSXDYLD::PutToLog(Log *log) const
+{
+    if (log == NULL)
+        return;
+
+    Mutex::Locker locker(m_mutex);
+    log->Printf("dyld_all_image_infos = { version=%d, count=%d, addr=0x%8.8llx, notify=0x%8.8llx }",
+                    m_dyld_all_image_infos.version,
+                    m_dyld_all_image_infos.dylib_info_count,
+                    (uint64_t)m_dyld_all_image_infos.dylib_info_addr,
+                    (uint64_t)m_dyld_all_image_infos.notification);
+    size_t i;
+    const size_t count = m_dyld_image_infos.size();
+    if (count > 0)
+    {
+        log->Printf("\tdyld_image_infos");
+        for (i = 0; i<count; i++)
+            m_dyld_image_infos[i].PutToLog(log);
+    }
+}
+
+//----------------------------------------------------------------------
+// Static callback function that gets called when the process state
+// changes.
+//----------------------------------------------------------------------
+void
+DynamicLoaderMacOSXDYLD::Initialize(void *baton, Process *process)
+{
+    ((DynamicLoaderMacOSXDYLD*)baton)->PrivateInitialize(process);
+}
+
+void
+DynamicLoaderMacOSXDYLD::PrivateInitialize(Process *process)
+{
+    DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
+    Clear(true);
+    m_process = process;
+}
+
+
+//----------------------------------------------------------------------
+// Static callback function that gets called when the process state
+// changes.
+//----------------------------------------------------------------------
+void
+DynamicLoaderMacOSXDYLD::ProcessStateChanged(void *baton, Process *process, StateType state)
+{
+    ((DynamicLoaderMacOSXDYLD*)baton)->PrivateProcessStateChanged(process, state);
+}
+
+bool
+DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint ()
+{
+    DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
+    if (m_break_id == LLDB_INVALID_BREAK_ID)
+    {
+        if (m_dyld_all_image_infos.notification != LLDB_INVALID_ADDRESS)
+        {
+            Address so_addr;
+            // Set the notification breakpoint and install a breakpoint
+            // callback function that will get called each time the
+            // breakpoint gets hit. We will use this to track when shared
+            // libraries get loaded/unloaded.
+
+            if (m_process->ResolveLoadAddress(m_dyld_all_image_infos.notification, so_addr))
+            {
+                Breakpoint *dyld_break = m_process->GetTarget().CreateBreakpoint (so_addr, true).get();
+                dyld_break->SetCallback (DynamicLoaderMacOSXDYLD::NotifyBreakpointHit, this, true);
+                m_break_id = dyld_break->GetID();
+            }
+        }
+    }
+    return m_break_id != LLDB_INVALID_BREAK_ID;
+}
+
+//----------------------------------------------------------------------Target.h
+
+// Member function that gets called when the process state changes.
+//----------------------------------------------------------------------
+void
+DynamicLoaderMacOSXDYLD::PrivateProcessStateChanged (Process *process, StateType state)
+{
+    DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s(%s)\n", __FUNCTION__, StateAsCString(state));
+    switch (state)
+    {
+    case eStateAttaching:
+    case eStateLaunching:
+    case eStateInvalid:
+    case eStateUnloaded:
+    case eStateExited:
+    case eStateDetached:
+        Clear(false);
+        break;
+
+    case eStateStopped:
+        // Keep trying find dyld and set our notification breakpoint each time
+        // we stop until we succeed
+        if (!DidSetNotificationBreakpoint () && m_process->IsAlive())
+        {
+            if (NeedToLocateDYLD ())
+                LocateDYLD ();
+
+            SetNotificationBreakpoint ();
+        }
+        break;
+
+    case eStateRunning:
+    case eStateStepping:
+    case eStateCrashed:
+    case eStateSuspended:
+        break;
+
+    default:
+        break;
+    }
+}
+
+ThreadPlanSP
+DynamicLoaderMacOSXDYLD::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
+{
+    ThreadPlanSP thread_plan_sp;
+    StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get();
+    const SymbolContext &current_context = current_frame->GetSymbolContext(eSymbolContextSymbol);
+    Symbol *current_symbol = current_context.symbol;
+
+    if (current_symbol != NULL)
+    {
+        if (current_symbol->IsTrampoline())
+        {
+            const ConstString &trampoline_name = current_symbol->GetMangled().GetName();
+            if (trampoline_name)
+            {
+                SymbolContextList target_symbols;
+                ModuleList &images = thread.GetProcess().GetTarget().GetImages();
+                images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, target_symbols);
+                // FIXME - Make the Run to Address take multiple addresses, and
+                // run to any of them.
+                if (target_symbols.GetSize() == 1)
+                {
+                    SymbolContext context;
+                    AddressRange addr_range;
+                    if (target_symbols.GetContextAtIndex(0, context))
+                    {
+                        context.GetAddressRange (eSymbolContextEverything, addr_range);
+                        thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addr_range.GetBaseAddress(), stop_others));
+                    }
+                }
+                else if (target_symbols.GetSize() > 1)
+                {
+                    Log *log = DynamicLoaderMacOSXDYLDLog::GetLogIfAllCategoriesSet (1);
+                    if (log)
+                    {
+                        log->Printf ("Found more than one symbol for trampoline target: \"%s\"", trampoline_name.AsCString());
+                    }
+                }
+                else
+                {
+                    Log *log = DynamicLoaderMacOSXDYLDLog::GetLogIfAllCategoriesSet (1);
+                    if (log)
+                    {
+                        log->Printf ("Could not find symbol for trampoline target: \"%s\"", trampoline_name.AsCString());
+                    }
+                }
+            }
+        }
+    }
+
+    if (thread_plan_sp == NULL && m_objc_trampoline_handler_ap.get())
+        thread_plan_sp = m_objc_trampoline_handler_ap->GetStepThroughDispatchPlan (thread, stop_others);
+        
+    return thread_plan_sp;
+}
+
+void
+DynamicLoaderMacOSXDYLD::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance);
+}
+
+void
+DynamicLoaderMacOSXDYLD::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+const char *
+DynamicLoaderMacOSXDYLD::GetPluginNameStatic()
+{
+    return "dynamic-loader.macosx-dyld";
+}
+
+const char *
+DynamicLoaderMacOSXDYLD::GetPluginDescriptionStatic()
+{
+    return "Dynamic loader plug-in that watches for shared library loads/unloads in MacOSX user processes.";
+}
+
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+const char *
+DynamicLoaderMacOSXDYLD::GetPluginName()
+{
+    return "DynamicLoaderMacOSXDYLD";
+}
+
+const char *
+DynamicLoaderMacOSXDYLD::GetShortPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+DynamicLoaderMacOSXDYLD::GetPluginVersion()
+{
+    return 1;
+}
+
+void
+DynamicLoaderMacOSXDYLD::GetPluginCommandHelp (const char *command, Stream *strm)
+{
+}
+
+Error
+DynamicLoaderMacOSXDYLD::ExecutePluginCommand (Args &command, Stream *strm)
+{
+    Error error;
+    error.SetErrorString("No plug-in command are currently supported.");
+    return error;
+}
+
+Log *
+DynamicLoaderMacOSXDYLD::EnablePluginLogging (Stream *strm, Args &command)
+{
+    return NULL;
+}
+
+
diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h
new file mode 100644
index 0000000..724a8b6
--- /dev/null
+++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h
@@ -0,0 +1,360 @@
+//===-- DynamicLoaderMacOSXDYLD.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_DynamicLoaderMacOSXDYLD_h_
+#define liblldb_DynamicLoaderMacOSXDYLD_h_
+
+// C Includes
+#include <mach-o/loader.h>
+
+// C++ Includes
+#include <map>
+#include <vector>
+#include <string>
+
+// Other libraries and framework includes
+#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Core/UUID.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Target/Process.h"
+#include "ObjCTrampolineHandler.h"
+
+class DynamicLoaderMacOSXDYLD : public lldb_private::DynamicLoader
+{
+public:
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static const char *
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb_private::DynamicLoader *
+    CreateInstance (lldb_private::Process *process);
+
+    DynamicLoaderMacOSXDYLD (lldb_private::Process *process);
+
+    virtual
+    ~DynamicLoaderMacOSXDYLD ();
+    //------------------------------------------------------------------
+    /// Called after attaching a process.
+    ///
+    /// Allow DynamicLoader plug-ins to execute some code after
+    /// attaching to a process.
+    //------------------------------------------------------------------
+    virtual void
+    DidAttach ();
+
+    virtual void
+    DidLaunch ();
+
+    //------------------------------------------------------------------
+    // Process::Notifications callback functions
+    //------------------------------------------------------------------
+    static void
+    Initialize (void *baton,
+                lldb_private::Process *process);
+
+    static void
+    ProcessStateChanged (void *baton,
+                         lldb_private::Process *process,
+                         lldb::StateType state);
+
+    virtual lldb::ThreadPlanSP
+    GetStepThroughTrampolinePlan (lldb_private::Thread &thread,
+                                  bool stop_others);
+
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual const char *
+    GetPluginName();
+
+    virtual const char *
+    GetShortPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+    virtual void
+    GetPluginCommandHelp (const char *command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Error
+    ExecutePluginCommand (lldb_private::Args &command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Log *
+    EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
+
+
+
+protected:
+    void
+    PrivateInitialize (lldb_private::Process *process);
+
+    void
+    PrivateProcessStateChanged (lldb_private::Process *process,
+                                lldb::StateType state);
+    bool
+    LocateDYLD ();
+
+    bool
+    DidSetNotificationBreakpoint () const;
+
+    void
+    Clear (bool clear_process);
+
+    void
+    PutToLog (lldb_private::Log *log) const;
+
+    bool
+    ReadDYLDInfoFromMemoryAndSetNotificationCallback (lldb::addr_t addr);
+
+    uint32_t
+    UpdateAllImageInfos ();
+
+    static bool
+    NotifyBreakpointHit (void *baton,
+                         lldb_private::StoppointCallbackContext *context,
+                         lldb::user_id_t break_id,
+                         lldb::user_id_t break_loc_id);
+    void
+    UpdateAllImageInfosHeaderAndLoadCommands ();
+
+    bool
+    UpdateCommPageLoadAddress (lldb_private::Module *module);
+
+    uint32_t
+    AddrByteSize()
+    {
+        switch (m_dyld.header.magic)
+        {
+            case MH_MAGIC:
+            case MH_CIGAM:
+                return 4;
+
+            case MH_MAGIC_64:
+            case MH_CIGAM_64:
+                return 8;
+
+            default:
+                break;
+        }
+        return 0;
+    }
+
+    static lldb::ByteOrder
+    GetByteOrderFromMagic (uint32_t magic)
+    {
+        switch (magic)
+        {
+            case MH_MAGIC:
+            case MH_MAGIC_64:
+                return lldb::eByteOrderHost;
+
+            case MH_CIGAM:
+            case MH_CIGAM_64:
+                if (lldb::eByteOrderHost == lldb::eByteOrderBig)
+                    return lldb::eByteOrderLittle;
+                else
+                    return lldb::eByteOrderBig;
+
+            default:
+                break;
+        }
+        return lldb::eByteOrderInvalid;
+    }
+
+    bool
+    ReadMachHeader (lldb::addr_t addr,
+                    struct mach_header *header,
+                    lldb_private::DataExtractor *load_command_data);
+    class Segment
+    {
+    public:
+
+        Segment() :
+            name(),
+            addr(LLDB_INVALID_ADDRESS),
+            size(0)
+        {
+        }
+
+        lldb_private::ConstString name;
+        lldb::addr_t addr;
+        lldb::addr_t size;
+
+        bool
+        operator==(const Segment& rhs) const
+        {
+            return name == rhs.name && addr == rhs.addr && size == rhs.size;
+        }
+
+        void
+        PutToLog (lldb_private::Log *log,
+                  lldb::addr_t slide) const;
+
+    };
+
+    struct DYLDImageInfo
+    {
+        lldb::addr_t address;           // Address of mach header for this dylib
+        lldb::addr_t slide;             // The amount to slide all segments by if there is a global slide.
+        lldb::addr_t mod_date;          // Modification date for this dylib
+        lldb_private::FileSpec file_spec;       // Resolved path for this dylib
+        lldb_private::UUID uuid;                // UUID for this dylib if it has one, else all zeros
+        struct mach_header header;      // The mach header for this image
+        std::vector<Segment> segments;  // All segment vmaddr and vmsize pairs for this executable (from memory of inferior)
+
+        DYLDImageInfo() :
+            address(LLDB_INVALID_ADDRESS),
+            slide(0),
+            mod_date(0),
+            file_spec(),
+            uuid(),
+            header(),
+            segments()
+        {
+        }
+
+        void
+        Clear(bool load_cmd_data_only)
+        {
+            if (!load_cmd_data_only)
+            {
+                address = LLDB_INVALID_ADDRESS;
+                slide = 0;
+                mod_date = 0;
+                file_spec.Clear();
+                ::bzero (&header, sizeof(header));
+            }
+            uuid.Clear();
+            segments.clear();
+        }
+
+        bool
+        operator == (const DYLDImageInfo& rhs) const
+        {
+            return  address == rhs.address
+                && slide == rhs.slide
+                && mod_date == rhs.mod_date
+                && file_spec == rhs.file_spec
+                && uuid == rhs.uuid
+                && memcmp(&header, &rhs.header, sizeof(header)) == 0
+                && segments == rhs.segments;
+        }
+
+        bool
+        UUIDValid() const
+        {
+            return uuid.IsValid();
+        }
+
+        const Segment *
+        FindSegment (const lldb_private::ConstString &name) const;
+
+        void
+        PutToLog (lldb_private::Log *log) const;
+
+        typedef std::vector<DYLDImageInfo> collection;
+        typedef collection::iterator iterator;
+        typedef collection::const_iterator const_iterator;
+    };
+
+    struct DYLDAllImageInfos
+    {
+        uint32_t version;
+        uint32_t dylib_info_count;              // Version >= 1
+        lldb::addr_t dylib_info_addr;           // Version >= 1
+        lldb::addr_t notification;              // Version >= 1
+        bool processDetachedFromSharedRegion;   // Version >= 1
+        bool libSystemInitialized;              // Version >= 2
+        lldb::addr_t dyldImageLoadAddress;      // Version >= 2
+
+        DYLDAllImageInfos() :
+            version (0),
+            dylib_info_count (0),
+            dylib_info_addr (LLDB_INVALID_ADDRESS),
+            notification (LLDB_INVALID_ADDRESS),
+            processDetachedFromSharedRegion (false),
+            libSystemInitialized (false),
+            dyldImageLoadAddress (LLDB_INVALID_ADDRESS)
+        {
+        }
+
+        void
+        Clear()
+        {
+            version = 0;
+            dylib_info_count = 0;
+            dylib_info_addr = LLDB_INVALID_ADDRESS;
+            notification = LLDB_INVALID_ADDRESS;
+            processDetachedFromSharedRegion = false;
+            libSystemInitialized = false;
+            dyldImageLoadAddress = LLDB_INVALID_ADDRESS;
+        }
+
+        bool
+        IsValid() const
+        {
+            return version >= 1 || version <= 6;
+        }
+    };
+
+    void
+    RegisterNotificationCallbacks();
+
+    void
+    UnregisterNotificationCallbacks();
+
+    uint32_t
+    ParseLoadCommands (const lldb_private::DataExtractor& data,
+                       struct DYLDImageInfo& dylib_info,
+                       lldb_private::FileSpec *lc_id_dylinker);
+
+    bool
+    UpdateImageLoadAddress(lldb_private::Module *module,
+                           struct DYLDImageInfo& info);
+
+    bool
+    UnloadImageLoadAddress (lldb_private::Module *module,
+                            struct DYLDImageInfo& info);
+
+    bool
+    NeedToLocateDYLD () const;
+
+    bool
+    SetNotificationBreakpoint ();
+
+    bool
+    ReadAllImageInfosStructure ();
+
+    DYLDImageInfo m_dyld;               // Info about the curent dyld being used
+    lldb::addr_t m_dyld_all_image_infos_addr;
+    DYLDAllImageInfos m_dyld_all_image_infos;
+    lldb::user_id_t m_break_id;
+    DYLDImageInfo::collection m_dyld_image_infos;   // Current shared libraries information
+    mutable lldb_private::Mutex m_mutex;
+    lldb_private::Process::Notifications m_notification_callbacks;
+    std::auto_ptr<lldb_private::ObjCTrampolineHandler> m_objc_trampoline_handler_ap;
+
+private:
+    DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXDYLD);
+};
+
+#endif  // liblldb_DynamicLoaderMacOSXDYLD_h_
diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLDLog.cpp b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLDLog.cpp
new file mode 100644
index 0000000..946c8f9
--- /dev/null
+++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLDLog.cpp
@@ -0,0 +1,72 @@
+//===-- DynamicLoaderMacOSXDYLDLog.cpp --------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DynamicLoaderMacOSXDYLDLog.h"
+#include "lldb/Core/Log.h"
+
+using namespace lldb_private;
+
+static Log *
+LogAccessor (bool get, Log *log)
+{
+    static Log* g_log = NULL; // Leak for now as auto_ptr was being cleaned up
+                                // by global constructors before other threads
+                                // were done with it.
+    if (get)
+    {
+//      // Debug code below for enabling logging by default
+//      if (g_log == NULL)
+//      {
+//          g_log = new Log("/dev/stdout", false);
+//          g_log->GetMask().SetAllFlagBits(0xffffffffu);
+//          g_log->GetOptions().Set(LLDB_LOG_OPTION_THREADSAFE | LLDB_LOG_OPTION_PREPEND_THREAD_NAME);
+//      }
+    }
+    else
+    {
+        if (g_log)
+            delete g_log;
+        g_log = log;
+    }
+
+    return g_log;
+}
+
+Log *
+DynamicLoaderMacOSXDYLDLog::GetLogIfAllCategoriesSet (uint32_t mask)
+{
+    Log *log = LogAccessor (true, NULL);
+    if (log && mask)
+    {
+        uint32_t log_mask = log->GetMask().GetAllFlagBits();
+        if ((log_mask & mask) != mask)
+            return NULL;
+    }
+    return log;
+}
+
+void
+DynamicLoaderMacOSXDYLDLog::SetLog (Log *log)
+{
+    LogAccessor (false, log);
+}
+
+
+void
+DynamicLoaderMacOSXDYLDLog::LogIf (uint32_t mask, const char *format, ...)
+{
+    Log *log = DynamicLoaderMacOSXDYLDLog::GetLogIfAllCategoriesSet (mask);
+    if (log)
+    {
+        va_list args;
+        va_start (args, format);
+        log->VAPrintf (format, args);
+        va_end (args);
+    }
+}
diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLDLog.h b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLDLog.h
new file mode 100644
index 0000000..9282ba5
--- /dev/null
+++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLDLog.h
@@ -0,0 +1,34 @@
+//===-- DynamicLoaderMacOSXDYLDLog.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_DynamicLoaderMacOSXDYLDLog_h_
+#define liblldb_DynamicLoaderMacOSXDYLDLog_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+
+#include "lldb/lldb-private.h"
+
+// Project includes
+
+class DynamicLoaderMacOSXDYLDLog
+{
+public:
+    static lldb_private::Log *
+    GetLogIfAllCategoriesSet (uint32_t mask);
+
+    static void
+    SetLog (lldb_private::Log *log);
+
+    static void
+    LogIf (uint32_t mask, const char *format, ...);
+};
+
+#endif  // liblldb_DynamicLoaderMacOSXDYLDLog_h_
diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/ObjCTrampolineHandler.cpp b/source/Plugins/DynamicLoader/MacOSX-DYLD/ObjCTrampolineHandler.cpp
new file mode 100644
index 0000000..169dc89
--- /dev/null
+++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/ObjCTrampolineHandler.cpp
@@ -0,0 +1,328 @@
+//===-- ObjCTrampolineHandler.cpp ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ObjCTrampolineHandler.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Expression/ClangFunction.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "ThreadPlanStepThroughObjCTrampoline.h"
+#include "lldb/Target/ThreadPlanRunToAddress.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+const ObjCTrampolineHandler::DispatchFunction
+ObjCTrampolineHandler::g_dispatch_functions[] =
+{
+    // NAME                              STRET  SUPER  FIXUP TYPE
+    {"objc_msgSend",                     false, false, ObjCTrampolineHandler::DispatchFunction::eFixUpNone    },
+    {"objc_msgSend_fixup",               false, false, ObjCTrampolineHandler::DispatchFunction::eFixUpToFix   },
+    {"objc_msgSend_fixedup",             false, false, ObjCTrampolineHandler::DispatchFunction::eFixUpFixed   },
+    {"objc_msgSend_stret",               true,  false, ObjCTrampolineHandler::DispatchFunction::eFixUpNone    },
+    {"objc_msgSend_stret_fixup",         true,  false, ObjCTrampolineHandler::DispatchFunction::eFixUpToFix   },
+    {"objc_msgSend_stret_fixedup",       true,  false, ObjCTrampolineHandler::DispatchFunction::eFixUpFixed   },
+    {"objc_msgSend_fpret",               false, false, ObjCTrampolineHandler::DispatchFunction::eFixUpNone    },
+    {"objc_msgSend_fpret_fixup",         false, false, ObjCTrampolineHandler::DispatchFunction::eFixUpToFix   },
+    {"objc_msgSend_fpret_fixedup",       false, false, ObjCTrampolineHandler::DispatchFunction::eFixUpFixed   },
+    {"objc_msgSend_fp2ret",              false, false, ObjCTrampolineHandler::DispatchFunction::eFixUpNone    },
+    {"objc_msgSend_fp2ret_fixup",        false, false, ObjCTrampolineHandler::DispatchFunction::eFixUpToFix   },
+    {"objc_msgSend_fp2ret_fixedup",      false, false, ObjCTrampolineHandler::DispatchFunction::eFixUpFixed   },
+    {"objc_msgSendSuper",                false, true,  ObjCTrampolineHandler::DispatchFunction::eFixUpNone    },
+    {"objc_msgSendSuper_stret",          true,  true,  ObjCTrampolineHandler::DispatchFunction::eFixUpNone    },
+    {"objc_msgSendSuper2",               false, true,  ObjCTrampolineHandler::DispatchFunction::eFixUpNone    },
+    {"objc_msgSendSuper2_fixup",         false, true,  ObjCTrampolineHandler::DispatchFunction::eFixUpToFix   },
+    {"objc_msgSendSuper2_fixedup",       false, true,  ObjCTrampolineHandler::DispatchFunction::eFixUpFixed   },
+    {"objc_msgSendSuper2_stret",         true,  true,  ObjCTrampolineHandler::DispatchFunction::eFixUpNone    },
+    {"objc_msgSendSuper2_stret_fixup",   true,  true,  ObjCTrampolineHandler::DispatchFunction::eFixUpToFix   },
+    {"objc_msgSendSuper2_stret_fixedup", true,  true,  ObjCTrampolineHandler::DispatchFunction::eFixUpFixed   },
+    {NULL}
+};
+
+bool
+ObjCTrampolineHandler::ModuleIsObjCLibrary (const ModuleSP &module_sp)
+{
+    const FileSpec &module_file_spec = module_sp->GetFileSpec();
+    static ConstString ObjCName ("libobjc.A.dylib");
+    
+    if (module_file_spec)
+    {
+        if (module_file_spec.GetFilename() == ObjCName)
+            return true;
+    }
+    
+    return false;
+}
+
+ObjCTrampolineHandler::ObjCTrampolineHandler (ProcessSP process_sp, ModuleSP objc_module) :
+    m_process_sp (process_sp),
+    m_objc_module_sp (objc_module),
+    m_impl_fn_addr (LLDB_INVALID_ADDRESS),
+    m_impl_stret_fn_addr (LLDB_INVALID_ADDRESS)
+{
+    // Look up the known resolution functions:
+    
+    ConstString get_impl_name("class_getMethodImplementation");
+    ConstString get_impl_stret_name("class_getMethodImplementation_stret");
+    
+    const Symbol *class_getMethodImplementation = m_objc_module_sp->FindFirstSymbolWithNameAndType (get_impl_name, eSymbolTypeCode);
+    const Symbol *class_getMethodImplementation_stret = m_objc_module_sp->FindFirstSymbolWithNameAndType (get_impl_stret_name, eSymbolTypeCode);
+    
+    if (class_getMethodImplementation)
+        m_impl_fn_addr = class_getMethodImplementation->GetValue().GetLoadAddress(m_process_sp.get());
+    if  (class_getMethodImplementation_stret)
+        m_impl_stret_fn_addr = class_getMethodImplementation_stret->GetValue().GetLoadAddress(m_process_sp.get());
+    
+    // FIXME: Do some kind of logging here.
+    if (m_impl_fn_addr == LLDB_INVALID_ADDRESS || m_impl_stret_fn_addr == LLDB_INVALID_ADDRESS)
+        return;
+        
+    // Look up the addresses for the objc dispatch functions and cache them.  For now I'm inspecting the symbol
+    // names dynamically to figure out how to dispatch to them.  If it becomes more complicated than this we can 
+    // turn the g_dispatch_functions char * array into a template table, and populate the DispatchFunction map
+    // from there.
+
+    for (int i = 0; g_dispatch_functions[i].name != NULL; i++)
+    {
+        ConstString name_const_str(g_dispatch_functions[i].name);
+        const Symbol *msgSend_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (name_const_str, eSymbolTypeCode);
+        if (msgSend_symbol)
+        {
+            // FixMe: Make g_dispatch_functions static table of DisptachFunctions, and have the map be address->index.
+            // Problem is we also need to lookup the dispatch function.  For now we could have a side table of stret & non-stret
+            // dispatch functions.  If that's as complex as it gets, we're fine.
+            
+            lldb::addr_t sym_addr = msgSend_symbol->GetValue().GetLoadAddress(m_process_sp.get());
+            
+            m_msgSend_map.insert(std::pair<lldb::addr_t, int>(sym_addr, i));
+        }
+    }
+}
+
+ThreadPlanSP
+ObjCTrampolineHandler::GetStepThroughDispatchPlan (Thread &thread, bool stop_others)
+{
+    ThreadPlanSP ret_plan_sp;
+    lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC();
+    
+    MsgsendMap::iterator pos;
+    pos = m_msgSend_map.find (curr_pc);
+    if (pos != m_msgSend_map.end())
+    {
+        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+
+        const DispatchFunction *this_dispatch = &g_dispatch_functions[(*pos).second];
+        
+        lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0);
+        
+        Process *process = thread.CalculateProcess();
+        const ABI *abi = process->GetABI();
+        if (abi == NULL)
+            return ret_plan_sp;
+            
+        Target *target = thread.CalculateTarget();
+        
+        // FIXME: Since neither the value nor the Clang QualType know their ASTContext, 
+        // we have to make sure the type we put in our value list comes from the same ASTContext
+        // the ABI will use to get the argument values.  THis is the bottom-most frame's module.
+
+        ClangASTContext *clang_ast_context = target->GetScratchClangASTContext();
+        ValueList argument_values;
+        Value input_value;
+        void *clang_void_ptr_type = clang_ast_context->GetVoidPtrType(false);
+        input_value.SetValueType (Value::eValueTypeScalar);
+        input_value.SetContext (Value::eContextTypeOpaqueClangQualType, clang_void_ptr_type);
+        
+        int obj_index;
+        int sel_index;
+        
+        // If this is a struct return dispatch, then the first argument is the
+        // return struct pointer, and the object is the second, and the selector is the third.
+        // Otherwise the object is the first and the selector the second.
+        if (this_dispatch->stret_return)
+        {
+            obj_index = 1;
+            sel_index = 2;
+            argument_values.PushValue(input_value);
+            argument_values.PushValue(input_value);
+            argument_values.PushValue(input_value);
+        }
+        else
+        {
+            obj_index = 0;
+            sel_index = 1;
+            argument_values.PushValue(input_value);
+            argument_values.PushValue(input_value);
+        }
+
+        
+        bool success = abi->GetArgumentValues (thread, argument_values);
+        if (!success)
+            return ret_plan_sp;
+        
+        // Okay, the first value here is the object, we actually want the class of that object.
+        // For now we're just going with the ISA.  
+        // FIXME: This should really be the return value of [object class] to properly handle KVO interposition.
+        
+        Value isa_value(*(argument_values.GetValueAtIndex(obj_index)));
+        
+        // This is a little cheesy, but since object->isa is the first field, 
+        // making the object value a load address value and resolving it will get
+        // the pointer sized data pointed to by that value...
+        ExecutionContext exec_ctx;
+        thread.Calculate (exec_ctx);
+
+        isa_value.SetValueType(Value::eValueTypeLoadAddress);
+        isa_value.ResolveValue(&exec_ctx, clang_ast_context->getASTContext());
+        
+        if (this_dispatch->fixedup == DispatchFunction::eFixUpFixed)
+        {
+            // For the FixedUp method the Selector is actually a pointer to a 
+            // structure, the second field of which is the selector number.
+            Value *sel_value = argument_values.GetValueAtIndex(sel_index);
+            sel_value->GetScalar() += process->GetAddressByteSize();
+            sel_value->SetValueType(Value::eValueTypeLoadAddress);
+            sel_value->ResolveValue(&exec_ctx, clang_ast_context->getASTContext());            
+        }
+        else if (this_dispatch->fixedup == DispatchFunction::eFixUpToFix)
+        {   
+            // FIXME: If the method dispatch is not "fixed up" then the selector is actually a
+            // pointer to the string name of the selector.  We need to look that up...
+            // For now I'm going to punt on that and just return no plan.
+            if (log)
+                log->Printf ("Punting on stepping into un-fixed-up method dispatch.");
+            return ret_plan_sp;
+        }
+        
+        // FIXME: If this is a dispatch to the super-class, we need to get the super-class from
+        // the class, and disaptch to that instead.
+        // But for now I just punt and return no plan.
+        if (this_dispatch->is_super)
+        {   
+            if (log)
+                log->Printf ("Punting on stepping into super method dispatch.");
+            return ret_plan_sp;
+        }
+        
+        ValueList dispatch_values;
+        dispatch_values.PushValue (isa_value);
+        dispatch_values.PushValue(*(argument_values.GetValueAtIndex(sel_index)));
+        
+        if (log)
+        {
+            log->Printf("Resolving method call for class - 0x%llx and selector - 0x%llx",
+                        dispatch_values.GetValueAtIndex(0)->GetScalar().ULongLong(),
+                        dispatch_values.GetValueAtIndex(1)->GetScalar().ULongLong());
+        }
+        
+        lldb::addr_t impl_addr = LookupInCache (dispatch_values.GetValueAtIndex(0)->GetScalar().ULongLong(),
+                                                dispatch_values.GetValueAtIndex(1)->GetScalar().ULongLong());
+                                                
+        if (impl_addr == LLDB_INVALID_ADDRESS)
+        {
+
+            Address resolve_address(NULL, this_dispatch->stret_return ? m_impl_stret_fn_addr : m_impl_fn_addr);
+            
+            StreamString errors;
+            { 
+                // Scope for mutex locker:
+                Mutex::Locker (m_impl_function_mutex);
+                if (!m_impl_function.get())
+                {
+                     m_impl_function.reset(new ClangFunction(process->GetTargetTriple().GetCString(), 
+                                                             clang_ast_context, 
+                                                             clang_void_ptr_type, 
+                                                             resolve_address, 
+                                                             dispatch_values));
+                            
+                    unsigned num_errors = m_impl_function->CompileFunction(errors);
+                    if (num_errors)
+                    {
+                        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+                        if (log)
+                            log->Printf ("Error compiling function: \"%s\".", errors.GetData());
+                        return ret_plan_sp;
+                    }
+                    
+                    errors.Clear();
+                    if (!m_impl_function->WriteFunctionWrapper(exec_ctx, errors))
+                    {
+                        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+                        if (log)
+                            log->Printf ("Error Inserting function: \"%s\".", errors.GetData());
+                        return ret_plan_sp;
+                    }
+                }
+                
+            }
+            
+            errors.Clear();
+            
+            // Now write down the argument values for this call.
+            lldb::addr_t args_addr = LLDB_INVALID_ADDRESS;
+            if (!m_impl_function->WriteFunctionArguments (exec_ctx, args_addr, resolve_address, dispatch_values, errors))
+                return ret_plan_sp;
+        
+            ret_plan_sp.reset (new ThreadPlanStepThroughObjCTrampoline (thread, this, args_addr, 
+                                                                        argument_values.GetValueAtIndex(0)->GetScalar().ULongLong(),
+                                                                        dispatch_values.GetValueAtIndex(0)->GetScalar().ULongLong(),
+                                                                        dispatch_values.GetValueAtIndex(1)->GetScalar().ULongLong(),
+                                                                        stop_others));
+        }
+        else
+        {
+            if (log)
+                log->Printf ("Found implementation address in cache: 0x%llx", impl_addr);
+                 
+            ret_plan_sp.reset (new ThreadPlanRunToAddress (thread, impl_addr, stop_others));
+        }
+    }
+    
+    return ret_plan_sp;
+}
+
+void
+ObjCTrampolineHandler::AddToCache (lldb::addr_t class_addr, lldb::addr_t selector, lldb::addr_t impl_addr)
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+    if (log)
+    {
+        log->Printf ("Caching: class 0x%llx selector 0x%llx implementation 0x%llx.", class_addr, selector, impl_addr);
+    }
+    m_impl_cache.insert (std::pair<ClassAndSel,lldb::addr_t> (ClassAndSel(class_addr, selector), impl_addr));
+}
+
+lldb::addr_t
+ObjCTrampolineHandler::LookupInCache (lldb::addr_t class_addr, lldb::addr_t selector)
+{
+    MsgImplMap::iterator pos, end = m_impl_cache.end();
+    pos = m_impl_cache.find (ClassAndSel(class_addr, selector));
+    if (pos != end)
+        return (*pos).second;
+    return LLDB_INVALID_ADDRESS;
+}
+
+ClangFunction *
+ObjCTrampolineHandler::GetLookupImplementationWrapperFunction ()
+{
+    return m_impl_function.get();
+}
diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/ObjCTrampolineHandler.h b/source/Plugins/DynamicLoader/MacOSX-DYLD/ObjCTrampolineHandler.h
new file mode 100644
index 0000000..bc06d26
--- /dev/null
+++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/ObjCTrampolineHandler.h
@@ -0,0 +1,133 @@
+//===-- ObjCTrampolineHandler.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_ObjCTrampolineHandler_h_
+#define lldb_ObjCTrampolineHandler_h_
+
+// C Includes
+// C++ Includes
+#include <map>
+#include <string>
+// Other libraries and framework includes
+// Project includes
+#include "lldb.h"
+#include "lldb/Expression/ClangExpression.h"
+#include "lldb/Expression/ClangFunction.h"
+#include "lldb/Host/Mutex.h"
+
+
+namespace lldb_private
+{
+using namespace lldb;
+  
+class ObjCTrampolineHandler {
+public:
+    
+    ObjCTrampolineHandler (ProcessSP process_sp, ModuleSP objc_module_sp);
+    
+    ~ObjCTrampolineHandler() {}
+    
+    static bool ModuleIsObjCLibrary (const ModuleSP &module_sp);
+        
+    ThreadPlanSP
+    GetStepThroughDispatchPlan (Thread &thread, bool stop_others);
+    
+    void
+    AddToCache (lldb::addr_t class_addr, lldb::addr_t sel, lldb::addr_t impl_addr);
+    
+    lldb::addr_t
+    LookupInCache (lldb::addr_t class_addr, lldb::addr_t sel);
+    
+    ClangFunction *
+    GetLookupImplementationWrapperFunction ();
+    
+    
+    struct DispatchFunction {
+    public:
+        typedef enum 
+        {
+            eFixUpNone,
+            eFixUpFixed,
+            eFixUpToFix
+        } FixUpState;
+                
+        const char *name;
+        bool stret_return;
+        bool is_super;
+        FixUpState fixedup;
+    };
+    
+private:
+    static const DispatchFunction g_dispatch_functions[];
+    
+    typedef std::map<lldb::addr_t, int> MsgsendMap; // This table maps an dispatch fn address to the index in g_dispatch_functions
+    MsgsendMap m_msgSend_map;
+    ProcessSP m_process_sp;
+    ModuleSP m_objc_module_sp;
+    lldb::addr_t get_impl_addr;
+    std::auto_ptr<ClangFunction> m_impl_function;
+    Mutex m_impl_function_mutex;
+    lldb::addr_t m_impl_fn_addr;
+    lldb::addr_t m_impl_stret_fn_addr;
+    
+     
+    // We keep a map of <Class,Selector>->Implementation so we don't have to call the resolver
+    // function over and over.
+    
+    // FIXME: We need to watch for the loading of Protocols, and flush the cache for any
+    // class that we see so changed.
+    
+    struct ClassAndSel
+    {
+        ClassAndSel()
+        {
+            sel_addr = LLDB_INVALID_ADDRESS;
+            class_addr = LLDB_INVALID_ADDRESS;
+        }
+        ClassAndSel (lldb::addr_t in_sel_addr, lldb::addr_t in_class_addr) :
+            class_addr (in_class_addr),
+            sel_addr(in_sel_addr)
+        {
+        }
+        bool operator== (const ClassAndSel &rhs)
+        {
+            if (class_addr == rhs.class_addr
+                && sel_addr == rhs.sel_addr)
+                return true;
+            else
+                return false;
+        }
+        
+        bool operator< (const ClassAndSel &rhs) const
+        {
+            if (class_addr < rhs.class_addr)
+                return true;
+            else if (class_addr > rhs.class_addr)
+                return false;
+            else
+            {
+                if (sel_addr < rhs.sel_addr)
+                    return true;
+                else
+                    return false;
+            }
+        }
+        
+        lldb::addr_t class_addr;
+        lldb::addr_t sel_addr;
+    };
+
+    typedef std::map<ClassAndSel,lldb::addr_t> MsgImplMap;
+    MsgImplMap m_impl_cache;
+    
+};
+
+};  // using namespace lldb_private
+
+#endif	// lldb_ObjCTrampolineHandler_h_
diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/ThreadPlanStepThroughObjCTrampoline.cpp b/source/Plugins/DynamicLoader/MacOSX-DYLD/ThreadPlanStepThroughObjCTrampoline.cpp
new file mode 100644
index 0000000..a0cb0a8
--- /dev/null
+++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/ThreadPlanStepThroughObjCTrampoline.cpp
@@ -0,0 +1,151 @@
+//===-- ThreadPlanStepThroughObjCTrampoline.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
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "ThreadPlanStepThroughObjCTrampoline.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Expression/ClangExpression.h"
+#include "lldb/Expression/ClangFunction.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/ThreadPlanRunToAddress.h"
+#include "lldb/Core/Log.h"
+
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// ThreadPlanStepThroughObjCTrampoline constructor
+//----------------------------------------------------------------------
+ThreadPlanStepThroughObjCTrampoline::ThreadPlanStepThroughObjCTrampoline(
+        Thread &thread, 
+        ObjCTrampolineHandler *trampoline_handler, 
+        lldb::addr_t args_addr, 
+        lldb::addr_t object_ptr, 
+        lldb::addr_t class_ptr, 
+        lldb::addr_t sel_ptr, 
+        bool stop_others) :
+    ThreadPlan ("MacOSX Step through ObjC Trampoline", thread, eVoteNoOpinion, eVoteNoOpinion),
+    m_objc_trampoline_handler (trampoline_handler),
+    m_impl_function (trampoline_handler->GetLookupImplementationWrapperFunction()),
+    m_args_addr (args_addr),
+    m_object_ptr (object_ptr),
+    m_class_ptr (class_ptr),
+    m_sel_ptr (sel_ptr),
+    m_stop_others (stop_others)
+{
+    
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ThreadPlanStepThroughObjCTrampoline::~ThreadPlanStepThroughObjCTrampoline()
+{
+}
+
+void
+ThreadPlanStepThroughObjCTrampoline::DidPush ()
+{
+    StreamString errors;
+    ExecutionContext exc_context;
+    m_thread.Calculate(exc_context);
+    m_func_sp.reset(m_impl_function->GetThreadPlanToCallFunction (exc_context, m_args_addr, errors, m_stop_others));
+    m_func_sp->SetPrivate(true);
+    m_thread.QueueThreadPlan (m_func_sp, false);
+}
+
+void
+ThreadPlanStepThroughObjCTrampoline::GetDescription (Stream *s,
+                lldb::DescriptionLevel level)
+{
+    if (level == lldb::eDescriptionLevelBrief)
+        s->Printf("Step through ObjC trampoline");
+    else
+    {
+        s->Printf ("Stepping to implementation of ObjC method - obj: 0x%llx class: 0x%llx selector: 0x%llx",
+        m_object_ptr, m_class_ptr, m_sel_ptr);
+    }
+}
+                
+bool
+ThreadPlanStepThroughObjCTrampoline::ValidatePlan (Stream *error)
+{
+    return true;
+}
+
+bool
+ThreadPlanStepThroughObjCTrampoline::PlanExplainsStop ()
+{
+    // This plan should actually never stop when it is on the top of the plan
+    // stack, since it does all it's running in client plans.
+    return false;
+}
+
+lldb::StateType
+ThreadPlanStepThroughObjCTrampoline::RunState ()
+{
+    return eStateRunning;
+}
+
+bool
+ThreadPlanStepThroughObjCTrampoline::ShouldStop (Event *event_ptr)
+{
+    if (m_func_sp.get() == NULL || m_thread.IsThreadPlanDone(m_func_sp.get()))
+    {
+        m_func_sp.reset();
+        if (!m_run_to_sp) 
+        {
+            Value target_addr_value;
+            ExecutionContext exc_context;
+            m_thread.Calculate(exc_context);
+            m_impl_function->FetchFunctionResults (exc_context, m_args_addr, target_addr_value);
+            m_impl_function->DeallocateFunctionResults(exc_context, m_args_addr);
+            lldb::addr_t target_addr = target_addr_value.GetScalar().ULongLong();
+            Address target_address(NULL, target_addr);
+            Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+            if (log)
+                log->Printf("Running to ObjC method implementation: 0x%llx", target_addr);
+            
+            m_objc_trampoline_handler->AddToCache (m_class_ptr, m_sel_ptr, target_addr);
+
+            // Extract the target address from the value:
+            
+            m_run_to_sp.reset(new ThreadPlanRunToAddress(m_thread, target_address, m_stop_others));
+            m_thread.QueueThreadPlan(m_run_to_sp, false);
+            m_run_to_sp->SetPrivate(true);
+            return false;
+        }
+        else if (m_thread.IsThreadPlanDone(m_run_to_sp.get()))
+        {
+            SetPlanComplete();
+            return true;
+        }
+    }
+    return false;
+}
+
+// The base class MischiefManaged does some cleanup - so you have to call it
+// in your MischiefManaged derived class.
+bool
+ThreadPlanStepThroughObjCTrampoline::MischiefManaged ()
+{
+    if (IsPlanComplete())
+        return true;
+    else
+        return false;
+}
+
+bool
+ThreadPlanStepThroughObjCTrampoline::WillStop()
+{
+    return true;
+}
diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/ThreadPlanStepThroughObjCTrampoline.h b/source/Plugins/DynamicLoader/MacOSX-DYLD/ThreadPlanStepThroughObjCTrampoline.h
new file mode 100644
index 0000000..8033718
--- /dev/null
+++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/ThreadPlanStepThroughObjCTrampoline.h
@@ -0,0 +1,94 @@
+//===-- ThreadPlanStepThroughObjCTrampoline.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_ThreadPlanStepThroughObjCTrampoline_h_
+#define lldb_ThreadPlanStepThroughObjCTrampoline_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb-types.h"
+#include "lldb-enumerations.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "ObjCTrampolineHandler.h"
+
+namespace lldb_private 
+{
+
+class ThreadPlanStepThroughObjCTrampoline : public ThreadPlan
+{
+public:
+	//------------------------------------------------------------------
+	// Constructors and Destructors
+	//------------------------------------------------------------------
+	ThreadPlanStepThroughObjCTrampoline(Thread &thread, 
+                                        ObjCTrampolineHandler *trampoline_handler, 
+                                        lldb::addr_t args_addr, 
+                                        lldb::addr_t object_ptr, 
+                                        lldb::addr_t class_ptr, 
+                                        lldb::addr_t sel_ptr, 
+                                        bool stop_others);
+    
+	virtual ~ThreadPlanStepThroughObjCTrampoline();
+
+    virtual void
+    GetDescription (Stream *s,
+                    lldb::DescriptionLevel level);
+                    
+    virtual bool
+    ValidatePlan (Stream *error);
+
+    virtual bool
+    PlanExplainsStop ();
+
+
+    virtual lldb::StateType
+    RunState ();
+
+    virtual bool
+    ShouldStop (Event *event_ptr);
+
+    // The base class MischiefManaged does some cleanup - so you have to call it
+    // in your MischiefManaged derived class.
+    virtual bool
+    MischiefManaged ();
+    
+    virtual void
+    DidPush();
+    
+    virtual bool
+    WillStop();
+
+
+
+protected:
+	//------------------------------------------------------------------
+	// Classes that inherit from ThreadPlanStepThroughObjCTrampoline can see and modify these
+	//------------------------------------------------------------------
+	
+private:
+	//------------------------------------------------------------------
+	// For ThreadPlanStepThroughObjCTrampoline only
+	//------------------------------------------------------------------
+    ThreadPlanSP m_func_sp;       // This is the function call plan.  We fill it at start, then set it
+                                  // to NULL when this plan is done.  That way we know to go to:
+    lldb::addr_t m_args_addr;     // Stores the address for our step through function result structure.
+    ThreadPlanSP m_run_to_sp;     // The plan that runs to the target.
+    bool m_stop_others;
+    ObjCTrampolineHandler *m_objc_trampoline_handler;
+    ClangFunction *m_impl_function;  // This is a pointer to a impl function that 
+                                     // is owned by the client that pushes this plan.
+    lldb::addr_t m_object_ptr;
+    lldb::addr_t m_class_ptr;
+    lldb::addr_t m_sel_ptr;
+};
+
+}; // namespace lldb_private
+#endif	// lldb_ThreadPlanStepThroughObjCTrampoline_h_
diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
new file mode 100644
index 0000000..c2fb2a5
--- /dev/null
+++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
@@ -0,0 +1,428 @@
+//===-- ObjectContainerBSDArchive.cpp ---------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ObjectContainerBSDArchive.h"
+
+#include <ar.h>
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Symbol/ObjectFile.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+
+ObjectContainerBSDArchive::Object::Object() :
+    ar_name(),
+    ar_date(0),
+    ar_uid(0),
+    ar_gid(0),
+    ar_mode(0),
+    ar_size(0),
+    ar_file_offset(0),
+    ar_file_size(0)
+{
+}
+
+void
+ObjectContainerBSDArchive::Object::Clear()
+{
+    ar_name.Clear();
+    ar_date = 0;
+    ar_uid  = 0;
+    ar_gid  = 0;
+    ar_mode = 0;
+    ar_size = 0;
+    ar_file_offset = 0;
+    ar_file_size = 0;
+}
+
+uint32_t
+ObjectContainerBSDArchive::Object::Extract (const DataExtractor& data, uint32_t offset)
+{
+    size_t ar_name_len = 0;
+    std::string str;
+    char *err;
+    str.assign ((const char *)data.GetData(&offset, 16),    16);
+    if (str.find(AR_EFMT1) == 0)
+    {
+        // If the name is longer than 16 bytes, or contains an embedded space
+        // then it will use this format where the length of the name is
+        // here and the name characters are after this header.
+        ar_name_len = strtoul(str.c_str() + 3, &err, 10);
+    }
+    else
+    {
+        // Strip off any spaces (if the object file name contains spaces it
+        // will use the extended format above).
+        str.erase (str.find(' '));
+        ar_name.SetCString(str.c_str());
+    }
+
+    str.assign ((const char *)data.GetData(&offset, 12),    12);
+    ar_date = strtoul(str.c_str(), &err, 10);
+
+    str.assign ((const char *)data.GetData(&offset, 6), 6);
+    ar_uid  = strtoul(str.c_str(), &err, 10);
+
+    str.assign ((const char *)data.GetData(&offset, 6), 6);
+    ar_gid  = strtoul(str.c_str(), &err, 10);
+
+    str.assign ((const char *)data.GetData(&offset, 8), 8);
+    ar_mode = strtoul(str.c_str(), &err, 8);
+
+    str.assign ((const char *)data.GetData(&offset, 10),    10);
+    ar_size = strtoul(str.c_str(), &err, 10);
+
+    str.assign ((const char *)data.GetData(&offset, 2), 2);
+    if (str == ARFMAG)
+    {
+        if (ar_name_len > 0)
+        {
+            str.assign ((const char *)data.GetData(&offset, ar_name_len), ar_name_len);
+            ar_name.SetCString (str.c_str());
+        }
+        ar_file_offset = offset;
+        ar_file_size = ar_size - ar_name_len;
+        return offset;
+    }
+    return LLDB_INVALID_INDEX32;
+}
+
+ObjectContainerBSDArchive::Archive::Archive
+(
+    const lldb_private::ArchSpec &arch,
+    const lldb_private::TimeValue &time
+) :
+    m_arch (arch),
+    m_time (time),
+    m_objects()
+{
+}
+
+ObjectContainerBSDArchive::Archive::~Archive ()
+{
+}
+
+size_t
+ObjectContainerBSDArchive::Archive::ParseObjects (DataExtractor &data)
+{
+    std::string str;
+    uint32_t offset = 0;
+    str.assign((const char *)data.GetData(&offset, SARMAG), SARMAG);
+    if (str == ARMAG)
+    {
+        Object obj;
+        do
+        {
+            offset = obj.Extract (data, offset);
+            if (offset == LLDB_INVALID_INDEX32)
+                break;
+            uint32_t obj_idx = m_objects.size();
+            m_objects.push_back(obj);
+            // Insert all of the C strings out of order for now...
+            m_object_name_to_index_map.Append (obj.ar_name.GetCString(), obj_idx);
+            offset += obj.ar_file_size;
+            obj.Clear();
+        } while (data.ValidOffset(offset));
+
+        // Now sort all of the object name pointers
+        m_object_name_to_index_map.Sort ();
+    }
+    return m_objects.size();
+}
+
+ObjectContainerBSDArchive::Object *
+ObjectContainerBSDArchive::Archive::FindObject (const ConstString &object_name)
+{
+    const UniqueCStringMap<uint32_t>::Entry *match = m_object_name_to_index_map.FindFirstValueForName (object_name.GetCString());
+    if (match)
+        return &m_objects[match->value];
+    return NULL;
+}
+
+
+ObjectContainerBSDArchive::Archive::shared_ptr
+ObjectContainerBSDArchive::Archive::FindCachedArchive (const FileSpec &file, const ArchSpec &arch, const TimeValue &time)
+{
+    Mutex::Locker locker(Archive::GetArchiveCacheMutex ());
+    shared_ptr archive_sp;
+    Archive::Map &archive_map = Archive::GetArchiveCache ();
+    Archive::Map::iterator pos;
+    for (pos = archive_map.find (file); pos != archive_map.end() && pos->first == file; ++pos)
+    {
+        if (pos->second->GetArchitecture() == arch &&
+            pos->second->GetModificationTime() == time)
+        {
+            archive_sp = pos->second;
+        }
+    }
+    return archive_sp;
+}
+
+ObjectContainerBSDArchive::Archive::shared_ptr
+ObjectContainerBSDArchive::Archive::ParseAndCacheArchiveForFile
+(
+    const FileSpec &file,
+    const ArchSpec &arch,
+    const TimeValue &time,
+    DataExtractor &data
+)
+{
+    shared_ptr archive_sp(new Archive (arch, time));
+    if (archive_sp)
+    {
+        if (archive_sp->ParseObjects (data) > 0)
+        {
+            Mutex::Locker locker(Archive::GetArchiveCacheMutex ());
+            Archive::GetArchiveCache().insert(std::make_pair(file, archive_sp));
+        }
+        else
+        {
+            archive_sp.reset();
+        }
+    }
+    return archive_sp;
+}
+
+ObjectContainerBSDArchive::Archive::Map &
+ObjectContainerBSDArchive::Archive::GetArchiveCache ()
+{
+    static Archive::Map g_archive_map;
+    return g_archive_map;
+}
+
+Mutex &
+ObjectContainerBSDArchive::Archive::GetArchiveCacheMutex ()
+{
+    static Mutex g_archive_map_mutex (Mutex::eMutexTypeRecursive);
+    return g_archive_map_mutex;
+}
+
+
+void
+ObjectContainerBSDArchive::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance);
+}
+
+void
+ObjectContainerBSDArchive::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+const char *
+ObjectContainerBSDArchive::GetPluginNameStatic()
+{
+    return "object-container.bsd-archive";
+}
+
+const char *
+ObjectContainerBSDArchive::GetPluginDescriptionStatic()
+{
+    return "BSD Archive object container reader.";
+}
+
+
+ObjectContainer *
+ObjectContainerBSDArchive::CreateInstance
+(
+    Module* module,
+    DataBufferSP& dataSP,
+    const FileSpec *file,
+    addr_t offset,
+    addr_t length)
+{
+    if (file)
+    {
+        std::string object;
+
+        Archive::shared_ptr archive_sp (Archive::FindCachedArchive (*file, module->GetArchitecture(), module->GetModificationTime()));
+
+        if (archive_sp)
+        {
+            // We already have this archive in our cache, use it
+            std::auto_ptr<ObjectContainerBSDArchive> container_ap(new ObjectContainerBSDArchive (module, dataSP, file, offset, length));
+            if (container_ap.get())
+            {
+                container_ap->SetArchive (archive_sp);
+                return container_ap.release();
+            }
+        }
+
+        if (dataSP)
+        {
+            if (ObjectContainerBSDArchive::MagicBytesMatch(dataSP))
+            {
+                // Read everything since we need that in order to index all the
+                // objects in the archive
+                dataSP = file->ReadFileContents(offset, length);
+
+                std::auto_ptr<ObjectContainerBSDArchive> container_ap(new ObjectContainerBSDArchive (module, dataSP, file, offset, length));
+                if (container_ap->ParseHeader())
+                    return container_ap.release();
+            }
+        }
+    }
+    return NULL;
+}
+
+
+
+bool
+ObjectContainerBSDArchive::MagicBytesMatch (DataBufferSP& dataSP)
+{
+    DataExtractor data(dataSP, eByteOrderHost, 4);
+    uint32_t offset = 0;
+    const char* armag = (const char* )data.PeekData (offset, sizeof(ar_hdr));
+    if (armag && ::strncmp(armag, ARMAG, SARMAG) == 0)
+    {
+        armag += offsetof(struct ar_hdr, ar_fmag) + SARMAG;
+        if (strncmp(armag, ARFMAG, 2) == 0)
+            return true;
+    }
+    return false;
+}
+
+ObjectContainerBSDArchive::ObjectContainerBSDArchive
+(
+    Module* module,
+    DataBufferSP& dataSP,
+    const lldb_private::FileSpec *file,
+    lldb::addr_t offset,
+    lldb::addr_t size
+) :
+    ObjectContainer (module, file, offset, size, dataSP),
+    m_archive_sp ()
+{
+}
+void
+ObjectContainerBSDArchive::SetArchive (Archive::shared_ptr &archive_sp)
+{
+    m_archive_sp  = archive_sp;
+}
+
+
+
+ObjectContainerBSDArchive::~ObjectContainerBSDArchive()
+{
+}
+
+bool
+ObjectContainerBSDArchive::ParseHeader ()
+{
+    if (m_archive_sp.get() == NULL)
+    {
+        if (m_data.GetByteSize() > 0)
+        {
+            m_archive_sp = Archive::ParseAndCacheArchiveForFile (m_file,
+                                                                 m_module->GetArchitecture(),
+                                                                 m_module->GetModificationTime(),
+                                                                 m_data);
+            // The archive might be huge, so clear "m_data" to free up the
+            // memory since it will contain the entire file (possibly more than
+            // one architecture slice). We already have an index of all objects
+            // in the file, so we will be ready to serve up those objects.
+            m_data.Clear();
+        }
+    }
+    return m_archive_sp.get() != NULL;
+}
+
+void
+ObjectContainerBSDArchive::Dump (Stream *s) const
+{
+    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+    s->Indent();
+    const size_t num_archs = GetNumArchitectures();
+    const size_t num_objects = GetNumObjects();
+    s->Printf("ObjectContainerBSDArchive, num_archs = %u, num_objects = %u", num_archs, num_objects);
+    uint32_t i;
+    ArchSpec arch;
+    s->IndentMore();
+    for (i=0; i<num_archs; i++)
+    {
+        s->Indent();
+        GetArchitectureAtIndex(i, arch);
+        s->Printf("arch[%u] = %s\n", arch.AsCString());
+    }
+    for (i=0; i<num_objects; i++)
+    {
+        s->Indent();
+        s->Printf("object[%u] = %s\n", GetObjectNameAtIndex (i));
+    }
+    s->IndentLess();
+    s->EOL();
+}
+
+ObjectFile *
+ObjectContainerBSDArchive::GetObjectFile (const FileSpec *file)
+{
+    if (m_module->GetObjectName() && m_archive_sp)
+    {
+        Object *object = m_archive_sp->FindObject (m_module->GetObjectName());
+        if (object)
+            return ObjectFile::FindPlugin (m_module, file, m_offset + object->ar_file_offset, object->ar_file_size);
+    }
+    return NULL;
+}
+
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+const char *
+ObjectContainerBSDArchive::GetPluginName()
+{
+    return "object-container.bsd-archive";
+}
+
+const char *
+ObjectContainerBSDArchive::GetShortPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+ObjectContainerBSDArchive::GetPluginVersion()
+{
+    return 1;
+}
+
+void
+ObjectContainerBSDArchive::GetPluginCommandHelp (const char *command, Stream *strm)
+{
+}
+
+Error
+ObjectContainerBSDArchive::ExecutePluginCommand (Args &command, Stream *strm)
+{
+    Error error;
+    error.SetErrorString("No plug-in command are currently supported.");
+    return error;
+}
+
+Log *
+ObjectContainerBSDArchive::EnablePluginLogging (Stream *strm, Args &command)
+{
+    return NULL;
+}
+
+
+
diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
new file mode 100644
index 0000000..88aba01
--- /dev/null
+++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
@@ -0,0 +1,183 @@
+//===-- ObjectContainerBSDArchive.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_ObjectContainerBSDArchive_h_
+#define liblldb_ObjectContainerBSDArchive_h_
+
+#include "lldb/Symbol/ObjectContainer.h"
+
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Core/UniqueCStringMap.h"
+#include "lldb/Host/TimeValue.h"
+
+class ObjectContainerBSDArchive :
+    public lldb_private::ObjectContainer
+{
+public:
+
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static const char *
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb_private::ObjectContainer *
+    CreateInstance (lldb_private::Module* module,
+                    lldb::DataBufferSP& dataSP,
+                    const lldb_private::FileSpec *file,
+                    lldb::addr_t offset,
+                    lldb::addr_t length);
+
+    static bool
+    MagicBytesMatch (lldb::DataBufferSP& dataSP);
+
+    //------------------------------------------------------------------
+    // Member Functions
+    //------------------------------------------------------------------
+    ObjectContainerBSDArchive (lldb_private::Module* module,
+                               lldb::DataBufferSP& dataSP,
+                               const lldb_private::FileSpec *file,
+                               lldb::addr_t offset,
+                               lldb::addr_t length);
+
+    virtual
+    ~ObjectContainerBSDArchive();
+
+    virtual bool
+    ParseHeader ();
+
+    virtual void
+    Dump (lldb_private::Stream *s) const;
+
+    virtual lldb_private::ObjectFile *
+    GetObjectFile (const lldb_private::FileSpec *file);
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual const char *
+    GetPluginName();
+
+    virtual const char *
+    GetShortPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+    virtual void
+    GetPluginCommandHelp (const char *command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Error
+    ExecutePluginCommand (lldb_private::Args &command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Log *
+    EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
+
+
+protected:
+
+    struct Object
+    {
+        Object();
+
+        void
+        Clear();
+
+        uint32_t
+        Extract (const lldb_private::DataExtractor& data, uint32_t offset);
+
+        lldb_private::ConstString       ar_name;        // name
+        uint32_t        ar_date;        // modification time
+        uint16_t        ar_uid;         // user id
+        uint16_t        ar_gid;         // group id
+        uint16_t        ar_mode;        // octal file permissions
+        uint32_t        ar_size;        // size in bytes
+        uint32_t        ar_file_offset; // file offset in bytes from the beginning of the file of the object data
+        uint32_t        ar_file_size;   // length of the object data
+
+        typedef std::vector<Object>         collection;
+        typedef collection::iterator        iterator;
+        typedef collection::const_iterator  const_iterator;
+    };
+
+    class Archive
+    {
+    public:
+        typedef lldb::SharedPtr<Archive>::Type shared_ptr;
+        typedef std::multimap<lldb_private::FileSpec, shared_ptr> Map;
+
+        static Map &
+        GetArchiveCache ();
+
+        static lldb_private::Mutex &
+        GetArchiveCacheMutex ();
+
+        static Archive::shared_ptr
+        FindCachedArchive (const lldb_private::FileSpec &file,
+                           const lldb_private::ArchSpec &arch,
+                           const lldb_private::TimeValue &mod_time);
+
+        static Archive::shared_ptr
+        ParseAndCacheArchiveForFile (const lldb_private::FileSpec &file,
+                                     const lldb_private::ArchSpec &arch,
+                                     const lldb_private::TimeValue &mod_time,
+                                     lldb_private::DataExtractor &data);
+
+        Archive (const lldb_private::ArchSpec &arch,
+                 const lldb_private::TimeValue &mod_time);
+
+        ~Archive ();
+
+        size_t
+        ParseObjects (lldb_private::DataExtractor &data);
+
+        Object *
+        FindObject (const lldb_private::ConstString &object_name);
+
+        const lldb_private::TimeValue &
+        GetModificationTime()
+        {
+            return m_time;
+        }
+
+        const lldb_private::ArchSpec &
+        GetArchitecture ()
+        {
+            return m_arch;
+        }
+
+    protected:
+
+        //----------------------------------------------------------------------
+        // Member Variables
+        //----------------------------------------------------------------------
+        lldb_private::ArchSpec m_arch;
+        lldb_private::TimeValue m_time;
+        Object::collection  m_objects;
+        lldb_private::UniqueCStringMap<uint32_t> m_object_name_to_index_map;
+    };
+
+    void
+    SetArchive (Archive::shared_ptr &archive_sp);
+
+    Archive::shared_ptr m_archive_sp;
+};
+
+#endif  // liblldb_ObjectContainerBSDArchive_h_
diff --git a/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp b/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp
new file mode 100644
index 0000000..015e498
--- /dev/null
+++ b/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp
@@ -0,0 +1,259 @@
+//===-- ObjectContainerUniversalMachO.cpp -----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ObjectContainerUniversalMachO.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Symbol/ObjectFile.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+void
+ObjectContainerUniversalMachO::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance);
+}
+
+void
+ObjectContainerUniversalMachO::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+const char *
+ObjectContainerUniversalMachO::GetPluginNameStatic()
+{
+    return "object-container.mach-o";
+}
+
+const char *
+ObjectContainerUniversalMachO::GetPluginDescriptionStatic()
+{
+    return "Universal mach-o object container reader.";
+}
+
+
+ObjectContainer *
+ObjectContainerUniversalMachO::CreateInstance
+(
+    Module* module,
+    DataBufferSP& dataSP,
+    const FileSpec *file,
+    addr_t offset,
+    addr_t length
+)
+{
+    if (ObjectContainerUniversalMachO::MagicBytesMatch(dataSP))
+    {
+        std::auto_ptr<ObjectContainerUniversalMachO> container_ap(new ObjectContainerUniversalMachO (module, dataSP, file, offset, length));
+        if (container_ap->ParseHeader())
+        {
+            return container_ap.release();
+        }
+    }
+    return NULL;
+}
+
+
+
+bool
+ObjectContainerUniversalMachO::MagicBytesMatch (DataBufferSP& dataSP)
+{
+    DataExtractor data(dataSP, eByteOrderHost, 4);
+    uint32_t offset = 0;
+    uint32_t magic = data.GetU32(&offset);
+    return magic == FAT_MAGIC || magic == FAT_CIGAM;
+}
+
+ObjectContainerUniversalMachO::ObjectContainerUniversalMachO
+(
+    Module* module,
+    DataBufferSP& dataSP,
+    const FileSpec *file,
+    addr_t offset,
+    addr_t length
+) :
+    ObjectContainer (module, file, offset, length, dataSP),
+    m_header(),
+    m_fat_archs()
+{
+    memset(&m_header, 0, sizeof(m_header));
+}
+
+
+ObjectContainerUniversalMachO::~ObjectContainerUniversalMachO()
+{
+}
+
+bool
+ObjectContainerUniversalMachO::ParseHeader ()
+{
+    // Store the file offset for this universal file as we could have a universal .o file
+    // in a BSD archive, or be contained in another kind of object.
+    uint32_t offset = 0;
+    // Universal mach-o files always have their headers in big endian.
+    m_data.SetByteOrder (eByteOrderBig);
+    m_header.magic = m_data.GetU32(&offset);
+
+    if (m_header.magic == FAT_MAGIC)
+    {
+        m_data.SetAddressByteSize(4);
+
+        m_header.nfat_arch = m_data.GetU32(&offset);
+
+        const size_t nfat_arch_size = sizeof(fat_arch_t) * m_header.nfat_arch;
+        // See if the current data we have is enough for all of the fat headers?
+        if (!m_data.ValidOffsetForDataOfSize(offset, nfat_arch_size))
+        {
+            // The fat headers are larger than the number of bytes we have been
+            // given when this class was constructed. We will read the exact number
+            // of bytes that we need.
+            DataBufferSP data_sp(m_file.ReadFileContents(m_offset, nfat_arch_size + sizeof(fat_header_t)));
+            m_data.SetData (data_sp);
+        }
+
+        // Now we should have enough data for all of the fat headers, so lets index
+        // them so we know how many architectures that this univeral binary contains.
+        uint32_t arch_idx = 0;
+        for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx)
+        {
+            if (m_data.ValidOffsetForDataOfSize(offset, sizeof(fat_arch_t)))
+            {
+                fat_arch_t arch;
+                if (m_data.GetU32(&offset, &arch, sizeof(fat_arch_t)/sizeof(uint32_t)))
+                {
+                    m_fat_archs.push_back(arch);
+                }
+            }
+        }
+        // Now that we have indexed the universal headers, we no longer need any cached data.
+        m_data.Clear();
+
+        return true;
+    }
+    else
+    {
+        memset(&m_header, 0, sizeof(m_header));
+    }
+
+    return false;
+}
+
+void
+ObjectContainerUniversalMachO::Dump (Stream *s) const
+{
+    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+    s->Indent();
+    const size_t num_archs = GetNumArchitectures();
+    const size_t num_objects = GetNumObjects();
+    s->Printf("ObjectContainerUniversalMachO, num_archs = %u, num_objects = %u", num_archs, num_objects);
+    uint32_t i;
+    ArchSpec arch;
+    s->IndentMore();
+    for (i=0; i<num_archs; i++)
+    {
+        s->Indent();
+        GetArchitectureAtIndex(i, arch);
+        s->Printf("arch[%u] = %s\n", arch.AsCString());
+    }
+    for (i=0; i<num_objects; i++)
+    {
+        s->Indent();
+        s->Printf("object[%u] = %s\n", GetObjectNameAtIndex (i));
+    }
+    s->IndentLess();
+    s->EOL();
+}
+
+size_t
+ObjectContainerUniversalMachO::GetNumArchitectures () const
+{
+    return m_header.nfat_arch;
+}
+
+bool
+ObjectContainerUniversalMachO::GetArchitectureAtIndex (uint32_t idx, ArchSpec& arch) const
+{
+    if (idx < m_header.nfat_arch)
+    {
+        arch.SetArch(m_fat_archs[idx].cputype, m_fat_archs[idx].cpusubtype);
+        return true;
+    }
+    return false;
+}
+
+ObjectFile *
+ObjectContainerUniversalMachO::GetObjectFile (const FileSpec *file)
+{
+    uint32_t arch_idx = 0;
+    const ArchSpec arch = m_module->GetArchitecture();
+    ArchSpec curr_arch;
+    for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx)
+    {
+        if (GetArchitectureAtIndex (arch_idx, curr_arch))
+        {
+            if (arch == curr_arch)
+            {
+                return ObjectFile::FindPlugin (m_module, file, m_offset + m_fat_archs[arch_idx].offset, m_fat_archs[arch_idx].size);
+            }
+        }
+    }
+    return NULL;
+}
+
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+const char *
+ObjectContainerUniversalMachO::GetPluginName()
+{
+    return "ObjectContainerUniversalMachO";
+}
+
+const char *
+ObjectContainerUniversalMachO::GetShortPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+ObjectContainerUniversalMachO::GetPluginVersion()
+{
+    return 1;
+}
+
+void
+ObjectContainerUniversalMachO::GetPluginCommandHelp (const char *command, Stream *strm)
+{
+}
+
+Error
+ObjectContainerUniversalMachO::ExecutePluginCommand (Args &command, Stream *strm)
+{
+    Error error;
+    error.SetErrorString("No plug-in command are currently supported.");
+    return error;
+}
+
+Log *
+ObjectContainerUniversalMachO::EnablePluginLogging (Stream *strm, Args &command)
+{
+    return NULL;
+}
+
+
+
diff --git a/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h b/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h
new file mode 100644
index 0000000..8a7f975
--- /dev/null
+++ b/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h
@@ -0,0 +1,103 @@
+//===-- ObjectContainerUniversalMachO.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_ObjectContainerUniversalMachO_h_
+#define liblldb_ObjectContainerUniversalMachO_h_
+
+#include <mach-o/fat.h>
+
+#include "lldb/Symbol/ObjectContainer.h"
+#include "lldb/Core/FileSpec.h"
+
+class ObjectContainerUniversalMachO :
+    public lldb_private::ObjectContainer
+{
+public:
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static const char *
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb_private::ObjectContainer *
+    CreateInstance (lldb_private::Module* module,
+                    lldb::DataBufferSP& dataSP,
+                    const lldb_private::FileSpec *file,
+                    lldb::addr_t offset,
+                    lldb::addr_t length);
+
+    static bool
+    MagicBytesMatch (lldb::DataBufferSP& dataSP);
+
+    //------------------------------------------------------------------
+    // Member Functions
+    //------------------------------------------------------------------
+    ObjectContainerUniversalMachO (lldb_private::Module* module,
+                                   lldb::DataBufferSP& dataSP,
+                                   const lldb_private::FileSpec *file,
+                                   lldb::addr_t offset,
+                                   lldb::addr_t length);
+
+    virtual
+    ~ObjectContainerUniversalMachO();
+
+    virtual bool
+    ParseHeader ();
+
+    virtual void
+    Dump (lldb_private::Stream *s) const;
+
+    virtual size_t
+    GetNumArchitectures () const;
+
+    virtual bool
+    GetArchitectureAtIndex (uint32_t cpu_idx, lldb_private::ArchSpec& arch) const;
+
+    virtual lldb_private::ObjectFile *
+    GetObjectFile (const lldb_private::FileSpec *file);
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual const char *
+    GetPluginName();
+
+    virtual const char *
+    GetShortPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+    virtual void
+    GetPluginCommandHelp (const char *command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Error
+    ExecutePluginCommand (lldb_private::Args &command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Log *
+    EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
+
+
+protected:
+    typedef struct fat_header fat_header_t;
+    typedef struct fat_arch fat_arch_t;
+    fat_header_t m_header;
+    std::vector<fat_arch_t> m_fat_archs;
+};
+
+#endif  // liblldb_ObjectContainerUniversalMachO_h_
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
new file mode 100644
index 0000000..b34dd3d
--- /dev/null
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -0,0 +1,929 @@
+//===-- ObjectFileELF.cpp ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ObjectFileELF.h"
+
+#include <mach/machine.h>
+#include <assert.h>
+
+#include <algorithm>
+
+#include <stdint.h>
+#include "elf.h"
+#include "lldb/Core/DataBuffer.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Symbol/ObjectFile.h"
+
+#define CASE_AND_STREAM(s, def, width)  case def: s->Printf("%-*s", width, #def); break;
+
+static uint32_t ELFMachineToMachCPU(Elf32_Half machine);
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace std;
+
+
+#include <mach-o/nlist.h>
+#include <mach-o/stab.h>
+
+
+void
+ObjectFileELF::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance);
+}
+
+void
+ObjectFileELF::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+const char *
+ObjectFileELF::GetPluginNameStatic()
+{
+    return "object-file.elf32";
+}
+
+const char *
+ObjectFileELF::GetPluginDescriptionStatic()
+{
+    return "ELF object file reader (32-bit).";
+}
+
+
+ObjectFile *
+ObjectFileELF::CreateInstance (Module* module, DataBufferSP& dataSP, const FileSpec* file, addr_t offset, addr_t length)
+{
+    if (ObjectFileELF::MagicBytesMatch(dataSP))
+    {
+        std::auto_ptr<ObjectFile> objfile_ap(new ObjectFileELF (module, dataSP, file, offset, length));
+        if (objfile_ap.get() && objfile_ap->ParseHeader())
+            return objfile_ap.release();
+    }
+    return NULL;
+}
+
+bool
+ObjectFileELF::MagicBytesMatch (DataBufferSP& dataSP)
+{
+    DataExtractor data(dataSP, eByteOrderHost, 4);
+    const uint8_t* magic = data.PeekData(0, 4);
+    if (magic != NULL)
+    {
+        return magic[EI_MAG0] == 0x7f
+            && magic[EI_MAG1] == 'E'
+            && magic[EI_MAG2] == 'L'
+            && magic[EI_MAG3] == 'F';
+    }
+    return false;
+}
+
+
+ObjectFileELF::ObjectFileELF(Module* module, DataBufferSP& dataSP, const FileSpec* file, addr_t offset, addr_t length) :
+    ObjectFile (module, file, offset, length, dataSP),
+    m_header(),
+    m_program_headers(),
+    m_section_headers(),
+    m_sections_ap(),
+    m_symtab_ap(),
+    m_shstr_data()
+{
+    if (file)
+        m_file = *file;
+    ::bzero (&m_header, sizeof(m_header));
+}
+
+
+ObjectFileELF::~ObjectFileELF()
+{
+}
+
+ByteOrder
+ObjectFileELF::GetByteOrder () const
+{
+    if (m_header.e_ident[EI_DATA] == ELFDATA2MSB)
+        return eByteOrderBig;
+    if (m_header.e_ident[EI_DATA] == ELFDATA2LSB)
+        return eByteOrderLittle;
+    return eByteOrderInvalid;
+}
+
+size_t
+ObjectFileELF::GetAddressByteSize () const
+{
+    return m_data.GetAddressByteSize();
+}
+
+bool
+ObjectFileELF::ParseHeader ()
+{
+    m_data.SetAddressByteSize(4);
+    uint32_t offset = GetOffset();
+    if (m_data.GetU8(&offset, m_header.e_ident, EI_NIDENT) == NULL)
+        return false;
+
+    m_data.SetByteOrder(GetByteOrder());
+
+    // Read e_type and e_machine
+    if (m_data.GetU16(&offset, &m_header.e_type, 2) == NULL)
+        return false;
+
+    // read e_version, e_entry, e_phoff, e_shoff, e_flags
+    if (m_data.GetU32(&offset, &m_header.e_version, 5) == NULL)
+        return false;
+
+    // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum, e_shstrndx
+    if (m_data.GetU16(&offset, &m_header.e_ehsize, 6) == NULL)
+        return false;
+
+    return true;
+}
+
+bool
+ObjectFileELF::GetUUID (UUID* uuid)
+{
+    return false;
+}
+
+uint32_t
+ObjectFileELF::GetDependentModules(FileSpecList& files)
+{
+    return 0;
+}
+
+//----------------------------------------------------------------------
+// ParseProgramHeaders
+//----------------------------------------------------------------------
+size_t
+ObjectFileELF::ParseProgramHeaders()
+{
+    // We have already parsed the program headers
+    if (!m_program_headers.empty())
+        return m_program_headers.size();
+
+    uint32_t offset = 0;
+    if (m_header.e_phnum > 0)
+    {
+        m_program_headers.resize(m_header.e_phnum);
+
+        if (m_program_headers.size() != m_header.e_phnum)
+            return 0;
+
+        const size_t byte_size = m_header.e_phnum * m_header.e_phentsize;
+        DataBufferSP buffer_sp(m_file.ReadFileContents(m_offset + m_header.e_phoff, byte_size));
+
+        if (buffer_sp.get() == NULL || buffer_sp->GetByteSize() != byte_size)
+            return 0;
+
+        DataExtractor data(buffer_sp, m_data.GetByteOrder(), m_data.GetAddressByteSize());
+
+        uint32_t idx;
+        for (idx = 0; idx < m_header.e_phnum; ++idx)
+        {
+            if (data.GetU32(&offset, &m_program_headers[idx].p_type, 8) == NULL)
+                return 0;
+        }
+        if (idx < m_program_headers.size())
+            m_program_headers.resize(idx);
+    }
+
+    return m_program_headers.size();
+}
+
+
+//----------------------------------------------------------------------
+// ParseSectionHeaders
+//----------------------------------------------------------------------
+size_t
+ObjectFileELF::ParseSectionHeaders()
+{
+    // We have already parsed the section headers
+    if (!m_section_headers.empty())
+        return m_section_headers.size();
+
+    if (m_header.e_shnum > 0)
+    {
+        uint32_t offset = 0;
+
+        m_section_headers.resize(m_header.e_shnum);
+
+        if (m_section_headers.size() != m_header.e_shnum)
+            return 0;
+
+        const size_t byte_size = m_header.e_shnum * m_header.e_shentsize;
+        DataBufferSP buffer_sp(m_file.ReadFileContents(m_offset + m_header.e_shoff, byte_size));
+
+        if (buffer_sp.get() == NULL || buffer_sp->GetByteSize() != byte_size)
+            return 0;
+
+        DataExtractor data(buffer_sp, m_data.GetByteOrder(), m_data.GetAddressByteSize());
+
+        uint32_t idx;
+        for (idx = 0; idx < m_header.e_shnum; ++idx)
+        {
+            if (data.GetU32(&offset, &m_section_headers[idx].sh_name, 10) == NULL)
+                break;
+        }
+        if (idx < m_section_headers.size())
+            m_section_headers.resize(idx);
+    }
+
+    return m_section_headers.size();
+}
+
+size_t
+ObjectFileELF::GetSectionHeaderStringTable()
+{
+    if (m_shstr_data.GetByteSize() == 0)
+    {
+        if (m_header.e_shstrndx && m_header.e_shstrndx < m_section_headers.size())
+        {
+            const size_t byte_size = m_section_headers[m_header.e_shstrndx].sh_size;
+            DataBufferSP buffer_sp(m_file.ReadFileContents(m_offset + m_section_headers[m_header.e_shstrndx].sh_offset, byte_size));
+
+            if (buffer_sp.get() == NULL || buffer_sp->GetByteSize() != byte_size)
+                return 0;
+
+            m_shstr_data.SetData(buffer_sp);
+        }
+    }
+    return m_shstr_data.GetByteSize();
+}
+
+uint32_t
+ObjectFileELF::GetSectionIndexByName(const char *name)
+{
+    if (ParseSectionHeaders() && GetSectionHeaderStringTable())
+    {
+        uint32_t offset = 1;    // Skip leading NULL string at offset 0;
+        while (m_shstr_data.ValidOffset(offset))
+        {
+            uint32_t sh_name = offset;  // Save offset in case we find a match
+            const char* sectionHeaderName = m_shstr_data.GetCStr(&offset);
+            if (sectionHeaderName)
+            {
+                if (strcmp(name, sectionHeaderName) == 0)
+                {
+                    SectionHeaderCollIter pos;
+                    for (pos = m_section_headers.begin(); pos != m_section_headers.end(); ++pos)
+                    {
+                        if ( (*pos).sh_name == sh_name )
+                        {
+                            // section indexes are 1 based
+                            return std::distance(m_section_headers.begin(), pos) + 1;
+                        }
+                    }
+                    return UINT32_MAX;
+                }
+            }
+            else
+            {
+                return UINT32_MAX;
+            }
+        }
+    }
+
+    return UINT32_MAX;
+}
+
+SectionList *
+ObjectFileELF::GetSectionList()
+{
+    if (m_sections_ap.get() == NULL)
+    {
+        m_sections_ap.reset(new SectionList());
+        if (ParseSectionHeaders() && GetSectionHeaderStringTable())
+        {
+            uint32_t sh_idx = 0;
+            const size_t num_sections = m_section_headers.size();
+            for (sh_idx = 0; sh_idx < num_sections; ++sh_idx)
+            {
+                ConstString section_name(m_shstr_data.PeekCStr(m_section_headers[sh_idx].sh_name));
+                uint64_t section_file_size = m_section_headers[sh_idx].sh_type == SHT_NOBITS ? 0 : m_section_headers[sh_idx].sh_size;
+                SectionSP section_sp(new Section(NULL,                                  // Parent section
+                                                 GetModule(),                           // Module to which this section belongs
+                                                 sh_idx + 1,                            // Section ID is the 1 based
+                                                 section_name,                          // Name of this section
+                                                 eSectionTypeOther,  // TODO: fill this in appropriately for ELF...
+                                                 m_section_headers[sh_idx].sh_addr,     // File VM address
+                                                 m_section_headers[sh_idx].sh_size,     // VM size in bytes of this section
+                                                 m_section_headers[sh_idx].sh_offset,   // Offset to the data for this section in the file
+                                                 section_file_size,                     // Size in bytes of this section as found in the the file
+                                                 m_section_headers[sh_idx].sh_flags));  // Flags for this section
+                if (section_sp.get())
+                    m_sections_ap->AddSection(section_sp);
+
+            }
+        }
+    }
+    return m_sections_ap.get();
+}
+
+static void
+ParseSymbols (Symtab *symtab, SectionList *section_list, const Elf32_Shdr &symtab_shdr, const DataExtractor& symtab_data, const DataExtractor& strtab_data)
+{
+    assert (sizeof(Elf32_Sym) == symtab_shdr.sh_entsize);
+    const uint32_t num_symbols = symtab_data.GetByteSize() / sizeof(Elf32_Sym);
+    uint32_t offset = 0;
+    Elf32_Sym symbol;
+    uint32_t i;
+    static ConstString text_section_name(".text");
+    static ConstString init_section_name(".init");
+    static ConstString fini_section_name(".fini");
+    static ConstString ctors_section_name(".ctors");
+    static ConstString dtors_section_name(".dtors");
+
+    static ConstString data_section_name(".data");
+    static ConstString rodata_section_name(".rodata");
+    static ConstString rodata1_section_name(".rodata1");
+    static ConstString data2_section_name(".data1");
+    static ConstString bss_section_name(".bss");
+
+    for (i=0; i<num_symbols; ++i)
+    {
+    //  if (symtab_data.GetU32(&offset, &symbol.st_name, 3) == 0)
+    //      break;
+
+        if (!symtab_data.ValidOffsetForDataOfSize(offset, sizeof(Elf32_Sym)))
+            break;
+
+        symbol.st_name  = symtab_data.GetU32 (&offset);
+        symbol.st_value = symtab_data.GetU32 (&offset);
+        symbol.st_size  = symtab_data.GetU32 (&offset);
+        symbol.st_info  = symtab_data.GetU8  (&offset);
+        symbol.st_other = symtab_data.GetU8  (&offset);
+        symbol.st_shndx = symtab_data.GetU16 (&offset);
+
+        Section * symbol_section = NULL;
+        SymbolType symbol_type = eSymbolTypeInvalid;
+
+        switch (symbol.st_shndx)
+        {
+        case SHN_ABS:
+            symbol_type = eSymbolTypeAbsolute;
+            break;
+        case SHN_UNDEF:
+            symbol_type = eSymbolTypeUndefined;
+            break;
+        default:
+            symbol_section = section_list->GetSectionAtIndex (symbol.st_shndx).get();
+            break;
+        }
+
+        switch (ELF32_ST_BIND (symbol.st_info))
+        {
+        default:
+        case STT_NOTYPE:
+            // The symbol's type is not specified.
+            break;
+
+        case STT_OBJECT:
+            // The symbol is associated with a data object, such as a variable, an array, etc.
+            symbol_type == eSymbolTypeData;
+            break;
+
+        case STT_FUNC:
+            // The symbol is associated with a function or other executable code.
+            symbol_type == eSymbolTypeCode;
+            break;
+
+        case STT_SECTION:
+            // The symbol is associated with a section. Symbol table entries of
+            // this type exist primarily for relocation and normally have
+            // STB_LOCAL binding.
+            break;
+
+        case STT_FILE:
+            // Conventionally, the symbol's name gives the name of the source
+            // file associated with the object file. A file symbol has STB_LOCAL
+            // binding, its section index is SHN_ABS, and it precedes the other
+            // STB_LOCAL symbols for the file, if it is present.
+            symbol_type == eSymbolTypeObjectFile;
+            break;
+        }
+
+        if (symbol_type == eSymbolTypeInvalid)
+        {
+            if (symbol_section)
+            {
+                const ConstString &sect_name = symbol_section->GetName();
+                if (sect_name == text_section_name ||
+                    sect_name == init_section_name ||
+                    sect_name == fini_section_name ||
+                    sect_name == ctors_section_name ||
+                    sect_name == dtors_section_name)
+                {
+                    symbol_type = eSymbolTypeCode;
+                }
+                else
+                if (sect_name == data_section_name ||
+                    sect_name == data2_section_name ||
+                    sect_name == rodata_section_name ||
+                    sect_name == rodata1_section_name ||
+                    sect_name == bss_section_name)
+                {
+                    symbol_type = eSymbolTypeData;
+                }
+            }
+        }
+
+        uint64_t symbol_value = symbol.st_value;
+        if (symbol_section != NULL)
+            symbol_value -= symbol_section->GetFileAddress();
+        const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);
+
+        Symbol dc_symbol(i,             // ID is the original symbol table index
+                        symbol_name,    // symbol name
+                        false,          // Is the symbol name mangled?
+                        symbol_type,    // type of this symbol
+                        ELF32_ST_BIND (symbol.st_info) == STB_GLOBAL,   // Is this globally visible?
+                        false,          // Is this symbol debug info?
+                        false,          // Is this symbol a trampoline?
+                        false,          // Is this symbol artificial?
+                        symbol_section, // section pointer if symbol_value is an offset within a section, else NULL
+                        symbol_value,   // offset from section if section is non-NULL, else the value for this symbol
+                        symbol.st_size, // size in bytes of this symbol
+                        symbol.st_other << 8 | symbol.st_info); // symbol flags
+        symtab->AddSymbol(dc_symbol);
+    }
+}
+
+
+Symtab *
+ObjectFileELF::GetSymtab()
+{
+    if (m_symtab_ap.get() == NULL)
+    {
+        m_symtab_ap.reset(new Symtab(this));
+
+        if (ParseSectionHeaders() && GetSectionHeaderStringTable())
+        {
+            uint32_t symtab_idx = UINT32_MAX;
+            uint32_t dynsym_idx = UINT32_MAX;
+            uint32_t sh_idx = 0;
+            const size_t num_sections = m_section_headers.size();
+            for (sh_idx = 0; sh_idx < num_sections; ++sh_idx)
+            {
+                if (m_section_headers[sh_idx].sh_type == SHT_SYMTAB)
+                {
+                    symtab_idx = sh_idx;
+                    break;
+                }
+                if (m_section_headers[sh_idx].sh_type == SHT_DYNSYM)
+                {
+                    dynsym_idx = sh_idx;
+                }
+            }
+
+            SectionList *section_list = NULL;
+            static ConstString g_symtab(".symtab");
+            static ConstString g_strtab(".strtab");
+            static ConstString g_dynsym(".dynsym");
+            static ConstString g_dynstr(".dynstr");
+            // Check if we found a full symbol table?
+            if (symtab_idx < num_sections)
+            {
+                section_list = GetSectionList();
+                if (section_list)
+                {
+                    Section *symtab_section = section_list->FindSectionByName(g_symtab).get();
+                    Section *strtab_section = section_list->FindSectionByName(g_strtab).get();
+                    if (symtab_section && strtab_section)
+                    {
+                        DataExtractor symtab_data;
+                        DataExtractor strtab_data;
+                        if (symtab_section->ReadSectionDataFromObjectFile (this, symtab_data) > 0 &&
+                            strtab_section->ReadSectionDataFromObjectFile (this, strtab_data) > 0)
+                        {
+                            ParseSymbols (m_symtab_ap.get(), section_list, m_section_headers[symtab_idx], symtab_data, strtab_data);
+                        }
+                    }
+                }
+            }
+            // Check if we found a reduced symbol table that gets used for dynamic linking?
+            else if (dynsym_idx < num_sections)
+            {
+                section_list = GetSectionList();
+                if (section_list)
+                {
+                    Section *dynsym_section = section_list->FindSectionByName(g_dynsym).get();
+                    Section *dynstr_section = section_list->FindSectionByName(g_dynstr).get();
+                    if (dynsym_section && dynstr_section)
+                    {
+                        DataExtractor dynsym_data;
+                        DataExtractor dynstr_data;
+                        if (dynsym_section->ReadSectionDataFromObjectFile (this, dynsym_data) > 0 &&
+                            dynstr_section->ReadSectionDataFromObjectFile (this, dynstr_data) > 0)
+                        {
+                            ParseSymbols (m_symtab_ap.get(), section_list, m_section_headers[dynsym_idx], dynsym_data, dynstr_data);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return m_symtab_ap.get();
+}
+
+//
+////----------------------------------------------------------------------
+//// GetNListSymtab
+////----------------------------------------------------------------------
+//bool
+//ELF32RuntimeFileParser::GetNListSymtab(BinaryDataRef& stabs_data, BinaryDataRef& stabstr_data, bool locals_only, uint32_t& value_size)
+//{
+//  value_size = 4; // Size in bytes of the nlist n_value member
+//  return  GetSectionInfo(GetSectionIndexByName(".stab"), NULL, NULL, NULL, NULL, NULL, NULL, &stabs_data, NULL) &&
+//          GetSectionInfo(GetSectionIndexByName(".stabstr"), NULL, NULL, NULL, NULL, NULL, NULL, &stabstr_data, NULL);
+//}
+//
+//===----------------------------------------------------------------------===//
+// Dump
+//
+// Dump the specifics of the runtime file container (such as any headers
+// segments, sections, etc).
+//----------------------------------------------------------------------
+void
+ObjectFileELF::Dump(Stream *s)
+{
+    DumpELFHeader(s, m_header);
+    s->EOL();
+    DumpELFProgramHeaders(s);
+    s->EOL();
+    DumpELFSectionHeaders(s);
+    s->EOL();
+    SectionList *section_list = GetSectionList();
+    if (section_list)
+        section_list->Dump(s, NULL, true);
+    Symtab *symtab = GetSymtab();
+    if (symtab)
+        symtab->Dump(s, NULL);
+    s->EOL();
+}
+
+//----------------------------------------------------------------------
+// DumpELFHeader
+//
+// Dump the ELF header to the specified output stream
+//----------------------------------------------------------------------
+void
+ObjectFileELF::DumpELFHeader(Stream *s, const Elf32_Ehdr& header)
+{
+
+    s->PutCString ("ELF Header\n");
+    s->Printf ("e_ident[EI_MAG0   ] = 0x%2.2x\n", header.e_ident[EI_MAG0]);
+    s->Printf ("e_ident[EI_MAG1   ] = 0x%2.2x '%c'\n", header.e_ident[EI_MAG1], header.e_ident[EI_MAG1]);
+    s->Printf ("e_ident[EI_MAG2   ] = 0x%2.2x '%c'\n", header.e_ident[EI_MAG2], header.e_ident[EI_MAG2]);
+    s->Printf ("e_ident[EI_MAG3   ] = 0x%2.2x '%c'\n", header.e_ident[EI_MAG3], header.e_ident[EI_MAG3]);
+    s->Printf ("e_ident[EI_CLASS  ] = 0x%2.2x\n", header.e_ident[EI_CLASS]);
+    s->Printf ("e_ident[EI_DATA   ] = 0x%2.2x ", header.e_ident[EI_DATA]);
+    DumpELFHeader_e_ident_EI_DATA(s, header.e_ident[EI_DATA]);
+    s->Printf ("\ne_ident[EI_VERSION] = 0x%2.2x\n", header.e_ident[EI_VERSION]);
+    s->Printf ("e_ident[EI_PAD    ] = 0x%2.2x\n", header.e_ident[EI_PAD]);
+
+    s->Printf("e_type      = 0x%4.4x ", header.e_type);
+    DumpELFHeader_e_type(s, header.e_type);
+    s->Printf("\ne_machine   = 0x%4.4x\n", header.e_machine);
+    s->Printf("e_version   = 0x%8.8x\n", header.e_version);
+    s->Printf("e_entry     = 0x%8.8x\n", header.e_entry);
+    s->Printf("e_phoff     = 0x%8.8x\n", header.e_phoff);
+    s->Printf("e_shoff     = 0x%8.8x\n", header.e_shoff);
+    s->Printf("e_flags     = 0x%8.8x\n", header.e_flags);
+    s->Printf("e_ehsize    = 0x%4.4x\n", header.e_ehsize);
+    s->Printf("e_phentsize = 0x%4.4x\n", header.e_phentsize);
+    s->Printf("e_phnum     = 0x%4.4x\n", header.e_phnum);
+    s->Printf("e_shentsize = 0x%4.4x\n", header.e_shentsize);
+    s->Printf("e_shnum     = 0x%4.4x\n", header.e_shnum);
+    s->Printf("e_shstrndx  = 0x%4.4x\n", header.e_shstrndx);
+}
+
+//----------------------------------------------------------------------
+// DumpELFHeader_e_type
+//
+// Dump an token value for the ELF header member e_type
+//----------------------------------------------------------------------
+void
+ObjectFileELF::DumpELFHeader_e_type(Stream *s, uint16_t e_type)
+{
+    switch (e_type)
+    {
+    case ET_NONE:   *s << "ET_NONE"; break;
+    case ET_REL:    *s << "ET_REL"; break;
+    case ET_EXEC:   *s << "ET_EXEC"; break;
+    case ET_DYN:    *s << "ET_DYN"; break;
+    case ET_CORE:   *s << "ET_CORE"; break;
+    default:
+        break;
+    }
+}
+
+//----------------------------------------------------------------------
+// DumpELFHeader_e_ident_EI_DATA
+//
+// Dump an token value for the ELF header member e_ident[EI_DATA]
+//----------------------------------------------------------------------
+void
+ObjectFileELF::DumpELFHeader_e_ident_EI_DATA(Stream *s, uint16_t ei_data)
+{
+    switch (ei_data)
+    {
+    case ELFDATANONE:   *s << "ELFDATANONE"; break;
+    case ELFDATA2LSB:   *s << "ELFDATA2LSB - Little Endian"; break;
+    case ELFDATA2MSB:   *s << "ELFDATA2MSB - Big Endian"; break;
+    default:
+        break;
+    }
+}
+
+
+//----------------------------------------------------------------------
+// DumpELFProgramHeader
+//
+// Dump a single ELF program header to the specified output stream
+//----------------------------------------------------------------------
+void
+ObjectFileELF::DumpELFProgramHeader(Stream *s, const Elf32_Phdr& ph)
+{
+    DumpELFProgramHeader_p_type(s, ph.p_type);
+    s->Printf(" %8.8x %8.8x %8.8x %8.8x %8.8x %8.8x (", ph.p_offset, ph.p_vaddr, ph.p_paddr, ph.p_filesz, ph.p_memsz, ph.p_flags);
+    DumpELFProgramHeader_p_flags(s, ph.p_flags);
+    s->Printf(") %8.8x", ph.p_align);
+}
+
+//----------------------------------------------------------------------
+// DumpELFProgramHeader_p_type
+//
+// Dump an token value for the ELF program header member p_type which
+// describes the type of the program header
+//----------------------------------------------------------------------
+void
+ObjectFileELF::DumpELFProgramHeader_p_type(Stream *s, Elf32_Word p_type)
+{
+    const int kStrWidth = 10;
+    switch (p_type)
+    {
+    CASE_AND_STREAM(s, PT_NULL      , kStrWidth);
+    CASE_AND_STREAM(s, PT_LOAD      , kStrWidth);
+    CASE_AND_STREAM(s, PT_DYNAMIC   , kStrWidth);
+    CASE_AND_STREAM(s, PT_INTERP    , kStrWidth);
+    CASE_AND_STREAM(s, PT_NOTE      , kStrWidth);
+    CASE_AND_STREAM(s, PT_SHLIB     , kStrWidth);
+    CASE_AND_STREAM(s, PT_PHDR      , kStrWidth);
+    default:
+        s->Printf("0x%8.8x%*s", p_type, kStrWidth - 10, "");
+        break;
+    }
+}
+
+
+//----------------------------------------------------------------------
+// DumpELFProgramHeader_p_flags
+//
+// Dump an token value for the ELF program header member p_flags
+//----------------------------------------------------------------------
+void
+ObjectFileELF::DumpELFProgramHeader_p_flags(Stream *s, Elf32_Word p_flags)
+{
+    *s  << ((p_flags & PF_X) ? "PF_X" : "    ")
+        << (((p_flags & PF_X) && (p_flags & PF_W)) ? '+' : ' ')
+        << ((p_flags & PF_W) ? "PF_W" : "    ")
+        << (((p_flags & PF_W) && (p_flags & PF_R)) ? '+' : ' ')
+        << ((p_flags & PF_R) ? "PF_R" : "    ");
+}
+
+//----------------------------------------------------------------------
+// DumpELFProgramHeaders
+//
+// Dump all of the ELF program header to the specified output stream
+//----------------------------------------------------------------------
+void
+ObjectFileELF::DumpELFProgramHeaders(Stream *s)
+{
+    if (ParseProgramHeaders())
+    {
+        s->PutCString("Program Headers\n");
+        s->PutCString("IDX  p_type     p_offset p_vaddr  p_paddr  p_filesz p_memsz  p_flags                   p_align\n");
+        s->PutCString("==== ---------- -------- -------- -------- -------- -------- ------------------------- --------\n");
+
+        uint32_t idx = 0;
+        ProgramHeaderCollConstIter pos;
+
+        for (pos = m_program_headers.begin(); pos != m_program_headers.end(); ++pos, ++idx)
+        {
+            s->Printf ("[%2u] ", idx);
+            ObjectFileELF::DumpELFProgramHeader(s, *pos);
+            s->EOL();
+        }
+    }
+}
+
+
+//----------------------------------------------------------------------
+// DumpELFSectionHeader
+//
+// Dump a single ELF section header to the specified output stream
+//----------------------------------------------------------------------
+void
+ObjectFileELF::DumpELFSectionHeader(Stream *s, const Elf32_Shdr& sh)
+{
+    s->Printf ("%8.8x ", sh.sh_name);
+    DumpELFSectionHeader_sh_type(s, sh.sh_type);
+    s->Printf (" %8.8x (", sh.sh_flags);
+    DumpELFSectionHeader_sh_flags(s, sh.sh_flags);
+    s->Printf (") %8.8x %8.8x %8.8x %8.8x %8.8x %8.8x %8.8x",
+                sh.sh_addr, sh.sh_offset, sh.sh_size, sh.sh_link, sh.sh_info, sh.sh_addralign, sh.sh_entsize);
+}
+
+//----------------------------------------------------------------------
+// DumpELFSectionHeader_sh_type
+//
+// Dump an token value for the ELF section header member sh_type which
+// describes the type of the section
+//----------------------------------------------------------------------
+void
+ObjectFileELF::DumpELFSectionHeader_sh_type(Stream *s, Elf32_Word sh_type)
+{
+    const int kStrWidth = 12;
+    switch (sh_type)
+    {
+    CASE_AND_STREAM(s, SHT_NULL     , kStrWidth);
+    CASE_AND_STREAM(s, SHT_PROGBITS , kStrWidth);
+    CASE_AND_STREAM(s, SHT_SYMTAB   , kStrWidth);
+    CASE_AND_STREAM(s, SHT_STRTAB   , kStrWidth);
+    CASE_AND_STREAM(s, SHT_RELA     , kStrWidth);
+    CASE_AND_STREAM(s, SHT_HASH     , kStrWidth);
+    CASE_AND_STREAM(s, SHT_DYNAMIC  , kStrWidth);
+    CASE_AND_STREAM(s, SHT_NOTE     , kStrWidth);
+    CASE_AND_STREAM(s, SHT_NOBITS   , kStrWidth);
+    CASE_AND_STREAM(s, SHT_REL      , kStrWidth);
+    CASE_AND_STREAM(s, SHT_SHLIB    , kStrWidth);
+    CASE_AND_STREAM(s, SHT_DYNSYM   , kStrWidth);
+    CASE_AND_STREAM(s, SHT_LOPROC   , kStrWidth);
+    CASE_AND_STREAM(s, SHT_HIPROC   , kStrWidth);
+    CASE_AND_STREAM(s, SHT_LOUSER   , kStrWidth);
+    CASE_AND_STREAM(s, SHT_HIUSER   , kStrWidth);
+    default:
+        s->Printf("0x%8.8x%*s", sh_type, kStrWidth - 10, "");
+        break;
+    }
+}
+
+
+//----------------------------------------------------------------------
+// DumpELFSectionHeader_sh_flags
+//
+// Dump an token value for the ELF section header member sh_flags
+//----------------------------------------------------------------------
+void
+ObjectFileELF::DumpELFSectionHeader_sh_flags(Stream *s, Elf32_Word sh_flags)
+{
+    *s  << ((sh_flags & SHF_WRITE) ? "WRITE" : "     ")
+        << (((sh_flags & SHF_WRITE) && (sh_flags & SHF_ALLOC)) ? '+' : ' ')
+        << ((sh_flags & SHF_ALLOC) ? "ALLOC" : "     ")
+        << (((sh_flags & SHF_ALLOC) && (sh_flags & SHF_EXECINSTR)) ? '+' : ' ')
+        << ((sh_flags & SHF_EXECINSTR) ? "EXECINSTR" : "         ");
+}
+//----------------------------------------------------------------------
+// DumpELFSectionHeaders
+//
+// Dump all of the ELF section header to the specified output stream
+//----------------------------------------------------------------------
+void
+ObjectFileELF::DumpELFSectionHeaders(Stream *s)
+{
+    if (ParseSectionHeaders() && GetSectionHeaderStringTable())
+    {
+        s->PutCString("Section Headers\n");
+        s->PutCString("IDX  name     type         flags                            addr     offset   size     link     info     addralgn entsize  Name\n");
+        s->PutCString("==== -------- ------------ -------------------------------- -------- -------- -------- -------- -------- -------- -------- ====================\n");
+
+        uint32_t idx = 0;
+        SectionHeaderCollConstIter pos;
+
+        for (pos = m_section_headers.begin(); pos != m_section_headers.end(); ++pos, ++idx)
+        {
+            s->Printf ("[%2u] ", idx);
+            ObjectFileELF::DumpELFSectionHeader(s, *pos);
+            const char* section_name = m_shstr_data.PeekCStr(pos->sh_name);
+            if (section_name)
+                *s << ' ' << section_name << "\n";
+        }
+    }
+}
+
+static uint32_t
+ELFMachineToMachCPU(Elf32_Half machine)
+{
+    switch (machine)
+    {
+    case EM_SPARC:  return CPU_TYPE_SPARC;
+    case EM_386:    return CPU_TYPE_I386;
+    case EM_68K:    return CPU_TYPE_MC680x0;
+    case EM_88K:    return CPU_TYPE_MC88000;
+    case EM_860:    return CPU_TYPE_I860;
+    case EM_MIPS:   return 8;   // commented out in mach/machine.h
+    case EM_PPC:    return CPU_TYPE_POWERPC;
+    case EM_PPC64:  return CPU_TYPE_POWERPC64;
+    case EM_ARM:    return 12;  // commented out in mach/machine.h
+    }
+    return 0;
+}
+
+bool
+ObjectFileELF::GetTargetTriple (ConstString &target_triple)
+{
+    static ConstString g_target_triple;
+
+    if (g_target_triple)
+    {
+        target_triple = g_target_triple;
+    }
+    else
+    {
+        std::string triple;
+        switch (m_header.e_machine)
+        {
+        case EM_SPARC:  triple.assign("sparc-"); break;
+        case EM_386:    triple.assign("i386-"); break;
+        case EM_68K:    triple.assign("68k-"); break;
+        case EM_88K:    triple.assign("88k-"); break;
+        case EM_860:    triple.assign("i860-"); break;
+        case EM_MIPS:   triple.assign("mips-"); break;
+        case EM_PPC:    triple.assign("powerpc-"); break;
+        case EM_PPC64:  triple.assign("powerpc64-"); break;
+        case EM_ARM:    triple.assign("arm-"); break;
+        }
+        // TODO: determine if there is a vendor in the ELF? Default to "apple" for now
+        triple += "apple-";
+        // TODO: determine if there is an OS in the ELF? Default to "darwin" for now
+        triple += "darwin10";
+        g_target_triple.SetCString(triple.c_str());
+        target_triple = g_target_triple;
+    }
+    return !target_triple.IsEmpty();
+}
+
+
+//bool
+//ELF32RuntimeFileParser::GetArch(ArchSpec &arch) const
+//{
+//  arch.SetCPUType(ELFMachineToMachCPU(m_header.e_machine));
+//  arch.SetCPUSubtype(ArchSpec::eAny);
+//  return true;
+//}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+const char *
+ObjectFileELF::GetPluginName()
+{
+    return "ObjectFileELF";
+}
+
+const char *
+ObjectFileELF::GetShortPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+ObjectFileELF::GetPluginVersion()
+{
+    return 1;
+}
+
+void
+ObjectFileELF::GetPluginCommandHelp (const char *command, Stream *strm)
+{
+}
+
+Error
+ObjectFileELF::ExecutePluginCommand (Args &command, Stream *strm)
+{
+    Error error;
+    error.SetErrorString("No plug-in command are currently supported.");
+    return error;
+}
+
+Log *
+ObjectFileELF::EnablePluginLogging (Stream *strm, Args &command)
+{
+    return NULL;
+}
+
+
+
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
new file mode 100644
index 0000000..5d5778c
--- /dev/null
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -0,0 +1,197 @@
+//===-- ObjectFileELF.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_ObjectFileELF_h_
+#define liblldb_ObjectFileELF_h_
+
+#include <stdint.h>
+#include <vector>
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Symbol/ObjectFile.h"
+
+#include "elf.h"
+
+//----------------------------------------------------------------------
+// This class needs to be hidden as eventually belongs in a plugin that
+// will export the ObjectFile protocol
+//----------------------------------------------------------------------
+class ObjectFileELF :
+    public lldb_private::ObjectFile
+{
+public:
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static const char *
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb_private::ObjectFile *
+    CreateInstance (lldb_private::Module* module,
+                    lldb::DataBufferSP& dataSP,
+                    const lldb_private::FileSpec* file,
+                    lldb::addr_t offset,
+                    lldb::addr_t length);
+    static bool
+    MagicBytesMatch (lldb::DataBufferSP& dataSP);
+
+    //------------------------------------------------------------------
+    // Member Functions
+    //------------------------------------------------------------------
+    ObjectFileELF (lldb_private::Module* module,
+                   lldb::DataBufferSP& dataSP,
+                   const lldb_private::FileSpec* file,
+                   lldb::addr_t offset,
+                   lldb::addr_t length);
+
+    virtual
+    ~ObjectFileELF();
+
+    virtual bool
+    ParseHeader ();
+
+    virtual lldb::ByteOrder
+    GetByteOrder () const;
+
+    virtual size_t
+    GetAddressByteSize ()  const;
+
+    virtual lldb_private::Symtab *
+    GetSymtab();
+
+    virtual lldb_private::SectionList *
+    GetSectionList();
+
+    virtual void
+    Dump (lldb_private::Stream *s);
+
+    virtual bool
+    GetTargetTriple (lldb_private::ConstString &target_triple);
+
+    virtual bool
+    GetUUID (lldb_private::UUID* uuid);
+
+    virtual uint32_t
+    GetDependentModules(lldb_private::FileSpecList& files);
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual const char *
+    GetPluginName();
+
+    virtual const char *
+    GetShortPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+    virtual void
+    GetPluginCommandHelp (const char *command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Error
+    ExecutePluginCommand (lldb_private::Args &command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Log *
+    EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
+
+
+
+protected:
+    typedef std::vector<Elf32_Phdr>             ProgramHeaderColl;
+    typedef ProgramHeaderColl::iterator         ProgramHeaderCollIter;
+    typedef ProgramHeaderColl::const_iterator   ProgramHeaderCollConstIter;
+
+    typedef std::vector<Elf32_Shdr>             SectionHeaderColl;
+    typedef SectionHeaderColl::iterator         SectionHeaderCollIter;
+    typedef SectionHeaderColl::const_iterator   SectionHeaderCollConstIter;
+
+    Elf32_Ehdr m_header;
+    ProgramHeaderColl m_program_headers;
+    SectionHeaderColl m_section_headers;
+    mutable std::auto_ptr<lldb_private::SectionList> m_sections_ap;
+    mutable std::auto_ptr<lldb_private::Symtab> m_symtab_ap;
+    lldb_private::DataExtractor m_shstr_data;
+
+    size_t
+    ParseSections ();
+
+    size_t
+    ParseSymtab (bool minimize);
+
+private:
+
+    // ELF header dump routines
+    static void
+    DumpELFHeader (lldb_private::Stream *s,
+                   const Elf32_Ehdr& header);
+
+    static void
+    DumpELFHeader_e_ident_EI_DATA (lldb_private::Stream *s,
+                                   uint16_t ei_data);
+    static void
+    DumpELFHeader_e_type (lldb_private::Stream *s,
+                          uint16_t e_type);
+
+    // ELF program header dump routines
+    void
+    DumpELFProgramHeaders (lldb_private::Stream *s);
+
+    static void
+    DumpELFProgramHeader (lldb_private::Stream *s,
+                          const Elf32_Phdr& ph);
+
+    static void
+    DumpELFProgramHeader_p_type (lldb_private::Stream *s,
+                                 Elf32_Word p_type);
+
+    static void
+    DumpELFProgramHeader_p_flags (lldb_private::Stream *s,
+                                  Elf32_Word p_flags);
+
+    // ELF section header dump routines
+    void
+    DumpELFSectionHeaders (lldb_private::Stream *s);
+
+    static void
+    DumpELFSectionHeader (lldb_private::Stream *s,
+                          const Elf32_Shdr& sh);
+
+    static void
+    DumpELFSectionHeader_sh_type (lldb_private::Stream *s,
+                                  Elf32_Word sh_type);
+
+    static void
+    DumpELFSectionHeader_sh_flags (lldb_private::Stream *s,
+                                   Elf32_Word sh_flags);
+
+    size_t
+    ParseProgramHeaders ();
+
+    size_t
+    ParseSectionHeaders ();
+
+    size_t
+    GetSectionHeaderStringTable ();
+
+    uint32_t
+    GetSectionIndexByName (const char *name);
+};
+
+#endif // #ifndef liblldb_ObjectFileELF_h_
diff --git a/source/Plugins/ObjectFile/ELF/elf.h b/source/Plugins/ObjectFile/ELF/elf.h
new file mode 100644
index 0000000..9d08119
--- /dev/null
+++ b/source/Plugins/ObjectFile/ELF/elf.h
@@ -0,0 +1,240 @@
+//===-- elf.h ---------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __elf_h__
+#define __elf_h__
+
+typedef uint16_t    Elf32_Half;
+typedef uint32_t    Elf32_Word;
+typedef int32_t     Elf32_Sword;
+typedef uint32_t    Elf32_Addr;
+typedef uint32_t    Elf32_Off;
+
+
+#define EI_NIDENT 16
+
+//----------------------------------------------------------------------
+// ELF Header
+//----------------------------------------------------------------------
+typedef struct Elf32_Ehdr_Tag
+{
+    unsigned char e_ident[EI_NIDENT];
+    Elf32_Half  e_type;
+    Elf32_Half  e_machine;
+    Elf32_Word  e_version;
+    Elf32_Addr  e_entry;
+    Elf32_Off   e_phoff;
+    Elf32_Off   e_shoff;
+    Elf32_Word  e_flags;
+    Elf32_Half  e_ehsize;
+    Elf32_Half  e_phentsize;
+    Elf32_Half  e_phnum;
+    Elf32_Half  e_shentsize;
+    Elf32_Half  e_shnum;
+    Elf32_Half  e_shstrndx;
+} Elf32_Ehdr;
+
+//----------------------------------------------------------------------
+// e_type
+//
+// This member identifies the object file type.
+//----------------------------------------------------------------------
+#define ET_NONE     0       // No file type
+#define ET_REL      1       // Relocatable file
+#define ET_EXEC     2       // Executable file
+#define ET_DYN      3       // Shared object file
+#define ET_CORE     4       // Core file
+#define ET_LOPROC   0xff00  // Processor-specific
+#define ET_HIPROC   0xffff  // Processor-specific
+
+//----------------------------------------------------------------------
+// e_machine
+//
+// Machine Type
+//----------------------------------------------------------------------
+#define EM_NONE     0   // No machine
+#define EM_M32      1   // AT&T WE 32100
+#define EM_SPARC    2   // SPARC
+#define EM_386      3   // Intel 80386
+#define EM_68K      4   // Motorola 68000
+#define EM_88K      5   // Motorola 88000
+#define EM_860      7   // Intel 80860
+#define EM_MIPS     8   // MIPS RS3000
+#define EM_PPC      20  // PowerPC
+#define EM_PPC64    21  // PowerPC64
+#define EM_ARM      40  // ARM
+
+
+//----------------------------------------------------------------------
+// e_ident indexes
+//----------------------------------------------------------------------
+#define EI_MAG0     0   // File identification
+#define EI_MAG1     1   // File identification
+#define EI_MAG2     2   // File identification
+#define EI_MAG3     3   // File identification
+#define EI_CLASS    4   // File class
+#define EI_DATA     5   // Data encoding
+#define EI_VERSION  6   // File version
+#define EI_PAD      7   // Start of padding bytes
+
+
+//----------------------------------------------------------------------
+// EI_DATA definitions
+//----------------------------------------------------------------------
+#define ELFDATANONE 0   // Invalid data encoding
+#define ELFDATA2LSB 1   // Little Endian
+#define ELFDATA2MSB 2   // Big Endian
+
+//----------------------------------------------------------------------
+// Section Header
+//----------------------------------------------------------------------
+typedef struct Elf32_Shdr_Tag
+{
+    Elf32_Word  sh_name;
+    Elf32_Word  sh_type;
+    Elf32_Word  sh_flags;
+    Elf32_Addr  sh_addr;
+    Elf32_Off   sh_offset;
+    Elf32_Word  sh_size;
+    Elf32_Word  sh_link;
+    Elf32_Word  sh_info;
+    Elf32_Word  sh_addralign;
+    Elf32_Word  sh_entsize;
+} Elf32_Shdr;
+
+//----------------------------------------------------------------------
+// Section Types (sh_type)
+//----------------------------------------------------------------------
+#define SHT_NULL        0
+#define SHT_PROGBITS    1
+#define SHT_SYMTAB      2
+#define SHT_STRTAB      3
+#define SHT_RELA        4
+#define SHT_HASH        5
+#define SHT_DYNAMIC     6
+#define SHT_NOTE        7
+#define SHT_NOBITS      8
+#define SHT_REL         9
+#define SHT_SHLIB       10
+#define SHT_DYNSYM      11
+#define SHT_LOPROC      0x70000000
+#define SHT_HIPROC      0x7fffffff
+#define SHT_LOUSER      0x80000000
+#define SHT_HIUSER      0xffffffff
+
+//----------------------------------------------------------------------
+// Special Section Indexes
+//----------------------------------------------------------------------
+#define SHN_UNDEF       0
+#define SHN_LORESERVE   0xff00
+#define SHN_LOPROC      0xff00
+#define SHN_HIPROC      0xff1f
+#define SHN_ABS         0xfff1
+#define SHN_COMMON      0xfff2
+#define SHN_HIRESERVE   0xffff
+
+//----------------------------------------------------------------------
+// Section Attribute Flags (sh_flags)
+//----------------------------------------------------------------------
+#define SHF_WRITE       0x1
+#define SHF_ALLOC       0x2
+#define SHF_EXECINSTR   0x4
+#define SHF_MASKPROC    0xf0000000
+
+
+//----------------------------------------------------------------------
+// Symbol Table Entry Header
+//----------------------------------------------------------------------
+typedef struct Elf32_Sym_Tag
+{
+    Elf32_Word      st_name;
+    Elf32_Addr      st_value;
+    Elf32_Word      st_size;
+    unsigned char   st_info;
+    unsigned char   st_other;
+    Elf32_Half      st_shndx;
+} Elf32_Sym;
+
+
+#define ELF32_ST_BIND(i)    ((i)>>4)
+#define ELF32_ST_TYPE(i)    ((i)&0xf)
+#define ELF32_ST_INFO(b,t)  (((b)<<4)+((t)&0xf))
+
+// ST_BIND
+#define STB_LOCAL   0
+#define STB_GLOBAL  1
+#define STB_WEAK    2
+#define STB_LOPROC  13
+#define STB_HIPROC  15
+
+// ST_TYPE
+#define STT_NOTYPE  0
+#define STT_OBJECT  1
+#define STT_FUNC    2
+#define STT_SECTION 3
+#define STT_FILE    4
+#define STT_LOPROC  13
+#define STT_HIPROC  15
+
+
+//----------------------------------------------------------------------
+// Relocation Entries
+//----------------------------------------------------------------------
+typedef struct Elf32_Rel_Tag
+{
+    Elf32_Addr  r_offset;
+    Elf32_Word  r_info;
+} Elf32_Rel;
+
+typedef struct Elf32_Rela_Tag
+{
+    Elf32_Addr  r_offset;
+    Elf32_Word  r_info;
+    Elf32_Sword r_addend;
+} Elf32_Rela;
+
+#define ELF32_R_SYM(i)      ((i)>>8)
+#define ELF32_R_TYPE(i)     ((unsignedchar)(i))
+#define ELF32_R_INFO(s,t)   (((s)<<8)+(unsignedchar)(t))
+
+
+//----------------------------------------------------------------------
+// Program Headers
+//----------------------------------------------------------------------
+typedef struct Elf32_Phdr_Tag
+{
+    Elf32_Word  p_type;
+    Elf32_Off   p_offset;
+    Elf32_Addr  p_vaddr;
+    Elf32_Addr  p_paddr;
+    Elf32_Word  p_filesz;
+    Elf32_Word  p_memsz;
+    Elf32_Word  p_flags;
+    Elf32_Word  p_align;
+} Elf32_Phdr;
+
+//----------------------------------------------------------------------
+// Program Header Type (p_type)
+//----------------------------------------------------------------------
+#define PT_NULL     0
+#define PT_LOAD     1
+#define PT_DYNAMIC  2
+#define PT_INTERP   3
+#define PT_NOTE     4
+#define PT_SHLIB    5
+#define PT_PHDR     6
+#define PT_LOPROC   0x70000000
+#define PT_HIPROC   0x7fffffff
+
+#define PF_X        (1 << 0)    // executable
+#define PF_W        (1 << 1)    // writable
+#define PF_R        (1 << 2)    // readable
+
+
+#endif // __elf_h__
diff --git a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
new file mode 100644
index 0000000..682a116
--- /dev/null
+++ b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -0,0 +1,1311 @@
+//===-- ObjectFileMachO.cpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ObjectFileMachO.h"
+
+#include <mach-o/nlist.h>
+#include <mach-o/stab.h>
+
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/DataBuffer.h"
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Core/FileSpecList.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Core/UUID.h"
+#include "lldb/Symbol/ObjectFile.h"
+
+#ifndef S_DTRACE_DOF
+// section contains DTrace Object Format
+#define S_DTRACE_DOF 0xf
+#endif
+
+#ifndef S_LAZY_DYLIB_SYMBOL_POINTERS
+// section with only lazy symbol pointers to lazy loaded dylibs
+#define S_LAZY_DYLIB_SYMBOL_POINTERS 0x10
+#endif
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+void
+ObjectFileMachO::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance);
+}
+
+void
+ObjectFileMachO::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+const char *
+ObjectFileMachO::GetPluginNameStatic()
+{
+    return "object-file.mach-o";
+}
+
+const char *
+ObjectFileMachO::GetPluginDescriptionStatic()
+{
+    return "Mach-o object file reader (32 and 64 bit)";
+}
+
+
+ObjectFile *
+ObjectFileMachO::CreateInstance (Module* module, DataBufferSP& dataSP, const FileSpec* file, addr_t offset, addr_t length)
+{
+    if (ObjectFileMachO::MagicBytesMatch(dataSP))
+    {
+        std::auto_ptr<ObjectFile> objfile_ap(new ObjectFileMachO (module, dataSP, file, offset, length));
+        if (objfile_ap.get() && objfile_ap->ParseHeader())
+            return objfile_ap.release();
+    }
+    return NULL;
+}
+
+
+static uint32_t
+MachHeaderSizeFromMagic(uint32_t magic)
+{
+    switch (magic)
+    {
+    case MH_MAGIC:
+    case MH_CIGAM:
+        return sizeof(struct mach_header);
+
+    case MH_MAGIC_64:
+    case MH_CIGAM_64:
+        return sizeof(struct mach_header_64);
+        break;
+
+    default:
+        break;
+    }
+    return 0;
+}
+
+
+bool
+ObjectFileMachO::MagicBytesMatch (DataBufferSP& dataSP)
+{
+    DataExtractor data(dataSP, eByteOrderHost, 4);
+    uint32_t offset = 0;
+    uint32_t magic = data.GetU32(&offset);
+    return MachHeaderSizeFromMagic(magic) != 0;
+}
+
+
+ObjectFileMachO::ObjectFileMachO(Module* module, DataBufferSP& dataSP, const FileSpec* file, addr_t offset, addr_t length) :
+    ObjectFile(module, file, offset, length, dataSP),
+    m_mutex (Mutex::eMutexTypeRecursive),
+    m_header(),
+    m_sections_ap(),
+    m_symtab_ap()
+{
+    ::bzero (&m_header, sizeof(m_header));
+    ::bzero (&m_dysymtab, sizeof(m_dysymtab));
+}
+
+
+ObjectFileMachO::~ObjectFileMachO()
+{
+}
+
+
+bool
+ObjectFileMachO::ParseHeader ()
+{
+    lldb_private::Mutex::Locker locker(m_mutex);
+    bool can_parse = false;
+    uint32_t offset = 0;
+    m_data.SetByteOrder (eByteOrderHost);
+    // Leave magic in the original byte order
+    m_header.magic = m_data.GetU32(&offset);
+    switch (m_header.magic)
+    {
+    case MH_MAGIC:
+        m_data.SetByteOrder (eByteOrderHost);
+        m_data.SetAddressByteSize(4);
+        can_parse = true;
+        break;
+
+    case MH_MAGIC_64:
+        m_data.SetByteOrder (eByteOrderHost);
+        m_data.SetAddressByteSize(8);
+        can_parse = true;
+        break;
+
+    case MH_CIGAM:
+        m_data.SetByteOrder(eByteOrderHost == eByteOrderBig ? eByteOrderLittle : eByteOrderBig);
+        m_data.SetAddressByteSize(4);
+        can_parse = true;
+        break;
+
+    case MH_CIGAM_64:
+        m_data.SetByteOrder(eByteOrderHost == eByteOrderBig ? eByteOrderLittle : eByteOrderBig);
+        m_data.SetAddressByteSize(8);
+        can_parse = true;
+        break;
+
+    default:
+        break;
+    }
+
+    if (can_parse)
+    {
+        m_data.GetU32(&offset, &m_header.cputype, 6);
+
+        ArchSpec mach_arch(m_header.cputype, m_header.cpusubtype);
+        if (mach_arch == m_module->GetArchitecture())
+        {
+            // Read in all only the load command data
+            DataBufferSP data_sp(m_file.ReadFileContents(m_offset, m_header.sizeofcmds + MachHeaderSizeFromMagic(m_header.magic)));
+            m_data.SetData (data_sp);
+            return true;
+        }
+    }
+    else
+    {
+        memset(&m_header, 0, sizeof(struct mach_header));
+    }
+    return false;
+}
+
+
+ByteOrder
+ObjectFileMachO::GetByteOrder () const
+{
+    lldb_private::Mutex::Locker locker(m_mutex);
+    return m_data.GetByteOrder ();
+}
+
+
+size_t
+ObjectFileMachO::GetAddressByteSize () const
+{
+    lldb_private::Mutex::Locker locker(m_mutex);
+    return m_data.GetAddressByteSize ();
+}
+
+
+Symtab *
+ObjectFileMachO::GetSymtab()
+{
+    lldb_private::Mutex::Locker locker(m_mutex);
+    if (m_symtab_ap.get() == NULL)
+    {
+        m_symtab_ap.reset(new Symtab(this));
+        ParseSymtab(false);
+    }
+    return m_symtab_ap.get();
+}
+
+
+SectionList *
+ObjectFileMachO::GetSectionList()
+{
+    lldb_private::Mutex::Locker locker(m_mutex);
+    if (m_sections_ap.get() == NULL)
+    {
+        m_sections_ap.reset(new SectionList());
+        ParseSections();
+    }
+    return m_sections_ap.get();
+}
+
+
+size_t
+ObjectFileMachO::ParseSections ()
+{
+    lldb::user_id_t segID = 0;
+    lldb::user_id_t sectID = 0;
+    struct segment_command_64 load_cmd;
+    uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
+    uint32_t i;
+    //bool dump_sections = false;
+    for (i=0; i<m_header.ncmds; ++i)
+    {
+        const uint32_t load_cmd_offset = offset;
+        if (m_data.GetU32(&offset, &load_cmd, 2) == NULL)
+            break;
+
+        if (load_cmd.cmd == LC_SEGMENT || load_cmd.cmd == LC_SEGMENT_64)
+        {
+            if (m_data.GetU8(&offset, (uint8_t*)load_cmd.segname, 16))
+            {
+                load_cmd.vmaddr = m_data.GetAddress(&offset);
+                load_cmd.vmsize = m_data.GetAddress(&offset);
+                load_cmd.fileoff = m_data.GetAddress(&offset);
+                load_cmd.filesize = m_data.GetAddress(&offset);
+                if (m_data.GetU32(&offset, &load_cmd.maxprot, 4))
+                {
+                    // Keep a list of mach segments around in case we need to
+                    // get at data that isn't stored in the abstracted Sections.
+                    m_mach_segments.push_back (load_cmd);
+
+                    ConstString segment_name (load_cmd.segname, std::min<int>(strlen(load_cmd.segname), sizeof(load_cmd.segname)));
+                    // Use a segment ID of the segment index shifted left by 8 so they
+                    // never conflict with any of the sections.
+                    SectionSP segment_sp;
+                    if (segment_name)
+                    {
+                        segment_sp.reset(new Section (NULL,
+                                                      GetModule(),            // Module to which this section belongs
+                                                      ++segID << 8,           // Section ID is the 1 based segment index shifted right by 8 bits as not to collide with any of the 256 section IDs that are possible
+                                                      segment_name,           // Name of this section
+                                                      eSectionTypeContainer,  // This section is a container of other sections.
+                                                      load_cmd.vmaddr,        // File VM address == addresses as they are found in the object file
+                                                      load_cmd.vmsize,        // VM size in bytes of this section
+                                                      load_cmd.fileoff,       // Offset to the data for this section in the file
+                                                      load_cmd.filesize,      // Size in bytes of this section as found in the the file
+                                                      load_cmd.flags));       // Flags for this section
+
+                        m_sections_ap->AddSection(segment_sp);
+                    }
+
+                    struct section_64 sect64;
+                    ::bzero (&sect64, sizeof(sect64));
+                    // Push a section into our mach sections for the section at
+                    // index zero (NO_SECT)
+                    m_mach_sections.push_back(sect64);
+                    uint32_t segment_sect_idx;
+                    const lldb::user_id_t first_segment_sectID = sectID + 1;
+
+
+                    const uint32_t num_u32s = load_cmd.cmd == LC_SEGMENT ? 7 : 8;
+                    for (segment_sect_idx=0; segment_sect_idx<load_cmd.nsects; ++segment_sect_idx)
+                    {
+                        if (m_data.GetU8(&offset, (uint8_t*)sect64.sectname, sizeof(sect64.sectname)) == NULL)
+                            break;
+                        if (m_data.GetU8(&offset, (uint8_t*)sect64.segname, sizeof(sect64.segname)) == NULL)
+                            break;
+                        sect64.addr = m_data.GetAddress(&offset);
+                        sect64.size = m_data.GetAddress(&offset);
+
+                        if (m_data.GetU32(&offset, &sect64.offset, num_u32s) == NULL)
+                            break;
+
+                        // Keep a list of mach sections around in case we need to
+                        // get at data that isn't stored in the abstracted Sections.
+                        m_mach_sections.push_back (sect64);
+
+                        ConstString section_name (sect64.sectname, std::min<size_t>(strlen(sect64.sectname), sizeof(sect64.sectname)));
+                        if (!segment_name)
+                        {
+                            // We have a segment with no name so we need to conjure up
+                            // segments that correspond to the section's segname if there
+                            // isn't already such a section. If there is such a section,
+                            // we resize the section so that it spans all sections.
+                            // We also mark these sections as fake so address matches don't
+                            // hit if they land in the gaps between the child sections.
+                            segment_name.SetTrimmedCStringWithLength(sect64.segname, sizeof(sect64.segname));
+                            segment_sp = m_sections_ap->FindSectionByName (segment_name);
+                            if (segment_sp.get())
+                            {
+                                Section *segment = segment_sp.get();
+                                // Grow the section size as needed.
+                                const lldb::addr_t sect64_min_addr = sect64.addr;
+                                const lldb::addr_t sect64_max_addr = sect64_min_addr + sect64.size;
+                                const lldb::addr_t curr_seg_byte_size = segment->GetByteSize();
+                                const lldb::addr_t curr_seg_min_addr = segment->GetFileAddress();
+                                const lldb::addr_t curr_seg_max_addr = curr_seg_min_addr + curr_seg_byte_size;
+                                if (sect64_min_addr >= curr_seg_min_addr)
+                                {
+                                    const lldb::addr_t new_seg_byte_size = sect64_max_addr - curr_seg_min_addr;
+                                    // Only grow the section size if needed
+                                    if (new_seg_byte_size > curr_seg_byte_size)
+                                        segment->SetByteSize (new_seg_byte_size);
+                                }
+                                else
+                                {
+                                    // We need to change the base address of the segment and
+                                    // adjust the child section offsets for all existing children.
+                                    const lldb::addr_t slide_amount = sect64_min_addr - curr_seg_min_addr;
+                                    segment->Slide(slide_amount, false);
+                                    segment->GetChildren().Slide (-slide_amount, false);
+                                    segment->SetByteSize (curr_seg_max_addr - sect64_min_addr);
+                                }
+                            }
+                            else
+                            {
+                                // Create a fake section for the section's named segment
+                                segment_sp.reset(new Section(segment_sp.get(),       // Parent section
+                                                             GetModule(),            // Module to which this section belongs
+                                                             ++segID << 8,           // Section ID is the 1 based segment index shifted right by 8 bits as not to collide with any of the 256 section IDs that are possible
+                                                             segment_name,           // Name of this section
+                                                             eSectionTypeContainer,  // This section is a container of other sections.
+                                                             sect64.addr,            // File VM address == addresses as they are found in the object file
+                                                             sect64.size,            // VM size in bytes of this section
+                                                             sect64.offset,          // Offset to the data for this section in the file
+                                                             sect64.offset ? sect64.size : 0,        // Size in bytes of this section as found in the the file
+                                                             load_cmd.flags));       // Flags for this section
+                                segment_sp->SetIsFake(true);
+                                m_sections_ap->AddSection(segment_sp);
+                            }
+                        }
+                        assert (segment_sp.get());
+
+                        uint32_t mach_sect_type = sect64.flags & SECTION_TYPE;
+                        static ConstString g_sect_name_objc_data ("__objc_data");
+                        static ConstString g_sect_name_objc_msgrefs ("__objc_msgrefs");
+                        static ConstString g_sect_name_objc_selrefs ("__objc_selrefs");
+                        static ConstString g_sect_name_objc_classrefs ("__objc_classrefs");
+                        static ConstString g_sect_name_objc_superrefs ("__objc_superrefs");
+                        static ConstString g_sect_name_objc_const ("__objc_const");
+                        static ConstString g_sect_name_objc_classlist ("__objc_classlist");
+                        static ConstString g_sect_name_cfstring ("__cfstring");
+                        SectionType sect_type = eSectionTypeOther;
+
+                        if (section_name == g_sect_name_objc_selrefs)
+                        {
+                            sect_type = eSectionTypeDataCStringPointers;
+                        }
+                        else if (section_name == g_sect_name_objc_msgrefs)
+                        {
+                            sect_type = eSectionTypeDataObjCMessageRefs;
+                        }
+                        else if (section_name == g_sect_name_objc_data ||
+                                 section_name == g_sect_name_objc_classrefs ||
+                                 section_name == g_sect_name_objc_superrefs ||
+                                 section_name == g_sect_name_objc_const ||
+                                 section_name == g_sect_name_objc_classlist)
+                        {
+                            sect_type = eSectionTypeDataPointers;
+                        }
+                        else if (section_name == g_sect_name_cfstring)
+                        {
+                            sect_type = eSectionTypeDataObjCCFStrings;
+                        }
+
+                        if (sect_type == eSectionTypeOther)
+                        {
+                            switch (mach_sect_type)
+                            {
+                            // TODO: categorize sections by other flags for regular sections
+                            case S_REGULAR:
+
+                                sect_type = eSectionTypeOther;
+                                break;
+                            case S_ZEROFILL:                    sect_type = eSectionTypeZeroFill; break;
+                            case S_CSTRING_LITERALS:            sect_type = eSectionTypeDataCString;    break; // section with only literal C strings
+                            case S_4BYTE_LITERALS:              sect_type = eSectionTypeData4;    break; // section with only 4 byte literals
+                            case S_8BYTE_LITERALS:              sect_type = eSectionTypeData8;    break; // section with only 8 byte literals
+                            case S_LITERAL_POINTERS:            sect_type = eSectionTypeDataPointers;  break; // section with only pointers to literals
+                            case S_NON_LAZY_SYMBOL_POINTERS:    sect_type = eSectionTypeDataPointers;  break; // section with only non-lazy symbol pointers
+                            case S_LAZY_SYMBOL_POINTERS:        sect_type = eSectionTypeDataPointers;  break; // section with only lazy symbol pointers
+                            case S_SYMBOL_STUBS:                sect_type = eSectionTypeCode;  break; // section with only symbol stubs, byte size of stub in the reserved2 field
+                            case S_MOD_INIT_FUNC_POINTERS:      sect_type = eSectionTypeDataPointers;    break; // section with only function pointers for initialization
+                            case S_MOD_TERM_FUNC_POINTERS:      sect_type = eSectionTypeDataPointers; break; // section with only function pointers for termination
+                            case S_COALESCED:                   sect_type = eSectionTypeOther; break;
+                            case S_GB_ZEROFILL:                 sect_type = eSectionTypeZeroFill; break;
+                            case S_INTERPOSING:                 sect_type = eSectionTypeCode;  break; // section with only pairs of function pointers for interposing
+                            case S_16BYTE_LITERALS:             sect_type = eSectionTypeData16; break; // section with only 16 byte literals
+                            case S_DTRACE_DOF:                  sect_type = eSectionTypeDebug; break;
+                            case S_LAZY_DYLIB_SYMBOL_POINTERS:  sect_type = eSectionTypeDataPointers;  break;
+                            default: break;
+                            }
+                        }
+
+                        SectionSP section_sp(new Section(segment_sp.get(),
+                                                         GetModule(),
+                                                         ++sectID,
+                                                         section_name,
+                                                         sect_type,
+                                                         sect64.addr - segment_sp->GetFileAddress(),
+                                                         sect64.size,
+                                                         sect64.offset,
+                                                         sect64.offset == 0 ? 0 : sect64.size,
+                                                         sect64.flags));
+                        segment_sp->GetChildren().AddSection(section_sp);
+
+                        if (segment_sp->IsFake())
+                        {
+                            segment_sp.reset();
+                            segment_name.Clear();
+                        }
+                    }
+                    if (m_header.filetype == MH_DSYM)
+                    {
+                        if (first_segment_sectID <= sectID)
+                        {
+                            lldb::user_id_t sect_uid;
+                            for (sect_uid = first_segment_sectID; sect_uid <= sectID; ++sect_uid)
+                            {
+                                SectionSP curr_section_sp(segment_sp->GetChildren().FindSectionByID (sect_uid));
+                                SectionSP next_section_sp;
+                                if (sect_uid + 1 <= sectID)
+                                    next_section_sp = segment_sp->GetChildren().FindSectionByID (sect_uid+1);
+
+                                if (curr_section_sp.get())
+                                {
+                                    if (curr_section_sp->GetByteSize() == 0)
+                                    {
+                                        if (next_section_sp.get() != NULL)
+                                            curr_section_sp->SetByteSize ( next_section_sp->GetFileAddress() - curr_section_sp->GetFileAddress() );
+                                        else
+                                            curr_section_sp->SetByteSize ( load_cmd.vmsize );
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        else if (load_cmd.cmd == LC_DYSYMTAB)
+        {
+            m_dysymtab.cmd = load_cmd.cmd;
+            m_dysymtab.cmdsize = load_cmd.cmdsize;
+            m_data.GetU32 (&offset, &m_dysymtab.ilocalsym, (sizeof(m_dysymtab) / sizeof(uint32_t)) - 2);
+        }
+
+        offset = load_cmd_offset + load_cmd.cmdsize;
+    }
+//    if (dump_sections)
+//    {
+//        StreamFile s(stdout);
+//        m_sections_ap->Dump(&s, true);
+//    }
+    return sectID;  // Return the number of sections we registered with the module
+}
+
+class MachSymtabSectionInfo
+{
+public:
+
+    MachSymtabSectionInfo (SectionList *section_list) :
+        m_section_list (section_list),
+        m_section_infos()
+    {
+        // Get the number of sections down to a depth of 1 to include
+        // all segments and their sections, but no other sections that
+        // may be added for debug map or
+        m_section_infos.resize(section_list->GetNumSections(1));
+    }
+
+
+    Section *
+    GetSection (uint8_t n_sect, addr_t file_addr)
+    {
+        if (n_sect == 0)
+            return NULL;
+        if (n_sect < m_section_infos.size())
+        {
+            if (m_section_infos[n_sect].section == NULL)
+            {
+                Section *section = m_section_list->FindSectionByID (n_sect).get();
+                m_section_infos[n_sect].section = section;
+                assert (section != NULL);
+                m_section_infos[n_sect].vm_range.SetBaseAddress (section->GetFileAddress());
+                m_section_infos[n_sect].vm_range.SetByteSize (section->GetByteSize());
+            }
+            if (m_section_infos[n_sect].vm_range.Contains(file_addr))
+                return m_section_infos[n_sect].section;
+        }
+        return m_section_list->FindSectionContainingFileAddress(file_addr).get();
+    }
+
+protected:
+    struct SectionInfo
+    {
+        SectionInfo () :
+            vm_range(),
+            section (NULL)
+        {
+        }
+
+        VMRange vm_range;
+        Section *section;
+    };
+    SectionList *m_section_list;
+    std::vector<SectionInfo> m_section_infos;
+};
+
+
+
+size_t
+ObjectFileMachO::ParseSymtab (bool minimize)
+{
+    Timer scoped_timer(__PRETTY_FUNCTION__,
+                       "ObjectFileMachO::ParseSymtab () module = %s",
+                       m_file.GetFilename().AsCString(""));
+    struct symtab_command symtab_load_command;
+    uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
+    uint32_t i;
+    for (i=0; i<m_header.ncmds; ++i)
+    {
+        const uint32_t cmd_offset = offset;
+        // Read in the load command and load command size
+        if (m_data.GetU32(&offset, &symtab_load_command, 2) == NULL)
+            break;
+        // Watch for the symbol table load command
+        if (symtab_load_command.cmd == LC_SYMTAB)
+        {
+            // Read in the rest of the symtab load command
+            if (m_data.GetU32(&offset, &symtab_load_command.symoff, 4))
+            {
+                Symtab *symtab = m_symtab_ap.get();
+                SectionList *section_list = GetSectionList();
+                assert(section_list);
+                const size_t addr_size = m_data.GetAddressByteSize();
+                const ByteOrder endian = m_data.GetByteOrder();
+                bool bit_width_32 = addr_size == 4;
+                const size_t nlist_size = bit_width_32 ? sizeof(struct nlist) : sizeof(struct nlist_64);
+
+                DataBufferSP symtab_data_sp(m_file.ReadFileContents(m_offset + symtab_load_command.symoff, symtab_load_command.nsyms * nlist_size));
+                DataBufferSP strtab_data_sp(m_file.ReadFileContents(m_offset + symtab_load_command.stroff, symtab_load_command.strsize));
+
+                const char *strtab_data = (const char *)strtab_data_sp->GetBytes();
+//                DataExtractor symtab_data(symtab_data_sp, endian, addr_size);
+//                DataExtractor strtab_data(strtab_data_sp, endian, addr_size);
+
+                static ConstString g_segment_name_TEXT ("__TEXT");
+                static ConstString g_segment_name_DATA ("__DATA");
+                static ConstString g_segment_name_OBJC ("__OBJC");
+                static ConstString g_section_name_eh_frame ("__eh_frame");
+                SectionSP text_section_sp(section_list->FindSectionByName(g_segment_name_TEXT));
+                SectionSP data_section_sp(section_list->FindSectionByName(g_segment_name_DATA));
+                SectionSP objc_section_sp(section_list->FindSectionByName(g_segment_name_OBJC));
+                SectionSP eh_frame_section_sp;
+                if (text_section_sp.get())
+                    eh_frame_section_sp = text_section_sp->GetChildren().FindSectionByName (g_section_name_eh_frame);
+                else
+                    eh_frame_section_sp = section_list->FindSectionByName (g_section_name_eh_frame);
+
+                uint8_t TEXT_eh_frame_sectID = eh_frame_section_sp.get() ? eh_frame_section_sp->GetID() : NO_SECT;
+                //uint32_t symtab_offset = 0;
+                const uint8_t* nlist_data = symtab_data_sp->GetBytes();
+                assert (symtab_data_sp->GetByteSize()/nlist_size >= symtab_load_command.nsyms);
+
+
+                if (endian != eByteOrderHost)
+                {
+                    // ...
+                    assert (!"UNIMPLEMENTED: Swap all nlist entries");
+                }
+                uint32_t N_SO_index = UINT_MAX;
+
+                MachSymtabSectionInfo section_info (section_list);
+                std::vector<uint32_t> N_FUN_indexes;
+                std::vector<uint32_t> N_NSYM_indexes;
+                std::vector<uint32_t> N_INCL_indexes;
+                std::vector<uint32_t> N_BRAC_indexes;
+                std::vector<uint32_t> N_COMM_indexes;
+                uint32_t nlist_idx = 0;
+                Symbol *symbol_ptr = NULL;
+
+                uint32_t sym_idx = 0;
+                Symbol *sym = symtab->Resize (symtab_load_command.nsyms + m_dysymtab.nindirectsyms);
+                uint32_t num_syms = symtab->GetNumSymbols();
+
+                //symtab->Reserve (symtab_load_command.nsyms + m_dysymtab.nindirectsyms);
+                for (nlist_idx = 0; nlist_idx < symtab_load_command.nsyms; ++nlist_idx)
+                {
+                    struct nlist_64 nlist;
+                    if (bit_width_32)
+                    {
+                        struct nlist* nlist32_ptr = (struct nlist*)(nlist_data + (nlist_idx * nlist_size));
+                        nlist.n_un.n_strx = nlist32_ptr->n_un.n_strx;
+                        nlist.n_type = nlist32_ptr->n_type;
+                        nlist.n_sect = nlist32_ptr->n_sect;
+                        nlist.n_desc = nlist32_ptr->n_desc;
+                        nlist.n_value = nlist32_ptr->n_value;
+                    }
+                    else
+                    {
+                        nlist = *((struct nlist_64*)(nlist_data + (nlist_idx * nlist_size)));
+                    }
+
+                    SymbolType type = eSymbolTypeInvalid;
+                    const char* symbol_name = &strtab_data[nlist.n_un.n_strx];
+                    if (symbol_name[0] == '\0')
+                        symbol_name = NULL;
+                    Section* symbol_section = NULL;
+                    bool add_nlist = true;
+                    bool is_debug = ((nlist.n_type & N_STAB) != 0);
+
+                    assert (sym_idx < num_syms);
+
+                    sym[sym_idx].SetDebug (is_debug);
+
+                    if (is_debug)
+                    {
+                        switch (nlist.n_type)
+                        {
+                        case N_GSYM:    // global symbol: name,,NO_SECT,type,0
+                            // Sometimes the N_GSYM value contains the address.
+                            if (nlist.n_value != 0)
+                                symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
+                            type = eSymbolTypeGlobal;
+                            break;
+
+                        case N_FNAME:   // procedure name (f77 kludge): name,,NO_SECT,0,0
+                            type = eSymbolTypeFunction;
+                            break;
+
+                        case N_FUN:                                         // procedure: name,,n_sect,linenumber,address
+                            if (symbol_name)
+                            {
+                                type = eSymbolTypeFunction;
+                                symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
+                                // We use the current number of symbols in the symbol table in lieu of
+                                // using nlist_idx in case we ever start trimming entries out
+                                N_FUN_indexes.push_back(sym_idx);
+                            }
+                            else
+                            {
+                                type = eSymbolTypeFunctionEnd;
+
+                                if ( !N_FUN_indexes.empty() )
+                                {
+                                    // Copy the size of the function into the original STAB entry so we don't have
+                                    // to hunt for it later
+                                    symtab->SymbolAtIndex(N_FUN_indexes.back())->SetByteSize(nlist.n_value);
+                                    N_FUN_indexes.pop_back();
+                                    // We dont' really need the end function STAB as it contains the size which
+                                    // we already placed with the original symbol, so don't add it if we want a
+                                    // minimal symbol table
+                                    if (minimize)
+                                        add_nlist = false;
+                                }
+                            }
+                            break;
+
+                        case N_STSYM:   // static symbol: name,,n_sect,type,address
+                            symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
+                            type = eSymbolTypeStatic;
+                            break;
+
+                        case N_LCSYM:   // .lcomm symbol: name,,n_sect,type,address
+                            symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
+                            type = eSymbolTypeCommonBlock;
+                            break;
+
+                        case N_BNSYM:
+                            // We use the current number of symbols in the symbol table in lieu of
+                            // using nlist_idx in case we ever start trimming entries out
+                            if (minimize)
+                            {
+                                // Skip these if we want minimal symbol tables
+                                add_nlist = false;
+                            }
+                            else
+                            {
+                                symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
+                                N_NSYM_indexes.push_back(sym_idx);
+                                type = eSymbolTypeScopeBegin;
+                            }
+                            break;
+
+                        case N_ENSYM:
+                            // Set the size of the N_BNSYM to the terminating index of this N_ENSYM
+                            // so that we can always skip the entire symbol if we need to navigate
+                            // more quickly at the source level when parsing STABS
+                            if (minimize)
+                            {
+                                // Skip these if we want minimal symbol tables
+                                add_nlist = false;
+                            }
+                            else
+                            {
+                                if ( !N_NSYM_indexes.empty() )
+                                {
+                                    symbol_ptr = symtab->SymbolAtIndex(N_NSYM_indexes.back());
+                                    symbol_ptr->SetByteSize(sym_idx + 1);
+                                    symbol_ptr->SetSizeIsSibling(true);
+                                    N_NSYM_indexes.pop_back();
+                                }
+                                type = eSymbolTypeScopeEnd;
+                            }
+                            break;
+
+
+                        case N_OPT:     // emitted with gcc2_compiled and in gcc source
+                            type = eSymbolTypeCompiler;
+                            break;
+
+                        case N_RSYM:    // register sym: name,,NO_SECT,type,register
+                            type = eSymbolTypeVariable;
+                            break;
+
+                        case N_SLINE:   // src line: 0,,n_sect,linenumber,address
+                            symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
+                            type = eSymbolTypeLineEntry;
+                            break;
+
+                        case N_SSYM:    // structure elt: name,,NO_SECT,type,struct_offset
+                            type = eSymbolTypeVariableType;
+                            break;
+
+                        case N_SO:
+                            type = eSymbolTypeSourceFile;
+                            if (symbol_name == NULL)
+                            {
+                                if (N_SO_index == UINT_MAX)
+                                {
+                                    // Skip the extra blank N_SO entries that happen when the entire
+                                    // path is contained in the second consecutive N_SO STAB.
+                                    if (minimize)
+                                        add_nlist = false;
+                                }
+                                else
+                                {
+                                    // Set the size of the N_SO to the terminating index of this N_SO
+                                    // so that we can always skip the entire N_SO if we need to navigate
+                                    // more quickly at the source level when parsing STABS
+                                    symbol_ptr = symtab->SymbolAtIndex(N_SO_index);
+                                    symbol_ptr->SetByteSize(sym_idx + 1);
+                                    symbol_ptr->SetSizeIsSibling(true);
+                                }
+                                N_NSYM_indexes.clear();
+                                N_INCL_indexes.clear();
+                                N_BRAC_indexes.clear();
+                                N_COMM_indexes.clear();
+                                N_FUN_indexes.clear();
+                                N_SO_index = UINT_MAX;
+                            }
+                            else if (symbol_name[0] == '/')
+                            {
+                                // We use the current number of symbols in the symbol table in lieu of
+                                // using nlist_idx in case we ever start trimming entries out
+                                N_SO_index = sym_idx;
+                            }
+                            break;
+
+                        case N_OSO:     // object file name: name,,0,0,st_mtime
+                            type = eSymbolTypeObjectFile;
+                            break;
+
+                        case N_LSYM:    // local sym: name,,NO_SECT,type,offset
+                            type = eSymbolTypeLocal;
+                            break;
+
+                        //----------------------------------------------------------------------
+                        // INCL scopes
+                        //----------------------------------------------------------------------
+                        case N_BINCL:   // include file beginning: name,,NO_SECT,0,sum
+                            // We use the current number of symbols in the symbol table in lieu of
+                            // using nlist_idx in case we ever start trimming entries out
+                            N_INCL_indexes.push_back(sym_idx);
+                            type = eSymbolTypeScopeBegin;
+                            break;
+                        case N_EINCL:   // include file end: name,,NO_SECT,0,0
+
+                            // Set the size of the N_BINCL to the terminating index of this N_EINCL
+                            // so that we can always skip the entire symbol if we need to navigate
+                            // more quickly at the source level when parsing STABS
+                            if ( !N_INCL_indexes.empty() )
+                            {
+                                symbol_ptr = symtab->SymbolAtIndex(N_INCL_indexes.back());
+                                symbol_ptr->SetByteSize(sym_idx + 1);
+                                symbol_ptr->SetSizeIsSibling(true);
+                                N_INCL_indexes.pop_back();
+                            }
+                            type = eSymbolTypeScopeEnd;
+                            break;
+
+                        case N_SOL:     // #included file name: name,,n_sect,0,address
+                            type = eSymbolTypeHeaderFile;
+                            break;
+
+                        case N_PARAMS:  // compiler parameters: name,,NO_SECT,0,0
+                            type = eSymbolTypeCompiler;
+                            break;
+
+                        case N_VERSION: // compiler version: name,,NO_SECT,0,0
+                            type = eSymbolTypeCompiler;
+                            break;
+
+                        case N_OLEVEL:  // compiler -O level: name,,NO_SECT,0,0
+                            type = eSymbolTypeCompiler;
+                            break;
+
+                        case N_PSYM:    // parameter: name,,NO_SECT,type,offset
+                            type = eSymbolTypeVariable;
+                            break;
+
+                        case N_ENTRY:   // alternate entry: name,,n_sect,linenumber,address
+                            symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
+                            type = eSymbolTypeLineEntry;
+                            break;
+
+                        //----------------------------------------------------------------------
+                        // Left and Right Braces
+                        //----------------------------------------------------------------------
+                        case N_LBRAC:   // left bracket: 0,,NO_SECT,nesting level,address
+                            // We use the current number of symbols in the symbol table in lieu of
+                            // using nlist_idx in case we ever start trimming entries out
+                            symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
+                            N_BRAC_indexes.push_back(sym_idx);
+                            type = eSymbolTypeScopeBegin;
+                            break;
+
+                        case N_RBRAC:   // right bracket: 0,,NO_SECT,nesting level,address
+                            // Set the size of the N_LBRAC to the terminating index of this N_RBRAC
+                            // so that we can always skip the entire symbol if we need to navigate
+                            // more quickly at the source level when parsing STABS
+                            symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
+                            if ( !N_BRAC_indexes.empty() )
+                            {
+                                symbol_ptr = symtab->SymbolAtIndex(N_BRAC_indexes.back());
+                                symbol_ptr->SetByteSize(sym_idx + 1);
+                                symbol_ptr->SetSizeIsSibling(true);
+                                N_BRAC_indexes.pop_back();
+                            }
+                            type = eSymbolTypeScopeEnd;
+                            break;
+
+                        case N_EXCL:    // deleted include file: name,,NO_SECT,0,sum
+                            type = eSymbolTypeHeaderFile;
+                            break;
+
+                        //----------------------------------------------------------------------
+                        // COMM scopes
+                        //----------------------------------------------------------------------
+                        case N_BCOMM:   // begin common: name,,NO_SECT,0,0
+                            // We use the current number of symbols in the symbol table in lieu of
+                            // using nlist_idx in case we ever start trimming entries out
+                            type = eSymbolTypeScopeBegin;
+                            N_COMM_indexes.push_back(sym_idx);
+                            break;
+
+                        case N_ECOML:   // end common (local name): 0,,n_sect,0,address
+                            symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
+                            // Fall through
+
+                        case N_ECOMM:   // end common: name,,n_sect,0,0
+                            // Set the size of the N_BCOMM to the terminating index of this N_ECOMM/N_ECOML
+                            // so that we can always skip the entire symbol if we need to navigate
+                            // more quickly at the source level when parsing STABS
+                            if ( !N_COMM_indexes.empty() )
+                            {
+                                symbol_ptr = symtab->SymbolAtIndex(N_COMM_indexes.back());
+                                symbol_ptr->SetByteSize(sym_idx + 1);
+                                symbol_ptr->SetSizeIsSibling(true);
+                                N_COMM_indexes.pop_back();
+                            }
+                            type = eSymbolTypeScopeEnd;
+                            break;
+
+                        case N_LENG:    // second stab entry with length information
+                            type = eSymbolTypeAdditional;
+                            break;
+
+                        default: break;
+                        }
+                    }
+                    else
+                    {
+                        //uint8_t n_pext    = N_PEXT & nlist.n_type;
+                        uint8_t n_type  = N_TYPE & nlist.n_type;
+                        sym[sym_idx].SetExternal((N_EXT & nlist.n_type) != 0);
+
+                        if (symbol_name && ::strstr (symbol_name, ".objc") == symbol_name)
+                        {
+                            type = eSymbolTypeRuntime;
+                        }
+                        else
+                        {
+                            switch (n_type)
+                            {
+                            case N_INDR:    // Fall through
+                            case N_PBUD:    // Fall through
+                            case N_UNDF:
+                                type = eSymbolTypeExtern;
+                                break;
+
+                            case N_ABS:
+                                type = eSymbolTypeAbsolute;
+                                break;
+
+                            case N_SECT:
+                                symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
+
+                                assert(symbol_section != NULL);
+                                if (TEXT_eh_frame_sectID == nlist.n_sect)
+                                {
+                                    type = eSymbolTypeException;
+                                }
+                                else
+                                {
+                                    uint32_t section_type = symbol_section->GetAllFlagBits() & SECTION_TYPE;
+
+                                    switch (section_type)
+                                    {
+                                    case S_REGULAR:                     break; // regular section
+                                    //case S_ZEROFILL:                  type = eSymbolTypeData;    break; // zero fill on demand section
+                                    case S_CSTRING_LITERALS:            type = eSymbolTypeData;    break; // section with only literal C strings
+                                    case S_4BYTE_LITERALS:              type = eSymbolTypeData;    break; // section with only 4 byte literals
+                                    case S_8BYTE_LITERALS:              type = eSymbolTypeData;    break; // section with only 8 byte literals
+                                    case S_LITERAL_POINTERS:            type = eSymbolTypeTrampoline; break; // section with only pointers to literals
+                                    case S_NON_LAZY_SYMBOL_POINTERS:    type = eSymbolTypeTrampoline; break; // section with only non-lazy symbol pointers
+                                    case S_LAZY_SYMBOL_POINTERS:        type = eSymbolTypeTrampoline; break; // section with only lazy symbol pointers
+                                    case S_SYMBOL_STUBS:                type = eSymbolTypeTrampoline; break; // section with only symbol stubs, byte size of stub in the reserved2 field
+                                    case S_MOD_INIT_FUNC_POINTERS:      type = eSymbolTypeCode;    break; // section with only function pointers for initialization
+                                    case S_MOD_TERM_FUNC_POINTERS:      type = eSymbolTypeCode;    break; // section with only function pointers for termination
+                                    //case S_COALESCED:                 type = eSymbolType;    break; // section contains symbols that are to be coalesced
+                                    //case S_GB_ZEROFILL:               type = eSymbolTypeData;    break; // zero fill on demand section (that can be larger than 4 gigabytes)
+                                    case S_INTERPOSING:                 type = eSymbolTypeTrampoline;  break; // section with only pairs of function pointers for interposing
+                                    case S_16BYTE_LITERALS:             type = eSymbolTypeData;    break; // section with only 16 byte literals
+                                    case S_DTRACE_DOF:                  type = eSymbolTypeInstrumentation; break;
+                                    case S_LAZY_DYLIB_SYMBOL_POINTERS:  type = eSymbolTypeTrampoline; break;
+                                    default: break;
+                                    }
+
+                                    if (type == eSymbolTypeInvalid)
+                                    {
+                                        const char *symbol_sect_name = symbol_section->GetName().AsCString();
+                                        if (symbol_section->IsDescendant (text_section_sp.get()))
+                                        {
+                                            if (symbol_section->IsClear(S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SELF_MODIFYING_CODE | S_ATTR_SOME_INSTRUCTIONS))
+                                                type = eSymbolTypeData;
+                                            else
+                                                type = eSymbolTypeCode;
+                                        }
+                                        else
+                                        if (symbol_section->IsDescendant(data_section_sp.get()))
+                                        {
+                                            if (symbol_sect_name && ::strstr (symbol_sect_name, "__objc") == symbol_sect_name)
+                                            {
+                                                type = eSymbolTypeRuntime;
+                                            }
+                                            else
+                                            if (symbol_sect_name && ::strstr (symbol_sect_name, "__gcc_except_tab") == symbol_sect_name)
+                                            {
+                                                type = eSymbolTypeException;
+                                            }
+                                            else
+                                            {
+                                                type = eSymbolTypeData;
+                                            }
+                                        }
+                                        else
+                                        if (symbol_sect_name && ::strstr (symbol_sect_name, "__IMPORT") == symbol_sect_name)
+                                        {
+                                            type = eSymbolTypeTrampoline;
+                                        }
+                                        else
+                                        if (symbol_section->IsDescendant(objc_section_sp.get()))
+                                        {
+                                            type = eSymbolTypeRuntime;
+                                        }
+                                    }
+                                }
+                                break;
+                            }
+                        }
+                    }
+
+                    if (add_nlist)
+                    {
+                        bool symbol_name_is_mangled = false;
+                        if (symbol_name && symbol_name[0] == '_')
+                        {
+                            symbol_name_is_mangled = symbol_name[1] == '_';
+                            symbol_name++;  // Skip the leading underscore
+                        }
+                        uint64_t symbol_value = nlist.n_value;
+                        if (symbol_section != NULL)
+                            symbol_value -= symbol_section->GetFileAddress();
+
+                        sym[sym_idx].SetID (nlist_idx);
+                        sym[sym_idx].SetType (type);
+                        if (symbol_name)
+                            sym[sym_idx].GetMangled().SetValue(symbol_name, symbol_name_is_mangled);
+                        sym[sym_idx].GetAddressRangeRef().GetBaseAddress().SetSection (symbol_section);
+                        sym[sym_idx].GetAddressRangeRef().GetBaseAddress().SetOffset (symbol_value);
+                        sym[sym_idx].SetFlags (nlist.n_type << 16 | nlist.n_desc);
+
+                        ++sym_idx;
+                    }
+                    else
+                    {
+                        sym[sym_idx].Clear();
+                    }
+
+                }
+
+
+                // STAB N_GSYM entries end up having a symbol type eSymbolTypeGlobal and when the symbol value
+                // is zero, the address of the global ends up being in a non-STAB entry. Try and fix up all
+                // such entries by figuring out what the address for the global is by looking up this non-STAB
+                // entry and copying the value into the debug symbol's value to save us the hassle in the
+                // debug symbol parser.
+
+                Symbol *global_symbol = NULL;
+                for (nlist_idx = 0;
+                     nlist_idx < symtab_load_command.nsyms && (global_symbol = symtab->FindSymbolWithType(eSymbolTypeGlobal, nlist_idx)) != NULL;
+                     nlist_idx++)
+                {
+                    if (global_symbol->GetValue().GetFileAddress() == 0)
+                    {
+                        std::vector<uint32_t> indexes;
+                        if (symtab->AppendSymbolIndexesWithName(global_symbol->GetMangled().GetName(), indexes) > 0)
+                        {
+                            std::vector<uint32_t>::const_iterator pos;
+                            std::vector<uint32_t>::const_iterator end = indexes.end();
+                            for (pos = indexes.begin(); pos != end; ++pos)
+                            {
+                                symbol_ptr = symtab->SymbolAtIndex(*pos);
+                                if (symbol_ptr != global_symbol && symbol_ptr->IsDebug() == false)
+                                {
+                                    global_symbol->SetValue(symbol_ptr->GetValue());
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+                // Now synthesize indirect symbols
+                if (m_dysymtab.nindirectsyms != 0)
+                {
+                    DataBufferSP indirect_symbol_indexes_sp(m_file.ReadFileContents(m_offset + m_dysymtab.indirectsymoff, m_dysymtab.nindirectsyms * 4));
+
+                    if (indirect_symbol_indexes_sp && indirect_symbol_indexes_sp->GetByteSize())
+                    {
+                        DataExtractor indirect_symbol_index_data (indirect_symbol_indexes_sp, m_data.GetByteOrder(), m_data.GetAddressByteSize());
+
+                        for (uint32_t sect_idx = 1; sect_idx < m_mach_sections.size(); ++sect_idx)
+                        {
+                            if ((m_mach_sections[sect_idx].flags & SECTION_TYPE) == S_SYMBOL_STUBS)
+                            {
+                                uint32_t symbol_stub_byte_size = m_mach_sections[sect_idx].reserved2;
+                                if (symbol_stub_byte_size == 0)
+                                    continue;
+
+                                const uint32_t num_symbol_stubs = m_mach_sections[sect_idx].size / symbol_stub_byte_size;
+
+                                if (num_symbol_stubs == 0)
+                                    continue;
+
+                                const uint32_t symbol_stub_index_offset = m_mach_sections[sect_idx].reserved1;
+                                uint32_t stub_sym_id = symtab_load_command.nsyms;
+                                for (uint32_t stub_idx = 0; stub_idx < num_symbol_stubs; ++stub_idx)
+                                {
+                                    const uint32_t symbol_stub_index = symbol_stub_index_offset + stub_idx;
+                                    const lldb::addr_t symbol_stub_addr = m_mach_sections[sect_idx].addr + (stub_idx * symbol_stub_byte_size);
+                                    uint32_t symbol_stub_offset = symbol_stub_index * 4;
+                                    if (indirect_symbol_index_data.ValidOffsetForDataOfSize(symbol_stub_offset, 4))
+                                    {
+                                        const uint32_t symbol_index = indirect_symbol_index_data.GetU32 (&symbol_stub_offset);
+
+                                        Symbol *stub_symbol = symtab->SymbolAtIndex(symbol_index);
+                                        if (stub_symbol)
+                                        {
+                                            Address so_addr(symbol_stub_addr, section_list);
+
+                                            if (stub_symbol->GetType() == eSymbolTypeExtern)
+                                            {
+                                                // Change the external symbol into a trampoline that makes sense
+                                                // These symbols were N_UNDF N_EXT, and are useless to us, so we
+                                                // can re-use them so we don't have to make up a synthetic symbol
+                                                // for no good reason.
+                                                stub_symbol->SetType (eSymbolTypeTrampoline);
+                                                stub_symbol->SetExternal (false);
+                                                stub_symbol->GetAddressRangeRef().GetBaseAddress() = so_addr;
+                                                stub_symbol->GetAddressRangeRef().SetByteSize (symbol_stub_byte_size);
+                                            }
+                                            else
+                                            {
+                                                // Make a synthetic symbol to describe the trampoline stub
+                                                if (sym_idx >= num_syms)
+                                                {
+                                                    sym = symtab->Resize (num_syms + 16);
+                                                    num_syms = symtab->GetNumSymbols();
+                                                }
+                                                sym[sym_idx].SetID (stub_sym_id++);
+                                                sym[sym_idx].GetMangled() = stub_symbol->GetMangled();
+                                                sym[sym_idx].SetType (eSymbolTypeTrampoline);
+                                                sym[sym_idx].SetIsSynthetic (true);
+                                                sym[sym_idx].GetAddressRangeRef().GetBaseAddress() = so_addr;
+                                                sym[sym_idx].GetAddressRangeRef().SetByteSize (symbol_stub_byte_size);
+                                                ++sym_idx;
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+
+                if (sym_idx != symtab->GetNumSymbols())
+                    symtab->Resize (sym_idx);
+
+                return symtab->GetNumSymbols();
+            }
+        }
+        offset = cmd_offset + symtab_load_command.cmdsize;
+    }
+    return 0;
+}
+
+
+void
+ObjectFileMachO::Dump (Stream *s)
+{
+    lldb_private::Mutex::Locker locker(m_mutex);
+    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+    s->Indent();
+    if (m_header.magic == MH_MAGIC_64 || m_header.magic == MH_CIGAM_64)
+        s->PutCString("ObjectFileMachO64");
+    else
+        s->PutCString("ObjectFileMachO32");
+
+    ArchSpec header_arch(m_header.cputype, m_header.cpusubtype);
+
+    *s << ", file = '" << m_file << "', arch = " << header_arch.AsCString() << "\n";
+
+    if (m_sections_ap.get())
+        m_sections_ap->Dump(s, NULL, true);
+
+    if (m_symtab_ap.get())
+        m_symtab_ap->Dump(s, NULL);
+}
+
+
+bool
+ObjectFileMachO::GetUUID (UUID* uuid)
+{
+    lldb_private::Mutex::Locker locker(m_mutex);
+    struct uuid_command load_cmd;
+    uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
+    uint32_t i;
+    for (i=0; i<m_header.ncmds; ++i)
+    {
+        const uint32_t cmd_offset = offset;
+        if (m_data.GetU32(&offset, &load_cmd, 2) == NULL)
+            break;
+
+        if (load_cmd.cmd == LC_UUID)
+        {
+            const uint8_t *uuid_bytes = m_data.PeekData(offset, 16);
+            if (uuid_bytes)
+            {
+                uuid->SetBytes (uuid_bytes);
+                return true;
+            }
+            return false;
+        }
+        offset = cmd_offset + load_cmd.cmdsize;
+    }
+    return false;
+}
+
+
+uint32_t
+ObjectFileMachO::GetDependentModules (FileSpecList& files)
+{
+    lldb_private::Mutex::Locker locker(m_mutex);
+    struct load_command load_cmd;
+    uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
+    uint32_t count = 0;
+    uint32_t i;
+    for (i=0; i<m_header.ncmds; ++i)
+    {
+        const uint32_t cmd_offset = offset;
+        if (m_data.GetU32(&offset, &load_cmd, 2) == NULL)
+            break;
+
+        switch (load_cmd.cmd)
+        {
+        case LC_LOAD_DYLIB:
+        case LC_LOAD_WEAK_DYLIB:
+        case LC_REEXPORT_DYLIB:
+        case LC_LOAD_DYLINKER:
+        case LC_LOADFVMLIB:
+            {
+                uint32_t name_offset = cmd_offset + m_data.GetU32(&offset);
+                const char *path = m_data.PeekCStr(name_offset);
+                // Skip any path that starts with '@' since these are usually:
+                // @executable_path/.../file
+                // @rpath/.../file
+                if (path && path[0] != '@')
+                {
+                    FileSpec file_spec(path);
+                    if (files.AppendIfUnique(file_spec))
+                        count++;
+                }
+            }
+            break;
+
+        default:
+            break;
+        }
+        offset = cmd_offset + load_cmd.cmdsize;
+    }
+    return count;
+}
+
+bool
+ObjectFileMachO::GetTargetTriple (ConstString &target_triple)
+{
+    lldb_private::Mutex::Locker locker(m_mutex);
+    std::string triple(GetModule()->GetArchitecture().AsCString());
+    triple += "-apple-darwin";
+    target_triple.SetCString(triple.c_str());
+    if (target_triple)
+        return true;
+    return false;
+}
+
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+const char *
+ObjectFileMachO::GetPluginName()
+{
+    return "ObjectFileMachO";
+}
+
+const char *
+ObjectFileMachO::GetShortPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+ObjectFileMachO::GetPluginVersion()
+{
+    return 1;
+}
+
+void
+ObjectFileMachO::GetPluginCommandHelp (const char *command, Stream *strm)
+{
+}
+
+Error
+ObjectFileMachO::ExecutePluginCommand (Args &command, Stream *strm)
+{
+    Error error;
+    error.SetErrorString("No plug-in command are currently supported.");
+    return error;
+}
+
+Log *
+ObjectFileMachO::EnablePluginLogging (Stream *strm, Args &command)
+{
+    return NULL;
+}
+
+
+
+
diff --git a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
new file mode 100644
index 0000000..3ffeb24
--- /dev/null
+++ b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
@@ -0,0 +1,131 @@
+//===-- ObjectFileMachO.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_ObjectFileMachO_h_
+#define liblldb_ObjectFileMachO_h_
+
+#include <mach-o/loader.h>
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Symbol/ObjectFile.h"
+
+//----------------------------------------------------------------------
+// This class needs to be hidden as eventually belongs in a plugin that
+// will export the ObjectFile protocol
+//----------------------------------------------------------------------
+class ObjectFileMachO :
+    public lldb_private::ObjectFile
+{
+public:
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static const char *
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static ObjectFile *
+    CreateInstance (lldb_private::Module* module,
+                    lldb::DataBufferSP& dataSP,
+                    const lldb_private::FileSpec* file,
+                    lldb::addr_t offset,
+                    lldb::addr_t length);
+
+    static bool
+    MagicBytesMatch (lldb::DataBufferSP& dataSP);
+
+    //------------------------------------------------------------------
+    // Member Functions
+    //------------------------------------------------------------------
+    ObjectFileMachO (lldb_private::Module* module,
+                     lldb::DataBufferSP& dataSP,
+                     const lldb_private::FileSpec* file,
+                     lldb::addr_t offset,
+                     lldb::addr_t length);
+
+    virtual
+    ~ObjectFileMachO();
+
+    virtual bool
+    ParseHeader ();
+
+    virtual lldb::ByteOrder
+    GetByteOrder () const;
+
+    virtual size_t
+    GetAddressByteSize ()  const;
+
+    virtual lldb_private::Symtab *
+    GetSymtab();
+
+    virtual lldb_private::SectionList *
+    GetSectionList();
+
+    virtual void
+    Dump (lldb_private::Stream *s);
+
+    virtual bool
+    GetTargetTriple (lldb_private::ConstString &target_triple);
+
+    virtual bool
+    GetUUID (lldb_private::UUID* uuid);
+
+    virtual uint32_t
+    GetDependentModules (lldb_private::FileSpecList& files);
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual const char *
+    GetPluginName();
+
+    virtual const char *
+    GetShortPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+    virtual void
+    GetPluginCommandHelp (const char *command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Error
+    ExecutePluginCommand (lldb_private::Args &command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Log *
+    EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
+
+
+
+protected:
+    mutable lldb_private::Mutex m_mutex;
+    struct  mach_header m_header;
+    mutable std::auto_ptr<lldb_private::SectionList> m_sections_ap;
+    mutable std::auto_ptr<lldb_private::Symtab> m_symtab_ap;
+
+    struct dysymtab_command m_dysymtab;
+    std::vector<struct segment_command_64> m_mach_segments;
+    std::vector<struct section_64> m_mach_sections;
+
+    size_t
+    ParseSections ();
+
+    size_t
+    ParseSymtab (bool minimize);
+
+};
+
+#endif  // liblldb_ObjectFileMachO_h_
diff --git a/source/Plugins/Process/MacOSX-User/scripts/cc-swig b/source/Plugins/Process/MacOSX-User/scripts/cc-swig
new file mode 100644
index 0000000..0bb089a
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/scripts/cc-swig
@@ -0,0 +1,47 @@
+#!/usr/bin/perl
+
+use File::Basename;
+
+sub execute_command
+{
+	print join(' ', @_), "\n";
+	if (scalar(@_) > 0) {
+		system(@_);		
+	} else {
+		system($_[0]);				
+	}
+}
+
+my $infile = $ENV{SCRIPT_INPUT_FILE_1};
+my($in_basename, $in_dirname, $in_extension) = fileparse($infile, qr/\.[^.]*/);
+my $outdir = "$ENV{DERIVED_FILE_DIR}";
+my $perl_wrap_c = "$outdir/${in_basename}_perl_wrap.c";
+mkdir "$ENV{OBJECT_FILE_DIR}";
+my $perl_wrap_o = "$ENV{OBJECT_FILE_DIR}/${in_basename}_perl_wrap.o";
+my $perl_module = "$outdir/${in_basename}.pm";
+my $header_paths = "-I'../../../../../debugcore/source' -I'../../../../../DebugBase'";
+my $framework_opts = "-F'$ENV{CONFIGURATION_BUILD_DIR}' ";
+execute_command("/usr/bin/swig -shadow -perl5 -DHAS_BOOL $header_paths -outdir '$outdir' -o '$perl_wrap_c' '$infile'");
+
+# Get any needed perl options for the next compile
+my $ccopts = `perl -MExtUtils::Embed -e ccopts`;
+my $libperl_dir = undef;
+if ($ccopts =~ /-I(\/System.*CORE)/)
+{
+	 $libperl_dir = $1;
+	 print "libperl directory: '$libperl_dir'\n";
+}
+
+execute_command("cd '$ENV{OBJECT_FILE_DIR}' && ln -s '$libperl_dir/libperl.dylib'");
+
+
+# Strip out the default architectures it gave us, we will add them back with
+# the $arch_opts below
+$ccopts =~ s/-arch [a-z_0-9]+//g;
+
+# Get a list of our build architectures
+my $arch_opts = "-arch " . join(' -arch ', split('\s+', $ENV{ARCHS}));
+
+execute_command("gcc -c -Dbool=char $arch_opts $ccopts $header_paths $framework_opts -I'$ENV{PROJECT_DIR}/source' '$perl_wrap_c' -o '$perl_wrap_o'");
+
+execute_command("cp '$perl_module' '$ENV{CONFIGURATION_BUILD_DIR}/$ENV{SHARED_SUPPORT_FOLDER_PATH}'");
\ No newline at end of file
diff --git a/source/Plugins/Process/MacOSX-User/scripts/config.pl b/source/Plugins/Process/MacOSX-User/scripts/config.pl
new file mode 100644
index 0000000..a6cf6ce
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/scripts/config.pl
@@ -0,0 +1,71 @@
+#!/usr/bin/perl
+
+use strict;
+my $config_file = "$ENV{SCRIPT_OUTPUT_FILE_0}";
+
+# Define the tests we need to run during this configuration
+my @config_tests = (
+	{
+		NAME => "HAVE_64_BIT_MACH_EXCEPTIONS",
+		TEST => "-e '$ENV{SDKROOT}/usr/include/mach/mach_exc.defs'",
+		COMMENT => "// Defined if we can use 64 bit mach exceptions",
+		FAIL => "#undef HAVE_64_BIT_MACH_EXCEPTIONS\
+#define mach_exception_data_t exception_data_t\
+#define mach_exception_data_type_t exception_data_type_t\
+#define mach_exc_server exc_server\
+#define MACH_EXCEPTION_CODES 0\n",
+		SUCCESS => "#define HAVE_64_BIT_MACH_EXCEPTIONS 1\n",
+	}
+);
+
+#----------------------------------------------------------------------
+# Open the config file
+#----------------------------------------------------------------------
+open(CONFIG, "> $config_file") || die "Couldn't open '$config_file' for writing: $!\n";
+print CONFIG "/*" . "-" x 72 . "\n";
+print CONFIG "// This file is auto generated by a config.pl, do not edit by hand!\n";
+print CONFIG "//" . "-" x 72 . "\n";
+print CONFIG "// COMMAND LINE\n";
+print CONFIG "//	" . join(' ', @ARGV) . "\n";
+print CONFIG "//" . "-" x 72 . "\n";
+print CONFIG "// ENVIRONMENT\n";
+my $key;
+my $val;
+while (($key, $val) = each %ENV) 
+{
+	printf CONFIG "//	%s = %s\n", $key, $val;
+}
+print CONFIG "//" . "-" x 72 . "\n";
+print CONFIG "// SETTINGS\n";
+print CONFIG "//	config_file: '$config_file'\n";
+print CONFIG "//" . "-" x 72 . "\n";
+print CONFIG "*/\n\n";
+print CONFIG "#ifndef liblldb_PDConfig_h_\n";
+print CONFIG "#define liblldb_PDConfig_h_\n";
+
+
+#----------------------------------------------------------------------
+# Run the tests
+#----------------------------------------------------------------------
+foreach my $test_href (@config_tests)
+{
+	if (exists $test_href->{COMMENT}) {
+		print CONFIG "\n$test_href->{COMMENT}\n";
+	} else {
+		print CONFIG "\n// $test_href->{NAME}\n";
+	}
+	
+	my $test_result = eval "$test_href->{TEST}";
+	if ($test_result != 0)
+	{
+		print CONFIG "$test_href->{SUCCESS}\n";		
+	}
+	else
+	{
+		print CONFIG "$test_href->{FAIL}\n";		
+	}
+}
+
+print CONFIG "#endif // #ifndef liblldb_PDConfig_h_\n";
+close(CONFIG);
+
diff --git a/source/Plugins/Process/MacOSX-User/scripts/test-ProcessDebug.pl b/source/Plugins/Process/MacOSX-User/scripts/test-ProcessDebug.pl
new file mode 100755
index 0000000..96b3115
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/scripts/test-ProcessDebug.pl
@@ -0,0 +1,409 @@
+#!/usr/bin/perl
+
+use strict;
+use Cwd 'abs_path';
+our $home = $ENV{HOME} || die "ERROR: Couldn't deduce your home directory...\n";
+
+our @inc_paths = (
+	'./include',	
+);
+
+my $inc_paths_added = 0;
+foreach my $inc_path (@inc_paths)
+{
+	if (-e $inc_path)
+	{
+		push (@INC, abs_path($inc_path));
+		$inc_paths_added++;
+	} 
+}
+
+if ($inc_paths_added == 0)
+{
+	die "Please compile the Release version of lldb\n";
+}
+
+require lldb;
+
+# my $state = lldb::eStateAttaching;
+
+use constant UINT32_MAX => 4294967295;
+
+#----------------------------------------------------------------------
+# Interactive Commands
+#----------------------------------------------------------------------
+our %commands = (
+	break => {
+		name => 'break',	# in case an alias is used to get to this command
+		description => "Sets a breakpoint.",
+		usage => ["break ADDR"],
+		function => \&command_set_breakpoint,
+		runs_target => 0,
+	},
+	delete => {
+		name => 'delete',	# in case an alias is used to get to this command
+		description => "Deletes one or more breakpoints by ID.\
+If no breakpoint IDs are given all breakpoints will be deleted.\
+If one or more IDs are given, only those breakpoints will be deleted.",
+		usage => ["delete [ID1 ID2 ...]"],
+		function => \&command_clear_breakpoint,
+		runs_target => 0,
+	},
+	continue => {
+		name => 'continue',	# in case an alias is used to get to this command
+		description => "Continues target execution.",
+		usage => ["continue [ADDR]"],
+		function => \&command_continue,
+		runs_target => 1
+	},
+	step => {
+		name => 'step',	# in case an alias is used to get to this command
+		description => "Single steps one instruction.",
+		usage => ["step"],
+		function => \&command_step,
+		runs_target => 1
+	},
+	info => {
+		name => 'info',	# in case an alias is used to get to this command
+		description => "Gets info on a variety of things.",
+		usage => ["info reg", "info thread", "info threads"],
+		function => \&command_info,
+		runs_target => 0
+	},
+	help => {
+		name => 'help',	# in case an alias is used to get to this command
+		description => "Displays a list of all commands, or help for a specific command.",
+		usage => ["help", "help CMD"],
+		function => \&command_help,
+		runs_target => 0
+	}
+);
+
+#----------------------------------------------------------------------
+# Command aliases
+#----------------------------------------------------------------------
+our %aliases = (
+	b => $commands{break},
+	c => $commands{continue},
+	s => $commands{step},
+	d => $commands{delete},
+	h => $commands{help}	
+);
+
+our $opt_g = 0;	# Enable verbose debug logging
+our $opt_v = 0;	# Verbose mode
+my $prev_command_href = undef;
+my $stdio = '/dev/stdin';
+my $launch = 0;
+my @env = ();
+my @break_ids;
+
+#----------------------------------------------------------------------
+# Given a command string, return the command hash reference for it, or
+# undef if it doesn't exist.
+#----------------------------------------------------------------------
+sub get_command_hash_ref
+{
+	my $cmd = shift;
+	my $cmd_href = undef;
+	if (length($cmd) == 0)			{ $cmd_href = $prev_command_href;	}
+	elsif (exists $aliases{$cmd})	{ $cmd_href = $aliases{$cmd};		} 
+	elsif (exists $commands{$cmd})	{ $cmd_href = $commands{$cmd};		}
+	defined $cmd_href and $prev_command_href = $cmd_href;
+	return $cmd_href;
+}
+
+#----------------------------------------------------------------------
+# Set a breakpoint
+#----------------------------------------------------------------------
+sub command_set_breakpoint
+{
+	my $pid = shift;
+	my $tid = shift;
+	$opt_g and print "command_set_breakpoint (pid = $pid, locations = @_)\n";
+	foreach my $location (@_)
+	{
+		my $success = 0;
+		my $address = hex($location);
+		if ($address != 0)
+		{
+			my $break_id = lldb::PDBreakpointSet ($pid, $address, 1, 0);
+			if ($break_id != $lldb::PD_INVALID_BREAK_ID)
+			{
+				printf("Breakpoint %i is set.\n", $break_id);
+				push(@break_ids, $break_id);
+				$success = 1;
+			}
+		}
+		$success or print("error: failed to set breakpoint at $location.\n");
+	}
+	return 1;
+}
+
+#----------------------------------------------------------------------
+# Clear a breakpoint
+#----------------------------------------------------------------------
+sub command_clear_breakpoint
+{
+	my $pid = shift;
+	my $tid = shift;
+	if (@_)
+	{
+		my $break_id;
+		my @cleared_break_ids;
+		my @new_break_ids;
+		$opt_g and print "command_clear_breakpoint (pid = $pid, break_ids = @_)\n";
+		foreach $break_id (@_)
+		{
+			if (lldb::PDBreakpointClear ($pid, $break_id))
+			{
+				printf("Breakpoint %i has been cleared.\n", $break_id);
+				push (@cleared_break_ids, $break_id);
+			}
+			else
+			{
+				printf("error: failed to clear breakpoint %i.\n", $break_id);					
+			}
+		}
+		
+		foreach my $old_break_id (@break_ids)
+		{
+			my $found_break_id = 0;
+			foreach $break_id (@cleared_break_ids)
+			{
+				if ($old_break_id == $break_id)
+				{
+					$found_break_id = 1;
+				}
+			}
+			$found_break_id or push (@new_break_ids, $old_break_id);
+		}
+		@break_ids = @new_break_ids;
+	}
+	else
+	{
+		# Nothing specified, clear all breakpoints
+		return command_clear_breakpoint($pid, $tid, @break_ids);
+	}
+	return 1;
+}
+#----------------------------------------------------------------------
+# Continue program execution
+#----------------------------------------------------------------------
+sub command_continue
+{
+	my $pid = shift;
+	my $tid = shift;
+	$opt_g and print "command_continue (pid = $pid)\n";
+	if ($pid != $lldb::PD_INVALID_PROCESS_ID)
+	{
+		$opt_v and printf("Resuming pid %d...\n", $pid);
+		return lldb::PDProcessResume ($pid);
+	}
+	return 0;
+}
+
+sub command_step
+{
+	my $pid = shift;
+	my $tid = shift;
+	$opt_g and print "command_step (pid = $pid, tid = $tid)\n";
+	if ($pid != $lldb::PD_INVALID_PROCESS_ID)
+	{
+		$opt_v and printf("Single stepping pid %d tid = %4.4x...\n", $pid, $tid);
+		return lldb::PDThreadResume ($pid, $tid, 1);
+	}
+	return 0;
+}
+
+sub command_info
+{
+	my $pid = shift;
+	my $tid = shift;
+	$opt_g and print "command_step (pid = $pid, tid = $tid)\n";
+	if ($pid != $lldb::PD_INVALID_PROCESS_ID)
+	{
+		if (@_)
+		{
+			my $info_cmd = shift;
+			if ($info_cmd eq 'reg')
+			{
+				
+			}
+			elsif ($info_cmd eq 'thread')
+			{
+				# info on the current thread
+				printf("thread 0x%4.4x %s\n", $tid, lldb::PDThreadGetInfo($pid, $tid));
+			}
+			elsif ($info_cmd eq 'threads')
+			{
+				my $num_threads = lldb::PDProcessGetNumThreads( $pid );
+				for my $thread_num (1..$num_threads)
+				{
+					my $curr_tid = lldb::PDProcessGetThreadAtIndex ( $pid, $thread_num - 1 );
+					printf("%c%u - thread 0x%4.4x %s\n", $curr_tid == $tid ? '*' : ' ', $thread_num, $curr_tid, lldb::PDThreadGetInfo($pid, $curr_tid));
+				}
+			}
+		}
+	}
+	return 1;
+}
+#----------------------------------------------------------------------
+# Get help on all commands, or a specific list of commands
+#----------------------------------------------------------------------
+sub command_help
+{
+	my $pid = shift;
+	my $tid = shift;
+	if (@_)
+	{
+		$opt_g and print "command_continue (pid = $pid, commands = @_)\n";
+		foreach my $cmd (@_)
+		{
+			my $cmd_href = get_command_hash_ref($cmd);
+			if ($cmd_href)
+			{
+				print '#', '-' x 72, "\n# $cmd_href->{name}\n", '#', '-' x 72, "\n";
+				my $usage_aref = $cmd_href->{usage};
+				if (@{$usage_aref})
+				{
+					print "  USAGE\n";
+					foreach my $usage (@{$usage_aref}) {
+						print "    $usage\n";
+					}
+					print "\n";
+				}
+				print "  DESCRIPTION\n    $cmd_href->{description}\n\n";
+			}
+			else
+			{
+				print "  invalid command: '$cmd'\n\n";
+			}
+		}
+	}
+	else
+	{
+		return command_help($pid, sort keys %commands);
+	}
+	return 1;
+}
+
+
+#lldb::PDLogSetLogMask ($lldb::PD_LOG_ALL);
+#lldb::PDLogSetLogFile ('/dev/stdout');
+
+print "running: ", join(' ', @ARGV), "\n";
+
+my $pid = lldb::PDProcessLaunch ($ARGV[0], \@ARGV, \@env, "i386", '/dev/stdin', '/dev/stdout', '/dev/stderr', $launch, '', 0);
+my $pid_state;
+while ($pid)
+{
+	$opt_g and printf("PDProcessWaitForEvents (%d, 0x%4.4x, SET, 1)\n", $pid, $lldb::PD_ALL_EVENTS);
+	my $events = lldb::PDProcessWaitForEvents ($pid, $lldb::PD_ALL_EVENTS, 1, 1);
+	if ($events)
+	{
+		$opt_g and printf ("Got event: 0x%8.8x\n", $events);
+
+		if ($events & $lldb::PD_EVENT_IMAGES_CHANGED)
+		{
+			$opt_g and printf("pid %d images changed...\n", $pid);
+		}
+
+		if ($events & $lldb::PD_EVENT_STDIO)
+		{
+			$opt_g and printf("pid %d has stdio...\n", $pid);
+		}
+
+		if ($events & $lldb::PD_EVENT_ASYNC_INTERRUPT)
+		{
+			$opt_g and printf("pid %d got async interrupt...\n", $pid);
+		}
+
+		if ($events & $lldb::PD_EVENT_RUNNING)
+		{
+			$pid_state = lldb::PDProcessGetState ($pid);
+			$opt_v and printf( "pid %d state: %s.\n", $pid, lldb::PDStateAsString ($pid_state) );
+		}
+		
+		if ($events & $lldb::PD_EVENT_STOPPED)
+		{
+			$pid_state = lldb::PDProcessGetState ($pid);
+			$opt_v and printf( "pid %d state: %s.\n", $pid, lldb::PDStateAsString ($pid_state) );
+
+			if ($pid_state == $lldb::eStateUnloaded ||
+				$pid_state == $lldb::eStateAttaching ||
+				$pid_state == $lldb::eStateLaunching )
+			{
+				
+			}
+		    elsif (	$pid_state == $lldb::eStateStopped )
+			{
+				my $tid = lldb::PDProcessGetCurrentThread ( $pid );
+				my $pc = lldb::PDThreadGetRegisterHexValueByName($pid, $tid, $lldb::PD_REGISTER_SET_ALL, "eip", 0);
+				$pc != 0 and printf("pc = 0x%8.8x ", $pc); 
+				# my $sp = lldb::PDThreadGetRegisterHexValueByName($pid, $tid, $lldb::PD_REGISTER_SET_ALL, "esp", 0);
+				# $sp != 0 and printf("sp = 0x%8.8x ", $sp);
+				# my $fp = lldb::PDThreadGetRegisterHexValueByName($pid, $tid, $lldb::PD_REGISTER_SET_ALL, "ebp", 0);
+				# $sp != 0 and printf("fp = 0x%8.8x ", $fp);
+				# print "\n";
+				my $done = 0;
+				my $input;
+				while (!$done)
+				{
+					print '(pdbg) '; 
+					
+					chomp($input = <STDIN>);
+					my @argv = split(/\s+/, $input);
+					my $cmd = @argv ? shift @argv : undef;
+					my $cmd_href = get_command_hash_ref ($cmd);
+					if ($cmd_href)
+					{
+						# Print the expanded alias if one was used
+						if ($opt_v and $cmd_href->{name} ne $cmd)
+						{
+							print "$cmd_href->{name} @argv\n";
+						}
+
+						# Call the command's callback function to make things happen
+						if ($cmd_href->{function}($pid, $tid, @argv))
+						{							
+							$done = $cmd_href->{runs_target};
+						}
+					}
+					else
+					{
+						print "invalid command: '$cmd'\nType 'help' for a list of all commands.\nType 'help CMD' for help on a specific commmand.\n";
+					}
+				}
+			}
+		    elsif (	$pid_state == $lldb::eStateRunning ||
+			 		$pid_state == $lldb::eStateStepping )
+			{
+				
+			}
+		    elsif (	$pid_state == $lldb::eStateCrashed ||
+		    		$pid_state == $lldb::eStateDetached	||
+		    		$pid_state == $lldb::eStateExited )
+			{
+				$pid = 0;				
+			}
+		    elsif ( $pid_state == $lldb::eStateSuspended )
+			{
+			}
+			else
+			{
+			}
+		}
+		
+		if ($pid)
+		{
+			$opt_g and printf("PDProcessResetEvents(%d, 0x%8.8x)\n", $pid, $events);
+			lldb::PDProcessResetEvents($pid, $events);			
+		}
+	}	
+}
+
+if ($pid != $lldb::PD_INVALID_PROCESS_ID)
+{
+	lldb::PDProcessDetach ($pid);
+}
diff --git a/source/Plugins/Process/MacOSX-User/source/MacOSX/MachException.cpp b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachException.cpp
new file mode 100644
index 0000000..7dc8d2c
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachException.cpp
@@ -0,0 +1,575 @@
+//===-- MachException.cpp ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/ptrace.h>
+
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/Host.h"
+
+#include "MachException.h"
+#include "ProcessMacOSXLog.h"
+
+using namespace lldb_private;
+
+// Routine mach_exception_raise
+extern "C"
+kern_return_t catch_mach_exception_raise
+(
+    mach_port_t exception_port,
+    mach_port_t thread,
+    mach_port_t task,
+    exception_type_t exception,
+    mach_exception_data_t code,
+    mach_msg_type_number_t codeCnt
+);
+
+extern "C"
+kern_return_t catch_mach_exception_raise_state
+(
+    mach_port_t exception_port,
+    exception_type_t exception,
+    const mach_exception_data_t code,
+    mach_msg_type_number_t codeCnt,
+    int *flavor,
+    const thread_state_t old_state,
+    mach_msg_type_number_t old_stateCnt,
+    thread_state_t new_state,
+    mach_msg_type_number_t *new_stateCnt
+);
+
+// Routine mach_exception_raise_state_identity
+extern "C"
+kern_return_t catch_mach_exception_raise_state_identity
+(
+    mach_port_t exception_port,
+    mach_port_t thread,
+    mach_port_t task,
+    exception_type_t exception,
+    mach_exception_data_t code,
+    mach_msg_type_number_t codeCnt,
+    int *flavor,
+    thread_state_t old_state,
+    mach_msg_type_number_t old_stateCnt,
+    thread_state_t new_state,
+    mach_msg_type_number_t *new_stateCnt
+);
+
+extern "C" boolean_t mach_exc_server(
+        mach_msg_header_t *InHeadP,
+        mach_msg_header_t *OutHeadP);
+
+// Any access to the g_message variable should be done by locking the
+// g_message_mutex first, using the g_message variable, then unlocking
+// the g_message_mutex. See MachException::Message::CatchExceptionRaise()
+// for sample code.
+
+static MachException::Data *g_message = NULL;
+//static pthread_mutex_t g_message_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+
+extern "C"
+kern_return_t
+catch_mach_exception_raise_state
+(
+    mach_port_t                 exc_port,
+    exception_type_t            exc_type,
+    const mach_exception_data_t exc_data,
+    mach_msg_type_number_t      exc_data_count,
+    int *                       flavor,
+    const thread_state_t        old_state,
+    mach_msg_type_number_t      old_stateCnt,
+    thread_state_t              new_state,
+    mach_msg_type_number_t *    new_stateCnt
+)
+{
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_EXCEPTIONS);
+    if (log)
+    {
+        log->Printf("::%s ( exc_port = 0x%4.4x, exc_type = %d ( %s ), exc_data = " MACH_EXCEPTION_DATA_FMT_HEX ", exc_data_count = %d)",
+            __FUNCTION__,
+            exc_port,
+            exc_type, MachException::Name(exc_type),
+            exc_data,
+            exc_data_count);
+    }
+    return KERN_FAILURE;
+}
+
+extern "C"
+kern_return_t
+catch_mach_exception_raise_state_identity
+(
+    mach_port_t             exc_port,
+    mach_port_t             thread_port,
+    mach_port_t             task_port,
+    exception_type_t        exc_type,
+    mach_exception_data_t   exc_data,
+    mach_msg_type_number_t  exc_data_count,
+    int *                   flavor,
+    thread_state_t          old_state,
+    mach_msg_type_number_t  old_stateCnt,
+    thread_state_t          new_state,
+    mach_msg_type_number_t *new_stateCnt
+)
+{
+    kern_return_t kret;
+    Log * log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_EXCEPTIONS);
+    if (log)
+    {
+        log->Printf("::%s ( exc_port = 0x%4.4x, thd_port = 0x%4.4x, tsk_port = 0x%4.4x, exc_type = %d ( %s ), exc_data[%d] = { " MACH_EXCEPTION_DATA_FMT_HEX ",  " MACH_EXCEPTION_DATA_FMT_HEX " })",
+            __FUNCTION__,
+            exc_port,
+            thread_port,
+            task_port,
+            exc_type, MachException::Name(exc_type),
+            exc_data_count,
+            exc_data_count > 0 ? exc_data[0] : 0xBADDBADD,
+            exc_data_count > 1 ? exc_data[1] : 0xBADDBADD);
+    }
+    kret = mach_port_deallocate (mach_task_self (), task_port);
+    kret = mach_port_deallocate (mach_task_self (), thread_port);
+
+    return KERN_FAILURE;
+}
+
+extern "C"
+kern_return_t
+catch_mach_exception_raise
+(
+    mach_port_t             exc_port,
+    mach_port_t             thread_port,
+    mach_port_t             task_port,
+    exception_type_t        exc_type,
+    mach_exception_data_t   exc_data,
+    mach_msg_type_number_t  exc_data_count)
+{
+    Log * log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_EXCEPTIONS);
+    if (log)
+    {
+        log->Printf("::%s ( exc_port = 0x%4.4x, thd_port = 0x%4.4x, tsk_port = 0x%4.4x, exc_type = %d ( %s ), exc_data[%d] = { " MACH_EXCEPTION_DATA_FMT_HEX ",  " MACH_EXCEPTION_DATA_FMT_HEX " })",
+            __FUNCTION__,
+            exc_port,
+            thread_port,
+            task_port,
+            exc_type, MachException::Name(exc_type),
+            exc_data_count,
+            exc_data_count > 0 ? exc_data[0] : 0xBADDBADD,
+            exc_data_count > 1 ? exc_data[1] : 0xBADDBADD);
+    }
+
+    g_message->task_port = task_port;
+    g_message->thread_port = thread_port;
+    g_message->exc_type = exc_type;
+    g_message->exc_data.resize(exc_data_count);
+    ::memcpy (&g_message->exc_data[0], exc_data, g_message->exc_data.size() * sizeof (mach_exception_data_type_t));
+    return KERN_SUCCESS;
+}
+
+
+void
+MachException::Message::PutToLog(Log *log) const
+{
+    if (log)
+    {
+        log->Printf("  exc_msg { bits = 0x%8.8lx size = 0x%8.8lx remote-port = 0x%8.8lx local-port = 0x%8.8lx reserved = 0x%8.8lx id = 0x%8.8lx } ",
+                exc_msg.hdr.msgh_bits,
+                exc_msg.hdr.msgh_size,
+                exc_msg.hdr.msgh_remote_port,
+                exc_msg.hdr.msgh_local_port,
+                exc_msg.hdr.msgh_reserved,
+                exc_msg.hdr.msgh_id);
+
+        log->Printf( "reply_msg { bits = 0x%8.8lx size = 0x%8.8lx remote-port = 0x%8.8lx local-port = 0x%8.8lx reserved = 0x%8.8lx id = 0x%8.8lx }",
+                reply_msg.hdr.msgh_bits,
+                reply_msg.hdr.msgh_size,
+                reply_msg.hdr.msgh_remote_port,
+                reply_msg.hdr.msgh_local_port,
+                reply_msg.hdr.msgh_reserved,
+                reply_msg.hdr.msgh_id);
+        state.PutToLog(log);
+    }
+}
+
+bool
+MachException::Data::GetStopInfo(Thread::StopInfo *stop_info) const
+{
+    // Zero out the structure.
+    stop_info->Clear();
+
+    // Make sure we have a valid exception before we return anything valid
+    if (exc_type == 0)
+        return true;
+    // We always stop with a mach exceptions
+    const size_t exc_data_count = exc_data.size();
+    stop_info->SetStopReasonWithException(exc_type, exc_data_count);
+
+    // Fill in a text description
+    const char * exc_name = MachException::Name(exc_type);
+    StreamString sstr;
+    if (exc_name)
+        sstr.PutCString(exc_name);
+    else
+        sstr.Printf ("%i", exc_type);
+
+    int signal = SoftSignal();
+    if (signal > 0)
+    {
+        const char *sig_str = Host::GetSignalAsCString(signal);
+        if (sig_str)
+            sstr.Printf (" EXC_SOFT_SIGNAL(%s)", sig_str);
+        else
+            sstr.Printf (" EXC_SOFT_SIGNAL(%i)", signal);
+    }
+    else
+    {
+        // No special disassembly for exception data, just
+        sstr.Printf (" data[%zu] = {", exc_data_count);
+
+        for (size_t idx = 0; idx < exc_data_count; ++idx)
+            sstr.Printf (MACH_EXCEPTION_DATA_FMT_MINHEX "%s", exc_data[idx], ((idx + 1 == exc_data_count) ? "" : ","));
+
+        sstr.PutChar('}');
+    }
+
+    stop_info->SetStopDescription (sstr.GetData());
+
+    // Copy the exception data
+    size_t i;
+    for (i=0; i<exc_data_count; i++)
+        stop_info->SetExceptionDataAtIndex(i, exc_data[i]);
+
+    return true;
+}
+
+
+void
+MachException::Data::DumpStopReason() const
+{
+    Log * log = ProcessMacOSXLog::GetLogIfAllCategoriesSet();
+    if (log)
+    {
+        int signal = SoftSignal();
+        if (signal > 0)
+        {
+            const char *signal_str = Host::GetSignalAsCString(signal);
+            if (signal_str)
+                log->Printf ("signal(%s)", signal_str);
+            else
+                log->Printf ("signal(%i)", signal);
+            return;
+        }
+        log->Printf ("%s", Name(exc_type));
+    }
+}
+
+kern_return_t
+MachException::Message::Receive(mach_port_t port, mach_msg_option_t options, mach_msg_timeout_t timeout, mach_port_t notify_port)
+{
+    Error err;
+    Log * log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_EXCEPTIONS);
+    mach_msg_timeout_t mach_msg_timeout = options & MACH_RCV_TIMEOUT ? timeout : 0;
+    if (log && ((options & MACH_RCV_TIMEOUT) == 0))
+    {
+        // Dump this log message if we have no timeout in case it never returns
+        log->Printf ("::mach_msg ( msg->{bits = %#x, size = %u remote_port = %#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, option = %#x, send_size = %u, rcv_size = %u, rcv_name = %#x, timeout = %u, notify = %#x)",
+                exc_msg.hdr.msgh_bits,
+                exc_msg.hdr.msgh_size,
+                exc_msg.hdr.msgh_remote_port,
+                exc_msg.hdr.msgh_local_port,
+                exc_msg.hdr.msgh_reserved,
+                exc_msg.hdr.msgh_id,
+                options,
+                0,
+                sizeof (exc_msg.data),
+                port,
+                mach_msg_timeout,
+                notify_port);
+    }
+
+    err = ::mach_msg (&exc_msg.hdr,
+                      options,                  // options
+                      0,                        // Send size
+                      sizeof (exc_msg.data),    // Receive size
+                      port,                     // exception port to watch for exception on
+                      mach_msg_timeout,         // timeout in msec (obeyed only if MACH_RCV_TIMEOUT is ORed into the options parameter)
+                      notify_port);
+
+    // Dump any errors we get
+    if (log && err.GetError() != MACH_RCV_TIMED_OUT)
+    {
+        log->Error("::mach_msg ( msg->{bits = %#x, size = %u remote_port = %#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, option = %#x, send_size = %u, rcv_size = %u, rcv_name = %#x, timeout = %u, notify = %#x)",
+            exc_msg.hdr.msgh_bits,
+            exc_msg.hdr.msgh_size,
+            exc_msg.hdr.msgh_remote_port,
+            exc_msg.hdr.msgh_local_port,
+            exc_msg.hdr.msgh_reserved,
+            exc_msg.hdr.msgh_id,
+            options,
+            0,
+            sizeof (exc_msg.data),
+            port,
+            mach_msg_timeout,
+            notify_port);
+    }
+    return err.GetError();
+}
+
+bool
+MachException::Message::CatchExceptionRaise()
+{
+    bool success = false;
+    // locker will keep a mutex locked until it goes out of scope
+//    Mutex::Locker locker(&g_message_mutex);
+    //    log->Printf ("calling  mach_exc_server");
+    g_message = &state;
+    // The exc_server function is the MIG generated server handling function
+    // to handle messages from the kernel relating to the occurrence of an
+    // exception in a thread. Such messages are delivered to the exception port
+    // set via thread_set_exception_ports or task_set_exception_ports. When an
+    // exception occurs in a thread, the thread sends an exception message to
+    // its exception port, blocking in the kernel waiting for the receipt of a
+    // reply. The exc_server function performs all necessary argument handling
+    // for this kernel message and calls catch_exception_raise,
+    // catch_exception_raise_state or catch_exception_raise_state_identity,
+    // which should handle the exception. If the called routine returns
+    // KERN_SUCCESS, a reply message will be sent, allowing the thread to
+    // continue from the point of the exception; otherwise, no reply message
+    // is sent and the called routine must have dealt with the exception
+    // thread directly.
+    if (mach_exc_server (&exc_msg.hdr, &reply_msg.hdr))
+    {
+        success = true;
+    }
+    else
+    {
+        Log * log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_EXCEPTIONS);
+        if (log)
+            log->Printf ("mach_exc_server returned zero...");
+    }
+    g_message = NULL;
+    return success;
+}
+
+
+
+kern_return_t
+MachException::Message::Reply(task_t task, pid_t pid, int signal)
+{
+    // Reply to the exception...
+    Error err;
+
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet();
+    if (log)
+        log->Printf("MachException::Message::Reply (task = 0x%4.4x, pid = %i, signal = %i)", task, pid, signal);
+
+    // If we had a soft signal, we need to update the thread first so it can
+    // continue without signaling
+    int soft_signal = state.SoftSignal();
+    int state_pid = LLDB_INVALID_PROCESS_ID;
+    if (task == state.task_port)
+    {
+        // This is our task, so we can update the signal to send to it
+        state_pid = pid;
+    }
+    else
+    {
+        err = ::pid_for_task(state.task_port, &state_pid);
+    }
+
+    if (signal == LLDB_INVALID_SIGNAL_NUMBER)
+        signal = 0;
+
+    if (log)
+        log->Printf("MachException::Message::Reply () updating thread signal to %i (original soft_signal = %i)", signal, soft_signal);
+
+    if (state_pid != LLDB_INVALID_PROCESS_ID)
+    {
+        errno = 0;
+        if (::ptrace (PT_THUPDATE, state_pid, (caddr_t)state.thread_port, signal) != 0)
+        {
+            if (soft_signal != LLDB_INVALID_SIGNAL_NUMBER)
+            // We know we currently can't forward signals for threads that didn't stop in EXC_SOFT_SIGNAL...
+            // So only report it as an error if we should have been able to do it.
+                err.SetErrorToErrno();
+            else
+                 err.Clear();
+        }
+        else
+            err.Clear();
+
+        if (log && log->GetMask().IsSet(PD_LOG_EXCEPTIONS) || err.Fail())
+            err.PutToLog(log, "::ptrace (request = PT_THUPDATE, pid = %i, tid = 0x%4.4x, signal = %i)", state_pid, state.thread_port, signal);
+    }
+
+    err = ::mach_msg (  &reply_msg.hdr,
+                        MACH_SEND_MSG | MACH_SEND_INTERRUPT,
+                        reply_msg.hdr.msgh_size,
+                        0,
+                        MACH_PORT_NULL,
+                        MACH_MSG_TIMEOUT_NONE,
+                        MACH_PORT_NULL);
+
+    if (log)
+        log->LogIf (PD_LOG_EXCEPTIONS, "::mach_msg ( msg->{bits = %#x, size = %u, remote_port = %#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, option = %#x, send_size = %u, rcv_size = %u, rcv_name = %#x, timeout = %u, notify = %#x) = 0x%8.8x",
+            reply_msg.hdr.msgh_bits,
+            reply_msg.hdr.msgh_size,
+            reply_msg.hdr.msgh_remote_port,
+            reply_msg.hdr.msgh_local_port,
+            reply_msg.hdr.msgh_reserved,
+            reply_msg.hdr.msgh_id,
+            MACH_SEND_MSG | MACH_SEND_INTERRUPT,
+            reply_msg.hdr.msgh_size,
+            0,
+            MACH_PORT_NULL,
+            MACH_MSG_TIMEOUT_NONE,
+            MACH_PORT_NULL,
+            err.GetError());
+
+
+    if (err.Fail())
+    {
+        if (err.GetError() == MACH_SEND_INTERRUPTED)
+        {
+            err.PutToLog(log, "::mach_msg() - send interrupted");
+        }
+        else
+        {
+            if (state.task_port == task)
+            {
+                err.PutToLog(log, "::mach_msg() - failed (task)");
+                abort ();
+            }
+            else
+            {
+                err.PutToLog(log, "::mach_msg() - failed (child of task)");
+            }
+        }
+    }
+
+    return err.GetError();
+}
+
+
+void
+MachException::Data::PutToLog(Log *log) const
+{
+    if (log == NULL)
+        return;
+
+    const char *exc_type_name = MachException::Name(exc_type);
+
+    log->Printf ("    state { task_port = 0x%4.4x, thread_port =  0x%4.4x, exc_type = %i (%s) ...", task_port, thread_port, exc_type, exc_type_name ? exc_type_name : "???");
+
+    const size_t exc_data_count = exc_data.size();
+    // Dump any special exception data contents
+    int soft_signal = SoftSignal();
+    if (soft_signal > 0)
+    {
+        const char *sig_str = Host::GetSignalAsCString(soft_signal);
+        log->Printf ("            exc_data: EXC_SOFT_SIGNAL (%i (%s))", soft_signal, sig_str ? sig_str : "unknown signal");
+    }
+    else
+    {
+        // No special disassembly for this data, just dump the data
+        size_t idx;
+        for (idx = 0; idx < exc_data_count; ++idx)
+        {
+            log->Printf("            exc_data[%u]: " MACH_EXCEPTION_DATA_FMT_HEX, idx, exc_data[idx]);
+        }
+    }
+}
+
+
+MachException::PortInfo::PortInfo() :
+    count(0)
+{
+    ::bzero (masks, sizeof(masks));
+    ::bzero (ports, sizeof(ports));
+    ::bzero (behaviors, sizeof(behaviors));
+    ::bzero (flavors, sizeof(flavors));
+}
+
+
+kern_return_t
+MachException::PortInfo::Save (task_t task)
+{
+    count = EXC_TYPES_COUNT;
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_EXCEPTIONS);
+    if (log)
+        log->Printf ("MachException::PortInfo::Save (task = 0x%4.4x)", task);
+    Error err;
+    if (log)
+        log->Printf("::task_get_exception_ports (task=0x%4.4x, mask=0x%x, maskCnt<=>%u, ports, behaviors, flavors)...", task, EXC_MASK_ALL, count);
+    err = ::task_get_exception_ports (task, EXC_MASK_ALL, masks, &count, ports, behaviors, flavors);
+    if (log || err.Fail())
+        err.PutToLog(log, "::task_get_exception_ports (task=0x%4.4x, mask=0x%x, maskCnt<=>%u, ports, behaviors, flavors)", task, EXC_MASK_ALL, count);
+    if (log)
+    {
+        mach_msg_type_number_t i;
+        log->Printf("Index Mask     Port     Behavior Flavor", masks[i], ports[i], behaviors[i], flavors[i]);
+        log->Printf("===== -------- -------- -------- --------");
+        for (i=0; i<count; ++i)
+            log->Printf("[%3u] %8.8x %8.8x %8.8x %8.8x", i, masks[i], ports[i], behaviors[i], flavors[i]);
+    }
+    if (err.Fail())
+        count = 0;
+    return err.GetError();
+}
+
+kern_return_t
+MachException::PortInfo::Restore (task_t task)
+{
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_EXCEPTIONS);
+    if (log && log->GetMask().IsSet(PD_LOG_VERBOSE))
+        log->Printf("MachException::PortInfo::Restore (task = 0x%4.4x)", task);
+    uint32_t i = 0;
+    Error err;
+    if (count > 0)
+    {
+        for (i = 0; i < count; i++)
+        {
+            err = ::task_set_exception_ports (task, masks[i], ports[i], behaviors[i], flavors[i]);
+            if (log || err.Fail())
+                err.PutToLog(log, "::task_set_exception_ports ( task = 0x%4.4x, exception_mask = 0x%8.8x, new_port = 0x%4.4x, behavior = 0x%8.8x, new_flavor = 0x%8.8x )", task, masks[i], ports[i], behaviors[i], flavors[i]);
+
+            if (err.Fail())
+                break;
+        }
+    }
+    count = 0;
+    return err.GetError();
+}
+
+const char *
+MachException::Name(exception_type_t exc_type)
+{
+    switch (exc_type)
+    {
+    case EXC_BAD_ACCESS:        return "EXC_BAD_ACCESS";
+    case EXC_BAD_INSTRUCTION:   return "EXC_BAD_INSTRUCTION";
+    case EXC_ARITHMETIC:        return "EXC_ARITHMETIC";
+    case EXC_EMULATION:         return "EXC_EMULATION";
+    case EXC_SOFTWARE:          return "EXC_SOFTWARE";
+    case EXC_BREAKPOINT:        return "EXC_BREAKPOINT";
+    case EXC_SYSCALL:           return "EXC_SYSCALL";
+    case EXC_MACH_SYSCALL:      return "EXC_MACH_SYSCALL";
+    case EXC_RPC_ALERT:         return "EXC_RPC_ALERT";
+#ifdef EXC_CRASH
+    case EXC_CRASH:             return "EXC_CRASH";
+#endif
+    default:
+        break;
+    }
+    return NULL;
+}
+
+
+
diff --git a/source/Plugins/Process/MacOSX-User/source/MacOSX/MachException.h b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachException.h
new file mode 100644
index 0000000..1f3aeb0
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachException.h
@@ -0,0 +1,148 @@
+//===-- MachException.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_MachException_h_
+#define liblldb_MachException_h_
+
+#include <mach/mach.h>
+#include <vector>
+#include "lldb/lldb-private.h"
+#include "lldb/Target/Thread.h"
+// TODO: Get the config script to run to this plug-in
+//#include "PDConfig.h"
+#define HAVE_64_BIT_MACH_EXCEPTIONS // REMOVE THIS WHEN PDConfig.h is included above
+#ifdef HAVE_64_BIT_MACH_EXCEPTIONS
+
+#define MACH_EXCEPTION_DATA_FMT_DEC "%lld"
+#define MACH_EXCEPTION_DATA_FMT_HEX "0x%16.16llx"
+#define MACH_EXCEPTION_DATA_FMT_MINHEX "0x%llx"
+
+#else
+
+#define MACH_EXCEPTION_DATA_FMT_DEC "%d"
+#define MACH_EXCEPTION_DATA_FMT_HEX "0x%8.8x"
+#define MACH_EXCEPTION_DATA_FMT_MINHEX "0x%x"
+
+#endif
+
+class MachProcess;
+
+typedef union MachMessageTag
+{
+    mach_msg_header_t hdr;
+    char data[1024];
+} MachMessage;
+
+
+class MachException
+{
+public:
+
+    struct PortInfo
+    {
+        exception_mask_t        masks[EXC_TYPES_COUNT];
+        mach_port_t             ports[EXC_TYPES_COUNT];
+        exception_behavior_t    behaviors[EXC_TYPES_COUNT];
+        thread_state_flavor_t   flavors[EXC_TYPES_COUNT];
+        mach_msg_type_number_t  count;
+
+        PortInfo();
+        kern_return_t   Save(task_t task);
+        kern_return_t   Restore(task_t task);
+    };
+
+    struct Data
+    {
+        task_t task_port;
+        lldb::tid_t thread_port;
+        exception_type_t exc_type;
+        std::vector<mach_exception_data_type_t> exc_data;
+        Data() :
+            task_port(TASK_NULL),
+            thread_port(THREAD_NULL),
+            exc_type(0),
+            exc_data()
+            {
+            }
+
+        void Clear()
+        {
+            task_port = TASK_NULL;
+            thread_port = THREAD_NULL;
+            exc_type = 0;
+            exc_data.clear();
+        }
+        bool IsValid() const
+        {
+            return  task_port != TASK_NULL &&
+                    thread_port != THREAD_NULL &&
+                    exc_type != 0;
+        }
+        // Return the SoftSignal for this MachException data, or zero if there is none
+        int SoftSignal() const
+        {
+            if (exc_type == EXC_SOFTWARE && exc_data.size() == 2 && exc_data[0] == EXC_SOFT_SIGNAL)
+                return exc_data[1];
+            return LLDB_INVALID_SIGNAL_NUMBER;
+        }
+        bool IsBreakpoint() const
+        {
+            return (exc_type == EXC_BREAKPOINT) || ((exc_type == EXC_SOFTWARE) && exc_data[0] == 1);
+        }
+        void PutToLog(lldb_private::Log *log) const;
+        void DumpStopReason() const;
+        bool GetStopInfo(lldb_private::Thread::StopInfo *stop_info) const;
+    };
+
+    struct Message
+    {
+        MachMessage exc_msg;
+        MachMessage reply_msg;
+        Data state;
+
+        Message() :
+            exc_msg(),
+            reply_msg(),
+            state()
+        {
+            memset(&exc_msg,   0, sizeof(exc_msg));
+            memset(&reply_msg, 0, sizeof(reply_msg));
+        }
+        bool CatchExceptionRaise();
+        void PutToLog(lldb_private::Log *log) const;
+        kern_return_t Reply (task_t task, pid_t pid, int signal);
+        kern_return_t Receive( mach_port_t receive_port,
+                               mach_msg_option_t options,
+                               mach_msg_timeout_t timeout,
+                               mach_port_t notify_port = MACH_PORT_NULL);
+
+        typedef std::vector<Message>        collection;
+        typedef collection::iterator        iterator;
+        typedef collection::const_iterator    const_iterator;
+    };
+
+    enum
+    {
+        e_actionForward,    // Forward signal to inferior process
+        e_actionStop,        // Stop when this signal is received
+    };
+    struct Action
+    {
+        task_t task_port;            // Set to TASK_NULL for any TASK
+        lldb::tid_t thread_port;        // Set to THREAD_NULL for any thread
+        exception_type_t exc_mask;    // Mach exception mask to watch for
+        std::vector<mach_exception_data_type_t> exc_data_mask;    // Mask to apply to exception data, or empty to ignore exc_data value for exception
+        std::vector<mach_exception_data_type_t> exc_data_value;    // Value to compare to exception data after masking, or empty to ignore exc_data value for exception
+        uint8_t flags;                // Action flags describing what to do with the exception
+    };
+    static const char *Name(exception_type_t exc_type);
+};
+
+#endif
diff --git a/source/Plugins/Process/MacOSX-User/source/MacOSX/MachTask.cpp b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachTask.cpp
new file mode 100644
index 0000000..1a0c3c4
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachTask.cpp
@@ -0,0 +1,674 @@
+//===-- MachTask.cpp --------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MachTask.h"
+
+// C Includes
+// C++ Includes
+
+// Other libraries and framework includes
+#if defined (__arm__)
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <SpringBoardServices/SpringBoardServer.h>
+#include <SpringBoardServices/SBSWatchdogAssertion.h>
+
+#endif
+
+#include "lldb/Host/Host.h"
+#include "lldb/Core/DataExtractor.h"
+
+// Project includes
+#include "ProcessMacOSX.h"
+#include "ProcessMacOSXLog.h"
+
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// MachTask constructor
+//----------------------------------------------------------------------
+MachTask::MachTask(ProcessMacOSX *process) :
+    m_process (process),
+    m_task (TASK_NULL),
+    m_vm_memory (),
+    m_exception_thread (0),
+    m_exception_port (MACH_PORT_NULL),
+    m_exc_port_info()
+{
+    memset(&m_exc_port_info, 0, sizeof(m_exc_port_info));
+
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+MachTask::~MachTask()
+{
+    Clear();
+}
+
+
+//----------------------------------------------------------------------
+// MachTask::Suspend
+//----------------------------------------------------------------------
+kern_return_t
+MachTask::Suspend()
+{
+    Error err;
+    task_t task = GetTaskPort();
+    err = ::task_suspend (task);
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_TASK);
+    if (log || err.Fail())
+        err.PutToLog(log, "::task_suspend ( target_task = 0x%4.4x )", task);
+    return err.GetError();
+}
+
+
+//----------------------------------------------------------------------
+// MachTask::Resume
+//----------------------------------------------------------------------
+kern_return_t
+MachTask::Resume()
+{
+    Error err;
+    task_t task = GetTaskPort();
+    err = ::task_resume (task);
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_TASK);
+    if (log || err.Fail())
+        err.PutToLog(log, "::task_resume ( target_task = 0x%4.4x )", task);
+    return err.GetError();
+}
+
+int32_t
+MachTask::GetSuspendCount () const
+{
+    struct task_basic_info task_info;
+    if (BasicInfo(&task_info) == KERN_SUCCESS)
+        return task_info.suspend_count;
+    return -1;
+}
+
+//----------------------------------------------------------------------
+// MachTask::ExceptionPort
+//----------------------------------------------------------------------
+mach_port_t
+MachTask::ExceptionPort() const
+{
+    return m_exception_port;
+}
+
+//----------------------------------------------------------------------
+// MachTask::ExceptionPortIsValid
+//----------------------------------------------------------------------
+bool
+MachTask::ExceptionPortIsValid() const
+{
+    return MACH_PORT_VALID(m_exception_port);
+}
+
+
+//----------------------------------------------------------------------
+// MachTask::Clear
+//----------------------------------------------------------------------
+void
+MachTask::Clear()
+{
+    // Do any cleanup needed for this task
+    m_task = TASK_NULL;
+    m_exception_thread = 0;
+    m_exception_port = MACH_PORT_NULL;
+
+}
+
+
+//----------------------------------------------------------------------
+// MachTask::SaveExceptionPortInfo
+//----------------------------------------------------------------------
+kern_return_t
+MachTask::SaveExceptionPortInfo()
+{
+    return m_exc_port_info.Save(GetTaskPort());
+}
+
+//----------------------------------------------------------------------
+// MachTask::RestoreExceptionPortInfo
+//----------------------------------------------------------------------
+kern_return_t
+MachTask::RestoreExceptionPortInfo()
+{
+    return m_exc_port_info.Restore(GetTaskPort());
+}
+
+
+//----------------------------------------------------------------------
+// MachTask::ReadMemory
+//----------------------------------------------------------------------
+size_t
+MachTask::ReadMemory (lldb::addr_t addr, void *buf, size_t size, Error& error)
+{
+    size_t n = 0;
+    task_t task = GetTaskPort();
+    if (task != TASK_NULL)
+    {
+        n = m_vm_memory.Read(task, addr, buf, size, error);
+        Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_MEMORY);
+        if (log)
+        {
+            log->Printf ("MachTask::ReadMemory ( addr = 0x%16.16llx, size = %zu, buf = %8.8p) => %u bytes read", (uint64_t)addr, size, buf, n);
+            if (log->GetMask().IsSet(PD_LOG_MEMORY_DATA_LONG) || (log->GetMask().IsSet(PD_LOG_MEMORY_DATA_SHORT) && size <= 8))
+            {
+                DataExtractor data((uint8_t*)buf, n, eByteOrderHost, 4);
+                data.PutToLog(log, 0, n, addr, 16, DataExtractor::TypeUInt8);
+            }
+        }
+    }
+    return n;
+}
+
+
+//----------------------------------------------------------------------
+// MachTask::WriteMemory
+//----------------------------------------------------------------------
+size_t
+MachTask::WriteMemory (lldb::addr_t addr, const void *buf, size_t size, Error& error)
+{
+    size_t n = 0;
+    task_t task = GetTaskPort();
+    if (task != TASK_NULL)
+    {
+        n = m_vm_memory.Write(task, addr, buf, size, error);
+        Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_MEMORY);
+        if (log)
+        {
+            log->Printf ("MachTask::WriteMemory ( addr = 0x%16.16llx, size = %zu, buf = %8.8p) => %u bytes written", (uint64_t)addr, size, buf, n);
+            if (log->GetMask().IsSet(PD_LOG_MEMORY_DATA_LONG) || (log->GetMask().IsSet(PD_LOG_MEMORY_DATA_SHORT) && size <= 8))
+            {
+                DataExtractor data((uint8_t*)buf, n, eByteOrderHost, 4);
+                data.PutToLog(log, 0, n, addr, 16, DataExtractor::TypeUInt8);
+            }
+        }
+    }
+    return n;
+}
+
+//----------------------------------------------------------------------
+// MachTask::AllocateMemory
+//----------------------------------------------------------------------
+lldb::addr_t
+MachTask::AllocateMemory (size_t size, uint32_t permissions, Error& error)
+{
+    // FIXME: vm_allocate allocates a page at a time, so we should use
+    // host_page_size to get the host page size and then parcel out the
+    // page we get back until it is filled.
+    // FIXME: Add log messages.
+
+    kern_return_t kret;
+    mach_vm_address_t addr;
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_MEMORY);
+
+    kret = ::mach_vm_allocate (GetTaskPort(), &addr, size, TRUE);
+    if (kret == KERN_SUCCESS)
+    {
+        // Set the protections:
+        vm_prot_t mach_prot = 0;
+        if (permissions & lldb::ePermissionsReadable)
+            mach_prot |= VM_PROT_READ;
+        if (permissions & lldb::ePermissionsWritable)
+            mach_prot |= VM_PROT_WRITE;
+        if (permissions & lldb::ePermissionsExecutable)
+            mach_prot |= VM_PROT_EXECUTE;
+
+        kret = ::mach_vm_protect (GetTaskPort(), addr, size, 0, mach_prot);
+        if (kret == KERN_SUCCESS)
+        {
+            if (log)
+                log->Printf("Allocated memory at addr = 0x%16.16llx, size = %zu, prot = 0x%x)", (uint64_t) addr, size, mach_prot);
+            m_allocations.insert (std::make_pair(addr, size));
+            return (lldb::addr_t) addr;
+        }
+        else
+        {
+            if (log)
+                log->Printf("Failed to set protections on memory at addr = 0x%16.16llx, size = %zu), prot = 0x%x", (uint64_t) addr, size, mach_prot);
+            kret = ::mach_vm_deallocate (GetTaskPort(), addr, size);
+            return LLDB_INVALID_ADDRESS;
+        }
+    }
+    else
+    {
+        if (log)
+            log->Printf("Failed to set allocate memory: size = %zu)", size);
+        return LLDB_INVALID_ADDRESS;
+    }
+}
+
+//----------------------------------------------------------------------
+// MachTask::DeallocateMemory
+//----------------------------------------------------------------------
+Error
+MachTask::DeallocateMemory (lldb::addr_t ptr)
+{
+    Error error;
+    // We have to stash away sizes for the allocations...
+    allocation_collection::iterator pos, end = m_allocations.end();
+    for (pos = m_allocations.begin(); pos != end; pos++)
+    {
+        if ((*pos).first == ptr)
+        {
+            m_allocations.erase (pos);
+            error = ::mach_vm_deallocate (GetTaskPort(), (vm_address_t) ptr, (*pos).second);
+            return error;
+        }
+    }
+    error.SetErrorStringWithFormat("no memory allocated at 0x%llx", (uint64_t)ptr);
+    return error;
+}
+
+//----------------------------------------------------------------------
+// MachTask::TaskPortForProcessID
+//----------------------------------------------------------------------
+task_t
+MachTask::GetTaskPortForProcessID (Error &err)
+{
+    err.Clear();
+    if (m_task == TASK_NULL && m_process != NULL)
+        m_task = MachTask::GetTaskPortForProcessID(m_process->GetID(), err);
+    return m_task;
+}
+
+//----------------------------------------------------------------------
+// MachTask::TaskPortForProcessID
+//----------------------------------------------------------------------
+task_t
+MachTask::GetTaskPortForProcessID (lldb::pid_t pid, Error &err)
+{
+    task_t task = TASK_NULL;
+    if (pid != LLDB_INVALID_PROCESS_ID)
+    {
+        mach_port_t task_self = mach_task_self ();
+        err = ::task_for_pid ( task_self, pid, &task);
+        Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_TASK);
+        if (log || err.Fail())
+        {
+            err.PutToLog(log, "::task_for_pid ( target_tport = 0x%4.4x, pid = %d, task => 0x%4.4x ) %u/%u %u/%u", task_self, pid, task, getuid(), geteuid(), getgid(), getegid());
+        }
+    }
+    return task;
+}
+
+
+//----------------------------------------------------------------------
+// MachTask::BasicInfo
+//----------------------------------------------------------------------
+kern_return_t
+MachTask::BasicInfo(struct task_basic_info *info) const
+{
+    return BasicInfo (GetTaskPort(), info);
+}
+
+//----------------------------------------------------------------------
+// MachTask::BasicInfo
+//----------------------------------------------------------------------
+kern_return_t
+MachTask::BasicInfo(task_t task, struct task_basic_info *info)
+{
+    if (info == NULL)
+        return KERN_INVALID_ARGUMENT;
+
+    Error err;
+    mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT;
+    err = ::task_info (task, TASK_BASIC_INFO, (task_info_t)info, &count);
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_TASK);
+    if (log || err.Fail())
+        err.PutToLog(log, "::task_info ( target_task = 0x%4.4x, flavor = TASK_BASIC_INFO, task_info_out => %p, task_info_outCnt => %u )", task, info, count);
+    if (log && log->GetMask().IsSet(PD_LOG_VERBOSE) && err.Success())
+    {
+        float user = (float)info->user_time.seconds + (float)info->user_time.microseconds / 1000000.0f;
+        float system = (float)info->user_time.seconds + (float)info->user_time.microseconds / 1000000.0f;
+        log->Printf ("task_basic_info = { suspend_count = %i, virtual_size = 0x%8.8x, resident_size = 0x%8.8x, user_time = %f, system_time = %f }",
+                    info->suspend_count, info->virtual_size, info->resident_size, user, system);
+    }
+    return err.GetError();
+}
+
+
+//----------------------------------------------------------------------
+// MachTask::IsValid
+//
+// Returns true if a task is a valid task port for a current process.
+//----------------------------------------------------------------------
+bool
+MachTask::IsValid () const
+{
+    return MachTask::IsValid(GetTaskPort());
+}
+
+//----------------------------------------------------------------------
+// MachTask::IsValid
+//
+// Returns true if a task is a valid task port for a current process.
+//----------------------------------------------------------------------
+bool
+MachTask::IsValid (task_t task)
+{
+    if (task != TASK_NULL)
+    {
+        struct task_basic_info task_info;
+        return BasicInfo(task, &task_info) == KERN_SUCCESS;
+    }
+    return false;
+}
+
+
+bool
+MachTask::StartExceptionThread(Error &err)
+{
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_EXCEPTIONS);
+
+    if (log)
+        log->Printf ("MachTask::%s ( )", __FUNCTION__);
+    task_t task = GetTaskPortForProcessID(err);
+    if (MachTask::IsValid(task))
+    {
+        // Got the mach port for the current process
+        mach_port_t task_self = mach_task_self ();
+
+        // Allocate an exception port that we will use to track our child process
+        err = ::mach_port_allocate (task_self, MACH_PORT_RIGHT_RECEIVE, &m_exception_port);
+        if (log || err.Fail())
+            err.PutToLog(log, "::mach_port_allocate (task_self=0x%4.4x, MACH_PORT_RIGHT_RECEIVE, &m_exception_port => 0x%4.4x)",
+                         task_self, m_exception_port);
+        if (err.Fail())
+            return false;
+
+        // Add the ability to send messages on the new exception port
+        err = ::mach_port_insert_right (task_self, m_exception_port, m_exception_port, MACH_MSG_TYPE_MAKE_SEND);
+        if (log || err.Fail())
+            err.PutToLog(log, "::mach_port_insert_right (task_self=0x%4.4x, m_exception_port=0x%4.4x, m_exception_port=0x%4.4x, MACH_MSG_TYPE_MAKE_SEND)",
+                         task_self, m_exception_port, m_exception_port);
+        if (err.Fail())
+            return false;
+
+        // Save the original state of the exception ports for our child process
+        err = SaveExceptionPortInfo();
+
+        // Set the ability to get all exceptions on this port
+        err = ::task_set_exception_ports (task, EXC_MASK_ALL, m_exception_port, EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE);
+        if (log || err.Fail())
+            err.PutToLog(log, "::task_set_exception_ports (task, EXC_MASK_ALL, m_exception_port, EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE)");
+        if (err.Fail())
+            return false;
+
+        // Create the exception thread
+        char thread_name[256];
+        ::snprintf (thread_name, sizeof(thread_name), "<lldb.process.process-macosx.mach-exception-%d>", m_process->GetID());
+        m_exception_thread = Host::ThreadCreate (thread_name, MachTask::ExceptionThread, this, &err);
+
+        return err.Success();
+    }
+    return false;
+}
+
+kern_return_t
+MachTask::ShutDownExceptionThread()
+{
+    Error err;
+
+    if (m_exception_thread == NULL)
+        return KERN_SUCCESS;
+
+    err = RestoreExceptionPortInfo();
+
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_EXCEPTIONS);
+
+    // NULL our our exception port and let our exception thread exit
+    mach_port_t exception_port = m_exception_port;
+    m_exception_port = NULL;
+
+    Host::ThreadCancel (m_exception_thread, &err);
+    if (log || err.Fail())
+        err.PutToLog(log, "Host::ThreadCancel ( thread = %p )", m_exception_thread);
+
+    Host::ThreadJoin (m_exception_thread, NULL, &err);
+    if (log || err.Fail())
+        err.PutToLog(log, "Host::ThreadJoin ( thread = %p, result_ptr = NULL)", m_exception_thread);
+
+    // Deallocate our exception port that we used to track our child process
+    mach_port_t task_self = mach_task_self ();
+    err = ::mach_port_deallocate (task_self, exception_port);
+    if (log || err.Fail())
+        err.PutToLog(log, "::mach_port_deallocate ( task = 0x%4.4x, name = 0x%4.4x )", task_self, exception_port);
+    exception_port = NULL;
+
+    Clear();
+    return err.GetError();
+}
+
+
+void *
+MachTask::ExceptionThread (void *arg)
+{
+    if (arg == NULL)
+        return NULL;
+
+    MachTask *mach_task = (MachTask*) arg;
+    ProcessMacOSX *mach_proc = mach_task->Process();
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_EXCEPTIONS);
+    if (log)
+        log->Printf ("MachTask::%s (arg = %p) thread starting...", __FUNCTION__, arg);
+
+    // We keep a count of the number of consecutive exceptions received so
+    // we know to grab all exceptions without a timeout. We do this to get a
+    // bunch of related exceptions on our exception port so we can process
+    // then together. When we have multiple threads, we can get an exception
+    // per thread and they will come in consecutively. The main loop in this
+    // thread can stop periodically if needed to service things related to this
+    // process.
+    // flag set in the options, so we will wait forever for an exception on
+    // our exception port. After we get one exception, we then will use the
+    // MACH_RCV_TIMEOUT option with a zero timeout to grab all other current
+    // exceptions for our process. After we have received the last pending
+    // exception, we will get a timeout which enables us to then notify
+    // our main thread that we have an exception bundle avaiable. We then wait
+    // for the main thread to tell this exception thread to start trying to get
+    // exceptions messages again and we start again with a mach_msg read with
+    // infinite timeout.
+    uint32_t num_exceptions_received = 0;
+    Error err;
+    task_t task = mach_task->GetTaskPort();
+    mach_msg_timeout_t periodic_timeout = 1000;
+
+#if defined (__arm__)
+    mach_msg_timeout_t watchdog_elapsed = 0;
+    mach_msg_timeout_t watchdog_timeout = 60 * 1000;
+    lldb::pid_t pid = mach_proc->GetID();
+    CFReleaser<SBSWatchdogAssertionRef> watchdog;
+
+    if (mach_proc->ProcessUsingSpringBoard())
+    {
+        // Request a renewal for every 60 seconds if we attached using SpringBoard
+        watchdog.reset(::SBSWatchdogAssertionCreateForPID(NULL, pid, 60));
+        if (log)
+            log->Printf ("::SBSWatchdogAssertionCreateForPID (NULL, %4.4x, 60 ) => %p", pid, watchdog.get());
+
+        if (watchdog.get())
+        {
+            ::SBSWatchdogAssertionRenew (watchdog.get());
+
+            CFTimeInterval watchdogRenewalInterval = ::SBSWatchdogAssertionGetRenewalInterval (watchdog.get());
+            if (log)
+                log->Printf ("::SBSWatchdogAssertionGetRenewalInterval ( %p ) => %g seconds", watchdog.get(), watchdogRenewalInterval);
+            if (watchdogRenewalInterval > 0.0)
+            {
+                watchdog_timeout = (mach_msg_timeout_t)watchdogRenewalInterval * 1000;
+                if (watchdog_timeout > 3000)
+                    watchdog_timeout -= 1000;   // Give us a second to renew our timeout
+                else if (watchdog_timeout > 1000)
+                    watchdog_timeout -= 250;    // Give us a quarter of a second to renew our timeout
+            }
+        }
+        if (periodic_timeout == 0 || periodic_timeout > watchdog_timeout)
+            periodic_timeout = watchdog_timeout;
+    }
+#endif  // #if defined (__arm__)
+
+    while (mach_task->ExceptionPortIsValid())
+    {
+        //::pthread_testcancel ();
+
+        MachException::Message exception_message;
+
+
+        if (num_exceptions_received > 0)
+        {
+            // No timeout, just receive as many exceptions as we can since we already have one and we want
+            // to get all currently available exceptions for this task
+            err = exception_message.Receive(mach_task->ExceptionPort(), MACH_RCV_MSG | MACH_RCV_INTERRUPT | MACH_RCV_TIMEOUT, 0);
+        }
+        else if (periodic_timeout > 0)
+        {
+            // We need to stop periodically in this loop, so try and get a mach message with a valid timeout (ms)
+            err = exception_message.Receive(mach_task->ExceptionPort(), MACH_RCV_MSG | MACH_RCV_INTERRUPT | MACH_RCV_TIMEOUT, periodic_timeout);
+        }
+        else
+        {
+            // We don't need to parse all current exceptions or stop periodically,
+            // just wait for an exception forever.
+            err = exception_message.Receive(mach_task->ExceptionPort(), MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0);
+        }
+
+        if (err.GetError() == MACH_RCV_INTERRUPTED)
+        {
+            // If we have no task port we should exit this thread
+            if (!mach_task->ExceptionPortIsValid())
+            {
+                if (log)
+                    log->Printf ("thread cancelled...");
+                break;
+            }
+
+            // Make sure our task is still valid
+            if (MachTask::IsValid(task))
+            {
+                // Task is still ok
+                if (log)
+                    log->Printf ("interrupted, but task still valid, continuing...");
+                continue;
+            }
+            else
+            {
+                if (log)
+                    log->Printf ("task has exited...");
+                mach_proc->SetPrivateState (eStateExited);
+                // Our task has died, exit the thread.
+                break;
+            }
+        }
+        else if (err.GetError() == MACH_RCV_TIMED_OUT)
+        {
+            if (num_exceptions_received > 0)
+            {
+                // We were receiving all current exceptions with a timeout of zero
+                // it is time to go back to our normal looping mode
+                num_exceptions_received = 0;
+
+                // Notify our main thread we have a complete exception message
+                // bundle available.
+                mach_proc->ExceptionMessageBundleComplete();
+
+                // in case we use a timeout value when getting exceptions...
+                // Make sure our task is still valid
+                if (MachTask::IsValid(task))
+                {
+                    // Task is still ok
+                    if (log)
+                        log->Printf ("got a timeout, continuing...");
+                    continue;
+                }
+                else
+                {
+                    if (log)
+                        log->Printf ("task has exited...");
+                    mach_proc->SetPrivateState (eStateExited);
+                    // Our task has died, exit the thread.
+                    break;
+                }
+                continue;
+            }
+
+#if defined (__arm__)
+            if (watchdog.get())
+            {
+                watchdog_elapsed += periodic_timeout;
+                if (watchdog_elapsed >= watchdog_timeout)
+                {
+                    LogIf(PD_LOG_TASK, "SBSWatchdogAssertionRenew ( %p )", watchdog.get());
+                    ::SBSWatchdogAssertionRenew (watchdog.get());
+                    watchdog_elapsed = 0;
+                }
+            }
+#endif
+        }
+        else if (err.GetError() != KERN_SUCCESS)
+        {
+            if (log)
+                log->Printf ("got some other error, do something about it??? nah, continuing for now...");
+            // TODO: notify of error?
+        }
+        else
+        {
+            if (exception_message.CatchExceptionRaise())
+            {
+                ++num_exceptions_received;
+                mach_proc->ExceptionMessageReceived(exception_message);
+            }
+        }
+    }
+
+#if defined (__arm__)
+    if (watchdog.get())
+    {
+        // TODO: change SBSWatchdogAssertionRelease to SBSWatchdogAssertionCancel when we
+        // all are up and running on systems that support it. The SBS framework has a #define
+        // that will forward SBSWatchdogAssertionRelease to SBSWatchdogAssertionCancel for now
+        // so it should still build either way.
+        LogIf(PD_LOG_TASK, "::SBSWatchdogAssertionRelease(%p)", watchdog.get());
+        ::SBSWatchdogAssertionRelease (watchdog.get());
+    }
+#endif  // #if defined (__arm__)
+
+    if (log)
+        log->Printf ("MachTask::%s (arg = %p) thread exiting...", __FUNCTION__, arg);
+    return NULL;
+}
+
+lldb::addr_t
+MachTask::GetDYLDAllImageInfosAddress ()
+{
+#ifdef TASK_DYLD_INFO
+    task_dyld_info_data_t dyld_info;
+    mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
+    Error err;
+        // The actual task shouldn't matter for the DYLD info, so lets just use ours
+    kern_return_t kret = ::task_info (GetTaskPortForProcessID (err), TASK_DYLD_INFO, (task_info_t)&dyld_info, &count);
+    if (kret == KERN_SUCCESS)
+    {
+        // We now have the address of the all image infos structure
+        return dyld_info.all_image_info_addr;
+    }
+#endif
+    return LLDB_INVALID_ADDRESS;
+}
+
+
+
+
+
diff --git a/source/Plugins/Process/MacOSX-User/source/MacOSX/MachTask.h b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachTask.h
new file mode 100644
index 0000000..228cb7c
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachTask.h
@@ -0,0 +1,138 @@
+//===-- MachTask.h ----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __MachTask_h__
+#define __MachTask_h__
+
+// C Includes
+// C++ Includes
+#include <map>
+// Other libraries and framework includes
+#include <mach/mach.h>
+#include <mach/mach_vm.h>
+#include <sys/socket.h>
+
+// Project includes
+#include "MachException.h"
+#include "MachVMMemory.h"
+
+class ProcessMacOSX;
+
+class MachTask
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    MachTask (ProcessMacOSX *process);
+
+    virtual
+    ~MachTask ();
+
+    void
+    Clear ();
+
+    kern_return_t
+    Suspend ();
+
+    kern_return_t
+    Resume ();
+
+    int32_t
+    GetSuspendCount () const;
+
+    size_t
+    ReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error& error);
+
+    size_t
+    WriteMemory (lldb::addr_t addr, const void *buf, size_t size, lldb_private::Error& error);
+
+    lldb::addr_t
+    AllocateMemory (size_t size, uint32_t permissions, lldb_private::Error& error);
+
+    lldb_private::Error
+    DeallocateMemory (lldb::addr_t addr);
+
+    mach_port_t
+    ExceptionPort () const;
+
+    bool
+    ExceptionPortIsValid () const;
+
+    kern_return_t
+    SaveExceptionPortInfo ();
+
+    kern_return_t
+    RestoreExceptionPortInfo ();
+
+    kern_return_t
+    ShutDownExceptionThread ();
+
+    bool
+    StartExceptionThread (lldb_private::Error &err);
+
+    lldb::addr_t
+    GetDYLDAllImageInfosAddress ();
+
+    kern_return_t
+    BasicInfo (struct task_basic_info *info) const;
+
+    static kern_return_t
+    BasicInfo (task_t task, struct task_basic_info *info);
+
+    bool
+    IsValid () const;
+
+    static bool
+    IsValid (task_t task);
+
+    static void *
+    ExceptionThread (void *arg);
+
+    task_t
+    GetTaskPort () const
+    {
+        return m_task;
+    }
+
+    task_t
+    GetTaskPortForProcessID (lldb_private::Error &err);
+
+    static task_t
+    GetTaskPortForProcessID (lldb::pid_t pid, lldb_private::Error &err);
+
+    ProcessMacOSX *
+    Process ()
+    {
+        return m_process;
+    }
+
+    const ProcessMacOSX *
+    Process () const
+    {
+        return m_process;
+    }
+
+protected:
+    ProcessMacOSX * m_process;                  // The mach process that owns this MachTask
+    task_t m_task;
+    MachVMMemory m_vm_memory;                   // Special mach memory reading class that will take care of watching for page and region boundaries
+    MachException::PortInfo m_exc_port_info;    // Saved settings for all exception ports
+    lldb::thread_t m_exception_thread;          // Thread ID for the exception thread in case we need it
+    mach_port_t m_exception_port;               // Exception port on which we will receive child exceptions
+
+    // Maybe sort this by address and use find?
+    typedef std::map<vm_address_t,size_t> allocation_collection;
+    allocation_collection m_allocations;
+
+private:
+    DISALLOW_COPY_AND_ASSIGN (MachTask);
+};
+
+#endif  // __MachTask_h__
diff --git a/source/Plugins/Process/MacOSX-User/source/MacOSX/MachThreadContext.h b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachThreadContext.h
new file mode 100644
index 0000000..3166c28
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachThreadContext.h
@@ -0,0 +1,48 @@
+//===-- MachThreadContext.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_MachThreadContext_h_
+#define liblldb_MachThreadContext_h_
+
+#include <vector>
+
+#include "MachException.h"
+
+class ThreadMacOSX;
+
+class MachThreadContext
+{
+public:
+    MachThreadContext (ThreadMacOSX &thread) :
+        m_thread (thread)
+    {
+    }
+
+    virtual ~MachThreadContext()
+    {
+    }
+
+    virtual lldb_private::RegisterContext *
+    CreateRegisterContext (lldb_private::StackFrame *frame) const = 0;
+
+    virtual void            InitializeInstance() = 0;
+    virtual void            ThreadWillResume () = 0;
+    virtual bool            ShouldStop () = 0;
+    virtual void            RefreshStateAfterStop() = 0;
+    virtual bool            NotifyException (MachException::Data& exc) { return false; }
+    virtual bool            StepNotComplete () { return false; }
+    virtual size_t          GetStackFrameData(lldb_private::StackFrame *frame, std::vector<std::pair<lldb::addr_t, lldb::addr_t> >& fp_pc_pairs) { return 0; }
+//  virtual const uint8_t * SoftwareBreakpointOpcode (size_t byte_size) = 0;
+
+protected:
+    ThreadMacOSX &m_thread;
+
+};
+
+#endif  // #ifndef liblldb_MachThreadContext_h_
diff --git a/source/Plugins/Process/MacOSX-User/source/MacOSX/MachThreadContext_arm.cpp b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachThreadContext_arm.cpp
new file mode 100644
index 0000000..4f6b17c
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachThreadContext_arm.cpp
@@ -0,0 +1,1884 @@
+//===-- MachThreadContext_arm.cpp -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MachThreadContext_arm.h"
+
+#include <sys/sysctl.h>
+
+#include "ProcessMacOSX.h"
+#include "ProcessMacOSXLog.h"
+#include "ThreadMacOSX.h"
+
+using namespace lldb_private;
+
+//#define DNB_ARCH_MACH_ARM_DEBUG_SW_STEP 1
+
+static const uint8_t g_arm_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 };
+static const uint8_t g_thumb_breakpooint_opcode[] = { 0xFE, 0xDE };
+
+// ARM constants used during decoding
+#define REG_RD          0
+#define LDM_REGLIST     1
+#define PC_REG          15
+#define PC_REGLIST_BIT  0x8000
+
+// ARM conditions
+#define COND_EQ     0x0
+#define COND_NE     0x1
+#define COND_CS     0x2
+#define COND_HS     0x2
+#define COND_CC     0x3
+#define COND_LO     0x3
+#define COND_MI     0x4
+#define COND_PL     0x5
+#define COND_VS     0x6
+#define COND_VC     0x7
+#define COND_HI     0x8
+#define COND_LS     0x9
+#define COND_GE     0xA
+#define COND_LT     0xB
+#define COND_GT     0xC
+#define COND_LE     0xD
+#define COND_AL     0xE
+#define COND_UNCOND 0xF
+
+#define MASK_CPSR_T (1u << 5)
+#define MASK_CPSR_J (1u << 24)
+
+#define MNEMONIC_STRING_SIZE 32
+#define OPERAND_STRING_SIZE 128
+
+using namespace lldb;
+using namespace lldb_private;
+
+MachThreadContext_arm::MachThreadContext_arm(ThreadMacOSX &thread) :
+    MachThreadContext(thread),
+    m_hw_single_chained_step_addr(LLDB_INVALID_ADDRESS),
+    m_bvr0_reg (LLDB_INVALID_REGNUM),
+    m_bcr0_reg (LLDB_INVALID_REGNUM),
+    m_bvr0_save (0),
+    m_bcr0_save (0)
+{
+}
+
+MachThreadContext_arm::~MachThreadContext_arm()
+{
+}
+
+RegisterContext *
+MachThreadContext_arm::CreateRegisterContext (StackFrame *frame) const
+{
+    return new RegisterContextMach_arm(m_thread, frame);
+}
+
+// Instance init function
+void
+MachThreadContext_arm::InitializeInstance()
+{
+    RegisterContext *reg_ctx = m_thread.GetRegisterContext();
+    assert (reg_ctx != NULL);
+    const RegisterInfo * reg_info;
+    reg_info = reg_ctx->GetRegisterInfoByName ("bvr0");
+    if (reg_info)
+        m_bvr0_reg = reg_info->reg;
+
+    reg_info = reg_ctx->GetRegisterInfoByName ("bcr0");
+    if (reg_info)
+        m_bcr0_reg = reg_info->reg;
+}
+
+
+
+uint32_t
+MachThreadContext_arm::GetCPUType()
+{
+    return CPU_TYPE_ARM;
+}
+
+void
+MachThreadContext_arm::ThreadWillResume()
+{
+    // Do we need to step this thread? If so, let the mach thread tell us so.
+    if (m_thread.GetState() == eStateStepping)
+    {
+        bool step_handled = false;
+        // This is the primary thread, let the arch do anything it needs
+        if (m_thread.GetRegisterContext()->NumSupportedHardwareBreakpoints() > 0)
+        {
+#if defined (DNB_ARCH_MACH_ARM_DEBUG_SW_STEP)
+            bool half_step = m_hw_single_chained_step_addr != LLDB_INVALID_ADDRESS;
+#endif
+            step_handled = EnableHardwareSingleStep(true) == KERN_SUCCESS;
+#if defined (DNB_ARCH_MACH_ARM_DEBUG_SW_STEP)
+            if (!half_step)
+                step_handled = false;
+#endif
+        }
+
+#if defined (ENABLE_ARM_SINGLE_STEP)
+        if (!step_handled)
+        {
+            SetSingleStepSoftwareBreakpoints();
+        }
+#endif
+    }
+}
+
+bool
+MachThreadContext_arm::ShouldStop ()
+{
+    return true;
+}
+
+void
+MachThreadContext_arm::RefreshStateAfterStop ()
+{
+    EnableHardwareSingleStep (false) == KERN_SUCCESS;
+}
+
+#if defined (ENABLE_ARM_SINGLE_STEP)
+
+bool
+MachThreadContext_arm::ShouldStop ()
+{
+    return true;
+}
+
+bool
+MachThreadContext_arm::RefreshStateAfterStop ()
+{
+    success = EnableHardwareSingleStep(false) == KERN_SUCCESS;
+
+    bool success = true;
+
+    m_state.InvalidateRegisterSet (GPRRegSet);
+    m_state.InvalidateRegisterSet (VFPRegSet);
+    m_state.InvalidateRegisterSet (EXCRegSet);
+
+    // Are we stepping a single instruction?
+    if (ReadGPRRegisters(true) == KERN_SUCCESS)
+    {
+        // We are single stepping, was this the primary thread?
+        if (m_thread.GetState() == eStateStepping)
+        {
+#if defined (DNB_ARCH_MACH_ARM_DEBUG_SW_STEP)
+            success = EnableHardwareSingleStep(false) == KERN_SUCCESS;
+            // Hardware single step must work if we are going to test software
+            // single step functionality
+            assert(success);
+            if (m_hw_single_chained_step_addr == LLDB_INVALID_ADDRESS && m_sw_single_step_next_pc != LLDB_INVALID_ADDRESS)
+            {
+                uint32_t sw_step_next_pc = m_sw_single_step_next_pc & 0xFFFFFFFEu;
+                bool sw_step_next_pc_is_thumb = (m_sw_single_step_next_pc & 1) != 0;
+                bool actual_next_pc_is_thumb = (m_state.gpr.__cpsr & 0x20) != 0;
+                if (m_state.gpr.r[15] != sw_step_next_pc)
+                {
+                    LogError("curr pc = 0x%8.8x - calculated single step target PC was incorrect: 0x%8.8x != 0x%8.8x", m_state.gpr.r[15], sw_step_next_pc, m_state.gpr.r[15]);
+                    exit(1);
+                }
+                if (actual_next_pc_is_thumb != sw_step_next_pc_is_thumb)
+                {
+                    LogError("curr pc = 0x%8.8x - calculated single step calculated mode mismatch: sw single mode = %s != %s",
+                                m_state.gpr.r[15],
+                                actual_next_pc_is_thumb ? "Thumb" : "ARM",
+                                sw_step_next_pc_is_thumb ? "Thumb" : "ARM");
+                    exit(1);
+                }
+                m_sw_single_step_next_pc = LLDB_INVALID_ADDRESS;
+            }
+#else
+#if defined (ENABLE_ARM_SINGLE_STEP)
+            // Are we software single stepping?
+            if (LLDB_BREAK_ID_IS_VALID(m_sw_single_step_break_id) || m_sw_single_step_itblock_break_count)
+            {
+                // Remove any software single stepping breakpoints that we have set
+
+                // Do we have a normal software single step breakpoint?
+                if (LLDB_BREAK_ID_IS_VALID(m_sw_single_step_break_id))
+                {
+                    ProcessMacOSXLog::LogIf(PD_LOG_STEP, "%s: removing software single step breakpoint (breakID=%d)", __FUNCTION__, m_sw_single_step_break_id);
+                    success = m_thread.Process()->DisableBreakpoint(m_sw_single_step_break_id, true);
+                    m_sw_single_step_break_id = LLDB_INVALID_BREAK_ID;
+                }
+
+                // Do we have any Thumb IT breakpoints?
+                if (m_sw_single_step_itblock_break_count > 0)
+                {
+                    // See if we hit one of our Thumb IT breakpoints?
+                    DNBBreakpoint *step_bp = m_thread.Process()->Breakpoints().FindByAddress(m_state.gpr.r[15]);
+
+                    if (step_bp)
+                    {
+                        // We did hit our breakpoint, tell the breakpoint it was
+                        // hit so that it can run its callback routine and fixup
+                        // the PC.
+                        ProcessMacOSXLog::LogIf(PD_LOG_STEP, "%s: IT software single step breakpoint hit (breakID=%u)", __FUNCTION__, step_bp->GetID());
+                        step_bp->BreakpointHit(m_thread.Process()->ProcessID(), m_thread.GetID());
+                    }
+
+                    // Remove all Thumb IT breakpoints
+                    for (int i = 0; i < m_sw_single_step_itblock_break_count; i++)
+                    {
+                        if (LLDB_BREAK_ID_IS_VALID(m_sw_single_step_itblock_break_id[i]))
+                        {
+                            ProcessMacOSXLog::LogIf(PD_LOG_STEP, "%s: removing IT software single step breakpoint (breakID=%d)", __FUNCTION__, m_sw_single_step_itblock_break_id[i]);
+                            success = m_thread.Process()->DisableBreakpoint(m_sw_single_step_itblock_break_id[i], true);
+                            m_sw_single_step_itblock_break_id[i] = LLDB_INVALID_BREAK_ID;
+                        }
+                    }
+                    m_sw_single_step_itblock_break_count = 0;
+
+                    // Decode instructions up to the current PC to ensure the internal decoder state is valid for the IT block
+                    // The decoder has to decode each instruction in the IT block even if it is not executed so that
+                    // the fields are correctly updated
+                    DecodeITBlockInstructions(m_state.gpr.r[15]);
+                }
+
+            }
+            else
+#endif
+                success = EnableHardwareSingleStep(false) == KERN_SUCCESS;
+#endif
+        }
+        else
+        {
+            // The MachThread will automatically restore the suspend count
+            // in ShouldStop (), so we don't need to do anything here if
+            // we weren't the primary thread the last time
+        }
+    }
+    return;
+}
+
+
+
+bool
+MachThreadContext_arm::StepNotComplete ()
+{
+    if (m_hw_single_chained_step_addr != LLDB_INVALID_ADDRESS)
+    {
+        kern_return_t kret = KERN_INVALID_ARGUMENT;
+        kret = ReadGPRRegisters(false);
+        if (kret == KERN_SUCCESS)
+        {
+            if (m_state.gpr.r[15] == m_hw_single_chained_step_addr)
+            {
+                //ProcessMacOSXLog::LogIf(PD_LOG_STEP, "Need to step some more at 0x%8.8x", m_hw_single_chained_step_addr);
+                return true;
+            }
+        }
+    }
+
+    m_hw_single_chained_step_addr = LLDB_INVALID_ADDRESS;
+    return false;
+}
+
+
+void
+MachThreadContext_arm::DecodeITBlockInstructions(lldb::addr_t curr_pc)
+
+{
+    uint16_t opcode16;
+    uint32_t opcode32;
+    lldb::addr_t next_pc_in_itblock;
+    lldb::addr_t pc_in_itblock = m_last_decode_pc;
+
+    ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: last_decode_pc=0x%8.8x", __FUNCTION__, m_last_decode_pc);
+
+    // Decode IT block instruction from the instruction following the m_last_decoded_instruction at
+    // PC m_last_decode_pc upto and including the instruction at curr_pc
+    if (m_thread.Process()->Task().ReadMemory(pc_in_itblock, 2, &opcode16) == 2)
+    {
+        opcode32 = opcode16;
+        pc_in_itblock += 2;
+        // Check for 32 bit thumb opcode and read the upper 16 bits if needed
+        if (((opcode32 & 0xE000) == 0xE000) && opcode32 & 0x1800)
+        {
+            // Adjust 'next_pc_in_itblock' to point to the default next Thumb instruction for
+            // a 32 bit Thumb opcode
+            // Read bits 31:16 of a 32 bit Thumb opcode
+            if (m_thread.Process()->Task().ReadMemory(pc_in_itblock, 2, &opcode16) == 2)
+            {
+                pc_in_itblock += 2;
+                // 32 bit thumb opcode
+                opcode32 = (opcode32 << 16) | opcode16;
+            }
+            else
+            {
+                LogError("%s: Unable to read opcode bits 31:16 for a 32 bit thumb opcode at pc=0x%8.8lx", __FUNCTION__, pc_in_itblock);
+            }
+        }
+    }
+    else
+    {
+        LogError("%s: Error reading 16-bit Thumb instruction at pc=0x%8.8x", __FUNCTION__, pc_in_itblock);
+    }
+
+    ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: pc_in_itblock=0x%8.8x, curr_pc=0x%8.8x", __FUNCTION__, pc_in_itblock, curr_pc);
+
+    next_pc_in_itblock = pc_in_itblock;
+    while (next_pc_in_itblock <= curr_pc)
+    {
+        arm_error_t decodeError;
+
+        m_last_decode_pc = pc_in_itblock;
+        decodeError = DecodeInstructionUsingDisassembler(pc_in_itblock, m_state.gpr.__cpsr, &m_last_decode_arm, &m_last_decode_thumb, &next_pc_in_itblock);
+
+        pc_in_itblock = next_pc_in_itblock;
+        ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: next_pc_in_itblock=0x%8.8x", __FUNCTION__, next_pc_in_itblock);
+    }
+}
+
+#endif
+
+// Set the single step bit in the processor status register.
+kern_return_t
+MachThreadContext_arm::EnableHardwareSingleStep (bool enable)
+{
+    Error err;
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_STEP);
+
+    if (log) log->Printf("%s( enable = %d )", __FUNCTION__, enable);
+
+    if (m_bvr0_reg == LLDB_INVALID_REGNUM || m_bcr0_reg == LLDB_INVALID_REGNUM)
+        return KERN_INVALID_ARGUMENT;
+
+    RegisterContext *reg_ctx = m_thread.GetRegisterContext();
+    uint32_t bvr = 0;
+    uint32_t bcr = 0;
+
+    const uint32_t i = 0;
+    if (enable)
+    {
+        m_hw_single_chained_step_addr = LLDB_INVALID_ADDRESS;
+
+        // Save our previous state
+        m_bvr0_save = reg_ctx->ReadRegisterAsUnsigned(m_bvr0_reg, 0);
+        m_bcr0_save = reg_ctx->ReadRegisterAsUnsigned(m_bcr0_reg, 0);
+        lldb::addr_t pc = reg_ctx->GetPC(LLDB_INVALID_ADDRESS);
+        lldb::addr_t cpsr = reg_ctx->GetFlags(0);
+        if (pc == LLDB_INVALID_ADDRESS)
+            return KERN_INVALID_ARGUMENT;
+
+        // Set a breakpoint that will stop when the PC doesn't match the current one!
+        bvr = pc & 0xFFFFFFFCu;     // Set the current PC as the breakpoint address
+        bcr = BCR_M_IMVA_MISMATCH | // Stop on address mismatch
+              S_USER |                  // Stop only in user mode
+              BCR_ENABLE;               // Enable this breakpoint
+        if (cpsr & 0x20)
+        {
+            // Thumb breakpoint
+            if (pc & 2)
+                bcr |= BAS_IMVA_2_3;
+            else
+                bcr |= BAS_IMVA_0_1;
+
+            uint16_t opcode;
+            Error error;
+            if (sizeof(opcode) == m_thread.GetProcess().ReadMemory(pc, &opcode, sizeof(opcode), error))
+            {
+                if (((opcode & 0xE000) == 0xE000) && opcode & 0x1800)
+                {
+                    // 32 bit thumb opcode...
+                    if (pc & 2)
+                    {
+                        // We can't take care of a 32 bit thumb instruction single step
+                        // with just IVA mismatching. We will need to chain an extra
+                        // hardware single step in order to complete this single step...
+                        m_hw_single_chained_step_addr = pc + 2;
+                    }
+                    else
+                    {
+                        // Extend the number of bits to ignore for the mismatch
+                        bcr |= BAS_IMVA_ALL;
+                    }
+                }
+            }
+        }
+        else
+        {
+            // ARM breakpoint
+            bcr |= BAS_IMVA_ALL; // Stop when any address bits change
+        }
+
+        ProcessMacOSXLog::LogIf(PD_LOG_STEP, "%s: BVR%u=0x%8.8x  BCR%u=0x%8.8x", __FUNCTION__, i, bvr, i, bcr);
+
+        m_bvr0_save = reg_ctx->ReadRegisterAsUnsigned(m_bvr0_reg, 0);
+        m_bcr0_save = reg_ctx->ReadRegisterAsUnsigned(m_bcr0_reg, 0);
+
+//        for (uint32_t j=i+1; j<16; ++j)
+//        {
+//          // Disable all others
+//          m_state.dbg.bvr[j] = 0;
+//          m_state.dbg.bcr[j] = 0;
+//        }
+    }
+    else
+    {
+        // Just restore the state we had before we did single stepping
+        bvr = m_bvr0_save;
+        bcr = m_bcr0_save;
+    }
+
+    if (reg_ctx->WriteRegisterFromUnsigned(m_bvr0_reg, bvr) &&
+        reg_ctx->WriteRegisterFromUnsigned(m_bcr0_reg, bcr))
+        return KERN_SUCCESS;
+
+    return KERN_INVALID_ARGUMENT;
+}
+
+#if defined (ENABLE_ARM_SINGLE_STEP)
+
+// return 1 if bit "BIT" is set in "value"
+static inline uint32_t bit(uint32_t value, uint32_t bit)
+{
+    return (value >> bit) & 1u;
+}
+
+// return the bitfield "value[msbit:lsbit]".
+static inline uint32_t bits(uint32_t value, uint32_t msbit, uint32_t lsbit)
+{
+    assert(msbit >= lsbit);
+    uint32_t shift_left = sizeof(value) * 8 - 1 - msbit;
+    value <<= shift_left;           // shift anything above the msbit off of the unsigned edge
+    value >>= shift_left + lsbit;   // shift it back again down to the lsbit (including undoing any shift from above)
+    return value;                   // return our result
+}
+
+bool
+MachThreadContext_arm::ConditionPassed(uint8_t condition, uint32_t cpsr)
+{
+    uint32_t cpsr_n = bit(cpsr, 31); // Negative condition code flag
+    uint32_t cpsr_z = bit(cpsr, 30); // Zero condition code flag
+    uint32_t cpsr_c = bit(cpsr, 29); // Carry condition code flag
+    uint32_t cpsr_v = bit(cpsr, 28); // Overflow condition code flag
+
+    switch (condition) {
+        case COND_EQ: // (0x0)
+            if (cpsr_z == 1) return true;
+            break;
+        case COND_NE: // (0x1)
+            if (cpsr_z == 0) return true;
+            break;
+        case COND_CS: // (0x2)
+            if (cpsr_c == 1) return true;
+            break;
+        case COND_CC: // (0x3)
+            if (cpsr_c == 0) return true;
+            break;
+        case COND_MI: // (0x4)
+            if (cpsr_n == 1) return true;
+            break;
+        case COND_PL: // (0x5)
+            if (cpsr_n == 0) return true;
+            break;
+        case COND_VS: // (0x6)
+            if (cpsr_v == 1) return true;
+            break;
+        case COND_VC: // (0x7)
+            if (cpsr_v == 0) return true;
+            break;
+        case COND_HI: // (0x8)
+            if ((cpsr_c == 1) && (cpsr_z == 0)) return true;
+            break;
+        case COND_LS: // (0x9)
+            if ((cpsr_c == 0) || (cpsr_z == 1)) return true;
+            break;
+        case COND_GE: // (0xA)
+            if (cpsr_n == cpsr_v) return true;
+            break;
+        case COND_LT: // (0xB)
+            if (cpsr_n != cpsr_v) return true;
+            break;
+        case COND_GT: // (0xC)
+            if ((cpsr_z == 0) && (cpsr_n == cpsr_v)) return true;
+            break;
+        case COND_LE: // (0xD)
+            if ((cpsr_z == 1) || (cpsr_n != cpsr_v)) return true;
+            break;
+        default:
+            return true;
+            break;
+    }
+
+    return false;
+}
+
+bool
+MachThreadContext_arm::ComputeNextPC(lldb::addr_t currentPC, arm_decoded_instruction_t decodedInstruction, bool currentPCIsThumb, lldb::addr_t *targetPC)
+{
+    lldb::addr_t myTargetPC, addressWherePCLives;
+    lldb::pid_t mypid;
+
+    uint32_t cpsr_c = bit(m_state.gpr.cpsr, 29); // Carry condition code flag
+
+    uint32_t firstOperand=0, secondOperand=0, shiftAmount=0, secondOperandAfterShift=0, immediateValue=0;
+    uint32_t halfwords=0, baseAddress=0, immediateOffset=0, addressOffsetFromRegister=0, addressOffsetFromRegisterAfterShift;
+    uint32_t baseAddressIndex=LLDB_INVALID_INDEX32;
+    uint32_t firstOperandIndex=LLDB_INVALID_INDEX32;
+    uint32_t secondOperandIndex=LLDB_INVALID_INDEX32;
+    uint32_t addressOffsetFromRegisterIndex=LLDB_INVALID_INDEX32;
+    uint32_t shiftRegisterIndex=LLDB_INVALID_INDEX32;
+    uint16_t registerList16, registerList16NoPC;
+    uint8_t registerList8;
+    uint32_t numRegistersToLoad=0;
+
+    ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: instruction->code=%d", __FUNCTION__, decodedInstruction.instruction->code);
+
+    // Get the following in this switch statement:
+    //   - firstOperand, secondOperand, immediateValue, shiftAmount: For arithmetic, logical and move instructions
+    //   - baseAddress, immediateOffset, shiftAmount: For LDR
+    //   - numRegistersToLoad: For LDM and POP instructions
+    switch (decodedInstruction.instruction->code)
+    {
+            // Arithmetic operations that can change the PC
+        case ARM_INST_ADC:
+        case ARM_INST_ADCS:
+        case ARM_INST_ADD:
+        case ARM_INST_ADDS:
+        case ARM_INST_AND:
+        case ARM_INST_ANDS:
+        case ARM_INST_ASR:
+        case ARM_INST_ASRS:
+        case ARM_INST_BIC:
+        case ARM_INST_BICS:
+        case ARM_INST_EOR:
+        case ARM_INST_EORS:
+        case ARM_INST_ORR:
+        case ARM_INST_ORRS:
+        case ARM_INST_RSB:
+        case ARM_INST_RSBS:
+        case ARM_INST_RSC:
+        case ARM_INST_RSCS:
+        case ARM_INST_SBC:
+        case ARM_INST_SBCS:
+        case ARM_INST_SUB:
+        case ARM_INST_SUBS:
+            switch (decodedInstruction.addressMode)
+            {
+                case ARM_ADDR_DATA_IMM:
+                    if (decodedInstruction.numOperands != 3)
+                    {
+                        LogError("Expected 3 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
+                        return false;
+                    }
+
+                    if (decodedInstruction.op[0].value != PC_REG)
+                    {
+                        LogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
+                        return false;
+                    }
+
+                    // Get firstOperand register value (at index=1)
+                    firstOperandIndex = decodedInstruction.op[1].value; // first operand register index
+                    firstOperand = m_state.gpr.r[firstOperandIndex];
+
+                    // Get immediateValue (at index=2)
+                    immediateValue = decodedInstruction.op[2].value;
+
+                    break;
+
+                case ARM_ADDR_DATA_REG:
+                    if (decodedInstruction.numOperands != 3)
+                    {
+                        LogError("Expected 3 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
+                        return false;
+                    }
+
+                    if (decodedInstruction.op[0].value != PC_REG)
+                    {
+                        LogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
+                        return false;
+                    }
+
+                    // Get firstOperand register value (at index=1)
+                    firstOperandIndex = decodedInstruction.op[1].value; // first operand register index
+                    firstOperand = m_state.gpr.r[firstOperandIndex];
+
+                    // Get secondOperand register value (at index=2)
+                    secondOperandIndex = decodedInstruction.op[2].value; // second operand register index
+                    secondOperand = m_state.gpr.r[secondOperandIndex];
+
+                    break;
+
+                case ARM_ADDR_DATA_SCALED_IMM:
+                    if (decodedInstruction.numOperands != 4)
+                    {
+                        LogError("Expected 4 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
+                        return false;
+                    }
+
+                    if (decodedInstruction.op[0].value != PC_REG)
+                    {
+                        LogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
+                        return false;
+                    }
+
+                    // Get firstOperand register value (at index=1)
+                    firstOperandIndex = decodedInstruction.op[1].value; // first operand register index
+                    firstOperand = m_state.gpr.r[firstOperandIndex];
+
+                    // Get secondOperand register value (at index=2)
+                    secondOperandIndex = decodedInstruction.op[2].value; // second operand register index
+                    secondOperand = m_state.gpr.r[secondOperandIndex];
+
+                    // Get shiftAmount as immediate value (at index=3)
+                    shiftAmount = decodedInstruction.op[3].value;
+
+                    break;
+
+
+                case ARM_ADDR_DATA_SCALED_REG:
+                    if (decodedInstruction.numOperands != 4)
+                    {
+                        LogError("Expected 4 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
+                        return false;
+                    }
+
+                    if (decodedInstruction.op[0].value != PC_REG)
+                    {
+                        LogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
+                        return false;
+                    }
+
+                    // Get firstOperand register value (at index=1)
+                    firstOperandIndex = decodedInstruction.op[1].value; // first operand register index
+                    firstOperand = m_state.gpr.r[firstOperandIndex];
+
+                    // Get secondOperand register value (at index=2)
+                    secondOperandIndex = decodedInstruction.op[2].value; // second operand register index
+                    secondOperand = m_state.gpr.r[secondOperandIndex];
+
+                    // Get shiftAmount from register (at index=3)
+                    shiftRegisterIndex = decodedInstruction.op[3].value; // second operand register index
+                    shiftAmount = m_state.gpr.r[shiftRegisterIndex];
+
+                    break;
+
+                case THUMB_ADDR_HR_HR:
+                    if (decodedInstruction.numOperands != 2)
+                    {
+                        LogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
+                        return false;
+                    }
+
+                    if (decodedInstruction.op[0].value != PC_REG)
+                    {
+                        LogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
+                        return false;
+                    }
+
+                    // Get firstOperand register value (at index=0)
+                    firstOperandIndex = decodedInstruction.op[0].value; // first operand register index
+                    firstOperand = m_state.gpr.r[firstOperandIndex];
+
+                    // Get secondOperand register value (at index=1)
+                    secondOperandIndex = decodedInstruction.op[1].value; // second operand register index
+                    secondOperand = m_state.gpr.r[secondOperandIndex];
+
+                    break;
+
+                default:
+                    break;
+            }
+            break;
+
+            // Logical shifts and move operations that can change the PC
+        case ARM_INST_LSL:
+        case ARM_INST_LSLS:
+        case ARM_INST_LSR:
+        case ARM_INST_LSRS:
+        case ARM_INST_MOV:
+        case ARM_INST_MOVS:
+        case ARM_INST_MVN:
+        case ARM_INST_MVNS:
+        case ARM_INST_ROR:
+        case ARM_INST_RORS:
+        case ARM_INST_RRX:
+        case ARM_INST_RRXS:
+            // In these cases, the firstOperand is always 0, as if it does not exist
+            switch (decodedInstruction.addressMode)
+            {
+                case ARM_ADDR_DATA_IMM:
+                    if (decodedInstruction.numOperands != 2)
+                    {
+                        LogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
+                        return false;
+                    }
+
+                    if (decodedInstruction.op[0].value != PC_REG)
+                    {
+                        LogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
+                        return false;
+                    }
+
+                    // Get immediateValue (at index=1)
+                    immediateValue = decodedInstruction.op[1].value;
+
+                    break;
+
+                case ARM_ADDR_DATA_REG:
+                    if (decodedInstruction.numOperands != 2)
+                    {
+                        LogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
+                        return false;
+                    }
+
+                    if (decodedInstruction.op[0].value != PC_REG)
+                    {
+                        LogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
+                        return false;
+                    }
+
+                    // Get secondOperand register value (at index=1)
+                    secondOperandIndex = decodedInstruction.op[1].value; // second operand register index
+                    secondOperand = m_state.gpr.r[secondOperandIndex];
+
+                    break;
+
+                case ARM_ADDR_DATA_SCALED_IMM:
+                    if (decodedInstruction.numOperands != 3)
+                    {
+                        LogError("Expected 4 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
+                        return false;
+                    }
+
+                    if (decodedInstruction.op[0].value != PC_REG)
+                    {
+                        LogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
+                        return false;
+                    }
+
+                    // Get secondOperand register value (at index=1)
+                    secondOperandIndex = decodedInstruction.op[2].value; // second operand register index
+                    secondOperand = m_state.gpr.r[secondOperandIndex];
+
+                    // Get shiftAmount as immediate value (at index=2)
+                    shiftAmount = decodedInstruction.op[2].value;
+
+                    break;
+
+
+                case ARM_ADDR_DATA_SCALED_REG:
+                    if (decodedInstruction.numOperands != 3)
+                    {
+                        LogError("Expected 3 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
+                        return false;
+                    }
+
+                    if (decodedInstruction.op[0].value != PC_REG)
+                    {
+                        LogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
+                        return false;
+                    }
+
+                    // Get secondOperand register value (at index=1)
+                    secondOperandIndex = decodedInstruction.op[1].value; // second operand register index
+                    secondOperand = m_state.gpr.r[secondOperandIndex];
+
+                    // Get shiftAmount from register (at index=2)
+                    shiftRegisterIndex = decodedInstruction.op[2].value; // second operand register index
+                    shiftAmount = m_state.gpr.r[shiftRegisterIndex];
+
+                    break;
+
+                case THUMB_ADDR_HR_HR:
+                    if (decodedInstruction.numOperands != 2)
+                    {
+                        LogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
+                        return false;
+                    }
+
+                    if (decodedInstruction.op[0].value != PC_REG)
+                    {
+                        LogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
+                        return false;
+                    }
+
+                    // Get secondOperand register value (at index=1)
+                    secondOperandIndex = decodedInstruction.op[1].value; // second operand register index
+                    secondOperand = m_state.gpr.r[secondOperandIndex];
+
+                    break;
+
+                default:
+                    break;
+            }
+
+            break;
+
+            // Simple branches, used to hop around within a routine
+        case ARM_INST_B:
+            *targetPC = decodedInstruction.targetPC; // Known targetPC
+            return true;
+            break;
+
+            // Branch-and-link, used to call ARM subroutines
+        case ARM_INST_BL:
+            *targetPC = decodedInstruction.targetPC; // Known targetPC
+            return true;
+            break;
+
+            // Branch-and-link with exchange, used to call opposite-mode subroutines
+        case ARM_INST_BLX:
+            if ((decodedInstruction.addressMode == ARM_ADDR_BRANCH_IMM) ||
+                (decodedInstruction.addressMode == THUMB_ADDR_UNCOND))
+            {
+                *targetPC = decodedInstruction.targetPC; // Known targetPC
+                return true;
+            }
+            else    // addressMode == ARM_ADDR_BRANCH_REG
+            {
+                // Unknown target unless we're branching to the PC itself,
+                //  although this may not work properly with BLX
+                if (decodedInstruction.op[REG_RD].value == PC_REG)
+                {
+                    // this should (almost) never happen
+                    *targetPC = decodedInstruction.targetPC; // Known targetPC
+                    return true;
+                }
+
+                // Get the branch address and return
+                if (decodedInstruction.numOperands != 1)
+                {
+                    LogError("Expected 1 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
+                    return false;
+                }
+
+                // Get branch address in register (at index=0)
+                *targetPC = m_state.gpr.r[decodedInstruction.op[0].value];
+                return true;
+            }
+            break;
+
+            // Branch with exchange, used to hop to opposite-mode code
+            // Branch to Jazelle code, used to execute Java; included here since it
+            //  acts just like BX unless the Jazelle unit is active and JPC is
+            //  already loaded into it.
+        case ARM_INST_BX:
+        case ARM_INST_BXJ:
+            // Unknown target unless we're branching to the PC itself,
+            //  although this can never switch to Thumb mode and is
+            //  therefore pretty much useless
+            if (decodedInstruction.op[REG_RD].value == PC_REG)
+            {
+                // this should (almost) never happen
+                *targetPC = decodedInstruction.targetPC; // Known targetPC
+                return true;
+            }
+
+            // Get the branch address and return
+            if (decodedInstruction.numOperands != 1)
+            {
+                LogError("Expected 1 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
+                return false;
+            }
+
+            // Get branch address in register (at index=0)
+            *targetPC = m_state.gpr.r[decodedInstruction.op[0].value];
+            return true;
+            break;
+
+            // Compare and branch on zero/non-zero (Thumb-16 only)
+            // Unusual condition check built into the instruction
+        case ARM_INST_CBZ:
+        case ARM_INST_CBNZ:
+            // Branch address is known at compile time
+            // Get the branch address and return
+            if (decodedInstruction.numOperands != 2)
+            {
+                LogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
+                return false;
+            }
+
+            // Get branch address as an immediate value (at index=1)
+            *targetPC = decodedInstruction.op[1].value;
+            return true;
+            break;
+
+            // Load register can be used to load PC, usually with a function pointer
+        case ARM_INST_LDR:
+            if (decodedInstruction.op[REG_RD].value != PC_REG)
+            {
+                LogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
+                return false;
+            }
+            switch (decodedInstruction.addressMode)
+            {
+                case ARM_ADDR_LSWUB_IMM:
+                case ARM_ADDR_LSWUB_IMM_PRE:
+                case ARM_ADDR_LSWUB_IMM_POST:
+                    if (decodedInstruction.numOperands != 3)
+                    {
+                        LogError("Expected 3 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
+                        return false;
+                    }
+
+                    // Get baseAddress from register (at index=1)
+                    baseAddressIndex = decodedInstruction.op[1].value;
+                    baseAddress = m_state.gpr.r[baseAddressIndex];
+
+                    // Get immediateOffset (at index=2)
+                    immediateOffset = decodedInstruction.op[2].value;
+                    break;
+
+                case ARM_ADDR_LSWUB_REG:
+                case ARM_ADDR_LSWUB_REG_PRE:
+                case ARM_ADDR_LSWUB_REG_POST:
+                    if (decodedInstruction.numOperands != 3)
+                    {
+                        LogError("Expected 3 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
+                        return false;
+                    }
+
+                    // Get baseAddress from register (at index=1)
+                    baseAddressIndex = decodedInstruction.op[1].value;
+                    baseAddress = m_state.gpr.r[baseAddressIndex];
+
+                    // Get immediateOffset from register (at index=2)
+                    addressOffsetFromRegisterIndex = decodedInstruction.op[2].value;
+                    addressOffsetFromRegister = m_state.gpr.r[addressOffsetFromRegisterIndex];
+
+                    break;
+
+                case ARM_ADDR_LSWUB_SCALED:
+                case ARM_ADDR_LSWUB_SCALED_PRE:
+                case ARM_ADDR_LSWUB_SCALED_POST:
+                    if (decodedInstruction.numOperands != 4)
+                    {
+                        LogError("Expected 4 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
+                        return false;
+                    }
+
+                    // Get baseAddress from register (at index=1)
+                    baseAddressIndex = decodedInstruction.op[1].value;
+                    baseAddress = m_state.gpr.r[baseAddressIndex];
+
+                    // Get immediateOffset from register (at index=2)
+                    addressOffsetFromRegisterIndex = decodedInstruction.op[2].value;
+                    addressOffsetFromRegister = m_state.gpr.r[addressOffsetFromRegisterIndex];
+
+                    // Get shiftAmount (at index=3)
+                    shiftAmount = decodedInstruction.op[3].value;
+
+                    break;
+
+                default:
+                    break;
+            }
+            break;
+
+            // 32b load multiple operations can load the PC along with everything else,
+            //  usually to return from a function call
+        case ARM_INST_LDMDA:
+        case ARM_INST_LDMDB:
+        case ARM_INST_LDMIA:
+        case ARM_INST_LDMIB:
+            if (decodedInstruction.op[LDM_REGLIST].value & PC_REGLIST_BIT)
+            {
+                if (decodedInstruction.numOperands != 2)
+                {
+                    LogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
+                    return false;
+                }
+
+                // Get baseAddress from register (at index=0)
+                baseAddressIndex = decodedInstruction.op[0].value;
+                baseAddress = m_state.gpr.r[baseAddressIndex];
+
+                // Get registerList from register (at index=1)
+                registerList16 = (uint16_t)decodedInstruction.op[1].value;
+
+                // Count number of registers to load in the multiple register list excluding the PC
+                registerList16NoPC = registerList16&0x3FFF; // exclude the PC
+                numRegistersToLoad=0;
+                for (int i = 0; i < 16; i++)
+                {
+                    if (registerList16NoPC & 0x1) numRegistersToLoad++;
+                    registerList16NoPC = registerList16NoPC >> 1;
+                }
+            }
+            else
+            {
+                LogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
+                return false;
+            }
+            break;
+
+            // Normal 16-bit LD multiple can't touch R15, but POP can
+        case ARM_INST_POP:  // Can also get the PC & updates SP
+            // Get baseAddress from SP (at index=0)
+            baseAddress = m_state.gpr.__sp;
+
+            if (decodedInstruction.thumb16b)
+            {
+                // Get registerList from register (at index=0)
+                registerList8 = (uint8_t)decodedInstruction.op[0].value;
+
+                // Count number of registers to load in the multiple register list
+                numRegistersToLoad=0;
+                for (int i = 0; i < 8; i++)
+                {
+                    if (registerList8 & 0x1) numRegistersToLoad++;
+                    registerList8 = registerList8 >> 1;
+                }
+            }
+            else
+            {
+                // Get registerList from register (at index=0)
+                registerList16 = (uint16_t)decodedInstruction.op[0].value;
+
+                // Count number of registers to load in the multiple register list excluding the PC
+                registerList16NoPC = registerList16&0x3FFF; // exclude the PC
+                numRegistersToLoad=0;
+                for (int i = 0; i < 16; i++)
+                {
+                    if (registerList16NoPC & 0x1) numRegistersToLoad++;
+                    registerList16NoPC = registerList16NoPC >> 1;
+                }
+            }
+            break;
+
+            // 16b TBB and TBH instructions load a jump address from a table
+        case ARM_INST_TBB:
+        case ARM_INST_TBH:
+            // Get baseAddress from register (at index=0)
+            baseAddressIndex = decodedInstruction.op[0].value;
+            baseAddress = m_state.gpr.r[baseAddressIndex];
+
+            // Get immediateOffset from register (at index=1)
+            addressOffsetFromRegisterIndex = decodedInstruction.op[1].value;
+            addressOffsetFromRegister = m_state.gpr.r[addressOffsetFromRegisterIndex];
+            break;
+
+            // ThumbEE branch-to-handler instructions: Jump to handlers at some offset
+            //  from a special base pointer register (which is unknown at disassembly time)
+        case ARM_INST_HB:
+        case ARM_INST_HBP:
+//          TODO: ARM_INST_HB, ARM_INST_HBP
+            break;
+
+        case ARM_INST_HBL:
+        case ARM_INST_HBLP:
+//          TODO: ARM_INST_HBL, ARM_INST_HBLP
+            break;
+
+            // Breakpoint and software interrupt jump to interrupt handler (always ARM)
+        case ARM_INST_BKPT:
+        case ARM_INST_SMC:
+        case ARM_INST_SVC:
+
+            // Return from exception, obviously modifies PC [interrupt only!]
+        case ARM_INST_RFEDA:
+        case ARM_INST_RFEDB:
+        case ARM_INST_RFEIA:
+        case ARM_INST_RFEIB:
+
+            // Other instructions either can't change R15 or are "undefined" if you do,
+            //  so no sane compiler should ever generate them & we don't care here.
+            //  Also, R15 can only legally be used in a read-only manner for the
+            //  various ARM addressing mode (to get PC-relative addressing of constants),
+            //  but can NOT be used with any of the update modes.
+        default:
+            LogError("%s should not be called for instruction code %d!", __FUNCTION__, decodedInstruction.instruction->code);
+            return false;
+            break;
+    }
+
+    // Adjust PC if PC is one of the input operands
+    if (baseAddressIndex == PC_REG)
+    {
+        if (currentPCIsThumb)
+            baseAddress += 4;
+        else
+            baseAddress += 8;
+    }
+
+    if (firstOperandIndex == PC_REG)
+    {
+        if (currentPCIsThumb)
+            firstOperand += 4;
+        else
+            firstOperand += 8;
+    }
+
+    if (secondOperandIndex == PC_REG)
+    {
+        if (currentPCIsThumb)
+            secondOperand += 4;
+        else
+            secondOperand += 8;
+    }
+
+    if (addressOffsetFromRegisterIndex == PC_REG)
+    {
+        if (currentPCIsThumb)
+            addressOffsetFromRegister += 4;
+        else
+            addressOffsetFromRegister += 8;
+    }
+
+    ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE,
+        "%s: firstOperand=%8.8x, secondOperand=%8.8x, immediateValue = %d, shiftAmount = %d, baseAddress = %8.8x, addressOffsetFromRegister = %8.8x, immediateOffset = %d, numRegistersToLoad = %d",
+        __FUNCTION__,
+        firstOperand,
+        secondOperand,
+        immediateValue,
+        shiftAmount,
+        baseAddress,
+        addressOffsetFromRegister,
+        immediateOffset,
+        numRegistersToLoad);
+
+
+    // Calculate following values after applying shiftAmount:
+    //   - immediateOffsetAfterShift, secondOperandAfterShift
+
+    switch (decodedInstruction.scaleMode)
+    {
+        case ARM_SCALE_NONE:
+            addressOffsetFromRegisterAfterShift = addressOffsetFromRegister;
+            secondOperandAfterShift = secondOperand;
+            break;
+
+        case ARM_SCALE_LSL:             // Logical shift left
+            addressOffsetFromRegisterAfterShift = addressOffsetFromRegister << shiftAmount;
+            secondOperandAfterShift = secondOperand << shiftAmount;
+            break;
+
+        case ARM_SCALE_LSR:             // Logical shift right
+            addressOffsetFromRegisterAfterShift = addressOffsetFromRegister >> shiftAmount;
+            secondOperandAfterShift = secondOperand >> shiftAmount;
+            break;
+
+        case ARM_SCALE_ASR:             // Arithmetic shift right
+            asm("mov %0, %1, asr %2" : "=r" (addressOffsetFromRegisterAfterShift) : "r" (addressOffsetFromRegister), "r" (shiftAmount));
+            asm("mov %0, %1, asr %2" : "=r" (secondOperandAfterShift) : "r" (secondOperand), "r" (shiftAmount));
+            break;
+
+        case ARM_SCALE_ROR:             // Rotate right
+            asm("mov %0, %1, ror %2" : "=r" (addressOffsetFromRegisterAfterShift) : "r" (addressOffsetFromRegister), "r" (shiftAmount));
+            asm("mov %0, %1, ror %2" : "=r" (secondOperandAfterShift) : "r" (secondOperand), "r" (shiftAmount));
+            break;
+
+        case ARM_SCALE_RRX:             // Rotate right, pulling in carry (1-bit shift only)
+            asm("mov %0, %1, rrx" : "=r" (addressOffsetFromRegisterAfterShift) : "r" (addressOffsetFromRegister));
+            asm("mov %0, %1, rrx" : "=r" (secondOperandAfterShift) : "r" (secondOperand));
+            break;
+    }
+
+    // Emulate instruction to calculate targetPC
+    // All branches are already handled in the first switch statement. A branch should not reach this switch
+    switch (decodedInstruction.instruction->code)
+    {
+            // Arithmetic operations that can change the PC
+        case ARM_INST_ADC:
+        case ARM_INST_ADCS:
+            // Add with Carry
+            *targetPC = firstOperand + (secondOperandAfterShift + immediateValue) + cpsr_c;
+            break;
+
+        case ARM_INST_ADD:
+        case ARM_INST_ADDS:
+            *targetPC = firstOperand + (secondOperandAfterShift + immediateValue);
+            break;
+
+        case ARM_INST_AND:
+        case ARM_INST_ANDS:
+            *targetPC = firstOperand & (secondOperandAfterShift + immediateValue);
+            break;
+
+        case ARM_INST_ASR:
+        case ARM_INST_ASRS:
+            asm("mov %0, %1, asr %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue));
+            *targetPC = myTargetPC;
+            break;
+
+        case ARM_INST_BIC:
+        case ARM_INST_BICS:
+            asm("bic %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue));
+            *targetPC = myTargetPC;
+            break;
+
+        case ARM_INST_EOR:
+        case ARM_INST_EORS:
+            asm("eor %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue));
+            *targetPC = myTargetPC;
+            break;
+
+        case ARM_INST_ORR:
+        case ARM_INST_ORRS:
+            asm("orr %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue));
+            *targetPC = myTargetPC;
+            break;
+
+        case ARM_INST_RSB:
+        case ARM_INST_RSBS:
+            asm("rsb %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue));
+            *targetPC = myTargetPC;
+            break;
+
+        case ARM_INST_RSC:
+        case ARM_INST_RSCS:
+            myTargetPC = secondOperandAfterShift - (firstOperand + !cpsr_c);
+            *targetPC = myTargetPC;
+            break;
+
+        case ARM_INST_SBC:
+        case ARM_INST_SBCS:
+            asm("sbc %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue  + !cpsr_c));
+            *targetPC = myTargetPC;
+            break;
+
+        case ARM_INST_SUB:
+        case ARM_INST_SUBS:
+            asm("sub %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue));
+            *targetPC = myTargetPC;
+            break;
+
+            // Logical shifts and move operations that can change the PC
+        case ARM_INST_LSL:
+        case ARM_INST_LSLS:
+        case ARM_INST_LSR:
+        case ARM_INST_LSRS:
+        case ARM_INST_MOV:
+        case ARM_INST_MOVS:
+        case ARM_INST_ROR:
+        case ARM_INST_RORS:
+        case ARM_INST_RRX:
+        case ARM_INST_RRXS:
+            myTargetPC = secondOperandAfterShift + immediateValue;
+            *targetPC = myTargetPC;
+            break;
+
+        case ARM_INST_MVN:
+        case ARM_INST_MVNS:
+            myTargetPC = !(secondOperandAfterShift + immediateValue);
+            *targetPC = myTargetPC;
+            break;
+
+            // Load register can be used to load PC, usually with a function pointer
+        case ARM_INST_LDR:
+            switch (decodedInstruction.addressMode) {
+                case ARM_ADDR_LSWUB_IMM_POST:
+                case ARM_ADDR_LSWUB_REG_POST:
+                case ARM_ADDR_LSWUB_SCALED_POST:
+                    addressWherePCLives = baseAddress;
+                    break;
+
+                case ARM_ADDR_LSWUB_IMM:
+                case ARM_ADDR_LSWUB_REG:
+                case ARM_ADDR_LSWUB_SCALED:
+                case ARM_ADDR_LSWUB_IMM_PRE:
+                case ARM_ADDR_LSWUB_REG_PRE:
+                case ARM_ADDR_LSWUB_SCALED_PRE:
+                    addressWherePCLives = baseAddress + (addressOffsetFromRegisterAfterShift + immediateOffset);
+                    break;
+
+                default:
+                    break;
+            }
+
+            mypid = m_thread.ProcessID();
+            if (PDProcessMemoryRead(mypid, addressWherePCLives, sizeof(lldb::addr_t), &myTargetPC) !=  sizeof(lldb::addr_t))
+            {
+                LogError("Could not read memory at %8.8x to get targetPC when processing the pop instruction!", addressWherePCLives);
+                return false;
+            }
+
+            *targetPC = myTargetPC;
+            break;
+
+            // 32b load multiple operations can load the PC along with everything else,
+            //  usually to return from a function call
+        case ARM_INST_LDMDA:
+            mypid = m_thread.ProcessID();
+            addressWherePCLives = baseAddress;
+            if (PDProcessMemoryRead(mypid, addressWherePCLives, sizeof(lldb::addr_t), &myTargetPC) !=  sizeof(lldb::addr_t))
+            {
+                LogError("Could not read memory at %8.8x to get targetPC when processing the pop instruction!", addressWherePCLives);
+                return false;
+            }
+
+            *targetPC = myTargetPC;
+            break;
+
+        case ARM_INST_LDMDB:
+            mypid = m_thread.ProcessID();
+            addressWherePCLives = baseAddress - 4;
+            if (PDProcessMemoryRead(mypid, addressWherePCLives, sizeof(lldb::addr_t), &myTargetPC) !=  sizeof(lldb::addr_t))
+            {
+                LogError("Could not read memory at %8.8x to get targetPC when processing the pop instruction!", addressWherePCLives);
+                return false;
+            }
+
+            *targetPC = myTargetPC;
+            break;
+
+        case ARM_INST_LDMIB:
+            mypid = m_thread.ProcessID();
+            addressWherePCLives = baseAddress + numRegistersToLoad*4 + 4;
+            if (PDProcessMemoryRead(mypid, addressWherePCLives, sizeof(lldb::addr_t), &myTargetPC) !=  sizeof(lldb::addr_t))
+            {
+                LogError("Could not read memory at %8.8x to get targetPC when processing the pop instruction!", addressWherePCLives);
+                return false;
+            }
+
+            *targetPC = myTargetPC;
+            break;
+
+        case ARM_INST_LDMIA: // same as pop
+            // Normal 16-bit LD multiple can't touch R15, but POP can
+        case ARM_INST_POP:  // Can also get the PC & updates SP
+            mypid = m_thread.ProcessID();
+            addressWherePCLives = baseAddress + numRegistersToLoad*4;
+            if (PDProcessMemoryRead(mypid, addressWherePCLives, sizeof(lldb::addr_t), &myTargetPC) !=  sizeof(lldb::addr_t))
+            {
+                LogError("Could not read memory at %8.8x to get targetPC when processing the pop instruction!", addressWherePCLives);
+                return false;
+            }
+
+            *targetPC = myTargetPC;
+            break;
+
+            // 16b TBB and TBH instructions load a jump address from a table
+        case ARM_INST_TBB:
+            mypid = m_thread.ProcessID();
+            addressWherePCLives = baseAddress + addressOffsetFromRegisterAfterShift;
+            if (PDProcessMemoryRead(mypid, addressWherePCLives, 1, &halfwords) !=  1)
+            {
+                LogError("Could not read memory at %8.8x to get targetPC when processing the TBB instruction!", addressWherePCLives);
+                return false;
+            }
+            // add 4 to currentPC since we are in Thumb mode and then add 2*halfwords
+            *targetPC = (currentPC + 4) + 2*halfwords;
+            break;
+
+        case ARM_INST_TBH:
+            mypid = m_thread.ProcessID();
+            addressWherePCLives = ((baseAddress + (addressOffsetFromRegisterAfterShift << 1)) & ~0x1);
+            if (PDProcessMemoryRead(mypid, addressWherePCLives, 2, &halfwords) !=  2)
+            {
+                LogError("Could not read memory at %8.8x to get targetPC when processing the TBH instruction!", addressWherePCLives);
+                return false;
+            }
+            // add 4 to currentPC since we are in Thumb mode and then add 2*halfwords
+            *targetPC = (currentPC + 4) + 2*halfwords;
+            break;
+
+            // ThumbEE branch-to-handler instructions: Jump to handlers at some offset
+            //  from a special base pointer register (which is unknown at disassembly time)
+        case ARM_INST_HB:
+        case ARM_INST_HBP:
+            //          TODO: ARM_INST_HB, ARM_INST_HBP
+            break;
+
+        case ARM_INST_HBL:
+        case ARM_INST_HBLP:
+            //          TODO: ARM_INST_HBL, ARM_INST_HBLP
+            break;
+
+            // Breakpoint and software interrupt jump to interrupt handler (always ARM)
+        case ARM_INST_BKPT:
+        case ARM_INST_SMC:
+        case ARM_INST_SVC:
+            //          TODO: ARM_INST_BKPT, ARM_INST_SMC, ARM_INST_SVC
+            break;
+
+            // Return from exception, obviously modifies PC [interrupt only!]
+        case ARM_INST_RFEDA:
+        case ARM_INST_RFEDB:
+        case ARM_INST_RFEIA:
+        case ARM_INST_RFEIB:
+            //          TODO: ARM_INST_RFEDA, ARM_INST_RFEDB, ARM_INST_RFEIA, ARM_INST_RFEIB
+            break;
+
+            // Other instructions either can't change R15 or are "undefined" if you do,
+            //  so no sane compiler should ever generate them & we don't care here.
+            //  Also, R15 can only legally be used in a read-only manner for the
+            //  various ARM addressing mode (to get PC-relative addressing of constants),
+            //  but can NOT be used with any of the update modes.
+        default:
+            LogError("%s should not be called for instruction code %d!", __FUNCTION__, decodedInstruction.instruction->code);
+            return false;
+            break;
+    }
+
+    return true;
+}
+
+void
+MachThreadContext_arm::EvaluateNextInstructionForSoftwareBreakpointSetup(lldb::addr_t currentPC, uint32_t cpsr, bool currentPCIsThumb, lldb::addr_t *nextPC, bool *nextPCIsThumb)
+{
+    ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "MachThreadContext_arm::EvaluateNextInstructionForSoftwareBreakpointSetup() called");
+
+    lldb::addr_t targetPC = LLDB_INVALID_ADDRESS;
+    uint32_t registerValue;
+    arm_error_t decodeError;
+    lldb::addr_t currentPCInITBlock, nextPCInITBlock;
+    int i;
+    bool last_decoded_instruction_executes = true;
+
+    ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: default nextPC=0x%8.8x (%s)", __FUNCTION__, *nextPC, *nextPCIsThumb ? "Thumb" : "ARM");
+
+    // Update *nextPC and *nextPCIsThumb for special cases
+    if (m_last_decode_thumb.itBlockRemaining) // we are in an IT block
+    {
+        // Set the nextPC to the PC of the instruction which will execute in the IT block
+        // If none of the instruction execute in the IT block based on the condition flags,
+        // then point to the instruction immediately following the IT block
+        const int itBlockRemaining = m_last_decode_thumb.itBlockRemaining;
+        ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: itBlockRemaining=%8.8x", __FUNCTION__, itBlockRemaining);
+
+        // Determine the PC at which the next instruction resides
+        if (m_last_decode_arm.thumb16b)
+            currentPCInITBlock = currentPC + 2;
+        else
+            currentPCInITBlock = currentPC + 4;
+
+        for (i = 0; i < itBlockRemaining; i++)
+        {
+            ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: currentPCInITBlock=%8.8x", __FUNCTION__, currentPCInITBlock);
+            decodeError = DecodeInstructionUsingDisassembler(currentPCInITBlock, cpsr, &m_last_decode_arm, &m_last_decode_thumb, &nextPCInITBlock);
+
+            if (decodeError != ARM_SUCCESS)
+                LogError("unable to disassemble instruction at 0x%8.8lx", currentPCInITBlock);
+
+            ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: condition=%d", __FUNCTION__, m_last_decode_arm.condition);
+            if (ConditionPassed(m_last_decode_arm.condition, cpsr))
+            {
+                ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: Condition codes matched for instruction %d", __FUNCTION__, i);
+                break; // break from the for loop
+            }
+            else
+            {
+                ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: Condition codes DID NOT matched for instruction %d", __FUNCTION__, i);
+            }
+
+            // update currentPC and nextPCInITBlock
+            currentPCInITBlock = nextPCInITBlock;
+        }
+
+        if (i == itBlockRemaining) // We came out of the IT block without executing any instructions
+            last_decoded_instruction_executes = false;
+
+        *nextPC = currentPCInITBlock;
+        ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: After IT block step-through: *nextPC=%8.8x", __FUNCTION__, *nextPC);
+    }
+
+    ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE,
+                    "%s: cpsr = %8.8x, thumb16b = %d, thumb = %d, branch = %d, conditional = %d, knownTarget = %d, links = %d, canSwitchMode = %d, doesSwitchMode = %d",
+                    __FUNCTION__,
+                    cpsr,
+                    m_last_decode_arm.thumb16b,
+                    m_last_decode_arm.thumb,
+                    m_last_decode_arm.branch,
+                    m_last_decode_arm.conditional,
+                    m_last_decode_arm.knownTarget,
+                    m_last_decode_arm.links,
+                    m_last_decode_arm.canSwitchMode,
+                    m_last_decode_arm.doesSwitchMode);
+
+
+    if (last_decoded_instruction_executes &&                    // Was this a conditional instruction that did execute?
+        m_last_decode_arm.branch &&                             // Can this instruction change the PC?
+        (m_last_decode_arm.instruction->code != ARM_INST_SVC))  // If this instruction is not an SVC instruction
+    {
+        // Set targetPC. Compute if needed.
+        if (m_last_decode_arm.knownTarget)
+        {
+            // Fixed, known PC-relative
+            targetPC = m_last_decode_arm.targetPC;
+        }
+        else
+        {
+            // if targetPC is not known at compile time (PC-relative target), compute targetPC
+            if (!ComputeNextPC(currentPC, m_last_decode_arm, currentPCIsThumb, &targetPC))
+            {
+                LogError("%s: Unable to compute targetPC for instruction at 0x%8.8lx", __FUNCTION__, currentPC);
+                targetPC = LLDB_INVALID_ADDRESS;
+            }
+        }
+
+        ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: targetPC=0x%8.8x, cpsr=0x%8.8x, condition=0x%hhx", __FUNCTION__, targetPC, cpsr, m_last_decode_arm.condition);
+
+        // Refine nextPC computation
+        if ((m_last_decode_arm.instruction->code == ARM_INST_CBZ) ||
+            (m_last_decode_arm.instruction->code == ARM_INST_CBNZ))
+        {
+            // Compare and branch on zero/non-zero (Thumb-16 only)
+            // Unusual condition check built into the instruction
+            registerValue = m_state.gpr.r[m_last_decode_arm.op[REG_RD].value];
+
+            if (m_last_decode_arm.instruction->code == ARM_INST_CBZ)
+            {
+                if (registerValue == 0)
+                    *nextPC = targetPC;
+            }
+            else
+            {
+                if (registerValue != 0)
+                    *nextPC = targetPC;
+            }
+        }
+        else if (m_last_decode_arm.conditional) // Is the change conditional on flag results?
+        {
+            if (ConditionPassed(m_last_decode_arm.condition, cpsr)) // conditions match
+            {
+                ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: Condition matched!", __FUNCTION__);
+                *nextPC = targetPC;
+            }
+            else
+            {
+                ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: Condition did not match!", __FUNCTION__);
+            }
+        }
+        else
+        {
+            *nextPC = targetPC;
+        }
+
+        // Refine nextPCIsThumb computation
+        if (m_last_decode_arm.doesSwitchMode)
+        {
+            *nextPCIsThumb = !currentPCIsThumb;
+        }
+        else if (m_last_decode_arm.canSwitchMode)
+        {
+            // Legal to switch ARM <--> Thumb mode with this branch
+            // dependent on bit[0] of targetPC
+            *nextPCIsThumb = (*nextPC & 1u) != 0;
+        }
+        else
+        {
+            *nextPCIsThumb = currentPCIsThumb;
+        }
+    }
+
+    ProcessMacOSXLog::LogIf(PD_LOG_STEP, "%s: calculated nextPC=0x%8.8x (%s)", __FUNCTION__, *nextPC, *nextPCIsThumb ? "Thumb" : "ARM");
+}
+
+
+arm_error_t
+MachThreadContext_arm::DecodeInstructionUsingDisassembler(lldb::addr_t curr_pc, uint32_t curr_cpsr, arm_decoded_instruction_t *decodedInstruction, thumb_static_data_t *thumbStaticData, lldb::addr_t *next_pc)
+{
+
+    ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: pc=0x%8.8x, cpsr=0x%8.8x", __FUNCTION__, curr_pc, curr_cpsr);
+
+    const uint32_t isetstate_mask = MASK_CPSR_T | MASK_CPSR_J;
+    const uint32_t curr_isetstate = curr_cpsr & isetstate_mask;
+    uint32_t opcode32;
+    lldb::addr_t nextPC = curr_pc;
+    arm_error_t decodeReturnCode = ARM_SUCCESS;
+
+    m_last_decode_pc = curr_pc;
+    ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: last_decode_pc=0x%8.8x", __FUNCTION__, m_last_decode_pc);
+
+    switch (curr_isetstate) {
+        case 0x0: // ARM Instruction
+            // Read the ARM opcode
+            if (m_thread.Process()->Task().ReadMemory(curr_pc, 4, &opcode32) != 4)
+            {
+                LogError("unable to read opcode bits 31:0 for an ARM opcode at 0x%8.8lx", curr_pc);
+                decodeReturnCode = ARM_ERROR;
+            }
+            else
+            {
+                nextPC += 4;
+                decodeReturnCode = ArmDisassembler((uint64_t)curr_pc, opcode32, false, decodedInstruction, NULL, 0, NULL, 0);
+
+                if (decodeReturnCode != ARM_SUCCESS)
+                    LogError("Unable to decode ARM instruction 0x%8.8x at 0x%8.8lx", opcode32, curr_pc);
+            }
+            break;
+
+        case 0x20: // Thumb Instruction
+            uint16_t opcode16;
+            // Read the a 16 bit Thumb opcode
+            if (m_thread.Process()->Task().ReadMemory(curr_pc, 2, &opcode16) != 2)
+            {
+                LogError("unable to read opcode bits 15:0 for a thumb opcode at 0x%8.8lx", curr_pc);
+                decodeReturnCode = ARM_ERROR;
+            }
+            else
+            {
+                nextPC += 2;
+                opcode32 = opcode16;
+
+                decodeReturnCode = ThumbDisassembler((uint64_t)curr_pc, opcode16, false, false, thumbStaticData, decodedInstruction, NULL, 0, NULL, 0);
+
+                switch (decodeReturnCode) {
+                    case ARM_SKIP:
+                        // 32 bit thumb opcode
+                        nextPC += 2;
+                        if (m_thread.Process()->Task().ReadMemory(curr_pc+2, 2, &opcode16) != 2)
+                        {
+                            LogError("unable to read opcode bits 15:0 for a thumb opcode at 0x%8.8lx", curr_pc+2);
+                        }
+                        else
+                        {
+                            opcode32 = (opcode32 << 16) | opcode16;
+
+                            decodeReturnCode = ThumbDisassembler((uint64_t)(curr_pc+2), opcode16, false, false, thumbStaticData, decodedInstruction, NULL, 0, NULL, 0);
+
+                            if (decodeReturnCode != ARM_SUCCESS)
+                                LogError("Unable to decode 2nd half of Thumb instruction 0x%8.4hx at 0x%8.8lx", opcode16, curr_pc+2);
+                            break;
+                        }
+                        break;
+
+                    case ARM_SUCCESS:
+                        // 16 bit thumb opcode; at this point we are done decoding the opcode
+                        break;
+
+                    default:
+                        LogError("Unable to decode Thumb instruction 0x%8.4hx at 0x%8.8lx", opcode16, curr_pc);
+                        decodeReturnCode = ARM_ERROR;
+                        break;
+                }
+            }
+            break;
+
+        default:
+            break;
+    }
+
+    if (next_pc)
+        *next_pc = nextPC;
+
+    return decodeReturnCode;
+}
+
+bool
+MachThreadContext_arm::BreakpointHit(lldb::pid_t pid, lldb::tid_t tid, lldb::user_id_t breakID, void *baton)
+{
+    lldb::addr_t bkpt_pc = (lldb::addr_t)baton;
+    ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s(pid = %i, tid = %4.4x, breakID = %u, baton = %p): Setting PC to 0x%8.8x", __FUNCTION__, pid, tid, breakID, baton, bkpt_pc);
+    return PDThreadSetRegisterValueByID(pid, tid, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, bkpt_pc);
+}
+
+// Set the single step bit in the processor status register.
+kern_return_t
+MachThreadContext_arm::SetSingleStepSoftwareBreakpoints()
+{
+    Error err;
+    err = ReadGPRRegisters(false);
+
+    if (err.Fail())
+    {
+        err.Log("%s: failed to read the GPR registers", __FUNCTION__);
+        return err.GetError();
+    }
+
+    lldb::addr_t curr_pc = m_state.gpr.r[15];
+    uint32_t curr_cpsr = m_state.gpr.__cpsr;
+    lldb::addr_t next_pc = curr_pc;
+
+    bool curr_pc_is_thumb = (m_state.gpr.__cpsr & 0x20) != 0;
+    bool next_pc_is_thumb = curr_pc_is_thumb;
+
+    uint32_t curr_itstate = ((curr_cpsr & 0x6000000) >> 25) | ((curr_cpsr & 0xFC00) >> 8);
+    bool inITBlock = (curr_itstate & 0xF) ? 1 : 0;
+    bool lastInITBlock = ((curr_itstate & 0xF) == 0x8) ? 1 : 0;
+
+    ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: curr_pc=0x%8.8x (%s), curr_itstate=0x%x, inITBlock=%d, lastInITBlock=%d", __FUNCTION__, curr_pc, curr_pc_is_thumb ? "Thumb" : "ARM", curr_itstate, inITBlock, lastInITBlock);
+
+    // If the instruction is not in the IT block, then decode using the Disassembler and compute next_pc
+    if (!inITBlock)
+    {
+        ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: Decoding an instruction NOT in the IT block", __FUNCTION__);
+
+        arm_error_t decodeReturnCode =  DecodeInstructionUsingDisassembler(curr_pc, curr_cpsr, &m_last_decode_arm, &m_last_decode_thumb, &next_pc);
+
+        if (decodeReturnCode != ARM_SUCCESS)
+        {
+            err = KERN_INVALID_ARGUMENT;
+            LogError("MachThreadContext_arm::SetSingleStepSoftwareBreakpoints: Unable to disassemble instruction at 0x%8.8lx", curr_pc);
+        }
+    }
+    else
+    {
+        next_pc = curr_pc + ((m_last_decode_arm.thumb16b) ? 2 : 4);
+    }
+
+    // Instruction is NOT in the IT block OR
+    if (!inITBlock)
+    {
+        ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: normal instruction", __FUNCTION__);
+        EvaluateNextInstructionForSoftwareBreakpointSetup(curr_pc, m_state.gpr.__cpsr, curr_pc_is_thumb, &next_pc, &next_pc_is_thumb);
+    }
+    else if (inITBlock && !m_last_decode_arm.setsFlags)
+    {
+        ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: IT instruction that doesn't set flags", __FUNCTION__);
+        EvaluateNextInstructionForSoftwareBreakpointSetup(curr_pc, m_state.gpr.__cpsr, curr_pc_is_thumb, &next_pc, &next_pc_is_thumb);
+    }
+    else if (lastInITBlock && m_last_decode_arm.branch)
+    {
+        ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: IT instruction which last in the IT block and is a branch", __FUNCTION__);
+        EvaluateNextInstructionForSoftwareBreakpointSetup(curr_pc, m_state.gpr.__cpsr, curr_pc_is_thumb, &next_pc, &next_pc_is_thumb);
+    }
+    else
+    {
+        // Instruction is in IT block and can modify the CPSR flags
+        ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: IT instruction that sets flags", __FUNCTION__);
+
+        // NOTE: When this point of code is reached, the instruction at curr_pc has already been decoded
+        // inside the function ShouldStop (). Therefore m_last_decode_arm, m_last_decode_thumb
+        // reflect the decoded instruction at curr_pc
+
+        // If we find an instruction inside the IT block which will set/modify the condition flags (NZCV bits in CPSR),
+        // we set breakpoints at all remaining instructions inside the IT block starting from the instruction immediately
+        // following this one AND a breakpoint at the instruction immediately following the IT block. We do this because
+        // we cannot determine the next_pc until the instruction at which we are currently stopped executes. Hence we
+        // insert (m_last_decode_thumb.itBlockRemaining+1) 16-bit Thumb breakpoints at consecutive memory locations
+        // starting at addrOfNextInstructionInITBlock. We record these breakpoints in class variable m_sw_single_step_itblock_break_id[],
+        // and also record the total number of IT breakpoints set in the variable 'm_sw_single_step_itblock_break_count'.
+
+        // The instructions inside the IT block, which are replaced by the 16-bit Thumb breakpoints (opcode=0xDEFE)
+        // instructions, can be either Thumb-16 or Thumb-32. When a Thumb-32 instruction (say, inst#1) is replaced  Thumb
+        // by a 16-bit breakpoint (OS only supports 16-bit breakpoints in Thumb mode and 32-bit breakpoints in ARM mode), the
+        // breakpoint for the next instruction (say instr#2) is saved in the upper half of this Thumb-32 (instr#1)
+        // instruction. Hence if the execution stops at Breakpoint2 corresponding to instr#2, the PC is offset by 16-bits.
+        // We therefore have to keep track of PC of each instruction in the IT block that is being replaced with the 16-bit
+        // Thumb breakpoint, to ensure that when the breakpoint is hit, the PC is adjusted to the correct value. We save
+        // the actual PC corresponding to each instruction in the IT block by associating a call back with each breakpoint
+        // we set and passing it as a baton. When the breakpoint hits and the callback routine is called, the routine
+        // adjusts the PC based on the baton that is passed to it.
+
+        lldb::addr_t addrOfNextInstructionInITBlock, pcInITBlock, nextPCInITBlock, bpAddressInITBlock;
+        uint16_t opcode16;
+        uint32_t opcode32;
+
+        addrOfNextInstructionInITBlock = (m_last_decode_arm.thumb16b) ? curr_pc + 2 : curr_pc + 4;
+
+        pcInITBlock = addrOfNextInstructionInITBlock;
+
+        ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: itBlockRemaining=%d", __FUNCTION__, m_last_decode_thumb.itBlockRemaining);
+
+        m_sw_single_step_itblock_break_count = 0;
+        for (int i = 0; i <= m_last_decode_thumb.itBlockRemaining; i++)
+        {
+            if (LLDB_BREAK_ID_IS_VALID(m_sw_single_step_itblock_break_id[i]))
+            {
+                LogError("FunctionProfiler::SetSingleStepSoftwareBreakpoints(): Array m_sw_single_step_itblock_break_id should not contain any valid breakpoint IDs at this point. But found a valid breakID=%d at index=%d", m_sw_single_step_itblock_break_id[i], i);
+            }
+            else
+            {
+                nextPCInITBlock = pcInITBlock;
+                // Compute nextPCInITBlock based on opcode present at pcInITBlock
+                if (m_thread.Process()->Task().ReadMemory(pcInITBlock, 2, &opcode16) == 2)
+                {
+                    opcode32 = opcode16;
+                    nextPCInITBlock += 2;
+
+                    // Check for 32 bit thumb opcode and read the upper 16 bits if needed
+                    if (((opcode32 & 0xE000) == 0xE000) && (opcode32 & 0x1800))
+                    {
+                        // Adjust 'next_pc_in_itblock' to point to the default next Thumb instruction for
+                        // a 32 bit Thumb opcode
+                        // Read bits 31:16 of a 32 bit Thumb opcode
+                        if (m_thread.Process()->Task().ReadMemory(pcInITBlock+2, 2, &opcode16) == 2)
+                        {
+                            // 32 bit thumb opcode
+                            opcode32 = (opcode32 << 16) | opcode16;
+                            nextPCInITBlock += 2;
+                        }
+                        else
+                        {
+                            LogError("FunctionProfiler::SetSingleStepSoftwareBreakpoints(): Unable to read opcode bits 31:16 for a 32 bit thumb opcode at pc=0x%8.8lx", nextPCInITBlock);
+                        }
+                    }
+                }
+                else
+                {
+                    LogError("FunctionProfiler::SetSingleStepSoftwareBreakpoints(): Error reading 16-bit Thumb instruction at pc=0x%8.8x", nextPCInITBlock);
+                }
+
+
+                // Set breakpoint and associate a callback function with it
+                bpAddressInITBlock = addrOfNextInstructionInITBlock + 2*i;
+                ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: Setting IT breakpoint[%d] at address: 0x%8.8x", __FUNCTION__, i, bpAddressInITBlock);
+
+                m_sw_single_step_itblock_break_id[i] = m_thread.Process()->CreateBreakpoint(bpAddressInITBlock, 2, false, m_thread.GetID());
+                if (!LLDB_BREAK_ID_IS_VALID(m_sw_single_step_itblock_break_id[i]))
+                    err = KERN_INVALID_ARGUMENT;
+                else
+                {
+                    ProcessMacOSXLog::LogIf(PD_LOG_STEP, "%s: Set IT breakpoint[%i]=%d set at 0x%8.8x for instruction at 0x%8.8x", __FUNCTION__, i, m_sw_single_step_itblock_break_id[i], bpAddressInITBlock, pcInITBlock);
+
+                    // Set the breakpoint callback for these special IT breakpoints
+                    // so that if one of these breakpoints gets hit, it knows to
+                    // update the PC to the original address of the conditional
+                    // IT instruction.
+                    PDBreakpointSetCallback(m_thread.ProcessID(), m_sw_single_step_itblock_break_id[i], MachThreadContext_arm::BreakpointHit, (void*)pcInITBlock);
+                    m_sw_single_step_itblock_break_count++;
+                }
+            }
+
+            pcInITBlock = nextPCInITBlock;
+        }
+
+        ProcessMacOSXLog::LogIf(PD_LOG_STEP | PD_LOG_VERBOSE, "%s: Set %u IT software single breakpoints.", __FUNCTION__, m_sw_single_step_itblock_break_count);
+
+    }
+
+    ProcessMacOSXLog::LogIf(PD_LOG_STEP, "%s: next_pc=0x%8.8x (%s)", __FUNCTION__, next_pc, next_pc_is_thumb ? "Thumb" : "ARM");
+
+    if (next_pc & 0x1)
+    {
+        assert(next_pc_is_thumb);
+    }
+
+    if (next_pc_is_thumb)
+    {
+        next_pc &= ~0x1;
+    }
+    else
+    {
+        assert((next_pc & 0x3) == 0);
+    }
+
+    if (!inITBlock || (inITBlock && !m_last_decode_arm.setsFlags) || (lastInITBlock && m_last_decode_arm.branch))
+    {
+        err = KERN_SUCCESS;
+
+#if defined DNB_ARCH_MACH_ARM_DEBUG_SW_STEP
+        m_sw_single_step_next_pc = next_pc;
+        if (next_pc_is_thumb)
+            m_sw_single_step_next_pc |= 1;  // Set bit zero if the next PC is expected to be Thumb
+#else
+        const DNBBreakpoint *bp = m_thread.Process()->Breakpoints().FindByAddress(next_pc);
+
+        if (bp == NULL)
+        {
+            m_sw_single_step_break_id = m_thread.Process()->CreateBreakpoint(next_pc, next_pc_is_thumb ? 2 : 4, false, m_thread.GetID());
+            if (!LLDB_BREAK_ID_IS_VALID(m_sw_single_step_break_id))
+                err = KERN_INVALID_ARGUMENT;
+            ProcessMacOSXLog::LogIf(PD_LOG_STEP, "%s: software single step breakpoint with breakID=%d set at 0x%8.8x", __FUNCTION__, m_sw_single_step_break_id, next_pc);
+        }
+#endif
+    }
+
+    return err.GetError();
+}
+
+#endif
+
+MachThreadContext*
+MachThreadContext_arm::Create (const ArchSpec &arch_spec, ThreadMacOSX &thread)
+{
+    return new MachThreadContext_arm(thread);
+}
+
+void
+MachThreadContext_arm::Initialize()
+{
+    ArchSpec arch_spec(CPU_TYPE_ARM, CPU_TYPE_ANY);
+    ProcessMacOSX::AddArchCreateCallback(arch_spec, MachThreadContext_arm::Create);
+}
diff --git a/source/Plugins/Process/MacOSX-User/source/MacOSX/MachThreadContext_arm.h b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachThreadContext_arm.h
new file mode 100644
index 0000000..4ec72df
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachThreadContext_arm.h
@@ -0,0 +1,63 @@
+//===-- MachThreadContext_arm.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_MachThreadContext_arm_h_
+#define liblldb_MachThreadContext_arm_h_
+
+#include "MachThreadContext.h"
+#include "RegisterContextMach_arm.h"
+
+class ThreadMacOSX;
+
+class MachThreadContext_arm : public MachThreadContext
+{
+public:
+    enum { kMaxNumThumbITBreakpoints = 4 };
+
+    static MachThreadContext*
+    Create (const lldb_private::ArchSpec &arch_spec, ThreadMacOSX &thread);
+
+    static void
+    Initialize();
+
+    MachThreadContext_arm(ThreadMacOSX &thread);
+
+    virtual
+    ~MachThreadContext_arm();
+
+    virtual lldb_private::RegisterContext *
+    CreateRegisterContext (lldb_private::StackFrame *frame) const;
+
+    virtual void
+    InitializeInstance();
+
+    virtual void
+    ThreadWillResume ();
+
+    virtual bool
+    ShouldStop ();
+
+    virtual void
+    RefreshStateAfterStop ();
+
+    static uint32_t
+    GetCPUType ();
+
+protected:
+    kern_return_t
+    EnableHardwareSingleStep (bool enable);
+
+protected:
+    lldb::addr_t m_hw_single_chained_step_addr;
+    uint32_t m_bvr0_reg;
+    uint32_t m_bcr0_reg;
+    uint32_t m_bvr0_save;
+    uint32_t m_bcr0_save;
+};
+#endif  // #ifndef liblldb_MachThreadContext_arm_h_
diff --git a/source/Plugins/Process/MacOSX-User/source/MacOSX/MachThreadContext_i386.cpp b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachThreadContext_i386.cpp
new file mode 100644
index 0000000..ea148a6
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachThreadContext_i386.cpp
@@ -0,0 +1,245 @@
+//===-- MachThreadContext_i386.cpp ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#if defined (__i386__) || defined (__x86_64__)
+
+
+#include "MachThreadContext_i386.h"
+
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/Symbol.h"
+
+#include "ProcessMacOSX.h"
+#include "ThreadMacOSX.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+MachThreadContext_i386::MachThreadContext_i386 (ThreadMacOSX &thread) :
+    MachThreadContext (thread),
+    m_flags_reg(LLDB_INVALID_REGNUM)
+{
+}
+
+MachThreadContext_i386::~MachThreadContext_i386()
+{
+}
+
+
+MachThreadContext*
+MachThreadContext_i386::Create (const ArchSpec &arch_spec, ThreadMacOSX &thread)
+{
+    return new MachThreadContext_i386(thread);
+}
+
+// Class init function
+void
+MachThreadContext_i386::Initialize()
+{
+    ArchSpec arch_spec("i386");
+    ProcessMacOSX::AddArchCreateCallback(arch_spec, MachThreadContext_i386::Create);
+}
+
+// Instance init function
+void
+MachThreadContext_i386::InitializeInstance()
+{
+    RegisterContext *reg_ctx = m_thread.GetRegisterContext();
+    assert (reg_ctx != NULL);
+    m_flags_reg = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
+}
+
+
+uint32_t
+MachThreadContext_i386::GetCPUType()
+{
+    return CPU_TYPE_I386;
+}
+
+void
+MachThreadContext_i386::ThreadWillResume()
+{
+    m_thread.GetRegisterContext()->HardwareSingleStep (m_thread.GetState() == eStateStepping);
+}
+
+bool
+MachThreadContext_i386::ShouldStop()
+{
+    return true;
+}
+
+void
+MachThreadContext_i386::RefreshStateAfterStop()
+{
+    m_thread.GetRegisterContext()->HardwareSingleStep (false);
+}
+
+bool
+MachThreadContext_i386::NotifyException (MachException::Data& exc)
+{
+    switch (exc.exc_type)
+    {
+    case EXC_BAD_ACCESS:
+        break;
+    case EXC_BAD_INSTRUCTION:
+        break;
+    case EXC_ARITHMETIC:
+        break;
+    case EXC_EMULATION:
+        break;
+    case EXC_SOFTWARE:
+        break;
+    case EXC_BREAKPOINT:
+        if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 2)
+        {
+            RegisterContext *reg_ctx = m_thread.GetRegisterContext();
+            assert (reg_ctx);
+            lldb::addr_t pc = reg_ctx->GetPC(LLDB_INVALID_ADDRESS);
+            if (pc != LLDB_INVALID_ADDRESS && pc > 0)
+            {
+                pc -= 1;
+                reg_ctx->SetPC(pc);
+            }
+            return true;
+        }
+        break;
+    case EXC_SYSCALL:
+        break;
+    case EXC_MACH_SYSCALL:
+        break;
+    case EXC_RPC_ALERT:
+        break;
+    }
+    return false;
+}
+
+
+// Set the single step bit in the processor status register.
+//kern_return_t
+//MachThreadContext_i386::EnableHardwareSingleStep (bool enable)
+//{
+//  RegisterContext *reg_ctx = m_thread.GetRegisterContext();
+//  assert (reg_ctx);
+//  Scalar rflags_scalar;
+//
+//    if (reg_ctx->ReadRegisterValue (m_flags_reg, rflags_scalar))
+//    {
+//      Flags rflags(rflags_scalar.UInt());
+//        const uint32_t trace_bit = 0x100u;
+//        if (enable)
+//      {
+//          // If the trace bit is already cleared, there is nothing to do
+//          if (rflags.IsSet (trace_bit))
+//              return KERN_SUCCESS;
+//            else
+//              rflags.Set (trace_bit);
+//      }
+//        else
+//      {
+//          // If the trace bit is already cleared, there is nothing to do
+//          if (rflags.IsClear (trace_bit))
+//              return KERN_SUCCESS;
+//            else
+//              rflags.Clear(trace_bit);
+//      }
+//
+//      rflags_scalar = rflags.GetAllFlagBits();
+//      // If the code makes it here we have changes to the GPRs which
+//      // we need to write back out, so lets do that.
+//        if (reg_ctx->WriteRegisterValue(m_flags_reg, rflags_scalar))
+//          return KERN_SUCCESS;
+//    }
+//  // Return the error code for reading the GPR registers back
+//    return KERN_INVALID_ARGUMENT;
+//}
+
+RegisterContext *
+MachThreadContext_i386::CreateRegisterContext (StackFrame *frame) const
+{
+    return new RegisterContextMach_i386(m_thread, frame);
+}
+
+
+size_t
+MachThreadContext_i386::GetStackFrameData(StackFrame *first_frame, std::vector<std::pair<lldb::addr_t, lldb::addr_t> >& fp_pc_pairs)
+{
+    fp_pc_pairs.clear();
+
+    std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair;
+
+    typedef struct Frame_i386
+    {
+        uint32_t fp;
+        uint32_t pc;
+    };
+
+    RegisterContext *reg_ctx = m_thread.GetRegisterContext();
+    assert (reg_ctx);
+
+    Frame_i386 frame = { reg_ctx->GetFP(0), reg_ctx->GetPC(LLDB_INVALID_ADDRESS) };
+
+    fp_pc_pairs.push_back(std::make_pair(frame.fp, frame.pc));
+
+    const size_t k_frame_size = sizeof(frame);
+    Error error;
+
+    while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0))
+    {
+        // Read both the FP and PC (8 bytes)
+        if (m_thread.GetProcess().ReadMemory (frame.fp, &frame.fp, k_frame_size, error) != k_frame_size)
+            break;
+
+        if (frame.pc != 0)
+            fp_pc_pairs.push_back(std::make_pair(frame.fp, frame.pc));
+    }
+    if (!fp_pc_pairs.empty())
+    {
+        lldb::addr_t first_frame_pc = fp_pc_pairs.front().second;
+        if (first_frame_pc != LLDB_INVALID_ADDRESS)
+        {
+            const uint32_t resolve_scope = eSymbolContextModule |
+                                           eSymbolContextCompUnit |
+                                           eSymbolContextFunction |
+                                           eSymbolContextSymbol;
+
+            SymbolContext first_frame_sc(first_frame->GetSymbolContext(resolve_scope));
+            const AddressRange *addr_range_ptr = NULL;
+            if (first_frame_sc.function)
+                addr_range_ptr = &first_frame_sc.function->GetAddressRange();
+            else if (first_frame_sc.symbol)
+                addr_range_ptr = first_frame_sc.symbol->GetAddressRangePtr();
+
+            if (addr_range_ptr)
+            {
+                if (first_frame->GetPC() == addr_range_ptr->GetBaseAddress())
+                {
+                    // We are at the first instruction, so we can recover the
+                    // previous PC by dereferencing the SP
+                    lldb::addr_t first_frame_sp = reg_ctx->GetSP(0);
+                    // Read the real second frame return address into frame.pc
+                    if (m_thread.GetProcess().ReadMemory (first_frame_sp, &frame.pc, sizeof(frame.pc), error) == sizeof(frame.pc))
+                    {
+                        // Construct a correct second frame (we already read the pc for it above
+                        frame.fp = fp_pc_pairs.front().first;
+
+                        // Insert the frame
+                        fp_pc_pairs.insert(fp_pc_pairs.begin()+1, std::make_pair(frame.fp, frame.pc));
+
+                        // Correct the fp in the first frame to use the SP
+                        fp_pc_pairs.front().first = first_frame_sp;
+                    }
+                }
+            }
+        }
+    }
+    return fp_pc_pairs.size();
+}
+
+
+#endif    // #if defined (__i386__)
diff --git a/source/Plugins/Process/MacOSX-User/source/MacOSX/MachThreadContext_i386.h b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachThreadContext_i386.h
new file mode 100644
index 0000000..4bee2e7
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachThreadContext_i386.h
@@ -0,0 +1,57 @@
+//===-- MachThreadContext_i386.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_MachThreadContext_i386_h_
+#define liblldb_MachThreadContext_i386_h_
+
+#if defined (__i386__) || defined (__x86_64__)
+
+#include "MachThreadContext.h"
+#include "RegisterContextMach_i386.h"
+
+class ThreadMacOSX;
+
+class MachThreadContext_i386 : public MachThreadContext
+{
+public:
+    static MachThreadContext* Create(const lldb_private::ArchSpec &arch_spec, ThreadMacOSX &thread);
+
+    // Class init function
+    static void Initialize();
+
+    MachThreadContext_i386(ThreadMacOSX &thread);
+
+    virtual
+    ~MachThreadContext_i386();
+
+    virtual lldb_private::RegisterContext *
+    CreateRegisterContext (lldb_private::StackFrame *frame) const;
+
+    virtual void            InitializeInstance();
+    virtual void            ThreadWillResume();
+    virtual bool            ShouldStop ();
+    virtual void            RefreshStateAfterStop();
+
+    virtual bool            NotifyException(MachException::Data& exc);
+    virtual size_t          GetStackFrameData(lldb_private::StackFrame *first_frame, std::vector<std::pair<lldb::addr_t, lldb::addr_t> >& fp_pc_pairs);
+    static uint32_t         GetCPUType();
+
+protected:
+//    kern_return_t EnableHardwareSingleStep (bool enable);
+    uint32_t m_flags_reg;
+private:
+    DISALLOW_COPY_AND_ASSIGN (MachThreadContext_i386);
+};
+
+//#if defined (__i386__)
+//typedef MachThreadContext_i386    DNBArch;
+//#endif
+
+#endif    // defined (__i386__) || defined (__x86_64__)
+#endif    // #ifndef liblldb_MachThreadContext_i386_h_
diff --git a/source/Plugins/Process/MacOSX-User/source/MacOSX/MachThreadContext_x86_64.cpp b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachThreadContext_x86_64.cpp
new file mode 100644
index 0000000..3ee9eb4
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachThreadContext_x86_64.cpp
@@ -0,0 +1,255 @@
+//===-- MachThreadContext_x86_64.cpp ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#if defined (__i386__) || defined (__x86_64__)
+
+#include <sys/cdefs.h>
+
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/Symbol.h"
+
+#include "MachThreadContext_x86_64.h"
+#include "ProcessMacOSX.h"
+#include "ThreadMacOSX.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+MachThreadContext_x86_64::MachThreadContext_x86_64(ThreadMacOSX &thread) :
+    MachThreadContext (thread),
+    m_flags_reg(LLDB_INVALID_REGNUM)
+{
+}
+
+MachThreadContext_x86_64::~MachThreadContext_x86_64()
+{
+}
+
+MachThreadContext*
+MachThreadContext_x86_64::Create(const ArchSpec &arch_spec, ThreadMacOSX &thread)
+{
+    return new MachThreadContext_x86_64(thread);
+}
+
+// Class init function
+void
+MachThreadContext_x86_64::Initialize()
+{
+    ArchSpec arch_spec("x86_64");
+    ProcessMacOSX::AddArchCreateCallback(arch_spec, MachThreadContext_x86_64::Create);
+}
+
+// Instance init function
+void
+MachThreadContext_x86_64::InitializeInstance()
+{
+    RegisterContext *reg_ctx = m_thread.GetRegisterContext();
+    assert (reg_ctx != NULL);
+    m_flags_reg = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
+}
+
+uint32_t
+MachThreadContext_x86_64::GetCPUType()
+{
+    return CPU_TYPE_X86_64;
+}
+
+void
+MachThreadContext_x86_64::ThreadWillResume()
+{
+    m_thread.GetRegisterContext()->HardwareSingleStep (m_thread.GetState() == eStateStepping);
+}
+
+bool
+MachThreadContext_x86_64::ShouldStop()
+{
+    return true;
+}
+
+void
+MachThreadContext_x86_64::RefreshStateAfterStop()
+{
+    m_thread.GetRegisterContext()->HardwareSingleStep (false);
+}
+
+bool
+MachThreadContext_x86_64::NotifyException(MachException::Data& exc)
+{
+    switch (exc.exc_type)
+    {
+    case EXC_BAD_ACCESS:
+        break;
+    case EXC_BAD_INSTRUCTION:
+        break;
+    case EXC_ARITHMETIC:
+        break;
+    case EXC_EMULATION:
+        break;
+    case EXC_SOFTWARE:
+        break;
+    case EXC_BREAKPOINT:
+        if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 2)
+        {
+            RegisterContext *reg_ctx = m_thread.GetRegisterContext();
+            assert (reg_ctx);
+            lldb::addr_t pc = reg_ctx->GetPC(LLDB_INVALID_ADDRESS);
+            if (pc != LLDB_INVALID_ADDRESS && pc > 0)
+            {
+                pc -= 1;
+                reg_ctx->SetPC(pc);
+            }
+            return true;
+        }
+        break;
+    case EXC_SYSCALL:
+        break;
+    case EXC_MACH_SYSCALL:
+        break;
+    case EXC_RPC_ALERT:
+        break;
+    }
+    return false;
+}
+
+
+// Set the single step bit in the processor status register.
+//kern_return_t
+//MachThreadContext_x86_64::EnableHardwareSingleStep (bool enable)
+//{
+//  RegisterContext *reg_ctx = m_thread.GetRegisterContext();
+//  assert (reg_ctx);
+//  Scalar rflags_scalar;
+//
+//    if (reg_ctx->ReadRegisterValue (m_flags_reg, rflags_scalar))
+//    {
+//      Flags rflags(rflags_scalar.UInt());
+//        const uint32_t trace_bit = 0x100u;
+//        if (enable)
+//      {
+//          // If the trace bit is already set, there is nothing to do
+//          if (rflags.IsSet (trace_bit))
+//              return KERN_SUCCESS;
+//            else
+//              rflags.Set (trace_bit);
+//      }
+//        else
+//      {
+//          // If the trace bit is already cleared, there is nothing to do
+//          if (rflags.IsClear (trace_bit))
+//              return KERN_SUCCESS;
+//            else
+//              rflags.Clear(trace_bit);
+//      }
+//
+//      rflags_scalar = rflags.GetAllFlagBits();
+//      // If the code makes it here we have changes to the GPRs which
+//      // we need to write back out, so lets do that.
+//        if (reg_ctx->WriteRegisterValue(m_flags_reg, rflags_scalar))
+//          return KERN_SUCCESS;
+//    }
+//  // Return the error code for reading the GPR registers back
+//    return KERN_INVALID_ARGUMENT;
+//}
+//
+
+//----------------------------------------------------------------------
+// Register information defintions for 32 bit PowerPC.
+//----------------------------------------------------------------------
+
+
+
+RegisterContext *
+MachThreadContext_x86_64::CreateRegisterContext (StackFrame *frame) const
+{
+    return new RegisterContextMach_x86_64(m_thread, frame);
+}
+
+
+//bool
+//MachThreadContext_x86_64::RegisterSetStateIsValid (uint32_t set) const
+//{
+//    return m_state.RegisterSetIsCached(set);
+//}
+
+
+size_t
+MachThreadContext_x86_64::GetStackFrameData(StackFrame *first_frame, std::vector<std::pair<lldb::addr_t, lldb::addr_t> >& fp_pc_pairs)
+{
+    fp_pc_pairs.clear();
+
+    std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair;
+
+    typedef struct Frame_x86_64
+    {
+        uint64_t fp;
+        uint64_t pc;
+    };
+
+    RegisterContext *reg_ctx = m_thread.GetRegisterContext();
+    assert (reg_ctx);
+
+    Frame_x86_64 frame = { reg_ctx->GetFP(0), reg_ctx->GetPC(LLDB_INVALID_ADDRESS) };
+
+    fp_pc_pairs.push_back(std::make_pair(frame.fp, frame.pc));
+    Error error;
+    const size_t k_frame_size = sizeof(frame);
+    while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0))
+    {
+        // Read both the FP and PC (16 bytes)
+        if (m_thread.GetProcess().ReadMemory (frame.fp, &frame.fp, k_frame_size, error) != k_frame_size)
+            break;
+
+        if (frame.pc >= 0x1000)
+            fp_pc_pairs.push_back(std::make_pair(frame.fp, frame.pc));
+    }
+    if (!fp_pc_pairs.empty())
+    {
+        lldb::addr_t first_frame_pc = fp_pc_pairs.front().second;
+        if (first_frame_pc != LLDB_INVALID_ADDRESS)
+        {
+            const uint32_t resolve_scope = eSymbolContextModule |
+                                           eSymbolContextCompUnit |
+                                           eSymbolContextFunction |
+                                           eSymbolContextSymbol;
+
+            SymbolContext first_frame_sc(first_frame->GetSymbolContext(resolve_scope));
+            const AddressRange *addr_range_ptr = NULL;
+            if (first_frame_sc.function)
+                addr_range_ptr = &first_frame_sc.function->GetAddressRange();
+            else if (first_frame_sc.symbol)
+                addr_range_ptr = first_frame_sc.symbol->GetAddressRangePtr();
+
+            if (addr_range_ptr)
+            {
+                if (first_frame->GetPC() == addr_range_ptr->GetBaseAddress())
+                {
+                    // We are at the first instruction, so we can recover the
+                    // previous PC by dereferencing the SP
+                    lldb::addr_t first_frame_sp = reg_ctx->GetSP(0);
+                    // Read the real second frame return address into frame.pc
+                    if (m_thread.GetProcess().ReadMemory (first_frame_sp, &frame.pc, sizeof(frame.pc), error) == sizeof(frame.pc))
+                    {
+                        // Construct a correct second frame (we already read the pc for it above
+                        frame.fp = fp_pc_pairs.front().first;
+
+                        // Insert the frame
+                        fp_pc_pairs.insert(fp_pc_pairs.begin()+1, std::make_pair(frame.fp, frame.pc));
+
+                        // Correct the fp in the first frame to use the SP
+                        fp_pc_pairs.front().first = first_frame_sp;
+                    }
+                }
+            }
+        }
+    }
+    return fp_pc_pairs.size();
+}
+
+
+#endif    // #if defined (__i386__) || defined (__x86_64__)
diff --git a/source/Plugins/Process/MacOSX-User/source/MacOSX/MachThreadContext_x86_64.h b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachThreadContext_x86_64.h
new file mode 100644
index 0000000..45d5a37
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachThreadContext_x86_64.h
@@ -0,0 +1,72 @@
+//===-- MachThreadContext_x86_64.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_MachThreadContext_x86_64_h_
+#define liblldb_MachThreadContext_x86_64_h_
+
+#if defined (__i386__) || defined (__x86_64__)
+
+#include "MachThreadContext.h"
+#include "RegisterContextMach_x86_64.h"
+
+class ThreadMacOSX;
+
+class MachThreadContext_x86_64 : public MachThreadContext
+{
+public:
+    static MachThreadContext*
+    Create(const lldb_private::ArchSpec &arch_spec, ThreadMacOSX &thread);
+
+    // Class init function
+    static void
+    Initialize();
+
+    // Instance init function
+    void
+    InitializeInstance();
+
+    MachThreadContext_x86_64 (ThreadMacOSX &thread);
+
+    virtual
+    ~MachThreadContext_x86_64();
+
+    virtual lldb_private::RegisterContext *
+    CreateRegisterContext (lldb_private::StackFrame *frame) const;
+
+    virtual void
+    ThreadWillResume ();
+
+    virtual bool
+    ShouldStop ();
+
+    virtual void
+    RefreshStateAfterStop ();
+
+    virtual bool
+    NotifyException (MachException::Data& exc);
+
+    virtual size_t
+    GetStackFrameData (lldb_private::StackFrame *first_frame, std::vector<std::pair<lldb::addr_t, lldb::addr_t> >& fp_pc_pairs);
+
+    static uint32_t
+    GetCPUType();
+
+protected:
+//    kern_return_t EnableHardwareSingleStep (bool enable);
+    uint32_t m_flags_reg;
+private:
+    DISALLOW_COPY_AND_ASSIGN (MachThreadContext_x86_64);
+};
+
+//#if defined (__x86_64__)
+//typedef MachThreadContext_x86_64    DNBArch;
+//#endif
+
+#endif    // defined (__i386__) || defined (__x86_64__)
+#endif    // #ifndef liblldb_MachThreadContext_x86_64_h_
diff --git a/source/Plugins/Process/MacOSX-User/source/MacOSX/MachVMMemory.cpp b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachVMMemory.cpp
new file mode 100644
index 0000000..c91af3c
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachVMMemory.cpp
@@ -0,0 +1,195 @@
+//===-- MachVMMemory.cpp ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MachVMMemory.h"
+
+#include <mach/mach_vm.h>
+
+#include "MachVMRegion.h"
+#include "ProcessMacOSXLog.h"
+
+using namespace lldb_private;
+
+MachVMMemory::MachVMMemory() :
+    m_page_size (kInvalidPageSize)
+{
+}
+
+MachVMMemory::~MachVMMemory()
+{
+}
+
+size_t
+MachVMMemory::PageSize(lldb_private::Error &error)
+{
+    if (m_page_size == kInvalidPageSize)
+    {
+        error = ::host_page_size( ::mach_host_self(), &m_page_size);
+        if (error.Fail())
+            m_page_size = 0;
+    }
+
+    if (m_page_size != 0 && m_page_size != kInvalidPageSize)
+    {
+        if (error.Success())
+            error.SetErrorString ("unable to determine page size");
+    }
+    return m_page_size;
+}
+
+size_t
+MachVMMemory::MaxBytesLeftInPage (lldb::addr_t addr, size_t count)
+{
+    Error error;
+    const size_t page_size = PageSize(error);
+    if (page_size > 0)
+    {
+        size_t page_offset = (addr % page_size);
+        size_t bytes_left_in_page = page_size - page_offset;
+        if (count > bytes_left_in_page)
+            count = bytes_left_in_page;
+    }
+    return count;
+}
+
+size_t
+MachVMMemory::Read(task_t task, lldb::addr_t address, void *data, size_t data_count, Error &error)
+{
+    if (data == NULL || data_count == 0)
+        return 0;
+
+    size_t total_bytes_read = 0;
+    lldb::addr_t curr_addr = address;
+    uint8_t *curr_data = (uint8_t*)data;
+    while (total_bytes_read < data_count)
+    {
+        mach_vm_size_t curr_size = MaxBytesLeftInPage(curr_addr, data_count - total_bytes_read);
+        mach_msg_type_number_t curr_bytes_read = 0;
+        vm_offset_t vm_memory = NULL;
+        error = ::mach_vm_read (task, curr_addr, curr_size, &vm_memory, &curr_bytes_read);
+        Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_MEMORY|PD_LOG_VERBOSE);
+
+        if (log || error.Fail())
+            error.PutToLog (log, "::mach_vm_read (task = 0x%4.4x, addr = 0x%8.8llx, size = %llu, data => %8.8p, dataCnt => %i)", task, (uint64_t)curr_addr, (uint64_t)curr_size, vm_memory, curr_bytes_read);
+
+        if (error.Success())
+        {
+            if (curr_bytes_read != curr_size)
+            {
+                if (log)
+                    error.PutToLog (log, "::mach_vm_read (task = 0x%4.4x, addr = 0x%8.8llx, size = %llu, data => %8.8p, dataCnt=>%i) only read %u of %llu bytes", task, (uint64_t)curr_addr, (uint64_t)curr_size, vm_memory, curr_bytes_read, curr_bytes_read, (uint64_t)curr_size);
+            }
+            ::memcpy (curr_data, (void *)vm_memory, curr_bytes_read);
+            ::vm_deallocate (mach_task_self (), vm_memory, curr_bytes_read);
+            total_bytes_read += curr_bytes_read;
+            curr_addr += curr_bytes_read;
+            curr_data += curr_bytes_read;
+        }
+        else
+        {
+            break;
+        }
+    }
+    return total_bytes_read;
+}
+
+
+size_t
+MachVMMemory::Write(task_t task, lldb::addr_t address, const void *data, size_t data_count, Error &error)
+{
+    MachVMRegion vmRegion(task);
+
+    size_t total_bytes_written = 0;
+    lldb::addr_t curr_addr = address;
+    const uint8_t *curr_data = (const uint8_t*)data;
+
+
+    while (total_bytes_written < data_count)
+    {
+        if (vmRegion.GetRegionForAddress(curr_addr))
+        {
+            mach_vm_size_t curr_data_count = data_count - total_bytes_written;
+            mach_vm_size_t region_bytes_left = vmRegion.BytesRemaining(curr_addr);
+            if (region_bytes_left == 0)
+            {
+                break;
+            }
+            if (curr_data_count > region_bytes_left)
+                curr_data_count = region_bytes_left;
+
+            if (vmRegion.SetProtections(curr_addr, curr_data_count, VM_PROT_READ | VM_PROT_WRITE))
+            {
+                size_t bytes_written = WriteRegion(task, curr_addr, curr_data, curr_data_count, error);
+                if (bytes_written <= 0)
+                {
+                    // Error should have already be posted by WriteRegion...
+                    break;
+                }
+                else
+                {
+                    total_bytes_written += bytes_written;
+                    curr_addr += bytes_written;
+                    curr_data += bytes_written;
+                }
+            }
+            else
+            {
+                ProcessMacOSXLog::LogIf (PD_LOG_MEMORY_PROTECTIONS, "Failed to set read/write protections on region for address: [0x%8.8llx-0x%8.8llx)", (uint64_t)curr_addr, (uint64_t)(curr_addr + curr_data_count));
+                break;
+            }
+        }
+        else
+        {
+            ProcessMacOSXLog::LogIf (PD_LOG_MEMORY_PROTECTIONS, "Failed to get region for address: 0x%8.8llx", (uint64_t)address);
+            break;
+        }
+    }
+
+    return total_bytes_written;
+}
+
+
+size_t
+MachVMMemory::WriteRegion(task_t task, const lldb::addr_t address, const void *data, const size_t data_count, Error &error)
+{
+    if (data == NULL || data_count == 0)
+        return 0;
+
+    size_t total_bytes_written = 0;
+    lldb::addr_t curr_addr = address;
+    const uint8_t *curr_data = (const uint8_t*)data;
+    while (total_bytes_written < data_count)
+    {
+        mach_msg_type_number_t curr_data_count = MaxBytesLeftInPage(curr_addr, data_count - total_bytes_written);
+        error = ::mach_vm_write (task, curr_addr, (pointer_t) curr_data, curr_data_count);
+        Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_MEMORY);
+        if (log || error.Fail())
+            error.PutToLog (log, "::mach_vm_write ( task = 0x%4.4x, addr = 0x%8.8llx, data = %8.8p, dataCnt = %u )", task, (uint64_t)curr_addr, curr_data, curr_data_count);
+
+#if defined (__powerpc__) || defined (__ppc__)
+        vm_machine_attribute_val_t mattr_value = MATTR_VAL_CACHE_FLUSH;
+
+        error = ::vm_machine_attribute (task, curr_addr, curr_data_count, MATTR_CACHE, &mattr_value);
+        if (log || error.Fail())
+            error.Log(log, "::vm_machine_attribute ( task = 0x%4.4x, addr = 0x%8.8llx, size = %u, attr = MATTR_CACHE, mattr_value => MATTR_VAL_CACHE_FLUSH )", task, (uint64_t)curr_addr, curr_data_count);
+#endif
+
+        if (error.Success())
+        {
+            total_bytes_written += curr_data_count;
+            curr_addr += curr_data_count;
+            curr_data += curr_data_count;
+        }
+        else
+        {
+            break;
+        }
+    }
+    return total_bytes_written;
+}
diff --git a/source/Plugins/Process/MacOSX-User/source/MacOSX/MachVMMemory.h b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachVMMemory.h
new file mode 100644
index 0000000..866fa36
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachVMMemory.h
@@ -0,0 +1,36 @@
+//===-- MachVMMemory.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_MachVMMemory_h_
+#define liblldb_MachVMMemory_h_
+
+#include <mach/mach.h>
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/Error.h"
+
+class MachVMMemory
+{
+public:
+    enum { kInvalidPageSize = ~0 };
+    MachVMMemory();
+    ~MachVMMemory();
+    size_t Read(task_t task, lldb::addr_t address, void *data, size_t data_count, lldb_private::Error &error);
+    size_t Write(task_t task, lldb::addr_t address, const void *data, size_t data_count, lldb_private::Error &error);
+    size_t PageSize(lldb_private::Error &error);
+
+protected:
+    size_t MaxBytesLeftInPage(lldb::addr_t addr, size_t count);
+
+    size_t WriteRegion(task_t task, const lldb::addr_t address, const void *data, const size_t data_count, lldb_private::Error &error);
+    vm_size_t m_page_size;
+};
+
+
+#endif //    #ifndef liblldb_MachVMMemory_h_
diff --git a/source/Plugins/Process/MacOSX-User/source/MacOSX/MachVMRegion.cpp b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachVMRegion.cpp
new file mode 100644
index 0000000..87044fb
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachVMRegion.cpp
@@ -0,0 +1,183 @@
+//===-- MachVMRegion.cpp ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <assert.h>
+#include <mach/mach_vm.h>
+#include "MachVMRegion.h"
+#include "ProcessMacOSXLog.h"
+
+using namespace lldb_private;
+
+MachVMRegion::MachVMRegion(task_t task) :
+    m_task(task),
+    m_addr(LLDB_INVALID_ADDRESS),
+    m_err(),
+    m_start(LLDB_INVALID_ADDRESS),
+    m_size(0),
+    m_depth(-1),
+    m_data(),
+    m_curr_protection(0),
+    m_protection_addr(LLDB_INVALID_ADDRESS),
+    m_protection_size(0)
+{
+    memset(&m_data, 0, sizeof(m_data));
+}
+
+MachVMRegion::~MachVMRegion()
+{
+    // Restore any original protections and clear our vars
+    Clear();
+}
+
+void
+MachVMRegion::Clear()
+{
+    RestoreProtections();
+    m_addr = LLDB_INVALID_ADDRESS;
+    m_err.Clear();
+    m_start = LLDB_INVALID_ADDRESS;
+    m_size = 0;
+    m_depth = -1;
+    memset(&m_data, 0, sizeof(m_data));
+    m_curr_protection = 0;
+    m_protection_addr = LLDB_INVALID_ADDRESS;
+    m_protection_size = 0;
+}
+
+bool
+MachVMRegion::SetProtections(mach_vm_address_t addr, mach_vm_size_t size, vm_prot_t prot)
+{
+    if (ContainsAddress(addr))
+    {
+        mach_vm_size_t prot_size = size;
+        mach_vm_address_t end_addr = EndAddress();
+        if (prot_size > (end_addr - addr))
+            prot_size = end_addr - addr;
+
+
+        Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_MEMORY_PROTECTIONS);
+        if (prot_size > 0)
+        {
+            if (prot == (m_curr_protection & VM_PROT_ALL))
+            {
+                if (log)
+                    log->Printf ("MachVMRegion::%s: protections (%u) already sufficient for task 0x%4.4x at address 0x%8.8llx) ", __FUNCTION__, prot, m_task, (uint64_t)addr);
+                // Protections are already set as requested...
+                return true;
+            }
+            else
+            {
+                m_err = ::mach_vm_protect (m_task, addr, prot_size, 0, prot);
+                if (log || m_err.Fail())
+                    m_err.PutToLog(log, "::mach_vm_protect ( task = 0x%4.4x, addr = 0x%8.8llx, size = %llu, set_max = %i, prot = %u )", m_task, (uint64_t)addr, (uint64_t)prot_size, 0, prot);
+                if (m_err.Fail())
+                {
+                    // Try again with the ability to create a copy on write region
+                    m_err = ::mach_vm_protect (m_task, addr, prot_size, 0, prot | VM_PROT_COPY);
+                    if (log || m_err.Fail())
+                        m_err.PutToLog(log, "::mach_vm_protect ( task = 0x%4.4x, addr = 0x%8.8llx, size = %llu, set_max = %i, prot = %u )", m_task, (uint64_t)addr, (uint64_t)prot_size, 0, prot | VM_PROT_COPY);
+                }
+                if (m_err.Success())
+                {
+                    m_curr_protection = prot;
+                    m_protection_addr = addr;
+                    m_protection_size = prot_size;
+                    return true;
+                }
+            }
+        }
+        else
+        {
+            log->Printf("MachVMRegion::%s: Zero size for task 0x%4.4x at address 0x%8.8llx) ", __FUNCTION__, m_task, (uint64_t)addr);
+        }
+    }
+    return false;
+}
+
+bool
+MachVMRegion::RestoreProtections()
+{
+    if (m_curr_protection != m_data.protection && m_protection_size > 0)
+    {
+        m_err = ::mach_vm_protect (m_task, m_protection_addr, m_protection_size, 0, m_data.protection);
+        Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_MEMORY_PROTECTIONS);
+        if (log || m_err.Fail())
+            m_err.PutToLog(log, "::mach_vm_protect ( task = 0x%4.4x, addr = 0x%8.8llx, size = %llu, set_max = %i, prot = %u )", m_task, (uint64_t)m_protection_addr, (uint64_t)m_protection_size, 0, m_data.protection);
+        if (m_err.Success())
+        {
+            m_protection_size = 0;
+            m_protection_addr = LLDB_INVALID_ADDRESS;
+            m_curr_protection = m_data.protection;
+            return true;
+        }
+    }
+    else
+    {
+        m_err.Clear();
+        return true;
+    }
+
+    return false;
+}
+
+bool
+MachVMRegion::GetRegionForAddress(lldb::addr_t addr)
+{
+    // Restore any original protections and clear our vars
+    Clear();
+    m_addr = addr;
+    m_start = addr;
+    m_depth = 1024;
+    mach_msg_type_number_t info_size = kRegionInfoSize;
+    assert(sizeof(info_size) == 4);
+    m_err = ::mach_vm_region_recurse (m_task, &m_start, &m_size, &m_depth, (vm_region_recurse_info_t)&m_data, &info_size);
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_MEMORY_PROTECTIONS);
+    if (log || m_err.Fail())
+        m_err.PutToLog(log, "::mach_vm_region_recurse ( task = 0x%4.4x, address => 0x%8.8llx, size => %llu, nesting_depth => %d, info => %p, infoCnt => %d) addr = 0x%8.8llx ", m_task, (uint64_t)m_start, (uint64_t)m_size, m_depth, &m_data, info_size, (uint64_t)addr);
+    if (m_err.Fail())
+    {
+        return false;
+    }
+    else
+    {
+        if (log && log->GetMask().IsSet(PD_LOG_VERBOSE))
+        {
+            log->Printf("info = { prot = %u, "
+                        "max_prot = %u, "
+                        "inheritance = 0x%8.8x, "
+                        "offset = 0x%8.8llx, "
+                        "user_tag = 0x%8.8x, "
+                        "ref_count = %u, "
+                        "shadow_depth = %u, "
+                        "ext_pager = %u, "
+                        "share_mode = %u, "
+                        "is_submap = %d, "
+                        "behavior = %d, "
+                        "object_id = 0x%8.8x, "
+                        "user_wired_count = 0x%4.4x }",
+                        m_data.protection,
+                        m_data.max_protection,
+                        m_data.inheritance,
+                        (uint64_t)m_data.offset,
+                        m_data.user_tag,
+                        m_data.ref_count,
+                        m_data.shadow_depth,
+                        m_data.external_pager,
+                        m_data.share_mode,
+                        m_data.is_submap,
+                        m_data.behavior,
+                        m_data.object_id,
+                        m_data.user_wired_count);
+        }
+    }
+
+    m_curr_protection = m_data.protection;
+
+    return true;
+}
diff --git a/source/Plugins/Process/MacOSX-User/source/MacOSX/MachVMRegion.h b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachVMRegion.h
new file mode 100644
index 0000000..b12353d
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/MacOSX/MachVMRegion.h
@@ -0,0 +1,63 @@
+//===-- MachVMRegion.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_MachVMRegion_h_
+#define liblldb_MachVMRegion_h_
+
+#include <mach/mach.h>
+#include "lldb/lldb-private.h"
+#include "lldb/Core/Error.h"
+
+class MachVMRegion
+{
+public:
+    MachVMRegion(task_t task);
+    ~MachVMRegion();
+
+    void Clear();
+    mach_vm_address_t StartAddress() const { return m_start; }
+    mach_vm_address_t EndAddress() const { return m_start + m_size; }
+    mach_vm_address_t BytesRemaining(mach_vm_address_t addr) const
+    {
+        if (ContainsAddress(addr))
+            return m_size - (addr - m_start);
+        else
+            return 0;
+    }
+    bool ContainsAddress(mach_vm_address_t addr) const
+    {
+        return addr >= StartAddress() && addr < EndAddress();
+    }
+
+    bool SetProtections(mach_vm_address_t addr, mach_vm_size_t size, vm_prot_t prot);
+    bool RestoreProtections();
+    bool GetRegionForAddress(lldb::addr_t addr);
+protected:
+#if defined (VM_REGION_SUBMAP_SHORT_INFO_COUNT_64)
+    typedef vm_region_submap_short_info_data_64_t RegionInfo;
+    enum { kRegionInfoSize = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64 };
+#else
+    typedef vm_region_submap_info_data_64_t RegionInfo;
+    enum { kRegionInfoSize = VM_REGION_SUBMAP_INFO_COUNT_64 };
+#endif
+
+    task_t              m_task;
+    mach_vm_address_t   m_addr;
+    lldb_private::Error m_err;
+    mach_vm_address_t   m_start;
+    mach_vm_size_t      m_size;
+    natural_t           m_depth;
+    RegionInfo          m_data;
+    vm_prot_t           m_curr_protection;    // The current, possibly modified protections. Original value is saved in m_data.protections.
+    mach_vm_address_t   m_protection_addr;    // The start address at which protections were changed
+    mach_vm_size_t      m_protection_size;    // The size of memory that had its protections changed
+
+};
+
+#endif    // #ifndef liblldb_MachVMRegion_h_
diff --git a/source/Plugins/Process/MacOSX-User/source/MacOSX/ProcessControl-mig.defs b/source/Plugins/Process/MacOSX-User/source/MacOSX/ProcessControl-mig.defs
new file mode 100644
index 0000000..7f16fe1
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/MacOSX/ProcessControl-mig.defs
@@ -0,0 +1,16 @@
+/*
+ * nub.defs
+ */
+ 
+/*
+ * DNBConfig.h is autogenerated by a perl script that is run as a build
+ * script in XCode. XCode is responsible for calling the script and setting
+ * the include paths correctly to locate it. The file will exist in the
+ * derived sources directory in the build folder.
+ *
+ */
+
+#include "DNBConfig.h"
+
+
+#include <mach/mach_exc.defs>
diff --git a/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp b/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp
new file mode 100644
index 0000000..3c37b64
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp
@@ -0,0 +1,2228 @@
+//===-- ProcessMacOSX.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 <mach/mach.h>
+#include <mach/mach_vm.h>
+#include <spawn.h>
+#include <sys/fcntl.h>
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <unistd.h>
+
+// C++ Includes
+#include <algorithm>
+#include <map>
+
+// Other libraries and framework includes
+
+#include "lldb/Breakpoint/WatchpointLocation.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/State.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Host/TimeValue.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/TargetList.h"
+#include "PseudoTerminal.h"
+
+#if defined (__arm__)
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <SpringBoardServices/SpringBoardServer.h>
+#include <SpringBoardServices/SBSWatchdogAssertion.h>
+
+#endif  // #if defined (__arm__)
+
+// Project includes
+#include "lldb/Host/Host.h"
+#include "ProcessMacOSX.h"
+#include "ProcessMacOSXLog.h"
+#include "ThreadMacOSX.h"
+
+
+#if 0
+#define DEBUG_LOG(fmt, ...) printf(fmt, ## __VA_ARGS__)
+#else
+#define DEBUG_LOG(fmt, ...)
+#endif
+
+#ifndef MACH_PROCESS_USE_POSIX_SPAWN
+#define MACH_PROCESS_USE_POSIX_SPAWN 1
+#endif
+
+
+#if defined (__arm__)
+
+static bool
+IsSBProcess (lldb::pid_t pid)
+{
+    bool opt_runningApps = true;
+    bool opt_debuggable = false;
+
+    CFReleaser<CFArrayRef> sbsAppIDs (::SBSCopyApplicationDisplayIdentifiers (opt_runningApps, opt_debuggable));
+    if (sbsAppIDs.get() != NULL)
+    {
+        CFIndex count = ::CFArrayGetCount (sbsAppIDs.get());
+        CFIndex i = 0;
+        for (i = 0; i < count; i++)
+        {
+            CFStringRef displayIdentifier = (CFStringRef)::CFArrayGetValueAtIndex (sbsAppIDs.get(), i);
+
+            // Get the process id for the app (if there is one)
+            lldb::pid_t sbs_pid = LLDB_INVALID_PROCESS_ID;
+            if (::SBSProcessIDForDisplayIdentifier ((CFStringRef)displayIdentifier, &sbs_pid) == TRUE)
+            {
+                if (sbs_pid == pid)
+                    return true;
+            }
+        }
+    }
+    return false;
+}
+
+
+#endif  // #if defined (__arm__)
+
+using namespace lldb;
+using namespace lldb_private;
+//
+//void *
+//ProcessMacOSX::WaitForChildProcessToExit (void *pid_ptr)
+//{
+//    const lldb::pid_t pid = *((lldb::user_id_t *)pid_ptr);
+//
+//    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_THREAD);
+//
+//    if (log)
+//        log->Printf ("ProcessMacOSX::%s (arg = %p) thread starting...", __FUNCTION__, pid_ptr);
+//
+//    int status = -1;
+//
+//    while (1)
+//    {
+//        if (log)
+//            log->Printf("::waitpid (pid = %i, stat_loc = %p, options = 0)...", pid, &status);
+//
+//        lldb::pid_t return_pid = ::waitpid (pid, &status, 0);
+//
+//        if (return_pid < 0)
+//        {
+//            if (log)
+//                log->Printf("%s ::waitpid (pid = %i, stat_loc = %p, options = 0) => errno = %i, status = 0x%8.8x", pid, &status, errno, status);
+//            break;
+//        }
+//
+//        bool set_exit_status = false;
+//        if (WIFSTOPPED(status))
+//        {
+//            if (log)
+//                log->Printf("::waitpid (pid = %i, stat_loc = %p, options = 0) => return_pid = %i, status = 0x%8.8x (STOPPED)", pid, &status, return_pid, status);
+//        }
+//        else if (WIFEXITED(status))
+//        {
+//            set_exit_status = true;
+//            if (log)
+//                log->Printf("::waitpid (pid = %i, stat_loc = %p, options = 0) => return_pid = %i, status = 0x%8.8x (EXITED)", pid, &status, return_pid, status);
+//        }
+//        else if (WIFSIGNALED(status))
+//        {
+//            set_exit_status = true;
+//            if (log)
+//                log->Printf("::waitpid (pid = %i, stat_loc = %p, options = 0) => return_pid = %i, status = 0x%8.8x (SIGNALED)", pid, &status, return_pid, status);
+//        }
+//        else
+//        {
+//            if (log)
+//                log->Printf("::waitpid (pid = %i, stat_loc = %p, options = 0) => return_pid = %i, status = 0x%8.8x", pid, &status, return_pid, status);
+//        }
+//
+//        if (set_exit_status)
+//        {
+//            // Try and deliver the news to the process if it is still around
+//            TargetSP target_sp(TargetList::SharedList().FindTargetWithProcessID (return_pid));
+//            if (target_sp.get())
+//            {
+//                ProcessMacOSX *process = dynamic_cast<ProcessMacOSX*>(target_sp->GetProcess().get());
+//                if (process)
+//                {
+//                    process->SetExitStatus (status);
+//                    if (log)
+//                        log->Printf("Setting exit status of %i to 0x%8.8x", pid, status);
+//                    process->Task().ShutDownExceptionThread();
+//                }
+//            }
+//            // Break out of the loop and return.
+//            break;
+//        }
+//    }
+//
+//    if (log)
+//        log->Printf ("ProcessMacOSX::%s (arg = %p) thread exiting...", __FUNCTION__, pid_ptr);
+//
+//    return NULL;
+//}
+//
+
+const char *
+ProcessMacOSX::GetPluginNameStatic()
+{
+    return "process.macosx";
+}
+
+const char *
+ProcessMacOSX::GetPluginDescriptionStatic()
+{
+    return "Native MacOSX user process debugging plug-in.";
+}
+
+void
+ProcessMacOSX::Terminate()
+{
+    PluginManager::UnregisterPlugin (ProcessMacOSX::CreateInstance);
+}
+
+
+Process*
+ProcessMacOSX::CreateInstance (Target &target, Listener &listener)
+{
+    ProcessMacOSX::Initialize();
+
+    return new ProcessMacOSX (target, listener);
+}
+
+bool
+ProcessMacOSX::CanDebug(Target &target)
+{
+    // For now we are just making sure the file exists for a given module
+    ModuleSP exe_module_sp(target.GetExecutableModule());
+    if (exe_module_sp.get())
+        return exe_module_sp->GetFileSpec().Exists();
+    return false;
+}
+
+//----------------------------------------------------------------------
+// ProcessMacOSX constructor
+//----------------------------------------------------------------------
+ProcessMacOSX::ProcessMacOSX(Target& target, Listener &listener) :
+    Process (target, listener),
+    m_dynamic_loader_ap (),
+//    m_wait_thread (LLDB_INVALID_HOST_THREAD),
+    m_byte_order (eByteOrderHost),
+    m_stdio_ours (false),
+    m_child_stdin (-1),
+    m_child_stdout (-1),
+    m_child_stderr (-1),
+    m_task (this),
+    m_flags (eFlagsNone),
+    m_stdio_thread (LLDB_INVALID_HOST_THREAD),
+    m_stdio_mutex (Mutex::eMutexTypeRecursive),
+    m_stdout_data (),
+    m_exception_messages (),
+    m_exception_messages_mutex (Mutex::eMutexTypeRecursive),
+    m_arch_spec ()
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ProcessMacOSX::~ProcessMacOSX()
+{
+//  m_mach_process.UnregisterNotificationCallbacks (this);
+    Clear();
+}
+
+//----------------------------------------------------------------------
+// PluginInterface
+//----------------------------------------------------------------------
+const char *
+ProcessMacOSX::GetPluginName()
+{
+    return "Process debugging plug-in for MacOSX";
+}
+
+const char *
+ProcessMacOSX::GetShortPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+ProcessMacOSX::GetPluginVersion()
+{
+    return 1;
+}
+
+void
+ProcessMacOSX::GetPluginCommandHelp (const char *command, Stream *strm)
+{
+    strm->Printf("The following arguments can be supplied to the 'log %s' command:\n", GetShortPluginName());
+    strm->PutCString("\tverbose - enable verbose logging\n");
+    strm->PutCString("\tprocess - enable process logging\n");
+    strm->PutCString("\tthread - enable thread logging\n");
+    strm->PutCString("\texceptions - enable exception logging\n");
+    strm->PutCString("\tdynamic - enable DynamicLoader logging\n");
+    strm->PutCString("\tmemory-calls - enable memory read and write call logging\n");
+    strm->PutCString("\tmemory-data-short - log short memory read and write byte data\n");
+    strm->PutCString("\tmemory-data-long - log all memory read and write byte data\n");
+    strm->PutCString("\tmemory-protections - log memory protection calls\n");
+    strm->PutCString("\tbreakpoints - log breakpoint calls\n");
+    strm->PutCString("\twatchpoints - log watchpoint calls\n");
+    strm->PutCString("\tevents - log event and event queue status\n");
+    strm->PutCString("\tstep - log step related activity\n");
+    strm->PutCString("\ttask - log task functions\n");
+}
+
+Error
+ProcessMacOSX::ExecutePluginCommand (Args &command, Stream *strm)
+{
+    Error error;
+    error.SetErrorString("No plug-in command are currently supported.");
+    return error;
+}
+
+Log *
+ProcessMacOSX::EnablePluginLogging (Stream *strm, Args &command)
+{
+    return NULL;
+}
+
+//----------------------------------------------------------------------
+// Process Control
+//----------------------------------------------------------------------
+Error
+ProcessMacOSX::DoLaunch
+(
+    Module* module,
+    char const *argv[],
+    char const *envp[],
+    const char *stdin_path,
+    const char *stdout_path,
+    const char *stderr_path
+)
+{
+//  ::LogSetBitMask (PD_LOG_DEFAULT);
+//  ::LogSetOptions (LLDB_LOG_OPTION_THREADSAFE | LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD);
+//  ::LogSetLogFile ("/dev/stdout");
+
+    Error error;
+    ObjectFile * object_file = module->GetObjectFile();
+    if (object_file)
+    {
+        ArchSpec arch_spec(module->GetArchitecture());
+
+        // Set our user ID to our process ID.
+        SetID (LaunchForDebug(argv[0], argv, envp, arch_spec, stdin_path, stdout_path, stderr_path, eLaunchDefault, error));
+    }
+    else
+    {
+        // Set our user ID to an invalid process ID.
+        SetID (LLDB_INVALID_PROCESS_ID);
+        error.SetErrorToGenericError ();
+        error.SetErrorStringWithFormat("Failed to get object file from '%s' for arch %s.\n", module->GetFileSpec().GetFilename().AsCString(), module->GetArchitecture().AsCString());
+    }
+
+    // Return the process ID we have
+    return error;
+}
+
+Error
+ProcessMacOSX::DoAttach (lldb::pid_t attach_pid)
+{
+    Error error;
+
+    // Clear out and clean up from any current state
+    Clear();
+    // HACK: require arch be set correctly at the target level until we can
+    // figure out a good way to determine the arch of what we are attaching to
+    m_arch_spec = m_target.GetArchitecture();
+
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_PROCESS);
+    if (attach_pid != LLDB_INVALID_PROCESS_ID)
+    {
+        SetPrivateState (eStateAttaching);
+        SetID(attach_pid);
+        // Let ourselves know we are going to be using SBS if the correct flag bit is set...
+#if defined (__arm__)
+        if (IsSBProcess(pid))
+            m_flags |= eFlagsUsingSBS;
+#endif
+
+        if (Task().GetTaskPortForProcessID(error) == TASK_NULL)
+        {
+            if (log)
+                log->Printf ("error attaching to pid %i: %s", GetID(), error.AsCString());
+
+        }
+        else
+        {
+            Task().StartExceptionThread(error);
+
+            if (error.Success())
+            {
+                errno = 0;
+                if (::ptrace (PT_ATTACHEXC, GetID(), 0, 0) == 0)
+                {
+                    m_flags.Set (eFlagsAttached);
+                    // Sleep a bit to let the exception get received and set our process status
+                    // to stopped.
+                    ::usleep(250000);
+
+                    if (log)
+                        log->Printf ("successfully attached to pid %d", GetID());
+                    return error;
+                }
+                else
+                {
+                    error.SetErrorToErrno();
+                    if (log)
+                        log->Printf ("error: failed to attach to pid %d", GetID());
+                }
+            }
+            else
+            {
+                if (log)
+                    log->Printf ("error: failed to start exception thread for pid %d: %s", GetID(), error.AsCString());
+            }
+
+        }
+    }
+    SetID (LLDB_INVALID_PROCESS_ID);
+    if (error.Success())
+        error.SetErrorStringWithFormat ("failed to attach to pid %d", attach_pid);
+    return error;
+}
+
+Error
+ProcessMacOSX::WillLaunchOrAttach ()
+{
+    Error error;
+    // TODO: this is hardcoded for macosx right now. We need this to be more dynamic
+    m_dynamic_loader_ap.reset(DynamicLoader::FindPlugin(this, "dynamic-loader.macosx-dyld"));
+
+    if (m_dynamic_loader_ap.get() == NULL)
+        error.SetErrorString("unable to find the dynamic loader named 'dynamic-loader.macosx-dyld'");
+    
+    return error;
+}
+
+
+Error
+ProcessMacOSX::WillLaunch (Module* module)
+{
+    return WillLaunchOrAttach ();
+}
+
+void
+ProcessMacOSX::DidLaunchOrAttach ()
+{
+    if (GetID() == LLDB_INVALID_PROCESS_ID)
+    {
+        m_dynamic_loader_ap.reset();
+    }
+    else
+    {
+        Module * exe_module = GetTarget().GetExecutableModule ().get();
+        assert (exe_module);
+
+        m_arch_spec = exe_module->GetArchitecture();
+        assert (m_arch_spec.IsValid());
+
+        ObjectFile *exe_objfile = exe_module->GetObjectFile();
+        assert (exe_objfile);
+
+        m_byte_order = exe_objfile->GetByteOrder();
+        assert (m_byte_order != eByteOrderInvalid);
+        // Install a signal handler so we can catch when our child process
+        // dies and set the exit status correctly.
+
+        Host::StartMonitoringChildProcess (Process::SetProcessExitStatus, NULL, GetID(), false);
+
+        if (m_arch_spec == ArchSpec("arm"))
+        {
+            // On ARM we want the actual target triple of the OS to get the
+            // most capable ARM slice for the process. Since this plug-in is
+            // only used for doing native debugging this will work.
+            m_target_triple = Host::GetTargetTriple();
+        }
+        else
+        {
+            // We want the arch of the process, and the vendor and OS from the
+            // host OS.
+            StreamString triple;
+
+            triple.Printf("%s-%s-%s", 
+                          m_arch_spec.AsCString(), 
+                          Host::GetVendorString().AsCString("apple"), 
+                          Host::GetOSString().AsCString("darwin"));
+
+            m_target_triple.SetCString(triple.GetString().c_str());
+        }
+    }
+}
+
+void
+ProcessMacOSX::DidLaunch ()
+{
+    ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "ProcessMacOSX::DidLaunch()");
+    DidLaunchOrAttach ();
+    if (m_dynamic_loader_ap.get())
+        m_dynamic_loader_ap->DidLaunch();
+}
+
+void
+ProcessMacOSX::DidAttach ()
+{
+    DidLaunchOrAttach ();
+    if (m_dynamic_loader_ap.get())
+        m_dynamic_loader_ap->DidAttach();
+}
+
+Error
+ProcessMacOSX::WillAttach (lldb::pid_t pid)
+{
+    return WillLaunchOrAttach ();
+}
+
+Error
+ProcessMacOSX::DoResume ()
+{
+    Error error;
+    ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "ProcessMacOSX::Resume()");
+    const StateType state = m_private_state.GetValue();
+
+    if (CanResume(state))
+    {
+        error = PrivateResume(LLDB_INVALID_THREAD_ID);
+    }
+    else if (state == eStateRunning)
+    {
+        ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "Resume() - task 0x%x is running, ignoring...", Task().GetTaskPort());
+    }
+    else
+    {
+        error.SetErrorStringWithFormat("task 0x%x can't continue, ignoring...", Task().GetTaskPort());
+        ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "Resume() - task 0x%x can't continue, ignoring...", Task().GetTaskPort());
+    }
+    return error;
+}
+
+size_t
+ProcessMacOSX::GetSoftwareBreakpointTrapOpcode (BreakpointSite* bp_site)
+{
+    const uint8_t *trap_opcode = NULL;
+    uint32_t trap_opcode_size = 0;
+
+    static const uint8_t g_arm_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 };
+    //static const uint8_t g_thumb_breakpooint_opcode[] = { 0xFE, 0xDE };
+    static const uint8_t g_ppc_breakpoint_opcode[] = { 0x7F, 0xC0, 0x00, 0x08 };
+    static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC };
+
+    switch (m_arch_spec.GetCPUType())
+    {
+    case CPU_TYPE_ARM:
+        // TODO: fill this in for ARM. We need to dig up the symbol for
+        // the address in the breakpoint locaiton and figure out if it is
+        // an ARM or Thumb breakpoint.
+        trap_opcode = g_arm_breakpoint_opcode;
+        trap_opcode_size = sizeof(g_arm_breakpoint_opcode);
+        break;
+
+    case CPU_TYPE_POWERPC:
+    case CPU_TYPE_POWERPC64:
+        trap_opcode = g_ppc_breakpoint_opcode;
+        trap_opcode_size = sizeof(g_ppc_breakpoint_opcode);
+        break;
+
+    case CPU_TYPE_I386:
+    case CPU_TYPE_X86_64:
+        trap_opcode = g_i386_breakpoint_opcode;
+        trap_opcode_size = sizeof(g_i386_breakpoint_opcode);
+        break;
+
+    default:
+        assert(!"Unhandled architecture in ProcessMacOSX::GetSoftwareBreakpointTrapOpcode()");
+        return 0;
+    }
+
+    if (trap_opcode && trap_opcode_size)
+    {
+        if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
+            return trap_opcode_size;
+    }
+    return 0;
+}
+uint32_t
+ProcessMacOSX::UpdateThreadListIfNeeded ()
+{
+    // locker will keep a mutex locked until it goes out of scope
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_THREAD);
+    if (log && log->GetMask().IsSet(PD_LOG_VERBOSE))
+        log->Printf ("ProcessMacOSX::%s (pid = %4.4x)", __FUNCTION__, GetID());
+
+    const uint32_t stop_id = GetStopID();
+    if (m_thread_list.GetSize(false) == 0 || stop_id != m_thread_list.GetStopID())
+    {
+        // Update the thread list's stop id immediately so we don't recurse into this function.
+        thread_array_t thread_list = NULL;
+        mach_msg_type_number_t thread_list_count = 0;
+        task_t task = Task().GetTaskPort();
+        Error err(::task_threads (task, &thread_list, &thread_list_count), eErrorTypeMachKernel);
+
+        if (log || err.Fail())
+            err.PutToLog(log, "::task_threads ( task = 0x%4.4x, thread_list => %p, thread_list_count => %u )", task, thread_list, thread_list_count);
+
+        if (err.GetError() == KERN_SUCCESS && thread_list_count > 0)
+        {
+            ThreadList curr_thread_list (this);
+            curr_thread_list.SetStopID(stop_id);
+
+            size_t idx;
+            // Iterator through the current thread list and see which threads
+            // we already have in our list (keep them), which ones we don't
+            // (add them), and which ones are not around anymore (remove them).
+            for (idx = 0; idx < thread_list_count; ++idx)
+            {
+                const lldb::tid_t tid = thread_list[idx];
+                ThreadSP thread_sp(GetThreadList().FindThreadByID (tid, false));
+                if (thread_sp.get() == NULL)
+                    thread_sp.reset (new ThreadMacOSX (*this, tid));
+                curr_thread_list.AddThread(thread_sp);
+            }
+
+            m_thread_list = curr_thread_list;
+
+            // Free the vm memory given to us by ::task_threads()
+            vm_size_t thread_list_size = (vm_size_t) (thread_list_count * sizeof (lldb::tid_t));
+            ::vm_deallocate (::mach_task_self(),
+                             (vm_address_t)thread_list,
+                             thread_list_size);
+        }
+    }
+    return GetThreadList().GetSize(false);
+}
+
+
+void
+ProcessMacOSX::RefreshStateAfterStop ()
+{
+    // If we are attaching, let our dynamic loader plug-in know so it can get
+    // an initial list of shared libraries.
+
+    // We must be attaching if we don't already have a valid architecture
+    if (!m_arch_spec.IsValid())
+    {
+        Module *exe_module = GetTarget().GetExecutableModule().get();
+        if (exe_module)
+            m_arch_spec = exe_module->GetArchitecture();
+    }
+    // Discover new threads:
+    UpdateThreadListIfNeeded ();
+
+    // Let all threads recover from stopping and do any clean up based
+    // on the previous thread state (if any).
+    m_thread_list.RefreshStateAfterStop();
+
+   // Let each thread know of any exceptions
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_EXCEPTIONS);
+    task_t task = Task().GetTaskPort();
+    size_t i;
+    for (i=0; i<m_exception_messages.size(); ++i)
+    {
+        // Let the thread list figure use the ProcessMacOSX to forward all exceptions
+        // on down to each thread.
+        if (m_exception_messages[i].state.task_port == task)
+        {
+            ThreadSP thread_sp(m_thread_list.FindThreadByID(m_exception_messages[i].state.thread_port));
+            if (thread_sp.get())
+            {
+                ThreadMacOSX *macosx_thread = (ThreadMacOSX *)thread_sp.get();
+                macosx_thread->NotifyException (m_exception_messages[i].state);
+            }
+        }
+        if (log)
+            m_exception_messages[i].PutToLog(log);
+    }
+
+}
+
+Error
+ProcessMacOSX::DoHalt ()
+{
+    return Signal (SIGSTOP);
+}
+
+Error
+ProcessMacOSX::WillDetach ()
+{
+    Error error;
+    const StateType state = m_private_state.GetValue();
+
+    if (IsRunning(state))
+    {
+        error.SetErrorToGenericError();
+        error.SetErrorString("Process must be stopped in order to detach.");
+    }
+    return error;
+}
+
+Error
+ProcessMacOSX::DoSIGSTOP (bool clear_all_breakpoints)
+{
+    Error error;
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_PROCESS);
+
+    if (log)
+        log->Printf ("ProcessMacOSX::DoSIGSTOP()");
+    EventSP event_sp;
+    TimeValue timeout_time;
+
+    StateType state = m_private_state.GetValue();
+
+    lldb::pid_t pid = GetID();
+
+    if (IsRunning(state))
+    {
+        // If our process is running, we need to SIGSTOP it so we can detach.
+        if (log)
+            log->Printf ("ProcessMacOSX::DoDestroy() - kill (%i, SIGSTOP)", pid);
+
+        // Send the SIGSTOP and wait a few seconds for it to stop
+
+        // Pause the Private State Thread so it doesn't intercept the events we need to wait for.
+        PausePrivateStateThread();
+
+        m_thread_list.DiscardThreadPlans();
+
+        // First jettison all the current thread plans, since we want to make sure it
+        // really just stops.
+
+        if (::kill (pid, SIGSTOP) == 0)
+            error.Clear();
+        else
+            error.SetErrorToErrno();
+
+        if (error.Fail())
+            error.PutToLog(log, "::kill (pid = %i, SIGSTOP)", pid);
+
+        timeout_time = TimeValue::Now();
+        timeout_time.OffsetWithSeconds(2);
+
+        state = WaitForStateChangedEventsPrivate (&timeout_time, event_sp);
+
+        // Resume the private state thread at this point.
+        ResumePrivateStateThread();
+
+        if (!StateIsStoppedState (state))
+        {
+            if (log)
+                log->Printf("ProcessMacOSX::DoSIGSTOP() failed to stop after sending SIGSTOP");
+           return error;
+        }
+        if (clear_all_breakpoints)
+            GetTarget().DisableAllBreakpoints();
+    }
+    else if (!HasExited(state))
+    {
+        if (clear_all_breakpoints)
+            GetTarget().DisableAllBreakpoints();
+
+//        const uint32_t num_threads = GetNumThreads();
+//        for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx)
+//        {
+//            Thread *thread = GetThreadAtIndex(thread_idx);
+//            thread->SetResumeState(eStateRunning);
+//            if (thread_idx == 0)
+//                thread->SetResumeSignal(SIGSTOP);
+//        }
+
+        // Our process was stopped, so resume it and then SIGSTOP it so we can
+        // detach.
+        // But discard all the thread plans first, so we don't keep going because we
+        // are in mid-plan.
+
+        // Pause the Private State Thread so it doesn't intercept the events we need to wait for.
+        PausePrivateStateThread();
+
+        m_thread_list.DiscardThreadPlans();
+
+        if (::kill (pid, SIGSTOP) == 0)
+            error.Clear();
+        else
+            error.SetErrorToErrno();
+
+        if (log || error.Fail())
+            error.PutToLog(log, "ProcessMacOSX::DoSIGSTOP() ::kill (pid = %i, SIGSTOP)", pid);
+
+        error = PrivateResume(LLDB_INVALID_THREAD_ID);
+
+        // Wait a few seconds for our process to resume
+        timeout_time = TimeValue::Now();
+        timeout_time.OffsetWithSeconds(2);
+        state = WaitForStateChangedEventsPrivate (&timeout_time, event_sp);
+
+        // Make sure the process resumed
+        if (StateIsStoppedState (state))
+        {
+            if (log)
+                log->Printf ("ProcessMacOSX::DoSIGSTOP() couldn't resume process, state = %s", StateAsCString(state));
+            error.SetErrorStringWithFormat("ProcessMacOSX::DoSIGSTOP() couldn't resume process, state = %s", StateAsCString(state));
+        }
+        else
+        {
+            // Send the SIGSTOP and wait a few seconds for it to stop
+            timeout_time = TimeValue::Now();
+            timeout_time.OffsetWithSeconds(2);
+            state = WaitForStateChangedEventsPrivate (&timeout_time, event_sp);
+            if (!StateIsStoppedState (state))
+            {
+                if (log)
+                    log->Printf("ProcessMacOSX::DoSIGSTOP() failed to stop after sending SIGSTOP");
+                error.SetErrorString("ProcessMacOSX::DoSIGSTOP() failed to stop after sending SIGSTOP");
+            }
+        }
+        // Resume the private state thread at this point.
+        ResumePrivateStateThread();
+    }
+
+    return error;
+}
+
+Error
+ProcessMacOSX::DoDestroy ()
+{
+    Error error;
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_PROCESS);
+    if (log)
+        log->Printf ("ProcessMacOSX::DoDestroy()");
+
+    error = DoSIGSTOP (true);
+    if (error.Success())
+    {
+        StopSTDIOThread(true);
+
+        if (log)
+            log->Printf ("ProcessMacOSX::DoDestroy() DoSIGSTOP succeeded");
+        const StateType state = m_private_state.GetValue();
+        // Scope for "locker" so we can reply to all of our exceptions (the SIGSTOP
+        // exception).
+        {
+            Mutex::Locker locker(m_exception_messages_mutex);
+            ReplyToAllExceptions();
+        }
+        if (log)
+            log->Printf ("ProcessMacOSX::DoDestroy() replied to all exceptions");
+
+        // Shut down the exception thread and cleanup our exception remappings
+        Task().ShutDownExceptionThread();
+
+        if (log)
+            log->Printf ("ProcessMacOSX::DoDestroy() exception thread has been shutdown");
+
+        if (!HasExited(state))
+        {
+            lldb::pid_t pid = GetID();
+
+            // Detach from our process while we are stopped.
+            errno = 0;
+
+            // Detach from our process
+            ::ptrace (PT_KILL, pid, 0, 0);
+
+            error.SetErrorToErrno();
+
+            if (log || error.Fail())
+                error.PutToLog (log, "::ptrace (PT_KILL, %u, 0, 0)", pid);
+
+            // Resume our task and let the SIGKILL do its thing. The thread named
+            // "ProcessMacOSX::WaitForChildProcessToExit(void*)" will catch the
+            // process exiting, so we don't need to set our state to exited in this
+            // function.
+            Task().Resume();
+        }
+
+        // NULL our task out as we have already retored all exception ports
+        Task().Clear();
+
+        // Clear out any notion of the process we once were
+        Clear();
+    }
+    return error;
+}
+
+ByteOrder
+ProcessMacOSX::GetByteOrder () const
+{
+    return m_byte_order;
+}
+
+//------------------------------------------------------------------
+// Process Queries
+//------------------------------------------------------------------
+
+bool
+ProcessMacOSX::IsAlive ()
+{
+    return MachTask::IsValid (Task().GetTaskPort());
+}
+
+lldb::addr_t
+ProcessMacOSX::GetImageInfoAddress()
+{
+    return Task().GetDYLDAllImageInfosAddress();
+}
+
+DynamicLoader *
+ProcessMacOSX::GetDynamicLoader()
+{
+    return m_dynamic_loader_ap.get();
+}
+
+//------------------------------------------------------------------
+// Process Memory
+//------------------------------------------------------------------
+
+size_t
+ProcessMacOSX::DoReadMemory (lldb::addr_t addr, void *buf, size_t size, Error& error)
+{
+    return Task().ReadMemory(addr, buf, size, error);
+}
+
+size_t
+ProcessMacOSX::DoWriteMemory (lldb::addr_t addr, const void *buf, size_t size, Error& error)
+{
+    return Task().WriteMemory(addr, buf, size, error);
+}
+
+lldb::addr_t
+ProcessMacOSX::DoAllocateMemory (size_t size, uint32_t permissions, Error& error)
+{
+    return Task().AllocateMemory (size, permissions, error);
+}
+
+Error
+ProcessMacOSX::DoDeallocateMemory (lldb::addr_t ptr)
+{
+    return Task().DeallocateMemory (ptr);
+}
+
+//------------------------------------------------------------------
+// Process STDIO
+//------------------------------------------------------------------
+
+size_t
+ProcessMacOSX::GetSTDOUT (char *buf, size_t buf_size, Error &error)
+{
+    error.Clear();
+    Mutex::Locker locker(m_stdio_mutex);
+    size_t bytes_available = m_stdout_data.size();
+    if (bytes_available > 0)
+    {
+        ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "ProcessMacOSX::%s (&%p[%u]) ...", __FUNCTION__, buf, buf_size);
+        if (bytes_available > buf_size)
+        {
+            memcpy(buf, m_stdout_data.data(), buf_size);
+            m_stdout_data.erase(0, buf_size);
+            bytes_available = buf_size;
+        }
+        else
+        {
+            memcpy(buf, m_stdout_data.data(), bytes_available);
+            m_stdout_data.clear();
+
+            //ResetEventBits(eBroadcastBitSTDOUT);
+        }
+    }
+    return bytes_available;
+}
+
+size_t
+ProcessMacOSX::GetSTDERR (char *buf, size_t buf_size, Error &error)
+{
+    error.Clear();
+    return 0;
+}
+
+size_t
+ProcessMacOSX::PutSTDIN (const char *buf, size_t buf_size, Error &error)
+{
+    if (m_child_stdin == -1)
+    {
+        error.SetErrorString ("Invalid child stdin handle.");
+    }
+    else
+    {
+        ssize_t bytes_written = ::write (m_child_stdin, buf, buf_size);
+        if (bytes_written == -1)
+            error.SetErrorToErrno();
+        else
+        {
+            error.Clear();
+            return bytes_written;
+        }
+    }
+    return 0;
+}
+
+Error
+ProcessMacOSX::EnableBreakpoint (BreakpointSite *bp_site)
+{
+    Error error;
+    assert (bp_site != NULL);
+    const lldb::addr_t addr = bp_site->GetLoadAddress();
+    const lldb::user_id_t site_id = bp_site->GetID();
+
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_BREAKPOINTS);
+    if (log)
+        log->Printf ("ProcessMacOSX::EnableBreakpoint (site_id = %d) addr = 0x%8.8llx", site_id, (uint64_t)addr);
+
+    if (bp_site->IsEnabled())
+    {
+        if (log)
+            log->Printf ("ProcessMacOSX::EnableBreakpoint (site_id = %d) addr = 0x%8.8llx -- SUCCESS (already enabled)", site_id, (uint64_t)addr);
+        return error;
+    }
+
+    if (bp_site->HardwarePreferred())
+    {
+        ThreadMacOSX *thread = (ThreadMacOSX *)m_thread_list.FindThreadByID(bp_site->GetThreadID()).get();
+        if (thread)
+        {
+            bp_site->SetHardwareIndex (thread->SetHardwareBreakpoint(bp_site));
+            if (bp_site->IsHardware())
+            {
+                bp_site->SetEnabled(true);
+                return error;
+            }
+        }
+    }
+
+    // Just let lldb::Process::EnableSoftwareBreakpoint() handle everything...
+    return EnableSoftwareBreakpoint (bp_site);
+}
+
+Error
+ProcessMacOSX::DisableBreakpoint (BreakpointSite *bp_site)
+{
+    Error error;
+    assert (bp_site != NULL);
+    const lldb::addr_t addr = bp_site->GetLoadAddress();
+    const lldb::user_id_t site_id = bp_site->GetID();
+
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_BREAKPOINTS);
+    if (log)
+        log->Printf ("ProcessMacOSX::DisableBreakpoint (site_id = %d) addr = 0x%8.8llx", site_id, (uint64_t)addr);
+
+    if (bp_site->IsHardware())
+    {
+        ThreadMacOSX *thread = (ThreadMacOSX *)m_thread_list.FindThreadByID(bp_site->GetThreadID()).get();
+        if (thread)
+        {
+            if (thread->ClearHardwareBreakpoint(bp_site))
+            {
+                bp_site->SetEnabled(false);
+                if (log)
+                    log->Printf ("ProcessMacOSX::DisableBreakpoint (site_id = %d) addr = 0x%8.8llx -- SUCCESS (hardware)", site_id, (uint64_t)addr);
+                return error;
+            }
+        }
+        error.SetErrorString("hardware breakpoints are no supported");
+        return error;
+    }
+
+    // Just let lldb::Process::EnableSoftwareBreakpoint() handle everything...
+    return DisableSoftwareBreakpoint (bp_site);
+}
+
+Error
+ProcessMacOSX::EnableWatchpoint (WatchpointLocation *wp)
+{
+    Error error;
+    if (wp)
+    {
+        lldb::user_id_t watchID = wp->GetID();
+        lldb::addr_t addr = wp->GetLoadAddress();
+        Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_WATCHPOINTS);
+        if (log)
+            log->Printf ("ProcessMacOSX::EnableWatchpoint(watchID = %d)", watchID);
+        if (wp->IsEnabled())
+        {
+            if (log)
+                log->Printf("ProcessMacOSX::EnableWatchpoint(watchID = %d) addr = 0x%8.8llx: watchpoint already enabled.", watchID, (uint64_t)addr);
+            return error;
+        }
+        else
+        {
+            ThreadMacOSX *thread = (ThreadMacOSX *)m_thread_list.FindThreadByID(wp->GetThreadID()).get();
+            if (thread)
+            {
+                wp->SetHardwareIndex (thread->SetHardwareWatchpoint (wp));
+                if (wp->IsHardware ())
+                {
+                    wp->SetEnabled(true);
+                    return error;
+                }
+            }
+            else
+            {
+                error.SetErrorString("Watchpoints currently only support thread specific watchpoints.");
+            }
+        }
+    }
+    return error;
+}
+
+Error
+ProcessMacOSX::DisableWatchpoint (WatchpointLocation *wp)
+{
+    Error error;
+    if (wp)
+    {
+        lldb::user_id_t watchID = wp->GetID();
+
+        Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_WATCHPOINTS);
+
+        lldb::addr_t addr = wp->GetLoadAddress();
+        if (log)
+            log->Printf ("ProcessMacOSX::DisableWatchpoint (watchID = %d) addr = 0x%8.8llx", watchID, (uint64_t)addr);
+
+        if (wp->IsHardware())
+        {
+            ThreadMacOSX *thread = (ThreadMacOSX *)m_thread_list.FindThreadByID(wp->GetThreadID()).get();
+            if (thread)
+            {
+                if (thread->ClearHardwareWatchpoint (wp))
+                {
+                    wp->SetEnabled(false);
+                    if (log)
+                        log->Printf ("ProcessMacOSX::Disablewatchpoint (watchID = %d) addr = 0x%8.8llx (hardware) => success", watchID, (uint64_t)addr);
+                    return error;
+                }
+            }
+        }
+        // TODO: clear software watchpoints if we implement them
+        error.SetErrorToGenericError();
+    }
+    else
+    {
+        error.SetErrorString("Watchpoint location argument was NULL.");
+    }
+    return error;
+}
+
+
+static ProcessMacOSX::CreateArchCalback
+ArchCallbackMap(const ArchSpec& arch_spec, ProcessMacOSX::CreateArchCalback callback, bool add )
+{
+    // We must wrap the "g_arch_map" file static in a function to avoid
+    // any global constructors so we don't get a build verification error
+    typedef std::multimap<ArchSpec, ProcessMacOSX::CreateArchCalback> ArchToProtocolMap;
+    static ArchToProtocolMap g_arch_map;
+
+    if (add)
+    {
+        g_arch_map.insert(std::make_pair(arch_spec, callback));
+        return callback;
+    }
+    else
+    {
+        ArchToProtocolMap::const_iterator pos = g_arch_map.find(arch_spec);
+        if (pos != g_arch_map.end())
+        {
+            return pos->second;
+        }
+    }
+    return NULL;
+}
+
+void
+ProcessMacOSX::AddArchCreateCallback(const ArchSpec& arch_spec, CreateArchCalback callback)
+{
+    ArchCallbackMap (arch_spec, callback, true);
+}
+
+ProcessMacOSX::CreateArchCalback
+ProcessMacOSX::GetArchCreateCallback()
+{
+    return ArchCallbackMap (m_arch_spec, NULL, false);
+}
+
+void
+ProcessMacOSX::Clear()
+{
+    // Clear any cached thread list while the pid and task are still valid
+
+    Task().Clear();
+    // Now clear out all member variables
+    CloseChildFileDescriptors();
+
+    m_flags = eFlagsNone;
+    m_thread_list.Clear();
+    {
+        Mutex::Locker locker(m_exception_messages_mutex);
+        m_exception_messages.clear();
+    }
+
+}
+
+bool
+ProcessMacOSX::StartSTDIOThread()
+{
+    // If we created and own the child STDIO file handles, then we track the
+    // STDIO ourselves, else we let whomever owns these file handles track
+    // the IO themselves.
+    if (m_stdio_ours)
+    {
+        ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "ProcessMacOSX::%s ( )", __FUNCTION__);
+        // Create the thread that watches for the child STDIO
+        m_stdio_thread = Host::ThreadCreate ("<lldb.process.process-macosx.stdio>", ProcessMacOSX::STDIOThread, this, NULL);
+        return m_stdio_thread != LLDB_INVALID_HOST_THREAD;
+    }
+    return false;
+}
+
+
+void
+ProcessMacOSX::StopSTDIOThread(bool close_child_fds)
+{
+    ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "ProcessMacOSX::%s ( )", __FUNCTION__);
+    // Stop the stdio thread
+    if (m_stdio_thread != LLDB_INVALID_HOST_THREAD)
+    {
+        Host::ThreadCancel (m_stdio_thread, NULL);
+        thread_result_t result = NULL;
+        Host::ThreadJoin (m_stdio_thread, &result, NULL);
+        if (close_child_fds)
+            CloseChildFileDescriptors();
+        else
+        {
+            // We may have given up control of these file handles, so just
+            // set them to invalid values so the STDIO thread can exit when
+            // we interrupt it with pthread_cancel...
+            m_child_stdin = -1;
+            m_child_stdout = -1;
+            m_child_stderr = -1;
+        }
+    }
+}
+
+
+void *
+ProcessMacOSX::STDIOThread(void *arg)
+{
+    ProcessMacOSX *proc = (ProcessMacOSX*) arg;
+
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_PROCESS);
+    if (log)
+        log->Printf ("ProcessMacOSX::%s (arg = %p) thread starting...", __FUNCTION__, arg);
+
+    // We start use a base and more options so we can control if we
+    // are currently using a timeout on the mach_msg. We do this to get a
+    // bunch of related exceptions on our exception port so we can process
+    // then together. When we have multiple threads, we can get an exception
+    // per thread and they will come in consecutively. The main thread loop
+    // will start by calling mach_msg to without having the MACH_RCV_TIMEOUT
+    // flag set in the options, so we will wait forever for an exception on
+    // our exception port. After we get one exception, we then will use the
+    // MACH_RCV_TIMEOUT option with a zero timeout to grab all other current
+    // exceptions for our process. After we have received the last pending
+    // exception, we will get a timeout which enables us to then notify
+    // our main thread that we have an exception bundle avaiable. We then wait
+    // for the main thread to tell this exception thread to start trying to get
+    // exceptions messages again and we start again with a mach_msg read with
+    // infinite timeout.
+    Error err;
+    int stdout_fd = proc->GetStdoutFileDescriptor();
+    int stderr_fd = proc->GetStderrFileDescriptor();
+    if (stdout_fd == stderr_fd)
+        stderr_fd = -1;
+
+    while (stdout_fd >= 0 || stderr_fd >= 0)
+    {
+        //::pthread_testcancel ();
+
+        fd_set read_fds;
+        FD_ZERO (&read_fds);
+        if (stdout_fd >= 0)
+            FD_SET (stdout_fd, &read_fds);
+        if (stderr_fd >= 0)
+            FD_SET (stderr_fd, &read_fds);
+        int nfds = std::max<int>(stdout_fd, stderr_fd) + 1;
+
+        int num_set_fds = select (nfds, &read_fds, NULL, NULL, NULL);
+        if (log)
+            log->Printf("select (nfds, &read_fds, NULL, NULL, NULL) => %d", num_set_fds);
+
+        if (num_set_fds < 0)
+        {
+            int select_errno = errno;
+            if (log)
+            {
+                err.SetError (select_errno, eErrorTypePOSIX);
+                err.LogIfError(log, "select (nfds, &read_fds, NULL, NULL, NULL) => %d", num_set_fds);
+            }
+
+            switch (select_errno)
+            {
+            case EAGAIN:    // The kernel was (perhaps temporarily) unable to allocate the requested number of file descriptors, or we have non-blocking IO
+                break;
+            case EBADF:     // One of the descriptor sets specified an invalid descriptor.
+                return NULL;
+                break;
+            case EINTR:     // A signal was delivered before the time limit expired and before any of the selected events occurred.
+            case EINVAL:    // The specified time limit is invalid. One of its components is negative or too large.
+            default:        // Other unknown error
+                break;
+            }
+        }
+        else if (num_set_fds == 0)
+        {
+        }
+        else
+        {
+            char s[1024];
+            s[sizeof(s)-1] = '\0';  // Ensure we have NULL termination
+            int bytes_read = 0;
+            if (stdout_fd >= 0 && FD_ISSET (stdout_fd, &read_fds))
+            {
+                do
+                {
+                    bytes_read = ::read (stdout_fd, s, sizeof(s)-1);
+                    if (bytes_read < 0)
+                    {
+                        int read_errno = errno;
+                        if (log)
+                            log->Printf("read (stdout_fd, ) => %d   errno: %d (%s)", bytes_read, read_errno, strerror(read_errno));
+                    }
+                    else if (bytes_read == 0)
+                    {
+                        // EOF...
+                        if (log)
+                            log->Printf("read (stdout_fd, ) => %d  (reached EOF for child STDOUT)", bytes_read);
+                        stdout_fd = -1;
+                    }
+                    else if (bytes_read > 0)
+                    {
+                        proc->AppendSTDOUT(s, bytes_read);
+                    }
+
+                } while (bytes_read > 0);
+            }
+
+            if (stderr_fd >= 0 && FD_ISSET (stderr_fd, &read_fds))
+            {
+                do
+                {
+                    bytes_read = ::read (stderr_fd, s, sizeof(s)-1);
+                    if (bytes_read < 0)
+                    {
+                        int read_errno = errno;
+                        if (log)
+                            log->Printf("read (stderr_fd, ) => %d   errno: %d (%s)", bytes_read, read_errno, strerror(read_errno));
+                    }
+                    else if (bytes_read == 0)
+                    {
+                        // EOF...
+                        if (log)
+                            log->Printf("read (stderr_fd, ) => %d  (reached EOF for child STDERR)", bytes_read);
+                        stderr_fd = -1;
+                    }
+                    else if (bytes_read > 0)
+                    {
+                        proc->AppendSTDOUT(s, bytes_read);
+                    }
+
+                } while (bytes_read > 0);
+            }
+        }
+    }
+
+    if (log)
+        log->Printf("ProcessMacOSX::%s (%p): thread exiting...", __FUNCTION__, arg);
+
+    return NULL;
+}
+
+Error
+ProcessMacOSX::DoSignal (int signal)
+{
+    Error error;
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_PROCESS);
+    if (log)
+        log->Printf ("ProcessMacOSX::DoSignal (signal = %d)", signal);
+    if (::kill (GetID(), signal) != 0)
+    {
+        error.SetErrorToErrno();
+        error.LogIfError(log, "ProcessMacOSX::DoSignal (%d)", signal);
+    }
+    return error;
+}
+
+
+Error
+ProcessMacOSX::DoDetach()
+{
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_PROCESS);
+    if (log)
+        log->Printf ("ProcessMacOSX::DoDetach()");
+
+    Error error (DoSIGSTOP (true));
+    if (error.Success())
+    {
+        CloseChildFileDescriptors ();
+
+        // Scope for "locker" so we can reply to all of our exceptions (the SIGSTOP
+        // exception).
+        {
+            Mutex::Locker locker(m_exception_messages_mutex);
+            ReplyToAllExceptions();
+        }
+
+        // Shut down the exception thread and cleanup our exception remappings
+        Task().ShutDownExceptionThread();
+
+        lldb::pid_t pid = GetID();
+
+        // Detach from our process while we are stopped.
+        errno = 0;
+
+        // Detach from our process
+        ::ptrace (PT_DETACH, pid, (caddr_t)1, 0);
+
+        error.SetErrorToErrno();
+
+        if (log || error.Fail())
+            error.PutToLog(log, "::ptrace (PT_DETACH, %u, (caddr_t)1, 0)", pid);
+
+        // Resume our task
+        Task().Resume();
+
+        // NULL our task out as we have already retored all exception ports
+        Task().Clear();
+
+        // Clear out any notion of the process we once were
+        Clear();
+
+        SetPrivateState (eStateDetached);
+    }
+    return error;
+}
+
+
+
+Error
+ProcessMacOSX::ReplyToAllExceptions()
+{
+    Error error;
+    Mutex::Locker locker(m_exception_messages_mutex);
+    if (m_exception_messages.empty() == false)
+    {
+        Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_EXCEPTIONS);
+
+        MachException::Message::iterator pos;
+        MachException::Message::iterator begin = m_exception_messages.begin();
+        MachException::Message::iterator end = m_exception_messages.end();
+        for (pos = begin; pos != end; ++pos)
+        {
+            int resume_signal = -1;
+            ThreadSP thread_sp = m_thread_list.FindThreadByID(pos->state.thread_port);
+            if (thread_sp.get())
+                resume_signal = thread_sp->GetResumeSignal();
+            if (log)
+                log->Printf ("Replying to exception %d for thread 0x%4.4x (resume_signal = %i).", std::distance(begin, pos), thread_sp->GetID(), resume_signal);
+            Error curr_error (pos->Reply (Task().GetTaskPort(), GetID(), resume_signal));
+
+            // Only report the first error
+            if (curr_error.Fail() && error.Success())
+                error = curr_error;
+
+            error.LogIfError(log, "Error replying to exception");
+        }
+
+        // Erase all exception message as we should have used and replied
+        // to them all already.
+        m_exception_messages.clear();
+    }
+    return error;
+}
+
+
+Error
+ProcessMacOSX::PrivateResume (lldb::tid_t tid)
+{
+    
+    Mutex::Locker locker(m_exception_messages_mutex);
+    Error error (ReplyToAllExceptions());
+
+    // Let the thread prepare to resume and see if any threads want us to
+    // step over a breakpoint instruction (ProcessWillResume will modify
+    // the value of stepOverBreakInstruction).
+    //StateType process_state = m_thread_list.ProcessWillResume(this);
+
+    // Set our state accordingly
+    SetPrivateState (eStateRunning);
+
+    // Now resume our task.
+    error = Task().Resume();
+    return error;
+}
+
+// Called by the exception thread when an exception has been received from
+// our process. The exception message is completely filled and the exception
+// data has already been copied.
+void
+ProcessMacOSX::ExceptionMessageReceived (const MachException::Message& exceptionMessage)
+{
+    Mutex::Locker locker(m_exception_messages_mutex);
+
+    if (m_exception_messages.empty())
+        Task().Suspend();
+
+    ProcessMacOSXLog::LogIf (PD_LOG_EXCEPTIONS, "ProcessMacOSX::ExceptionMessageReceived ( )");
+
+    // Use a locker to automatically unlock our mutex in case of exceptions
+    // Add the exception to our internal exception stack
+    m_exception_messages.push_back(exceptionMessage);
+}
+
+
+//bool
+//ProcessMacOSX::GetProcessInfo (struct kinfo_proc* proc_info)
+//{
+//  int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, GetID() };
+//  size_t buf_size = sizeof(struct kinfo_proc);
+//
+//  if (::sysctl (mib, (unsigned)(sizeof(mib)/sizeof(int)), &proc_info, &buf_size, NULL, 0) == 0)
+//      return buf_size > 0;
+//
+//  return false;
+//}
+//
+//
+void
+ProcessMacOSX::ExceptionMessageBundleComplete()
+{
+    // We have a complete bundle of exceptions for our child process.
+    Mutex::Locker locker(m_exception_messages_mutex);
+    ProcessMacOSXLog::LogIf (PD_LOG_EXCEPTIONS, "%s: %d exception messages.", __PRETTY_FUNCTION__, m_exception_messages.size());
+    if (!m_exception_messages.empty())
+    {
+        SetPrivateState (eStateStopped);
+    }
+    else
+    {
+        ProcessMacOSXLog::LogIf (PD_LOG_EXCEPTIONS, "%s empty exception messages bundle.", __PRETTY_FUNCTION__, m_exception_messages.size());
+    }
+}
+
+bool
+ProcessMacOSX::ReleaseChildFileDescriptors ( int *stdin_fileno, int *stdout_fileno, int *stderr_fileno )
+{
+    if (stdin_fileno)
+        *stdin_fileno = m_child_stdin;
+    if (stdout_fileno)
+        *stdout_fileno = m_child_stdout;
+    if (stderr_fileno)
+        *stderr_fileno = m_child_stderr;
+    // Stop the stdio thread if we have one, but don't have it close the child
+    // file descriptors since we are giving control of these descriptors to the
+    // caller
+    bool close_child_fds = false;
+    StopSTDIOThread(close_child_fds);
+    return true;
+}
+
+void
+ProcessMacOSX::AppendSTDOUT (const char* s, size_t len)
+{
+    ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "ProcessMacOSX::%s (<%d> %s) ...", __FUNCTION__, len, s);
+    Mutex::Locker locker(m_stdio_mutex);
+    m_stdout_data.append(s, len);
+
+    // FIXME: Make a real data object for this and put it out.
+    BroadcastEventIfUnique (eBroadcastBitSTDOUT);
+}
+
+lldb::pid_t
+ProcessMacOSX::LaunchForDebug
+(
+    const char *path,
+    char const *argv[],
+    char const *envp[],
+    ArchSpec& arch_spec,
+    const char *stdin_path,
+    const char *stdout_path,
+    const char *stderr_path,
+    PDLaunchType launch_type,
+    Error &launch_err)
+{
+    // Clear out and clean up from any current state
+    Clear();
+
+    m_arch_spec = arch_spec;
+
+    if (launch_type == eLaunchDefault)
+        launch_type = eLaunchPosixSpawn;
+
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_PROCESS);
+    if (log)
+        log->Printf ("%s( path = '%s', argv = %p, envp = %p, launch_type = %u )", __FUNCTION__, path, argv, envp, launch_type);
+
+    // Fork a child process for debugging
+    SetPrivateState (eStateLaunching);
+    switch (launch_type)
+    {
+    case eLaunchForkExec:
+        SetID(ProcessMacOSX::ForkChildForPTraceDebugging(path, argv, envp, arch_spec, stdin_path, stdout_path, stderr_path, this, launch_err));
+        break;
+
+    case eLaunchPosixSpawn:
+        SetID(ProcessMacOSX::PosixSpawnChildForPTraceDebugging(path, argv, envp, arch_spec, stdin_path, stdout_path, stderr_path, this, launch_err));
+        break;
+
+#if defined (__arm__)
+
+    case eLaunchSpringBoard:
+        {
+            const char *app_ext = strstr(path, ".app");
+            if (app_ext != NULL)
+            {
+                std::string app_bundle_path(path, app_ext + strlen(".app"));
+                return SBLaunchForDebug (app_bundle_path.c_str(), argv, envp, arch_spec, stdin_path, stdout_path, stderr_path, launch_err);
+            }
+        }
+        break;
+
+#endif
+
+    default:
+        // Invalid  launch
+        launch_err.SetErrorToGenericError ();
+        return LLDB_INVALID_PROCESS_ID;
+    }
+
+    lldb::pid_t pid = GetID();
+
+    if (pid == LLDB_INVALID_PROCESS_ID)
+    {
+        // If we don't have a valid process ID and no one has set the error,
+        // then return a generic error
+        if (launch_err.Success())
+            launch_err.SetErrorToGenericError ();
+    }
+    else
+    {
+        // Make sure we can get our task port before going any further
+        Task().GetTaskPortForProcessID (launch_err);
+
+        // If that goes well then kick off our exception thread
+        if (launch_err.Success())
+            Task().StartExceptionThread(launch_err);
+
+        if (launch_err.Success())
+        {
+            //m_path = path;
+//          size_t i;
+//          if (argv)
+//          {
+//              char const *arg;
+//              for (i=0; (arg = argv[i]) != NULL; i++)
+//                  m_args.push_back(arg);
+//          }
+
+            StartSTDIOThread();
+
+            if (launch_type == eLaunchPosixSpawn)
+            {
+
+                //SetState (eStateAttaching);
+                errno = 0;
+                if (::ptrace (PT_ATTACHEXC, pid, 0, 0) == 0)
+                    launch_err.Clear();
+                else
+                    launch_err.SetErrorToErrno();
+
+                if (launch_err.Fail() || log)
+                    launch_err.PutToLog(log, "::ptrace (PT_ATTACHEXC, pid = %i, 0, 0 )", pid);
+
+                if (launch_err.Success())
+                    m_flags.Set (eFlagsAttached);
+                else
+                    SetPrivateState (eStateExited);
+            }
+            else
+            {
+                launch_err.Clear();
+            }
+        }
+        else
+        {
+            // We were able to launch the process, but not get its task port
+            // so now we need to make it sleep with da fishes.
+            SetID(LLDB_INVALID_PROCESS_ID);
+            ::ptrace (PT_KILL, pid, 0, 0 );
+            ::kill (pid, SIGCONT);
+            pid = LLDB_INVALID_PROCESS_ID;
+        }
+
+    }
+    return pid;
+}
+
+lldb::pid_t
+ProcessMacOSX::PosixSpawnChildForPTraceDebugging
+(
+    const char *path,
+    char const *argv[],
+    char const *envp[],
+    ArchSpec& arch_spec,
+    const char *stdin_path,
+    const char *stdout_path,
+    const char *stderr_path,
+    ProcessMacOSX* process,
+    Error &err
+)
+{
+    posix_spawnattr_t attr;
+
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_PROCESS);
+
+    Error local_err;    // Errors that don't affect the spawning.
+    if (log)
+        log->Printf ("%s ( path='%s', argv=%p, envp=%p, process )", __FUNCTION__, path, argv, envp);
+    err.SetError( ::posix_spawnattr_init (&attr), eErrorTypePOSIX);
+    if (err.Fail() || log)
+        err.PutToLog(log, "::posix_spawnattr_init ( &attr )");
+    if (err.Fail())
+        return LLDB_INVALID_PROCESS_ID;
+
+    err.SetError( ::posix_spawnattr_setflags (&attr, POSIX_SPAWN_START_SUSPENDED), eErrorTypePOSIX);
+    if (err.Fail() || log)
+        err.PutToLog(log, "::posix_spawnattr_setflags ( &attr, POSIX_SPAWN_START_SUSPENDED )");
+    if (err.Fail())
+        return LLDB_INVALID_PROCESS_ID;
+
+#if !defined(__arm__)
+
+    // We don't need to do this for ARM, and we really shouldn't now that we
+    // have multiple CPU subtypes and no posix_spawnattr call that allows us
+    // to set which CPU subtype to launch...
+    cpu_type_t cpu = arch_spec.GetCPUType();
+    if (cpu != 0 && cpu != CPU_TYPE_ANY && cpu != LLDB_INVALID_CPUTYPE)
+    {
+        size_t ocount = 0;
+        err.SetError( ::posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &ocount), eErrorTypePOSIX);
+        if (err.Fail() || log)
+            err.PutToLog(log, "::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = 0x%8.8x, count => %zu )", cpu, ocount);
+
+        if (err.Fail() != 0 || ocount != 1)
+            return LLDB_INVALID_PROCESS_ID;
+    }
+
+#endif
+
+    lldb_utility::PseudoTerminal pty;
+
+    posix_spawn_file_actions_t file_actions;
+    err.SetError( ::posix_spawn_file_actions_init (&file_actions), eErrorTypePOSIX);
+    int file_actions_valid = err.Success();
+    if (!file_actions_valid || log)
+        err.PutToLog(log, "::posix_spawn_file_actions_init ( &file_actions )");
+    Error stdio_err;
+    lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+    if (file_actions_valid)
+    {
+        // If the user specified any STDIO files, then use those
+        if (stdin_path || stdout_path || stderr_path)
+        {
+            process->SetSTDIOIsOurs(false);
+            if (stderr_path != NULL && stderr_path[0])
+            {
+                stdio_err.SetError( ::posix_spawn_file_actions_addopen(&file_actions, STDERR_FILENO,    stderr_path, O_RDWR, 0), eErrorTypePOSIX);
+                if (stdio_err.Fail() || log)
+                    stdio_err.PutToLog(log, "::posix_spawn_file_actions_addopen ( &file_actions, filedes = STDERR_FILENO, path = '%s', oflag = O_RDWR, mode = 0 )", stderr_path);
+            }
+
+            if (stdin_path != NULL && stdin_path[0])
+            {
+                stdio_err.SetError( ::posix_spawn_file_actions_addopen(&file_actions, STDIN_FILENO, stdin_path, O_RDONLY, 0), eErrorTypePOSIX);
+                if (stdio_err.Fail() || log)
+                    stdio_err.PutToLog(log, "::posix_spawn_file_actions_addopen ( &file_actions, filedes = STDIN_FILENO, path = '%s', oflag = O_RDONLY, mode = 0 )", stdin_path);
+            }
+
+            if (stdout_path != NULL && stdout_path[0])
+            {
+                stdio_err.SetError( ::posix_spawn_file_actions_addopen(&file_actions, STDOUT_FILENO,    stdout_path, O_WRONLY, 0), eErrorTypePOSIX);
+                if (stdio_err.Fail() || log)
+                    stdio_err.PutToLog(log, "::posix_spawn_file_actions_addopen ( &file_actions, filedes = STDOUT_FILENO, path = '%s', oflag = O_WRONLY, mode = 0 )", stdout_path);
+            }
+        }
+        else
+        {
+            // The user did not specify any STDIO files, use a pseudo terminal.
+            // Callers can then access the file handles using the
+            // ProcessMacOSX::ReleaseChildFileDescriptors() function, otherwise
+            // this class will spawn a thread that tracks STDIO and buffers it.
+            process->SetSTDIOIsOurs(true);
+            char error_str[1024];
+            if (pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)))
+            {
+                const char* slave_name = pty.GetSlaveName(error_str, sizeof(error_str));
+                if (slave_name == NULL)
+                    slave_name = "/dev/null";
+                stdio_err.SetError( ::posix_spawn_file_actions_addopen(&file_actions, STDERR_FILENO,    slave_name, O_RDWR|O_NOCTTY, 0), eErrorTypePOSIX);
+                if (stdio_err.Fail() || log)
+                    stdio_err.PutToLog(log, "::posix_spawn_file_actions_addopen ( &file_actions, filedes = STDERR_FILENO, path = '%s', oflag = O_RDWR|O_NOCTTY, mode = 0 )", slave_name);
+
+                stdio_err.SetError( ::posix_spawn_file_actions_addopen(&file_actions, STDIN_FILENO, slave_name, O_RDONLY|O_NOCTTY, 0), eErrorTypePOSIX);
+                if (stdio_err.Fail() || log)
+                    stdio_err.PutToLog(log, "::posix_spawn_file_actions_addopen ( &file_actions, filedes = STDIN_FILENO, path = '%s', oflag = O_RDONLY|O_NOCTTY, mode = 0 )", slave_name);
+
+                stdio_err.SetError( ::posix_spawn_file_actions_addopen(&file_actions, STDOUT_FILENO,    slave_name, O_WRONLY|O_NOCTTY, 0), eErrorTypePOSIX);
+                if (stdio_err.Fail() || log)
+                    stdio_err.PutToLog(log, "::posix_spawn_file_actions_addopen ( &file_actions, filedes = STDOUT_FILENO, path = '%s', oflag = O_WRONLY|O_NOCTTY, mode = 0 )", slave_name);
+            }
+            else
+            {
+                if (error_str[0])
+                    stdio_err.SetErrorString(error_str);
+                else
+                    stdio_err.SetErrorString("Unable to open master side of pty for inferior.");
+            }
+
+        }
+        err.SetError( ::posix_spawnp (&pid, path, &file_actions, &attr, (char * const*)argv, (char * const*)envp), eErrorTypePOSIX);
+        if (err.Fail() || log)
+            err.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", pid, path, &file_actions, &attr, argv, envp);
+
+        if (stdio_err.Success())
+        {
+            // If we have a valid process and we created the STDIO file handles,
+            // then remember them on our process class so we can spawn a STDIO
+            // thread and close them when we are done with them.
+            if (process != NULL && process->STDIOIsOurs())
+            {
+                int master_fd = pty.ReleaseMasterFileDescriptor ();
+                process->SetChildFileDescriptors (master_fd, master_fd, master_fd);
+            }
+        }
+    }
+    else
+    {
+        err.SetError( ::posix_spawnp (&pid, path, NULL, &attr, (char * const*)argv, (char * const*)envp), eErrorTypePOSIX);
+        if (err.Fail() || log)
+            err.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", pid, path, NULL, &attr, argv, envp);
+    }
+
+    // We have seen some cases where posix_spawnp was returning a valid
+    // looking pid even when an error was returned, so clear it out
+    if (err.Fail())
+        pid = LLDB_INVALID_PROCESS_ID;
+
+    if (file_actions_valid)
+    {
+        local_err.SetError( ::posix_spawn_file_actions_destroy (&file_actions), eErrorTypePOSIX);
+        if (local_err.Fail() || log)
+            local_err.PutToLog(log, "::posix_spawn_file_actions_destroy ( &file_actions )");
+    }
+
+    return pid;
+}
+
+lldb::pid_t
+ProcessMacOSX::ForkChildForPTraceDebugging
+(
+    const char *path,
+    char const *argv[],
+    char const *envp[],
+    ArchSpec& arch_spec,
+    const char *stdin_path,
+    const char *stdout_path,
+    const char *stderr_path,
+    ProcessMacOSX* process,
+    Error &launch_err
+)
+{
+    lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+
+    if (stdin_path || stdout_path || stderr_path)
+    {
+        assert(!"TODO: ForkChildForPTraceDebugging doesn't currently support fork/exec with user file handles...");
+    }
+    else
+    {
+
+        // Use a fork that ties the child process's stdin/out/err to a pseudo
+        // terminal so we can read it in our ProcessMacOSX::STDIOThread
+        // as unbuffered io.
+        lldb_utility::PseudoTerminal pty;
+        char error_str[1024];
+        pid = pty.Fork(error_str, sizeof(error_str));
+
+        if (pid < 0)
+        {
+            launch_err.SetErrorString (error_str);
+            //--------------------------------------------------------------
+            // Error during fork.
+            //--------------------------------------------------------------
+            return pid;
+        }
+        else if (pid == 0)
+        {
+            //--------------------------------------------------------------
+            // Child process
+            //--------------------------------------------------------------
+            ::ptrace (PT_TRACE_ME, 0, 0, 0);    // Debug this process
+            ::ptrace (PT_SIGEXC, 0, 0, 0);    // Get BSD signals as mach exceptions
+
+            // If our parent is setgid, lets make sure we don't inherit those
+            // extra powers due to nepotism.
+            ::setgid (getgid ());
+
+            // Let the child have its own process group. We need to execute
+            // this call in both the child and parent to avoid a race condition
+            // between the two processes.
+            ::setpgid (0, 0);    // Set the child process group to match its pid
+
+            // Sleep a bit to before the exec call
+            ::sleep (1);
+
+            // Turn this process into
+            ::execv (path, (char * const *)argv);
+            // Exit with error code. Child process should have taken
+            // over in above exec call and if the exec fails it will
+            // exit the child process below.
+            ::exit (127);
+        }
+        else
+        {
+            //--------------------------------------------------------------
+            // Parent process
+            //--------------------------------------------------------------
+            // Let the child have its own process group. We need to execute
+            // this call in both the child and parent to avoid a race condition
+            // between the two processes.
+            ::setpgid (pid, pid);    // Set the child process group to match its pid
+
+            if (process != NULL)
+            {
+                // Release our master pty file descriptor so the pty class doesn't
+                // close it and so we can continue to use it in our STDIO thread
+                int master_fd = pty.ReleaseMasterFileDescriptor ();
+                process->SetChildFileDescriptors (master_fd, master_fd, master_fd);
+            }
+        }
+    }
+    return pid;
+}
+
+#if defined (__arm__)
+
+lldb::pid_t
+ProcessMacOSX::SBLaunchForDebug
+(
+    const char *path,
+    char const *argv[],
+    char const *envp[],
+    ArchSpec& arch_spec,
+    const char *stdin_path,
+    const char *stdout_path,
+    const char *stderr_path,
+    Error &launch_err
+)
+{
+    // Clear out and clean up from any current state
+    Clear();
+
+    ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "%s( '%s', argv)", __FUNCTION__, path);
+
+    // Fork a child process for debugging
+    SetState(eStateLaunching);
+    m_pid = ProcessMacOSX::SBLaunchForDebug(path, argv, envp, this, launch_err);
+    if (m_pid != 0)
+    {
+        m_flags |= eFlagsUsingSBS;
+        //m_path = path;
+//        size_t i;
+//        char const *arg;
+//        for (i=0; (arg = argv[i]) != NULL; i++)
+//            m_args.push_back(arg);
+        Task().StartExceptionThread();
+        StartSTDIOThread();
+        SetState (eStateAttaching);
+        int err = ptrace (PT_ATTACHEXC, m_pid, 0, 0);
+        if (err == 0)
+        {
+            m_flags |= eFlagsAttached;
+            ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "successfully attached to pid %d", m_pid);
+        }
+        else
+        {
+            SetState (eStateExited);
+            ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "error: failed to attach to pid %d", m_pid);
+        }
+    }
+    return m_pid;
+}
+
+#include <servers/bootstrap.h>
+#include "CFBundle.h"
+#include "CFData.h"
+#include "CFString.h"
+
+lldb::pid_t
+ProcessMacOSX::SBLaunchForDebug
+(
+    const char *app_bundle_path,
+    char const *argv[],
+    char const *envp[],
+    ArchSpec& arch_spec,
+    const char *stdin_path,
+    const char *stdout_path,
+    const char *stderr_path,
+    ProcessMacOSX* process,
+    Error &launch_err
+)
+{
+    ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "%s( '%s', argv, %p)", __FUNCTION__, app_bundle_path, process);
+    CFAllocatorRef alloc = kCFAllocatorDefault;
+    if (argv[0] == NULL)
+        return LLDB_INVALID_PROCESS_ID;
+
+    size_t argc = 0;
+    // Count the number of arguments
+    while (argv[argc] != NULL)
+        argc++;
+
+    // Enumerate the arguments
+    size_t first_launch_arg_idx = 1;
+    CFReleaser<CFMutableArrayRef> launch_argv;
+
+    if (argv[first_launch_arg_idx])
+    {
+        size_t launch_argc = argc > 0 ? argc - 1 : 0;
+        launch_argv.reset (::CFArrayCreateMutable (alloc, launch_argc, &kCFTypeArrayCallBacks));
+        size_t i;
+        char const *arg;
+        CFString launch_arg;
+        for (i=first_launch_arg_idx; (i < argc) && ((arg = argv[i]) != NULL); i++)
+        {
+            launch_arg.reset(::CFStringCreateWithCString (alloc, arg, kCFStringEncodingUTF8));
+            if (launch_arg.get() != NULL)
+                CFArrayAppendValue(launch_argv.get(), launch_arg.get());
+            else
+                break;
+        }
+    }
+
+    // Next fill in the arguments dictionary.  Note, the envp array is of the form
+    // Variable=value but SpringBoard wants a CF dictionary.  So we have to convert
+    // this here.
+
+    CFReleaser<CFMutableDictionaryRef> launch_envp;
+
+    if (envp[0])
+    {
+        launch_envp.reset(::CFDictionaryCreateMutable(alloc, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+        const char *value;
+        int name_len;
+        CFString name_string, value_string;
+
+        for (int i = 0; envp[i] != NULL; i++)
+        {
+            value = strstr (envp[i], "=");
+
+            // If the name field is empty or there's no =, skip it.  Somebody's messing with us.
+            if (value == NULL || value == envp[i])
+                continue;
+
+            name_len = value - envp[i];
+
+            // Now move value over the "="
+            value++;
+
+            name_string.reset(::CFStringCreateWithBytes(alloc, (const UInt8 *) envp[i], name_len, kCFStringEncodingUTF8, false));
+            value_string.reset(::CFStringCreateWithCString(alloc, value, kCFStringEncodingUTF8));
+            CFDictionarySetValue (launch_envp.get(), name_string.get(), value_string.get());
+        }
+    }
+
+    CFString stdout_cf_path;
+    CFString stderr_cf_path;
+    PseudoTerminal pty;
+
+    if (stdin_path || stdout_path || stderr_path)
+    {
+        process->SetSTDIOIsOurs(false);
+        if (stdout_path)
+            stdout_cf_path.SetFileSystemRepresentation (stdout_path);
+        if (stderr_path)
+            stderr_cf_path.SetFileSystemRepresentation (stderr_path);
+    }
+    else
+    {
+        process->SetSTDIOIsOurs(true);
+        PseudoTerminal::Error pty_err = pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY);
+        if (pty_err == PseudoTerminal::success)
+        {
+            const char* slave_name = pty.SlaveName();
+            ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "%s() successfully opened master pty, slave is %s", __FUNCTION__, slave_name);
+            if (slave_name && slave_name[0])
+            {
+                ::chmod (slave_name, S_IRWXU | S_IRWXG | S_IRWXO);
+                stdout_cf_path.SetFileSystemRepresentation (slave_name);
+                stderr_cf_path.(stdout_cf_path);
+            }
+        }
+    }
+
+    if (stdout_cf_path.get() == NULL)
+        stdout_cf_path.SetFileSystemRepresentation ("/dev/null");
+    if (stderr_cf_path.get() == NULL)
+        stderr_cf_path.SetFileSystemRepresentation ("/dev/null");
+
+    CFBundle bundle(app_bundle_path);
+    CFStringRef bundleIDCFStr = bundle.GetIdentifier();
+    std::string bundleID;
+    if (CFString::UTF8(bundleIDCFStr, bundleID) == NULL)
+    {
+        struct stat app_bundle_stat;
+        if (::stat (app_bundle_path, &app_bundle_stat) < 0)
+        {
+            launch_err.SetError(errno, eErrorTypePOSIX);
+            launch_err.SetErrorStringWithFormat("%s: \"%s\".\n", launch_err.AsString(), app_bundle_path);
+            ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "%s() error: %s", __FUNCTION__, launch_err.AsCString());
+        }
+        else
+        {
+            launch_err.SetError(-1, eErrorTypeGeneric);
+            launch_err.SetErrorStringWithFormat("Failed to extract CFBundleIdentifier from %s.\n", app_bundle_path);
+            ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "%s() error: failed to extract CFBundleIdentifier from '%s'", __FUNCTION__, app_bundle_path);
+        }
+        return LLDB_INVALID_PROCESS_ID;
+    }
+    ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "%s() extracted CFBundleIdentifier: %s", __FUNCTION__, bundleID.c_str());
+
+
+    CFData argv_data(NULL);
+
+    if (launch_argv.get())
+    {
+        if (argv_data.Serialize(launch_argv.get(), kCFPropertyListBinaryFormat_v1_0) == NULL)
+        {
+            ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "%s() error: failed to serialize launch arg array...", __FUNCTION__);
+            return LLDB_INVALID_PROCESS_ID;
+        }
+    }
+
+    ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "%s() serialized launch arg array", __FUNCTION__);
+
+    // Find SpringBoard
+    SBSApplicationLaunchError sbs_error = 0;
+    sbs_error = SBSLaunchApplication (  bundleIDCFStr,
+                                        (CFURLRef)NULL,         // openURL
+                                        launch_argv.get(),
+                                        launch_envp.get(),      // CFDictionaryRef environment
+                                        stdout_cf_path.get(),
+                                        stderr_cf_path.get(),
+                                        SBSApplicationLaunchWaitForDebugger | SBSApplicationLaunchUnlockDevice);
+
+
+    launch_err.SetError(sbs_error, eErrorTypeSpringBoard);
+
+    if (sbs_error == SBSApplicationLaunchErrorSuccess)
+    {
+        static const useconds_t pid_poll_interval = 200000;
+        static const useconds_t pid_poll_timeout = 30000000;
+
+        useconds_t pid_poll_total = 0;
+
+        lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+        Boolean pid_found = SBSProcessIDForDisplayIdentifier(bundleIDCFStr, &pid);
+        // Poll until the process is running, as long as we are getting valid responses and the timeout hasn't expired
+        // A return PID of 0 means the process is not running, which may be because it hasn't been (asynchronously) started
+        // yet, or that it died very quickly (if you weren't using waitForDebugger).
+        while (!pid_found && pid_poll_total < pid_poll_timeout)
+        {
+            usleep (pid_poll_interval);
+            pid_poll_total += pid_poll_interval;
+            ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "%s() polling Springboard for pid for %s...", __FUNCTION__, bundleID.c_str());
+            pid_found = SBSProcessIDForDisplayIdentifier(bundleIDCFStr, &pid);
+        }
+
+        if (pid_found)
+        {
+            // If we have a valid process and we created the STDIO file handles,
+            // then remember them on our process class so we can spawn a STDIO
+            // thread and close them when we are done with them.
+            if (process != NULL && process->STDIOIsOurs())
+            {
+                // Release our master pty file descriptor so the pty class doesn't
+                // close it and so we can continue to use it in our STDIO thread
+                int master_fd = pty.ReleaseMasterFD();
+                process->SetChildFileDescriptors(master_fd, master_fd, master_fd);
+            }
+            ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "%s() => pid = %4.4x", __FUNCTION__, pid);
+        }
+        else
+        {
+            LogError("failed to lookup the process ID for CFBundleIdentifier %s.", bundleID.c_str());
+        }
+        return pid;
+    }
+
+    LogError("unable to launch the application with CFBundleIdentifier '%s' sbs_error = %u", bundleID.c_str(), sbs_error);
+    return LLDB_INVALID_PROCESS_ID;
+}
+
+#endif // #if defined (__arm__)
+
+
+#include "MachThreadContext_x86_64.h"
+#include "MachThreadContext_i386.h"
+#include "MachThreadContext_arm.h"
+
+void
+ProcessMacOSX::Initialize()
+{
+    static bool g_initialized = false;
+
+    if (g_initialized == false)
+    {
+        g_initialized = true;
+
+        MachThreadContext_x86_64::Initialize();
+        MachThreadContext_i386::Initialize();
+        MachThreadContext_arm::Initialize();
+        PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                       GetPluginDescriptionStatic(),
+                                       CreateInstance);
+
+        Log::Callbacks log_callbacks = {
+            ProcessMacOSXLog::DisableLog,
+            ProcessMacOSXLog::EnableLog,
+            ProcessMacOSXLog::ListLogCategories
+        };
+
+        Log::RegisterLogChannel (ProcessMacOSX::GetPluginNameStatic(), log_callbacks);
+
+
+    }
+}
+
+
+
diff --git a/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h b/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h
new file mode 100644
index 0000000..8388d4e
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h
@@ -0,0 +1,490 @@
+//===-- ProcessMacOSX.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_MacOSXProcess_H_
+#define liblldb_MacOSXProcess_H_
+
+// C Includes
+
+// C++ Includes
+#include <list>
+
+// Other libraries and framework includes
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/ThreadSafeValue.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+
+// Project includes
+#include "MachTask.h"
+#include "MachException.h"
+
+typedef enum PDLaunch
+{
+    eLaunchDefault = 0,
+    eLaunchPosixSpawn,
+    eLaunchForkExec,
+#if defined (__arm__)
+    eLaunchSpringBoard,
+#endif
+} PDLaunchType;
+
+
+
+class ThreadMacOSX;
+class MachThreadContext;
+
+class ProcessMacOSX :
+    public lldb_private::Process
+{
+public:
+    friend class ThreadMacOSX;
+    friend class MachTask;
+
+    typedef MachThreadContext* (*CreateArchCalback) (const lldb_private::ArchSpec &arch_spec, ThreadMacOSX &thread);
+
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    static Process*
+    CreateInstance (lldb_private::Target& target, lldb_private::Listener &listener);
+
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static const char *
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    ProcessMacOSX(lldb_private::Target& target, lldb_private::Listener &listener);
+
+    virtual
+    ~ProcessMacOSX();
+
+    //------------------------------------------------------------------
+    // Check if a given Process
+    //------------------------------------------------------------------
+    virtual bool
+    CanDebug (lldb_private::Target &target);
+
+    //------------------------------------------------------------------
+    // Creating a new process, or attaching to an existing one
+    //------------------------------------------------------------------
+    virtual lldb_private::Error
+    WillLaunch (lldb_private::Module* module);
+
+    virtual lldb_private::Error
+    DoLaunch (lldb_private::Module* module,
+              char const *argv[],           // Can be NULL
+              char const *envp[],           // Can be NULL
+              const char *stdin_path,       // Can be NULL
+              const char *stdout_path,  // Can be NULL
+              const char *stderr_path); // Can be NULL
+
+    virtual void
+    DidLaunch ();
+
+    virtual lldb_private::Error
+    WillAttach (lldb::pid_t pid);
+
+    virtual lldb_private::Error
+    DoAttach (lldb::pid_t pid);
+
+    virtual void
+    DidAttach ();
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual const char *
+    GetPluginName();
+
+    virtual const char *
+    GetShortPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+    virtual void
+    GetPluginCommandHelp (const char *command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Error
+    ExecutePluginCommand (lldb_private::Args &command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Log *
+    EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
+
+    //------------------------------------------------------------------
+    // Process Control
+    //------------------------------------------------------------------
+    virtual lldb_private::Error
+    DoResume ();
+
+    virtual lldb_private::Error
+    DoHalt ();
+
+    virtual lldb_private::Error
+    WillDetach ();
+
+    virtual lldb_private::Error
+    DoDetach ();
+
+    virtual lldb_private::Error
+    DoSignal (int signal);
+
+    virtual lldb_private::Error
+    DoDestroy ();
+
+    virtual void
+    RefreshStateAfterStop();
+
+    //------------------------------------------------------------------
+    // Process Queries
+    //------------------------------------------------------------------
+    virtual bool
+    IsAlive ();
+
+    virtual lldb::addr_t
+    GetImageInfoAddress();
+
+    //------------------------------------------------------------------
+    // Process Memory
+    //------------------------------------------------------------------
+    virtual size_t
+    DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error);
+
+    virtual size_t
+    DoWriteMemory (lldb::addr_t addr, const void *buf, size_t size, lldb_private::Error &error);
+
+    virtual lldb::addr_t
+    DoAllocateMemory (size_t size, uint32_t permissions, lldb_private::Error &error);
+
+    virtual lldb_private::Error
+    DoDeallocateMemory (lldb::addr_t ptr);
+
+    //------------------------------------------------------------------
+    // Process STDIO
+    //------------------------------------------------------------------
+    virtual size_t
+    GetSTDOUT (char *buf, size_t buf_size, lldb_private::Error &error);
+
+    virtual size_t
+    GetSTDERR (char *buf, size_t buf_size, lldb_private::Error &error);
+
+    virtual size_t
+    PutSTDIN (const char *buf, size_t buf_size, lldb_private::Error &error);
+
+    //----------------------------------------------------------------------
+    // Process Breakpoints
+    //----------------------------------------------------------------------
+    virtual size_t
+    GetSoftwareBreakpointTrapOpcode (lldb_private::BreakpointSite *bp_site);
+
+    //----------------------------------------------------------------------
+    // Process Breakpoints
+    //----------------------------------------------------------------------
+    virtual lldb_private::Error
+    EnableBreakpoint (lldb_private::BreakpointSite *bp_site);
+
+    virtual lldb_private::Error
+    DisableBreakpoint (lldb_private::BreakpointSite *bp_site);
+
+    //----------------------------------------------------------------------
+    // Process Watchpoints
+    //----------------------------------------------------------------------
+    virtual lldb_private::Error
+    EnableWatchpoint (lldb_private::WatchpointLocation *wp_loc);
+
+    virtual lldb_private::Error
+    DisableWatchpoint (lldb_private::WatchpointLocation *wp_loc);
+
+    virtual lldb::ByteOrder
+    GetByteOrder () const;
+
+    virtual lldb_private::DynamicLoader *
+    GetDynamicLoader ();
+
+    static void
+    AddArchCreateCallback(const lldb_private::ArchSpec& arch_spec,
+                          ProcessMacOSX::CreateArchCalback callback);
+
+protected:
+
+    bool m_stdio_ours;          // True if we created and own the child STDIO file handles, false if they were supplied to us and owned by someone else
+    int m_child_stdin;
+    int m_child_stdout;
+    int m_child_stderr;
+    MachTask m_task;            // The mach task for this process
+    lldb_private::Flags m_flags;            // Process specific flags (see eFlags enums)
+    lldb::thread_t m_stdio_thread;  // Thread ID for the thread that watches for child process stdio
+    lldb_private::Mutex m_stdio_mutex;      // Multithreaded protection for stdio
+    std::string m_stdout_data;
+    MachException::Message::collection m_exception_messages;       // A collection of exception messages caught when listening to the exception port
+    lldb_private::Mutex m_exception_messages_mutex; // Multithreaded protection for m_exception_messages
+    lldb_private::ArchSpec m_arch_spec;
+    std::auto_ptr<lldb_private::DynamicLoader> m_dynamic_loader_ap;
+//    lldb::thread_t m_wait_thread;
+    lldb::ByteOrder m_byte_order;
+
+    //----------------------------------------------------------------------
+    // Child process control
+    //----------------------------------------------------------------------
+    lldb::pid_t
+    LaunchForDebug (const char *path,
+                    char const *argv[],
+                    char const *envp[],
+                    lldb_private::ArchSpec& arch_spec,
+                    const char *stdin_path,
+                    const char *stdout_path,
+                    const char *stderr_path,
+                    PDLaunchType launch_type,
+                    lldb_private::Error &launch_err);
+
+    static lldb::pid_t
+    ForkChildForPTraceDebugging (const char *path,
+                                 char const *argv[],
+                                 char const *envp[],
+                                 lldb_private::ArchSpec& arch_spec,
+                                 const char *stdin_path,
+                                 const char *stdout_path,
+                                 const char *stderr_path,
+                                 ProcessMacOSX* process,
+                                 lldb_private::Error &launch_err);
+
+    static lldb::pid_t
+    PosixSpawnChildForPTraceDebugging (const char *path,
+                                       char const *argv[],
+                                       char const *envp[],
+                                       lldb_private::ArchSpec& arch_spec,
+                                       const char *stdin_path,
+                                       const char *stdout_path,
+                                       const char *stderr_path,
+                                       ProcessMacOSX* process,
+                                       lldb_private::Error &launch_err);
+
+#if defined (__arm__)
+    lldb::pid_t
+    SBLaunchForDebug (const char *path,
+                      char const *argv[],
+                      char const *envp[],
+                      lldb_private::ArchSpec& arch_spec,
+                      const char *stdin_path,
+                      const char *stdout_path,
+                      const char *stderr_path,
+                      lldb_private::Error &launch_err);
+
+    static lldb::pid_t
+    SBLaunchForDebug (const char *path,
+                      char const *argv[],
+                      char const *envp[],
+                      lldb_private::ArchSpec& arch_spec,
+                      const char *stdin_path,
+                      const char *stdout_path,
+                      const char *stderr_path,
+                      ProcessMacOSX* process,
+                      lldb_private::Error &launch_err);
+#endif
+
+    //----------------------------------------------------------------------
+    // Exception thread functions
+    //----------------------------------------------------------------------
+    bool
+    StartSTDIOThread ();
+
+    void
+    StopSTDIOThread (bool close_child_fds);
+
+    static void *
+    STDIOThread (void *arg);
+
+    void
+    ExceptionMessageReceived (const MachException::Message& exceptionMessage);
+
+    void
+    ExceptionMessageBundleComplete ();
+
+    //----------------------------------------------------------------------
+    // Accessors
+    //----------------------------------------------------------------------
+    bool
+    ProcessIDIsValid ( ) const;
+
+    MachTask&
+    Task() { return m_task; }
+
+    const MachTask&
+    Task() const { return m_task; }
+
+    bool
+    IsRunning ( lldb::StateType state )
+    {
+        return    state == lldb::eStateRunning || IsStepping(state);
+    }
+
+    bool
+    IsStepping ( lldb::StateType state)
+    {
+        return    state == lldb::eStateStepping;
+    }
+    bool
+    CanResume ( lldb::StateType state)
+    {
+        return state == lldb::eStateStopped;
+    }
+
+    bool
+    HasExited (lldb::StateType state)
+    {
+        return state == lldb::eStateExited;
+    }
+
+    void
+    SetChildFileDescriptors (int stdin_fileno, int stdout_fileno, int stderr_fileno)
+    {
+        m_child_stdin   = stdin_fileno;
+        m_child_stdout  = stdout_fileno;
+        m_child_stderr  = stderr_fileno;
+    }
+
+    int
+    GetStdinFileDescriptor () const
+    {
+        return m_child_stdin;
+    }
+
+    int
+    GetStdoutFileDescriptor () const
+    {
+        return m_child_stdout;
+    }
+    int
+    GetStderrFileDescriptor () const
+    {
+        return m_child_stderr;
+    }
+    bool
+    ReleaseChildFileDescriptors ( int *stdin_fileno, int *stdout_fileno, int *stderr_fileno );
+
+    void
+    AppendSTDOUT (const char* s, size_t len);
+
+    void
+    CloseChildFileDescriptors ()
+    {
+        if (m_child_stdin >= 0)
+        {
+            ::close (m_child_stdin);
+            m_child_stdin = -1;
+        }
+        if (m_child_stdout >= 0)
+        {
+            ::close (m_child_stdout);
+            m_child_stdout = -1;
+        }
+        if (m_child_stderr >= 0)
+        {
+            ::close (m_child_stderr);
+            m_child_stderr = -1;
+        }
+    }
+
+    bool
+    ProcessUsingSpringBoard() const
+    {
+        return m_flags.IsSet(eFlagsUsingSBS);
+    }
+
+    lldb_private::ArchSpec&
+    GetArchSpec()
+    {
+        return m_arch_spec;
+    }
+    const lldb_private::ArchSpec&
+    GetArchSpec() const
+    {
+        return m_arch_spec;
+    }
+
+    CreateArchCalback
+    GetArchCreateCallback();
+
+    enum
+    {
+        eFlagsNone = 0,
+        eFlagsAttached = (1 << 0),
+        eFlagsUsingSBS = (1 << 1)
+    };
+
+    void
+    Clear ( );
+
+    lldb_private::Error
+    ReplyToAllExceptions();
+
+    lldb_private::Error
+    PrivateResume ( lldb::tid_t tid);
+
+    lldb_private::Flags &
+    GetFlags ()
+    {
+        return m_flags;
+    }
+
+    const lldb_private::Flags &
+    GetFlags () const
+    {
+        return m_flags;
+    }
+
+    bool
+    STDIOIsOurs() const
+    {
+        return m_stdio_ours;
+    }
+
+    void
+    SetSTDIOIsOurs(bool b)
+    {
+        m_stdio_ours = b;
+    }
+
+    uint32_t
+    UpdateThreadListIfNeeded ();
+
+private:
+
+    void
+    DidLaunchOrAttach ();
+
+    lldb_private::Error
+    DoSIGSTOP (bool clear_all_breakpoints);
+
+    lldb_private::Error
+    WillLaunchOrAttach ();
+
+//    static void *
+//    WaitForChildProcessToExit (void *pid_ptr);
+//
+//
+    //------------------------------------------------------------------
+    // For ProcessMacOSX only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (ProcessMacOSX);
+
+};
+
+#endif  // liblldb_MacOSXProcess_H_
diff --git a/source/Plugins/Process/MacOSX-User/source/ProcessMacOSXLog.cpp b/source/Plugins/Process/MacOSX-User/source/ProcessMacOSXLog.cpp
new file mode 100644
index 0000000..4bfd1ff
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/ProcessMacOSXLog.cpp
@@ -0,0 +1,124 @@
+//===-- ProcessMacOSXLog.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ProcessMacOSXLog.h"
+
+#include "lldb/Core/Args.h"
+#include "lldb/Core/StreamFile.h"
+
+#include "ProcessMacOSX.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+static Log* g_log = NULL; // Leak for now as auto_ptr was being cleaned up
+                          // by global constructors before other threads
+                          // were done with it.
+Log *
+ProcessMacOSXLog::GetLogIfAllCategoriesSet (uint32_t mask)
+{
+    Log *log = g_log;
+    if (log && mask)
+    {
+        uint32_t log_mask = log->GetMask().GetAllFlagBits();
+        if ((log_mask & mask) != mask)
+            return NULL;
+    }
+    return log;
+}
+
+void
+ProcessMacOSXLog::DisableLog ()
+{
+    if (g_log)
+    {
+        delete g_log;
+        g_log = NULL;
+    }
+}
+
+Log *
+ProcessMacOSXLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &args, Stream *feedback_strm)
+{
+    DisableLog ();
+    g_log = new Log (log_stream_sp);
+    if (g_log)
+    {
+        uint32_t flag_bits = 0;
+        bool got_unknown_category = false;
+        const size_t argc = args.GetArgumentCount();
+        for (size_t i=0; i<argc; ++i)
+        {
+            const char *arg = args.GetArgumentAtIndex(i);
+
+            if      (::strcasecmp (arg, "all")        == 0   ) flag_bits |= PD_LOG_ALL;
+            else if (::strcasestr (arg, "break")      == arg ) flag_bits |= PD_LOG_BREAKPOINTS;
+            else if (::strcasecmp (arg, "default")    == 0   ) flag_bits |= PD_LOG_DEFAULT;
+            else if (::strcasestr (arg, "exc")        == arg ) flag_bits |= PD_LOG_EXCEPTIONS;
+            else if (::strcasecmp (arg, "memory")     == 0   ) flag_bits |= PD_LOG_MEMORY;
+            else if (::strcasecmp (arg, "data-short") == 0   ) flag_bits |= PD_LOG_MEMORY_DATA_SHORT;
+            else if (::strcasecmp (arg, "data-long")  == 0   ) flag_bits |= PD_LOG_MEMORY_DATA_LONG;
+            else if (::strcasecmp (arg, "protections")== 0   ) flag_bits |= PD_LOG_MEMORY_PROTECTIONS;
+            else if (::strcasecmp (arg, "process")    == 0   ) flag_bits |= PD_LOG_PROCESS;
+            else if (::strcasecmp (arg, "step")       == 0   ) flag_bits |= PD_LOG_STEP;
+            else if (::strcasecmp (arg, "task")       == 0   ) flag_bits |= PD_LOG_TASK;
+            else if (::strcasecmp (arg, "thread")     == 0   ) flag_bits |= PD_LOG_THREAD;
+            else if (::strcasecmp (arg, "verbose")    == 0   ) flag_bits |= PD_LOG_VERBOSE;
+            else if (::strcasestr (arg, "watch")      == arg ) flag_bits |= PD_LOG_WATCHPOINTS;
+            else
+            {
+                feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
+                if (got_unknown_category == false)
+                {
+                    got_unknown_category = true;
+                    ListLogCategories (feedback_strm);
+                }
+            }
+        }
+        if (flag_bits == 0)
+            flag_bits = PD_LOG_DEFAULT;
+        g_log->GetMask().SetAllFlagBits(flag_bits);
+        g_log->GetOptions().SetAllFlagBits(log_options);
+    }
+    return g_log;
+}
+
+void
+ProcessMacOSXLog::ListLogCategories (Stream *strm)
+{
+    strm->Printf("Logging categories for '%s':\n"
+        "\tall - turn on all available logging categories\n"
+        "\tbreak - log breakpoints\n"
+        "\tdefault - enable the default set of logging categories for liblldb\n"
+        "\tmemory - log memory reads and writes\n"
+        "\tdata-short - log memory bytes for memory reads and writes for short transactions only\n"
+        "\tdata-long - log memory bytes for memory reads and writes for all transactions\n"
+        "\tprocess - log process events and activities\n"
+        "\tprotections - log memory protections\n"
+        "\ttask - log mach task calls\n"
+        "\tthread - log thread events and activities\n"
+        "\tstep - log step related activities\n"
+        "\tverbose - enable verbose loggging\n"
+        "\twatch - log watchpoint related activities\n", ProcessMacOSX::GetPluginNameStatic());
+}
+
+
+void
+ProcessMacOSXLog::LogIf (uint32_t mask, const char *format, ...)
+{
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (mask);
+    if (log)
+    {
+        va_list args;
+        va_start (args, format);
+        log->VAPrintf (format, args);
+        va_end (args);
+    }
+}
diff --git a/source/Plugins/Process/MacOSX-User/source/ProcessMacOSXLog.h b/source/Plugins/Process/MacOSX-User/source/ProcessMacOSXLog.h
new file mode 100644
index 0000000..cb2a4e8
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/ProcessMacOSXLog.h
@@ -0,0 +1,62 @@
+//===-- ProcessMacOSXLog.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_ProcessMacOSXLog_h_
+#define liblldb_ProcessMacOSXLog_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+
+// Project includes
+#include "lldb/Core/Log.h"
+
+#define PD_LOG_VERBOSE                  (1u << 0)
+#define PD_LOG_PROCESS                  (1u << 1)
+#define PD_LOG_THREAD                   (1u << 2)
+#define PD_LOG_EXCEPTIONS               (1u << 3)
+#define PD_LOG_MEMORY                   (1u << 4)    // Log memory reads/writes calls
+#define PD_LOG_MEMORY_DATA_SHORT        (1u << 5)    // Log short memory reads/writes bytes
+#define PD_LOG_MEMORY_DATA_LONG         (1u << 6)    // Log all memory reads/writes bytes
+#define PD_LOG_MEMORY_PROTECTIONS       (1u << 7)    // Log memory protection changes
+#define PD_LOG_BREAKPOINTS              (1u << 8)
+#define PD_LOG_WATCHPOINTS              (1u << 9)
+#define PD_LOG_STEP                     (1u << 10)
+#define PD_LOG_TASK                     (1u << 11)
+#define PD_LOG_ALL                      (UINT32_MAX)
+#define PD_LOG_DEFAULT                  (PD_LOG_PROCESS     |\
+                                         PD_LOG_TASK        |\
+                                         PD_LOG_THREAD      |\
+                                         PD_LOG_EXCEPTIONS  |\
+                                         PD_LOG_MEMORY      |\
+                                         PD_LOG_MEMORY_DATA_SHORT |\
+                                         PD_LOG_BREAKPOINTS |\
+                                         PD_LOG_WATCHPOINTS |\
+                                         PD_LOG_STEP        )
+
+class ProcessMacOSXLog
+{
+public:
+    static lldb_private::Log *
+    GetLogIfAllCategoriesSet(uint32_t mask = 0);
+
+    static void
+    DisableLog ();
+
+    static lldb_private::Log *
+    EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, lldb_private::Args &args, lldb_private::Stream *feedback_strm);
+
+    static void
+    ListLogCategories (lldb_private::Stream *strm);
+
+    static void
+    LogIf (uint32_t mask, const char *format, ...);
+};
+
+#endif  // liblldb_ProcessMacOSXLog_h_
diff --git a/source/Plugins/Process/MacOSX-User/source/ProcessMacOSXRemote.cpp b/source/Plugins/Process/MacOSX-User/source/ProcessMacOSXRemote.cpp
new file mode 100644
index 0000000..835d003
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/ProcessMacOSXRemote.cpp
@@ -0,0 +1,1819 @@
+//===-- ProcessMacOSXRemote.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//----------------------------------------------------------------------
+//
+//  ProcessMacOSXRemote.cpp
+//  liblldb
+//
+//  Created by Greg Clayton on 4/21/09.
+//
+//
+//----------------------------------------------------------------------
+
+// C Includes
+#include <errno.h>
+
+// C++ Includes
+//#include <algorithm>
+//#include <map>
+
+// Other libraries and framework includes
+
+// Project includes
+#include "ProcessMacOSXRemote.h"
+#include "ProcessMacOSXLog.h"
+#include "ThreadMacOSX.h"
+
+Process*
+ProcessMacOSXRemote::CreateInstance (Target &target)
+{
+    return new ProcessMacOSXRemote (target);
+}
+
+bool
+ProcessMacOSXRemote::CanDebug(Target &target)
+{
+    // For now we are just making sure the file exists for a given module
+    ModuleSP exe_module_sp(target.GetExecutableModule());
+    if (exe_module_sp.get())
+        return exe_module_sp->GetFileSpec().Exists();
+    return false;
+}
+
+//----------------------------------------------------------------------
+// ProcessMacOSXRemote constructor
+//----------------------------------------------------------------------
+ProcessMacOSXRemote::ProcessMacOSXRemote(Target& target) :
+    Process (target),
+    m_flags (0),
+    m_arch_spec (),
+    m_dynamic_loader_ap (),
+    m_byte_order(eByteOrderInvalid)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ProcessMacOSXRemote::~DCProcessMacOSXRemote()
+{
+    Clear();
+}
+
+//----------------------------------------------------------------------
+// Process Control
+//----------------------------------------------------------------------
+lldb::pid_t
+ProcessMacOSXRemote::DoLaunch
+(
+    Module* module,
+    char const *argv[],
+    char const *envp[],
+    const char *stdin_path,
+    const char *stdout_path,
+    const char *stderr_path
+)
+{
+//  ::LogSetBitMask (PD_LOG_DEFAULT);
+//  ::LogSetOptions (LLDB_LOG_OPTION_THREADSAFE | LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD);
+//  ::LogSetLogFile ("/dev/stdout");
+
+    ObjectFile * object_file = module->GetObjectFile();
+    if (object_file)
+    {
+        char exec_file_path[PATH_MAX];
+        FileSpec* file_spec_ptr = object_file->GetFileSpec();
+        if (file_spec_ptr)
+            file_spec_ptr->GetPath(exec_file_path, sizeof(exec_file_path));
+
+        ArchSpec arch_spec(module->GetArchitecture());
+
+        switch (arch_spec.GetCPUType())
+        {
+
+        }
+        // Set our user ID to our process ID.
+        SetID(LaunchForDebug(exec_file_path, argv, envp, arch_spec, stdin_path, stdout_path, stderr_path, eLaunchDefault, GetError()));
+    }
+    else
+    {
+        // Set our user ID to an invalid process ID.
+        SetID(LLDB_INVALID_PROCESS_ID);
+        GetError().SetErrorToGenericError ();
+        GetError().SetErrorStringWithFormat ("Failed to get object file from '%s' for arch %s.\n", module->GetFileSpec().GetFilename().AsCString(), module->GetArchitecture().AsCString());
+    }
+
+    // Return the process ID we have
+    return GetID();
+}
+
+lldb::pid_t
+ProcessMacOSXRemote::DoAttach (lldb::pid_t attach_pid)
+{
+    // Set our user ID to the attached process ID (which can be invalid if
+    // the attach fails
+    lldb::pid_t pid = AttachForDebug(attach_pid);
+    SetID(pid);
+
+//  if (pid != LLDB_INVALID_PROCESS_ID)
+//  {
+//      // Wait for a process stopped event, but don't consume it
+//      if (WaitForEvents(LLDB_EVENT_STOPPED, NULL, 30))
+//      {
+//      }
+//  }
+//
+    // Return the process ID we have
+    return pid;
+}
+
+
+void
+ProcessMacOSXRemote::DidLaunch ()
+{
+    if (GetID() == LLDB_INVALID_PROCESS_ID)
+    {
+        m_dynamic_loader_ap.reset();
+    }
+    else
+    {
+        Module * exe_module = GetTarget().GetExecutableModule ().get();
+        assert(exe_module);
+        ObjectFile *exe_objfile = exe_module->GetObjectFile();
+        assert(exe_objfile);
+        m_byte_order = exe_objfile->GetByteOrder();
+        assert(m_byte_order != eByteOrderInvalid);
+        // Install a signal handler so we can catch when our child process
+        // dies and set the exit status correctly.
+        m_wait_thread = Host::ThreadCreate (ProcessMacOSXRemote::WaitForChildProcessToExit, &m_uid, &m_error);
+        if (m_wait_thread != LLDB_INVALID_HOST_THREAD)
+        {
+            // Don't need to get the return value of this thread, so just let
+            // it clean up after itself when it dies.
+            Host::ThreadDetach (m_wait_thread, NULL);
+        }
+        m_dynamic_loader_ap.reset(DynamicLoader::FindPlugin(this, "macosx-dyld"));
+    }
+
+}
+
+void
+ProcessMacOSXRemote::DidAttach ()
+{
+    DidLaunch ();
+    m_need_to_run_did_attach = true;
+}
+
+bool
+ProcessMacOSXRemote::DoResume ()
+{
+    ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "ProcessMacOSXRemote::Resume()");
+    State state = GetState();
+
+    if (CanResume(state))
+    {
+        PrivateResume(LLDB_INVALID_THREAD_ID);
+    }
+    else if (state == eStateRunning)
+    {
+        ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "Resume() - task 0x%x is running, ignoring...", m_task.TaskPort());
+        GetError().Clear();
+
+    }
+    else
+    {
+        ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "Resume() - task 0x%x can't continue, ignoring...", m_task.TaskPort());
+        GetError().SetError(UINT_MAX, Error::Generic);
+    }
+
+    return GetError().Success();
+}
+
+size_t
+ProcessMacOSXRemote::GetSoftwareBreakpointTrapOpcode (BreakpointSite *bp_site)
+{
+    ModuleSP exe_module_sp(GetTarget().GetExecutableModule());
+    if (exe_module_sp.get())
+    {
+        const ArchSpec &exe_arch = exe_module_sp->GetArchitecture();
+        const uint8_t *trap_opcode = NULL;
+        uint32_t trap_opcode_size = 0;
+
+        static const uint8_t g_arm_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 };
+        //static const uint8_t g_thumb_breakpooint_opcode[] = { 0xFE, 0xDE };
+        static const uint8_t g_ppc_breakpoint_opcode[] = { 0x7F, 0xC0, 0x00, 0x08 };
+        static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC };
+
+        switch (exe_arch.GetCPUType())
+        {
+        case CPU_TYPE_ARM:
+            // TODO: fill this in for ARM. We need to dig up the symbol for
+            // the address in the breakpoint locaiton and figure out if it is
+            // an ARM or Thumb breakpoint.
+            trap_opcode = g_arm_breakpoint_opcode;
+            trap_opcode_size = sizeof(g_arm_breakpoint_opcode);
+            break;
+
+        case CPU_TYPE_POWERPC:
+        case CPU_TYPE_POWERPC64:
+            trap_opcode = g_ppc_breakpoint_opcode;
+            trap_opcode_size = sizeof(g_ppc_breakpoint_opcode);
+            break;
+
+        case CPU_TYPE_I386:
+        case CPU_TYPE_X86_64:
+            trap_opcode = g_i386_breakpoint_opcode;
+            trap_opcode_size = sizeof(g_i386_breakpoint_opcode);
+            break;
+
+        default:
+            assert(!"Unhandled architecture in ProcessMacOSXRemote::GetSoftwareBreakpointTrapOpcode()");
+            return 0;
+        }
+
+        if (trap_opcode && trap_opcode_size)
+        {
+            if (bp_loc->SetTrapOpcode(trap_opcode, trap_opcode_size))
+                return trap_opcode_size;
+        }
+    }
+    // No executable yet, so we can't tell what the breakpoint opcode will be.
+    return 0;
+}
+uint32_t
+ProcessMacOSXRemote::UpdateThreadListIfNeeded ()
+{
+    // locker will keep a mutex locked until it goes out of scope
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_THREAD);
+    if (log && log->GetMask().IsSet(PD_LOG_VERBOSE))
+        log->Printf ("ProcessMacOSXRemote::%s (pid = %4.4x)", __FUNCTION__, GetID());
+
+    const uint32_t stop_id = GetStopID();
+    if (m_thread_list.GetSize() == 0 || stop_id != m_thread_list.GetID())
+    {
+        m_thread_list.SetID (stop_id);
+        thread_array_t thread_list = NULL;
+        mach_msg_type_number_t thread_list_count = 0;
+        task_t task = Task().TaskPort();
+        Error err(::task_threads (task, &thread_list, &thread_list_count), Error::MachKernel);
+
+        if (log || err.Fail())
+            err.Log(log, "::task_threads ( task = 0x%4.4x, thread_list => %p, thread_list_count => %u )", task, thread_list, thread_list_count);
+
+        if (err.GetError() == KERN_SUCCESS && thread_list_count > 0)
+        {
+            ThreadList curr_thread_list;
+
+            size_t idx;
+            // Iterator through the current thread list and see which threads
+            // we already have in our list (keep them), which ones we don't
+            // (add them), and which ones are not around anymore (remove them).
+            for (idx = 0; idx < thread_list_count; ++idx)
+            {
+                const lldb::tid_t tid = thread_list[idx];
+                ThreadSP thread_sp(m_thread_list.FindThreadByID (tid));
+                if (thread_sp.get() == NULL)
+                    thread_sp.reset (new ThreadMacOSX (this, tid));
+                curr_thread_list.AddThread(thread_sp);
+            }
+
+            m_thread_list = curr_thread_list;
+
+            // Free the vm memory given to us by ::task_threads()
+            vm_size_t thread_list_size = (vm_size_t) (thread_list_count * sizeof (lldb::tid_t));
+            ::vm_deallocate (::mach_task_self(),
+                             (vm_address_t)thread_list,
+                             thread_list_size);
+        }
+    }
+    return m_thread_list.GetSize();
+}
+
+bool
+ProcessMacOSXRemote::ShouldStop ()
+{
+    // If we are attaching, let our dynamic loader plug-in know so it can get
+    // an initial list of shared libraries.
+    if (m_need_to_run_did_attach && m_dynamic_loader_ap.get())
+    {
+        m_need_to_run_did_attach = false;
+        m_dynamic_loader_ap->DidAttach();
+    }
+
+    // We must be attaching if we don't already have a valid architecture
+    if (!m_arch_spec.IsValid())
+    {
+        Module *exe_module = GetTarget().GetExecutableModule().get();
+        if (exe_module)
+            m_arch_spec = exe_module->GetArchitecture();
+    }
+    // Let all threads recover from stopping and do any clean up based
+    // on the previous thread state (if any).
+    UpdateThreadListIfNeeded ();
+
+    if (m_thread_list.ShouldStop())
+    {
+        // Let each thread know of any exceptions
+        Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_EXCEPTIONS);
+        task_t task = m_task.TaskPort();
+        size_t i;
+        for (i=0; i<m_exception_messages.size(); ++i)
+        {
+            // Let the thread list figure use the ProcessMacOSXRemote to forward all exceptions
+            // on down to each thread.
+            if (m_exception_messages[i].state.task_port == task)
+            {
+                ThreadSP thread_sp(m_thread_list.FindThreadByID(m_exception_messages[i].state.thread_port));
+                if (thread_sp.get())
+                {
+                    ThreadMacOSX *macosx_thread = (ThreadMacOSX *)thread_sp.get();
+                    macosx_thread->NotifyException (m_exception_messages[i].state);
+                }
+            }
+            if (log)
+                m_exception_messages[i].Log(log);
+        }
+        return true;
+    }
+    return false;
+}
+
+bool
+ProcessMacOSXRemote::DoHalt ()
+{
+    return Kill (SIGINT);
+}
+
+bool
+ProcessMacOSXRemote::WillDetach ()
+{
+    State state = GetState();
+
+    if (IsRunning(state))
+    {
+        m_error.SetErrorToGenericError();
+        m_error.SetErrorString("Process must be stopped in order to detach.");
+        return false;
+    }
+    return true;
+}
+
+bool
+ProcessMacOSXRemote::DoDetach ()
+{
+    m_use_public_queue = false;
+    bool success = Detach();
+    m_use_public_queue = true;
+    if (success)
+        SetState (eStateDetached);
+    return success;
+}
+
+bool
+ProcessMacOSXRemote::DoKill (int signal)
+{
+    return Kill (signal);
+}
+
+
+//------------------------------------------------------------------
+// Thread Queries
+//------------------------------------------------------------------
+
+Thread *
+ProcessMacOSXRemote::GetCurrentThread ()
+{
+    return m_thread_list.GetCurrentThread().get();
+}
+
+ByteOrder
+ProcessMacOSXRemote::GetByteOrder () const
+{
+    return m_byte_order;
+}
+
+
+
+//------------------------------------------------------------------
+// Process Queries
+//------------------------------------------------------------------
+
+bool
+ProcessMacOSXRemote::IsAlive ()
+{
+    return MachTask::IsValid (Task().TaskPort());
+}
+
+bool
+ProcessMacOSXRemote::IsRunning ()
+{
+    return LLDB_STATE_IS_RUNNING(GetState());
+}
+
+lldb::addr_t
+ProcessMacOSXRemote::GetImageInfoAddress()
+{
+    return Task().GetDYLDAllImageInfosAddress();
+}
+
+DynamicLoader *
+ProcessMacOSXRemote::GetDynamicLoader()
+{
+    return m_dynamic_loader_ap.get();
+}
+
+//------------------------------------------------------------------
+// Process Memory
+//------------------------------------------------------------------
+
+size_t
+ProcessMacOSXRemote::DoReadMemory (lldb::addr_t addr, void *buf, size_t size)
+{
+    return Task().ReadMemory(addr, buf, size);
+}
+
+size_t
+ProcessMacOSXRemote::DoWriteMemory (lldb::addr_t addr, const void *buf, size_t size)
+{
+    return Task().WriteMemory(addr, buf, size);
+}
+
+//------------------------------------------------------------------
+// Process STDIO
+//------------------------------------------------------------------
+
+size_t
+ProcessMacOSXRemote::GetSTDOUT (char *buf, size_t buf_size)
+{
+    ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "ProcessMacOSXRemote::%s (&%p[%u]) ...", __FUNCTION__, buf, buf_size);
+    Mutex::Locker locker(m_stdio_mutex);
+    size_t bytes_available = m_stdout_data.size();
+    if (bytes_available > 0)
+    {
+        if (bytes_available > buf_size)
+        {
+            memcpy(buf, m_stdout_data.data(), buf_size);
+            m_stdout_data.erase(0, buf_size);
+            bytes_available = buf_size;
+        }
+        else
+        {
+            memcpy(buf, m_stdout_data.data(), bytes_available);
+            m_stdout_data.clear();
+        }
+    }
+    return bytes_available;
+}
+
+size_t
+ProcessMacOSXRemote::GetSTDERR (char *buf, size_t buf_size)
+{
+    return 0;
+}
+
+bool
+ProcessMacOSXRemote::EnableBreakpoint (BreakpointLocation *bp)
+{
+    assert (bp != NULL);
+
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_BREAKPOINTS);
+    lldb::user_id_t breakID = bp->GetID();
+    lldb::addr_t addr = bp->GetAddress();
+    if (bp->IsEnabled())
+    {
+        if (log)
+            log->Printf("ProcessMacOSXRemote::EnableBreakpoint ( breakID = %d ) breakpoint already enabled.", breakID);
+        return true;
+    }
+    else
+    {
+        if (bp->HardwarePreferred())
+        {
+            ThreadMacOSX *thread = (ThreadMacOSX *)m_thread_list.FindThreadByID(bp->GetThreadID()).get();
+            if (thread)
+            {
+                bp->SetHardwareIndex (thread->EnableHardwareBreakpoint(bp));
+                if (bp->IsHardware())
+                {
+                    bp->SetEnabled(true);
+                    return true;
+                }
+            }
+        }
+
+        const size_t break_op_size = GetSoftwareBreakpointTrapOpcode (bp);
+        assert (break_op_size > 0);
+        const uint8_t * const break_op = bp->GetTrapOpcodeBytes();
+
+        if (break_op_size > 0)
+        {
+            // Save the original opcode by reading it
+            if (m_task.ReadMemory(addr, bp->GetSavedOpcodeBytes(), break_op_size) == break_op_size)
+            {
+                // Write a software breakpoint in place of the original opcode
+                if (m_task.WriteMemory(addr, break_op, break_op_size) == break_op_size)
+                {
+                    uint8_t verify_break_op[4];
+                    if (m_task.ReadMemory(addr, verify_break_op, break_op_size) == break_op_size)
+                    {
+                        if (memcmp(break_op, verify_break_op, break_op_size) == 0)
+                        {
+                            bp->SetEnabled(true);
+                            if (log)
+                                log->Printf("ProcessMacOSXRemote::EnableBreakpoint ( breakID = %d ) SUCCESS.", breakID, (uint64_t)addr);
+                            return true;
+                        }
+                        else
+                        {
+                            GetError().SetErrorString("Failed to verify the breakpoint trap in memory.");
+                        }
+                    }
+                    else
+                    {
+                        GetError().SetErrorString("Unable to read memory to verify breakpoint trap.");
+                    }
+                }
+                else
+                {
+                    GetError().SetErrorString("Unable to write breakpoint trap to memory.");
+                }
+            }
+            else
+            {
+                GetError().SetErrorString("Unable to read memory at breakpoint address.");
+            }
+        }
+    }
+
+    if (log)
+    {
+        const char *err_string = GetError().AsCString();
+        log->Printf ("ProcessMacOSXRemote::EnableBreakpoint ( breakID = %d ) error: %s",
+                     breakID, err_string ? err_string : "NULL");
+    }
+    GetError().SetErrorToGenericError();
+    return false;
+}
+
+bool
+ProcessMacOSXRemote::DisableBreakpoint (BreakpointLocation *bp)
+{
+    assert (bp != NULL);
+    lldb::addr_t addr = bp->GetAddress();
+    lldb::user_id_t breakID = bp->GetID();
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_BREAKPOINTS);
+    if (log)
+        log->Printf ("ProcessMacOSXRemote::DisableBreakpoint (breakID = %d) addr = 0x%8.8llx", breakID, (uint64_t)addr);
+
+    if (bp->IsHardware())
+    {
+        ThreadMacOSX *thread = (ThreadMacOSX *)m_thread_list.FindThreadByID(bp->GetThreadID()).get();
+        if (thread)
+        {
+            if (thread->DisableHardwareBreakpoint(bp))
+            {
+                bp->SetEnabled(false);
+                if (log)
+                    log->Printf ("ProcessMacOSXRemote::DisableBreakpoint (breakID = %d) (hardware) => success", breakID);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    const size_t break_op_size = bp->GetByteSize();
+    assert (break_op_size > 0);
+    const uint8_t * const break_op = bp->GetTrapOpcodeBytes();
+    if (break_op_size > 0)
+    {
+        // Clear a software breakoint instruction
+        uint8_t curr_break_op[break_op_size];
+        bool break_op_found = false;
+
+        // Read the breakpoint opcode
+        if (m_task.ReadMemory(addr, curr_break_op, break_op_size) == break_op_size)
+        {
+            bool verify = false;
+            if (bp->IsEnabled())
+            {
+                // Make sure we have the a breakpoint opcode exists at this address
+                if (memcmp(curr_break_op, break_op, break_op_size) == 0)
+                {
+                    break_op_found = true;
+                    // We found a valid breakpoint opcode at this address, now restore
+                    // the saved opcode.
+                    if (m_task.WriteMemory(addr, bp->GetSavedOpcodeBytes(), break_op_size) == break_op_size)
+                    {
+                        verify = true;
+                    }
+                    else
+                    {
+                        GetError().SetErrorString("Memory write failed when restoring original opcode.");
+                    }
+                }
+                else
+                {
+                    GetError().SetErrorString("Original breakpoint trap is no longer in memory.");
+                    // Set verify to true and so we can check if the original opcode has already been restored
+                    verify = true;
+                }
+            }
+            else
+            {
+                if (log)
+                    log->Printf ("ProcessMacOSXRemote::DisableBreakpoint (breakID = %d) is already disabled", breakID);
+                // Set verify to true and so we can check if the original opcode is there
+                verify = true;
+            }
+
+            if (verify)
+            {
+                uint8_t verify_opcode[break_op_size];
+                // Verify that our original opcode made it back to the inferior
+                if (m_task.ReadMemory(addr, verify_opcode, break_op_size) == break_op_size)
+                {
+                    // compare the memory we just read with the original opcode
+                    if (memcmp(bp->GetSavedOpcodeBytes(), verify_opcode, break_op_size) == 0)
+                    {
+                        // SUCCESS
+                        bp->SetEnabled(false);
+                        if (log)
+                            log->Printf ("ProcessMacOSXRemote::DisableBreakpoint (breakID = %d) SUCCESS", breakID);
+                        return true;
+                    }
+                    else
+                    {
+                        if (break_op_found)
+                            GetError().SetErrorString("Failed to restore original opcode.");
+                    }
+                }
+                else
+                {
+                    GetError().SetErrorString("Failed to read memory to verify that breakpoint trap was restored.");
+                }
+            }
+        }
+        else
+        {
+            GetError().SetErrorString("Unable to read memory that should contain the breakpoint trap.");
+        }
+    }
+
+    GetError().SetErrorToGenericError();
+    return false;
+}
+
+bool
+ProcessMacOSXRemote::EnableWatchpoint (WatchpointLocation *wp)
+{
+    if (wp)
+    {
+        lldb::user_id_t watchID = wp->GetID();
+        lldb::addr_t addr = wp->GetAddress();
+        Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_WATCHPOINTS);
+        if (log)
+            log->Printf ("ProcessMacOSXRemote::EnableWatchpoint(watchID = %d)", watchID);
+        if (wp->IsEnabled())
+        {
+            if (log)
+                log->Printf("ProcessMacOSXRemote::EnableWatchpoint(watchID = %d) addr = 0x%8.8llx: watchpoint already enabled.", watchID, (uint64_t)addr);
+            return true;
+        }
+        else
+        {
+            ThreadMacOSX *thread = (ThreadMacOSX *)m_thread_list.FindThreadByID(wp->GetThreadID()).get();
+            if (thread)
+            {
+                wp->SetHardwareIndex (thread->EnableHardwareWatchpoint (wp));
+                if (wp->IsHardware ())
+                {
+                    wp->SetEnabled(true);
+                    return true;
+                }
+            }
+            else
+            {
+                GetError().SetErrorString("Watchpoints currently only support thread specific watchpoints.");
+            }
+        }
+    }
+    return false;
+}
+
+bool
+ProcessMacOSXRemote::DisableWatchpoint (WatchpointLocation *wp)
+{
+    if (wp)
+    {
+        lldb::user_id_t watchID = wp->GetID();
+
+        Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_WATCHPOINTS);
+
+        lldb::addr_t addr = wp->GetAddress();
+        if (log)
+            log->Printf ("ProcessMacOSXRemote::DisableWatchpoint (watchID = %d) addr = 0x%8.8llx", watchID, (uint64_t)addr);
+
+        if (wp->IsHardware())
+        {
+            ThreadMacOSX *thread = (ThreadMacOSX *)m_thread_list.FindThreadByID(wp->GetThreadID()).get();
+            if (thread)
+            {
+                if (thread->DisableHardwareWatchpoint (wp))
+                {
+                    wp->SetEnabled(false);
+                    if (log)
+                        log->Printf ("ProcessMacOSXRemote::Disablewatchpoint (watchID = %d) addr = 0x%8.8llx (hardware) => success", watchID, (uint64_t)addr);
+                    return true;
+                }
+            }
+        }
+        // TODO: clear software watchpoints if we implement them
+    }
+    else
+    {
+        GetError().SetErrorString("Watchpoint location argument was NULL.");
+    }
+    GetError().SetErrorToGenericError();
+    return false;
+}
+
+
+static ProcessMacOSXRemote::CreateArchCalback
+ArchDCScriptInterpreter::TypeMap(const ArchSpec& arch_spec, ProcessMacOSXRemote::CreateArchCalback callback, bool add )
+{
+    // We must wrap the "g_arch_map" file static in a function to avoid
+    // any global constructors so we don't get a build verification error
+    typedef std::multimap<ArchSpec, ProcessMacOSXRemote::CreateArchCalback> ArchToProtocolMap;
+    static ArchToProtocolMap g_arch_map;
+
+    if (add)
+    {
+        g_arch_map.insert(std::make_pair(arch_spec, callback));
+        return callback;
+    }
+    else
+    {
+        ArchToProtocolMap::const_iterator pos = g_arch_map.find(arch_spec);
+        if (pos != g_arch_map.end())
+        {
+            return pos->second;
+        }
+    }
+    return NULL;
+}
+
+void
+ProcessMacOSXRemote::AddArchCreateDCScriptInterpreter::Type(const ArchSpec& arch_spec, CreateArchCalback callback)
+{
+    ArchDCScriptInterpreter::TypeMap (arch_spec, callback, true);
+}
+
+ProcessMacOSXRemote::CreateArchCalback
+ProcessMacOSXRemote::GetArchCreateDCScriptInterpreter::Type()
+{
+    return ArchDCScriptInterpreter::TypeMap (m_arch_spec, NULL, false);
+}
+
+void
+ProcessMacOSXRemote::Clear()
+{
+    // Clear any cached thread list while the pid and task are still valid
+
+    m_task.Clear();
+    // Now clear out all member variables
+    CloseChildFileDescriptors();
+
+    m_flags = eFlagsNone;
+    m_thread_list.Clear();
+    {
+        Mutex::Locker locker(m_exception_messages_mutex);
+        m_exception_messages.clear();
+    }
+
+}
+
+
+bool
+ProcessMacOSXRemote::Kill (int signal)
+{
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_PROCESS);
+    if (log)
+        log->Printf ("ProcessMacOSXRemote::Kill(signal = %d)", signal);
+    State state = GetState();
+
+    if (IsRunning(state))
+    {
+        if (::kill (GetID(), signal) == 0)
+        {
+            GetError().Clear();
+        }
+        else
+        {
+            GetError().SetErrorToErrno();
+            GetError().LogIfError(log, "ProcessMacOSXRemote::Kill(%d)", signal);
+        }
+    }
+    else
+    {
+        if (log)
+            log->Printf ("ProcessMacOSXRemote::Kill(signal = %d) pid %u (task = 0x%4.4x) was't running, ignoring...", signal, GetID(), m_task.TaskPort());
+        GetError().Clear();
+    }
+    return GetError().Success();
+
+}
+
+
+bool
+ProcessMacOSXRemote::Detach()
+{
+    ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "ProcessMacOSXRemote::Detach()");
+
+    State state = GetState();
+
+    if (!IsRunning(state))
+    {
+        // Resume our process
+        PrivateResume(LLDB_INVALID_THREAD_ID);
+
+        // We have resumed and now we wait for that event to get posted
+        Event event;
+        if (WaitForPrivateEvents(LLDB_EVENT_RUNNING, &event, 2) == false)
+            return false;
+
+
+        // We need to be stopped in order to be able to detach, so we need
+        // to send ourselves a SIGSTOP
+        if (Kill(SIGSTOP))
+        {
+            Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_PROCESS);
+
+            lldb::pid_t pid = GetID();
+            // Wait for our process stop event to get posted
+            if (WaitForPrivateEvents(LLDB_EVENT_STOPPED, &event, 2) == false)
+            {
+                GetError().Log(log, "::kill (pid = %u, SIGSTOP)", pid);
+                return false;
+            }
+
+            // Shut down the exception thread and cleanup our exception remappings
+            m_task.ShutDownExceptionThread();
+
+            // Detach from our process while we are stopped.
+            errno = 0;
+
+            // Detach from our process
+            ::ptrace (PT_DETACH, pid, (caddr_t)1, 0);
+
+            GetError().SetErrorToErrno();
+
+            if (log || GetError().Fail())
+                GetError().Log(log, "::ptrace (PT_DETACH, %u, (caddr_t)1, 0)", pid);
+
+            // Resume our task
+            m_task.Resume();
+
+            // NULL our task out as we have already retored all exception ports
+            m_task.Clear();
+
+            // Clear out any notion of the process we once were
+            Clear();
+        }
+    }
+    else
+    {
+        ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "ProcessMacOSXRemote::Detach() error: process must be stopped (SIGINT the process first).");
+    }
+    return false;
+}
+
+
+
+void
+ProcessMacOSXRemote::ReplyToAllExceptions()
+{
+    Mutex::Locker locker(m_exception_messages_mutex);
+    if (m_exception_messages.empty() == false)
+    {
+        Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_EXCEPTIONS);
+
+        MachException::Message::iterator pos;
+        MachException::Message::iterator begin = m_exception_messages.begin();
+        MachException::Message::iterator end = m_exception_messages.end();
+        for (pos = begin; pos != end; ++pos)
+        {
+            if (log)
+                log->Printf ("Replying to exception %d...", std::distance(begin, pos));
+            int resume_signal = 0;
+            ThreadSP thread_sp = m_thread_list.FindThreadByID(pos->state.thread_port);
+            if (thread_sp.get())
+                resume_signal = thread_sp->GetResumeSignal();
+            GetError() = pos->Reply (Task().TaskPort(), GetID(), resume_signal);
+            GetError().LogIfError(log, "Error replying to exception");
+        }
+
+        // Erase all exception message as we should have used and replied
+        // to them all already.
+        m_exception_messages.clear();
+    }
+}
+void
+ProcessMacOSXRemote::PrivateResume (lldb::tid_t tid)
+{
+    Mutex::Locker locker(m_exception_messages_mutex);
+    ReplyToAllExceptions();
+
+    // Let the thread prepare to resume and see if any threads want us to
+    // step over a breakpoint instruction (ProcessWillResume will modify
+    // the value of stepOverBreakInstruction).
+    //StateType process_state = m_thread_list.ProcessWillResume(this);
+
+    // Set our state accordingly
+    SetState(eStateRunning);
+
+    // Now resume our task.
+    GetError() = m_task.Resume();
+
+}
+
+// Called by the exception thread when an exception has been received from
+// our process. The exception message is completely filled and the exception
+// data has already been copied.
+void
+ProcessMacOSXRemote::ExceptionMessageReceived (const MachException::Message& exceptionMessage)
+{
+    Mutex::Locker locker(m_exception_messages_mutex);
+
+    if (m_exception_messages.empty())
+        m_task.Suspend();
+
+    ProcessMacOSXLog::LogIf (PD_LOG_EXCEPTIONS, "ProcessMacOSXRemote::ExceptionMessageReceived ( )");
+
+    // Use a locker to automatically unlock our mutex in case of exceptions
+    // Add the exception to our internal exception stack
+    m_exception_messages.push_back(exceptionMessage);
+}
+
+
+//bool
+//ProcessMacOSXRemote::GetProcessInfo (struct kinfo_proc* proc_info)
+//{
+//  int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, GetID() };
+//  size_t buf_size = sizeof(struct kinfo_proc);
+//
+//  if (::sysctl (mib, (unsigned)(sizeof(mib)/sizeof(int)), &proc_info, &buf_size, NULL, 0) == 0)
+//      return buf_size > 0;
+//
+//  return false;
+//}
+//
+//
+void
+ProcessMacOSXRemote::ExceptionMessageBundleComplete()
+{
+    // We have a complete bundle of exceptions for our child process.
+    Mutex::Locker locker(m_exception_messages_mutex);
+    ProcessMacOSXLog::LogIf (PD_LOG_EXCEPTIONS, "%s: %d exception messages.", __PRETTY_FUNCTION__, m_exception_messages.size());
+    if (!m_exception_messages.empty())
+    {
+        SetState (eStateStopped);
+    }
+    else
+    {
+        ProcessMacOSXLog::LogIf (PD_LOG_EXCEPTIONS, "%s empty exception messages bundle.", __PRETTY_FUNCTION__, m_exception_messages.size());
+    }
+}
+
+bool
+ProcessMacOSXRemote::ReleaseChildFileDescriptors ( int *stdin_fileno, int *stdout_fileno, int *stderr_fileno )
+{
+    if (stdin_fileno)
+        *stdin_fileno = m_child_stdin;
+    if (stdout_fileno)
+        *stdout_fileno = m_child_stdout;
+    if (stderr_fileno)
+        *stderr_fileno = m_child_stderr;
+    // Stop the stdio thread if we have one, but don't have it close the child
+    // file descriptors since we are giving control of these descriptors to the
+    // caller
+    bool close_child_fds = false;
+    StopSTDIOThread(close_child_fds);
+    return true;
+}
+
+void
+ProcessMacOSXRemote::AppendSTDOUT (char* s, size_t len)
+{
+    ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "ProcessMacOSXRemote::%s (<%d> %s) ...", __FUNCTION__, len, s);
+    Mutex::Locker locker(m_stdio_mutex);
+    m_stdout_data.append(s, len);
+    AppendEvent (LLDB_EVENT_STDIO);
+}
+
+void *
+ProcessMacOSXRemote::STDIOThread(void *arg)
+{
+    ProcessMacOSXRemote *proc = (ProcessMacOSXRemote*) arg;
+
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_PROCESS);
+    if (log)
+        log->Printf ("ProcessMacOSXRemote::%s (arg = %p) thread starting...", __FUNCTION__, arg);
+
+    // We start use a base and more options so we can control if we
+    // are currently using a timeout on the mach_msg. We do this to get a
+    // bunch of related exceptions on our exception port so we can process
+    // then together. When we have multiple threads, we can get an exception
+    // per thread and they will come in consecutively. The main thread loop
+    // will start by calling mach_msg to without having the MACH_RCV_TIMEOUT
+    // flag set in the options, so we will wait forever for an exception on
+    // our exception port. After we get one exception, we then will use the
+    // MACH_RCV_TIMEOUT option with a zero timeout to grab all other current
+    // exceptions for our process. After we have received the last pending
+    // exception, we will get a timeout which enables us to then notify
+    // our main thread that we have an exception bundle avaiable. We then wait
+    // for the main thread to tell this exception thread to start trying to get
+    // exceptions messages again and we start again with a mach_msg read with
+    // infinite timeout.
+    Error err;
+    int stdout_fd = proc->GetStdoutFileDescriptor();
+    int stderr_fd = proc->GetStderrFileDescriptor();
+    if (stdout_fd == stderr_fd)
+        stderr_fd = -1;
+
+    while (stdout_fd >= 0 || stderr_fd >= 0)
+    {
+        ::pthread_testcancel ();
+
+        fd_set read_fds;
+        FD_ZERO (&read_fds);
+        if (stdout_fd >= 0)
+            FD_SET (stdout_fd, &read_fds);
+        if (stderr_fd >= 0)
+            FD_SET (stderr_fd, &read_fds);
+        int nfds = std::max<int>(stdout_fd, stderr_fd) + 1;
+
+        int num_set_fds = select (nfds, &read_fds, NULL, NULL, NULL);
+        if (log)
+            log->Printf("select (nfds, &read_fds, NULL, NULL, NULL) => %d", num_set_fds);
+
+        if (num_set_fds < 0)
+        {
+            int select_errno = errno;
+            if (log)
+            {
+                err.SetError (select_errno, Error::POSIX);
+                err.LogIfError(log, "select (nfds, &read_fds, NULL, NULL, NULL) => %d", num_set_fds);
+            }
+
+            switch (select_errno)
+            {
+            case EAGAIN:    // The kernel was (perhaps temporarily) unable to allocate the requested number of file descriptors, or we have non-blocking IO
+                break;
+            case EBADF:     // One of the descriptor sets specified an invalid descriptor.
+                return NULL;
+                break;
+            case EINTR:     // A signal was delivered before the time limit expired and before any of the selected events occurred.
+            case EINVAL:    // The specified time limit is invalid. One of its components is negative or too large.
+            default:        // Other unknown error
+                break;
+            }
+        }
+        else if (num_set_fds == 0)
+        {
+        }
+        else
+        {
+            char s[1024];
+            s[sizeof(s)-1] = '\0';  // Ensure we have NULL termination
+            int bytes_read = 0;
+            if (stdout_fd >= 0 && FD_ISSET (stdout_fd, &read_fds))
+            {
+                do
+                {
+                    bytes_read = ::read (stdout_fd, s, sizeof(s)-1);
+                    if (bytes_read < 0)
+                    {
+                        int read_errno = errno;
+                        if (log)
+                            log->Printf("read (stdout_fd, ) => %d   errno: %d (%s)", bytes_read, read_errno, strerror(read_errno));
+                    }
+                    else if (bytes_read == 0)
+                    {
+                        // EOF...
+                        if (log)
+                            log->Printf("read (stdout_fd, ) => %d  (reached EOF for child STDOUT)", bytes_read);
+                        stdout_fd = -1;
+                    }
+                    else if (bytes_read > 0)
+                    {
+                        proc->AppendSTDOUT(s, bytes_read);
+                    }
+
+                } while (bytes_read > 0);
+            }
+
+            if (stderr_fd >= 0 && FD_ISSET (stderr_fd, &read_fds))
+            {
+                do
+                {
+                    bytes_read = ::read (stderr_fd, s, sizeof(s)-1);
+                    if (bytes_read < 0)
+                    {
+                        int read_errno = errno;
+                        if (log)
+                            log->Printf("read (stderr_fd, ) => %d   errno: %d (%s)", bytes_read, read_errno, strerror(read_errno));
+                    }
+                    else if (bytes_read == 0)
+                    {
+                        // EOF...
+                        if (log)
+                            log->Printf("read (stderr_fd, ) => %d  (reached EOF for child STDERR)", bytes_read);
+                        stderr_fd = -1;
+                    }
+                    else if (bytes_read > 0)
+                    {
+                        proc->AppendSTDOUT(s, bytes_read);
+                    }
+
+                } while (bytes_read > 0);
+            }
+        }
+    }
+
+    if (log)
+        log->Printf("ProcessMacOSXRemote::%s (%p): thread exiting...", __FUNCTION__, arg);
+
+    return NULL;
+}
+
+lldb::pid_t
+ProcessMacOSXRemote::AttachForDebug (lldb::pid_t pid)
+{
+    // Clear out and clean up from any current state
+    Clear();
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_PROCESS);
+    if (pid != 0)
+    {
+        SetState(eStateAttaching);
+        SetID(pid);
+        // Let ourselves know we are going to be using SBS if the correct flag bit is set...
+#if defined (__arm__)
+        if (IsSBProcess(pid))
+            m_flags |= eFlagsUsingSBS;
+#endif
+        m_task.StartExceptionThread(GetError());
+
+        if (GetError().Success())
+        {
+            if (ptrace (PT_ATTACHEXC, pid, 0, 0) == 0)
+            {
+                m_flags.Set (eFlagsAttached);
+                // Sleep a bit to let the exception get received and set our process status
+                // to stopped.
+                ::usleep(250000);
+                if (log)
+                    log->Printf ("successfully attached to pid %d", pid);
+                return GetID();
+            }
+            else
+            {
+                GetError().SetErrorToErrno();
+                if (log)
+                    log->Printf ("error: failed to attach to pid %d", pid);
+            }
+        }
+        else
+        {
+            GetError().Log(log, "ProcessMacOSXRemote::%s (pid = %i) failed to start exception thread", __FUNCTION__, pid);
+        }
+    }
+    return LLDB_INVALID_PROCESS_ID;
+}
+
+lldb::pid_t
+ProcessMacOSXRemote::LaunchForDebug
+(
+    const char *path,
+    char const *argv[],
+    char const *envp[],
+    ArchSpec& arch_spec,
+    const char *stdin_path,
+    const char *stdout_path,
+    const char *stderr_path,
+    PDLaunchType launch_type,
+    Error &launch_err)
+{
+    // Clear out and clean up from any current state
+    Clear();
+
+    m_arch_spec = arch_spec;
+
+    if (launch_type == eLaunchDefault)
+        launch_type = eLaunchPosixSpawn;
+
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_PROCESS);
+    if (log)
+        log->Printf ("%s( path = '%s', argv = %p, envp = %p, launch_type = %u )", __FUNCTION__, path, argv, envp, launch_type);
+
+    // Fork a child process for debugging
+    SetState(eStateLaunching);
+    switch (launch_type)
+    {
+    case eLaunchForkExec:
+        SetID(ProcessMacOSXRemote::ForkChildForPTraceDebugging(path, argv, envp, arch_spec, stdin_path, stdout_path, stderr_path, this, launch_err));
+        break;
+
+    case eLaunchPosixSpawn:
+        SetID(ProcessMacOSXRemote::PosixSpawnChildForPTraceDebugging(path, argv, envp, arch_spec, stdin_path, stdout_path, stderr_path, this, launch_err));
+        break;
+
+#if defined (__arm__)
+
+    case eLaunchSpringBoard:
+        {
+            const char *app_ext = strstr(path, ".app");
+            if (app_ext != NULL)
+            {
+                std::string app_bundle_path(path, app_ext + strlen(".app"));
+                return SBLaunchForDebug (app_bundle_path.c_str(), argv, envp, arch_spec, stdin_path, stdout_path, stderr_path, launch_err);
+            }
+        }
+        break;
+
+#endif
+
+    default:
+        // Invalid  launch
+        launch_err.SetErrorToGenericError ();
+        return LLDB_INVALID_PROCESS_ID;
+    }
+
+    lldb::pid_t pid = GetID();
+
+    if (pid == LLDB_INVALID_PROCESS_ID)
+    {
+        // If we don't have a valid process ID and no one has set the error,
+        // then return a generic error
+        if (launch_err.Success())
+            launch_err.SetErrorToGenericError ();
+    }
+    else
+    {
+        // Make sure we can get our task port before going any further
+        m_task.TaskPortForProcessID (launch_err);
+
+        // If that goes well then kick off our exception thread
+        if (launch_err.Success())
+            m_task.StartExceptionThread(launch_err);
+
+        if (launch_err.Success())
+        {
+            //m_path = path;
+//          size_t i;
+//          if (argv)
+//          {
+//              char const *arg;
+//              for (i=0; (arg = argv[i]) != NULL; i++)
+//                  m_args.push_back(arg);
+//          }
+
+            StartSTDIOThread();
+
+            if (launch_type == eLaunchPosixSpawn)
+            {
+
+                //SetState (eStateAttaching);
+                errno = 0;
+                if (::ptrace (PT_ATTACHEXC, pid, 0, 0) == 0)
+                    launch_err.Clear();
+                else
+                    launch_err.SetErrorToErrno();
+
+                if (launch_err.Fail() || log)
+                    launch_err.Log(log, "::ptrace (PT_ATTACHEXC, pid = %i, 0, 0 )", pid);
+
+                if (launch_err.Success())
+                    m_flags.Set (eFlagsAttached);
+                else
+                    SetState (eStateExited);
+            }
+            else
+            {
+                launch_err.Clear();
+            }
+        }
+        else
+        {
+            // We were able to launch the process, but not get its task port
+            // so now we need to make it sleep with da fishes.
+            SetID(LLDB_INVALID_PROCESS_ID);
+            ::kill (pid, SIGCONT);
+            ::kill (pid, SIGKILL);
+            pid = LLDB_INVALID_PROCESS_ID;
+        }
+
+    }
+    return pid;
+}
+
+lldb::pid_t
+ProcessMacOSXRemote::PosixSpawnChildForPTraceDebugging
+(
+    const char *path,
+    char const *argv[],
+    char const *envp[],
+    ArchSpec& arch_spec,
+    const char *stdin_path,
+    const char *stdout_path,
+    const char *stderr_path,
+    ProcessMacOSXRemote* process,
+    Error &err
+)
+{
+    posix_spawnattr_t attr;
+
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_PROCESS);
+
+    Error local_err;    // Errors that don't affect the spawning.
+    if (log)
+        log->Printf ("%s ( path='%s', argv=%p, envp=%p, process )", __FUNCTION__, path, argv, envp);
+    err.SetError( ::posix_spawnattr_init (&attr), Error::POSIX);
+    if (err.Fail() || log)
+        err.Log(log, "::posix_spawnattr_init ( &attr )");
+    if (err.Fail())
+        return LLDB_INVALID_PROCESS_ID;
+
+    err.SetError( ::posix_spawnattr_setflags (&attr, POSIX_SPAWN_START_SUSPENDED), Error::POSIX);
+    if (err.Fail() || log)
+        err.Log(log, "::posix_spawnattr_setflags ( &attr, POSIX_SPAWN_START_SUSPENDED )");
+    if (err.Fail())
+        return LLDB_INVALID_PROCESS_ID;
+
+#if !defined(__arm__)
+
+    // We don't need to do this for ARM, and we really shouldn't now that we
+    // have multiple CPU subtypes and no posix_spawnattr call that allows us
+    // to set which CPU subtype to launch...
+    cpu_type_t cpu = arch_spec.GetCPUType();
+    if (cpu != 0 && cpu != CPU_TYPE_ANY && cpu != LLDB_INVALID_CPUTYPE)
+    {
+        size_t ocount = 0;
+        err.SetError( ::posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &ocount), Error::POSIX);
+        if (err.Fail() || log)
+            err.Log(log, "::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = 0x%8.8x, count => %zu )", cpu, ocount);
+
+        if (err.Fail() != 0 || ocount != 1)
+            return LLDB_INVALID_PROCESS_ID;
+    }
+
+#endif
+
+    PseudoTerminal pty;
+
+    posix_spawn_file_actions_t file_actions;
+    err.SetError( ::posix_spawn_file_actions_init (&file_actions), Error::POSIX);
+    int file_actions_valid = err.Success();
+    if (!file_actions_valid || log)
+        err.Log(log, "::posix_spawn_file_actions_init ( &file_actions )");
+    Error stdio_err;
+    lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+    if (file_actions_valid)
+    {
+        // If the user specified any STDIO files, then use those
+        if (stdin_path || stdout_path || stderr_path)
+        {
+            process->SetSTDIOIsOurs(false);
+            if (stderr_path != NULL && stderr_path[0])
+            {
+                stdio_err.SetError( ::posix_spawn_file_actions_addopen(&file_actions, STDERR_FILENO,    stderr_path, O_RDWR, 0), Error::POSIX);
+                if (stdio_err.Fail() || log)
+                    stdio_err.Log(log, "::posix_spawn_file_actions_addopen ( &file_actions, filedes = STDERR_FILENO, path = '%s', oflag = O_RDWR, mode = 0 )", stderr_path);
+            }
+
+            if (stdin_path != NULL && stdin_path[0])
+            {
+                stdio_err.SetError( ::posix_spawn_file_actions_addopen(&file_actions, STDIN_FILENO, stdin_path, O_RDONLY, 0), Error::POSIX);
+                if (stdio_err.Fail() || log)
+                    stdio_err.Log(log, "::posix_spawn_file_actions_addopen ( &file_actions, filedes = STDIN_FILENO, path = '%s', oflag = O_RDONLY, mode = 0 )", stdin_path);
+            }
+
+            if (stdout_path != NULL && stdout_path[0])
+            {
+                stdio_err.SetError( ::posix_spawn_file_actions_addopen(&file_actions, STDOUT_FILENO,    stdout_path, O_WRONLY, 0), Error::POSIX);
+                if (stdio_err.Fail() || log)
+                    stdio_err.Log(log, "::posix_spawn_file_actions_addopen ( &file_actions, filedes = STDOUT_FILENO, path = '%s', oflag = O_WRONLY, mode = 0 )", stdout_path);
+            }
+        }
+        else
+        {
+            // The user did not specify any STDIO files, use a pseudo terminal.
+            // Callers can then access the file handles using the
+            // ProcessMacOSXRemote::ReleaseChildFileDescriptors() function, otherwise
+            // this class will spawn a thread that tracks STDIO and buffers it.
+            process->SetSTDIOIsOurs(true);
+            if (pty.OpenFirstAvailableMaster(O_RDWR, &stdio_err))
+            {
+                const char* slave_name = pty.GetSlaveName(&stdio_err);
+                if (slave_name == NULL)
+                    slave_name = "/dev/null";
+                stdio_err.SetError( ::posix_spawn_file_actions_addopen(&file_actions, STDERR_FILENO,    slave_name, O_RDWR, 0), Error::POSIX);
+                if (stdio_err.Fail() || log)
+                    stdio_err.Log(log, "::posix_spawn_file_actions_addopen ( &file_actions, filedes = STDERR_FILENO, path = '%s', oflag = O_RDWR, mode = 0 )", slave_name);
+
+                stdio_err.SetError( ::posix_spawn_file_actions_addopen(&file_actions, STDIN_FILENO, slave_name, O_RDONLY, 0), Error::POSIX);
+                if (stdio_err.Fail() || log)
+                    stdio_err.Log(log, "::posix_spawn_file_actions_addopen ( &file_actions, filedes = STDIN_FILENO, path = '%s', oflag = O_RDONLY, mode = 0 )", slave_name);
+
+                stdio_err.SetError( ::posix_spawn_file_actions_addopen(&file_actions, STDOUT_FILENO,    slave_name, O_WRONLY, 0), Error::POSIX);
+                if (stdio_err.Fail() || log)
+                    stdio_err.Log(log, "::posix_spawn_file_actions_addopen ( &file_actions, filedes = STDOUT_FILENO, path = '%s', oflag = O_WRONLY, mode = 0 )", slave_name);
+            }
+        }
+        err.SetError( ::posix_spawnp (&pid, path, &file_actions, &attr, (char * const*)argv, (char * const*)envp), Error::POSIX);
+        if (err.Fail() || log)
+            err.Log(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", pid, path, &file_actions, &attr, argv, envp);
+
+        if (stdio_err.Success())
+        {
+            // If we have a valid process and we created the STDIO file handles,
+            // then remember them on our process class so we can spawn a STDIO
+            // thread and close them when we are done with them.
+            if (process != NULL && process->STDIOIsOurs())
+            {
+                int master_fd = pty.ReleaseMasterFileDescriptor ();
+                process->SetChildFileDescriptors (master_fd, master_fd, master_fd);
+            }
+        }
+    }
+    else
+    {
+        err.SetError( ::posix_spawnp (&pid, path, NULL, &attr, (char * const*)argv, (char * const*)envp), Error::POSIX);
+        if (err.Fail() || log)
+            err.Log(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", pid, path, NULL, &attr, argv, envp);
+    }
+
+    // We have seen some cases where posix_spawnp was returning a valid
+    // looking pid even when an error was returned, so clear it out
+    if (err.Fail())
+        pid = LLDB_INVALID_PROCESS_ID;
+
+    if (file_actions_valid)
+    {
+        local_err.SetError( ::posix_spawn_file_actions_destroy (&file_actions), Error::POSIX);
+        if (local_err.Fail() || log)
+            local_err.Log(log, "::posix_spawn_file_actions_destroy ( &file_actions )");
+    }
+
+    return pid;
+}
+
+lldb::pid_t
+ProcessMacOSXRemote::ForkChildForPTraceDebugging
+(
+    const char *path,
+    char const *argv[],
+    char const *envp[],
+    ArchSpec& arch_spec,
+    const char *stdin_path,
+    const char *stdout_path,
+    const char *stderr_path,
+    ProcessMacOSXRemote* process,
+    Error &launch_err
+)
+{
+    lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+
+    if (stdin_path || stdout_path || stderr_path)
+    {
+        assert(!"TODO: ForkChildForPTraceDebugging doesn't currently support fork/exec with user file handles...");
+    }
+    else
+    {
+
+        // Use a fork that ties the child process's stdin/out/err to a pseudo
+        // terminal so we can read it in our ProcessMacOSXRemote::STDIOThread
+        // as unbuffered io.
+        PseudoTerminal pty;
+        pid = pty.Fork(&launch_err);
+
+        if (pid < 0)
+        {
+            //--------------------------------------------------------------
+            // Error during fork.
+            //--------------------------------------------------------------
+            return pid;
+        }
+        else if (pid == 0)
+        {
+            //--------------------------------------------------------------
+            // Child process
+            //--------------------------------------------------------------
+            ::ptrace (PT_TRACE_ME, 0, 0, 0);    // Debug this process
+            ::ptrace (PT_SIGEXC, 0, 0, 0);    // Get BSD signals as mach exceptions
+
+            // If our parent is setgid, lets make sure we don't inherit those
+            // extra powers due to nepotism.
+            ::setgid (getgid ());
+
+            // Let the child have its own process group. We need to execute
+            // this call in both the child and parent to avoid a race condition
+            // between the two processes.
+            ::setpgid (0, 0);    // Set the child process group to match its pid
+
+            // Sleep a bit to before the exec call
+            ::sleep (1);
+
+            // Turn this process into
+            ::execv (path, (char * const *)argv);
+            // Exit with error code. Child process should have taken
+            // over in above exec call and if the exec fails it will
+            // exit the child process below.
+            ::exit (127);
+        }
+        else
+        {
+            //--------------------------------------------------------------
+            // Parent process
+            //--------------------------------------------------------------
+            // Let the child have its own process group. We need to execute
+            // this call in both the child and parent to avoid a race condition
+            // between the two processes.
+            ::setpgid (pid, pid);    // Set the child process group to match its pid
+
+            if (process != NULL)
+            {
+                // Release our master pty file descriptor so the pty class doesn't
+                // close it and so we can continue to use it in our STDIO thread
+                int master_fd = pty.ReleaseMasterFileDescriptor ();
+                process->SetChildFileDescriptors (master_fd, master_fd, master_fd);
+            }
+        }
+    }
+    return pid;
+}
+
+#if defined (__arm__)
+
+lldb::pid_t
+ProcessMacOSXRemote::SBLaunchForDebug
+(
+    const char *path,
+    char const *argv[],
+    char const *envp[],
+    ArchSpec& arch_spec,
+    const char *stdin_path,
+    const char *stdout_path,
+    const char *stderr_path,
+    Error &launch_err
+)
+{
+    // Clear out and clean up from any current state
+    Clear();
+
+    ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "%s( '%s', argv)", __FUNCTION__, path);
+
+    // Fork a child process for debugging
+    SetState(eStateLaunching);
+    m_pid = ProcessMacOSXRemote::SBLaunchForDebug(path, argv, envp, this, launch_err);
+    if (m_pid != 0)
+    {
+        m_flags |= eFlagsUsingSBS;
+        //m_path = path;
+//        size_t i;
+//        char const *arg;
+//        for (i=0; (arg = argv[i]) != NULL; i++)
+//            m_args.push_back(arg);
+        m_task.StartExceptionThread();
+        StartSTDIOThread();
+        SetState (eStateAttaching);
+        int err = ptrace (PT_ATTACHEXC, m_pid, 0, 0);
+        if (err == 0)
+        {
+            m_flags |= eFlagsAttached;
+            ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "successfully attached to pid %d", m_pid);
+        }
+        else
+        {
+            SetState (eStateExited);
+            ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "error: failed to attach to pid %d", m_pid);
+        }
+    }
+    return m_pid;
+}
+
+#include <servers/bootstrap.h>
+#include "CFBundle.h"
+#include "CFData.h"
+#include "CFString.h"
+
+lldb::pid_t
+ProcessMacOSXRemote::SBLaunchForDebug
+(
+    const char *app_bundle_path,
+    char const *argv[],
+    char const *envp[],
+    ArchSpec& arch_spec,
+    const char *stdin_path,
+    const char *stdout_path,
+    const char *stderr_path,
+    ProcessMacOSXRemote* process,
+    Error &launch_err
+)
+{
+    ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "%s( '%s', argv, %p)", __FUNCTION__, app_bundle_path, process);
+    CFAllocatorRef alloc = kCFAllocatorDefault;
+    if (argv[0] == NULL)
+        return LLDB_INVALID_PROCESS_ID;
+
+    size_t argc = 0;
+    // Count the number of arguments
+    while (argv[argc] != NULL)
+        argc++;
+
+    // Enumerate the arguments
+    size_t first_launch_arg_idx = 1;
+    CFReleaser<CFMutableArrayRef> launch_argv;
+
+    if (argv[first_launch_arg_idx])
+    {
+        size_t launch_argc = argc > 0 ? argc - 1 : 0;
+        launch_argv.reset (::CFArrayCreateMutable (alloc, launch_argc, &kCFTypeArrayCallBacks));
+        size_t i;
+        char const *arg;
+        CFString launch_arg;
+        for (i=first_launch_arg_idx; (i < argc) && ((arg = argv[i]) != NULL); i++)
+        {
+            launch_arg.reset(::CFStringCreateWithCString (alloc, arg, kCFStringEncodingUTF8));
+            if (launch_arg.get() != NULL)
+                CFArrayAppendValue(launch_argv.get(), launch_arg.get());
+            else
+                break;
+        }
+    }
+
+    // Next fill in the arguments dictionary.  Note, the envp array is of the form
+    // Variable=value but SpringBoard wants a CF dictionary.  So we have to convert
+    // this here.
+
+    CFReleaser<CFMutableDictionaryRef> launch_envp;
+
+    if (envp[0])
+    {
+        launch_envp.reset(::CFDictionaryCreateMutable(alloc, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+        const char *value;
+        int name_len;
+        CFString name_string, value_string;
+
+        for (int i = 0; envp[i] != NULL; i++)
+        {
+            value = strstr (envp[i], "=");
+
+            // If the name field is empty or there's no =, skip it.  Somebody's messing with us.
+            if (value == NULL || value == envp[i])
+                continue;
+
+            name_len = value - envp[i];
+
+            // Now move value over the "="
+            value++;
+
+            name_string.reset(::CFStringCreateWithBytes(alloc, (const UInt8 *) envp[i], name_len, kCFStringEncodingUTF8, false));
+            value_string.reset(::CFStringCreateWithCString(alloc, value, kCFStringEncodingUTF8));
+            CFDictionarySetValue (launch_envp.get(), name_string.get(), value_string.get());
+        }
+    }
+
+    CFString stdout_cf_path;
+    CFString stderr_cf_path;
+    PseudoTerminal pty;
+
+    if (stdin_path || stdout_path || stderr_path)
+    {
+        process->SetSTDIOIsOurs(false);
+        if (stdout_path)
+            stdout_cf_path.SetFileSystemRepresentation (stdout_path);
+        if (stderr_path)
+            stderr_cf_path.SetFileSystemRepresentation (stderr_path);
+    }
+    else
+    {
+        process->SetSTDIOIsOurs(true);
+        PseudoTerminal::Error pty_err = pty.OpenFirstAvailableMaster(O_RDWR);
+        if (pty_err == PseudoTerminal::success)
+        {
+            const char* slave_name = pty.SlaveName();
+            ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "%s() successfully opened master pty, slave is %s", __FUNCTION__, slave_name);
+            if (slave_name && slave_name[0])
+            {
+                ::chmod (slave_name, S_IRWXU | S_IRWXG | S_IRWXO);
+                stdout_cf_path.SetFileSystemRepresentation (slave_name);
+                stderr_cf_path.(stdout_cf_path);
+            }
+        }
+    }
+
+    if (stdout_cf_path.get() == NULL)
+        stdout_cf_path.SetFileSystemRepresentation ("/dev/null");
+    if (stderr_cf_path.get() == NULL)
+        stderr_cf_path.SetFileSystemRepresentation ("/dev/null");
+
+    CFBundle bundle(app_bundle_path);
+    CFStringRef bundleIDCFStr = bundle.GetIdentifier();
+    std::string bundleID;
+    if (CFString::UTF8(bundleIDCFStr, bundleID) == NULL)
+    {
+        struct stat app_bundle_stat;
+        if (::stat (app_bundle_path, &app_bundle_stat) < 0)
+        {
+            launch_err.SetError(errno, Error::POSIX);
+            launch_err.SetErrorStringWithFormat ("%s: \"%s\".\n", launch_err.AsString(), app_bundle_path);
+        }
+        else
+        {
+            launch_err.SetError(-1, Error::Generic);
+            launch_err.SetErrorStringWithFormat ("Failed to extract CFBundleIdentifier from %s.\n", app_bundle_path);
+        }
+        return LLDB_INVALID_PROCESS_ID;
+    }
+    ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "%s() extracted CFBundleIdentifier: %s", __FUNCTION__, bundleID.c_str());
+
+
+    CFData argv_data(NULL);
+
+    if (launch_argv.get())
+    {
+        if (argv_data.Serialize(launch_argv.get(), kCFPropertyListBinaryFormat_v1_0) == NULL)
+        {
+            ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "%s() error: failed to serialize launch arg array...", __FUNCTION__);
+            return LLDB_INVALID_PROCESS_ID;
+        }
+    }
+
+    ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "%s() serialized launch arg array", __FUNCTION__);
+
+    // Find SpringBoard
+    SBSApplicationLaunchError sbs_error = 0;
+    sbs_error = SBSLaunchApplication (  bundleIDCFStr,
+                                        (CFURLRef)NULL,         // openURL
+                                        launch_argv.get(),
+                                        launch_envp.get(),      // CFDictionaryRef environment
+                                        stdout_cf_path.get(),
+                                        stderr_cf_path.get(),
+                                        SBSApplicationLaunchWaitForDebugger | SBSApplicationLaunchUnlockDevice);
+
+
+    launch_err.SetError(sbs_error, Error::SpringBoard);
+
+    if (sbs_error == SBSApplicationLaunchErrorSuccess)
+    {
+        static const useconds_t pid_poll_interval = 200000;
+        static const useconds_t pid_poll_timeout = 30000000;
+
+        useconds_t pid_poll_total = 0;
+
+        lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+        Boolean pid_found = SBSProcessIDForDisplayIdentifier(bundleIDCFStr, &pid);
+        // Poll until the process is running, as long as we are getting valid responses and the timeout hasn't expired
+        // A return PID of 0 means the process is not running, which may be because it hasn't been (asynchronously) started
+        // yet, or that it died very quickly (if you weren't using waitForDebugger).
+        while (!pid_found && pid_poll_total < pid_poll_timeout)
+        {
+            usleep (pid_poll_interval);
+            pid_poll_total += pid_poll_interval;
+            ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "%s() polling Springboard for pid for %s...", __FUNCTION__, bundleID.c_str());
+            pid_found = SBSProcessIDForDisplayIdentifier(bundleIDCFStr, &pid);
+        }
+
+        if (pid_found)
+        {
+            // If we have a valid process and we created the STDIO file handles,
+            // then remember them on our process class so we can spawn a STDIO
+            // thread and close them when we are done with them.
+            if (process != NULL && process->STDIOIsOurs())
+            {
+                // Release our master pty file descriptor so the pty class doesn't
+                // close it and so we can continue to use it in our STDIO thread
+                int master_fd = pty.ReleaseMasterFD();
+                process->SetChildFileDescriptors(master_fd, master_fd, master_fd);
+            }
+            ProcessMacOSXLog::LogIf (PD_LOG_PROCESS, "%s() => pid = %4.4x", __FUNCTION__, pid);
+        }
+        else
+        {
+            LogError("failed to lookup the process ID for CFBundleIdentifier %s.", bundleID.c_str());
+        }
+        return pid;
+    }
+
+    LogError("unable to launch the application with CFBundleIdentifier '%s' sbs_error = %u", bundleID.c_str(), sbs_error);
+    return LLDB_INVALID_PROCESS_ID;
+}
+
+#endif // #if defined (__arm__)
+
diff --git a/source/Plugins/Process/MacOSX-User/source/ProcessMacOSXRemote.h b/source/Plugins/Process/MacOSX-User/source/ProcessMacOSXRemote.h
new file mode 100644
index 0000000..01905c6
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/ProcessMacOSXRemote.h
@@ -0,0 +1,206 @@
+//===-- ProcessMacOSXRemote.h -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//----------------------------------------------------------------------
+//
+//  ProcessMacOSXRemote.h
+//  liblldb
+//
+//  Created by Greg Clayton on 4/21/09.
+//
+//
+//----------------------------------------------------------------------
+
+#ifndef liblldb_ProcessMacOSXRemote_H_
+#define liblldb_ProcessMacOSXRemote_H_
+
+// C Includes
+
+// C++ Includes
+#include <list>
+
+// Other libraries and framework includes
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+
+class ThreadMacOSXRemote;
+
+class ProcessMacOSXRemote :
+    public Process
+{
+public:
+    friend class ThreadMacOSX;
+
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    ProcessMacOSXRemote(Target& target);
+    virtual ~DCProcessMacOSXRemote();
+
+    static Process* CreateInstance (Target& target);
+
+    //------------------------------------------------------------------
+    // Check if a given Process
+    //------------------------------------------------------------------
+    virtual bool        CanDebug(Target &target);
+
+    //------------------------------------------------------------------
+    // Creating a new process, or attaching to an existing one
+    //------------------------------------------------------------------
+    virtual lldb::pid_t DoLaunch (Module* module,
+                                char const *argv[],         // Can be NULL
+                                char const *envp[],         // Can be NULL
+                                const char *stdin_path,     // Can be NULL
+                                const char *stdout_path,    // Can be NULL
+                                const char *stderr_path);   // Can be NULL
+    virtual void        DidLaunch ();
+    virtual lldb::pid_t DoAttach (lldb::pid_t pid);
+    virtual void        DidAttach ();
+
+    //------------------------------------------------------------------
+    // Process Control
+    //------------------------------------------------------------------
+//  virtual bool        WillResume ();
+    virtual bool        DoResume ();
+//  virtual void        DidResume ();
+
+    virtual bool        DoHalt ();
+    virtual bool        WillDetach ();
+    virtual bool        DoDetach ();
+    virtual bool        DoKill (int signal);
+
+    virtual bool        ShouldStop ();
+
+    //------------------------------------------------------------------
+    // Process Queries
+    //------------------------------------------------------------------
+    virtual bool        IsAlive ();
+    virtual bool        IsRunning ();
+    virtual lldb::addr_t    GetImageInfoAddress();
+
+    //------------------------------------------------------------------
+    // Process Memory
+    //------------------------------------------------------------------
+    virtual size_t      DoReadMemory (lldb::addr_t addr, void *buf, size_t size);
+    virtual size_t      DoWriteMemory (lldb::addr_t addr, const void *buf, size_t size);
+
+    //------------------------------------------------------------------
+    // Process STDIO
+    //------------------------------------------------------------------
+    virtual size_t      GetSTDOUT (char *buf, size_t buf_size);
+    virtual size_t      GetSTDERR (char *buf, size_t buf_size);
+
+    //----------------------------------------------------------------------
+    // Process Breakpoints
+    //----------------------------------------------------------------------
+    virtual size_t
+    GetSoftwareBreakpointTrapOpcode (lldb::BreakpointSite *bp_site);
+
+    //----------------------------------------------------------------------
+    // Process Breakpoints
+    //----------------------------------------------------------------------
+    virtual bool
+    EnableBreakpoint (lldb::BreakpointSite *bp_site);
+
+    virtual bool
+    DisableBreakpoint (lldb::BreakpointSite *bp_site);
+
+    //----------------------------------------------------------------------
+    // Process Watchpoints
+    //----------------------------------------------------------------------
+    virtual bool        EnableWatchpoint (WatchpointLocation *wp_loc);
+    virtual bool        DisableWatchpoint (WatchpointLocation *wp_loc);
+
+    //------------------------------------------------------------------
+    // Thread Queries
+    //------------------------------------------------------------------
+    virtual Thread *    GetCurrentThread ();
+    virtual bool        SetCurrentThread (lldb::tid_t tid);
+    virtual Thread *    GetThreadAtIndex (uint32_t idx);
+    virtual Thread *    GetThreadByID (lldb::tid_t tid);
+    virtual size_t      GetNumThreads ();
+
+    virtual ByteOrder   GetByteOrder () const;
+
+    virtual DynamicLoader *
+    GetDynamicLoader ();
+
+protected:
+    Flags m_flags; // Process specific flags (see eFlags enums)
+    ArchSpec m_arch_spec;
+    std::auto_ptr<DynamicLoader> m_dynamic_loader_ap;
+    ByteOrder m_byte_order;
+
+    //----------------------------------------------------------------------
+    // Accessors
+    //----------------------------------------------------------------------
+    bool
+    ProcessIDIsValid ( ) const;
+
+    bool
+    IsRunning ( State state )
+    {
+        return state == eStateRunning || IsStepping(state);
+    }
+
+    bool
+    IsStepping ( State state)
+    {
+        return state == eStateStepping;
+    }
+    bool
+    CanResume ( State state)
+    {
+        return state == eStateStopped;
+    }
+
+    ArchSpec&
+    GetArchSpec()
+    {
+        return m_arch_spec;
+    }
+    const ArchSpec&
+    GetArchSpec() const
+    {
+        return m_arch_spec;
+    }
+
+    enum
+    {
+        eFlagsNone = 0,
+        eFlagsAttached = (1 << 0),
+        eFlagsUsingSBS = (1 << 1)
+    };
+
+    void
+    Clear ( );
+
+    Flags &
+    GetFlags ()
+    {
+        return m_flags;
+    }
+
+    const Flags &
+    GetFlags () const
+    {
+        return m_flags;
+    }
+
+    uint32_t
+    UpdateThreadListIfNeeded ();
+
+private:
+    //------------------------------------------------------------------
+    // For ProcessMacOSXRemote only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (ProcessMacOSXRemote);
+
+};
+
+#endif  // liblldb_ProcessMacOSXRemote_H_
diff --git a/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_arm.cpp b/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_arm.cpp
new file mode 100644
index 0000000..3747254
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_arm.cpp
@@ -0,0 +1,1448 @@
+//===-- RegisterContextMach_arm.cpp -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegisterContextMach_arm.h"
+
+// C Includes
+#include <mach/thread_act.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Scalar.h"
+
+// Project includes
+#include "ARM_GCC_Registers.h"
+#include "ARM_DWARF_Registers.h"
+#include "ProcessMacOSXLog.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+enum
+{
+    gpr_r0 = 0,
+    gpr_r1,
+    gpr_r2,
+    gpr_r3,
+    gpr_r4,
+    gpr_r5,
+    gpr_r6,
+    gpr_r7,
+    gpr_r8,
+    gpr_r9,
+    gpr_r10,
+    gpr_r11,
+    gpr_r12,
+    gpr_r13, gpr_sp = gpr_r13,
+    gpr_r14, gpr_lr = gpr_r14,
+    gpr_r15, gpr_pc = gpr_r15,
+    gpr_cpsr,
+
+    fpu_s0,
+    fpu_s1,
+    fpu_s2,
+    fpu_s3,
+    fpu_s4,
+    fpu_s5,
+    fpu_s6,
+    fpu_s7,
+    fpu_s8,
+    fpu_s9,
+    fpu_s10,
+    fpu_s11,
+    fpu_s12,
+    fpu_s13,
+    fpu_s14,
+    fpu_s15,
+    fpu_s16,
+    fpu_s17,
+    fpu_s18,
+    fpu_s19,
+    fpu_s20,
+    fpu_s21,
+    fpu_s22,
+    fpu_s23,
+    fpu_s24,
+    fpu_s25,
+    fpu_s26,
+    fpu_s27,
+    fpu_s28,
+    fpu_s29,
+    fpu_s30,
+    fpu_s31,
+    fpu_fpscr,
+
+    exc_exception,
+    exc_fsr,
+    exc_far,
+
+    dbg_bvr0,
+    dbg_bvr1,
+    dbg_bvr2,
+    dbg_bvr3,
+    dbg_bvr4,
+    dbg_bvr5,
+    dbg_bvr6,
+    dbg_bvr7,
+    dbg_bvr8,
+    dbg_bvr9,
+    dbg_bvr10,
+    dbg_bvr11,
+    dbg_bvr12,
+    dbg_bvr13,
+    dbg_bvr14,
+    dbg_bvr15,
+
+    dbg_bcr0,
+    dbg_bcr1,
+    dbg_bcr2,
+    dbg_bcr3,
+    dbg_bcr4,
+    dbg_bcr5,
+    dbg_bcr6,
+    dbg_bcr7,
+    dbg_bcr8,
+    dbg_bcr9,
+    dbg_bcr10,
+    dbg_bcr11,
+    dbg_bcr12,
+    dbg_bcr13,
+    dbg_bcr14,
+    dbg_bcr15,
+
+    dbg_wvr0,
+    dbg_wvr1,
+    dbg_wvr2,
+    dbg_wvr3,
+    dbg_wvr4,
+    dbg_wvr5,
+    dbg_wvr6,
+    dbg_wvr7,
+    dbg_wvr8,
+    dbg_wvr9,
+    dbg_wvr10,
+    dbg_wvr11,
+    dbg_wvr12,
+    dbg_wvr13,
+    dbg_wvr14,
+    dbg_wvr15,
+
+    dbg_wcr0,
+    dbg_wcr1,
+    dbg_wcr2,
+    dbg_wcr3,
+    dbg_wcr4,
+    dbg_wcr5,
+    dbg_wcr6,
+    dbg_wcr7,
+    dbg_wcr8,
+    dbg_wcr9,
+    dbg_wcr10,
+    dbg_wcr11,
+    dbg_wcr12,
+    dbg_wcr13,
+    dbg_wcr14,
+    dbg_wcr15,
+
+    k_num_registers
+};
+
+
+RegisterContextMach_arm::RegisterContextMach_arm(Thread &thread, StackFrame *frame) :
+    RegisterContext(thread, frame),
+    gpr(),
+    fpu(),
+    exc()
+{
+    uint32_t i;
+    for (i=0; i<kNumErrors; i++)
+    {
+        gpr_errs[i] = -1;
+        fpu_errs[i] = -1;
+        exc_errs[i] = -1;
+    }
+}
+
+RegisterContextMach_arm::~RegisterContextMach_arm()
+{
+}
+
+
+#define GPR_OFFSET(idx) ((idx) * 4)
+#define FPU_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextMach_arm::GPR))
+#define EXC_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextMach_arm::GPR) + sizeof (RegisterContextMach_arm::FPU))
+#define DBG_OFFSET(reg) (offsetof (RegisterContextMach_arm::DBG, reg) + sizeof (RegisterContextMach_arm::GPR) + sizeof (RegisterContextMach_arm::FPU) + sizeof (RegisterContextMach_arm::EXC))
+
+#define DEFINE_DBG(reg, i)  #reg, NULL, sizeof(((RegisterContextMach_arm::DBG *)NULL)->reg[i]), DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, dbg_##reg##i, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }
+#define REG_CONTEXT_SIZE (sizeof (RegisterContextMach_arm::GPR) + sizeof (RegisterContextMach_arm::FPU) + sizeof (RegisterContextMach_arm::EXC))
+// General purpose registers
+static lldb::RegisterInfo
+g_register_infos[] =
+{
+//  NAME        ALT     SZ  OFFSET              ENCODING        FORMAT          NATIVE      COMPILER            DWARF               GENERIC
+//  ======      ======= ==  =============       =============   ============    ==========  ===============     ===============     =========
+{   "r0",       NULL,   4,  GPR_OFFSET(0),      eEncodingUint,  eFormatHex,     gpr_r0,     { gcc_r0,               dwarf_r0,           LLDB_INVALID_REGNUM     }},
+{   "r1",       NULL,   4,  GPR_OFFSET(1),      eEncodingUint,  eFormatHex,     gpr_r1,     { gcc_r1,               dwarf_r1,           LLDB_INVALID_REGNUM     }},
+{   "r2",       NULL,   4,  GPR_OFFSET(2),      eEncodingUint,  eFormatHex,     gpr_r2,     { gcc_r2,               dwarf_r2,           LLDB_INVALID_REGNUM     }},
+{   "r3",       NULL,   4,  GPR_OFFSET(3),      eEncodingUint,  eFormatHex,     gpr_r3,     { gcc_r3,               dwarf_r3,           LLDB_INVALID_REGNUM     }},
+{   "r4",       NULL,   4,  GPR_OFFSET(4),      eEncodingUint,  eFormatHex,     gpr_r4,     { gcc_r4,               dwarf_r4,           LLDB_INVALID_REGNUM     }},
+{   "r5",       NULL,   4,  GPR_OFFSET(5),      eEncodingUint,  eFormatHex,     gpr_r5,     { gcc_r5,               dwarf_r5,           LLDB_INVALID_REGNUM     }},
+{   "r6",       NULL,   4,  GPR_OFFSET(6),      eEncodingUint,  eFormatHex,     gpr_r6,     { gcc_r6,               dwarf_r6,           LLDB_INVALID_REGNUM     }},
+{   "r7",       NULL,   4,  GPR_OFFSET(7),      eEncodingUint,  eFormatHex,     gpr_r7,     { gcc_r7,               dwarf_r7,           LLDB_REGNUM_GENERIC_FP  }},
+{   "r8",       NULL,   4,  GPR_OFFSET(8),      eEncodingUint,  eFormatHex,     gpr_r8,     { gcc_r8,               dwarf_r8,           LLDB_INVALID_REGNUM     }},
+{   "r9",       NULL,   4,  GPR_OFFSET(9),      eEncodingUint,  eFormatHex,     gpr_r9,     { gcc_r9,               dwarf_r9,           LLDB_INVALID_REGNUM     }},
+{   "r10",      NULL,   4,  GPR_OFFSET(10),     eEncodingUint,  eFormatHex,     gpr_r10,    { gcc_r10,          dwarf_r10,          LLDB_INVALID_REGNUM     }},
+{   "r11",      NULL,   4,  GPR_OFFSET(11),     eEncodingUint,  eFormatHex,     gpr_r11,    { gcc_r11,          dwarf_r11,          LLDB_INVALID_REGNUM     }},
+{   "r12",      NULL,   4,  GPR_OFFSET(12),     eEncodingUint,  eFormatHex,     gpr_r12,    { gcc_r12,          dwarf_r12,          LLDB_INVALID_REGNUM     }},
+{   "sp",       "r13",  4,  GPR_OFFSET(13),     eEncodingUint,  eFormatHex,     gpr_sp,     { gcc_sp,               dwarf_sp,           LLDB_REGNUM_GENERIC_SP  }},
+{   "lr",       "r14",  4,  GPR_OFFSET(14),     eEncodingUint,  eFormatHex,     gpr_lr,     { gcc_lr,               dwarf_lr,           LLDB_REGNUM_GENERIC_RA  }},
+{   "pc",       "r15",  4,  GPR_OFFSET(15),     eEncodingUint,  eFormatHex,     gpr_pc,     { gcc_pc,               dwarf_pc,           LLDB_REGNUM_GENERIC_PC  }},
+{   "cpsr",     "psr",  4,  GPR_OFFSET(16),     eEncodingUint,  eFormatHex,     gpr_cpsr,   { gcc_cpsr,         dwarf_cpsr,         LLDB_REGNUM_GENERIC_FLAGS   }},
+
+{   "s0",       NULL,   4,  FPU_OFFSET(0),      eEncodingIEEE754,eFormatFloat,  fpu_s0,     { LLDB_INVALID_REGNUM,  dwarf_s0,           LLDB_INVALID_REGNUM     }},
+{   "s1",       NULL,   4,  FPU_OFFSET(1),      eEncodingIEEE754,eFormatFloat,  fpu_s1,     { LLDB_INVALID_REGNUM,  dwarf_s1,           LLDB_INVALID_REGNUM     }},
+{   "s2",       NULL,   4,  FPU_OFFSET(2),      eEncodingIEEE754,eFormatFloat,  fpu_s2,     { LLDB_INVALID_REGNUM,  dwarf_s2,           LLDB_INVALID_REGNUM     }},
+{   "s3",       NULL,   4,  FPU_OFFSET(3),      eEncodingIEEE754,eFormatFloat,  fpu_s3,     { LLDB_INVALID_REGNUM,  dwarf_s3,           LLDB_INVALID_REGNUM     }},
+{   "s4",       NULL,   4,  FPU_OFFSET(4),      eEncodingIEEE754,eFormatFloat,  fpu_s4,     { LLDB_INVALID_REGNUM,  dwarf_s4,           LLDB_INVALID_REGNUM     }},
+{   "s5",       NULL,   4,  FPU_OFFSET(5),      eEncodingIEEE754,eFormatFloat,  fpu_s5,     { LLDB_INVALID_REGNUM,  dwarf_s5,           LLDB_INVALID_REGNUM     }},
+{   "s6",       NULL,   4,  FPU_OFFSET(6),      eEncodingIEEE754,eFormatFloat,  fpu_s6,     { LLDB_INVALID_REGNUM,  dwarf_s6,           LLDB_INVALID_REGNUM     }},
+{   "s7",       NULL,   4,  FPU_OFFSET(7),      eEncodingIEEE754,eFormatFloat,  fpu_s7,     { LLDB_INVALID_REGNUM,  dwarf_s7,           LLDB_INVALID_REGNUM     }},
+{   "s8",       NULL,   4,  FPU_OFFSET(8),      eEncodingIEEE754,eFormatFloat,  fpu_s8,     { LLDB_INVALID_REGNUM,  dwarf_s8,           LLDB_INVALID_REGNUM     }},
+{   "s9",       NULL,   4,  FPU_OFFSET(9),      eEncodingIEEE754,eFormatFloat,  fpu_s9,     { LLDB_INVALID_REGNUM,  dwarf_s9,           LLDB_INVALID_REGNUM     }},
+{   "s10",      NULL,   4,  FPU_OFFSET(10),     eEncodingIEEE754,eFormatFloat,  fpu_s10,    { LLDB_INVALID_REGNUM,  dwarf_s10,          LLDB_INVALID_REGNUM     }},
+{   "s11",      NULL,   4,  FPU_OFFSET(11),     eEncodingIEEE754,eFormatFloat,  fpu_s11,    { LLDB_INVALID_REGNUM,  dwarf_s11,          LLDB_INVALID_REGNUM     }},
+{   "s12",      NULL,   4,  FPU_OFFSET(12),     eEncodingIEEE754,eFormatFloat,  fpu_s12,    { LLDB_INVALID_REGNUM,  dwarf_s12,          LLDB_INVALID_REGNUM     }},
+{   "s13",      NULL,   4,  FPU_OFFSET(13),     eEncodingIEEE754,eFormatFloat,  fpu_s13,    { LLDB_INVALID_REGNUM,  dwarf_s13,          LLDB_INVALID_REGNUM     }},
+{   "s14",      NULL,   4,  FPU_OFFSET(14),     eEncodingIEEE754,eFormatFloat,  fpu_s14,    { LLDB_INVALID_REGNUM,  dwarf_s14,          LLDB_INVALID_REGNUM     }},
+{   "s15",      NULL,   4,  FPU_OFFSET(15),     eEncodingIEEE754,eFormatFloat,  fpu_s15,    { LLDB_INVALID_REGNUM,  dwarf_s15,          LLDB_INVALID_REGNUM     }},
+{   "s16",      NULL,   4,  FPU_OFFSET(16),     eEncodingIEEE754,eFormatFloat,  fpu_s16,    { LLDB_INVALID_REGNUM,  dwarf_s16,          LLDB_INVALID_REGNUM     }},
+{   "s17",      NULL,   4,  FPU_OFFSET(17),     eEncodingIEEE754,eFormatFloat,  fpu_s17,    { LLDB_INVALID_REGNUM,  dwarf_s17,          LLDB_INVALID_REGNUM     }},
+{   "s18",      NULL,   4,  FPU_OFFSET(18),     eEncodingIEEE754,eFormatFloat,  fpu_s18,    { LLDB_INVALID_REGNUM,  dwarf_s18,          LLDB_INVALID_REGNUM     }},
+{   "s19",      NULL,   4,  FPU_OFFSET(19),     eEncodingIEEE754,eFormatFloat,  fpu_s19,    { LLDB_INVALID_REGNUM,  dwarf_s19,          LLDB_INVALID_REGNUM     }},
+{   "s20",      NULL,   4,  FPU_OFFSET(20),     eEncodingIEEE754,eFormatFloat,  fpu_s20,    { LLDB_INVALID_REGNUM,  dwarf_s20,          LLDB_INVALID_REGNUM     }},
+{   "s21",      NULL,   4,  FPU_OFFSET(21),     eEncodingIEEE754,eFormatFloat,  fpu_s21,    { LLDB_INVALID_REGNUM,  dwarf_s21,          LLDB_INVALID_REGNUM     }},
+{   "s22",      NULL,   4,  FPU_OFFSET(22),     eEncodingIEEE754,eFormatFloat,  fpu_s22,    { LLDB_INVALID_REGNUM,  dwarf_s22,          LLDB_INVALID_REGNUM     }},
+{   "s23",      NULL,   4,  FPU_OFFSET(23),     eEncodingIEEE754,eFormatFloat,  fpu_s23,    { LLDB_INVALID_REGNUM,  dwarf_s23,          LLDB_INVALID_REGNUM     }},
+{   "s24",      NULL,   4,  FPU_OFFSET(24),     eEncodingIEEE754,eFormatFloat,  fpu_s24,    { LLDB_INVALID_REGNUM,  dwarf_s24,          LLDB_INVALID_REGNUM     }},
+{   "s25",      NULL,   4,  FPU_OFFSET(25),     eEncodingIEEE754,eFormatFloat,  fpu_s25,    { LLDB_INVALID_REGNUM,  dwarf_s25,          LLDB_INVALID_REGNUM     }},
+{   "s26",      NULL,   4,  FPU_OFFSET(26),     eEncodingIEEE754,eFormatFloat,  fpu_s26,    { LLDB_INVALID_REGNUM,  dwarf_s26,          LLDB_INVALID_REGNUM     }},
+{   "s27",      NULL,   4,  FPU_OFFSET(27),     eEncodingIEEE754,eFormatFloat,  fpu_s27,    { LLDB_INVALID_REGNUM,  dwarf_s27,          LLDB_INVALID_REGNUM     }},
+{   "s28",      NULL,   4,  FPU_OFFSET(28),     eEncodingIEEE754,eFormatFloat,  fpu_s28,    { LLDB_INVALID_REGNUM,  dwarf_s28,          LLDB_INVALID_REGNUM     }},
+{   "s29",      NULL,   4,  FPU_OFFSET(29),     eEncodingIEEE754,eFormatFloat,  fpu_s29,    { LLDB_INVALID_REGNUM,  dwarf_s29,          LLDB_INVALID_REGNUM     }},
+{   "s30",      NULL,   4,  FPU_OFFSET(30),     eEncodingIEEE754,eFormatFloat,  fpu_s30,    { LLDB_INVALID_REGNUM,  dwarf_s30,          LLDB_INVALID_REGNUM     }},
+{   "s31",      NULL,   4,  FPU_OFFSET(31),     eEncodingIEEE754,eFormatFloat,  fpu_s31,    { LLDB_INVALID_REGNUM,  dwarf_s31,          LLDB_INVALID_REGNUM     }},
+{   "fpscr",    NULL,   4,  FPU_OFFSET(32),     eEncodingUint,  eFormatHex,     fpu_fpscr,  { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM     }},
+
+{   "exception",NULL,   4,  EXC_OFFSET(0),      eEncodingUint,  eFormatHex,     exc_exception,{ LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM     }},
+{   "fsr",      NULL,   4,  EXC_OFFSET(1),      eEncodingUint,  eFormatHex,     exc_fsr,    { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM     }},
+{   "far",      NULL,   4,  EXC_OFFSET(2),      eEncodingUint,  eFormatHex,     exc_far,    { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM     }},
+
+{   DEFINE_DBG (bvr, 0) },
+{   DEFINE_DBG (bvr, 0) },
+{   DEFINE_DBG (bvr, 1) },
+{   DEFINE_DBG (bvr, 2) },
+{   DEFINE_DBG (bvr, 3) },
+{   DEFINE_DBG (bvr, 4) },
+{   DEFINE_DBG (bvr, 5) },
+{   DEFINE_DBG (bvr, 6) },
+{   DEFINE_DBG (bvr, 7) },
+{   DEFINE_DBG (bvr, 8) },
+{   DEFINE_DBG (bvr, 9) },
+{   DEFINE_DBG (bvr, 10) },
+{   DEFINE_DBG (bvr, 11) },
+{   DEFINE_DBG (bvr, 12) },
+{   DEFINE_DBG (bvr, 13) },
+{   DEFINE_DBG (bvr, 14) },
+{   DEFINE_DBG (bvr, 15) },
+
+{   DEFINE_DBG (bcr, 0) },
+{   DEFINE_DBG (bcr, 0) },
+{   DEFINE_DBG (bcr, 1) },
+{   DEFINE_DBG (bcr, 2) },
+{   DEFINE_DBG (bcr, 3) },
+{   DEFINE_DBG (bcr, 4) },
+{   DEFINE_DBG (bcr, 5) },
+{   DEFINE_DBG (bcr, 6) },
+{   DEFINE_DBG (bcr, 7) },
+{   DEFINE_DBG (bcr, 8) },
+{   DEFINE_DBG (bcr, 9) },
+{   DEFINE_DBG (bcr, 10) },
+{   DEFINE_DBG (bcr, 11) },
+{   DEFINE_DBG (bcr, 12) },
+{   DEFINE_DBG (bcr, 13) },
+{   DEFINE_DBG (bcr, 14) },
+{   DEFINE_DBG (bcr, 15) },
+
+{   DEFINE_DBG (wvr, 0) },
+{   DEFINE_DBG (wvr, 0) },
+{   DEFINE_DBG (wvr, 1) },
+{   DEFINE_DBG (wvr, 2) },
+{   DEFINE_DBG (wvr, 3) },
+{   DEFINE_DBG (wvr, 4) },
+{   DEFINE_DBG (wvr, 5) },
+{   DEFINE_DBG (wvr, 6) },
+{   DEFINE_DBG (wvr, 7) },
+{   DEFINE_DBG (wvr, 8) },
+{   DEFINE_DBG (wvr, 9) },
+{   DEFINE_DBG (wvr, 10) },
+{   DEFINE_DBG (wvr, 11) },
+{   DEFINE_DBG (wvr, 12) },
+{   DEFINE_DBG (wvr, 13) },
+{   DEFINE_DBG (wvr, 14) },
+{   DEFINE_DBG (wvr, 15) },
+
+{   DEFINE_DBG (wcr, 0) },
+{   DEFINE_DBG (wcr, 0) },
+{   DEFINE_DBG (wcr, 1) },
+{   DEFINE_DBG (wcr, 2) },
+{   DEFINE_DBG (wcr, 3) },
+{   DEFINE_DBG (wcr, 4) },
+{   DEFINE_DBG (wcr, 5) },
+{   DEFINE_DBG (wcr, 6) },
+{   DEFINE_DBG (wcr, 7) },
+{   DEFINE_DBG (wcr, 8) },
+{   DEFINE_DBG (wcr, 9) },
+{   DEFINE_DBG (wcr, 10) },
+{   DEFINE_DBG (wcr, 11) },
+{   DEFINE_DBG (wcr, 12) },
+{   DEFINE_DBG (wcr, 13) },
+{   DEFINE_DBG (wcr, 14) },
+{   DEFINE_DBG (wcr, 15) }
+};
+
+// General purpose registers
+static uint32_t
+g_gpr_regnums[] =
+{
+    gpr_r0,
+    gpr_r1,
+    gpr_r2,
+    gpr_r3,
+    gpr_r4,
+    gpr_r5,
+    gpr_r6,
+    gpr_r7,
+    gpr_r8,
+    gpr_r9,
+    gpr_r10,
+    gpr_r11,
+    gpr_r12,
+    gpr_sp,
+    gpr_lr,
+    gpr_pc,
+    gpr_cpsr
+};
+
+// Floating point registers
+static uint32_t
+g_fpu_regnums[] =
+{
+    fpu_s0,
+    fpu_s1,
+    fpu_s2,
+    fpu_s3,
+    fpu_s4,
+    fpu_s5,
+    fpu_s6,
+    fpu_s7,
+    fpu_s8,
+    fpu_s9,
+    fpu_s10,
+    fpu_s11,
+    fpu_s12,
+    fpu_s13,
+    fpu_s14,
+    fpu_s15,
+    fpu_s16,
+    fpu_s17,
+    fpu_s18,
+    fpu_s19,
+    fpu_s20,
+    fpu_s21,
+    fpu_s22,
+    fpu_s23,
+    fpu_s24,
+    fpu_s25,
+    fpu_s26,
+    fpu_s27,
+    fpu_s28,
+    fpu_s29,
+    fpu_s30,
+    fpu_s31,
+    fpu_fpscr,
+};
+
+// Exception registers
+
+static uint32_t
+g_exc_regnums[] =
+{
+    exc_exception,
+    exc_fsr,
+    exc_far,
+};
+
+static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo));
+
+void
+RegisterContextMach_arm::Invalidate ()
+{
+    InvalidateAllRegisterStates();
+}
+
+
+size_t
+RegisterContextMach_arm::GetRegisterCount ()
+{
+    assert(k_num_register_infos == k_num_registers);
+    return k_num_registers;
+}
+
+const RegisterInfo *
+RegisterContextMach_arm::GetRegisterInfoAtIndex (uint32_t reg)
+{
+    assert(k_num_register_infos == k_num_registers);
+    if (reg < k_num_registers)
+        return &g_register_infos[reg];
+    return NULL;
+}
+
+size_t
+RegisterContextMach_arm::GetRegisterInfosCount ()
+{
+    return k_num_register_infos;
+}
+
+const RegisterInfo *
+RegisterContextMach_arm::GetRegisterInfos ()
+{
+    return g_register_infos;
+}
+
+
+// Number of registers in each register set
+const size_t k_num_gpr_registers = sizeof(g_gpr_regnums) / sizeof(uint32_t);
+const size_t k_num_fpu_registers = sizeof(g_fpu_regnums) / sizeof(uint32_t);
+const size_t k_num_exc_registers = sizeof(g_exc_regnums) / sizeof(uint32_t);
+
+//----------------------------------------------------------------------
+// Register set definitions. The first definitions at register set index
+// of zero is for all registers, followed by other registers sets. The
+// register information for the all register set need not be filled in.
+//----------------------------------------------------------------------
+static const RegisterSet g_reg_sets[] =
+{
+    { "General Purpose Registers",  "gpr",  k_num_gpr_registers,    g_gpr_regnums,      },
+    { "Floating Point Registers",   "fpu",  k_num_fpu_registers,    g_fpu_regnums       },
+    { "Exception State Registers",  "exc",  k_num_exc_registers,    g_exc_regnums       }
+};
+
+const size_t k_num_regsets = sizeof(g_reg_sets) / sizeof(RegisterSet);
+
+
+size_t
+RegisterContextMach_arm::GetRegisterSetCount ()
+{
+    return k_num_regsets;
+}
+
+const RegisterSet *
+RegisterContextMach_arm::GetRegisterSet (uint32_t reg_set)
+{
+    if (reg_set < k_num_regsets)
+        return &g_reg_sets[reg_set];
+    return NULL;
+}
+
+
+//----------------------------------------------------------------------
+// Register information defintions for 32 bit i386.
+//----------------------------------------------------------------------
+int
+RegisterContextMach_arm::GetSetForNativeRegNum (int reg)
+{
+    if (reg < fpu_s0)
+        return GPRRegSet;
+    else if (reg < exc_exception)
+        return FPURegSet;
+    else if (reg < k_num_registers)
+        return EXCRegSet;
+    return -1;
+}
+
+kern_return_t
+RegisterContextMach_arm::ReadGPR (bool force)
+{
+    int set = GPRRegSet;
+    if (force || !RegisterSetIsCached(set))
+    {
+        mach_msg_type_number_t count = GPRWordCount;
+        SetError(GPRRegSet, Read, ::thread_get_state(GetThreadID(), set, (thread_state_t)&gpr, &count));
+    }
+    return GetError(GPRRegSet, Read);
+}
+
+kern_return_t
+RegisterContextMach_arm::ReadFPU (bool force)
+{
+    int set = FPURegSet;
+    if (force || !RegisterSetIsCached(set))
+    {
+        mach_msg_type_number_t count = FPUWordCount;
+        SetError(FPURegSet, Read, ::thread_get_state(GetThreadID(), set, (thread_state_t)&fpu, &count));
+    }
+    return GetError(FPURegSet, Read);
+}
+
+kern_return_t
+RegisterContextMach_arm::ReadEXC (bool force)
+{
+    int set = EXCRegSet;
+    if (force || !RegisterSetIsCached(set))
+    {
+        mach_msg_type_number_t count = EXCWordCount;
+        SetError(EXCRegSet, Read, ::thread_get_state(GetThreadID(), set, (thread_state_t)&exc, &count));
+    }
+    return GetError(EXCRegSet, Read);
+}
+
+kern_return_t
+RegisterContextMach_arm::ReadDBG (bool force)
+{
+    int set = DBGRegSet;
+    if (force || !RegisterSetIsCached(set))
+    {
+        mach_msg_type_number_t count = DBGWordCount;
+        SetError(DBGRegSet, Read, ::thread_get_state(GetThreadID(), set, (thread_state_t)&dbg, &count));
+    }
+    return GetError(DBGRegSet, Read);
+}
+
+kern_return_t
+RegisterContextMach_arm::WriteGPR ()
+{
+    int set = GPRRegSet;
+    if (!RegisterSetIsCached(set))
+    {
+        SetError (set, Write, -1);
+        return KERN_INVALID_ARGUMENT;
+    }
+    SetError(GPRRegSet, Write, ::thread_set_state(GetThreadID(), set, (thread_state_t)&gpr, GPRWordCount));
+    return GetError(GPRRegSet, Write);
+}
+
+kern_return_t
+RegisterContextMach_arm::WriteFPU ()
+{
+    int set = FPURegSet;
+    if (!RegisterSetIsCached(set))
+    {
+        SetError (set, Write, -1);
+        return KERN_INVALID_ARGUMENT;
+    }
+    SetError(FPURegSet, Write, ::thread_set_state(GetThreadID(), set, (thread_state_t)&fpu, FPUWordCount));
+    return GetError(FPURegSet, Write);
+}
+
+kern_return_t
+RegisterContextMach_arm::WriteEXC ()
+{
+    int set = EXCRegSet;
+    if (!RegisterSetIsCached(set))
+    {
+        SetError (set, Write, -1);
+        return KERN_INVALID_ARGUMENT;
+    }
+    SetError(EXCRegSet, Write, ::thread_set_state(GetThreadID(), set, (thread_state_t)&exc, EXCWordCount));
+    return GetError(EXCRegSet, Write);
+}
+
+kern_return_t
+RegisterContextMach_arm::WriteDBG ()
+{
+    int set = DBGRegSet;
+    if (!RegisterSetIsCached(set))
+    {
+        SetError (set, Write, -1);
+        return KERN_INVALID_ARGUMENT;
+    }
+    SetError(DBGRegSet, Write, ::thread_set_state(GetThreadID(), set, (thread_state_t)&dbg, DBGWordCount));
+    return GetError(DBGRegSet, Write);
+}
+
+
+kern_return_t
+RegisterContextMach_arm::ReadRegisterSet (uint32_t set, bool force)
+{
+    switch (set)
+    {
+    case GPRRegSet:    return ReadGPR(force);
+    case FPURegSet:    return ReadFPU(force);
+    case EXCRegSet:    return ReadEXC(force);
+    case DBGRegSet:    return ReadDBG(force);
+    default: break;
+    }
+    return KERN_INVALID_ARGUMENT;
+}
+
+kern_return_t
+RegisterContextMach_arm::WriteRegisterSet (uint32_t set)
+{
+    // Make sure we have a valid context to set.
+    if (RegisterSetIsCached(set))
+    {
+        switch (set)
+        {
+        case GPRRegSet:    return WriteGPR();
+        case FPURegSet:    return WriteFPU();
+        case EXCRegSet:    return WriteEXC();
+        case DBGRegSet:    return WriteDBG();
+        default: break;
+        }
+    }
+    return KERN_INVALID_ARGUMENT;
+}
+
+void
+RegisterContextMach_arm::LogDBGRegisters (Log *log, const DBG& dbg)
+{
+    if (log)
+    {
+        for (uint32_t i=0; i<16; i++)
+            log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { 0x%8.8x, 0x%8.8x }",
+                i, i, dbg.bvr[i], dbg.bcr[i],
+                i, i, dbg.wvr[i], dbg.wcr[i]);
+    }
+}
+
+
+bool
+RegisterContextMach_arm::ReadRegisterValue (uint32_t reg, Scalar &value)
+{
+    int set = RegisterContextMach_arm::GetSetForNativeRegNum (reg);
+
+    if (set == -1)
+        return false;
+
+    if (ReadRegisterSet(set, false) != KERN_SUCCESS)
+        return false;
+
+    switch (reg)
+    {
+    case gpr_r0:
+    case gpr_r1:
+    case gpr_r2:
+    case gpr_r3:
+    case gpr_r4:
+    case gpr_r5:
+    case gpr_r6:
+    case gpr_r7:
+    case gpr_r8:
+    case gpr_r9:
+    case gpr_r10:
+    case gpr_r11:
+    case gpr_r12:
+    case gpr_sp:
+    case gpr_lr:
+    case gpr_pc:
+    case gpr_cpsr:
+        value = gpr.r[reg - gpr_r0];
+        break;
+
+    case fpu_s0:
+    case fpu_s1:
+    case fpu_s2:
+    case fpu_s3:
+    case fpu_s4:
+    case fpu_s5:
+    case fpu_s6:
+    case fpu_s7:
+    case fpu_s8:
+    case fpu_s9:
+    case fpu_s10:
+    case fpu_s11:
+    case fpu_s12:
+    case fpu_s13:
+    case fpu_s14:
+    case fpu_s15:
+    case fpu_s16:
+    case fpu_s17:
+    case fpu_s18:
+    case fpu_s19:
+    case fpu_s20:
+    case fpu_s21:
+    case fpu_s22:
+    case fpu_s23:
+    case fpu_s24:
+    case fpu_s25:
+    case fpu_s26:
+    case fpu_s27:
+    case fpu_s28:
+    case fpu_s29:
+    case fpu_s30:
+    case fpu_s31:
+        value = fpu.floats.s[reg];
+        break;
+
+    case fpu_fpscr:
+        value = fpu.fpscr;
+        break;
+
+    case exc_exception:
+        value = exc.exception;
+        break;
+    case exc_fsr:
+        value = exc.fsr;
+        break;
+    case exc_far:
+        value = exc.far;
+        break;
+
+    default:
+        return false;
+
+    }
+    return true;
+}
+
+
+bool
+RegisterContextMach_arm::WriteRegisterValue (uint32_t reg, const Scalar &value)
+{
+    int set = GetSetForNativeRegNum (reg);
+
+    if (set == -1)
+        return false;
+
+    if (ReadRegisterSet(set, false) != KERN_SUCCESS)
+        return false;
+
+    switch (reg)
+    {
+    case gpr_r0:
+    case gpr_r1:
+    case gpr_r2:
+    case gpr_r3:
+    case gpr_r4:
+    case gpr_r5:
+    case gpr_r6:
+    case gpr_r7:
+    case gpr_r8:
+    case gpr_r9:
+    case gpr_r10:
+    case gpr_r11:
+    case gpr_r12:
+    case gpr_sp:
+    case gpr_lr:
+    case gpr_pc:
+    case gpr_cpsr:
+        gpr.r[reg - gpr_r0] = value.UInt(0);
+        break;
+
+    case fpu_s0:
+    case fpu_s1:
+    case fpu_s2:
+    case fpu_s3:
+    case fpu_s4:
+    case fpu_s5:
+    case fpu_s6:
+    case fpu_s7:
+    case fpu_s8:
+    case fpu_s9:
+    case fpu_s10:
+    case fpu_s11:
+    case fpu_s12:
+    case fpu_s13:
+    case fpu_s14:
+    case fpu_s15:
+    case fpu_s16:
+    case fpu_s17:
+    case fpu_s18:
+    case fpu_s19:
+    case fpu_s20:
+    case fpu_s21:
+    case fpu_s22:
+    case fpu_s23:
+    case fpu_s24:
+    case fpu_s25:
+    case fpu_s26:
+    case fpu_s27:
+    case fpu_s28:
+    case fpu_s29:
+    case fpu_s30:
+    case fpu_s31:
+        fpu.floats.s[reg] = value.UInt(0);
+        break;
+
+    case fpu_fpscr:
+        fpu.fpscr = value.UInt(0);
+        break;
+
+    case exc_exception:
+        exc.exception = value.UInt(0);
+        break;
+    case exc_fsr:
+        exc.fsr = value.UInt(0);
+        break;
+    case exc_far:
+        exc.far = value.UInt(0);
+        break;
+
+    default:
+        return false;
+
+    }
+    return WriteRegisterSet(set) == KERN_SUCCESS;
+}
+
+bool
+RegisterContextMach_arm::ReadRegisterBytes (uint32_t reg, DataExtractor &data)
+{
+    int set = RegisterContextMach_arm::GetSetForNativeRegNum (reg);
+    if (set == -1)
+        return false;
+
+    if (ReadRegisterSet(set, false) != KERN_SUCCESS)
+        return false;
+
+    const RegisterInfo * reg_info = GetRegisterInfoAtIndex (reg);
+    if (reg_info == NULL)
+        return false;
+
+    switch (reg)
+    {
+    case gpr_r0:
+    case gpr_r1:
+    case gpr_r2:
+    case gpr_r3:
+    case gpr_r4:
+    case gpr_r5:
+    case gpr_r6:
+    case gpr_r7:
+    case gpr_r8:
+    case gpr_r9:
+    case gpr_r10:
+    case gpr_r11:
+    case gpr_r12:
+    case gpr_sp:
+    case gpr_lr:
+    case gpr_pc:
+    case gpr_cpsr:
+        data.SetData(&gpr.r[reg - gpr_r0], reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_s0:
+    case fpu_s1:
+    case fpu_s2:
+    case fpu_s3:
+    case fpu_s4:
+    case fpu_s5:
+    case fpu_s6:
+    case fpu_s7:
+    case fpu_s8:
+    case fpu_s9:
+    case fpu_s10:
+    case fpu_s11:
+    case fpu_s12:
+    case fpu_s13:
+    case fpu_s14:
+    case fpu_s15:
+    case fpu_s16:
+    case fpu_s17:
+    case fpu_s18:
+    case fpu_s19:
+    case fpu_s20:
+    case fpu_s21:
+    case fpu_s22:
+    case fpu_s23:
+    case fpu_s24:
+    case fpu_s25:
+    case fpu_s26:
+    case fpu_s27:
+    case fpu_s28:
+    case fpu_s29:
+    case fpu_s30:
+    case fpu_s31:
+        data.SetData(&fpu.floats.s[reg - fpu_s0], reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_fpscr:
+        data.SetData(&fpu.fpscr, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case exc_exception:
+        data.SetData(&exc.exception, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case exc_fsr:
+        data.SetData(&exc.fsr, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case exc_far:
+        data.SetData(&exc.far, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    default:
+        return false;
+    }
+    return true;
+}
+
+bool
+RegisterContextMach_arm::WriteRegisterBytes (uint32_t reg, DataExtractor &data, uint32_t data_offset)
+{
+    int set = GetSetForNativeRegNum (reg);
+
+    if (set == -1)
+        return false;
+
+    if (ReadRegisterSet(set, false) != KERN_SUCCESS)
+        return false;
+
+
+    const RegisterInfo * reg_info = GetRegisterInfoAtIndex (reg);
+    if (reg_info == NULL && data.ValidOffsetForDataOfSize(data_offset, reg_info->byte_size))
+        return false;
+
+    uint32_t offset = data_offset;
+    switch (reg)
+    {
+    case gpr_r0:
+    case gpr_r1:
+    case gpr_r2:
+    case gpr_r3:
+    case gpr_r4:
+    case gpr_r5:
+    case gpr_r6:
+    case gpr_r7:
+    case gpr_r8:
+    case gpr_r9:
+    case gpr_r10:
+    case gpr_r11:
+    case gpr_r12:
+    case gpr_sp:
+    case gpr_lr:
+    case gpr_pc:
+    case gpr_cpsr:
+        gpr.r[reg - gpr_r0] = data.GetU32 (&offset);
+        break;
+
+    case fpu_s0:
+    case fpu_s1:
+    case fpu_s2:
+    case fpu_s3:
+    case fpu_s4:
+    case fpu_s5:
+    case fpu_s6:
+    case fpu_s7:
+    case fpu_s8:
+    case fpu_s9:
+    case fpu_s10:
+    case fpu_s11:
+    case fpu_s12:
+    case fpu_s13:
+    case fpu_s14:
+    case fpu_s15:
+    case fpu_s16:
+    case fpu_s17:
+    case fpu_s18:
+    case fpu_s19:
+    case fpu_s20:
+    case fpu_s21:
+    case fpu_s22:
+    case fpu_s23:
+    case fpu_s24:
+    case fpu_s25:
+    case fpu_s26:
+    case fpu_s27:
+    case fpu_s28:
+    case fpu_s29:
+    case fpu_s30:
+    case fpu_s31:
+        fpu.floats.s[reg - fpu_s0] = data.GetU32 (&offset);
+        break;
+
+    case fpu_fpscr:
+        fpu.fpscr = data.GetU32 (&offset);
+        break;
+
+    case exc_exception:
+        fpu.fpscr = data.GetU32 (&offset);
+        break;
+
+    case exc_fsr:
+        exc.fsr = data.GetU32 (&offset);
+        break;
+
+    case exc_far:
+        exc.far = data.GetU32 (&offset);
+        break;
+
+    default:
+        return false;
+    }
+    return WriteRegisterSet(set) == KERN_SUCCESS;
+}
+
+bool
+RegisterContextMach_arm::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
+{
+    data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
+    if (data_sp &&
+        ReadGPR (false) == KERN_SUCCESS &&
+        ReadFPU (false) == KERN_SUCCESS &&
+        ReadEXC (false) == KERN_SUCCESS)
+    {
+        uint8_t *dst = data_sp->GetBytes();
+        ::memcpy (dst, &gpr, sizeof(gpr));
+        dst += sizeof(gpr);
+
+        ::memcpy (dst, &fpu, sizeof(fpu));
+        dst += sizeof(gpr);
+
+        ::memcpy (dst, &exc, sizeof(exc));
+        return true;
+    }
+    return false;
+}
+
+bool
+RegisterContextMach_arm::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
+{
+    if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
+    {
+        const uint8_t *src = data_sp->GetBytes();
+        ::memcpy (&gpr, src, sizeof(gpr));
+        src += sizeof(gpr);
+
+        ::memcpy (&fpu, src, sizeof(fpu));
+        src += sizeof(gpr);
+
+        ::memcpy (&exc, src, sizeof(exc));
+        uint32_t success_count = 0;
+        if (WriteGPR() == KERN_SUCCESS)
+            ++success_count;
+        if (WriteFPU() == KERN_SUCCESS)
+            ++success_count;
+        if (WriteEXC() == KERN_SUCCESS)
+            ++success_count;
+        return success_count == 3;
+    }
+    return false;
+}
+
+uint32_t
+RegisterContextMach_arm::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t reg)
+{
+    if (kind == eRegisterKindGeneric)
+    {
+        switch (reg)
+        {
+        case LLDB_REGNUM_GENERIC_PC: return gpr_pc;
+        case LLDB_REGNUM_GENERIC_SP: return gpr_sp;
+        case LLDB_REGNUM_GENERIC_FP: return gpr_r7;
+        case LLDB_REGNUM_GENERIC_RA: return gpr_lr;
+        case LLDB_REGNUM_GENERIC_FLAGS: return gpr_cpsr;
+        default:
+            break;
+        }
+    }
+    else if (kind == eRegisterKindDWARF)
+    {
+        switch (reg)
+        {
+        case dwarf_r0:  return gpr_r0;
+        case dwarf_r1:  return gpr_r1;
+        case dwarf_r2:  return gpr_r2;
+        case dwarf_r3:  return gpr_r3;
+        case dwarf_r4:  return gpr_r4;
+        case dwarf_r5:  return gpr_r5;
+        case dwarf_r6:  return gpr_r6;
+        case dwarf_r7:  return gpr_r7;
+        case dwarf_r8:  return gpr_r8;
+        case dwarf_r9:  return gpr_r9;
+        case dwarf_r10: return gpr_r10;
+        case dwarf_r11: return gpr_r11;
+        case dwarf_r12: return gpr_r12;
+        case dwarf_sp:  return gpr_sp;
+        case dwarf_lr:  return gpr_lr;
+        case dwarf_pc:  return gpr_pc;
+        case dwarf_spsr: return gpr_cpsr;
+
+        case dwarf_s0:  return fpu_s0;
+        case dwarf_s1:  return fpu_s1;
+        case dwarf_s2:  return fpu_s2;
+        case dwarf_s3:  return fpu_s3;
+        case dwarf_s4:  return fpu_s4;
+        case dwarf_s5:  return fpu_s5;
+        case dwarf_s6:  return fpu_s6;
+        case dwarf_s7:  return fpu_s7;
+        case dwarf_s8:  return fpu_s8;
+        case dwarf_s9:  return fpu_s9;
+        case dwarf_s10: return fpu_s10;
+        case dwarf_s11: return fpu_s11;
+        case dwarf_s12: return fpu_s12;
+        case dwarf_s13: return fpu_s13;
+        case dwarf_s14: return fpu_s14;
+        case dwarf_s15: return fpu_s15;
+        case dwarf_s16: return fpu_s16;
+        case dwarf_s17: return fpu_s17;
+        case dwarf_s18: return fpu_s18;
+        case dwarf_s19: return fpu_s19;
+        case dwarf_s20: return fpu_s20;
+        case dwarf_s21: return fpu_s21;
+        case dwarf_s22: return fpu_s22;
+        case dwarf_s23: return fpu_s23;
+        case dwarf_s24: return fpu_s24;
+        case dwarf_s25: return fpu_s25;
+        case dwarf_s26: return fpu_s26;
+        case dwarf_s27: return fpu_s27;
+        case dwarf_s28: return fpu_s28;
+        case dwarf_s29: return fpu_s29;
+        case dwarf_s30: return fpu_s30;
+        case dwarf_s31: return fpu_s31;
+
+        default:
+            break;
+        }
+    }
+    else if (kind == eRegisterKindGCC)
+    {
+        switch (reg)
+        {
+        case gcc_r0:    return gpr_r0;
+        case gcc_r1:    return gpr_r1;
+        case gcc_r2:    return gpr_r2;
+        case gcc_r3:    return gpr_r3;
+        case gcc_r4:    return gpr_r4;
+        case gcc_r5:    return gpr_r5;
+        case gcc_r6:    return gpr_r6;
+        case gcc_r7:    return gpr_r7;
+        case gcc_r8:    return gpr_r8;
+        case gcc_r9:    return gpr_r9;
+        case gcc_r10:   return gpr_r10;
+        case gcc_r11:   return gpr_r11;
+        case gcc_r12:   return gpr_r12;
+        case gcc_sp:    return gpr_sp;
+        case gcc_lr:    return gpr_lr;
+        case gcc_pc:    return gpr_pc;
+        case gcc_cpsr:  return gpr_cpsr;
+        }
+    }
+    return LLDB_INVALID_REGNUM;
+}
+
+
+uint32_t
+RegisterContextMach_arm::NumSupportedHardwareBreakpoints ()
+{
+#if defined (__arm__)
+    // Set the init value to something that will let us know that we need to
+    // autodetect how many breakpoints are supported dynamically...
+    static uint32_t g_num_supported_hw_breakpoints = UINT_MAX
+    if (g_num_supported_hw_breakpoints == UINT_MAX)
+    {
+        // Set this to zero in case we can't tell if there are any HW breakpoints
+        g_num_supported_hw_breakpoints = 0;
+
+        // Read the DBGDIDR to get the number of available hardware breakpoints
+        // However, in some of our current armv7 processors, hardware
+        // breakpoints/watchpoints were not properly connected. So detect those
+        // cases using a field in a sysctl. For now we are using "hw.cpusubtype"
+        // field to distinguish CPU architectures. This is a hack until we can
+        // get <rdar://problem/6372672> fixed, at which point we will switch to
+        // using a different sysctl string that will tell us how many BRPs
+        // are available to us directly without having to read DBGDIDR.
+        uint32_t register_DBGDIDR;
+
+        asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR));
+        uint32_t numBRPs = bits(register_DBGDIDR, 27, 24);
+        // Zero is reserved for the BRP count, so don't increment it if it is zero
+        if (numBRPs > 0)
+            numBRPs++;
+        ProcessMacOSXLog::LogIf(PD_LOG_THREAD, "DBGDIDR=0x%8.8x (number BRP pairs = %u)", register_DBGDIDR, numBRPs);
+
+        if (numBRPs > 0)
+        {
+            uint32_t cpu_subtype;
+            size_t len;
+            len = sizeof(cpusubtype);
+            // TODO: remove this hack and change to using hw.optional.xx when implmented
+            if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
+            {
+                ProcessMacOSXLog::LogIf(PD_LOG_THREAD, "hw.cpusubtype=0x%d", cpusubtype);
+                if (cpusubtype == CPU_SUBTYPE_ARM_V7)
+                    ProcessMacOSXLog::LogIf(PD_LOG_THREAD, "Hardware breakpoints disabled for armv7 (rdar://problem/6372672)");
+                else
+                    g_num_supported_hw_breakpoints = numBRPs;
+            }
+        }
+
+    }
+    return g_num_supported_hw_breakpoints;
+#else
+    // TODO: figure out remote case here!
+    return 6;
+#endif
+}
+
+uint32_t
+RegisterContextMach_arm::SetHardwareBreakpoint (lldb::addr_t addr, size_t size)
+{
+    // Make sure our address isn't bogus
+    if (addr & 1)
+        return LLDB_INVALID_INDEX32;
+
+    kern_return_t kret = ReadDBG (false);
+
+    if (kret == KERN_SUCCESS)
+    {
+        const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints();
+        uint32_t i;
+        for (i=0; i<num_hw_breakpoints; ++i)
+        {
+            if ((dbg.bcr[i] & BCR_ENABLE) == 0)
+                break; // We found an available hw breakpoint slot (in i)
+        }
+
+        // See if we found an available hw breakpoint slot above
+        if (i < num_hw_breakpoints)
+        {
+            // Make sure bits 1:0 are clear in our address
+            dbg.bvr[i] = addr & ~((lldb::addr_t)3);
+
+            if (size == 2 || addr & 2)
+            {
+                uint32_t byte_addr_select = (addr & 2) ? BAS_IMVA_2_3 : BAS_IMVA_0_1;
+
+                // We have a thumb breakpoint
+                // We have an ARM breakpoint
+                dbg.bcr[i] =  BCR_M_IMVA_MATCH |    // Stop on address mismatch
+                                        byte_addr_select |  // Set the correct byte address select so we only trigger on the correct opcode
+                                        S_USER |            // Which modes should this breakpoint stop in?
+                                        BCR_ENABLE;         // Enable this hardware breakpoint
+                ProcessMacOSXLog::LogIf(PD_LOG_BREAKPOINTS, "RegisterContextMach_arm::EnableHardwareBreakpoint( addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (Thumb)",
+                        addr,
+                        size,
+                        i,
+                        i,
+                        dbg.bvr[i],
+                        dbg.bcr[i]);
+            }
+            else if (size == 4)
+            {
+                // We have an ARM breakpoint
+                dbg.bcr[i] =  BCR_M_IMVA_MATCH |    // Stop on address mismatch
+                                        BAS_IMVA_ALL |      // Stop on any of the four bytes following the IMVA
+                                        S_USER |            // Which modes should this breakpoint stop in?
+                                        BCR_ENABLE;         // Enable this hardware breakpoint
+                ProcessMacOSXLog::LogIf(PD_LOG_BREAKPOINTS, "RegisterContextMach_arm::EnableHardwareBreakpoint( addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (ARM)",
+                        addr,
+                        size,
+                        i,
+                        i,
+                        dbg.bvr[i],
+                        dbg.bcr[i]);
+            }
+
+            kret = WriteDBG();
+            ProcessMacOSXLog::LogIf(PD_LOG_BREAKPOINTS, "RegisterContextMach_arm::EnableHardwareBreakpoint() WriteDBG() => 0x%8.8x.", kret);
+
+            if (kret == KERN_SUCCESS)
+                return i;
+        }
+        else
+        {
+            ProcessMacOSXLog::LogIf(PD_LOG_BREAKPOINTS, "RegisterContextMach_arm::EnableHardwareBreakpoint(addr = %8.8p, size = %u) => all hardware breakpoint resources are being used.", addr, size);
+        }
+    }
+
+    return LLDB_INVALID_INDEX32;
+}
+
+bool
+RegisterContextMach_arm::ClearHardwareBreakpoint (uint32_t hw_index)
+{
+    kern_return_t kret = ReadDBG (false);
+
+    const uint32_t num_hw_points = NumSupportedHardwareBreakpoints();
+    if (kret == KERN_SUCCESS)
+    {
+        if (hw_index < num_hw_points)
+        {
+            dbg.bcr[hw_index] = 0;
+            ProcessMacOSXLog::LogIf(PD_LOG_BREAKPOINTS, "RegisterContextMach_arm::SetHardwareBreakpoint( %u ) - BVR%u = 0x%8.8x  BCR%u = 0x%8.8x",
+                    hw_index,
+                    hw_index,
+                    dbg.bvr[hw_index],
+                    hw_index,
+                    dbg.bcr[hw_index]);
+
+            kret = WriteDBG();
+
+            if (kret == KERN_SUCCESS)
+                return true;
+        }
+    }
+    return false;
+}
+
+uint32_t
+RegisterContextMach_arm::NumSupportedHardwareWatchpoints ()
+{
+#if defined (__arm__)
+    // Set the init value to something that will let us know that we need to
+    // autodetect how many watchpoints are supported dynamically...
+    static uint32_t g_num_supported_hw_watchpoints = UINT_MAX;
+    if (g_num_supported_hw_watchpoints == UINT_MAX)
+    {
+        // Set this to zero in case we can't tell if there are any HW breakpoints
+        g_num_supported_hw_watchpoints = 0;
+        // Read the DBGDIDR to get the number of available hardware breakpoints
+        // However, in some of our current armv7 processors, hardware
+        // breakpoints/watchpoints were not properly connected. So detect those
+        // cases using a field in a sysctl. For now we are using "hw.cpusubtype"
+        // field to distinguish CPU architectures. This is a hack until we can
+        // get <rdar://problem/6372672> fixed, at which point we will switch to
+        // using a different sysctl string that will tell us how many WRPs
+        // are available to us directly without having to read DBGDIDR.
+
+        uint32_t register_DBGDIDR;
+        asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR));
+        uint32_t numWRPs = bits(register_DBGDIDR, 31, 28) + 1;
+        ProcessMacOSXLog::LogIf(PD_LOG_THREAD, "DBGDIDR=0x%8.8x (number WRP pairs = %u)", register_DBGDIDR, numWRPs);
+
+        if (numWRPs > 0)
+        {
+            uint32_t cpusubtype;
+            size_t len;
+            len = sizeof(cpusubtype);
+            // TODO: remove this hack and change to using hw.optional.xx when implmented
+            if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
+            {
+                ProcessMacOSXLog::LogIf(PD_LOG_THREAD, "hw.cpusubtype=0x%d", cpusubtype);
+
+                if (cpusubtype == CPU_SUBTYPE_ARM_V7)
+                    ProcessMacOSXLog::LogIf(PD_LOG_THREAD, "Hardware watchpoints disabled for armv7 (rdar://problem/6372672)");
+                else
+                    g_num_supported_hw_watchpoints = numWRPs;
+            }
+        }
+
+    }
+    return g_num_supported_hw_watchpoints;
+#else
+    // TODO: figure out remote case here!
+    return 2;
+#endif
+}
+
+
+uint32_t
+RegisterContextMach_arm::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write)
+{
+    ProcessMacOSXLog::LogIf(PD_LOG_WATCHPOINTS, "RegisterContextMach_arm::EnableHardwareWatchpoint(addr = %8.8p, size = %u, read = %u, write = %u)", addr, size, read, write);
+
+    const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
+
+    // Can't watch zero bytes
+    if (size == 0)
+        return LLDB_INVALID_INDEX32;
+
+    // We must watch for either read or write
+    if (read == false && write == false)
+        return LLDB_INVALID_INDEX32;
+
+    // Can't watch more than 4 bytes per WVR/WCR pair
+    if (size > 4)
+        return LLDB_INVALID_INDEX32;
+
+    // We can only watch up to four bytes that follow a 4 byte aligned address
+    // per watchpoint register pair. Since we have at most so we can only watch
+    // until the next 4 byte boundary and we need to make sure we can properly
+    // encode this.
+    uint32_t addr_word_offset = addr % 4;
+    ProcessMacOSXLog::LogIf(PD_LOG_WATCHPOINTS, "RegisterContextMach_arm::EnableHardwareWatchpoint() - addr_word_offset = 0x%8.8x", addr_word_offset);
+
+    uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset;
+    ProcessMacOSXLog::LogIf(PD_LOG_WATCHPOINTS, "RegisterContextMach_arm::EnableHardwareWatchpoint() - byte_mask = 0x%8.8x", byte_mask);
+    if (byte_mask > 0xfu)
+        return LLDB_INVALID_INDEX32;
+
+    // Read the debug state
+    kern_return_t kret = ReadDBG (false);
+
+    if (kret == KERN_SUCCESS)
+    {
+        // Check to make sure we have the needed hardware support
+        uint32_t i = 0;
+
+        for (i=0; i<num_hw_watchpoints; ++i)
+        {
+            if ((dbg.wcr[i] & WCR_ENABLE) == 0)
+                break; // We found an available hw breakpoint slot (in i)
+        }
+
+        // See if we found an available hw breakpoint slot above
+        if (i < num_hw_watchpoints)
+        {
+            // Make the byte_mask into a valid Byte Address Select mask
+            uint32_t byte_address_select = byte_mask << 5;
+            // Make sure bits 1:0 are clear in our address
+            dbg.wvr[i] = addr & ~((lldb::addr_t)3);
+            dbg.wcr[i] =  byte_address_select |       // Which bytes that follow the IMVA that we will watch
+                                    S_USER |                    // Stop only in user mode
+                                    (read ? WCR_LOAD : 0) |     // Stop on read access?
+                                    (write ? WCR_STORE : 0) |   // Stop on write access?
+                                    WCR_ENABLE;                 // Enable this watchpoint;
+
+            kret = WriteDBG();
+            ProcessMacOSXLog::LogIf(PD_LOG_WATCHPOINTS, "RegisterContextMach_arm::EnableHardwareWatchpoint() WriteDBG() => 0x%8.8x.", kret);
+
+            if (kret == KERN_SUCCESS)
+                return i;
+        }
+        else
+        {
+            ProcessMacOSXLog::LogIf(PD_LOG_WATCHPOINTS, "RegisterContextMach_arm::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints);
+        }
+    }
+    return LLDB_INVALID_INDEX32;
+}
+
+bool
+RegisterContextMach_arm::ClearHardwareWatchpoint (uint32_t hw_index)
+{
+    kern_return_t kret = ReadDBG (false);
+
+    const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
+    if (kret == KERN_SUCCESS)
+    {
+        if (hw_index < num_hw_points)
+        {
+            dbg.wcr[hw_index] = 0;
+            ProcessMacOSXLog::LogIf(PD_LOG_WATCHPOINTS, "RegisterContextMach_arm::ClearHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x  WCR%u = 0x%8.8x",
+                    hw_index,
+                    hw_index,
+                    dbg.wvr[hw_index],
+                    hw_index,
+                    dbg.wcr[hw_index]);
+
+            kret = WriteDBG();
+
+            if (kret == KERN_SUCCESS)
+                return true;
+        }
+    }
+    return false;
+}
+
+
diff --git a/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_arm.h b/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_arm.h
new file mode 100644
index 0000000..37821cd
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_arm.h
@@ -0,0 +1,302 @@
+//===-- RegisterContextMach_arm.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_RegisterContextMach_arm_h_
+#define liblldb_RegisterContextMach_arm_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/RegisterContext.h"
+
+// BCR address match type
+#define BCR_M_IMVA_MATCH        ((uint32_t)(0u << 21))
+#define BCR_M_CONTEXT_ID_MATCH  ((uint32_t)(1u << 21))
+#define BCR_M_IMVA_MISMATCH     ((uint32_t)(2u << 21))
+#define BCR_M_RESERVED          ((uint32_t)(3u << 21))
+
+// Link a BVR/BCR or WVR/WCR pair to another
+#define E_ENABLE_LINKING        ((uint32_t)(1u << 20))
+
+// Byte Address Select
+#define BAS_IMVA_PLUS_0         ((uint32_t)(1u << 5))
+#define BAS_IMVA_PLUS_1         ((uint32_t)(1u << 6))
+#define BAS_IMVA_PLUS_2         ((uint32_t)(1u << 7))
+#define BAS_IMVA_PLUS_3         ((uint32_t)(1u << 8))
+#define BAS_IMVA_0_1            ((uint32_t)(3u << 5))
+#define BAS_IMVA_2_3            ((uint32_t)(3u << 7))
+#define BAS_IMVA_ALL            ((uint32_t)(0xfu << 5))
+
+// Break only in priveleged or user mode
+#define S_RSVD                  ((uint32_t)(0u << 1))
+#define S_PRIV                  ((uint32_t)(1u << 1))
+#define S_USER                  ((uint32_t)(2u << 1))
+#define S_PRIV_USER             ((S_PRIV) | (S_USER))
+
+#define BCR_ENABLE              ((uint32_t)(1u))
+#define WCR_ENABLE              ((uint32_t)(1u))
+
+// Watchpoint load/store
+#define WCR_LOAD                ((uint32_t)(1u << 3))
+#define WCR_STORE               ((uint32_t)(1u << 4))
+
+class RegisterContextMach_arm : public lldb_private::RegisterContext
+{
+public:
+
+    RegisterContextMach_arm(lldb_private::Thread &thread, lldb_private::StackFrame *frame);
+
+    virtual
+    ~RegisterContextMach_arm();
+
+    virtual void
+    Invalidate ();
+
+    virtual size_t
+    GetRegisterCount ();
+
+    virtual const lldb::RegisterInfo *
+    GetRegisterInfoAtIndex (uint32_t reg);
+
+    virtual size_t
+    GetRegisterSetCount ();
+
+    virtual const lldb::RegisterSet *
+    GetRegisterSet (uint32_t set);
+
+    virtual bool
+    ReadRegisterValue (uint32_t reg, lldb_private::Scalar &value);
+
+    virtual bool
+    ReadRegisterBytes (uint32_t reg, lldb_private::DataExtractor &data);
+
+    virtual bool
+    ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+
+    virtual bool
+    WriteRegisterValue (uint32_t reg, const lldb_private::Scalar &value);
+
+    virtual bool
+    WriteRegisterBytes (uint32_t reg, lldb_private::DataExtractor &data, uint32_t data_offset = 0);
+
+    virtual bool
+    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+
+    virtual uint32_t
+    ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+
+    virtual uint32_t
+    NumSupportedHardwareBreakpoints ();
+
+    virtual uint32_t
+    SetHardwareBreakpoint (lldb::addr_t addr, size_t size);
+
+    virtual bool
+    ClearHardwareBreakpoint (uint32_t hw_idx);
+
+    virtual uint32_t
+    NumSupportedHardwareWatchpoints ();
+
+    virtual uint32_t
+    SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write);
+
+    virtual bool
+    ClearHardwareWatchpoint (uint32_t hw_index);
+
+    struct GPR
+    {
+        uint32_t    r[16];  // R0-R15
+        uint32_t    cpsr;   // CPSR
+    };
+
+
+    struct FPU
+    {
+        union {
+            uint32_t s[32];
+            uint64_t d[16];
+        } floats;
+        uint32_t fpscr;
+    };
+
+//  struct NeonReg
+//  {
+//      uint8_t bytes[16];
+//  };
+//
+//  struct VFPv3
+//  {
+//      union {
+//          uint32_t s[32];
+//          uint64_t d[32];
+//          NeonReg  q[16];
+//      } v3;
+//      uint32_t fpscr;
+//  };
+
+    struct EXC
+    {
+        uint32_t    exception;
+        uint32_t    fsr; /* Fault status */
+        uint32_t    far; /* Virtual Fault Address */
+    };
+
+    struct DBG
+    {
+        uint32_t bvr[16];
+        uint32_t bcr[16];
+        uint32_t wvr[16];
+        uint32_t wcr[16];
+    };
+
+    static void
+    LogDBGRegisters (lldb_private::Log *log, const DBG& dbg);
+
+protected:
+
+    typedef enum
+    {
+        GPRRegSet = 1,
+        FPURegSet = 2,
+        EXCRegSet = 3,
+        DBGRegSet = 4,
+    };
+
+    enum
+    {
+        GPRWordCount = sizeof(GPR)/sizeof(uint32_t),
+        FPUWordCount = sizeof(FPU)/sizeof(uint32_t),
+        EXCWordCount = sizeof(EXC)/sizeof(uint32_t),
+        DBGWordCount = sizeof(DBG)/sizeof(uint32_t)
+    };
+
+    enum
+    {
+        Read = 0,
+        Write = 1,
+        kNumErrors = 2
+    };
+
+    GPR gpr;
+    FPU fpu;
+    EXC exc;
+    DBG dbg;
+    kern_return_t gpr_errs[2]; // Read/Write errors
+    kern_return_t fpu_errs[2]; // Read/Write errors
+    kern_return_t exc_errs[2]; // Read/Write errors
+    kern_return_t dbg_errs[2]; // Read/Write errors
+
+    void
+    InvalidateAllRegisterStates()
+    {
+        SetError (GPRRegSet, Read, -1);
+        SetError (FPURegSet, Read, -1);
+        SetError (EXCRegSet, Read, -1);
+    }
+
+    kern_return_t
+    GetError (int flavor, uint32_t err_idx) const
+    {
+        if (err_idx < kNumErrors)
+        {
+            switch (flavor)
+            {
+            // When getting all errors, just OR all values together to see if
+            // we got any kind of error.
+            case GPRRegSet:    return gpr_errs[err_idx];
+            case FPURegSet:    return fpu_errs[err_idx];
+            case EXCRegSet:    return exc_errs[err_idx];
+            case DBGRegSet:    return dbg_errs[err_idx];
+            default: break;
+            }
+        }
+        return -1;
+    }
+
+    bool
+    SetError (int flavor, uint32_t err_idx, kern_return_t err)
+    {
+        if (err_idx < kNumErrors)
+        {
+            switch (flavor)
+            {
+            case GPRRegSet:
+                gpr_errs[err_idx] = err;
+                return true;
+
+            case FPURegSet:
+                fpu_errs[err_idx] = err;
+                return true;
+
+            case EXCRegSet:
+                exc_errs[err_idx] = err;
+                return true;
+
+            case DBGRegSet:
+                exc_errs[err_idx] = err;
+                return true;
+
+            default: break;
+            }
+        }
+        return false;
+    }
+
+    bool
+    RegisterSetIsCached (int set) const
+    {
+        return GetError(set, Read) == KERN_SUCCESS;
+    }
+
+    kern_return_t
+    ReadGPR (bool force);
+
+    kern_return_t
+    ReadFPU (bool force);
+
+    kern_return_t
+    ReadEXC (bool force);
+
+    kern_return_t
+    ReadDBG (bool force);
+
+    kern_return_t
+    WriteGPR ();
+
+    kern_return_t
+    WriteFPU ();
+
+    kern_return_t
+    WriteEXC ();
+
+    kern_return_t
+    WriteDBG ();
+
+    kern_return_t
+    ReadRegisterSet (uint32_t set, bool force);
+
+    kern_return_t
+    WriteRegisterSet (uint32_t set);
+
+    static uint32_t
+    GetRegisterNumber (uint32_t reg_kind, uint32_t reg_num);
+
+    static int
+    GetSetForNativeRegNum (int reg_num);
+
+    static size_t
+    GetRegisterInfosCount ();
+
+    static const lldb::RegisterInfo *
+    GetRegisterInfos ();
+};
+
+#endif  // liblldb_RegisterContextMach_arm_h_
diff --git a/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_i386.cpp b/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_i386.cpp
new file mode 100644
index 0000000..daa4f0d
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_i386.cpp
@@ -0,0 +1,1202 @@
+//===-- RegisterContextMach_i386.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 <mach/thread_act.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Scalar.h"
+
+// Project includes
+#include "RegisterContextMach_i386.h"
+#include "ProcessMacOSXLog.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+enum
+{
+    gpr_eax = 0,
+    gpr_ebx,
+    gpr_ecx,
+    gpr_edx,
+    gpr_edi,
+    gpr_esi,
+    gpr_ebp,
+    gpr_esp,
+    gpr_ss,
+    gpr_eflags,
+    gpr_eip,
+    gpr_cs,
+    gpr_ds,
+    gpr_es,
+    gpr_fs,
+    gpr_gs,
+
+    fpu_fcw,
+    fpu_fsw,
+    fpu_ftw,
+    fpu_fop,
+    fpu_ip,
+    fpu_cs,
+    fpu_dp,
+    fpu_ds,
+    fpu_mxcsr,
+    fpu_mxcsrmask,
+    fpu_stmm0,
+    fpu_stmm1,
+    fpu_stmm2,
+    fpu_stmm3,
+    fpu_stmm4,
+    fpu_stmm5,
+    fpu_stmm6,
+    fpu_stmm7,
+    fpu_xmm0,
+    fpu_xmm1,
+    fpu_xmm2,
+    fpu_xmm3,
+    fpu_xmm4,
+    fpu_xmm5,
+    fpu_xmm6,
+    fpu_xmm7,
+
+    exc_trapno,
+    exc_err,
+    exc_faultvaddr,
+
+    k_num_registers,
+
+    // Aliases
+    fpu_fctrl = fpu_fcw,
+    fpu_fstat = fpu_fsw,
+    fpu_ftag  = fpu_ftw,
+    fpu_fiseg = fpu_cs,
+    fpu_fioff = fpu_ip,
+    fpu_foseg = fpu_ds,
+    fpu_fooff = fpu_dp
+};
+
+enum
+{
+    gcc_eax = 0,
+    gcc_ecx,
+    gcc_edx,
+    gcc_ebx,
+    gcc_ebp,
+    gcc_esp,
+    gcc_esi,
+    gcc_edi,
+    gcc_eip,
+    gcc_eflags
+};
+
+enum
+{
+    dwarf_eax = 0,
+    dwarf_ecx,
+    dwarf_edx,
+    dwarf_ebx,
+    dwarf_esp,
+    dwarf_ebp,
+    dwarf_esi,
+    dwarf_edi,
+    dwarf_eip,
+    dwarf_eflags,
+    dwarf_stmm0 = 11,
+    dwarf_stmm1,
+    dwarf_stmm2,
+    dwarf_stmm3,
+    dwarf_stmm4,
+    dwarf_stmm5,
+    dwarf_stmm6,
+    dwarf_stmm7,
+    dwarf_xmm0 = 21,
+    dwarf_xmm1,
+    dwarf_xmm2,
+    dwarf_xmm3,
+    dwarf_xmm4,
+    dwarf_xmm5,
+    dwarf_xmm6,
+    dwarf_xmm7
+};
+
+enum
+{
+    gdb_eax        =  0,
+    gdb_ecx        =  1,
+    gdb_edx        =  2,
+    gdb_ebx        =  3,
+    gdb_esp        =  4,
+    gdb_ebp        =  5,
+    gdb_esi        =  6,
+    gdb_edi        =  7,
+    gdb_eip        =  8,
+    gdb_eflags     =  9,
+    gdb_cs         = 10,
+    gdb_ss         = 11,
+    gdb_ds         = 12,
+    gdb_es         = 13,
+    gdb_fs         = 14,
+    gdb_gs         = 15,
+    gdb_stmm0      = 16,
+    gdb_stmm1      = 17,
+    gdb_stmm2      = 18,
+    gdb_stmm3      = 19,
+    gdb_stmm4      = 20,
+    gdb_stmm5      = 21,
+    gdb_stmm6      = 22,
+    gdb_stmm7      = 23,
+    gdb_fctrl      = 24,    gdb_fcw     = gdb_fctrl,
+    gdb_fstat      = 25,    gdb_fsw     = gdb_fstat,
+    gdb_ftag       = 26,    gdb_ftw     = gdb_ftag,
+    gdb_fiseg      = 27,    gdb_fpu_cs  = gdb_fiseg,
+    gdb_fioff      = 28,    gdb_ip      = gdb_fioff,
+    gdb_foseg      = 29,    gdb_fpu_ds  = gdb_foseg,
+    gdb_fooff      = 30,    gdb_dp      = gdb_fooff,
+    gdb_fop        = 31,
+    gdb_xmm0       = 32,
+    gdb_xmm1       = 33,
+    gdb_xmm2       = 34,
+    gdb_xmm3       = 35,
+    gdb_xmm4       = 36,
+    gdb_xmm5       = 37,
+    gdb_xmm6       = 38,
+    gdb_xmm7       = 39,
+    gdb_mxcsr      = 40,
+    gdb_mm0        = 41,
+    gdb_mm1        = 42,
+    gdb_mm2        = 43,
+    gdb_mm3        = 44,
+    gdb_mm4        = 45,
+    gdb_mm5        = 46,
+    gdb_mm6        = 47,
+    gdb_mm7        = 48
+};
+
+RegisterContextMach_i386::RegisterContextMach_i386 (Thread &thread, StackFrame *frame) :
+    RegisterContext(thread, frame),
+    gpr(),
+    fpu(),
+    exc()
+{
+    uint32_t i;
+    for (i=0; i<kNumErrors; i++)
+    {
+        gpr_errs[i] = -1;
+        fpu_errs[i] = -1;
+        exc_errs[i] = -1;
+    }
+}
+
+RegisterContextMach_i386::~RegisterContextMach_i386()
+{
+}
+
+
+
+#define GPR_OFFSET(reg) (offsetof (RegisterContextMach_i386::GPR, reg))
+#define FPU_OFFSET(reg) (offsetof (RegisterContextMach_i386::FPU, reg) + sizeof (RegisterContextMach_i386::GPR))
+#define EXC_OFFSET(reg) (offsetof (RegisterContextMach_i386::EXC, reg) + sizeof (RegisterContextMach_i386::GPR) + sizeof (RegisterContextMach_i386::FPU))
+
+// These macros will auto define the register name, alt name, register size,
+// register offset, encoding, format and native register. This ensures that
+// the register state structures are defined correctly and have the correct
+// sizes and offsets.
+#define DEFINE_GPR(reg, alt)    #reg, alt, sizeof(((RegisterContextMach_i386::GPR *)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, eFormatHex, gpr_##reg
+#define DEFINE_FPU_UINT(reg)    #reg, NULL, sizeof(((RegisterContextMach_i386::FPU *)NULL)->reg), FPU_OFFSET(reg), eEncodingUint, eFormatHex, fpu_##reg
+#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextMach_i386::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, fpu_##reg##i, { LLDB_INVALID_REGNUM, dwarf_##reg##i, LLDB_INVALID_REGNUM, gdb_##reg##i }
+
+#define DEFINE_EXC(reg)         #reg, NULL, sizeof(((RegisterContextMach_i386::EXC *)NULL)->reg), EXC_OFFSET(reg), eEncodingUint, eFormatHex, exc_##reg
+#define REG_CONTEXT_SIZE (sizeof (RegisterContextMach_i386::GPR) + sizeof (RegisterContextMach_i386::FPU) + sizeof (RegisterContextMach_i386::EXC))
+
+static RegisterInfo g_register_infos[] =
+{
+//  Macro auto defines most stuff   GCC REG KIND NUM        DWARF REG KIND NUM    GENERIC REG KIND NUM        GDB REG KIND NUM
+//  =============================== ======================= ===================   ==========================  ==========================
+    { DEFINE_GPR(eax    , NULL)     , { gcc_eax             , dwarf_eax       , LLDB_INVALID_REGNUM       , gdb_eax         }},
+    { DEFINE_GPR(ebx    , NULL)     , { gcc_ebx             , dwarf_ebx       , LLDB_INVALID_REGNUM       , gdb_ebx         }},
+    { DEFINE_GPR(ecx    , NULL)     , { gcc_ecx             , dwarf_ecx       , LLDB_INVALID_REGNUM       , gdb_ecx         }},
+    { DEFINE_GPR(edx    , NULL)     , { gcc_edx             , dwarf_edx       , LLDB_INVALID_REGNUM       , gdb_edx         }},
+    { DEFINE_GPR(edi    , NULL)     , { gcc_edi             , dwarf_edi       , LLDB_INVALID_REGNUM       , gdb_edi         }},
+    { DEFINE_GPR(esi    , NULL)     , { gcc_esi             , dwarf_esi       , LLDB_INVALID_REGNUM       , gdb_esi         }},
+    { DEFINE_GPR(ebp    , "fp")     , { gcc_ebp             , dwarf_ebp       , LLDB_REGNUM_GENERIC_FP    , gdb_ebp         }},
+    { DEFINE_GPR(esp    , "sp")     , { gcc_esp             , dwarf_esp       , LLDB_REGNUM_GENERIC_SP    , gdb_esp         }},
+    { DEFINE_GPR(ss     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_ss          }},
+    { DEFINE_GPR(eflags , "flags")  , { gcc_eflags          , dwarf_eflags    , LLDB_REGNUM_GENERIC_FLAGS , gdb_eflags      }},
+    { DEFINE_GPR(eip    , "pc")     , { gcc_eip             , dwarf_eip       , LLDB_REGNUM_GENERIC_PC    , gdb_eip         }},
+    { DEFINE_GPR(cs     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_cs          }},
+    { DEFINE_GPR(ds     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_ds          }},
+    { DEFINE_GPR(es     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_es          }},
+    { DEFINE_GPR(fs     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fs          }},
+    { DEFINE_GPR(gs     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_gs          }},
+
+    { DEFINE_FPU_UINT(fcw)          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fcw         }},
+    { DEFINE_FPU_UINT(fsw)          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fsw         }},
+    { DEFINE_FPU_UINT(ftw)          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_ftw         }},
+    { DEFINE_FPU_UINT(fop)          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fop         }},
+    { DEFINE_FPU_UINT(ip)           , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_ip          }},
+    { DEFINE_FPU_UINT(cs)           , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_cs          }},
+    { DEFINE_FPU_UINT(dp)           , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_dp          }},
+    { DEFINE_FPU_UINT(ds)           , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_ds          }},
+    { DEFINE_FPU_UINT(mxcsr)        , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_mxcsr       }},
+    { DEFINE_FPU_UINT(mxcsrmask)    , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM }},
+    { DEFINE_FPU_VECT(stmm,0)   },
+    { DEFINE_FPU_VECT(stmm,1)   },
+    { DEFINE_FPU_VECT(stmm,2)   },
+    { DEFINE_FPU_VECT(stmm,3)   },
+    { DEFINE_FPU_VECT(stmm,4)   },
+    { DEFINE_FPU_VECT(stmm,5)   },
+    { DEFINE_FPU_VECT(stmm,6)   },
+    { DEFINE_FPU_VECT(stmm,7)   },
+    { DEFINE_FPU_VECT(xmm,0)    },
+    { DEFINE_FPU_VECT(xmm,1)    },
+    { DEFINE_FPU_VECT(xmm,2)    },
+    { DEFINE_FPU_VECT(xmm,3)    },
+    { DEFINE_FPU_VECT(xmm,4)    },
+    { DEFINE_FPU_VECT(xmm,5)    },
+    { DEFINE_FPU_VECT(xmm,6)    },
+    { DEFINE_FPU_VECT(xmm,7)    },
+
+    { DEFINE_EXC(trapno)            , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM   , LLDB_INVALID_REGNUM         , LLDB_INVALID_REGNUM }},
+    { DEFINE_EXC(err)               , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM   , LLDB_INVALID_REGNUM         , LLDB_INVALID_REGNUM }},
+    { DEFINE_EXC(faultvaddr)        , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM   , LLDB_INVALID_REGNUM         , LLDB_INVALID_REGNUM }}
+};
+
+static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo));
+
+void
+RegisterContextMach_i386::Invalidate ()
+{
+    InvalidateAllRegisterStates();
+}
+
+
+size_t
+RegisterContextMach_i386::GetRegisterCount ()
+{
+    assert(k_num_register_infos == k_num_registers);
+    return k_num_registers;
+}
+
+const RegisterInfo *
+RegisterContextMach_i386::GetRegisterInfoAtIndex (uint32_t reg)
+{
+    assert(k_num_register_infos == k_num_registers);
+    if (reg < k_num_registers)
+        return &g_register_infos[reg];
+    return NULL;
+}
+
+size_t
+RegisterContextMach_i386::GetRegisterInfosCount ()
+{
+    return k_num_register_infos;
+}
+
+const RegisterInfo *
+RegisterContextMach_i386::GetRegisterInfos ()
+{
+    return g_register_infos;
+}
+
+
+// General purpose registers
+static uint32_t
+g_gpr_regnums[] =
+{
+    gpr_eax,
+    gpr_ebx,
+    gpr_ecx,
+    gpr_edx,
+    gpr_edi,
+    gpr_esi,
+    gpr_ebp,
+    gpr_esp,
+    gpr_ss,
+    gpr_eflags,
+    gpr_eip,
+    gpr_cs,
+    gpr_ds,
+    gpr_es,
+    gpr_fs,
+    gpr_gs
+};
+
+// Floating point registers
+static uint32_t
+g_fpu_regnums[] =
+{
+    fpu_fcw,
+    fpu_fsw,
+    fpu_ftw,
+    fpu_fop,
+    fpu_ip,
+    fpu_cs,
+    fpu_dp,
+    fpu_ds,
+    fpu_mxcsr,
+    fpu_mxcsrmask,
+    fpu_stmm0,
+    fpu_stmm1,
+    fpu_stmm2,
+    fpu_stmm3,
+    fpu_stmm4,
+    fpu_stmm5,
+    fpu_stmm6,
+    fpu_stmm7,
+    fpu_xmm0,
+    fpu_xmm1,
+    fpu_xmm2,
+    fpu_xmm3,
+    fpu_xmm4,
+    fpu_xmm5,
+    fpu_xmm6,
+    fpu_xmm7
+};
+
+// Exception registers
+
+static uint32_t
+g_exc_regnums[] =
+{
+    exc_trapno,
+    exc_err,
+    exc_faultvaddr
+};
+
+// Number of registers in each register set
+const size_t k_num_gpr_registers = sizeof(g_gpr_regnums) / sizeof(uint32_t);
+const size_t k_num_fpu_registers = sizeof(g_fpu_regnums) / sizeof(uint32_t);
+const size_t k_num_exc_registers = sizeof(g_exc_regnums) / sizeof(uint32_t);
+
+//----------------------------------------------------------------------
+// Register set definitions. The first definitions at register set index
+// of zero is for all registers, followed by other registers sets. The
+// register information for the all register set need not be filled in.
+//----------------------------------------------------------------------
+static const RegisterSet g_reg_sets[] =
+{
+    { "General Purpose Registers",  "gpr",  k_num_gpr_registers,    g_gpr_regnums,      },
+    { "Floating Point Registers",   "fpu",  k_num_fpu_registers,    g_fpu_regnums       },
+    { "Exception State Registers",  "exc",  k_num_exc_registers,    g_exc_regnums       }
+};
+
+const size_t k_num_regsets = sizeof(g_reg_sets) / sizeof(RegisterSet);
+
+
+size_t
+RegisterContextMach_i386::GetRegisterSetCount ()
+{
+    return k_num_regsets;
+}
+
+const RegisterSet *
+RegisterContextMach_i386::GetRegisterSet (uint32_t reg_set)
+{
+    if (reg_set < k_num_regsets)
+        return &g_reg_sets[reg_set];
+    return NULL;
+}
+
+
+//----------------------------------------------------------------------
+// Register information defintions for 32 bit i386.
+//----------------------------------------------------------------------
+int
+RegisterContextMach_i386::GetSetForNativeRegNum (int reg_num)
+{
+    if (reg_num < fpu_fcw)
+        return GPRRegSet;
+    else if (reg_num < exc_trapno)
+        return FPURegSet;
+    else if (reg_num < k_num_registers)
+        return EXCRegSet;
+    return -1;
+}
+
+
+void
+RegisterContextMach_i386::LogGPR(Log *log, const char *title)
+{
+    if (log)
+    {
+        if (title)
+            log->Printf ("%s", title);
+        for (uint32_t i=0; i<k_num_gpr_registers; i++)
+        {
+            uint32_t reg = gpr_eax + i;
+            log->Printf("%12s = 0x%8.8x", g_register_infos[reg].name, (&gpr.eax)[reg]);
+        }
+    }
+}
+
+
+
+kern_return_t
+RegisterContextMach_i386::ReadGPR (bool force)
+{
+    int set = GPRRegSet;
+    if (force || !RegisterSetIsCached(set))
+    {
+        mach_msg_type_number_t count = GPRWordCount;
+        SetError(set, Read, ::thread_get_state(GetThreadID(), set, (thread_state_t)&gpr, &count));
+        LogGPR (ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_THREAD), "RegisterContextMach_i386::ReadGPR()");
+    }
+    return GetError(set, Read);
+}
+
+kern_return_t
+RegisterContextMach_i386::ReadFPU (bool force)
+{
+    int set = FPURegSet;
+    if (force || !RegisterSetIsCached(set))
+    {
+        mach_msg_type_number_t count = FPUWordCount;
+        SetError(set, Read, ::thread_get_state(GetThreadID(), set, (thread_state_t)&fpu, &count));
+    }
+    return GetError(set, Read);
+}
+
+kern_return_t
+RegisterContextMach_i386::ReadEXC (bool force)
+{
+    int set = EXCRegSet;
+    if (force || !RegisterSetIsCached(set))
+    {
+        mach_msg_type_number_t count = EXCWordCount;
+        SetError(set, Read, ::thread_get_state(GetThreadID(), set, (thread_state_t)&exc, &count));
+    }
+    return GetError(set, Read);
+}
+
+kern_return_t
+RegisterContextMach_i386::WriteGPR ()
+{
+    int set = GPRRegSet;
+    if (!RegisterSetIsCached(set))
+    {
+        SetError (set, Write, -1);
+        return KERN_INVALID_ARGUMENT;
+    }
+    SetError (set, Write, ::thread_set_state(GetThreadID(), set, (thread_state_t)&gpr, GPRWordCount));
+    SetError (set, Read, -1);
+    return GetError(set, Write);
+}
+
+kern_return_t
+RegisterContextMach_i386::WriteFPU ()
+{
+    int set = FPURegSet;
+    if (!RegisterSetIsCached(set))
+    {
+        SetError (set, Write, -1);
+        return KERN_INVALID_ARGUMENT;
+    }
+    SetError (set, Write, ::thread_set_state(GetThreadID(), set, (thread_state_t)&fpu, FPUWordCount));
+    SetError (set, Read, -1);
+    return GetError(set, Write);
+}
+
+kern_return_t
+RegisterContextMach_i386::WriteEXC ()
+{
+    int set = EXCRegSet;
+    if (!RegisterSetIsCached(set))
+    {
+        SetError (set, Write, -1);
+        return KERN_INVALID_ARGUMENT;
+    }
+    SetError (set, Write, ::thread_set_state(GetThreadID(), set, (thread_state_t)&exc, EXCWordCount));
+    SetError (set, Read, -1);
+    return GetError(set, Write);
+}
+
+kern_return_t
+RegisterContextMach_i386::ReadRegisterSet (uint32_t set, bool force)
+{
+    switch (set)
+    {
+    case GPRRegSet:    return ReadGPR(force);
+    case FPURegSet:    return ReadFPU(force);
+    case EXCRegSet:    return ReadEXC(force);
+    default: break;
+    }
+    return KERN_INVALID_ARGUMENT;
+}
+
+kern_return_t
+RegisterContextMach_i386::WriteRegisterSet (uint32_t set)
+{
+    // Make sure we have a valid context to set.
+    if (RegisterSetIsCached(set))
+    {
+        switch (set)
+        {
+        case GPRRegSet:    return WriteGPR();
+        case FPURegSet:    return WriteFPU();
+        case EXCRegSet:    return WriteEXC();
+        default: break;
+        }
+    }
+    return KERN_INVALID_ARGUMENT;
+}
+
+bool
+RegisterContextMach_i386::ReadRegisterValue (uint32_t reg, Scalar &value)
+{
+    int set = RegisterContextMach_i386::GetSetForNativeRegNum (reg);
+
+    if (set == -1)
+        return false;
+
+    if (ReadRegisterSet(set, false) != KERN_SUCCESS)
+        return false;
+
+    switch (reg)
+    {
+    case gpr_eax:
+    case gpr_ebx:
+    case gpr_ecx:
+    case gpr_edx:
+    case gpr_edi:
+    case gpr_esi:
+    case gpr_ebp:
+    case gpr_esp:
+    case gpr_ss:
+    case gpr_eflags:
+    case gpr_eip:
+    case gpr_cs:
+    case gpr_ds:
+    case gpr_es:
+    case gpr_fs:
+    case gpr_gs:
+        value = (&gpr.eax)[reg - gpr_eax];
+        break;
+
+    case fpu_fcw:
+        value = fpu.fcw;
+        break;
+
+    case fpu_fsw:
+        value = fpu.fsw;
+        break;
+
+    case fpu_ftw:
+        value  = fpu.ftw;
+        break;
+
+    case fpu_fop:
+        value = fpu.fop;
+        break;
+
+    case fpu_ip:
+        value = fpu.ip;
+        break;
+
+    case fpu_cs:
+        value = fpu.cs;
+        break;
+
+    case fpu_dp:
+        value = fpu.dp;
+        break;
+
+    case fpu_ds:
+        value = fpu.ds;
+        break;
+
+    case fpu_mxcsr:
+        value = fpu.mxcsr;
+        break;
+
+    case fpu_mxcsrmask:
+        value = fpu.mxcsrmask;
+        break;
+
+    case fpu_stmm0:
+    case fpu_stmm1:
+    case fpu_stmm2:
+    case fpu_stmm3:
+    case fpu_stmm4:
+    case fpu_stmm5:
+    case fpu_stmm6:
+    case fpu_stmm7:
+        // These values don't fit into scalar types,
+        // RegisterContext::ReadRegisterBytes() must be used for these
+        // registers
+        //::memcpy (reg_value.value.vector.uint8, fpu.stmm[reg - fpu_stmm0].bytes, 10);
+        return false;
+
+    case fpu_xmm0:
+    case fpu_xmm1:
+    case fpu_xmm2:
+    case fpu_xmm3:
+    case fpu_xmm4:
+    case fpu_xmm5:
+    case fpu_xmm6:
+    case fpu_xmm7:
+        // These values don't fit into scalar types, RegisterContext::ReadRegisterBytes()
+        // must be used for these registers
+        //::memcpy (reg_value.value.vector.uint8, fpu.xmm[reg - fpu_xmm0].bytes, 16);
+        return false;
+
+    case exc_trapno:
+        value = exc.trapno;
+        break;
+
+    case exc_err:
+        value = exc.err;
+        break;
+
+    case exc_faultvaddr:
+        value = exc.faultvaddr;
+        break;
+
+    default:
+        return false;
+    }
+    return true;
+}
+
+
+bool
+RegisterContextMach_i386::WriteRegisterValue (uint32_t reg, const Scalar &value)
+{
+    int set = GetSetForNativeRegNum (reg);
+
+    if (set == -1)
+        return false;
+
+    if (ReadRegisterSet(set, false) != KERN_SUCCESS)
+        return false;
+
+    switch (reg)
+    {
+    case gpr_eax:
+    case gpr_ebx:
+    case gpr_ecx:
+    case gpr_edx:
+    case gpr_edi:
+    case gpr_esi:
+    case gpr_ebp:
+    case gpr_esp:
+    case gpr_ss:
+    case gpr_eflags:
+    case gpr_eip:
+    case gpr_cs:
+    case gpr_ds:
+    case gpr_es:
+    case gpr_fs:
+    case gpr_gs:
+        (&gpr.eax)[reg - gpr_eax] = value.UInt(0);
+        break;
+
+    case fpu_fcw:
+        fpu.fcw = value.UInt(0);
+        break;
+
+    case fpu_fsw:
+        fpu.fsw = value.UInt(0);
+        break;
+
+    case fpu_ftw:
+        fpu.ftw = value.UInt(0);
+        break;
+
+    case fpu_fop:
+        fpu.fop = value.UInt(0);
+        break;
+
+    case fpu_ip:
+        fpu.ip = value.UInt(0);
+        break;
+
+    case fpu_cs:
+        fpu.cs = value.UInt(0);
+        break;
+
+    case fpu_dp:
+        fpu.dp = value.UInt(0);
+        break;
+
+    case fpu_ds:
+        fpu.ds = value.UInt(0);
+        break;
+
+    case fpu_mxcsr:
+        fpu.mxcsr = value.UInt(0);
+        break;
+
+    case fpu_mxcsrmask:
+        fpu.mxcsrmask = value.UInt(0);
+        break;
+
+    case fpu_stmm0:
+    case fpu_stmm1:
+    case fpu_stmm2:
+    case fpu_stmm3:
+    case fpu_stmm4:
+    case fpu_stmm5:
+    case fpu_stmm6:
+    case fpu_stmm7:
+        // These values don't fit into scalar types, RegisterContext::ReadRegisterBytes()
+        // must be used for these registers
+        //::memcpy (fpu.stmm[reg - fpu_stmm0].bytes, reg_value.value.vector.uint8, 10);
+        return false;
+
+    case fpu_xmm0:
+    case fpu_xmm1:
+    case fpu_xmm2:
+    case fpu_xmm3:
+    case fpu_xmm4:
+    case fpu_xmm5:
+    case fpu_xmm6:
+    case fpu_xmm7:
+        // These values don't fit into scalar types, RegisterContext::ReadRegisterBytes()
+        // must be used for these registers
+        //::memcpy (fpu.xmm[reg - fpu_xmm0].bytes, reg_value.value.vector.uint8, 16);
+        return false;
+
+    case exc_trapno:
+        exc.trapno = value.UInt(0);
+        break;
+
+    case exc_err:
+        exc.err = value.UInt(0);
+        break;
+
+    case exc_faultvaddr:
+        exc.faultvaddr = value.UInt(0);
+        break;
+
+    default:
+        return false;
+    }
+    return WriteRegisterSet(set) == KERN_SUCCESS;
+}
+
+bool
+RegisterContextMach_i386::ReadRegisterBytes (uint32_t reg, DataExtractor &data)
+{
+    int set = RegisterContextMach_i386::GetSetForNativeRegNum (reg);
+    if (set == -1)
+        return false;
+
+    if (ReadRegisterSet(set, false) != KERN_SUCCESS)
+        return false;
+
+    const RegisterInfo * reg_info = GetRegisterInfoAtIndex (reg);
+    if (reg_info == NULL)
+        return false;
+
+    switch (reg)
+    {
+    case gpr_eax:
+    case gpr_ebx:
+    case gpr_ecx:
+    case gpr_edx:
+    case gpr_edi:
+    case gpr_esi:
+    case gpr_ebp:
+    case gpr_esp:
+    case gpr_ss:
+    case gpr_eflags:
+    case gpr_eip:
+    case gpr_cs:
+    case gpr_ds:
+    case gpr_es:
+    case gpr_fs:
+    case gpr_gs:
+        data.SetData(&gpr.eax + reg - gpr_eax, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_fcw:
+        data.SetData(&fpu.fcw, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_fsw:
+        data.SetData(&fpu.fsw, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_ftw:
+        data.SetData(&fpu.ftw, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_fop:
+        data.SetData(&fpu.fop, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_ip:
+        data.SetData(&fpu.ip, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_cs:
+        data.SetData(&fpu.cs, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_dp:
+        data.SetData(&fpu.dp, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_ds:
+        data.SetData(&fpu.ds, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_mxcsr:
+        data.SetData(&fpu.mxcsr, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_mxcsrmask:
+        data.SetData(&fpu.mxcsrmask, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_stmm0:
+    case fpu_stmm1:
+    case fpu_stmm2:
+    case fpu_stmm3:
+    case fpu_stmm4:
+    case fpu_stmm5:
+    case fpu_stmm6:
+    case fpu_stmm7:
+        data.SetData(fpu.stmm[reg - fpu_stmm0].bytes, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_xmm0:
+    case fpu_xmm1:
+    case fpu_xmm2:
+    case fpu_xmm3:
+    case fpu_xmm4:
+    case fpu_xmm5:
+    case fpu_xmm6:
+    case fpu_xmm7:
+        data.SetData(fpu.xmm[reg - fpu_xmm0].bytes, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case exc_trapno:
+        data.SetData(&exc.trapno, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case exc_err:
+        data.SetData(&exc.err, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case exc_faultvaddr:
+        data.SetData(&exc.faultvaddr, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    default:
+        return false;
+    }
+    return true;
+}
+
+bool
+RegisterContextMach_i386::WriteRegisterBytes (uint32_t reg, DataExtractor &data, uint32_t data_offset)
+{
+    int set = GetSetForNativeRegNum (reg);
+
+    if (set == -1)
+        return false;
+
+    if (ReadRegisterSet(set, false) != KERN_SUCCESS)
+        return false;
+
+
+    const RegisterInfo * reg_info = GetRegisterInfoAtIndex (reg);
+    if (reg_info == NULL && data.ValidOffsetForDataOfSize(data_offset, reg_info->byte_size))
+        return false;
+
+    uint32_t offset = data_offset;
+    switch (reg)
+    {
+    case gpr_eax:
+    case gpr_ebx:
+    case gpr_ecx:
+    case gpr_edx:
+    case gpr_edi:
+    case gpr_esi:
+    case gpr_ebp:
+    case gpr_esp:
+    case gpr_ss:
+    case gpr_eflags:
+    case gpr_eip:
+    case gpr_cs:
+    case gpr_ds:
+    case gpr_es:
+    case gpr_fs:
+    case gpr_gs:
+        (&gpr.eax)[reg - gpr_eax] = data.GetU32 (&offset);
+        break;
+
+    case fpu_fcw:
+        fpu.fcw = data.GetU16(&offset);
+        break;
+
+    case fpu_fsw:
+        fpu.fsw = data.GetU16(&offset);
+        break;
+
+    case fpu_ftw:
+        fpu.ftw = data.GetU8(&offset);
+        break;
+
+    case fpu_fop:
+        fpu.fop = data.GetU16(&offset);
+        break;
+
+    case fpu_ip:
+        fpu.ip = data.GetU32(&offset);
+        break;
+
+    case fpu_cs:
+        fpu.cs = data.GetU16(&offset);
+        break;
+
+    case fpu_dp:
+        fpu.dp = data.GetU32(&offset);
+        break;
+
+    case fpu_ds:
+        fpu.ds = data.GetU16(&offset);
+        break;
+
+    case fpu_mxcsr:
+        fpu.mxcsr = data.GetU32(&offset);
+        break;
+
+    case fpu_mxcsrmask:
+        fpu.mxcsrmask = data.GetU32(&offset);
+        break;
+
+    case fpu_stmm0:
+    case fpu_stmm1:
+    case fpu_stmm2:
+    case fpu_stmm3:
+    case fpu_stmm4:
+    case fpu_stmm5:
+    case fpu_stmm6:
+    case fpu_stmm7:
+        ::memcpy (fpu.stmm[reg - fpu_stmm0].bytes, data.PeekData(offset, reg_info->byte_size), reg_info->byte_size);
+        return false;
+
+    case fpu_xmm0:
+    case fpu_xmm1:
+    case fpu_xmm2:
+    case fpu_xmm3:
+    case fpu_xmm4:
+    case fpu_xmm5:
+    case fpu_xmm6:
+    case fpu_xmm7:
+        // These values don't fit into scalar types, RegisterContext::ReadRegisterBytes()
+        // must be used for these registers
+        ::memcpy (fpu.xmm[reg - fpu_xmm0].bytes, data.PeekData(offset, reg_info->byte_size), reg_info->byte_size);
+        return false;
+
+    case exc_trapno:
+        exc.trapno = data.GetU32 (&offset);
+        break;
+
+    case exc_err:
+        exc.err = data.GetU32 (&offset);
+        break;
+
+    case exc_faultvaddr:
+        exc.faultvaddr = data.GetU32 (&offset);
+        break;
+
+    default:
+        return false;
+    }
+    return WriteRegisterSet(set) == KERN_SUCCESS;
+}
+
+bool
+RegisterContextMach_i386::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
+{
+    data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
+    if (data_sp &&
+        ReadGPR (false) == KERN_SUCCESS &&
+        ReadFPU (false) == KERN_SUCCESS &&
+        ReadEXC (false) == KERN_SUCCESS)
+    {
+        uint8_t *dst = data_sp->GetBytes();
+        ::memcpy (dst, &gpr, sizeof(gpr));
+        dst += sizeof(gpr);
+
+        ::memcpy (dst, &fpu, sizeof(fpu));
+        dst += sizeof(gpr);
+
+        ::memcpy (dst, &exc, sizeof(exc));
+        return true;
+    }
+    return false;
+}
+
+bool
+RegisterContextMach_i386::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
+{
+    if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
+    {
+        const uint8_t *src = data_sp->GetBytes();
+        ::memcpy (&gpr, src, sizeof(gpr));
+        src += sizeof(gpr);
+
+        ::memcpy (&fpu, src, sizeof(fpu));
+        src += sizeof(gpr);
+
+        ::memcpy (&exc, src, sizeof(exc));
+        uint32_t success_count = 0;
+        if (WriteGPR() == KERN_SUCCESS)
+            ++success_count;
+        if (WriteFPU() == KERN_SUCCESS)
+            ++success_count;
+        if (WriteEXC() == KERN_SUCCESS)
+            ++success_count;
+        return success_count == 3;
+    }
+    return false;
+}
+
+
+uint32_t
+RegisterContextMach_i386::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t reg)
+{
+    if (kind == eRegisterKindGeneric)
+    {
+        switch (reg)
+        {
+        case LLDB_REGNUM_GENERIC_PC:        return gpr_eip;
+        case LLDB_REGNUM_GENERIC_SP:        return gpr_esp;
+        case LLDB_REGNUM_GENERIC_FP:        return gpr_ebp;
+        case LLDB_REGNUM_GENERIC_FLAGS:     return gpr_eflags;
+        case LLDB_REGNUM_GENERIC_RA:
+        default:
+            break;
+        }
+    }
+    else if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
+    {
+        switch (reg)
+        {
+        case dwarf_eax:     return gpr_eax;
+        case dwarf_ecx:     return gpr_ecx;
+        case dwarf_edx:     return gpr_edx;
+        case dwarf_ebx:     return gpr_ebx;
+        case dwarf_esp:     return gpr_esp;
+        case dwarf_ebp:     return gpr_ebp;
+        case dwarf_esi:     return gpr_esi;
+        case dwarf_edi:     return gpr_edi;
+        case dwarf_eip:     return gpr_eip;
+        case dwarf_eflags:  return gpr_eflags;
+        case dwarf_stmm0:   return fpu_stmm0;
+        case dwarf_stmm1:   return fpu_stmm1;
+        case dwarf_stmm2:   return fpu_stmm2;
+        case dwarf_stmm3:   return fpu_stmm3;
+        case dwarf_stmm4:   return fpu_stmm4;
+        case dwarf_stmm5:   return fpu_stmm5;
+        case dwarf_stmm6:   return fpu_stmm6;
+        case dwarf_stmm7:   return fpu_stmm7;
+        case dwarf_xmm0:    return fpu_xmm0;
+        case dwarf_xmm1:    return fpu_xmm1;
+        case dwarf_xmm2:    return fpu_xmm2;
+        case dwarf_xmm3:    return fpu_xmm3;
+        case dwarf_xmm4:    return fpu_xmm4;
+        case dwarf_xmm5:    return fpu_xmm5;
+        case dwarf_xmm6:    return fpu_xmm6;
+        case dwarf_xmm7:    return fpu_xmm7;
+        default:
+            break;
+        }
+    }
+    else if (kind == eRegisterKindGDB)
+    {
+        switch (reg)
+        {
+        case gdb_eax     : return gpr_eax;
+        case gdb_ebx     : return gpr_ebx;
+        case gdb_ecx     : return gpr_ecx;
+        case gdb_edx     : return gpr_edx;
+        case gdb_esi     : return gpr_esi;
+        case gdb_edi     : return gpr_edi;
+        case gdb_ebp     : return gpr_ebp;
+        case gdb_esp     : return gpr_esp;
+        case gdb_eip     : return gpr_eip;
+        case gdb_eflags  : return gpr_eflags;
+        case gdb_cs      : return gpr_cs;
+        case gdb_ss      : return gpr_ss;
+        case gdb_ds      : return gpr_ds;
+        case gdb_es      : return gpr_es;
+        case gdb_fs      : return gpr_fs;
+        case gdb_gs      : return gpr_gs;
+        case gdb_stmm0   : return fpu_stmm0;
+        case gdb_stmm1   : return fpu_stmm1;
+        case gdb_stmm2   : return fpu_stmm2;
+        case gdb_stmm3   : return fpu_stmm3;
+        case gdb_stmm4   : return fpu_stmm4;
+        case gdb_stmm5   : return fpu_stmm5;
+        case gdb_stmm6   : return fpu_stmm6;
+        case gdb_stmm7   : return fpu_stmm7;
+        case gdb_fctrl   : return fpu_fctrl;
+        case gdb_fstat   : return fpu_fstat;
+        case gdb_ftag    : return fpu_ftag;
+        case gdb_fiseg   : return fpu_fiseg;
+        case gdb_fioff   : return fpu_fioff;
+        case gdb_foseg   : return fpu_foseg;
+        case gdb_fooff   : return fpu_fooff;
+        case gdb_fop     : return fpu_fop;
+        case gdb_xmm0    : return fpu_xmm0;
+        case gdb_xmm1    : return fpu_xmm1;
+        case gdb_xmm2    : return fpu_xmm2;
+        case gdb_xmm3    : return fpu_xmm3;
+        case gdb_xmm4    : return fpu_xmm4;
+        case gdb_xmm5    : return fpu_xmm5;
+        case gdb_xmm6    : return fpu_xmm6;
+        case gdb_xmm7    : return fpu_xmm7;
+        case gdb_mxcsr   : return fpu_mxcsr;
+        default:
+            break;
+        }
+    }
+    return LLDB_INVALID_REGNUM;
+}
+
+
+bool
+RegisterContextMach_i386::HardwareSingleStep (bool enable)
+{
+    if (ReadGPR(false) != KERN_SUCCESS)
+        return false;
+
+    const uint32_t trace_bit = 0x100u;
+    if (enable)
+    {
+        // If the trace bit is already set, there is nothing to do
+        if (gpr.eflags & trace_bit)
+            return true;
+        else
+            gpr.eflags |= trace_bit;
+    }
+    else
+    {
+        // If the trace bit is already cleared, there is nothing to do
+        if (gpr.eflags & trace_bit)
+            gpr.eflags &= ~trace_bit;
+        else
+            return true;
+    }
+
+    return WriteGPR() == KERN_SUCCESS;
+}
+
+
+
diff --git a/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_i386.h b/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_i386.h
new file mode 100644
index 0000000..5801867
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_i386.h
@@ -0,0 +1,256 @@
+//===-- RegisterContextMach_i386.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_RegisterContextMach_i386_h_
+#define liblldb_RegisterContextMach_i386_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/RegisterContext.h"
+
+class RegisterContextMach_i386 : public lldb_private::RegisterContext
+{
+public:
+
+    RegisterContextMach_i386(lldb_private::Thread &thread,
+                             lldb_private::StackFrame *frame);
+
+    virtual
+    ~RegisterContextMach_i386();
+
+    virtual void
+    Invalidate ();
+
+    virtual size_t
+    GetRegisterCount ();
+
+    virtual const lldb::RegisterInfo *
+    GetRegisterInfoAtIndex (uint32_t reg);
+
+    virtual size_t
+    GetRegisterSetCount ();
+
+    virtual const lldb::RegisterSet *
+    GetRegisterSet (uint32_t set);
+
+    virtual bool
+    ReadRegisterValue (uint32_t reg, lldb_private::Scalar &value);
+
+    virtual bool
+    ReadRegisterBytes (uint32_t reg, lldb_private::DataExtractor &data);
+
+    virtual bool
+    ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+
+    virtual bool
+    WriteRegisterValue (uint32_t reg, const lldb_private::Scalar &value);
+
+    virtual bool
+    WriteRegisterBytes (uint32_t reg, lldb_private::DataExtractor &data, uint32_t data_offset = 0);
+
+    virtual bool
+    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+
+    virtual uint32_t
+    ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+
+    virtual bool
+    HardwareSingleStep (bool enable);
+
+    struct GPR
+    {
+        uint32_t eax;
+        uint32_t ebx;
+        uint32_t ecx;
+        uint32_t edx;
+        uint32_t edi;
+        uint32_t esi;
+        uint32_t ebp;
+        uint32_t esp;
+        uint32_t ss;
+        uint32_t eflags;
+        uint32_t eip;
+        uint32_t cs;
+        uint32_t ds;
+        uint32_t es;
+        uint32_t fs;
+        uint32_t gs;
+    };
+
+    struct MMSReg
+    {
+        uint8_t bytes[10];
+        uint8_t pad[6];
+    };
+
+    struct XMMReg
+    {
+        uint8_t bytes[16];
+    };
+
+    struct FPU
+    {
+        uint32_t    pad[2];
+        uint16_t    fcw;
+        uint16_t    fsw;
+        uint8_t     ftw;
+        uint8_t     pad1;
+        uint16_t    fop;
+        uint32_t    ip;
+        uint16_t    cs;
+        uint16_t    pad2;
+        uint32_t    dp;
+        uint16_t    ds;
+        uint16_t    pad3;
+        uint32_t    mxcsr;
+        uint32_t    mxcsrmask;
+        MMSReg      stmm[8];
+        XMMReg      xmm[8];
+        uint8_t     pad4[14*16];
+        int         pad5;
+    };
+
+    struct EXC
+    {
+        uint32_t trapno;
+        uint32_t err;
+        uint32_t faultvaddr;
+    };
+
+protected:
+
+    enum
+    {
+        GPRRegSet = 1,
+        FPURegSet = 2,
+        EXCRegSet = 3
+    };
+
+    enum
+    {
+        GPRWordCount = sizeof(GPR)/sizeof(uint32_t),
+        FPUWordCount = sizeof(FPU)/sizeof(uint32_t),
+        EXCWordCount = sizeof(EXC)/sizeof(uint32_t)
+    };
+
+    enum
+    {
+        Read = 0,
+        Write = 1,
+        kNumErrors = 2
+    };
+
+    GPR gpr;
+    FPU fpu;
+    EXC exc;
+    kern_return_t gpr_errs[2]; // Read/Write errors
+    kern_return_t fpu_errs[2]; // Read/Write errors
+    kern_return_t exc_errs[2]; // Read/Write errors
+
+    void
+    InvalidateAllRegisterStates()
+    {
+        SetError (GPRRegSet, Read, -1);
+        SetError (FPURegSet, Read, -1);
+        SetError (EXCRegSet, Read, -1);
+    }
+
+    kern_return_t
+    GetError (int flavor, uint32_t err_idx) const
+    {
+        if (err_idx < kNumErrors)
+        {
+            switch (flavor)
+            {
+            // When getting all errors, just OR all values together to see if
+            // we got any kind of error.
+            case GPRRegSet:    return gpr_errs[err_idx];
+            case FPURegSet:    return fpu_errs[err_idx];
+            case EXCRegSet:    return exc_errs[err_idx];
+            default: break;
+            }
+        }
+        return -1;
+    }
+
+    bool
+    SetError (int flavor, uint32_t err_idx, kern_return_t err)
+    {
+        if (err_idx < kNumErrors)
+        {
+            switch (flavor)
+            {
+            case GPRRegSet:
+                gpr_errs[err_idx] = err;
+                return true;
+
+            case FPURegSet:
+                fpu_errs[err_idx] = err;
+                return true;
+
+            case EXCRegSet:
+                exc_errs[err_idx] = err;
+                return true;
+
+            default: break;
+            }
+        }
+        return false;
+    }
+
+    bool
+    RegisterSetIsCached (int set) const
+    {
+        return GetError(set, Read) == KERN_SUCCESS;
+    }
+
+    void
+    LogGPR (lldb_private::Log *log, const char *title);
+
+    kern_return_t
+    ReadGPR (bool force);
+
+    kern_return_t
+    ReadFPU (bool force);
+
+    kern_return_t
+    ReadEXC (bool force);
+
+    kern_return_t
+    WriteGPR ();
+
+    kern_return_t
+    WriteFPU ();
+
+    kern_return_t
+    WriteEXC ();
+
+    kern_return_t
+    ReadRegisterSet (uint32_t set, bool force);
+
+    kern_return_t
+    WriteRegisterSet (uint32_t set);
+
+    static uint32_t
+    GetRegisterNumber (uint32_t reg_kind, uint32_t reg_num);
+
+    static int
+    GetSetForNativeRegNum (int reg_num);
+
+    static size_t
+    GetRegisterInfosCount ();
+
+    static const lldb::RegisterInfo *
+    GetRegisterInfos ();
+};
+
+#endif  // liblldb_RegisterContextMach_i386_h_
diff --git a/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_x86_64.cpp b/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_x86_64.cpp
new file mode 100644
index 0000000..a7ed32e
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_x86_64.cpp
@@ -0,0 +1,1328 @@
+//===-- RegisterContextMach_x86_64.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 <mach/thread_act.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Scalar.h"
+
+// Project includes
+#include "RegisterContextMach_x86_64.h"
+#include "ProcessMacOSXLog.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+enum
+{
+    gpr_rax = 0,
+    gpr_rbx,
+    gpr_rcx,
+    gpr_rdx,
+    gpr_rdi,
+    gpr_rsi,
+    gpr_rbp,
+    gpr_rsp,
+    gpr_r8,
+    gpr_r9,
+    gpr_r10,
+    gpr_r11,
+    gpr_r12,
+    gpr_r13,
+    gpr_r14,
+    gpr_r15,
+    gpr_rip,
+    gpr_rflags,
+    gpr_cs,
+    gpr_fs,
+    gpr_gs,
+
+    fpu_fcw,
+    fpu_fsw,
+    fpu_ftw,
+    fpu_fop,
+    fpu_ip,
+    fpu_cs,
+    fpu_dp,
+    fpu_ds,
+    fpu_mxcsr,
+    fpu_mxcsrmask,
+    fpu_stmm0,
+    fpu_stmm1,
+    fpu_stmm2,
+    fpu_stmm3,
+    fpu_stmm4,
+    fpu_stmm5,
+    fpu_stmm6,
+    fpu_stmm7,
+    fpu_xmm0,
+    fpu_xmm1,
+    fpu_xmm2,
+    fpu_xmm3,
+    fpu_xmm4,
+    fpu_xmm5,
+    fpu_xmm6,
+    fpu_xmm7,
+    fpu_xmm8,
+    fpu_xmm9,
+    fpu_xmm10,
+    fpu_xmm11,
+    fpu_xmm12,
+    fpu_xmm13,
+    fpu_xmm14,
+    fpu_xmm15,
+
+    exc_trapno,
+    exc_err,
+    exc_faultvaddr,
+
+    k_num_registers,
+
+    // Aliases
+    fpu_fctrl = fpu_fcw,
+    fpu_fstat = fpu_fsw,
+    fpu_ftag  = fpu_ftw,
+    fpu_fiseg = fpu_cs,
+    fpu_fioff = fpu_ip,
+    fpu_foseg = fpu_ds,
+    fpu_fooff = fpu_dp,
+};
+
+enum gcc_dwarf_regnums
+{
+    gcc_dwarf_gpr_rax = 0,
+    gcc_dwarf_gpr_rdx,
+    gcc_dwarf_gpr_rcx,
+    gcc_dwarf_gpr_rbx,
+    gcc_dwarf_gpr_rsi,
+    gcc_dwarf_gpr_rdi,
+    gcc_dwarf_gpr_rbp,
+    gcc_dwarf_gpr_rsp,
+    gcc_dwarf_gpr_r8,
+    gcc_dwarf_gpr_r9,
+    gcc_dwarf_gpr_r10,
+    gcc_dwarf_gpr_r11,
+    gcc_dwarf_gpr_r12,
+    gcc_dwarf_gpr_r13,
+    gcc_dwarf_gpr_r14,
+    gcc_dwarf_gpr_r15,
+    gcc_dwarf_gpr_rip,
+    gcc_dwarf_fpu_xmm0,
+    gcc_dwarf_fpu_xmm1,
+    gcc_dwarf_fpu_xmm2,
+    gcc_dwarf_fpu_xmm3,
+    gcc_dwarf_fpu_xmm4,
+    gcc_dwarf_fpu_xmm5,
+    gcc_dwarf_fpu_xmm6,
+    gcc_dwarf_fpu_xmm7,
+    gcc_dwarf_fpu_xmm8,
+    gcc_dwarf_fpu_xmm9,
+    gcc_dwarf_fpu_xmm10,
+    gcc_dwarf_fpu_xmm11,
+    gcc_dwarf_fpu_xmm12,
+    gcc_dwarf_fpu_xmm13,
+    gcc_dwarf_fpu_xmm14,
+    gcc_dwarf_fpu_xmm15,
+    gcc_dwarf_fpu_stmm0,
+    gcc_dwarf_fpu_stmm1,
+    gcc_dwarf_fpu_stmm2,
+    gcc_dwarf_fpu_stmm3,
+    gcc_dwarf_fpu_stmm4,
+    gcc_dwarf_fpu_stmm5,
+    gcc_dwarf_fpu_stmm6,
+    gcc_dwarf_fpu_stmm7,
+
+};
+
+enum gdb_regnums
+{
+    gdb_gpr_rax     =   0,
+    gdb_gpr_rbx     =   1,
+    gdb_gpr_rcx     =   2,
+    gdb_gpr_rdx     =   3,
+    gdb_gpr_rsi     =   4,
+    gdb_gpr_rdi     =   5,
+    gdb_gpr_rbp     =   6,
+    gdb_gpr_rsp     =   7,
+    gdb_gpr_r8      =   8,
+    gdb_gpr_r9      =   9,
+    gdb_gpr_r10     =  10,
+    gdb_gpr_r11     =  11,
+    gdb_gpr_r12     =  12,
+    gdb_gpr_r13     =  13,
+    gdb_gpr_r14     =  14,
+    gdb_gpr_r15     =  15,
+    gdb_gpr_rip     =  16,
+    gdb_gpr_rflags  =  17,
+    gdb_gpr_cs      =  18,
+    gdb_gpr_ss      =  19,
+    gdb_gpr_ds      =  20,
+    gdb_gpr_es      =  21,
+    gdb_gpr_fs      =  22,
+    gdb_gpr_gs      =  23,
+    gdb_fpu_stmm0   =  24,
+    gdb_fpu_stmm1   =  25,
+    gdb_fpu_stmm2   =  26,
+    gdb_fpu_stmm3   =  27,
+    gdb_fpu_stmm4   =  28,
+    gdb_fpu_stmm5   =  29,
+    gdb_fpu_stmm6   =  30,
+    gdb_fpu_stmm7   =  31,
+    gdb_fpu_fctrl   =  32,  gdb_fpu_fcw = gdb_fpu_fctrl,
+    gdb_fpu_fstat   =  33,  gdb_fpu_fsw = gdb_fpu_fstat,
+    gdb_fpu_ftag    =  34,  gdb_fpu_ftw = gdb_fpu_ftag,
+    gdb_fpu_fiseg   =  35,  gdb_fpu_cs  = gdb_fpu_fiseg,
+    gdb_fpu_fioff   =  36,  gdb_fpu_ip  = gdb_fpu_fioff,
+    gdb_fpu_foseg   =  37,  gdb_fpu_ds  = gdb_fpu_foseg,
+    gdb_fpu_fooff   =  38,  gdb_fpu_dp  = gdb_fpu_fooff,
+    gdb_fpu_fop     =  39,
+    gdb_fpu_xmm0    =  40,
+    gdb_fpu_xmm1    =  41,
+    gdb_fpu_xmm2    =  42,
+    gdb_fpu_xmm3    =  43,
+    gdb_fpu_xmm4    =  44,
+    gdb_fpu_xmm5    =  45,
+    gdb_fpu_xmm6    =  46,
+    gdb_fpu_xmm7    =  47,
+    gdb_fpu_xmm8    =  48,
+    gdb_fpu_xmm9    =  49,
+    gdb_fpu_xmm10   =  50,
+    gdb_fpu_xmm11   =  51,
+    gdb_fpu_xmm12   =  52,
+    gdb_fpu_xmm13   =  53,
+    gdb_fpu_xmm14   =  54,
+    gdb_fpu_xmm15   =  55,
+    gdb_fpu_mxcsr   =  56,
+};
+
+RegisterContextMach_x86_64::RegisterContextMach_x86_64 (Thread &thread, StackFrame *frame) :
+    RegisterContext (thread, frame),
+    gpr(),
+    fpu(),
+    exc()
+{
+    uint32_t i;
+    for (i=0; i<kNumErrors; i++)
+    {
+        gpr_errs[i] = -1;
+        fpu_errs[i] = -1;
+        exc_errs[i] = -1;
+    }
+}
+
+RegisterContextMach_x86_64::~RegisterContextMach_x86_64()
+{
+}
+
+#define GPR_OFFSET(reg) (offsetof (RegisterContextMach_x86_64::GPR, reg))
+#define FPU_OFFSET(reg) (offsetof (RegisterContextMach_x86_64::FPU, reg) + sizeof (RegisterContextMach_x86_64::GPR))
+#define EXC_OFFSET(reg) (offsetof (RegisterContextMach_x86_64::EXC, reg) + sizeof (RegisterContextMach_x86_64::GPR) + sizeof (RegisterContextMach_x86_64::FPU))
+
+// These macros will auto define the register name, alt name, register size,
+// register offset, encoding, format and native register. This ensures that
+// the register state structures are defined correctly and have the correct
+// sizes and offsets.
+#define DEFINE_GPR(reg, alt)    #reg, alt, sizeof(((RegisterContextMach_x86_64::GPR *)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, eFormatHex, gpr_##reg
+#define DEFINE_FPU_UINT(reg)    #reg, NULL, sizeof(((RegisterContextMach_x86_64::FPU *)NULL)->reg), FPU_OFFSET(reg), eEncodingUint, eFormatHex, fpu_##reg
+#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextMach_x86_64::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, fpu_##reg##i, { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, LLDB_INVALID_REGNUM, gdb_fpu_##reg##i }
+#define DEFINE_EXC(reg)         #reg, NULL, sizeof(((RegisterContextMach_x86_64::EXC *)NULL)->reg), EXC_OFFSET(reg), eEncodingUint, eFormatHex, exc_##reg
+
+#define REG_CONTEXT_SIZE (sizeof (RegisterContextMach_x86_64::GPR) + sizeof (RegisterContextMach_x86_64::FPU) + sizeof (RegisterContextMach_x86_64::EXC))
+
+// General purpose registers for 64 bit
+static RegisterInfo g_register_infos[] =
+{
+//  Macro auto defines most stuff   GCC REG KIND NUM        DWARF REG KIND NUM  GENERIC REG KIND NUM        GDB REG KIND NUM
+//  =============================== ======================= =================== ==========================  ==========================
+    { DEFINE_GPR (rax   , NULL)     , { gcc_dwarf_gpr_rax   , gcc_dwarf_gpr_rax , LLDB_INVALID_REGNUM           , gdb_gpr_rax   }},
+    { DEFINE_GPR (rbx   , NULL)     , { gcc_dwarf_gpr_rbx   , gcc_dwarf_gpr_rbx , LLDB_INVALID_REGNUM           , gdb_gpr_rbx   }},
+    { DEFINE_GPR (rcx   , NULL)     , { gcc_dwarf_gpr_rcx   , gcc_dwarf_gpr_rcx , LLDB_INVALID_REGNUM           , gdb_gpr_rcx   }},
+    { DEFINE_GPR (rdx   , NULL)     , { gcc_dwarf_gpr_rdx   , gcc_dwarf_gpr_rdx , LLDB_INVALID_REGNUM           , gdb_gpr_rdx   }},
+    { DEFINE_GPR (rdi   , NULL)     , { gcc_dwarf_gpr_rdi   , gcc_dwarf_gpr_rdi , LLDB_INVALID_REGNUM           , gdb_gpr_rdi   }},
+    { DEFINE_GPR (rsi   , NULL)     , { gcc_dwarf_gpr_rsi   , gcc_dwarf_gpr_rsi , LLDB_INVALID_REGNUM           , gdb_gpr_rsi   }},
+    { DEFINE_GPR (rbp   , "fp")     , { gcc_dwarf_gpr_rbp   , gcc_dwarf_gpr_rbp , LLDB_REGNUM_GENERIC_FP        , gdb_gpr_rbp   }},
+    { DEFINE_GPR (rsp   , "sp")     , { gcc_dwarf_gpr_rsp   , gcc_dwarf_gpr_rsp , LLDB_REGNUM_GENERIC_SP        , gdb_gpr_rsp   }},
+    { DEFINE_GPR (r8    , NULL)     , { gcc_dwarf_gpr_r8    , gcc_dwarf_gpr_r8  , LLDB_INVALID_REGNUM           , gdb_gpr_r8    }},
+    { DEFINE_GPR (r9    , NULL)     , { gcc_dwarf_gpr_r9    , gcc_dwarf_gpr_r9  , LLDB_INVALID_REGNUM           , gdb_gpr_r9    }},
+    { DEFINE_GPR (r10   , NULL)     , { gcc_dwarf_gpr_r10   , gcc_dwarf_gpr_r10 , LLDB_INVALID_REGNUM           , gdb_gpr_r10   }},
+    { DEFINE_GPR (r11   , NULL)     , { gcc_dwarf_gpr_r11   , gcc_dwarf_gpr_r11 , LLDB_INVALID_REGNUM           , gdb_gpr_r11   }},
+    { DEFINE_GPR (r12   , NULL)     , { gcc_dwarf_gpr_r12   , gcc_dwarf_gpr_r12 , LLDB_INVALID_REGNUM           , gdb_gpr_r12   }},
+    { DEFINE_GPR (r13   , NULL)     , { gcc_dwarf_gpr_r13   , gcc_dwarf_gpr_r13 , LLDB_INVALID_REGNUM           , gdb_gpr_r13   }},
+    { DEFINE_GPR (r14   , NULL)     , { gcc_dwarf_gpr_r14   , gcc_dwarf_gpr_r14 , LLDB_INVALID_REGNUM           , gdb_gpr_r14   }},
+    { DEFINE_GPR (r15   , NULL)     , { gcc_dwarf_gpr_r15   , gcc_dwarf_gpr_r15 , LLDB_INVALID_REGNUM           , gdb_gpr_r15   }},
+    { DEFINE_GPR (rip   , "pc")     , { gcc_dwarf_gpr_rip   , gcc_dwarf_gpr_rip , LLDB_REGNUM_GENERIC_PC        , gdb_gpr_rip   }},
+    { DEFINE_GPR (rflags, "flags")  , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM   , LLDB_REGNUM_GENERIC_FLAGS , gdb_gpr_rflags}},
+    { DEFINE_GPR (cs    , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM   , LLDB_INVALID_REGNUM           , gdb_gpr_cs    }},
+    { DEFINE_GPR (fs    , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM   , LLDB_INVALID_REGNUM           , gdb_gpr_fs    }},
+    { DEFINE_GPR (gs    , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM   , LLDB_INVALID_REGNUM           , gdb_gpr_gs    }},
+
+    { DEFINE_FPU_UINT(fcw)          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM         , gdb_fpu_fcw       }},
+    { DEFINE_FPU_UINT(fsw)          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM         , gdb_fpu_fsw       }},
+    { DEFINE_FPU_UINT(ftw)          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM         , gdb_fpu_ftw       }},
+    { DEFINE_FPU_UINT(fop)          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM         , gdb_fpu_fop       }},
+    { DEFINE_FPU_UINT(ip)           , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM         , gdb_fpu_ip        }},
+    { DEFINE_FPU_UINT(cs)           , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM         , gdb_fpu_cs        }},
+    { DEFINE_FPU_UINT(dp)           , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM         , gdb_fpu_dp        }},
+    { DEFINE_FPU_UINT(ds)           , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM         , gdb_fpu_ds        }},
+    { DEFINE_FPU_UINT(mxcsr)        , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM         , gdb_fpu_mxcsr     }},
+    { DEFINE_FPU_UINT(mxcsrmask)    , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM         , LLDB_INVALID_REGNUM }},
+    { DEFINE_FPU_VECT(stmm,0)   },
+    { DEFINE_FPU_VECT(stmm,1)   },
+    { DEFINE_FPU_VECT(stmm,2)   },
+    { DEFINE_FPU_VECT(stmm,3)   },
+    { DEFINE_FPU_VECT(stmm,4)   },
+    { DEFINE_FPU_VECT(stmm,5)   },
+    { DEFINE_FPU_VECT(stmm,6)   },
+    { DEFINE_FPU_VECT(stmm,7)   },
+    { DEFINE_FPU_VECT(xmm,0)    },
+    { DEFINE_FPU_VECT(xmm,1)    },
+    { DEFINE_FPU_VECT(xmm,2)    },
+    { DEFINE_FPU_VECT(xmm,3)    },
+    { DEFINE_FPU_VECT(xmm,4)    },
+    { DEFINE_FPU_VECT(xmm,5)    },
+    { DEFINE_FPU_VECT(xmm,6)    },
+    { DEFINE_FPU_VECT(xmm,7)    },
+    { DEFINE_FPU_VECT(xmm,8)    },
+    { DEFINE_FPU_VECT(xmm,9)    },
+    { DEFINE_FPU_VECT(xmm,10)   },
+    { DEFINE_FPU_VECT(xmm,11)   },
+    { DEFINE_FPU_VECT(xmm,12)   },
+    { DEFINE_FPU_VECT(xmm,13)   },
+    { DEFINE_FPU_VECT(xmm,14)   },
+    { DEFINE_FPU_VECT(xmm,15)   },
+
+    { DEFINE_EXC(trapno)            , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM   , LLDB_INVALID_REGNUM           , LLDB_INVALID_REGNUM }},
+    { DEFINE_EXC(err)               , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM   , LLDB_INVALID_REGNUM           , LLDB_INVALID_REGNUM }},
+    { DEFINE_EXC(faultvaddr)        , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM   , LLDB_INVALID_REGNUM           , LLDB_INVALID_REGNUM }}
+};
+
+static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo));
+
+
+void
+RegisterContextMach_x86_64::Invalidate ()
+{
+    InvalidateAllRegisterStates();
+}
+
+
+size_t
+RegisterContextMach_x86_64::GetRegisterCount ()
+{
+    assert(k_num_register_infos == k_num_registers);
+    return k_num_registers;
+}
+
+
+const RegisterInfo *
+RegisterContextMach_x86_64::GetRegisterInfoAtIndex (uint32_t reg)
+{
+    assert(k_num_register_infos == k_num_registers);
+    if (reg < k_num_registers)
+        return &g_register_infos[reg];
+    return NULL;
+}
+
+
+size_t
+RegisterContextMach_x86_64::GetRegisterInfosCount ()
+{
+    return k_num_register_infos;
+}
+
+const RegisterInfo *
+RegisterContextMach_x86_64::GetRegisterInfos ()
+{
+    return g_register_infos;
+}
+
+
+
+static uint32_t g_gpr_regnums[] =
+{
+    gpr_rax,
+    gpr_rbx,
+    gpr_rcx,
+    gpr_rdx,
+    gpr_rdi,
+    gpr_rsi,
+    gpr_rbp,
+    gpr_rsp,
+    gpr_r8,
+    gpr_r9,
+    gpr_r10,
+    gpr_r11,
+    gpr_r12,
+    gpr_r13,
+    gpr_r14,
+    gpr_r15,
+    gpr_rip,
+    gpr_rflags,
+    gpr_cs,
+    gpr_fs,
+    gpr_gs
+};
+
+static uint32_t g_fpu_regnums[] =
+{
+    fpu_fcw,
+    fpu_fsw,
+    fpu_ftw,
+    fpu_fop,
+    fpu_ip,
+    fpu_cs,
+    fpu_dp,
+    fpu_ds,
+    fpu_mxcsr,
+    fpu_mxcsrmask,
+    fpu_stmm0,
+    fpu_stmm1,
+    fpu_stmm2,
+    fpu_stmm3,
+    fpu_stmm4,
+    fpu_stmm5,
+    fpu_stmm6,
+    fpu_stmm7,
+    fpu_xmm0,
+    fpu_xmm1,
+    fpu_xmm2,
+    fpu_xmm3,
+    fpu_xmm4,
+    fpu_xmm5,
+    fpu_xmm6,
+    fpu_xmm7,
+    fpu_xmm8,
+    fpu_xmm9,
+    fpu_xmm10,
+    fpu_xmm11,
+    fpu_xmm12,
+    fpu_xmm13,
+    fpu_xmm14,
+    fpu_xmm15
+};
+
+static uint32_t
+g_exc_regnums[] =
+{
+    exc_trapno,
+    exc_err,
+    exc_faultvaddr
+};
+
+// Number of registers in each register set
+const size_t k_num_gpr_registers = sizeof(g_gpr_regnums) / sizeof(uint32_t);
+const size_t k_num_fpu_registers = sizeof(g_fpu_regnums) / sizeof(uint32_t);
+const size_t k_num_exc_registers = sizeof(g_exc_regnums) / sizeof(uint32_t);
+
+//----------------------------------------------------------------------
+// Register set definitions. The first definitions at register set index
+// of zero is for all registers, followed by other registers sets. The
+// register information for the all register set need not be filled in.
+//----------------------------------------------------------------------
+static const RegisterSet g_reg_sets[] =
+{
+    { "General Purpose Registers",  "gpr",  k_num_gpr_registers,    g_gpr_regnums,      },
+    { "Floating Point Registers",   "fpu",  k_num_fpu_registers,    g_fpu_regnums       },
+    { "Exception State Registers",  "exc",  k_num_exc_registers,    g_exc_regnums       }
+};
+
+const size_t k_num_regsets = sizeof(g_reg_sets) / sizeof(RegisterSet);
+
+
+size_t
+RegisterContextMach_x86_64::GetRegisterSetCount ()
+{
+    return k_num_regsets;
+}
+
+const RegisterSet *
+RegisterContextMach_x86_64::GetRegisterSet (uint32_t reg_set)
+{
+    if (reg_set < k_num_regsets)
+        return &g_reg_sets[reg_set];
+    return NULL;
+}
+
+int
+RegisterContextMach_x86_64::GetSetForNativeRegNum (int reg_num)
+{
+    if (reg_num < fpu_fcw)
+        return GPRRegSet;
+    else if (reg_num < exc_trapno)
+        return FPURegSet;
+    else if (reg_num < k_num_registers)
+        return EXCRegSet;
+    return -1;
+}
+
+void
+RegisterContextMach_x86_64::LogGPR(Log *log, const char *format, ...)
+{
+    if (log)
+    {
+        if (format)
+        {
+            va_list args;
+            va_start (args, format);
+            log->VAPrintf (format, args);
+            va_end (args);
+        }
+        for (uint32_t i=0; i<k_num_gpr_registers; i++)
+        {
+            uint32_t reg = gpr_rax + i;
+            log->Printf("%12s = 0x%16.16llx", g_register_infos[reg].name, (&gpr.rax)[reg]);
+        }
+    }
+}
+
+kern_return_t
+RegisterContextMach_x86_64::ReadGPR (bool force)
+{
+    int set = GPRRegSet;
+    if (force || !RegisterSetIsCached(set))
+    {
+        mach_msg_type_number_t count = GPRWordCount;
+        SetError(GPRRegSet, Read, ::thread_get_state(GetThreadID(), set, (thread_state_t)&gpr, &count));
+        Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_THREAD);
+        if (log)
+            LogGPR (log, "RegisterContextMach_x86_64::ReadGPR(thread = 0x%4.4x)", GetThreadID());
+    }
+    return GetError(GPRRegSet, Read);
+}
+
+kern_return_t
+RegisterContextMach_x86_64::ReadFPU (bool force)
+{
+    int set = FPURegSet;
+    if (force || !RegisterSetIsCached(set))
+    {
+        mach_msg_type_number_t count = FPUWordCount;
+        SetError(FPURegSet, Read, ::thread_get_state(GetThreadID(), set, (thread_state_t)&fpu, &count));
+    }
+    return GetError(FPURegSet, Read);
+}
+
+kern_return_t
+RegisterContextMach_x86_64::ReadEXC (bool force)
+{
+    int set = EXCRegSet;
+    if (force || !RegisterSetIsCached(set))
+    {
+        mach_msg_type_number_t count = EXCWordCount;
+        SetError(EXCRegSet, Read, ::thread_get_state(GetThreadID(), set, (thread_state_t)&exc, &count));
+    }
+    return GetError(EXCRegSet, Read);
+}
+
+kern_return_t
+RegisterContextMach_x86_64::WriteGPR ()
+{
+    int set = GPRRegSet;
+    if (!RegisterSetIsCached(set))
+    {
+        SetError (set, Write, -1);
+        return KERN_INVALID_ARGUMENT;
+    }
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_THREAD);
+    if (log)
+        LogGPR (log, "RegisterContextMach_x86_64::WriteGPR (thread = 0x%4.4x)", GetThreadID());
+    SetError (set, Write, ::thread_set_state(GetThreadID(), set, (thread_state_t)&gpr, GPRWordCount));
+    SetError (set, Read, -1);
+    return GetError (set, Write);
+}
+
+kern_return_t
+RegisterContextMach_x86_64::WriteFPU ()
+{
+    int set = FPURegSet;
+    if (!RegisterSetIsCached(set))
+    {
+        SetError (set, Write, -1);
+        return KERN_INVALID_ARGUMENT;
+    }
+    SetError (set, Write, ::thread_set_state(GetThreadID(), set, (thread_state_t)&fpu, FPUWordCount));
+    SetError (set, Read, -1);
+    return GetError (set, Write);
+}
+
+kern_return_t
+RegisterContextMach_x86_64::WriteEXC ()
+{
+    int set = EXCRegSet;
+    if (!RegisterSetIsCached(set))
+    {
+        SetError (set, Write, -1);
+        return KERN_INVALID_ARGUMENT;
+    }
+    SetError (set, Write, ::thread_set_state(GetThreadID(), set, (thread_state_t)&exc, EXCWordCount));
+    SetError (set, Read, -1);
+    return GetError (set, Write);
+}
+
+kern_return_t
+RegisterContextMach_x86_64::ReadRegisterSet(uint32_t set, bool force)
+{
+    switch (set)
+    {
+    case GPRRegSet:    return ReadGPR (force);
+    case FPURegSet:    return ReadFPU (force);
+    case EXCRegSet:    return ReadEXC (force);
+    default: break;
+    }
+    return KERN_INVALID_ARGUMENT;
+}
+
+kern_return_t
+RegisterContextMach_x86_64::WriteRegisterSet(uint32_t set)
+{
+    // Make sure we have a valid context to set.
+    switch (set)
+    {
+    case GPRRegSet:    return WriteGPR ();
+    case FPURegSet:    return WriteFPU ();
+    case EXCRegSet:    return WriteEXC ();
+    default: break;
+    }
+    return KERN_INVALID_ARGUMENT;
+}
+
+
+bool
+RegisterContextMach_x86_64::ReadRegisterValue (uint32_t reg, Scalar &value)
+{
+    int set = RegisterContextMach_x86_64::GetSetForNativeRegNum (reg);
+
+    if (set == -1)
+        return false;
+
+    if (ReadRegisterSet(set, false) != KERN_SUCCESS)
+        return false;
+
+    switch (reg)
+    {
+    case gpr_rax:
+    case gpr_rbx:
+    case gpr_rcx:
+    case gpr_rdx:
+    case gpr_rdi:
+    case gpr_rsi:
+    case gpr_rbp:
+    case gpr_rsp:
+    case gpr_r8:
+    case gpr_r9:
+    case gpr_r10:
+    case gpr_r11:
+    case gpr_r12:
+    case gpr_r13:
+    case gpr_r14:
+    case gpr_r15:
+    case gpr_rip:
+    case gpr_rflags:
+    case gpr_cs:
+    case gpr_fs:
+    case gpr_gs:
+        value = (&gpr.rax)[reg - gpr_rax];
+        break;
+
+    case fpu_fcw:
+        value = fpu.fcw;
+        break;
+
+    case fpu_fsw:
+        value = fpu.fsw;
+        break;
+
+    case fpu_ftw:
+        value = fpu.ftw;
+        break;
+
+    case fpu_fop:
+        value = fpu.fop;
+        break;
+
+    case fpu_ip:
+        value = fpu.ip;
+        break;
+
+    case fpu_cs:
+        value = fpu.cs;
+        break;
+
+    case fpu_dp:
+        value = fpu.dp;
+        break;
+
+    case fpu_ds:
+        value = fpu.ds;
+        break;
+
+    case fpu_mxcsr:
+        value = fpu.mxcsr;
+        break;
+
+    case fpu_mxcsrmask:
+        value = fpu.mxcsrmask;
+        break;
+
+    case fpu_stmm0:
+    case fpu_stmm1:
+    case fpu_stmm2:
+    case fpu_stmm3:
+    case fpu_stmm4:
+    case fpu_stmm5:
+    case fpu_stmm6:
+    case fpu_stmm7:
+        // These values don't fit into scalar types,
+        // RegisterContext::ReadRegisterBytes() must be used for these
+        // registers
+        //::memcpy (reg_value.value.vector.uint8, fpu.stmm[reg - fpu_stmm0].bytes, 10);
+        return false;
+
+    case fpu_xmm0:
+    case fpu_xmm1:
+    case fpu_xmm2:
+    case fpu_xmm3:
+    case fpu_xmm4:
+    case fpu_xmm5:
+    case fpu_xmm6:
+    case fpu_xmm7:
+    case fpu_xmm8:
+    case fpu_xmm9:
+    case fpu_xmm10:
+    case fpu_xmm11:
+    case fpu_xmm12:
+    case fpu_xmm13:
+    case fpu_xmm14:
+    case fpu_xmm15:
+        // These values don't fit into scalar types, RegisterContext::ReadRegisterBytes()
+        // must be used for these registers
+        //::memcpy (reg_value.value.vector.uint8, fpu.xmm[reg - fpu_xmm0].bytes, 16);
+        return false;
+
+    case exc_trapno:
+        value = exc.trapno;
+        break;
+
+    case exc_err:
+        value = exc.err;
+        break;
+
+    case exc_faultvaddr:
+        value = exc.faultvaddr;
+        break;
+
+    default:
+        return false;
+    }
+    return true;
+}
+
+
+bool
+RegisterContextMach_x86_64::WriteRegisterValue (uint32_t reg, const Scalar &value)
+{
+    int set = RegisterContextMach_x86_64::GetSetForNativeRegNum (reg);
+
+    if (set == -1)
+        return false;
+
+    if (ReadRegisterSet(set, false) != KERN_SUCCESS)
+        return false;
+
+    switch (reg)
+    {
+    case gpr_rax:
+    case gpr_rbx:
+    case gpr_rcx:
+    case gpr_rdx:
+    case gpr_rdi:
+    case gpr_rsi:
+    case gpr_rbp:
+    case gpr_rsp:
+    case gpr_r8:
+    case gpr_r9:
+    case gpr_r10:
+    case gpr_r11:
+    case gpr_r12:
+    case gpr_r13:
+    case gpr_r14:
+    case gpr_r15:
+    case gpr_rip:
+    case gpr_rflags:
+    case gpr_cs:
+    case gpr_fs:
+    case gpr_gs:
+        (&gpr.rax)[reg - gpr_rax] = value.ULongLong(0);
+        break;
+
+    case fpu_fcw:
+        fpu.fcw = value.UInt(0);
+        break;
+
+    case fpu_fsw:
+        fpu.fsw = value.UInt(0);
+        break;
+
+    case fpu_ftw:
+        fpu.ftw = value.UInt(0);
+        break;
+
+    case fpu_fop:
+        fpu.fop = value.UInt(0);
+        break;
+
+    case fpu_ip:
+        fpu.ip = value.UInt(0);
+        break;
+
+    case fpu_cs:
+        fpu.cs = value.UInt(0);
+        break;
+
+    case fpu_dp:
+        fpu.dp = value.UInt(0);
+        break;
+
+    case fpu_ds:
+        fpu.ds = value.UInt(0);
+        break;
+
+    case fpu_mxcsr:
+        fpu.mxcsr = value.UInt(0);
+        break;
+
+    case fpu_mxcsrmask:
+        fpu.mxcsrmask = value.UInt(0);
+        break;
+
+    case fpu_stmm0:
+    case fpu_stmm1:
+    case fpu_stmm2:
+    case fpu_stmm3:
+    case fpu_stmm4:
+    case fpu_stmm5:
+    case fpu_stmm6:
+    case fpu_stmm7:
+        // These values don't fit into scalar types, RegisterContext::ReadRegisterBytes()
+        // must be used for these registers
+        //::memcpy (fpu.stmm[reg - fpu_stmm0].bytes, reg_value.value.vector.uint8, 10);
+        return false;
+
+    case fpu_xmm0:
+    case fpu_xmm1:
+    case fpu_xmm2:
+    case fpu_xmm3:
+    case fpu_xmm4:
+    case fpu_xmm5:
+    case fpu_xmm6:
+    case fpu_xmm7:
+    case fpu_xmm8:
+    case fpu_xmm9:
+    case fpu_xmm10:
+    case fpu_xmm11:
+    case fpu_xmm12:
+    case fpu_xmm13:
+    case fpu_xmm14:
+    case fpu_xmm15:
+        // These values don't fit into scalar types, RegisterContext::ReadRegisterBytes()
+        // must be used for these registers
+        //::memcpy (fpu.xmm[reg - fpu_xmm0].bytes, reg_value.value.vector.uint8, 16);
+        return false;
+
+    case exc_trapno:
+        exc.trapno = value.UInt(0);
+        break;
+
+    case exc_err:
+        exc.err = value.UInt(0);
+        break;
+
+    case exc_faultvaddr:
+        exc.faultvaddr = value.UInt(0);
+        break;
+
+    default:
+        return false;
+    }
+    return WriteRegisterSet(set) == KERN_SUCCESS;
+}
+
+bool
+RegisterContextMach_x86_64::ReadRegisterBytes (uint32_t reg, DataExtractor &data)
+{
+    int set = RegisterContextMach_x86_64::GetSetForNativeRegNum (reg);
+    if (set == -1)
+        return false;
+
+    if (ReadRegisterSet(set, false) != KERN_SUCCESS)
+        return false;
+
+    const RegisterInfo * reg_info = GetRegisterInfoAtIndex (reg);
+    if (reg_info == NULL)
+        return false;
+
+    switch (reg)
+    {
+    case gpr_rax:
+    case gpr_rbx:
+    case gpr_rcx:
+    case gpr_rdx:
+    case gpr_rdi:
+    case gpr_rsi:
+    case gpr_rbp:
+    case gpr_rsp:
+    case gpr_r8:
+    case gpr_r9:
+    case gpr_r10:
+    case gpr_r11:
+    case gpr_r12:
+    case gpr_r13:
+    case gpr_r14:
+    case gpr_r15:
+    case gpr_rip:
+    case gpr_rflags:
+    case gpr_cs:
+    case gpr_fs:
+    case gpr_gs:
+        data.SetData(&gpr.rax + reg - gpr_rax, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_fcw:
+        data.SetData(&fpu.fcw, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_fsw:
+        data.SetData(&fpu.fsw, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_ftw:
+        data.SetData(&fpu.ftw, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_fop:
+        data.SetData(&fpu.fop, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_ip:
+        data.SetData(&fpu.ip, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_cs:
+        data.SetData(&fpu.cs, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_dp:
+        data.SetData(&fpu.dp, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_ds:
+        data.SetData(&fpu.ds, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_mxcsr:
+        data.SetData(&fpu.mxcsr, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_mxcsrmask:
+        data.SetData(&fpu.mxcsrmask, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_stmm0:
+    case fpu_stmm1:
+    case fpu_stmm2:
+    case fpu_stmm3:
+    case fpu_stmm4:
+    case fpu_stmm5:
+    case fpu_stmm6:
+    case fpu_stmm7:
+        data.SetData(fpu.stmm[reg - fpu_stmm0].bytes, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case fpu_xmm0:
+    case fpu_xmm1:
+    case fpu_xmm2:
+    case fpu_xmm3:
+    case fpu_xmm4:
+    case fpu_xmm5:
+    case fpu_xmm6:
+    case fpu_xmm7:
+    case fpu_xmm8:
+    case fpu_xmm9:
+    case fpu_xmm10:
+    case fpu_xmm11:
+    case fpu_xmm12:
+    case fpu_xmm13:
+    case fpu_xmm14:
+    case fpu_xmm15:
+        data.SetData(fpu.xmm[reg - fpu_xmm0].bytes, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case exc_trapno:
+        data.SetData(&exc.trapno, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case exc_err:
+        data.SetData(&exc.err, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    case exc_faultvaddr:
+        data.SetData(&exc.faultvaddr, reg_info->byte_size, eByteOrderHost);
+        break;
+
+    default:
+        return false;
+    }
+    return true;
+}
+
+bool
+RegisterContextMach_x86_64::WriteRegisterBytes (uint32_t reg, DataExtractor &data, uint32_t data_offset)
+{
+    int set = RegisterContextMach_x86_64::GetSetForNativeRegNum (reg);
+
+    if (set == -1)
+        return false;
+
+    if (ReadRegisterSet(set, false) != KERN_SUCCESS)
+        return false;
+
+
+    const RegisterInfo * reg_info = GetRegisterInfoAtIndex (reg);
+    if (reg_info == NULL && data.ValidOffsetForDataOfSize(data_offset, reg_info->byte_size))
+        return false;
+
+    uint32_t offset = data_offset;
+    switch (reg)
+    {
+    case gpr_rax:
+    case gpr_rbx:
+    case gpr_rcx:
+    case gpr_rdx:
+    case gpr_rdi:
+    case gpr_rsi:
+    case gpr_rbp:
+    case gpr_rsp:
+    case gpr_r8:
+    case gpr_r9:
+    case gpr_r10:
+    case gpr_r11:
+    case gpr_r12:
+    case gpr_r13:
+    case gpr_r14:
+    case gpr_r15:
+    case gpr_rip:
+    case gpr_rflags:
+    case gpr_cs:
+    case gpr_fs:
+    case gpr_gs:
+        (&gpr.rax)[reg - gpr_rax] = data.GetU32 (&offset);
+        break;
+
+    case fpu_fcw:
+        fpu.fcw = data.GetU16(&offset);
+        break;
+
+    case fpu_fsw:
+        fpu.fsw = data.GetU16(&offset);
+        break;
+
+    case fpu_ftw:
+        fpu.ftw = data.GetU8(&offset);
+        break;
+
+    case fpu_fop:
+        fpu.fop = data.GetU16(&offset);
+        break;
+
+    case fpu_ip:
+        fpu.ip = data.GetU32(&offset);
+        break;
+
+    case fpu_cs:
+        fpu.cs = data.GetU16(&offset);
+        break;
+
+    case fpu_dp:
+        fpu.dp = data.GetU32(&offset);
+        break;
+
+    case fpu_ds:
+        fpu.ds = data.GetU16(&offset);
+        break;
+
+    case fpu_mxcsr:
+        fpu.mxcsr = data.GetU32(&offset);
+        break;
+
+    case fpu_mxcsrmask:
+        fpu.mxcsrmask = data.GetU32(&offset);
+        break;
+
+    case fpu_stmm0:
+    case fpu_stmm1:
+    case fpu_stmm2:
+    case fpu_stmm3:
+    case fpu_stmm4:
+    case fpu_stmm5:
+    case fpu_stmm6:
+    case fpu_stmm7:
+        ::memcpy (fpu.stmm[reg - fpu_stmm0].bytes, data.PeekData(offset, reg_info->byte_size), reg_info->byte_size);
+        return false;
+
+    case fpu_xmm0:
+    case fpu_xmm1:
+    case fpu_xmm2:
+    case fpu_xmm3:
+    case fpu_xmm4:
+    case fpu_xmm5:
+    case fpu_xmm6:
+    case fpu_xmm7:
+    case fpu_xmm8:
+    case fpu_xmm9:
+    case fpu_xmm10:
+    case fpu_xmm11:
+    case fpu_xmm12:
+    case fpu_xmm13:
+    case fpu_xmm14:
+    case fpu_xmm15:
+        // These values don't fit into scalar types, RegisterContext::ReadRegisterBytes()
+        // must be used for these registers
+        ::memcpy (fpu.xmm[reg - fpu_xmm0].bytes, data.PeekData(offset, reg_info->byte_size), reg_info->byte_size);
+        return false;
+
+    case exc_trapno:
+        exc.trapno = data.GetU32 (&offset);
+        break;
+
+    case exc_err:
+        exc.err = data.GetU32 (&offset);
+        break;
+
+    case exc_faultvaddr:
+        exc.faultvaddr = data.GetU32 (&offset);
+        break;
+
+    default:
+        return false;
+    }
+    return WriteRegisterSet(set) == KERN_SUCCESS;
+}
+
+bool
+RegisterContextMach_x86_64::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
+{
+    data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
+    if (data_sp &&
+        ReadGPR (false) == KERN_SUCCESS &&
+        ReadFPU (false) == KERN_SUCCESS &&
+        ReadEXC (false) == KERN_SUCCESS)
+    {
+        uint8_t *dst = data_sp->GetBytes();
+        ::memcpy (dst, &gpr, sizeof(gpr));
+        dst += sizeof(gpr);
+
+        ::memcpy (dst, &fpu, sizeof(fpu));
+        dst += sizeof(gpr);
+
+        ::memcpy (dst, &exc, sizeof(exc));
+        return true;
+    }
+    return false;
+}
+
+bool
+RegisterContextMach_x86_64::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
+{
+    if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
+    {
+        const uint8_t *src = data_sp->GetBytes();
+        ::memcpy (&gpr, src, sizeof(gpr));
+        src += sizeof(gpr);
+
+        ::memcpy (&fpu, src, sizeof(fpu));
+        src += sizeof(gpr);
+
+        ::memcpy (&exc, src, sizeof(exc));
+        uint32_t success_count = 0;
+        if (WriteGPR() == KERN_SUCCESS)
+            ++success_count;
+        if (WriteFPU() == KERN_SUCCESS)
+            ++success_count;
+        if (WriteEXC() == KERN_SUCCESS)
+            ++success_count;
+        return success_count == 3;
+    }
+    return false;
+}
+
+
+uint32_t
+RegisterContextMach_x86_64::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t reg)
+{
+    if (kind == eRegisterKindGeneric)
+    {
+        switch (reg)
+        {
+        case LLDB_REGNUM_GENERIC_PC:    return gpr_rip;
+        case LLDB_REGNUM_GENERIC_SP:    return gpr_rsp;
+        case LLDB_REGNUM_GENERIC_FP:    return gpr_rbp;
+        case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags;
+        case LLDB_REGNUM_GENERIC_RA:
+        default:
+            break;
+        }
+    }
+    else if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
+    {
+        switch (reg)
+        {
+        case gcc_dwarf_gpr_rax:  return gpr_rax;
+        case gcc_dwarf_gpr_rdx:  return gpr_rdx;
+        case gcc_dwarf_gpr_rcx:  return gpr_rcx;
+        case gcc_dwarf_gpr_rbx:  return gpr_rbx;
+        case gcc_dwarf_gpr_rsi:  return gpr_rsi;
+        case gcc_dwarf_gpr_rdi:  return gpr_rdi;
+        case gcc_dwarf_gpr_rbp:  return gpr_rbp;
+        case gcc_dwarf_gpr_rsp:  return gpr_rsp;
+        case gcc_dwarf_gpr_r8:   return gpr_r8;
+        case gcc_dwarf_gpr_r9:   return gpr_r9;
+        case gcc_dwarf_gpr_r10:  return gpr_r10;
+        case gcc_dwarf_gpr_r11:  return gpr_r11;
+        case gcc_dwarf_gpr_r12:  return gpr_r12;
+        case gcc_dwarf_gpr_r13:  return gpr_r13;
+        case gcc_dwarf_gpr_r14:  return gpr_r14;
+        case gcc_dwarf_gpr_r15:  return gpr_r15;
+        case gcc_dwarf_gpr_rip:  return gpr_rip;
+        case gcc_dwarf_fpu_xmm0: return fpu_xmm0;
+        case gcc_dwarf_fpu_xmm1: return fpu_xmm1;
+        case gcc_dwarf_fpu_xmm2: return fpu_xmm2;
+        case gcc_dwarf_fpu_xmm3: return fpu_xmm3;
+        case gcc_dwarf_fpu_xmm4: return fpu_xmm4;
+        case gcc_dwarf_fpu_xmm5: return fpu_xmm5;
+        case gcc_dwarf_fpu_xmm6: return fpu_xmm6;
+        case gcc_dwarf_fpu_xmm7: return fpu_xmm7;
+        case gcc_dwarf_fpu_xmm8: return fpu_xmm8;
+        case gcc_dwarf_fpu_xmm9: return fpu_xmm9;
+        case gcc_dwarf_fpu_xmm10: return fpu_xmm10;
+        case gcc_dwarf_fpu_xmm11: return fpu_xmm11;
+        case gcc_dwarf_fpu_xmm12: return fpu_xmm12;
+        case gcc_dwarf_fpu_xmm13: return fpu_xmm13;
+        case gcc_dwarf_fpu_xmm14: return fpu_xmm14;
+        case gcc_dwarf_fpu_xmm15: return fpu_xmm15;
+        case gcc_dwarf_fpu_stmm0: return fpu_stmm0;
+        case gcc_dwarf_fpu_stmm1: return fpu_stmm1;
+        case gcc_dwarf_fpu_stmm2: return fpu_stmm2;
+        case gcc_dwarf_fpu_stmm3: return fpu_stmm3;
+        case gcc_dwarf_fpu_stmm4: return fpu_stmm4;
+        case gcc_dwarf_fpu_stmm5: return fpu_stmm5;
+        case gcc_dwarf_fpu_stmm6: return fpu_stmm6;
+        case gcc_dwarf_fpu_stmm7: return fpu_stmm7;
+        default:
+            break;
+        }
+    }
+    else if (kind == eRegisterKindGDB)
+    {
+        switch (reg)
+        {
+        case gdb_gpr_rax     : return gpr_rax;
+        case gdb_gpr_rbx     : return gpr_rbx;
+        case gdb_gpr_rcx     : return gpr_rcx;
+        case gdb_gpr_rdx     : return gpr_rdx;
+        case gdb_gpr_rsi     : return gpr_rsi;
+        case gdb_gpr_rdi     : return gpr_rdi;
+        case gdb_gpr_rbp     : return gpr_rbp;
+        case gdb_gpr_rsp     : return gpr_rsp;
+        case gdb_gpr_r8      : return gpr_r8;
+        case gdb_gpr_r9      : return gpr_r9;
+        case gdb_gpr_r10     : return gpr_r10;
+        case gdb_gpr_r11     : return gpr_r11;
+        case gdb_gpr_r12     : return gpr_r12;
+        case gdb_gpr_r13     : return gpr_r13;
+        case gdb_gpr_r14     : return gpr_r14;
+        case gdb_gpr_r15     : return gpr_r15;
+        case gdb_gpr_rip     : return gpr_rip;
+        case gdb_gpr_rflags  : return gpr_rflags;
+        case gdb_gpr_cs      : return gpr_cs;
+        case gdb_gpr_ss      : return gpr_gs;   // HACK: For now for "ss", just copy what is in "gs"
+        case gdb_gpr_ds      : return gpr_gs;   // HACK: For now for "ds", just copy what is in "gs"
+        case gdb_gpr_es      : return gpr_gs;   // HACK: For now for "es", just copy what is in "gs"
+        case gdb_gpr_fs      : return gpr_fs;
+        case gdb_gpr_gs      : return gpr_gs;
+        case gdb_fpu_stmm0   : return fpu_stmm0;
+        case gdb_fpu_stmm1   : return fpu_stmm1;
+        case gdb_fpu_stmm2   : return fpu_stmm2;
+        case gdb_fpu_stmm3   : return fpu_stmm3;
+        case gdb_fpu_stmm4   : return fpu_stmm4;
+        case gdb_fpu_stmm5   : return fpu_stmm5;
+        case gdb_fpu_stmm6   : return fpu_stmm6;
+        case gdb_fpu_stmm7   : return fpu_stmm7;
+        case gdb_fpu_fctrl   : return fpu_fctrl;
+        case gdb_fpu_fstat   : return fpu_fstat;
+        case gdb_fpu_ftag    : return fpu_ftag;
+        case gdb_fpu_fiseg   : return fpu_fiseg;
+        case gdb_fpu_fioff   : return fpu_fioff;
+        case gdb_fpu_foseg   : return fpu_foseg;
+        case gdb_fpu_fooff   : return fpu_fooff;
+        case gdb_fpu_fop     : return fpu_fop;
+        case gdb_fpu_xmm0    : return fpu_xmm0;
+        case gdb_fpu_xmm1    : return fpu_xmm1;
+        case gdb_fpu_xmm2    : return fpu_xmm2;
+        case gdb_fpu_xmm3    : return fpu_xmm3;
+        case gdb_fpu_xmm4    : return fpu_xmm4;
+        case gdb_fpu_xmm5    : return fpu_xmm5;
+        case gdb_fpu_xmm6    : return fpu_xmm6;
+        case gdb_fpu_xmm7    : return fpu_xmm7;
+        case gdb_fpu_xmm8    : return fpu_xmm8;
+        case gdb_fpu_xmm9    : return fpu_xmm9;
+        case gdb_fpu_xmm10   : return fpu_xmm10;
+        case gdb_fpu_xmm11   : return fpu_xmm11;
+        case gdb_fpu_xmm12   : return fpu_xmm12;
+        case gdb_fpu_xmm13   : return fpu_xmm13;
+        case gdb_fpu_xmm14   : return fpu_xmm14;
+        case gdb_fpu_xmm15   : return fpu_xmm15;
+        case gdb_fpu_mxcsr   : return fpu_mxcsr;
+        default:
+            break;
+        }
+    }
+    return LLDB_INVALID_REGNUM;
+}
+
+bool
+RegisterContextMach_x86_64::HardwareSingleStep (bool enable)
+{
+    if (ReadGPR(true) != KERN_SUCCESS)
+        return false;
+
+    const uint64_t trace_bit = 0x100ull;
+    if (enable)
+    {
+
+        if (gpr.rflags & trace_bit)
+            return true;    // trace bit is already set, there is nothing to do
+        else
+            gpr.rflags |= trace_bit;
+    }
+    else
+    {
+        if (gpr.rflags & trace_bit)
+            gpr.rflags &= ~trace_bit;
+        else
+            return true;    // trace bit is clear, there is nothing to do
+    }
+
+    return WriteGPR() == KERN_SUCCESS;
+}
+
diff --git a/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_x86_64.h b/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_x86_64.h
new file mode 100644
index 0000000..4f33bbd
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_x86_64.h
@@ -0,0 +1,261 @@
+//===-- RegisterContextMach_x86_64.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_RegisterContextMach_x86_64_h_
+#define liblldb_RegisterContextMach_x86_64_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/RegisterContext.h"
+
+class RegisterContextMach_x86_64 : public lldb_private::RegisterContext
+{
+public:
+    RegisterContextMach_x86_64 (lldb_private::Thread &thread,
+                                lldb_private::StackFrame *frame);
+
+    virtual
+    ~RegisterContextMach_x86_64();
+
+    virtual void
+    Invalidate ();
+
+    virtual size_t
+    GetRegisterCount ();
+
+    virtual const lldb::RegisterInfo *
+    GetRegisterInfoAtIndex (uint32_t reg);
+
+    virtual size_t
+    GetRegisterSetCount ();
+
+    virtual const lldb::RegisterSet *
+    GetRegisterSet (uint32_t set);
+
+    virtual bool
+    ReadRegisterValue (uint32_t reg, lldb_private::Scalar &value);
+
+    virtual bool
+    ReadRegisterBytes (uint32_t reg, lldb_private::DataExtractor &data);
+
+    virtual bool
+    ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+
+    virtual bool
+    WriteRegisterValue (uint32_t reg, const lldb_private::Scalar &value);
+
+    virtual bool
+    WriteRegisterBytes (uint32_t reg, lldb_private::DataExtractor &data, uint32_t data_offset = 0);
+
+    virtual bool
+    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+
+    virtual uint32_t
+    ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+
+    virtual bool
+    HardwareSingleStep (bool enable);
+
+    struct GPR
+    {
+        uint64_t rax;
+        uint64_t rbx;
+        uint64_t rcx;
+        uint64_t rdx;
+        uint64_t rdi;
+        uint64_t rsi;
+        uint64_t rbp;
+        uint64_t rsp;
+        uint64_t r8;
+        uint64_t r9;
+        uint64_t r10;
+        uint64_t r11;
+        uint64_t r12;
+        uint64_t r13;
+        uint64_t r14;
+        uint64_t r15;
+        uint64_t rip;
+        uint64_t rflags;
+        uint64_t cs;
+        uint64_t fs;
+        uint64_t gs;
+    };
+
+    struct MMSReg
+    {
+        uint8_t bytes[10];
+        uint8_t pad[6];
+    };
+
+    struct XMMReg
+    {
+        uint8_t bytes[16];
+    };
+
+    struct FPU
+    {
+        uint32_t    pad[2];
+        uint16_t    fcw;    // "fctrl"
+        uint16_t    fsw;    // "fstat"
+        uint8_t     ftw;    // "ftag"
+        uint8_t     pad1;
+        uint16_t    fop;    // "fop"
+        uint32_t    ip;     // "fioff"
+        uint16_t    cs;     // "fiseg"
+        uint16_t    pad2;
+        uint32_t    dp;     // "fooff"
+        uint16_t    ds;     // "foseg"
+        uint16_t    pad3;
+        uint32_t    mxcsr;
+        uint32_t    mxcsrmask;
+        MMSReg      stmm[8];
+        XMMReg      xmm[16];
+        uint8_t     pad4[6*16];
+        int         pad5;
+    };
+
+    struct EXC
+    {
+        uint32_t trapno;
+        uint32_t err;
+        uint64_t faultvaddr;
+    };
+
+protected:
+
+    typedef enum
+    {
+        GPRRegSet = 4,
+        FPURegSet = 5,
+        EXCRegSet = 6
+    };
+
+    enum
+    {
+        GPRWordCount = sizeof(GPR)/sizeof(uint32_t),
+        FPUWordCount = sizeof(FPU)/sizeof(uint32_t),
+        EXCWordCount = sizeof(EXC)/sizeof(uint32_t)
+    };
+
+    enum
+    {
+        Read = 0,
+        Write = 1,
+        kNumErrors = 2
+    };
+
+    GPR gpr;
+    FPU fpu;
+    EXC exc;
+    kern_return_t gpr_errs[2]; // Read/Write errors
+    kern_return_t fpu_errs[2]; // Read/Write errors
+    kern_return_t exc_errs[2]; // Read/Write errors
+
+    void
+    InvalidateAllRegisterStates()
+    {
+        SetError (GPRRegSet, Read, -1);
+        SetError (FPURegSet, Read, -1);
+        SetError (EXCRegSet, Read, -1);
+    }
+
+    kern_return_t
+    GetError (int flavor, uint32_t err_idx) const
+    {
+        if (err_idx < kNumErrors)
+        {
+            switch (flavor)
+            {
+            // When getting all errors, just OR all values together to see if
+            // we got any kind of error.
+            case GPRRegSet:    return gpr_errs[err_idx];
+            case FPURegSet:    return fpu_errs[err_idx];
+            case EXCRegSet:    return exc_errs[err_idx];
+            default: break;
+            }
+        }
+        return -1;
+    }
+
+    bool
+    SetError (int flavor, uint32_t err_idx, kern_return_t err)
+    {
+        if (err_idx < kNumErrors)
+        {
+            switch (flavor)
+            {
+            case GPRRegSet:
+                gpr_errs[err_idx] = err;
+                return true;
+
+            case FPURegSet:
+                fpu_errs[err_idx] = err;
+                return true;
+
+            case EXCRegSet:
+                exc_errs[err_idx] = err;
+                return true;
+
+            default: break;
+            }
+        }
+        return false;
+    }
+
+    bool
+    RegisterSetIsCached (int set) const
+    {
+        return GetError(set, Read) == KERN_SUCCESS;
+    }
+
+    void
+    LogGPR (lldb_private::Log *log, const char *format, ...);
+
+    kern_return_t
+    ReadGPR (bool force);
+
+    kern_return_t
+    ReadFPU (bool force);
+
+    kern_return_t
+    ReadEXC (bool force);
+
+    kern_return_t
+    WriteGPR ();
+
+    kern_return_t
+    WriteFPU ();
+
+    kern_return_t
+    WriteEXC ();
+
+    kern_return_t
+    ReadRegisterSet (uint32_t set, bool force);
+
+    kern_return_t
+    WriteRegisterSet (uint32_t set);
+
+    static uint32_t
+    GetRegisterNumber (uint32_t reg_kind, uint32_t reg_num);
+
+    static int
+    GetSetForNativeRegNum (int reg_num);
+
+    static size_t
+    GetRegisterInfosCount ();
+
+    static const lldb::RegisterInfo *
+    GetRegisterInfos ();
+
+};
+
+#endif  // liblldb_RegisterContextMach_x86_64_h_
diff --git a/source/Plugins/Process/MacOSX-User/source/ThreadMacOSX.cpp b/source/Plugins/Process/MacOSX-User/source/ThreadMacOSX.cpp
new file mode 100644
index 0000000..46d84a8
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/ThreadMacOSX.cpp
@@ -0,0 +1,769 @@
+//===-- ThreadMacOSX.cpp ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "ThreadMacOSX.h"
+
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "ProcessMacOSX.h"
+#include "ProcessMacOSXLog.h"
+#include "MachThreadContext.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Breakpoint/WatchpointLocation.h"
+#include "lldb/Core/StreamString.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Thread Registers
+//----------------------------------------------------------------------
+
+ThreadMacOSX::ThreadMacOSX (ProcessMacOSX &process, lldb::tid_t tid) :
+    Thread(process, tid),
+    m_fp_pc_pairs(),
+    m_basic_info(),
+    m_suspend_count(0),
+    m_stop_exception(),
+    m_context()
+{
+    ProcessMacOSX::CreateArchCalback create_arch_callback = process.GetArchCreateCallback();
+    assert(create_arch_callback != NULL);
+    m_context.reset(create_arch_callback(process.GetArchSpec(), *this));
+    assert(m_context.get() != NULL);
+    m_context->InitializeInstance();
+    ::bzero (&m_basic_info, sizeof (m_basic_info));
+    ::bzero (&m_ident_info, sizeof (m_ident_info));
+    ::bzero (&m_proc_threadinfo, sizeof (m_proc_threadinfo));
+    ProcessMacOSXLog::LogIf(PD_LOG_THREAD | PD_LOG_VERBOSE, "ThreadMacOSX::ThreadMacOSX ( pid = %i, tid = 0x%4.4x, )", m_process.GetID(), GetID());
+}
+
+ThreadMacOSX::~ThreadMacOSX ()
+{
+}
+
+#if defined (__i386__) || defined (__x86_64__)
+    #define MACH_SOFTWARE_BREAKPOINT_DATA_0 EXC_I386_BPT
+    #define MACH_TRAP_DATA_0 EXC_I386_SGL
+#elif defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__)
+    #define MACH_SOFTWARE_BREAKPOINT_DATA_0 EXC_PPC_BREAKPOINT
+
+#elif defined (__arm__)
+    #define MACH_SOFTWARE_BREAKPOINT_DATA_0 EXC_ARM_BREAKPOINT
+#endif
+
+
+bool
+ThreadMacOSX::GetRawStopReason (Thread::StopInfo *stop_info )
+{
+    stop_info->SetThread(this);
+
+    bool success = GetStopException().GetStopInfo(stop_info);
+
+
+#if defined (MACH_SOFTWARE_BREAKPOINT_DATA_0) || defined (MACH_TRAP_DATA_0)
+    if (stop_info->GetStopReason() == eStopReasonException)
+    {
+        if (stop_info->GetExceptionType() == EXC_BREAKPOINT && stop_info->GetExceptionDataCount() == 2)
+        {
+            const lldb::addr_t data_0 = stop_info->GetExceptionDataAtIndex(0);
+#if defined (MACH_SOFTWARE_BREAKPOINT_DATA_0)
+            if (data_0 == MACH_SOFTWARE_BREAKPOINT_DATA_0)
+            {
+                lldb::addr_t pc = GetRegisterContext()->GetPC();
+                lldb::user_id_t break_id = m_process.GetBreakpointSiteList().FindIDByAddress(pc);
+                if (break_id != LLDB_INVALID_BREAK_ID)
+                {
+                    stop_info->Clear ();
+                    stop_info->SetStopReasonWithBreakpointSiteID (break_id);
+                    return success;
+                }
+            }
+#endif
+#if defined (MACH_TRAP_DATA_0)
+            if (data_0 == MACH_TRAP_DATA_0)
+            {
+                stop_info->Clear ();
+                stop_info->SetStopReasonToTrace ();
+                return success;
+            }
+#endif
+        }
+    }
+#endif
+
+    if (stop_info->GetStopReason() == eStopReasonException)
+    {
+        if (stop_info->GetExceptionType() == EXC_SOFTWARE &&
+            stop_info->GetExceptionDataCount() == 2 &&
+            stop_info->GetExceptionDataAtIndex(0) == EXC_SOFT_SIGNAL)
+        {
+            int signo = stop_info->GetExceptionDataAtIndex(1);
+            stop_info->Clear ();
+            stop_info->SetStopReasonWithSignal (signo);
+        }
+    }
+    else
+    {
+        stop_info->SetStopReasonToNone();
+    }
+
+    return success;
+}
+
+const char *
+ThreadMacOSX::GetInfo ()
+{
+    return GetBasicInfoAsString();
+}
+
+bool
+ThreadMacOSX::GetIdentifierInfo ()
+{
+#ifdef THREAD_IDENTIFIER_INFO_COUNT
+    if (m_ident_info.thread_id == 0)
+    {
+        mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;
+        return ::thread_info (GetID(), THREAD_IDENTIFIER_INFO, (thread_info_t) &m_ident_info, &count) == KERN_SUCCESS;
+    }
+#else
+    //m_error.SetErrorString("Thread_info doesn't support THREAD_IDENTIFIER_INFO.");
+#endif
+
+    return false;
+}
+
+const char *
+ThreadMacOSX::GetDispatchQueueName()
+{
+    if (GetIdentifierInfo ())
+    {
+        if (m_ident_info.dispatch_qaddr == 0)
+            return NULL;
+
+        uint8_t memory_buffer[8];
+        DataExtractor data(memory_buffer, sizeof(memory_buffer), m_process.GetByteOrder(), m_process.GetAddressByteSize());
+        ModuleSP module_sp(m_process.GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libSystem.B.dylib")));
+        if (module_sp.get() == NULL)
+            return NULL;
+
+        lldb::addr_t dispatch_queue_offsets_addr = LLDB_INVALID_ADDRESS;
+        const Symbol *dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (ConstString("dispatch_queue_offsets"), eSymbolTypeData);
+        if (dispatch_queue_offsets_symbol)
+            dispatch_queue_offsets_addr = dispatch_queue_offsets_symbol->GetValue().GetLoadAddress(&GetProcess());
+
+        if (dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS)
+            return NULL;
+
+        // Excerpt from src/queue_private.h
+        struct dispatch_queue_offsets_s
+        {
+            uint16_t dqo_version;
+            uint16_t dqo_label;
+            uint16_t dqo_label_size;
+        } dispatch_queue_offsets;
+
+        Error error;
+        if (m_process.ReadMemory (dispatch_queue_offsets_addr, memory_buffer, sizeof(dispatch_queue_offsets), error) == sizeof(dispatch_queue_offsets))
+        {
+            uint32_t data_offset = 0;
+            if (data.GetU16(&data_offset, &dispatch_queue_offsets.dqo_version, sizeof(dispatch_queue_offsets)/sizeof(uint16_t)))
+            {
+                if (m_process.ReadMemory (m_ident_info.dispatch_qaddr, &memory_buffer, data.GetAddressByteSize(), error) == data.GetAddressByteSize())
+                {
+                    data_offset = 0;
+                    lldb::addr_t queue_addr = data.GetAddress(&data_offset);
+                    lldb::addr_t label_addr = queue_addr + dispatch_queue_offsets.dqo_label;
+                    const size_t chunk_size = 32;
+                    uint32_t label_pos = 0;
+                    m_dispatch_queue_name.resize(chunk_size, '\0');
+                    while (1)
+                    {
+                        size_t bytes_read = m_process.ReadMemory (label_addr + label_pos, &m_dispatch_queue_name[label_pos], chunk_size, error);
+
+                        if (bytes_read <= 0)
+                            break;
+
+                        if (m_dispatch_queue_name.find('\0', label_pos) != std::string::npos)
+                            break;
+                        label_pos += bytes_read;
+                    }
+                    m_dispatch_queue_name.erase(m_dispatch_queue_name.find('\0'));
+                }
+            }
+        }
+    }
+
+    if (m_dispatch_queue_name.empty())
+        return NULL;
+    return m_dispatch_queue_name.c_str();
+}
+
+const char *
+ThreadMacOSX::GetName ()
+{
+    if (GetIdentifierInfo ())
+        ::proc_pidinfo (m_process.GetID(), PROC_PIDTHREADINFO, m_ident_info.thread_handle, &m_proc_threadinfo, sizeof (m_proc_threadinfo));
+
+    // No thread name, lets return the queue name instead
+    if (m_proc_threadinfo.pth_name[0] == '\0')
+        return GetDispatchQueueName();
+
+    // Return the thread name if there was one
+    if (m_proc_threadinfo.pth_name[0])
+        return m_proc_threadinfo.pth_name;
+    return NULL;
+}
+
+bool
+ThreadMacOSX::WillResume (StateType resume_state)
+{
+    ThreadWillResume(resume_state);
+    Thread::WillResume(resume_state);
+    return true;
+}
+
+void
+ThreadMacOSX::RefreshStateAfterStop()
+{
+    // Invalidate all registers in our register context
+    GetRegisterContext()->Invalidate();
+
+    m_context->RefreshStateAfterStop();
+
+    // We may have suspended this thread so the primary thread could step
+    // without worrying about race conditions, so lets restore our suspend
+    // count.
+    RestoreSuspendCount();
+
+    // Update the basic information for a thread for suspend count reasons.
+    ThreadMacOSX::GetBasicInfo(GetID(), &m_basic_info);
+    m_suspend_count = m_basic_info.suspend_count;
+    m_basic_info_string.clear();
+}
+
+uint32_t
+ThreadMacOSX::GetStackFrameCount()
+{
+    if (m_fp_pc_pairs.empty())
+        GetStackFrameData(m_fp_pc_pairs);
+    return m_fp_pc_pairs.size();
+}
+
+// Make sure that GetStackFrameAtIndex() does NOT call GetStackFrameCount() when
+// getting the stack frame at index zero! This way GetStackFrameCount() (via
+// GetStackFRameData()) can call this function to get the first frame in order
+// to provide the first frame to a lower call for efficiency sake (avoid
+// redundant lookups in the frame symbol context).
+lldb::StackFrameSP
+ThreadMacOSX::GetStackFrameAtIndex (uint32_t idx)
+{
+    StackFrameSP frame_sp(m_frames.GetFrameAtIndex(idx));
+
+    if (frame_sp)
+        return frame_sp;
+
+    // Don't try and fetch a frame while process is running
+    // Calling IsRunning isn't right here, because IsRunning reads the Public
+    // state but we need to be able to read the stack frames in the ShouldStop
+    // methods, which happen before the Public state has been updated.
+//    if (m_process.IsRunning())
+//        return frame_sp;
+
+    // Special case the first frame (idx == 0) so that we don't need to
+    // know how many stack frames there are to get it. If we need any other
+    // frames, then we do need to know if "idx" is a valid index.
+    if (idx == 0)
+    {
+        // If this is the first frame, we want to share the thread register
+        // context with the stack frame at index zero.
+        GetRegisterContext();
+        assert (m_reg_context_sp.get());
+        frame_sp.reset (new StackFrame (idx, *this, m_reg_context_sp, m_reg_context_sp->GetFP(), m_reg_context_sp->GetPC()));
+    }
+    else if (idx < GetStackFrameCount())
+    {
+        assert (idx < m_fp_pc_pairs.size());
+        frame_sp.reset (new StackFrame (idx, *this, m_fp_pc_pairs[idx].first, m_fp_pc_pairs[idx].second));
+    }
+    m_frames.SetFrameAtIndex(idx, frame_sp);
+    return frame_sp;
+}
+
+void
+ThreadMacOSX::ClearStackFrames ()
+{
+    m_fp_pc_pairs.clear();
+    Thread::ClearStackFrames();
+}
+
+
+
+int32_t
+ThreadMacOSX::Suspend()
+{
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_THREAD);
+    if (log && log->GetMask().IsSet(PD_LOG_VERBOSE))
+        log->Printf ("ThreadMacOSX::%s ( )", __FUNCTION__);
+    lldb::tid_t tid = GetID ();
+    if (ThreadIDIsValid(tid))
+    {
+        Error err(::thread_suspend (tid), eErrorTypeMachKernel);
+        if (err.Success())
+            m_suspend_count++;
+        if (log || err.Fail())
+            err.PutToLog(log, "::thread_suspend (%4.4x)", tid);
+    }
+    return GetSuspendCount();
+}
+
+int32_t
+ThreadMacOSX::Resume()
+{
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_THREAD);
+    if (log && log->GetMask().IsSet(PD_LOG_VERBOSE))
+        log->Printf ("ThreadMacOSX::%s ()", __FUNCTION__);
+    lldb::tid_t tid = GetID ();
+    if (ThreadIDIsValid(tid))
+    {
+        while (m_suspend_count > 0)
+        {
+            Error err(::thread_resume (tid), eErrorTypeMachKernel);
+            if (err.Success())
+                m_suspend_count--;
+            if (log || err.Fail())
+                err.PutToLog(log, "::thread_resume (%4.4x)", tid);
+        }
+    }
+    return GetSuspendCount();
+}
+
+bool
+ThreadMacOSX::RestoreSuspendCount()
+{
+    Log *log = ProcessMacOSXLog::GetLogIfAllCategoriesSet(PD_LOG_THREAD);
+    if (log && log->GetMask().IsSet(PD_LOG_VERBOSE))
+        log->Printf ("ThreadMacOSX::%s ( )", __FUNCTION__);
+    Error err;
+    lldb::tid_t tid = GetID ();
+    if (ThreadIDIsValid(tid) == false)
+        return false;
+    else if (m_suspend_count > m_basic_info.suspend_count)
+    {
+        while (m_suspend_count > m_basic_info.suspend_count)
+        {
+            err = ::thread_resume (tid);
+            if (err.Success())
+                --m_suspend_count;
+            if (log || err.Fail())
+                err.PutToLog(log, "::thread_resume (%4.4x)", tid);
+        }
+    }
+    else if (m_suspend_count < m_basic_info.suspend_count)
+    {
+        while (m_suspend_count < m_basic_info.suspend_count)
+        {
+            err = ::thread_suspend (tid);
+            if (err.Success())
+                --m_suspend_count;
+            if (log || err.Fail())
+                err.PutToLog(log, "::thread_suspend (%4.4x)", tid);
+        }
+    }
+    return  m_suspend_count == m_basic_info.suspend_count;
+}
+
+
+const char *
+ThreadMacOSX::GetBasicInfoAsString ()
+{
+    if (m_basic_info_string.empty())
+    {
+        StreamString sstr;
+        struct thread_basic_info basicInfo;
+
+        lldb::tid_t tid = GetID ();
+        if (GetBasicInfo(tid, &basicInfo))
+        {
+//          char run_state_str[32];
+//          size_t run_state_str_size = sizeof(run_state_str);
+//          switch (basicInfo.run_state)
+//          {
+//          case TH_STATE_RUNNING:          strncpy(run_state_str, "running", run_state_str_size); break;
+//          case TH_STATE_STOPPED:          strncpy(run_state_str, "stopped", run_state_str_size); break;
+//          case TH_STATE_WAITING:          strncpy(run_state_str, "waiting", run_state_str_size); break;
+//          case TH_STATE_UNINTERRUPTIBLE:  strncpy(run_state_str, "uninterruptible", run_state_str_size); break;
+//          case TH_STATE_HALTED:           strncpy(run_state_str, "halted", run_state_str_size); break;
+//          default:                        snprintf(run_state_str, run_state_str_size, "%d", basicInfo.run_state); break;    // ???
+//          }
+            float user = (float)basicInfo.user_time.seconds + (float)basicInfo.user_time.microseconds / 1000000.0f;
+            float system = (float)basicInfo.user_time.seconds + (float)basicInfo.user_time.microseconds / 1000000.0f;
+            sstr.Printf("Thread 0x%4.4x: user=%f system=%f cpu=%d sleep_time=%d",
+                InferiorThreadID(),
+                user,
+                system,
+                basicInfo.cpu_usage,
+                basicInfo.sleep_time);
+            m_basic_info_string.assign (sstr.GetData(), sstr.GetSize());
+        }
+    }
+    if (m_basic_info_string.empty())
+        return NULL;
+    return m_basic_info_string.c_str();
+}
+
+
+//const uint8_t *
+//ThreadMacOSX::SoftwareBreakpointOpcode (size_t break_op_size) const
+//{
+//  return m_context->SoftwareBreakpointOpcode(break_op_size);
+//}
+
+
+lldb::tid_t
+ThreadMacOSX::InferiorThreadID() const
+{
+    mach_msg_type_number_t i;
+    mach_port_name_array_t names;
+    mach_port_type_array_t types;
+    mach_msg_type_number_t ncount, tcount;
+    lldb::tid_t inferior_tid = LLDB_INVALID_THREAD_ID;
+    task_t my_task = ::mach_task_self();
+    task_t task = GetMacOSXProcess().Task().GetTaskPort();
+
+    kern_return_t kret = ::mach_port_names (task, &names, &ncount, &types, &tcount);
+    if (kret == KERN_SUCCESS)
+    {
+        lldb::tid_t tid = GetID ();
+
+        for (i = 0; i < ncount; i++)
+        {
+            mach_port_t my_name;
+            mach_msg_type_name_t my_type;
+
+            kret = ::mach_port_extract_right (task, names[i], MACH_MSG_TYPE_COPY_SEND, &my_name, &my_type);
+            if (kret == KERN_SUCCESS)
+            {
+                ::mach_port_deallocate (my_task, my_name);
+                if (my_name == tid)
+                {
+                    inferior_tid = names[i];
+                    break;
+                }
+            }
+        }
+        // Free up the names and types
+        ::vm_deallocate (my_task, (vm_address_t) names, ncount * sizeof (mach_port_name_t));
+        ::vm_deallocate (my_task, (vm_address_t) types, tcount * sizeof (mach_port_type_t));
+    }
+    return inferior_tid;
+}
+
+bool
+ThreadMacOSX::GetBasicInfo(lldb::tid_t thread, struct thread_basic_info *basicInfoPtr)
+{
+    if (ThreadIDIsValid(thread))
+    {
+        unsigned int info_count = THREAD_BASIC_INFO_COUNT;
+        kern_return_t err = ::thread_info (thread, THREAD_BASIC_INFO, (thread_info_t) basicInfoPtr, &info_count);
+        if (err == KERN_SUCCESS)
+            return true;
+    }
+    ::memset (basicInfoPtr, 0, sizeof (struct thread_basic_info));
+    return false;
+}
+
+
+bool
+ThreadMacOSX::ThreadIDIsValid (lldb::tid_t thread)
+{
+    return thread != 0;
+}
+
+void
+ThreadMacOSX::Dump(Log *log, uint32_t index)
+{
+    const char * thread_run_state = NULL;
+
+    switch (m_basic_info.run_state)
+    {
+    case TH_STATE_RUNNING:          thread_run_state = "running"; break;    // 1 thread is running normally
+    case TH_STATE_STOPPED:          thread_run_state = "stopped"; break;    // 2 thread is stopped
+    case TH_STATE_WAITING:          thread_run_state = "waiting"; break;    // 3 thread is waiting normally
+    case TH_STATE_UNINTERRUPTIBLE:  thread_run_state = "uninter"; break;    // 4 thread is in an uninterruptible wait
+    case TH_STATE_HALTED:           thread_run_state = "halted "; break;     // 5 thread is halted at a
+    default:                        thread_run_state = "???"; break;
+    }
+
+    RegisterContext *reg_context = GetRegisterContext();
+    log->Printf ("thread[%u] %4.4x (%u): pc: 0x%8.8llx sp: 0x%8.8llx breakID: %d  user: %d.%06.6d  system: %d.%06.6d  cpu: %d  policy: %d  run_state: %d (%s)  flags: %d suspend_count: %d (current %d) sleep_time: %d",
+        index,
+        GetID (),
+        reg_context->GetPC (LLDB_INVALID_ADDRESS),
+        reg_context->GetSP (LLDB_INVALID_ADDRESS),
+        m_basic_info.user_time.seconds,        m_basic_info.user_time.microseconds,
+        m_basic_info.system_time.seconds,    m_basic_info.system_time.microseconds,
+        m_basic_info.cpu_usage,
+        m_basic_info.policy,
+        m_basic_info.run_state,
+        thread_run_state,
+        m_basic_info.flags,
+        m_basic_info.suspend_count, m_suspend_count,
+        m_basic_info.sleep_time);
+    //DumpRegisterState(0);
+}
+
+void
+ThreadMacOSX::ThreadWillResume (StateType resume_state)
+{
+    // Update the thread state to be the state we wanted when the task resumes
+    SetState (resume_state);
+    switch (resume_state)
+    {
+    case eStateSuspended:
+        Suspend();
+        break;
+
+    case eStateRunning:
+    case eStateStepping:
+        Resume();
+        break;
+    }
+    m_context->ThreadWillResume();
+}
+
+void
+ThreadMacOSX::DidResume ()
+{
+    // TODO: cache current stack frames for next time in case we can match things up??
+    ClearStackFrames();
+    m_stop_exception.Clear();
+    Thread::DidResume();
+}
+
+bool
+ThreadMacOSX::ShouldStop(bool &step_more)
+{
+// TODO: REmove this after all is working, Process should be managing this
+// for us.
+//
+//    // See if this thread is at a breakpoint?
+//    lldb::user_id_t breakID = CurrentBreakpoint();
+//
+//    if (LLDB_BREAK_ID_IS_VALID(breakID))
+//    {
+//        // This thread is sitting at a breakpoint, ask the breakpoint
+//        // if we should be stopping here.
+//        if (Process()->Breakpoints().ShouldStop(ProcessID(), ThreadID(), breakID))
+//            return true;
+//        else
+//        {
+//            // The breakpoint said we shouldn't stop, but we may have gotten
+//            // a signal or the user may have requested to stop in some other
+//            // way. Stop if we have a valid exception (this thread won't if
+//            // another thread was the reason this process stopped) and that
+//            // exception, is NOT a breakpoint exception (a common case would
+//            // be a SIGINT signal).
+//            if (GetStopException().IsValid() && !GetStopException().IsBreakpoint())
+//                return true;
+//        }
+//    }
+//    else
+//    {
+        if (m_context->StepNotComplete())
+        {
+            step_more = true;
+            return false;
+        }
+//        // The thread state is used to let us know what the thread was
+//        // trying to do. ThreadMacOSX::ThreadWillResume() will set the
+//        // thread state to various values depending if the thread was
+//        // the current thread and if it was to be single stepped, or
+//        // resumed.
+//        if (GetState() == eStateRunning)
+//        {
+//            // If our state is running, then we should continue as we are in
+//            // the process of stepping over a breakpoint.
+//            return false;
+//        }
+//        else
+//        {
+//            // Stop if we have any kind of valid exception for this
+//            // thread.
+//            if (GetStopException().IsValid())
+//                return true;
+//        }
+//    }
+//    return false;
+    return true;
+}
+
+bool
+ThreadMacOSX::NotifyException(MachException::Data& exc)
+{
+    if (m_stop_exception.IsValid())
+    {
+        // We may have more than one exception for a thread, but we need to
+        // only remember the one that we will say is the reason we stopped.
+        // We may have been single stepping and also gotten a signal exception,
+        // so just remember the most pertinent one.
+        if (m_stop_exception.IsBreakpoint())
+            m_stop_exception = exc;
+    }
+    else
+    {
+        m_stop_exception = exc;
+    }
+//    bool handled =
+    m_context->NotifyException(exc);
+//    if (!handled)
+//    {
+//        handled = true;
+//        lldb::addr_t pc = GetPC();
+//        lldb::user_id_t breakID = m_process.Breakpoints().FindIDCyAddress(pc);
+//        SetCurrentBreakpoint(breakID);
+//        switch (exc.exc_type)
+//        {
+//        case EXC_BAD_ACCESS:
+//            break;
+//        case EXC_BAD_INSTRUCTION:
+//            break;
+//        case EXC_ARITHMETIC:
+//            break;
+//        case EXC_EMULATION:
+//            break;
+//        case EXC_SOFTWARE:
+//            break;
+//        case EXC_BREAKPOINT:
+//            break;
+//        case EXC_SYSCALL:
+//            break;
+//        case EXC_MACH_SYSCALL:
+//            break;
+//        case EXC_RPC_ALERT:
+//            break;
+//        }
+//    }
+//    return handled;
+    return true;
+}
+
+RegisterContext *
+ThreadMacOSX::GetRegisterContext ()
+{
+    if (m_reg_context_sp.get() == NULL)
+        m_reg_context_sp.reset (CreateRegisterContextForFrame (NULL));
+    return m_reg_context_sp.get();
+}
+
+RegisterContext *
+ThreadMacOSX::CreateRegisterContextForFrame (StackFrame *frame)
+{
+    return m_context->CreateRegisterContext (frame);
+}
+
+uint32_t
+ThreadMacOSX::SetHardwareBreakpoint (const BreakpointSite *bp)
+{
+    if (bp != NULL)
+        return GetRegisterContext()->SetHardwareBreakpoint(bp->GetLoadAddress(), bp->GetByteSize());
+    return LLDB_INVALID_INDEX32;
+}
+
+uint32_t
+ThreadMacOSX::SetHardwareWatchpoint (const WatchpointLocation *wp)
+{
+    if (wp != NULL)
+        return GetRegisterContext()->SetHardwareWatchpoint(wp->GetLoadAddress(), wp->GetByteSize(), wp->WatchpointRead(), wp->WatchpointWrite());
+    return LLDB_INVALID_INDEX32;
+}
+
+
+bool
+ThreadMacOSX::SaveFrameZeroState (RegisterCheckpoint &checkpoint)
+{
+    lldb::StackFrameSP frame_sp(GetStackFrameAtIndex (0));
+    if (frame_sp)
+    {
+        checkpoint.SetStackID(frame_sp->GetStackID());
+        return frame_sp->GetRegisterContext()->ReadAllRegisterValues (checkpoint.GetData());
+    }
+    return false;
+}
+
+bool
+ThreadMacOSX::RestoreSaveFrameZero (const RegisterCheckpoint &checkpoint)
+{
+    lldb::StackFrameSP frame_sp(GetStackFrameAtIndex (0));
+    if (frame_sp)
+    {
+        bool ret = frame_sp->GetRegisterContext()->WriteAllRegisterValues (checkpoint.GetData());
+
+        // Clear out all stack frames as our world just changed.
+        ClearStackFrames();
+        frame_sp->GetRegisterContext()->Invalidate();
+
+        return ret;
+    }
+    return false;
+}
+
+bool
+ThreadMacOSX::ClearHardwareBreakpoint (const BreakpointSite *bp)
+{
+    if (bp != NULL && bp->IsHardware())
+        return GetRegisterContext()->ClearHardwareBreakpoint(bp->GetHardwareIndex());
+    return false;
+}
+
+bool
+ThreadMacOSX::ClearHardwareWatchpoint (const WatchpointLocation *wp)
+{
+    if (wp != NULL && wp->IsHardware())
+        return GetRegisterContext()->ClearHardwareWatchpoint(wp->GetHardwareIndex());
+    return false;
+}
+
+size_t
+ThreadMacOSX::GetStackFrameData(std::vector<std::pair<lldb::addr_t, lldb::addr_t> >& fp_pc_pairs)
+{
+    lldb::StackFrameSP frame_sp(GetStackFrameAtIndex (0));
+    return m_context->GetStackFrameData(frame_sp.get(), fp_pc_pairs);
+}
+
+
+//void
+//ThreadMacOSX::NotifyBreakpointChanged (const BreakpointSite *bp)
+//{
+//  if (bp)
+//  {
+//      lldb::user_id_t breakID = bp->GetID();
+//      if (bp->IsEnabled())
+//      {
+//          if (bp->Address() == GetPC())
+//          {
+//              SetCurrentBreakpoint(breakID);
+//          }
+//      }
+//      else
+//      {
+//          if (CurrentBreakpoint() == breakID)
+//          {
+//              SetCurrentBreakpoint(LLDB_INVALID_BREAK_ID);
+//          }
+//      }
+//  }
+//}
+//
+
+
diff --git a/source/Plugins/Process/MacOSX-User/source/ThreadMacOSX.h b/source/Plugins/Process/MacOSX-User/source/ThreadMacOSX.h
new file mode 100644
index 0000000..0039f36
--- /dev/null
+++ b/source/Plugins/Process/MacOSX-User/source/ThreadMacOSX.h
@@ -0,0 +1,159 @@
+//===-- ThreadMacOSX.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_ThreadMacOSX_h_
+#define liblldb_ThreadMacOSX_h_
+
+#include <libproc.h>
+
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+#include "MachException.h"
+
+class ProcessMacOSX;
+class MachThreadContext;
+
+class ThreadMacOSX : public lldb_private::Thread
+{
+public:
+    ThreadMacOSX (ProcessMacOSX &process, lldb::tid_t tid);
+
+    virtual
+    ~ThreadMacOSX ();
+
+    virtual bool
+    WillResume (lldb::StateType resume_state);
+
+    virtual void
+    RefreshStateAfterStop();
+
+    virtual const char *
+    GetInfo ();
+
+    virtual const char *
+    GetName ();
+
+    virtual lldb_private::RegisterContext *
+    GetRegisterContext ();
+
+    virtual lldb_private::RegisterContext *
+    CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+
+    virtual bool
+    SaveFrameZeroState (RegisterCheckpoint &checkpoint);
+
+    virtual bool
+    RestoreSaveFrameZero (const RegisterCheckpoint &checkpoint);
+
+    virtual uint32_t
+    GetStackFrameCount();
+
+    virtual lldb::StackFrameSP
+    GetStackFrameAtIndex (uint32_t idx);
+
+    virtual void
+    ClearStackFrames ();
+
+    ProcessMacOSX &
+    GetMacOSXProcess ()
+    {
+        return (ProcessMacOSX &)m_process;
+    }
+
+    const ProcessMacOSX &
+    GetMacOSXProcess () const
+    {
+        return (ProcessMacOSX &)m_process;
+    }
+
+    void
+    Dump (lldb_private::Log *log, uint32_t index);
+
+    lldb::tid_t
+    InferiorThreadID () const;
+
+    static bool
+    ThreadIDIsValid (lldb::tid_t thread);
+
+    int32_t
+    Resume ();
+
+    int32_t
+    Suspend ();
+
+    int32_t
+    GetSuspendCount () const { return m_suspend_count; }
+
+    bool
+    RestoreSuspendCount ();
+
+    uint32_t
+    SetHardwareBreakpoint (const lldb_private::BreakpointSite *bp);
+
+    uint32_t
+    SetHardwareWatchpoint (const lldb_private::WatchpointLocation *wp);
+
+    bool
+    ClearHardwareBreakpoint (const lldb_private::BreakpointSite *bp);
+
+    bool
+    ClearHardwareWatchpoint (const lldb_private::WatchpointLocation *wp);
+
+    void
+    ThreadWillResume (lldb::StateType resume_state);
+
+    virtual void
+    DidResume ();
+
+    bool
+    ShouldStop (bool &step_more);
+
+    bool
+    NotifyException (MachException::Data& exc);
+
+    const MachException::Data&
+    GetStopException () { return m_stop_exception; }
+
+    const char *
+    GetBasicInfoAsString ();
+
+    size_t
+    GetStackFrameData (std::vector<std::pair<lldb::addr_t, lldb::addr_t> >& fp_pc_pairs);
+
+    virtual bool
+    GetRawStopReason (lldb_private::Thread::StopInfo *stop_info);
+
+protected:
+    bool
+    GetIdentifierInfo ();
+
+    const char *
+    GetDispatchQueueName();
+
+    static bool
+    GetBasicInfo (lldb::tid_t threadID, struct thread_basic_info *basic_info);
+
+    //------------------------------------------------------------------
+    // Member variables.
+    //------------------------------------------------------------------
+    std::vector<std::pair<lldb::addr_t, lldb::addr_t> > m_fp_pc_pairs;
+    struct thread_basic_info        m_basic_info;       // Basic information for a thread used to see if a thread is valid
+    std::string                     m_basic_info_string;// Basic thread info as a C string.
+#ifdef THREAD_IDENTIFIER_INFO_COUNT
+    thread_identifier_info_data_t   m_ident_info;
+    struct proc_threadinfo          m_proc_threadinfo;
+    std::string                     m_dispatch_queue_name;
+#endif
+    int32_t                         m_suspend_count;    // The current suspend count
+    MachException::Data             m_stop_exception;   // The best exception that describes why this thread is stopped
+    std::auto_ptr<MachThreadContext> m_context;         // The arch specific thread context for this thread (register state and more)
+
+};
+
+#endif  // liblldb_ThreadMacOSX_h_
diff --git a/source/Plugins/Process/Utility/LibUnwindRegisterContext.cpp b/source/Plugins/Process/Utility/LibUnwindRegisterContext.cpp
new file mode 100644
index 0000000..bf6b6c2
--- /dev/null
+++ b/source/Plugins/Process/Utility/LibUnwindRegisterContext.cpp
@@ -0,0 +1,327 @@
+//===-- LibUnwindRegisterContext.cpp ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LibUnwindRegisterContext.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Target/Thread.h"
+// Project includes
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// LibUnwindRegisterContext constructor
+//----------------------------------------------------------------------
+LibUnwindRegisterContext::LibUnwindRegisterContext
+(
+    Thread &thread,
+    StackFrame *frame,
+    const lldb_private::unw_cursor_t& unwind_cursor
+) :
+    RegisterContext (thread, frame),
+    m_unwind_cursor (unwind_cursor),
+    m_unwind_cursor_is_valid (true)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+LibUnwindRegisterContext::~LibUnwindRegisterContext()
+{
+}
+
+void
+LibUnwindRegisterContext::Invalidate ()
+{
+    m_unwind_cursor_is_valid = false;
+}
+
+size_t
+LibUnwindRegisterContext::GetRegisterCount ()
+{
+    return m_thread.GetRegisterContext()->GetRegisterCount();
+}
+
+const lldb::RegisterInfo *
+LibUnwindRegisterContext::GetRegisterInfoAtIndex (uint32_t reg)
+{
+    return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg);
+}
+
+size_t
+LibUnwindRegisterContext::GetRegisterSetCount ()
+{
+    return m_thread.GetRegisterContext()->GetRegisterSetCount();
+}
+
+
+
+const lldb::RegisterSet *
+LibUnwindRegisterContext::GetRegisterSet (uint32_t reg_set)
+{
+    return m_thread.GetRegisterContext()->GetRegisterSet (reg_set);
+}
+
+
+
+bool
+LibUnwindRegisterContext::ReadRegisterValue (uint32_t reg, Scalar &value)
+{
+    if (m_unwind_cursor_is_valid == false)
+        return false;
+
+    // Read the register
+    unw_word_t reg_value;
+    if (unw_get_reg (&m_unwind_cursor, reg, &reg_value) != UNW_ESUCCESS)
+        return false;
+
+    const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
+    switch (reg_info->encoding)
+    {
+    case eEncodingUint:
+        switch (reg_info->byte_size)
+        {
+        case 1:
+        case 2:
+        case 4:
+            value = (uint32_t)reg_value;
+            return true;
+
+        case 8:
+            value = (uint64_t)reg_value;
+            return true;
+        }
+        break;
+
+    case eEncodingSint:
+        switch (reg_info->byte_size)
+        {
+        case 1:
+        case 2:
+        case 4:
+            value = (int32_t)reg_value;
+            return true;
+
+        case 8:
+            value = (int64_t)reg_value;
+            return true;
+        }
+        break;
+
+    case eEncodingIEEE754:
+        if (reg_info->byte_size > sizeof(unw_word_t))
+            return false;
+
+        switch (reg_info->byte_size)
+        {
+        case sizeof (float):
+            if (sizeof (float) == sizeof(uint32_t))
+            {
+                value = (uint32_t)reg_value;
+                return true;
+            }
+            else if (sizeof (float) == sizeof(uint64_t))
+            {
+                value = (uint64_t)reg_value;
+                return true;
+            }
+            break;
+
+        case sizeof (double):
+            if (sizeof (double) == sizeof(uint32_t))
+            {
+                value = (uint32_t)reg_value;
+                return true;
+            }
+            else if (sizeof (double) == sizeof(uint64_t))
+            {
+                value = (uint64_t)reg_value;
+                return true;
+            }
+            break;
+
+        case sizeof (long double):
+            if (sizeof (long double) == sizeof(uint32_t))
+            {
+                value = (uint32_t)reg_value;
+                return true;
+            }
+            else if (sizeof (long double) == sizeof(uint64_t))
+            {
+                value = (uint64_t)reg_value;
+                return true;
+            }
+            break;
+        }
+        break;
+    }
+    return false;
+}
+
+
+bool
+LibUnwindRegisterContext::ReadRegisterBytes (uint32_t reg, DataExtractor &data)
+{
+    Scalar reg_value;
+    
+    if (ReadRegisterValue (reg, reg_value))
+    {
+        if (reg_value.GetData(data))
+        {
+            // "reg_value" is local and now "data" points to the data within
+            // "reg_value", so we must make a copy that will live within "data"
+            DataBufferSP data_sp (new DataBufferHeap (data.GetDataStart(), data.GetByteSize()));
+            data.SetData (data_sp, 0, data.GetByteSize());
+            return true;
+        }
+    }
+    return false;
+}
+
+
+bool
+LibUnwindRegisterContext::WriteRegisterValue (uint32_t reg, const Scalar &value)
+{
+    const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
+    if (reg_info == NULL)
+        return false;
+    unw_word_t reg_value;
+    switch (value.GetType())
+    {
+    case Scalar::e_sint:        reg_value = value.SInt(); break;
+    case Scalar::e_uint:        reg_value = value.UInt(); break;
+    case Scalar::e_slong:       reg_value = value.SLong(); break;
+    case Scalar::e_ulong:       reg_value = value.ULong(); break;
+    case Scalar::e_slonglong:   reg_value = value.SLongLong(); break;
+    case Scalar::e_ulonglong:   reg_value = value.ULongLong(); break;
+    case Scalar::e_float:
+        if (sizeof (float) == sizeof (unsigned int))
+            reg_value = value.UInt();
+        else if (sizeof (float) == sizeof (unsigned long))
+            reg_value = value.ULong();
+        else if (sizeof (float) == sizeof (unsigned long long))
+            reg_value = value.ULongLong();
+        else
+            return false;
+        break;
+            
+    case Scalar::e_double:
+        if (sizeof (double) == sizeof (unsigned int))
+            reg_value = value.UInt();
+        else if (sizeof (double) == sizeof (unsigned long))
+            reg_value = value.ULong();
+        else if (sizeof (double) == sizeof (unsigned long long))
+            reg_value = value.ULongLong();
+        else
+            return false;
+        break;
+            
+    case Scalar::e_long_double:
+        if (sizeof (long double) == sizeof (unsigned int))
+            reg_value = value.UInt();
+        else if (sizeof (long double) == sizeof (unsigned long))
+            reg_value = value.ULong();
+        else if (sizeof (long double) == sizeof (unsigned long long))
+            reg_value = value.ULongLong();
+        else
+            return false;
+        break;
+    }
+    
+    return unw_set_reg (&m_unwind_cursor, reg, reg_value) == UNW_ESUCCESS;
+}
+
+
+bool
+LibUnwindRegisterContext::WriteRegisterBytes (uint32_t reg, DataExtractor &data, uint32_t data_offset)
+{
+    const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
+
+    if (reg_info == NULL)
+        return false;
+    if (reg_info->byte_size > sizeof (unw_word_t))
+        return false;
+    
+    Scalar value;
+    uint32_t offset = data_offset;
+    
+    switch (reg_info->encoding)
+    {
+    case eEncodingUint:
+        if (reg_info->byte_size <= 4)
+            value = data.GetMaxU32 (&offset, reg_info->byte_size);
+        else if (reg_info->byte_size <= 8)
+            value = data.GetMaxU64 (&offset, reg_info->byte_size);
+        else
+            return false;
+        break;
+
+    case eEncodingSint:
+        if (reg_info->byte_size <= 4)
+            value = (int32_t)data.GetMaxU32 (&offset, reg_info->byte_size);
+        else if (reg_info->byte_size <= 8)
+            value = data.GetMaxS64 (&offset, reg_info->byte_size);
+        else
+            return false;
+        break;
+
+    case eEncodingIEEE754:
+        switch (reg_info->byte_size)
+        {
+        case sizeof (float):
+            value = data.GetFloat (&offset);
+            break;
+
+        case sizeof (double):
+            value = data.GetDouble (&offset);
+            break;
+
+        case sizeof (long double):
+            value = data.GetLongDouble (&offset);
+            break;
+        default:
+            return false;
+        }
+    }        
+    return WriteRegisterValue (reg, value);
+}
+
+
+bool
+LibUnwindRegisterContext::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
+{
+    // libunwind frames can't handle this it doesn't always have all register
+    // values. This call should only be called on frame zero anyway so there
+    // shouldn't be any problem
+    return false;
+}
+
+bool
+LibUnwindRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
+{
+    // Since this class doesn't respond to "ReadAllRegisterValues()", it must
+    // not have been the one that saved all the register values. So we just let
+    // the thread's register context (the register context for frame zero) do
+    // the writing.
+    return m_thread.GetRegisterContext()->WriteAllRegisterValues(data_sp);
+}
+
+
+uint32_t
+LibUnwindRegisterContext::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
+{
+    return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber (kind, num);
+}
+
diff --git a/source/Plugins/Process/Utility/LibUnwindRegisterContext.h b/source/Plugins/Process/Utility/LibUnwindRegisterContext.h
new file mode 100644
index 0000000..4e89b27
--- /dev/null
+++ b/source/Plugins/Process/Utility/LibUnwindRegisterContext.h
@@ -0,0 +1,83 @@
+//===-- LibUnwindRegisterContext.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_LibUnwindRegisterContext_h_
+#define lldb_LibUnwindRegisterContext_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/RegisterContext.h"
+
+#include "libunwind.h"
+
+class LibUnwindRegisterContext : public lldb_private::RegisterContext
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    LibUnwindRegisterContext (lldb_private::Thread &thread,
+                              lldb_private::StackFrame *frame,
+                              const lldb_private::unw_cursor_t &unwind_cursor);
+
+    virtual
+    ~LibUnwindRegisterContext ();
+
+    //------------------------------------------------------------------
+    // Subclasses must override these functions
+    //------------------------------------------------------------------
+    virtual void
+    Invalidate ();
+
+    virtual size_t
+    GetRegisterCount ();
+
+    virtual const lldb::RegisterInfo *
+    GetRegisterInfoAtIndex (uint32_t reg);
+
+    virtual size_t
+    GetRegisterSetCount ();
+
+    virtual const lldb::RegisterSet *
+    GetRegisterSet (uint32_t reg_set);
+
+    virtual bool
+    ReadRegisterValue (uint32_t reg, lldb_private::Scalar &value);
+
+    virtual bool
+    ReadRegisterBytes (uint32_t reg, lldb_private::DataExtractor &data);
+
+    virtual bool
+    ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+
+    virtual bool
+    WriteRegisterValue (uint32_t reg, const lldb_private::Scalar &value);
+
+    virtual bool
+    WriteRegisterBytes (uint32_t reg, lldb_private::DataExtractor &data, uint32_t data_offset);
+
+    virtual bool
+    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+
+    virtual uint32_t
+    ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+    
+private:
+    lldb_private::unw_cursor_t m_unwind_cursor;
+    bool m_unwind_cursor_is_valid;
+    //------------------------------------------------------------------
+    // For LibUnwindRegisterContext only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (LibUnwindRegisterContext);
+};
+
+#endif  // lldb_LibUnwindRegisterContext_h_
diff --git a/source/Plugins/Process/Utility/MacOSXLibunwindCallbacks.cpp b/source/Plugins/Process/Utility/MacOSXLibunwindCallbacks.cpp
new file mode 100644
index 0000000..58a7ac0
--- /dev/null
+++ b/source/Plugins/Process/Utility/MacOSXLibunwindCallbacks.cpp
@@ -0,0 +1,306 @@
+//===-- MacOSXLibunwindCallbacks.cpp ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_MacOSXLibunwindCallbacks_cpp_
+#define liblldb_MacOSXLibunwindCallbacks_cpp_
+#if defined(__cplusplus)
+
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+#include "lldb-enumerations.h"
+#include "libunwind.h"
+#include "llvm-c/EnhancedDisassembly.h"
+
+using namespace lldb;
+
+namespace lldb_private {
+
+/* Don't implement (libunwind does not use)
+      find_proc_info
+      put_unwind_info
+      get_dyn_info_list_addr
+      access_mem
+      resume
+*/
+/*
+  Should implement (not needed yet)
+      access_fpreg
+      access_vecreg
+      proc_is_sigtramp
+      proc_is_inferior_function_call
+      access_reg_inf_func_call
+*/
+  
+static int 
+access_reg (lldb_private::unw_addr_space_t as, lldb_private::unw_regnum_t regnum, lldb_private::unw_word_t *valp, int write, void *arg)
+{
+    if (arg == 0)
+        return -1;
+    Thread *th = (Thread *) arg;
+    /* FIXME Only support reading for now.  */
+    if (write == 1)
+        return -1;
+    if (th->GetRegisterContext()->GetRegisterInfoAtIndex(regnum) == NULL)
+        return -1;
+    DataExtractor de;
+    if (!th->GetRegisterContext()->ReadRegisterBytes (regnum, de))
+        return -1;
+    memcpy (valp, de.GetDataStart(), de.GetByteSize());
+    return UNW_ESUCCESS;
+}
+
+static int 
+get_proc_name (lldb_private::unw_addr_space_t as, lldb_private::unw_word_t ip, char *bufp, size_t buf_len, lldb_private::unw_word_t *offp, void *arg)
+{
+    if (arg == 0)
+        return -1;
+    Thread *th = (Thread *) arg;
+    Address addr;
+    if (!th->GetProcess().ResolveLoadAddress(ip, addr))
+        return -1;
+    
+    SymbolContext sc;
+    if (!th->GetProcess().GetTarget().GetImages().ResolveSymbolContextForAddress (addr, eSymbolContextFunction, sc))
+        return -1;
+    if (!sc.symbol)
+        return -1;
+    strlcpy (bufp, sc.symbol->GetMangled().GetMangledName().AsCString(""), buf_len);
+    if (offp)
+        *offp = addr.GetLoadAddress(&th->GetProcess()) - sc.symbol->GetValue().GetLoadAddress(&th->GetProcess());
+    return UNW_ESUCCESS;
+}
+
+static int 
+find_image_info (lldb_private::unw_addr_space_t as, lldb_private::unw_word_t load_addr, lldb_private::unw_word_t *mh, 
+                 lldb_private::unw_word_t *text_start, lldb_private::unw_word_t *text_end, 
+                 lldb_private::unw_word_t *eh_frame, lldb_private::unw_word_t *eh_frame_len, 
+                 lldb_private::unw_word_t *compact_unwind_start, lldb_private::unw_word_t *compact_unwind_len, void *arg)
+{
+    if (arg == 0)
+        return -1;
+    Thread *th = (Thread *) arg;
+    Address addr;
+    if (!th->GetProcess().ResolveLoadAddress(load_addr, addr))
+        return -1;
+    
+    SymbolContext sc;
+    if (!th->GetProcess().GetTarget().GetImages().ResolveSymbolContextForAddress (addr, eSymbolContextModule, sc))
+        return -1;
+    
+    SectionList *sl = sc.module_sp->GetObjectFile()->GetSectionList();
+    static ConstString g_segment_name_TEXT("__TEXT");
+    SectionSP text_segment_sp(sl->FindSectionByName(g_segment_name_TEXT));
+    if (!text_segment_sp)
+        return -1;
+    
+    *mh = text_segment_sp->GetLoadBaseAddress (&th->GetProcess());
+    *text_start = text_segment_sp->GetLoadBaseAddress (&th->GetProcess());
+    *text_end = *text_start + text_segment_sp->GetByteSize();
+    
+    static ConstString g_section_name_eh_frame ("__eh_frame");
+    SectionSP eh_frame_section_sp = text_segment_sp->GetChildren().FindSectionByName(g_section_name_eh_frame);
+    if (eh_frame_section_sp.get()) {
+        *eh_frame = eh_frame_section_sp->GetLoadBaseAddress (&th->GetProcess());
+        *eh_frame_len = eh_frame_section_sp->GetByteSize();
+    } else {
+        *eh_frame = 0;
+        *eh_frame_len = 0;
+    }
+    
+    static ConstString g_section_name_unwind_info ("__unwind_info");
+    SectionSP unwind_info_section_sp = text_segment_sp->GetChildren().FindSectionByName(g_section_name_unwind_info);
+    if (unwind_info_section_sp.get()) {
+        *compact_unwind_start = unwind_info_section_sp->GetLoadBaseAddress (&th->GetProcess());
+        *compact_unwind_len = unwind_info_section_sp->GetByteSize();
+    } else {
+        *compact_unwind_start = 0;
+        *compact_unwind_len = 0;
+    }
+    return UNW_ESUCCESS;
+}
+
+static int 
+get_proc_bounds (lldb_private::unw_addr_space_t as, lldb_private::unw_word_t ip, lldb_private::unw_word_t *low, lldb_private::unw_word_t *high, void *arg)
+{
+    if (arg == 0)
+        return -1;
+    Thread *th = (Thread *) arg;
+    Address addr;
+    if (!th->GetProcess().ResolveLoadAddress(ip, addr))
+        return -1;
+    SymbolContext sc;
+    if (!th->GetProcess().GetTarget().GetImages().ResolveSymbolContextForAddress (addr, eSymbolContextFunction | eSymbolContextSymbol, sc))
+        return -1;
+    if (sc.function)
+    {
+        lldb::addr_t start, len;
+        start = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(&th->GetProcess());
+        len = sc.function->GetAddressRange().GetByteSize();
+        if (start == LLDB_INVALID_ADDRESS || len == LLDB_INVALID_ADDRESS)
+            return -1;
+        *low = start;
+        *high = start + len;
+        return UNW_ESUCCESS;
+    }
+    if (sc.symbol)
+    {
+        lldb::addr_t start, len;
+        start = sc.symbol->GetAddressRangeRef().GetBaseAddress().GetLoadAddress(&th->GetProcess());
+        len = sc.symbol->GetAddressRangeRef().GetByteSize();
+        if (start == LLDB_INVALID_ADDRESS)
+            return -1;
+        *low = start;
+        if (len != LLDB_INVALID_ADDRESS)
+            *high = start + len;
+        else
+            *high = 0;
+        return UNW_ESUCCESS;
+    }
+    return -1;
+}
+
+static int 
+access_raw (lldb_private::unw_addr_space_t as, lldb_private::unw_word_t addr, lldb_private::unw_word_t extent, uint8_t *valp, int write, void *arg)
+{
+    if (arg == 0)
+        return -1;
+    Thread *th = (Thread *) arg;
+    /* FIXME Only support reading for now.  */
+    if (write == 1)
+        return -1;
+    
+    Error error;
+    if (th->GetProcess().ReadMemory (addr, valp, extent, error) != extent)
+        return -1;
+    return UNW_ESUCCESS;
+}
+
+
+static int 
+reg_info (lldb_private::unw_addr_space_t as, lldb_private::unw_regnum_t regnum, lldb_private::unw_regtype_t *type, char *buf, size_t buflen, void *arg)
+{
+    if (arg == 0)
+        return -1;
+    Thread *th = (Thread *) arg;
+    RegisterContext *regc = th->GetRegisterContext();
+    if (regnum > regc->GetRegisterCount())
+    {
+        *type = UNW_NOT_A_REG;
+        return UNW_ESUCCESS;
+    }
+    
+    const char *name = regc->GetRegisterName (regnum);
+    if (name == NULL)
+    {
+        *type = UNW_NOT_A_REG;
+        return UNW_ESUCCESS;
+    }
+    strlcpy (buf, name, buflen);
+    
+    const lldb::RegisterInfo *reginfo = regc->GetRegisterInfoAtIndex (regnum);
+    if (reginfo == NULL || reginfo->encoding == eEncodingInvalid)
+    {
+        *type = UNW_NOT_A_REG;
+        return UNW_ESUCCESS;
+    }
+    if (reginfo->encoding == eEncodingUint || reginfo->encoding == eEncodingSint)
+        *type = UNW_INTEGER_REG;
+    if (reginfo->encoding == eEncodingIEEE754)
+        *type = UNW_FLOATING_POINT_REG;
+    if (reginfo->encoding == eEncodingVector)
+        *type = UNW_VECTOR_REG;
+    
+    return UNW_ESUCCESS;
+}
+
+
+static int
+read_byte_for_edis (uint8_t *buf, uint64_t addr, void *arg)
+{
+    if (arg == 0)
+        return -1;
+    Thread *th = (Thread *) arg;
+    DataBufferHeap onebyte(1, 0);
+    Error error;
+    if (th->GetProcess().ReadMemory (addr, onebyte.GetBytes(), onebyte.GetByteSize(), error) != 1)
+        return -1;
+    *buf = onebyte.GetBytes()[0];
+    return UNW_ESUCCESS;
+}
+
+static int 
+instruction_length (lldb_private::unw_addr_space_t as, lldb_private::unw_word_t addr, int *length, void *arg)
+{
+    EDDisassemblerRef disasm;
+    EDInstRef         cur_insn;
+    
+    if (arg == 0)
+        return -1;
+    Thread *th = (Thread *) arg;
+    const ArchSpec target_arch (th->GetProcess().GetTarget().GetArchitecture ());
+    
+    if (target_arch.GetCPUType() == CPU_TYPE_I386)
+    {
+        if (EDGetDisassembler (&disasm, "i386-apple-darwin", kEDAssemblySyntaxX86ATT) != 0)
+            return -1;
+    }
+    else if (target_arch.GetCPUType() == CPU_TYPE_X86_64)
+    {
+        if (EDGetDisassembler (&disasm, "x86_64-apple-darwin", kEDAssemblySyntaxX86ATT) != 0)
+            return -1;
+    }
+    else
+    {
+        return -1;
+    }
+    
+    if (EDCreateInsts (&cur_insn, 1, disasm, read_byte_for_edis, addr, arg) != 1)
+        return -1;
+    *length = EDInstByteSize (cur_insn);
+    EDReleaseInst (cur_insn);
+    return UNW_ESUCCESS;
+}
+
+lldb_private::unw_accessors_t 
+get_macosx_libunwind_callbacks () {
+  lldb_private::unw_accessors_t ap;
+  bzero (&ap, sizeof (lldb_private::unw_accessors_t));
+  ap.find_proc_info = NULL;
+  ap.put_unwind_info = NULL;
+  ap.get_dyn_info_list_addr = NULL;
+  ap.find_image_info = find_image_info;
+  ap.access_mem = NULL;
+  ap.access_reg = access_reg;
+  ap.access_fpreg = NULL;
+  ap.access_vecreg = NULL;
+  ap.resume = NULL;
+  ap.get_proc_name = get_proc_name;
+  ap.get_proc_bounds = get_proc_bounds;
+  ap.access_raw = access_raw;
+  ap.reg_info = reg_info;
+  ap.proc_is_sigtramp = NULL;
+  ap.proc_is_inferior_function_call = NULL;
+  ap.access_reg_inf_func_call = NULL;
+  ap.instruction_length = instruction_length;
+  return ap;
+}
+
+
+} // namespace lldb_private
+
+#endif  // #if defined(__cplusplus)
+#endif // #ifndef liblldb_MacOSXLibunwindCallbacks_cpp_
diff --git a/source/Plugins/Process/Utility/MacOSXLibunwindCallbacks.h b/source/Plugins/Process/Utility/MacOSXLibunwindCallbacks.h
new file mode 100644
index 0000000..78bd27b
--- /dev/null
+++ b/source/Plugins/Process/Utility/MacOSXLibunwindCallbacks.h
@@ -0,0 +1,22 @@
+//===-- MacOSXLibunwindCallbacks.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_MacOSXLibunwindCallbacks_h_
+#define liblldb_MacOSXLibunwindCallbacks_h_
+#if defined(__cplusplus)
+
+namespace lldb_private {
+
+unw_accessors_t get_macosx_libunwind_callbacks ();
+
+} // namespace lldb_utility
+
+#endif  // #if defined(__cplusplus)
+#endif // #ifndef liblldb_MacOSXLibunwindCallbacks_h_
+
diff --git a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
new file mode 100644
index 0000000..df2f7c0
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
@@ -0,0 +1,255 @@
+//===-- RegisterContextMacOSXFrameBackchain.cpp -----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegisterContextMacOSXFrameBackchain.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Target/Thread.h"
+// Project includes
+#include "StringExtractorGDBRemote.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// RegisterContextMacOSXFrameBackchain constructor
+//----------------------------------------------------------------------
+RegisterContextMacOSXFrameBackchain::RegisterContextMacOSXFrameBackchain
+(
+    Thread &thread,
+    StackFrame *frame,
+    const UnwindMacOSXFrameBackchain::Cursor &cursor
+) :
+    RegisterContext (thread, frame),
+    m_cursor (cursor),
+    m_cursor_is_valid (true)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+RegisterContextMacOSXFrameBackchain::~RegisterContextMacOSXFrameBackchain()
+{
+}
+
+void
+RegisterContextMacOSXFrameBackchain::Invalidate ()
+{
+    m_cursor_is_valid = false;
+}
+
+size_t
+RegisterContextMacOSXFrameBackchain::GetRegisterCount ()
+{
+    return m_thread.GetRegisterContext()->GetRegisterCount();
+}
+
+const lldb::RegisterInfo *
+RegisterContextMacOSXFrameBackchain::GetRegisterInfoAtIndex (uint32_t reg)
+{
+    return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg);
+}
+
+size_t
+RegisterContextMacOSXFrameBackchain::GetRegisterSetCount ()
+{
+    return m_thread.GetRegisterContext()->GetRegisterSetCount();
+}
+
+
+
+const lldb::RegisterSet *
+RegisterContextMacOSXFrameBackchain::GetRegisterSet (uint32_t reg_set)
+{
+    return m_thread.GetRegisterContext()->GetRegisterSet (reg_set);
+}
+
+
+
+bool
+RegisterContextMacOSXFrameBackchain::ReadRegisterValue (uint32_t reg, Scalar &value)
+{
+    if (!m_cursor_is_valid)
+        return false;
+
+    uint64_t reg_value = LLDB_INVALID_ADDRESS;
+    
+    const RegisterInfo *reg_info = m_thread.GetRegisterContext()->GetRegisterInfoAtIndex (reg);
+    if (reg_info == NULL)
+        return false;
+
+    switch (reg_info->kinds[eRegisterKindGeneric])
+    {
+    case LLDB_REGNUM_GENERIC_PC:
+        if (m_cursor.pc == LLDB_INVALID_ADDRESS)
+            return false;
+        reg_value = m_cursor.pc;
+        break;
+    
+    case LLDB_REGNUM_GENERIC_FP:
+        if (m_cursor.fp == LLDB_INVALID_ADDRESS)
+            return false;
+        reg_value = m_cursor.pc;
+        break;
+    
+    default:
+        return false;    
+    }
+    
+    switch (reg_info->encoding)
+    {
+    case eEncodingUint:
+        switch (reg_info->byte_size)
+        {
+        case 1:
+        case 2:
+        case 4:
+            value = (uint32_t)reg_value;
+            return true;
+
+        case 8:
+            value = (uint64_t)reg_value;
+            return true;
+        }
+        break;
+
+    case eEncodingSint:
+        switch (reg_info->byte_size)
+        {
+        case 1:
+        case 2:
+        case 4:
+            value = (int32_t)reg_value;
+            return true;
+
+        case 8:
+            value = (int64_t)reg_value;
+            return true;
+        }
+        break;
+
+    case eEncodingIEEE754:
+        switch (reg_info->byte_size)
+        {
+        case sizeof (float):
+            if (sizeof (float) == sizeof(uint32_t))
+            {
+                value = (uint32_t)reg_value;
+                return true;
+            }
+            else if (sizeof (float) == sizeof(uint64_t))
+            {
+                value = (uint64_t)reg_value;
+                return true;
+            }
+            break;
+
+        case sizeof (double):
+            if (sizeof (double) == sizeof(uint32_t))
+            {
+                value = (uint32_t)reg_value;
+                return true;
+            }
+            else if (sizeof (double) == sizeof(uint64_t))
+            {
+                value = (uint64_t)reg_value;
+                return true;
+            }
+            break;
+
+        case sizeof (long double):
+            if (sizeof (long double) == sizeof(uint32_t))
+            {
+                value = (uint32_t)reg_value;
+                return true;
+            }
+            else if (sizeof (long double) == sizeof(uint64_t))
+            {
+                value = (uint64_t)reg_value;
+                return true;
+            }
+            break;
+        }
+        break;
+    }
+    return false;
+}
+
+
+bool
+RegisterContextMacOSXFrameBackchain::ReadRegisterBytes (uint32_t reg, DataExtractor &data)
+{
+    Scalar reg_value;
+    
+    if (ReadRegisterValue (reg, reg_value))
+    {
+        if (reg_value.GetData(data))
+        {
+            // "reg_value" is local and now "data" points to the data within
+            // "reg_value", so we must make a copy that will live within "data"
+            DataBufferSP data_sp (new DataBufferHeap (data.GetDataStart(), data.GetByteSize()));
+            data.SetData (data_sp, 0, data.GetByteSize());
+            return true;
+        }
+    }
+    return false;
+}
+
+
+bool
+RegisterContextMacOSXFrameBackchain::WriteRegisterValue (uint32_t reg, const Scalar &value)
+{
+    // Not supported yet. We could easily add support for this by remembering
+    // the address of each entry (it would need to be part of the cursor)
+    return false;
+}
+
+
+bool
+RegisterContextMacOSXFrameBackchain::WriteRegisterBytes (uint32_t reg, DataExtractor &data, uint32_t data_offset)
+{
+    // Not supported yet. We could easily add support for this by remembering
+    // the address of each entry (it would need to be part of the cursor)
+    return false;
+}
+
+
+bool
+RegisterContextMacOSXFrameBackchain::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
+{
+    // libunwind frames can't handle this it doesn't always have all register
+    // values. This call should only be called on frame zero anyway so there
+    // shouldn't be any problem
+    return false;
+}
+
+bool
+RegisterContextMacOSXFrameBackchain::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
+{
+    // Since this class doesn't respond to "ReadAllRegisterValues()", it must
+    // not have been the one that saved all the register values. So we just let
+    // the thread's register context (the register context for frame zero) do
+    // the writing.
+    return m_thread.GetRegisterContext()->WriteAllRegisterValues(data_sp);
+}
+
+
+uint32_t
+RegisterContextMacOSXFrameBackchain::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
+{
+    return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber (kind, num);
+}
+
diff --git a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h
new file mode 100644
index 0000000..f4118c2
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h
@@ -0,0 +1,83 @@
+//===-- RegisterContextMacOSXFrameBackchain.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_RegisterContextMacOSXFrameBackchain_h_
+#define lldb_RegisterContextMacOSXFrameBackchain_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/RegisterContext.h"
+
+#include "UnwindMacOSXFrameBackchain.h"
+
+class RegisterContextMacOSXFrameBackchain : public lldb_private::RegisterContext
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    RegisterContextMacOSXFrameBackchain (lldb_private::Thread &thread,
+                                         lldb_private::StackFrame *frame,
+                                         const UnwindMacOSXFrameBackchain::Cursor &cursor);
+
+    virtual
+    ~RegisterContextMacOSXFrameBackchain ();
+
+    //------------------------------------------------------------------
+    // Subclasses must override these functions
+    //------------------------------------------------------------------
+    virtual void
+    Invalidate ();
+
+    virtual size_t
+    GetRegisterCount ();
+
+    virtual const lldb::RegisterInfo *
+    GetRegisterInfoAtIndex (uint32_t reg);
+
+    virtual size_t
+    GetRegisterSetCount ();
+
+    virtual const lldb::RegisterSet *
+    GetRegisterSet (uint32_t reg_set);
+
+    virtual bool
+    ReadRegisterValue (uint32_t reg, lldb_private::Scalar &value);
+
+    virtual bool
+    ReadRegisterBytes (uint32_t reg, lldb_private::DataExtractor &data);
+
+    virtual bool
+    ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+
+    virtual bool
+    WriteRegisterValue (uint32_t reg, const lldb_private::Scalar &value);
+
+    virtual bool
+    WriteRegisterBytes (uint32_t reg, lldb_private::DataExtractor &data, uint32_t data_offset);
+
+    virtual bool
+    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+
+    virtual uint32_t
+    ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+    
+private:
+    UnwindMacOSXFrameBackchain::Cursor m_cursor;
+    bool m_cursor_is_valid;
+    //------------------------------------------------------------------
+    // For RegisterContextMacOSXFrameBackchain only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (RegisterContextMacOSXFrameBackchain);
+};
+
+#endif  // lldb_RegisterContextMacOSXFrameBackchain_h_
diff --git a/source/Plugins/Process/Utility/UnwindLibUnwind.cpp b/source/Plugins/Process/Utility/UnwindLibUnwind.cpp
new file mode 100644
index 0000000..1b6fa58
--- /dev/null
+++ b/source/Plugins/Process/Utility/UnwindLibUnwind.cpp
@@ -0,0 +1,73 @@
+//===-- UnwindLibUnwind.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
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/Thread.h"
+#include "UnwindLibUnwind.h"
+#include "LibUnwindRegisterContext.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+UnwindLibUnwind::UnwindLibUnwind (Thread &thread, unw_addr_space_t addr_space) :
+    Unwind (thread),
+    m_addr_space (addr_space),
+    m_cursors()
+{
+    m_pc_regnum = thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+    m_sp_regnum = thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+}
+
+uint32_t
+UnwindLibUnwind::GetFrameCount()
+{
+    if (m_cursors.empty())
+    {
+        unw_cursor_t cursor;
+        unw_init_remote (&cursor, m_addr_space, &m_thread);
+
+        m_cursors.push_back (cursor);
+
+        while (1) 
+        {
+            int stepresult = unw_step (&cursor);
+            if (stepresult > 0)
+                m_cursors.push_back (cursor);
+            else
+                break;
+        }
+    }
+    return m_cursors.size();
+}
+
+bool
+UnwindLibUnwind::GetFrameInfoAtIndex (uint32_t idx, addr_t& cfa, addr_t& pc)
+{
+    const uint32_t frame_count = GetFrameCount();
+    if (idx < frame_count)
+    {
+        int pc_err = unw_get_reg (&m_cursors[idx], m_pc_regnum, &pc);
+        int sp_err = unw_get_reg (&m_cursors[idx], m_sp_regnum, &cfa);
+        return pc_err == UNW_ESUCCESS && sp_err == UNW_ESUCCESS;
+    }
+    return false;
+}
+    
+RegisterContext *
+UnwindLibUnwind::CreateRegisterContextForFrame (StackFrame *frame)
+{
+    uint32_t idx = frame->GetID();
+    const uint32_t frame_count = GetFrameCount();
+    if (idx < frame_count)
+        return new LibUnwindRegisterContext (m_thread, frame, m_cursors[idx]);
+    return NULL;
+}
diff --git a/source/Plugins/Process/Utility/UnwindLibUnwind.h b/source/Plugins/Process/Utility/UnwindLibUnwind.h
new file mode 100644
index 0000000..d91f164
--- /dev/null
+++ b/source/Plugins/Process/Utility/UnwindLibUnwind.h
@@ -0,0 +1,66 @@
+//===-- UnwindLibUnwind.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_UnwindLibUnwind_h_
+#define lldb_UnwindLibUnwind_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+#include "libunwind.h"
+
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/Unwind.h"
+
+class UnwindLibUnwind : public lldb_private::Unwind
+{
+public: 
+    UnwindLibUnwind (lldb_private::Thread &thread, 
+                     lldb_private::unw_addr_space_t addr_space);
+    
+    virtual
+    ~UnwindLibUnwind()
+    {
+    }
+    
+    virtual void
+    Clear()
+    {
+        m_cursors.clear();
+    }
+
+    virtual uint32_t
+    GetFrameCount();
+
+    bool
+    GetFrameInfoAtIndex (uint32_t frame_idx,
+                         lldb::addr_t& cfa, 
+                         lldb::addr_t& pc);
+    
+    lldb_private::RegisterContext *
+    CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+
+    lldb_private::Thread &
+    GetThread();
+
+private:
+    lldb_private::unw_addr_space_t m_addr_space;
+    std::vector<lldb_private::unw_cursor_t> m_cursors;
+    uint32_t m_pc_regnum;
+    uint32_t m_sp_regnum;
+    //------------------------------------------------------------------
+    // For UnwindLibUnwind only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (UnwindLibUnwind);
+};
+
+#endif  // lldb_UnwindLibUnwind_h_
diff --git a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp
new file mode 100644
index 0000000..586e3d7
--- /dev/null
+++ b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp
@@ -0,0 +1,243 @@
+//===-- UnwindMacOSXFrameBackchain.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
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "RegisterContextMacOSXFrameBackchain.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+UnwindMacOSXFrameBackchain::UnwindMacOSXFrameBackchain (Thread &thread) :
+    Unwind (thread),
+    m_cursors()
+{
+}
+
+uint32_t
+UnwindMacOSXFrameBackchain::GetFrameCount()
+{
+    if (m_cursors.empty())
+    {
+        const ArchSpec target_arch (m_thread.GetProcess().GetTarget().GetArchitecture ());
+        // Frame zero should always be supplied by the thread...
+        StackFrameSP frame_sp (m_thread.GetStackFrameAtIndex (0));
+        if (target_arch == ArchSpec("x86_64"))
+            GetStackFrameData_x86_64 (frame_sp.get());
+        else if (target_arch == ArchSpec("i386"))
+            GetStackFrameData_i386 (frame_sp.get());
+
+    }
+    return m_cursors.size();
+}
+
+bool
+UnwindMacOSXFrameBackchain::GetFrameInfoAtIndex (uint32_t idx, addr_t& cfa, addr_t& pc)
+{
+    const uint32_t frame_count = GetFrameCount();
+    if (idx < frame_count)
+    {
+        if (m_cursors[idx].pc == LLDB_INVALID_ADDRESS)
+            return false;
+        if (m_cursors[idx].fp == LLDB_INVALID_ADDRESS)
+            return false;
+
+        pc = m_cursors[idx].pc;
+        cfa = m_cursors[idx].fp;
+
+        return true;
+    }
+    return false;
+}
+    
+RegisterContext *
+UnwindMacOSXFrameBackchain::CreateRegisterContextForFrame (StackFrame *frame)
+{
+    uint32_t idx = frame->GetID();
+    const uint32_t frame_count = GetFrameCount();
+    if (idx < frame_count)
+        return new RegisterContextMacOSXFrameBackchain (m_thread, frame, m_cursors[idx]);
+    return NULL;
+}
+
+size_t
+UnwindMacOSXFrameBackchain::GetStackFrameData_i386 (StackFrame *first_frame)
+{
+    m_cursors.clear();
+
+    std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair;
+
+    typedef struct Frame_i386
+    {
+        uint32_t fp;
+        uint32_t pc;
+    };
+
+    RegisterContext *reg_ctx = m_thread.GetRegisterContext();
+    assert (reg_ctx);
+
+    Cursor cursor;
+    cursor.pc = reg_ctx->GetPC (LLDB_INVALID_ADDRESS);
+    cursor.fp = reg_ctx->GetFP (0);
+    
+    Frame_i386 frame = { cursor.fp, cursor.pc };
+
+    m_cursors.push_back(cursor);
+
+    const size_t k_frame_size = sizeof(frame);
+    Error error;
+    while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0))
+    {
+        // Read both the FP and PC (8 bytes)
+        if (m_thread.GetProcess().ReadMemory (frame.fp, &frame.fp, k_frame_size, error) != k_frame_size)
+            break;
+        if (frame.pc >= 0x1000)
+        {
+            cursor.pc = frame.pc;
+            cursor.fp = frame.fp;
+            m_cursors.push_back (cursor);
+        }
+    }
+    if (!m_cursors.empty())
+    {
+        lldb::addr_t first_frame_pc = m_cursors.front().pc;
+        if (first_frame_pc != LLDB_INVALID_ADDRESS)
+        {
+            const uint32_t resolve_scope = eSymbolContextModule |
+                                           eSymbolContextCompUnit |
+                                           eSymbolContextFunction |
+                                           eSymbolContextSymbol;
+
+            SymbolContext first_frame_sc (first_frame->GetSymbolContext(resolve_scope));
+            const AddressRange *addr_range_ptr = NULL;
+            if (first_frame_sc.function)
+                addr_range_ptr = &first_frame_sc.function->GetAddressRange();
+            else if (first_frame_sc.symbol)
+                addr_range_ptr = first_frame_sc.symbol->GetAddressRangePtr();
+
+            if (addr_range_ptr)
+            {
+                if (first_frame->GetPC() == addr_range_ptr->GetBaseAddress())
+                {
+                    // We are at the first instruction, so we can recover the
+                    // previous PC by dereferencing the SP
+                    lldb::addr_t first_frame_sp = reg_ctx->GetSP (0);
+                    // Read the real second frame return address into frame.pc
+                    if (first_frame_sp && m_thread.GetProcess().ReadMemory (first_frame_sp, &frame.pc, sizeof(frame.pc), error) == sizeof(frame.pc))
+                    {
+                        cursor.fp = m_cursors.front().fp;
+                        cursor.pc = frame.pc;           // Set the new second frame PC
+
+                        // Insert the second frame
+                        m_cursors.insert(m_cursors.begin()+1, cursor);
+                        
+                        m_cursors.front().fp = first_frame_sp;
+                    }
+                }
+            }
+        }
+    }
+//    uint32_t i=0;
+//    printf("      PC                 FP\n");
+//    printf("      ------------------ ------------------ \n");
+//    for (i=0; i<m_cursors.size(); ++i)
+//    {
+//        printf("[%3u] 0x%16.16llx 0x%16.16llx\n", i, m_cursors[i].pc, m_cursors[i].fp);
+//    }
+    return m_cursors.size();
+}
+
+
+size_t
+UnwindMacOSXFrameBackchain::GetStackFrameData_x86_64 (StackFrame *first_frame)
+{
+    m_cursors.clear();
+
+    std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair;
+
+    typedef struct Frame_x86_64
+    {
+        uint64_t fp;
+        uint64_t pc;
+    };
+
+    RegisterContext *reg_ctx = m_thread.GetRegisterContext();
+    assert (reg_ctx);
+
+    Cursor cursor;
+    cursor.pc = reg_ctx->GetPC (LLDB_INVALID_ADDRESS);
+    cursor.fp = reg_ctx->GetFP (0);
+    
+    Frame_x86_64 frame = { cursor.fp, cursor.pc };
+
+    m_cursors.push_back(cursor);
+    Error error;
+    const size_t k_frame_size = sizeof(frame);
+    while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0))
+    {
+        // Read both the FP and PC (16 bytes)
+        if (m_thread.GetProcess().ReadMemory (frame.fp, &frame.fp, k_frame_size, error) != k_frame_size)
+            break;
+
+        if (frame.pc >= 0x1000)
+        {
+            cursor.pc = frame.pc;
+            cursor.fp = frame.fp;
+            m_cursors.push_back (cursor);
+        }
+    }
+    if (!m_cursors.empty())
+    {
+        lldb::addr_t first_frame_pc = m_cursors.front().pc;
+        if (first_frame_pc != LLDB_INVALID_ADDRESS)
+        {
+            const uint32_t resolve_scope = eSymbolContextModule |
+                                           eSymbolContextCompUnit |
+                                           eSymbolContextFunction |
+                                           eSymbolContextSymbol;
+
+            SymbolContext first_frame_sc(first_frame->GetSymbolContext(resolve_scope));
+            const AddressRange *addr_range_ptr = NULL;
+            if (first_frame_sc.function)
+                addr_range_ptr = &first_frame_sc.function->GetAddressRange();
+            else if (first_frame_sc.symbol)
+                addr_range_ptr = first_frame_sc.symbol->GetAddressRangePtr();
+
+            if (addr_range_ptr)
+            {
+                if (first_frame->GetPC() == addr_range_ptr->GetBaseAddress())
+                {
+                    // We are at the first instruction, so we can recover the
+                    // previous PC by dereferencing the SP
+                    lldb::addr_t first_frame_sp = reg_ctx->GetSP (0);
+                    // Read the real second frame return address into frame.pc
+                    if (m_thread.GetProcess().ReadMemory (first_frame_sp, &frame.pc, sizeof(frame.pc), error) == sizeof(frame.pc))
+                    {
+                        cursor.fp = m_cursors.front().fp;
+                        cursor.pc = frame.pc;           // Set the new second frame PC
+
+                        // Insert the second frame
+                        m_cursors.insert(m_cursors.begin()+1, cursor);
+                        
+                        m_cursors.front().fp = first_frame_sp;
+                    }
+                }
+            }
+        }
+    }
+    return m_cursors.size();
+}
+
diff --git a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h
new file mode 100644
index 0000000..86ba6e7
--- /dev/null
+++ b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h
@@ -0,0 +1,77 @@
+//===-- UnwindMacOSXFrameBackchain.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_UnwindMacOSXFrameBackchain_h_
+#define lldb_UnwindMacOSXFrameBackchain_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/Unwind.h"
+
+class UnwindMacOSXFrameBackchain : public lldb_private::Unwind
+{
+public: 
+    UnwindMacOSXFrameBackchain (lldb_private::Thread &thread);
+    
+    virtual
+    ~UnwindMacOSXFrameBackchain()
+    {
+    }
+    
+    virtual void
+    Clear()
+    {
+        m_cursors.clear();
+    }
+
+    virtual uint32_t
+    GetFrameCount();
+
+    bool
+    GetFrameInfoAtIndex (uint32_t frame_idx,
+                         lldb::addr_t& cfa, 
+                         lldb::addr_t& pc);
+    
+    lldb_private::RegisterContext *
+    CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+
+    lldb_private::Thread &
+    GetThread();
+
+protected:
+    friend class RegisterContextMacOSXFrameBackchain;
+
+    typedef struct Cursor
+    {
+        lldb::addr_t pc;    // Program counter
+        lldb::addr_t fp;    // Frame pointer for us with backchain
+    };
+
+private:
+    std::vector<Cursor> m_cursors;
+
+    size_t
+    GetStackFrameData_i386 (lldb_private::StackFrame *first_frame);
+
+    size_t
+    GetStackFrameData_x86_64 (lldb_private::StackFrame *first_frame);
+
+    //------------------------------------------------------------------
+    // For UnwindMacOSXFrameBackchain only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (UnwindMacOSXFrameBackchain);
+};
+
+#endif  // lldb_UnwindMacOSXFrameBackchain_h_
diff --git a/source/Plugins/Process/Utility/libunwind/include/libunwind.h b/source/Plugins/Process/Utility/libunwind/include/libunwind.h
new file mode 100644
index 0000000..63cc8ba
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/include/libunwind.h
@@ -0,0 +1,509 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- libunwind.h ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//            C interface to libuwind 
+//
+// Source compatible with Level 1 Base ABI documented at:
+//    http://www.codesourcery.com/public/cxx-abi/abi-eh.html
+// 
+//===----------------------------------------------------------------------===//
+
+
+#ifndef __LIBUNWIND__
+#define __LIBUNWIND__
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <mach/mach_types.h>
+#include <Availability.h>
+
+namespace lldb_private {
+
+#pragma mark Error codes
+
+enum {
+    UNW_ESUCCESS           = 0,            /* no error */
+    UNW_EUNSPEC            = -6540,        /* unspecified (general) error */
+    UNW_ENOMEM             = -6541,        /* out of memory */
+    UNW_EBADREG            = -6542,        /* bad register number */
+    UNW_EREADONLYREG       = -6543,        /* attempt to write read-only register */
+    UNW_ESTOPUNWIND        = -6544,        /* stop unwinding */
+    UNW_EINVALIDIP         = -6545,        /* invalid IP */
+    UNW_EBADFRAME          = -6546,        /* bad frame */
+    UNW_EINVAL             = -6547,        /* unsupported operation or bad value */
+    UNW_EBADVERSION        = -6548,        /* unwind info has unsupported version */
+    UNW_ENOINFO            = -6549,        /* no unwind info found */
+    UNW_EREGUNAVAILABLE    = -6550         /* contents of requested reg are not available */
+};
+
+#pragma mark General data structures
+
+struct unw_context_t { uint64_t data[128]; };
+typedef struct unw_context_t     unw_context_t;
+
+struct unw_cursor_t { uint64_t data[140]; };
+typedef struct unw_cursor_t      unw_cursor_t;
+
+enum unw_as_type { UNW_LOCAL, UNW_REMOTE };
+struct unw_addr_space
+{ 
+	enum unw_as_type type; 
+	uint8_t data[]; 
+};
+typedef struct unw_addr_space* unw_addr_space_t;
+
+typedef int                      unw_regnum_t;
+typedef uint64_t                 unw_word_t;
+typedef double                   unw_fpreg_t;
+
+enum unw_vecreg_format {
+	UNW_VECREG_SIGNED,
+	UNW_VECREG_UNSIGNED,
+	UNW_VECREG_FLOAT
+};
+
+typedef struct
+{
+	union {
+		double   doubles[8];
+		float    floats [16];
+		
+		uint64_t dwords	[8];
+		uint32_t words	[16];
+		uint16_t hwords	[32];
+		uint8_t  bytes	[64];
+	} data;
+	uint16_t unit_size; // bits
+	uint16_t num_units;
+	uint8_t format;
+} unw_vecreg_t;
+
+struct unw_proc_info_t
+{
+    unw_word_t    start_ip;         /* start address of function */
+    unw_word_t    end_ip;           /* address after end of function */
+    unw_word_t    lsda;             /* address of language specific data area, or zero if not used */
+    unw_word_t    handler;          /* personality routine, or zero if not used */
+    unw_word_t    gp;               /* not used */
+    unw_word_t    flags;            /* not used */
+    uint32_t      format;           /* compact unwind encoding, or zero if none */
+    uint32_t      unwind_info_size; /* size of dwarf unwind info, or zero if none */
+    unw_word_t    unwind_info;      /* address of dwarf unwind info, or zero if none */
+    unw_word_t    extra;            /* mach_header of mach-o image containing function */
+};
+typedef struct unw_proc_info_t unw_proc_info_t;
+
+#pragma mark Local API
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int         unw_getcontext(unw_context_t*)                               __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA);
+extern int         unw_init_local(unw_cursor_t*, unw_context_t*)                __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA);
+extern int         unw_step(unw_cursor_t*)                                      __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA);
+extern int         unw_get_reg(unw_cursor_t*, unw_regnum_t, unw_word_t*)        __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA);
+extern int         unw_get_fpreg(unw_cursor_t*, unw_regnum_t, unw_fpreg_t*)     __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA);
+extern int         unw_set_reg(unw_cursor_t*, unw_regnum_t, unw_word_t)         __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA);
+extern int         unw_set_fpreg(unw_cursor_t*, unw_regnum_t, unw_fpreg_t)      __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA);
+extern int         unw_resume(unw_cursor_t*)                                    __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA);
+
+extern const char* unw_regname(unw_cursor_t*, unw_regnum_t)                     __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA);
+extern int         unw_get_proc_info(unw_cursor_t*, unw_proc_info_t*)           __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA);
+extern int         unw_is_fpreg(unw_cursor_t*, unw_regnum_t)                    __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA);
+extern int         unw_is_signal_frame(unw_cursor_t*)                           __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA);
+extern int         unw_get_proc_name(unw_cursor_t*, char*, size_t, unw_word_t*) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA);
+//extern int       unw_get_save_loc(unw_cursor_t*, int, unw_save_loc_t*);
+
+
+#pragma mark Remote data structures
+	
+typedef enum {
+	UNW_NOT_A_REG = 0,
+	UNW_INTEGER_REG,
+	UNW_FLOATING_POINT_REG,
+	UNW_VECTOR_REG,
+	UNW_OTHER_REG
+} unw_regtype_t;
+
+typedef enum {
+	UNW_TARGET_UNSPECIFIED = 0,
+	UNW_TARGET_I386,
+	UNW_TARGET_X86_64,
+	UNW_TARGET_PPC,
+	UNW_TARGET_ARM
+} unw_targettype_t;
+
+typedef enum {
+    UNW_LOG_LEVEL_NONE =     0x00000000,
+    UNW_LOG_LEVEL_INFO =     0x00000001,
+    UNW_LOG_LEVEL_API =      0x00000002,
+    UNW_LOG_LEVEL_VERBOSE =  0x00000004,
+    UNW_LOG_LEVEL_TIMINGS =  0x00000008,
+    UNW_LOG_LEVEL_DEBUG =    0x00000010,
+    UNW_LOG_LEVEL_ALL =      0x0FFFFFFF
+} unw_log_level_t;
+
+typedef enum {
+	UNW_CACHE_NONE = 0,
+	UNW_CACHE_GLOBAL,
+	UNW_CACHE_PER_THREAD
+} unw_caching_policy_t;
+
+typedef struct {
+	int (*find_proc_info)(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pip, int need_unwind_info, void *arg);
+	int (*put_unwind_info)(unw_addr_space_t as, unw_proc_info_t *pip, void *arg);
+	int (*get_dyn_info_list_addr)(unw_addr_space_t as, unw_word_t *dilap, void *arg);
+
+	// Reads or writes a memory object the size of a target pointer.  
+    // Byte-swaps if necessary.
+	int (*access_mem)(unw_addr_space_t as, unw_word_t addr, unw_word_t *valp, int write, void *arg);
+	
+    // Register contents sent as-is (i.e. not byte-swapped).  
+    // Register numbers are the driver program's numbering scheme as 
+    // determined by the reg_info callbacks; libunwind will interrogate 
+    // the driver program to figure out which numbers it uses to refer to 
+    // which registers.
+	int (*access_reg)(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t *valp, int write, void *arg);
+	int (*access_fpreg)(unw_addr_space_t as, unw_regnum_t regnum, unw_fpreg_t *valp, int write, void *arg);
+	int (*resume)(unw_addr_space_t as, unw_cursor_t *cp, void *arg);
+	int (*get_proc_name)(unw_addr_space_t as, unw_word_t addr, char *bufp, size_t buf_len, unw_word_t *offp, void *arg);
+
+
+	// Added to find the start of the image (executable, bundle, dylib, etc) 
+    // for a given address.
+    //   as                     - The address space to use
+    //   ip                     - The address libunwind wants to know about
+    //   mh                     - The Mach-O header address for this image
+    //   text_start             - The start of __TEXT segment (all its sections)
+    //   text_end               - The end address of __TEXT segment (all its sections)
+    //   eh_frame               - The start of __TEXT,__eh_frame
+    //   eh_frame_len           - The length of __TEXT,__eh_frame
+    //   compact_unwind_start   - The start of __TEXT,__unwind_info
+    //   compact_unwind_len     - The length of __TEXT,__unwind_info
+    //   arg                    - The driver-provided generic argument
+    // All addresses are the in-memory, slid, addresses. 
+    // If eh_frame or unwind_info are missing, addr and len is returned as 0.
+    int (*find_image_info)(unw_addr_space_t as, unw_word_t ip, unw_word_t *mh, 
+                           unw_word_t *text_start, unw_word_t *text_end,
+                           unw_word_t *eh_frame, unw_word_t *eh_frame_len, 
+                           unw_word_t *compact_unwind_start, 
+                           unw_word_t *compact_unwind_len, void *arg);
+
+    // Added to get the start and end address of a function without needing
+    // all of the information (and potential allocation) that the
+    // find_proc_info() call entails.
+    //   as         - The address space to use
+    //   ip         - The address libunwind wants to know about
+    //   low        - The start address of the function at 'ip'
+    //   high       - The first address past the function at 'ip'
+    //   arg        - The driver-provided generic argument
+    // If HIGH is unknown, it should be set to 0.  All addresses
+    // are the in-memory, slid, addresses.
+	int (*get_proc_bounds)(unw_addr_space_t as, unw_word_t ip, 
+                           unw_word_t *low, unw_word_t *high, void *arg);
+
+    // Added to support accessing non-word-size memory objects across 
+    // platforms.  No byte swapping should be done.
+    //   as     - The address space to use
+    //   addr   - The starting address to access
+    //   extent - The extent of the region to access, in bytes
+    //   valp   - The local region to be written from / read into
+    //   write  - non-zero if the data is to be written into the target
+    //            rather than read
+    //   arg    - The driver-provided generic argument (see unw_init_remote)
+    int (*access_raw)(unw_addr_space_t as, unw_word_t addr, unw_word_t extent, 
+                      uint8_t *valp, int write, void *arg);
+
+    // Added to support identifying registers.
+    // libunwind will interrogate the driver program via this callback to
+    // identify what register numbers it is using; the register names are
+    // used to correlate that the driver program's register numbers with
+    // libunwind's internal register numbers.  The driver program should
+    // use its own register numbers when requesting registers with
+    // unw_get_reg() and libunwind will provide the driver program's
+    // register numbers to the access_reg callback function.
+    //   as         - The address space to use
+    //   regnum     - The register number
+    //   type       - Write the register type to this address
+    //                For a non-existent register, return UNW_ESUCCESS but 
+    //                write UNW_NOT_A_REG to type
+    //   buf        - If non-NULL, the register name is written to this address
+    //   buf_len    - The size of the buffer provided for the register name
+    //   arg        - The driver-provided generic argument (see unw_init_remote)
+    int (*reg_info)(unw_addr_space_t as, unw_regnum_t regnum, 
+                    unw_regtype_t* type, char *bufp, size_t buf_len, void *arg);
+
+	// Added to read a vector register's value from the remote machine.
+	//   as			- The address space to use
+	//   regnum		- The register number
+	//   valp		- The local region to be written from / read into
+	//   write		- non-zero if the data is to be written into the target 
+    //                rather than read
+	//   arg		- The driver-specified generic argument
+	int (*access_vecreg)(unw_addr_space_t as, unw_regnum_t regnum, 
+                         unw_vecreg_t* valp, int write, void *arg);
+
+    // Added to identify if an unwind cursor is pointing to _sigtramp().
+    // After a _sigtramp we have an entire register set available and we should
+    // return any of the registers requested.
+    //  as          - The address space to use
+    //  ip          - The address of the function libunwind is examining
+    //  arg         - The driver-provided generic argument
+    // This function returns non-zero if ip is in _sigtramp.
+    int (*proc_is_sigtramp) (unw_addr_space_t as, unw_word_t ip, void *arg);
+
+    // Added to identify if an unwind cursor is pointing to a debugger's
+    // inferior function call dummy frame.
+    // The driver program will need to provide the full register set (via the
+    // standard access_reg callback) for the function that was executing 
+    // when the inferior function call was made; it will use these register
+    // values and not try to unwind out of the inferior function call dummy
+    // frame.
+    // After a inf func call we have an entire register set available and 
+    // we should return any of the registers requested.
+    //  as          - The address space to use
+    //  ip          - The address of the function libunwind is examining
+    //  sp          - The stack pointer value of the frame
+    //  arg         - The driver-provided generic argument (see unw_init_remote)
+    // This function returns non-zero if ip/sp is an inferior function call 
+    // dummy frame.
+    int (*proc_is_inferior_function_call) (unw_addr_space_t as, unw_word_t ip, 
+                                           unw_word_t sp, void *arg);
+
+    // Added to retrieve a register value from a above a debugger's inferior
+    // function call dummy frame.  Similar to _sigtramp but the debugger will
+    // have the register context squirreled away in its own memory (or possibly
+    // saved on the stack somewhere).
+    // May be NULL if the program being unwound will not have a debugger
+    // calling functions mid-execution.
+    //   as         - The address space to use
+    //   ip         - The pc value for the dummy frame
+    //   sp         - The stack pointer for the dummy frame
+    //   regnum     - The register number in the driver program's register
+    //                numbering scheme.
+    //   valp       - Pointer to a word of memory to be read/written
+    //   write      - Non-zero if libunwind is writing a new value to the reg,
+    //                else it is reading the contents of that register.
+    //   arg        - The driver-provided generic argument (see unw_init_remote)
+	int (*access_reg_inf_func_call)(unw_addr_space_t as, unw_word_t ip, 
+                                    unw_word_t sp, unw_regnum_t regnum, 
+                                    unw_word_t *valp, int write, void *arg);
+
+    // Added to iterate over unknown assembly instructions when analyzing a
+    // function prologue.  Needed for ISAs with variable length instructions
+    // (i386, x86_64) or multiple instruction sizes (arm, thumb).
+    // Returns zero if the instruction length was successfully measured.
+    //  as         - The address space to use
+    //  addr       - The address of the instruction being measured
+    //  length     - Set to the length of the instruction
+    //  arg        - The driver-provided generic argument (see unw_init_remote)
+    int (*instruction_length)(unw_addr_space_t as, unw_word_t addr, 
+                              int *length, void *arg);
+
+} unw_accessors_t;
+
+extern int               unw_init_remote(unw_cursor_t*, unw_addr_space_t, void*)			__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA);
+extern unw_accessors_t*  unw_get_accessors(unw_addr_space_t)								__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA);
+extern unw_addr_space_t	 unw_create_addr_space(unw_accessors_t*, unw_targettype_t)	        __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA);
+extern void              unw_flush_caches(unw_addr_space_t)			                        __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA);
+extern int               unw_set_caching_policy(unw_addr_space_t, unw_caching_policy_t)		__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA);
+extern void              unw_destroy_addr_space(unw_addr_space_t asp)                       __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA);
+extern void              unw_set_logging_level(unw_addr_space_t, FILE *, unw_log_level_t)   __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); 
+
+// Should be called when remote unwinding if a bundle in the remote process 
+// is unloaded
+extern void              unw_image_was_unloaded(unw_addr_space_t, unw_word_t mh)            __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA);
+
+// Try to discern where the function's prologue instructions end
+//   start - start address of the function, required
+//   end   - first address beyond the function, or zero if unknown
+//   endofprologue - set to the address after the last prologue instruction if successful
+extern int               unw_end_of_prologue_setup(unw_cursor_t*, unw_word_t start, unw_word_t end, unw_word_t *endofprologue) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA);
+
+/*
+ * Dynamic unwinding API
+ *     NOT IMPLEMENTED on Mac OS X 
+ * extern void              _U_dyn_register(unw_dyn_info_t*);
+ * extern void              _U_dyn_cancel(unw_dyn_info_t*);
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#pragma mark Register numbers
+
+// architecture independent register numbers 
+enum {
+    UNW_REG_IP = -1,        // instruction pointer
+    UNW_REG_SP = -2,        // stack pointer
+};
+
+
+// 32-bit x86 registers
+enum {
+    UNW_X86_EAX = 0,
+    UNW_X86_ECX = 1,
+    UNW_X86_EDX = 2,
+    UNW_X86_EBX = 3,
+    UNW_X86_EBP = 4,
+    UNW_X86_ESP = 5,
+    UNW_X86_ESI = 6,
+    UNW_X86_EDI = 7
+};
+
+
+// 64-bit x86_64 registers
+enum {
+    UNW_X86_64_RAX =  0,
+    UNW_X86_64_RDX =  1,
+    UNW_X86_64_RCX =  2,
+    UNW_X86_64_RBX =  3,
+    UNW_X86_64_RSI =  4,
+    UNW_X86_64_RDI =  5,
+    UNW_X86_64_RBP =  6,
+    UNW_X86_64_RSP =  7,
+    UNW_X86_64_R8  =  8,
+    UNW_X86_64_R9  =  9,
+    UNW_X86_64_R10 = 10,
+    UNW_X86_64_R11 = 11,
+    UNW_X86_64_R12 = 12,
+    UNW_X86_64_R13 = 13,
+    UNW_X86_64_R14 = 14,
+    UNW_X86_64_R15 = 15
+};
+
+
+// 32-bit ppc register numbers
+enum {
+    UNW_PPC_R0  =  0,
+    UNW_PPC_R1  =  1,
+    UNW_PPC_R2  =  2,
+    UNW_PPC_R3  =  3,
+    UNW_PPC_R4  =  4,
+    UNW_PPC_R5  =  5,
+    UNW_PPC_R6  =  6,
+    UNW_PPC_R7  =  7,
+    UNW_PPC_R8  =  8,
+    UNW_PPC_R9  =  9,
+    UNW_PPC_R10 = 10,
+    UNW_PPC_R11 = 11,
+    UNW_PPC_R12 = 12,
+    UNW_PPC_R13 = 13,
+    UNW_PPC_R14 = 14,
+    UNW_PPC_R15 = 15,
+    UNW_PPC_R16 = 16,
+    UNW_PPC_R17 = 17,
+    UNW_PPC_R18 = 18,
+    UNW_PPC_R19 = 19,
+    UNW_PPC_R20 = 20,
+    UNW_PPC_R21 = 21,
+    UNW_PPC_R22 = 22,
+    UNW_PPC_R23 = 23,
+    UNW_PPC_R24 = 24,
+    UNW_PPC_R25 = 25,
+    UNW_PPC_R26 = 26,
+    UNW_PPC_R27 = 27,
+    UNW_PPC_R28 = 28,
+    UNW_PPC_R29 = 29,
+    UNW_PPC_R30 = 30,
+    UNW_PPC_R31 = 31,
+    UNW_PPC_F0  = 32,
+    UNW_PPC_F1  = 33,
+    UNW_PPC_F2  = 34,
+    UNW_PPC_F3  = 35,
+    UNW_PPC_F4  = 36,
+    UNW_PPC_F5  = 37,
+    UNW_PPC_F6  = 38,
+    UNW_PPC_F7  = 39,
+    UNW_PPC_F8  = 40,
+    UNW_PPC_F9  = 41,
+    UNW_PPC_F10 = 42,
+    UNW_PPC_F11 = 43,
+    UNW_PPC_F12 = 44,
+    UNW_PPC_F13 = 45,
+    UNW_PPC_F14 = 46,
+    UNW_PPC_F15 = 47,
+    UNW_PPC_F16 = 48,
+    UNW_PPC_F17 = 49,
+    UNW_PPC_F18 = 50,
+    UNW_PPC_F19 = 51,
+    UNW_PPC_F20 = 52,
+    UNW_PPC_F21 = 53,
+    UNW_PPC_F22 = 54,
+    UNW_PPC_F23 = 55,
+    UNW_PPC_F24 = 56,
+    UNW_PPC_F25 = 57,
+    UNW_PPC_F26 = 58,
+    UNW_PPC_F27 = 59,
+    UNW_PPC_F28 = 60,
+    UNW_PPC_F29 = 61,
+    UNW_PPC_F30 = 62,
+    UNW_PPC_F31 = 63,
+    UNW_PPC_MQ  = 64,
+    UNW_PPC_LR  = 65,
+    UNW_PPC_CTR = 66,
+    UNW_PPC_AP  = 67,
+	UNW_PPC_CR0 = 68,
+    UNW_PPC_CR1 = 69,
+	UNW_PPC_CR2 = 70,
+	UNW_PPC_CR3 = 71,
+	UNW_PPC_CR4 = 72,
+	UNW_PPC_CR5 = 73,
+	UNW_PPC_CR6 = 74,
+	UNW_PPC_CR7 = 75,
+	UNW_PPC_XER = 76,
+	UNW_PPC_V0  = 77,
+    UNW_PPC_V1  = 78,
+    UNW_PPC_V2  = 79,
+    UNW_PPC_V3  = 80,
+    UNW_PPC_V4  = 81,
+    UNW_PPC_V5  = 82,
+    UNW_PPC_V6  = 83,
+    UNW_PPC_V7  = 84,
+    UNW_PPC_V8  = 85,
+    UNW_PPC_V9  = 86,
+    UNW_PPC_V10 = 87,
+    UNW_PPC_V11 = 88,
+    UNW_PPC_V12 = 89,
+    UNW_PPC_V13 = 90,
+    UNW_PPC_V14 = 91,
+    UNW_PPC_V15 = 92,
+    UNW_PPC_V16 = 93,
+    UNW_PPC_V17 = 94,
+    UNW_PPC_V18 = 95,
+    UNW_PPC_V19 = 96,
+    UNW_PPC_V20 = 97,
+    UNW_PPC_V21 = 98,
+    UNW_PPC_V22 = 99,
+    UNW_PPC_V23 = 100,
+    UNW_PPC_V24 = 101,
+    UNW_PPC_V25 = 102,
+    UNW_PPC_V26 = 103,
+    UNW_PPC_V27 = 104,
+    UNW_PPC_V28 = 105,
+    UNW_PPC_V29 = 106,
+    UNW_PPC_V30 = 107,
+    UNW_PPC_V31 = 108,
+    UNW_PPC_VRSAVE  = 109,
+    UNW_PPC_VSCR    = 110,
+    UNW_PPC_SPE_ACC = 111,
+    UNW_PPC_SPEFSCR = 112
+	
+};
+
+
+}; // namespace lldb_private
+
+
+#endif
+
diff --git a/source/Plugins/Process/Utility/libunwind/include/mach-o/compact_unwind_encoding.h b/source/Plugins/Process/Utility/libunwind/include/mach-o/compact_unwind_encoding.h
new file mode 100644
index 0000000..bee2ad5
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/include/mach-o/compact_unwind_encoding.h
@@ -0,0 +1,212 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- compact_unwind_encoding.h -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+ 
+
+#ifndef __COMPACT_UNWIND_ENCODING__
+#define __COMPACT_UNWIND_ENCODING__
+
+#include <stdint.h>
+
+namespace lldb_private {
+
+// 
+// Each final linked mach-o image has an optional __TEXT, __unwind_info section.
+// This section is much smaller and faster to use than the __eh_frame section.
+//
+
+
+
+//
+// Compilers usually emit standard Dwarf FDEs.  The linker recognizes standard FDEs and
+// synthesizes a matching compact_unwind_encoding_t and adds it to the __unwind_info table.
+// It is also possible for the compiler to emit __unwind_info entries for functions that 
+// have different unwind requirements at different ranges in the function.
+//
+typedef uint32_t compact_unwind_encoding_t;
+
+
+
+//
+// The __unwind_info section is laid out for an efficient two level lookup.
+// The header of the section contains a coarse index that maps function address
+// to the page (4096 byte block) containing the unwind info for that function.  
+//
+
+#define UNWIND_SECTION_VERSION 1
+struct unwind_info_section_header
+{
+    uint32_t    version;            // UNWIND_SECTION_VERSION
+    uint32_t    commonEncodingsArraySectionOffset;
+    uint32_t    commonEncodingsArrayCount;
+    uint32_t    personalityArraySectionOffset;
+    uint32_t    personalityArrayCount;
+    uint32_t    indexSectionOffset;
+    uint32_t    indexCount;
+    // compact_unwind_encoding_t[]
+    // uintptr_t personalities[]
+    // unwind_info_section_header_index_entry[]
+    // unwind_info_section_header_lsda_index_entry[]
+};
+
+struct unwind_info_section_header_index_entry 
+{
+    uint32_t        functionOffset;
+    uint32_t        secondLevelPagesSectionOffset;  // section offset to start of regular or compress page
+    uint32_t        lsdaIndexArraySectionOffset;    // section offset to start of lsda_index array for this range
+};
+
+struct unwind_info_section_header_lsda_index_entry 
+{
+    uint32_t        functionOffset;
+    uint32_t        lsdaOffset;
+};
+
+//
+// There are two kinds of second level index pages: regular and compressed.
+// A compressed page can hold up to 1021 entries, but it cannot be used
+// if too many different encoding types are used.  The regular page holds
+// 511 entries.  
+//
+
+struct unwind_info_regular_second_level_entry 
+{
+    uint32_t                    functionOffset;
+    compact_unwind_encoding_t    encoding;
+};
+
+#define UNWIND_SECOND_LEVEL_REGULAR 2
+struct unwind_info_regular_second_level_page_header
+{
+    uint32_t    kind;    // UNWIND_SECOND_LEVEL_REGULAR
+    uint16_t    entryPageOffset;
+    uint16_t    entryCount;
+    // entry array
+};
+
+#define UNWIND_SECOND_LEVEL_COMPRESSED 3
+struct unwind_info_compressed_second_level_page_header
+{
+    uint32_t    kind;    // UNWIND_SECOND_LEVEL_COMPRESSED
+    uint16_t    entryPageOffset;
+    uint16_t    entryCount;
+    uint16_t    encodingsPageOffset;
+    uint16_t    encodingsCount;
+    // 32-bit entry array    
+    // encodings array
+};
+
+#define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry)            (entry & 0x00FFFFFF)
+#define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry)        ((entry >> 24) & 0xFF)
+
+
+
+// architecture independent bits
+enum {
+    UNWIND_IS_NOT_FUNCTION_START           = 0x80000000,
+    UNWIND_HAS_LSDA                        = 0x40000000,
+    UNWIND_PERSONALITY_MASK                = 0x30000000,
+};
+
+
+// x86_64
+//
+// 1-bit: start
+// 1-bit: has lsda
+// 2-bit: personality index
+//
+// 4-bits: 0=old, 1=rbp based, 2=stack-imm, 3=stack-ind, 4=dwarf
+//  rbp based:
+//        15-bits (5*3-bits per reg) register permutation
+//        8-bits for stack offset
+//  frameless:
+//        8-bits stack size
+//        3-bits stack adjust
+//        3-bits register count
+//        10-bits register permutation
+//
+enum {
+    UNWIND_X86_64_MODE_MASK                         = 0x0F000000,
+    UNWIND_X86_64_MODE_COMPATIBILITY                = 0x00000000,
+    UNWIND_X86_64_MODE_RBP_FRAME                    = 0x01000000,
+    UNWIND_X86_64_MODE_STACK_IMMD                   = 0x02000000,
+    UNWIND_X86_64_MODE_STACK_IND                    = 0x03000000,
+    UNWIND_X86_64_MODE_DWARF                        = 0x04000000,
+    
+    UNWIND_X86_64_RBP_FRAME_REGISTERS               = 0x00007FFF,
+    UNWIND_X86_64_RBP_FRAME_OFFSET                  = 0x00FF0000,
+
+    UNWIND_X86_64_FRAMELESS_STACK_SIZE              = 0x00FF0000,
+    UNWIND_X86_64_FRAMELESS_STACK_ADJUST            = 0x0000E000,
+    UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT         = 0x00001C00,
+    UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION   = 0x000003FF,
+
+    UNWIND_X86_64_DWARF_SECTION_OFFSET              = 0x00FFFFFF,
+};
+
+enum {
+    UNWIND_X86_64_REG_NONE       = 0,
+    UNWIND_X86_64_REG_RBX        = 1,
+    UNWIND_X86_64_REG_R12        = 2,
+    UNWIND_X86_64_REG_R13        = 3,
+    UNWIND_X86_64_REG_R14        = 4,
+    UNWIND_X86_64_REG_R15        = 5,
+    UNWIND_X86_64_REG_RBP        = 6,
+};
+
+
+// x86
+//
+// 1-bit: start
+// 1-bit: has lsda
+// 2-bit: personality index
+//
+// 4-bits: 0=old, 1=ebp based, 2=stack-imm, 3=stack-ind, 4=dwarf
+//  ebp based:
+//        15-bits (5*3-bits per reg) register permutation
+//        8-bits for stack offset
+//  frameless:
+//        8-bits stack size
+//        3-bits stack adjust
+//        3-bits register count
+//        10-bits register permutation
+//
+enum {
+    UNWIND_X86_MODE_MASK                         = 0x0F000000,
+    UNWIND_X86_MODE_COMPATIBILITY                = 0x00000000,
+    UNWIND_X86_MODE_EBP_FRAME                    = 0x01000000,
+    UNWIND_X86_MODE_STACK_IMMD                   = 0x02000000,
+    UNWIND_X86_MODE_STACK_IND                    = 0x03000000,
+    UNWIND_X86_MODE_DWARF                        = 0x04000000,
+    
+    UNWIND_X86_EBP_FRAME_REGISTERS               = 0x00007FFF,
+    UNWIND_X86_EBP_FRAME_OFFSET                  = 0x00FF0000,
+    
+    UNWIND_X86_FRAMELESS_STACK_SIZE              = 0x00FF0000,
+    UNWIND_X86_FRAMELESS_STACK_ADJUST            = 0x0000E000,
+    UNWIND_X86_FRAMELESS_STACK_REG_COUNT         = 0x00001C00,
+    UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION   = 0x000003FF,
+    
+    UNWIND_X86_DWARF_SECTION_OFFSET              = 0x00FFFFFF,
+};
+
+enum {
+    UNWIND_X86_REG_NONE     = 0,
+    UNWIND_X86_REG_EBX      = 1,
+    UNWIND_X86_REG_ECX      = 2,
+    UNWIND_X86_REG_EDX      = 3,
+    UNWIND_X86_REG_EDI      = 4,
+    UNWIND_X86_REG_ESI      = 5,
+    UNWIND_X86_REG_EBP      = 6,
+};
+
+}; // namespace lldb_private
+
+#endif
+
diff --git a/source/Plugins/Process/Utility/libunwind/include/unwind.h b/source/Plugins/Process/Utility/libunwind/include/unwind.h
new file mode 100644
index 0000000..80b9d28
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/include/unwind.h
@@ -0,0 +1,213 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- unwind.h ------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//            C interface to libuwind 
+//
+// Source compatible with Level 1 Base ABI documented at:
+//    http://www.codesourcery.com/public/cxx-abi/abi-eh.html
+// 
+//===----------------------------------------------------------------------===//
+
+
+#ifndef __UNWIND_H__
+#define __UNWIND_H__
+
+#include <stdint.h>
+#include <stddef.h>
+#include <Availability.h>
+
+namespace lldb_private {
+
+typedef enum {
+	_URC_NO_REASON = 0,
+	_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
+	_URC_FATAL_PHASE2_ERROR = 2,
+	_URC_FATAL_PHASE1_ERROR = 3,
+	_URC_NORMAL_STOP = 4,
+	_URC_END_OF_STACK = 5,
+	_URC_HANDLER_FOUND = 6,
+	_URC_INSTALL_CONTEXT = 7,
+	_URC_CONTINUE_UNWIND = 8
+} _Unwind_Reason_Code;
+
+typedef enum {
+        _UA_SEARCH_PHASE = 1,
+        _UA_CLEANUP_PHASE = 2,
+        _UA_HANDLER_FRAME = 4,
+        _UA_FORCE_UNWIND = 8,
+        _UA_END_OF_STACK = 16	// gcc extension to C++ ABI
+} _Unwind_Action;
+
+
+struct _Unwind_Context;		// opaque 
+struct _Unwind_Exception;	// forward declaration
+
+struct _Unwind_Exception {
+	uint64_t                   exception_class;
+	void							(*exception_cleanup)(_Unwind_Reason_Code reason, struct _Unwind_Exception* exc);
+	uintptr_t                  private_1;        // non-zero means forced unwind
+	uintptr_t                  private_2;        // holds sp that phase1 found for phase2 to use
+};
+
+
+typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
+		(int version,
+		 _Unwind_Action actions,
+		 uint64_t exceptionClass,
+		 struct _Unwind_Exception* exceptionObject,
+		 struct _Unwind_Context* context,
+		 void* stop_parameter );
+
+
+typedef _Unwind_Reason_Code (*__personality_routine)
+	    (int version,
+	     _Unwind_Action actions,
+	     uint64_t exceptionClass,
+	     struct _Unwind_Exception* exceptionObject,
+	     struct _Unwind_Context* context);
+		 
+
+		 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//
+// The following are the base functions documented by the C++ ABI
+//
+#if __arm__
+	extern _Unwind_Reason_Code _Unwind_SjLj_RaiseException(struct _Unwind_Exception* exception_object);
+	extern void		          _Unwind_SjLj_Resume(struct _Unwind_Exception* exception_object);
+#else
+	extern _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception* exception_object);
+	extern void		          _Unwind_Resume(struct _Unwind_Exception* exception_object);
+#endif
+extern void		_Unwind_DeleteException(struct _Unwind_Exception* exception_object);
+extern uintptr_t _Unwind_GetGR(struct _Unwind_Context* context, int index);
+extern void		_Unwind_SetGR(struct _Unwind_Context* context, int index, uintptr_t new_value);
+extern uintptr_t _Unwind_GetIP(struct _Unwind_Context* context);
+extern void		_Unwind_SetIP(struct _Unwind_Context*, uintptr_t new_value);
+extern uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context* context);
+extern uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context* context);
+#if __arm__
+	extern _Unwind_Reason_Code _Unwind_SjLj_ForcedUnwind(struct _Unwind_Exception* exception_object, _Unwind_Stop_Fn stop, void* stop_parameter );
+#else	
+	extern _Unwind_Reason_Code _Unwind_ForcedUnwind(struct _Unwind_Exception* exception_object, _Unwind_Stop_Fn stop, void* stop_parameter );
+#endif
+
+#if __arm__
+	typedef struct _Unwind_FunctionContext* _Unwind_FunctionContext_t;
+	extern void _Unwind_SjLj_Register(_Unwind_FunctionContext_t fc);
+	extern void _Unwind_SjLj_Unregister(_Unwind_FunctionContext_t fc);
+#endif	
+	
+//
+// The following are semi-suppoted extensions to the C++ ABI
+//
+
+
+//
+//	called by __cxa_rethrow().  
+//
+#if __arm__
+	extern _Unwind_Reason_Code _Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception* exception_object);
+#else
+	extern _Unwind_Reason_Code _Unwind_Resume_or_Rethrow(struct _Unwind_Exception* exception_object);
+#endif
+	
+
+//
+// _Unwind_Backtrace() is a gcc extension that walks the stack and calls the 
+// _Unwind_Trace_Fn once per frame until it reaches the bottom of the stack
+// or the _Unwind_Trace_Fn function returns something other than _URC_NO_REASON.
+//
+typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)(struct _Unwind_Context*, void*);
+extern _Unwind_Reason_Code	_Unwind_Backtrace(_Unwind_Trace_Fn, void*);
+
+
+//
+// _Unwind_GetCFA is a gcc extension that can be called from within a personality 
+// handler to get the CFA (stack pointer before call) of current frame.
+//
+extern uintptr_t _Unwind_GetCFA(struct _Unwind_Context*);
+
+
+//
+// _Unwind_GetIPInfo is a gcc extension that can be called from within a personality 
+// handler.  Similar to _Unwind_GetIP() but also returns in *ipBefore a non-zero 
+// value if the instruction pointer is at or before the instruction causing 
+// the unwind.  Normally, in a function call, the IP returned is the return address
+// which is after the call instruction and may be past the end of the function
+// containing the call instruction.
+//
+extern uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context* context, int* ipBefore);
+
+
+//
+// __register_frame() is used with dynamically generated code to register the FDE
+// for a generated (JIT) code.  The FDE must use pc-rel addressing to point to its
+// function and optional LSDA.  __register_frame() has existed in all versions of
+// Mac OS X, but in 10.4 and 10.5 it was buggy and did not actually register the 
+// FDE with the unwinder.  In 10.6 and later it does register properly.
+//
+extern void	__register_frame(const void* fde);
+extern void	__deregister_frame(const void* fde);
+
+
+//
+// _Unwind_Find_FDE() will locate the FDE if the pc is in some function that has
+// an associated FDE. Note, Mac OS X 10.6 and later, introduces "compact unwind info"
+// which the runtime uses in preference to dwarf unwind info.  This function
+// will only work if the target function has an FDE but no compact unwind info.
+//
+struct dwarf_eh_bases
+{
+    uintptr_t tbase;
+    uintptr_t dbase;
+    uintptr_t func;
+};
+extern const void* _Unwind_Find_FDE(const void* pc, struct dwarf_eh_bases*);
+
+
+//
+// This function attempts to find the start (address of first instruction) of
+// a function given an address inside the function.  It only works if the function
+// has an FDE (dwarf unwind info).  
+// This function is unimplemented on Mac OS X 10.6 and later.  Instead, use
+// _Unwind_Find_FDE() and look at the dwarf_eh_bases.func result.
+extern void* _Unwind_FindEnclosingFunction(void* pc);
+
+
+// Mac OS X does not support text-rel and data-rel addressing so these functions are unimplemented
+extern uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context* context) __attribute__((unavailable));
+extern uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context* context) __attribute__((unavailable));
+
+
+
+// Mac OS X 10.4 and 10.5 had implementations of these functions in libgcc_s.dylib,
+// but they never worked.  These functions are no longer available.
+extern void	 __register_frame_info_bases(const void* fde, void* ob, void* tb, void* db) __attribute__((unavailable));
+extern void	 __register_frame_info(const void* fde, void* ob) __attribute__((unavailable));
+extern void	 __register_frame_info_table_bases(const void* fde, void* ob,void* tb, void* db) __attribute__((unavailable));
+extern void	 __register_frame_info_table(const void* fde, void* ob) __attribute__((unavailable));
+extern void	 __register_frame_table(const void* fde) __attribute__((unavailable));
+extern void* __deregister_frame_info(const void* fde) __attribute__((unavailable));
+extern void* __deregister_frame_info_bases(const void* fde) __attribute__((unavailable));
+
+
+#ifdef __cplusplus
+}
+#endif
+
+}; // namespace lldb_private
+
+#endif // __UNWIND_H__
+
+
diff --git a/source/Plugins/Process/Utility/libunwind/src/AddressSpace.hpp b/source/Plugins/Process/Utility/libunwind/src/AddressSpace.hpp
new file mode 100644
index 0000000..5173dc0
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/AddressSpace.hpp
@@ -0,0 +1,456 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- AddressSpace.hpp ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+ 
+//
+//	C++ interface to lower levels of libuwind 
+//
+
+#ifndef __ADDRESSSPACE_HPP__
+#define __ADDRESSSPACE_HPP__
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <mach-o/loader.h>
+#include <mach-o/getsect.h>
+#if !defined (SUPPORT_REMOTE_UNWINDING)
+#include <mach-o/dyld_priv.h>
+#endif
+#include <mach/ppc/thread_status.h>
+#include <mach/i386/thread_status.h>
+#include <Availability.h>
+
+#include "FileAbstraction.hpp"
+#include "libunwind.h"
+#include "InternalMacros.h"
+#include "dwarf2.h"
+#include "RemoteProcInfo.hpp"
+
+#if defined (SUPPORT_REMOTE_UNWINDING)
+bool _dyld_find_unwind_sections(void* addr, void* info)
+{
+    assert("unwinding with a non-remote process not supported.");
+    return false;
+}
+#endif // SUPPORT_REMOTE_UNWINDING
+
+namespace lldb_private {
+
+///
+/// LocalAddressSpace is used as a template parameter to UnwindCursor when unwinding a thread
+/// in the same process.  It compiles away and making local unwinds very fast.
+///
+class LocalAddressSpace
+{
+public:
+	
+	#if __LP64__
+		typedef uint64_t	pint_t;
+		typedef  int64_t	sint_t;
+	#else
+		typedef uint32_t	pint_t;
+		typedef  int32_t	sint_t;
+	#endif
+        int			    getBytes(pint_t addr, pint_t extent, uint8_t* buf) { memcpy(buf, (void*)addr, extent); return 1; }
+		uint8_t			get8(pint_t addr)	{ return *((uint8_t*)addr); }
+		uint16_t		get16(pint_t addr)	{ return *((uint16_t*)addr); }
+		uint32_t		get32(pint_t addr)	{ return *((uint32_t*)addr); }
+		uint64_t		get64(pint_t addr)	{ return *((uint64_t*)addr); }
+		double			getDouble(pint_t addr)	{ return *((double*)addr); }
+		v128			getVector(pint_t addr)	{ return *((v128*)addr); }
+
+		uint8_t			get8(pint_t addr, int& err)	    { return *((uint8_t*)addr); err = 0; }
+		uint16_t		get16(pint_t addr, int& err)	{ return *((uint16_t*)addr); err = 0; }
+		uint32_t		get32(pint_t addr, int& err)	{ return *((uint32_t*)addr); err = 0; }
+		uint64_t		get64(pint_t addr, int& err)	{ return *((uint64_t*)addr); err = 0; }
+		double			getDouble(pint_t addr, int& err)	{ return *((double*)addr); err = 0; }
+		v128			getVector(pint_t addr, int& err)	{ return *((v128*)addr); err = 0; }
+
+		uintptr_t		getP(pint_t addr);
+        uintptr_t       getP(pint_t addr, int &err);
+        static uint64_t	getULEB128(pint_t& addr, pint_t end);
+        static int64_t	getSLEB128(pint_t& addr, pint_t end);
+	
+		pint_t			getEncodedP(pint_t& addr, pint_t end, uint8_t encoding);
+		bool			findFunctionName(pint_t addr, char* buf, size_t bufLen, unw_word_t* offset);
+		bool			findUnwindSections(pint_t addr, pint_t& mh, pint_t& dwarfStart, pint_t& dwarfLen, pint_t& compactStart);
+
+#if defined (SUPPORT_REMOTE_UNWINDING)
+        RemoteProcInfo*         getRemoteProcInfo ()    { return NULL; }
+        unw_accessors_t*        accessors()             { return NULL; }
+        unw_addr_space_t        wrap()                  { return NULL; }
+#endif
+};
+
+LocalAddressSpace sThisAddress;
+
+inline uintptr_t LocalAddressSpace::getP(pint_t addr)
+{
+#if __LP64__
+	return get64(addr);
+#else
+	return get32(addr);
+#endif
+}
+
+inline uintptr_t LocalAddressSpace::getP(pint_t addr, int &err)
+{
+#if __LP64__
+	return get64(addr);
+#else
+	return get32(addr);
+#endif
+    err = 0;
+}
+
+/* Read a ULEB128 into a 64-bit word.   */
+inline uint64_t
+LocalAddressSpace::getULEB128(pint_t& addr, pint_t end)
+{
+	const uint8_t* p = (uint8_t*)addr;
+	const uint8_t* pend = (uint8_t*)end;
+	uint64_t result = 0;
+	int bit = 0;
+	do  {
+		uint64_t b;
+
+		if ( p == pend )
+			ABORT("truncated uleb128 expression");
+
+		b = *p & 0x7f;
+
+		if (bit >= 64 || b << bit >> bit != b) {
+			ABORT("malformed uleb128 expression");
+		}
+		else {
+			result |= b << bit;
+			bit += 7;
+		}
+	} while ( *p++ >= 0x80 );
+	addr = (pint_t)p;
+	return result;
+}
+
+/* Read a SLEB128 into a 64-bit word.  */
+inline int64_t
+LocalAddressSpace::getSLEB128(pint_t& addr, pint_t end)
+{
+	const uint8_t* p = (uint8_t*)addr;
+	int64_t result = 0;
+	int bit = 0;
+	uint8_t byte;
+	do {
+		byte = *p++;
+		result |= ((byte & 0x7f) << bit);
+		bit += 7;
+	} while (byte & 0x80);
+	// sign extend negative numbers
+	if ( (byte & 0x40) != 0 )
+		result |= (-1LL) << bit;
+	addr = (pint_t)p;
+	return result;
+}
+
+LocalAddressSpace::pint_t
+LocalAddressSpace::getEncodedP(pint_t& addr, pint_t end, uint8_t encoding)
+{
+	pint_t startAddr = addr;
+	const uint8_t* p = (uint8_t*)addr;
+	pint_t result;
+	
+	// first get value
+	switch (encoding & 0x0F) {
+		case DW_EH_PE_ptr:
+			result = getP(addr);
+			p += sizeof(pint_t);
+			addr = (pint_t)p;
+			break;
+		case DW_EH_PE_uleb128:
+			result = getULEB128(addr, end);
+			break;
+		case DW_EH_PE_udata2:
+			result = get16(addr);
+			p += 2;
+			addr = (pint_t)p;
+			break;
+		case DW_EH_PE_udata4:
+			result = get32(addr);
+			p += 4;
+			addr = (pint_t)p;
+			break;
+		case DW_EH_PE_udata8:
+			result = get64(addr);
+			p += 8;
+			addr = (pint_t)p;
+			break;
+		case DW_EH_PE_sleb128:
+			result = getSLEB128(addr, end);
+			break;
+		case DW_EH_PE_sdata2:
+			result = (int16_t)get16(addr);
+			p += 2;
+			addr = (pint_t)p;
+			break;
+		case DW_EH_PE_sdata4:
+			result = (int32_t)get32(addr);
+			p += 4;
+			addr = (pint_t)p;
+			break;
+		case DW_EH_PE_sdata8:
+			result = get64(addr);
+			p += 8;
+			addr = (pint_t)p;
+			break;
+		default:
+			ABORT("unknown pointer encoding");
+	}
+	
+	// then add relative offset
+	switch ( encoding & 0x70 ) {
+		case DW_EH_PE_absptr:
+			// do nothing
+			break;
+		case DW_EH_PE_pcrel:
+			result += startAddr;
+			break;
+		case DW_EH_PE_textrel:
+			ABORT("DW_EH_PE_textrel pointer encoding not supported");
+			break;
+		case DW_EH_PE_datarel:
+			ABORT("DW_EH_PE_datarel pointer encoding not supported");
+			break;
+		case DW_EH_PE_funcrel:
+			ABORT("DW_EH_PE_funcrel pointer encoding not supported");
+			break;
+		case DW_EH_PE_aligned:
+			ABORT("DW_EH_PE_aligned pointer encoding not supported");
+			break;
+		default:
+			ABORT("unknown pointer encoding");
+			break;
+	}
+	
+	if ( encoding & DW_EH_PE_indirect )
+		result = getP(result);
+	
+	return result;
+}
+
+
+inline bool LocalAddressSpace::findUnwindSections(pint_t addr, pint_t& mh, pint_t& dwarfStart, pint_t& dwarfLen, pint_t& compactStart)
+{
+#if !defined (SUPPORT_REMOTE_UNWINDING)
+	dyld_unwind_sections info;
+	if ( _dyld_find_unwind_sections((void*)addr, &info) ) {
+		mh				= (pint_t)info.mh;
+		dwarfStart		= (pint_t)info.dwarf_section;
+		dwarfLen		= (pint_t)info.dwarf_section_length;
+		compactStart	= (pint_t)info.compact_unwind_section;
+		return true;
+	}
+#else
+    assert("unwinding with a non-remote process not supported.");
+#endif
+	return false;
+}
+
+
+inline bool	LocalAddressSpace::findFunctionName(pint_t addr, char* buf, size_t bufLen, unw_word_t* offset)
+{
+	dl_info dyldInfo;
+	if ( dladdr((void*)addr, &dyldInfo) ) {
+		if ( dyldInfo.dli_sname != NULL ) {
+			strlcpy(buf, dyldInfo.dli_sname, bufLen);
+			*offset = (addr - (pint_t)dyldInfo.dli_saddr);
+			return true;
+		}
+	}
+	return false;
+}
+
+#if defined (SUPPORT_REMOTE_UNWINDING)
+///
+/// OtherAddressSpace is used as a template parameter to UnwindCursor when unwinding a thread
+/// in the another process.  The other process can be a different endianness and a different
+/// pointer size and is handled by the P template parameter.  
+///
+template <typename P>
+class OtherAddressSpace
+{
+public:
+        OtherAddressSpace (unw_addr_space_t remote_addr_space, void* arg) : fAddrSpace ((unw_addr_space_remote *)remote_addr_space), fArg(arg)
+        {
+          if (fAddrSpace->type != UNW_REMOTE)
+            ABORT("OtherAddressSpace ctor called with non-remote address space.");
+          fRemoteProcInfo = fAddrSpace->ras;
+        }
+
+		typedef typename P::uint_t	pint_t;
+		typedef typename P::int_t	sint_t;
+
+	    int			    getBytes(pint_t addr, pint_t extent, uint8_t* buf)   { return fRemoteProcInfo->getBytes (addr, extent, buf, fArg); }
+        uint8_t         get8(pint_t addr)                                    { return fRemoteProcInfo->get8(addr, fArg); }
+        uint16_t        get16(pint_t addr)                                   { return fRemoteProcInfo->get16(addr, fArg); }
+        uint32_t        get32(pint_t addr)                                   { return fRemoteProcInfo->get32(addr, fArg); }
+        uint64_t        get64(pint_t addr)                                   { return fRemoteProcInfo->get64(addr, fArg); }
+        pint_t          getP(pint_t addr)                                    { return fRemoteProcInfo->getP(addr, fArg); }
+
+        uint8_t         get8(pint_t addr, int& err)                          { return fRemoteProcInfo->get8(addr, err, fArg); }
+        uint16_t        get16(pint_t addr, int& err)                         { return fRemoteProcInfo->get16(addr, err, fArg); }
+        uint32_t        get32(pint_t addr, int& err)                         { return fRemoteProcInfo->get32(addr, err, fArg); }
+        uint64_t        get64(pint_t addr, int& err)                         { return fRemoteProcInfo->get64(addr, err, fArg); }
+        pint_t          getP(pint_t addr, int &err)                          { return fRemoteProcInfo->getP(addr, err, fArg); }
+
+        uint64_t        getULEB128(pint_t& addr, pint_t end)                 { return fRemoteProcInfo->getULEB128 (addr, end, fArg); }
+        int64_t         getSLEB128(pint_t& addr, pint_t end)                 { return fRemoteProcInfo->getSLEB128 (addr, end, fArg); }
+        pint_t          getEncodedP(pint_t& addr, pint_t end, uint8_t encoding);
+        double          getDouble(pint_t addr);
+        v128            getVector(pint_t addr);
+        bool            findFunctionName(pint_t addr, char* buf, size_t bufLen, unw_word_t* offset);
+        bool            findFunctionExtent(pint_t addr, unw_word_t* begin, unw_word_t* end);
+        bool            findUnwindSections(pint_t addr, pint_t& mh, pint_t& eh_frame_start, pint_t& eh_frame_len, pint_t& compactStart);
+        RemoteProcInfo* getRemoteProcInfo () { return fRemoteProcInfo; }
+        unw_accessors_t*    accessors()   { return fRemoteProcInfo->getAccessors(); }
+        unw_addr_space_t    wrap()        { return (unw_addr_space_t) fAddrSpace; }
+private:
+		void*			localCopy(pint_t addr);
+        unw_addr_space_remote *fAddrSpace;
+        RemoteProcInfo* fRemoteProcInfo;
+        void*           fArg;
+};
+
+template <typename P>
+typename OtherAddressSpace<P>::pint_t OtherAddressSpace<P>::getEncodedP(pint_t& addr, pint_t end, uint8_t encoding)
+{
+	pint_t startAddr = addr;
+	pint_t p = addr;
+	pint_t result;
+	
+	// first get value
+	switch (encoding & 0x0F) {
+		case DW_EH_PE_ptr:
+			result = fRemoteProcInfo->getP(addr, fArg);
+			p += sizeof(pint_t);
+			addr = p;
+			break;
+		case DW_EH_PE_uleb128:
+			result = fRemoteProcInfo->getULEB128(addr, end, fArg);
+			break;
+		case DW_EH_PE_udata2:
+			result = fRemoteProcInfo->get16(addr, fArg);
+			p += 2;
+			addr = p;
+			break;
+		case DW_EH_PE_udata4:
+			result = fRemoteProcInfo->get32(addr, fArg);
+			p += 4;
+			addr = p;
+			break;
+		case DW_EH_PE_udata8:
+			result = fRemoteProcInfo->get64(addr, fArg);
+			p += 8;
+			addr = p;
+			break;
+		case DW_EH_PE_sleb128:
+			result = fRemoteProcInfo->getSLEB128(addr, end, fArg);
+			break;
+		case DW_EH_PE_sdata2:
+			result = (int16_t)fRemoteProcInfo->get16(addr, fArg);
+			p += 2;
+			addr = p;
+			break;
+		case DW_EH_PE_sdata4:
+			result = (int32_t)fRemoteProcInfo->get32(addr, fArg);
+			p += 4;
+			addr = p;
+			break;
+		case DW_EH_PE_sdata8:
+			result = fRemoteProcInfo->get64(addr, fArg);
+			p += 8;
+			addr = p;
+			break;
+		default:
+			ABORT("unknown pointer encoding");
+	}
+	
+	// then add relative offset
+	switch ( encoding & 0x70 ) {
+		case DW_EH_PE_absptr:
+			// do nothing
+			break;
+		case DW_EH_PE_pcrel:
+			result += startAddr;
+			break;
+		case DW_EH_PE_textrel:
+			ABORT("DW_EH_PE_textrel pointer encoding not supported");
+			break;
+		case DW_EH_PE_datarel:
+			ABORT("DW_EH_PE_datarel pointer encoding not supported");
+			break;
+		case DW_EH_PE_funcrel:
+			ABORT("DW_EH_PE_funcrel pointer encoding not supported");
+			break;
+		case DW_EH_PE_aligned:
+			ABORT("DW_EH_PE_aligned pointer encoding not supported");
+			break;
+		default:
+			ABORT("unknown pointer encoding");
+			break;
+	}
+	
+	if ( encoding & DW_EH_PE_indirect )
+		result = fRemoteProcInfo->getP(result, fArg);
+	
+	return result;
+}
+
+template <typename P>
+double OtherAddressSpace<P>::getDouble(pint_t addr)
+{
+    return fRemoteProcInfo->getDouble(addr, fArg);
+}
+
+template <typename P>
+v128 OtherAddressSpace<P>::getVector(pint_t addr)
+{
+    return fRemoteProcInfo->getVector(addr, fArg);
+}
+
+template <typename P>
+bool OtherAddressSpace<P>::findUnwindSections(pint_t addr, pint_t& mh, pint_t& eh_frame_start, pint_t& eh_frame_len, pint_t& compactStart)
+{
+    compactStart = 0;
+    uint64_t t_mh, t_text_start, t_text_end, t_eh_frame_start, t_eh_frame_len, t_compact_start;
+    if (fRemoteProcInfo->getImageAddresses (addr, t_mh, t_text_start, t_text_end, t_eh_frame_start, t_eh_frame_len, t_compact_start, fArg))
+      {
+        mh = t_mh;
+        eh_frame_start = t_eh_frame_start;
+        eh_frame_len = t_eh_frame_len;
+        compactStart = t_compact_start;
+        return true;
+      }
+    return false;
+}
+
+template <typename P>
+bool OtherAddressSpace<P>::findFunctionName(pint_t addr, char* buf, size_t bufLen, unw_word_t* offset)
+{
+  return fRemoteProcInfo->findFunctionName (addr, buf, bufLen, offset, fArg);
+}
+
+#endif // SUPPORT_REMOTE_UNWINDING
+
+
+} // namespace lldb_private 
+
+
+
+#endif // __ADDRESSSPACE_HPP__
diff --git a/source/Plugins/Process/Utility/libunwind/src/ArchDefaultUnwinder.hpp b/source/Plugins/Process/Utility/libunwind/src/ArchDefaultUnwinder.hpp
new file mode 100644
index 0000000..d19d7ae
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/ArchDefaultUnwinder.hpp
@@ -0,0 +1,115 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- ArchDefaultUnwinder.hpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Unwind a stack frame using nothing but the default conventions on
+// this architecture.
+
+#ifndef __ARCH_DEFAULT_UNWINDER_HPP
+#define __ARCH_DEFAULT_UNWINDER_HPP
+
+#if defined (SUPPORT_REMOTE_UNWINDING)
+
+#include "AddressSpace.hpp"
+#include "Registers.hpp"
+#include "RemoteRegisterMap.hpp"
+#include "RemoteProcInfo.hpp"
+
+namespace lldb_private
+{
+
+// As a last ditch attempt to unwind a stack frame, unwind by the
+// architecture's typical conventions.  We try compact unwind, eh frame CFI,
+// and then assembly profiling if we have function bounds -- but if we're
+// looking at an address with no function bounds or unwind info, make a best
+// guess at how to get out.
+
+// In practice, this is usually hit when we try to step out of start() in a 
+// stripped application binary, we've jumped to 0x0, or we're in jitted code
+// in the heap.
+
+template <typename A, typename R>
+int stepByArchitectureDefault_x86 (A& addressSpace, R& registers, 
+                                   uint64_t pc, int wordsize) {
+    R newRegisters(registers);
+    RemoteRegisterMap *rmap = addressSpace.getRemoteProcInfo()->getRegisterMap();
+    int frame_reg = rmap->unwind_regno_for_frame_pointer();
+    int stack_reg = rmap->unwind_regno_for_stack_pointer();
+    int err;
+
+    /* If the pc is 0x0 either we call'ed 0 (went thorugh a null function 
+       pointer) or this is a thread in the middle of being created that has
+       no stack at all.
+       For the call-0x0 case, we know how to unwind that - the pc is at
+       the stack pointer.  
+
+       Otherwise follow the usual convention of trusting that RBP/EBP has the
+       start of the stack frame and we can find the caller's pc based on
+       that.  */
+
+    uint64_t newpc, newframeptr;
+    newpc = 0;
+    newframeptr = -1;
+    if (pc == 0) {
+        uint64_t oldsp = registers.getRegister(stack_reg);
+        err = 0;
+        if (oldsp != 0) {
+            newpc = addressSpace.getP(registers.getRegister(stack_reg), err);
+            if (err != 0)
+                return UNW_EUNSPEC;
+            newRegisters.setIP (newpc);
+            newRegisters.setRegister (stack_reg, registers.getRegister(stack_reg) +
+                                                                        wordsize);
+        }
+    }
+    else {
+        newpc = addressSpace.getP(registers.getRegister(frame_reg) + 
+                                           wordsize, err);
+        if (err != 0)
+            return UNW_EUNSPEC;
+
+        newRegisters.setIP (newpc);
+        newframeptr = addressSpace.getP(registers.getRegister(frame_reg), 
+                                        err);
+        if (err != 0)
+            return UNW_EUNSPEC;
+
+        newRegisters.setRegister (frame_reg, newframeptr);
+        newRegisters.setRegister (stack_reg, registers.getRegister(frame_reg) + 
+                                                               (wordsize * 2));
+    }
+    registers = newRegisters;
+    if (newpc == 0 || newframeptr == 0)
+        return UNW_STEP_END;
+    return UNW_STEP_SUCCESS;
+}
+
+template <typename A>
+int stepByArchitectureDefault (A& addressSpace, Registers_x86_64 &registers, 
+                               uint64_t pc) {
+    return stepByArchitectureDefault_x86 (addressSpace, registers, pc, 8);
+}
+
+template <typename A>
+int stepByArchitectureDefault (A& addressSpace, Registers_x86& registers, 
+                               uint64_t pc) {
+    return stepByArchitectureDefault_x86 (addressSpace, registers, pc, 4);
+}
+
+template <typename A>
+int stepByArchitectureDefault (A& addressSpace, Registers_ppc& registers, 
+                               uint64_t pc) {
+    ABORT("Remote unwinding not supported for ppc.");
+    return UNW_EUNSPEC;
+}
+
+}; // namespace lldb_private
+
+#endif // SUPPORT_REMOTE_UNWINDING
+#endif // __ARCH_DEFAULT_UNWINDER_HPP
diff --git a/source/Plugins/Process/Utility/libunwind/src/AssemblyInstructions.hpp b/source/Plugins/Process/Utility/libunwind/src/AssemblyInstructions.hpp
new file mode 100644
index 0000000..1e695d5
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/AssemblyInstructions.hpp
@@ -0,0 +1,147 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- AssemblyInstructions.hpp --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __ASSEMBLY_INSTRUCTIONS_HPP
+#define __ASSEMBLY_INSTRUCTIONS_HPP
+
+#if defined (SUPPORT_REMOTE_UNWINDING)
+
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS
+#endif
+#ifndef __STDC_CONSTANT_MACROS
+#define __STDC_CONSTANT_MACROS
+#endif
+
+#include <limits.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <map>
+
+#include "libunwind.h"
+#include "AssemblyParser.hpp"
+#include "AddressSpace.hpp"
+#include "Registers.hpp"
+#include "RemoteUnwindProfile.h"
+
+namespace lldb_private
+{
+
+// A debug function to dump the contents of an RemoteUnwindProfile to
+// stdout in a human readable form.
+
+template <typename A, typename R>
+void printProfile (A& addressSpace, uint64_t pc, RemoteUnwindProfile* profile, R& registers) {
+    RemoteProcInfo *procinfo = addressSpace.getRemoteProcInfo();
+    RemoteRegisterMap *regmap = procinfo->getRegisterMap();
+
+    procinfo->logDebug ("Print profile: given pc of 0x%llx, profile has range 0x%llx - 0x%llx", pc, profile->fStart, profile->fEnd);
+    procinfo->logDebug ("CFA locations:");
+    std::map<uint64_t, RemoteUnwindProfile::CFALocation>::iterator i;
+    for (i = profile->cfa.begin(); i != profile->cfa.end(); ++i) {
+        procinfo->logDebug ("   as of 0x%llx cfa is based off of reg %d (%s) offset %d", i->first, i->second.regno, regmap->unwind_regno_to_name(i->second.regno), i->second.offset);
+    }
+    procinfo->logDebug ("Caller's saved IP is at %d bytes offset from the cfa", (int)profile->returnAddress.value);
+    procinfo->logDebug ("Register saves:");
+    std::map<uint64_t, std::vector<RemoteUnwindProfile::SavedReg> >::iterator j;
+    for (j = profile->saved_registers.begin(); j != profile->saved_registers.end(); ++j) {
+        char *tbuf1, *tbuf2, *tbuf3;
+        asprintf (&tbuf1, "  at pc 0x%llx there are %d registers saved ", j->first, (int) j->second.size());
+        std::vector<RemoteUnwindProfile::SavedReg>::iterator k;
+        for (k = j->second.begin(); k != j->second.end(); ++k) {
+            if (k->location == RemoteUnwindProfile::kRegisterOffsetFromCFA) {
+                asprintf (&tbuf2, "[reg %d (%s) is %d bytes from cfa] ", k->regno, regmap->unwind_regno_to_name(k->regno), (int) k->value);
+                int newlen = strlen (tbuf1) + strlen (tbuf2) + 1;
+                tbuf3 = (char *) malloc (newlen);
+                strcpy (tbuf3, tbuf1);
+                strcat (tbuf3, tbuf2);
+                free (tbuf1);
+                free (tbuf2);
+                tbuf1 = tbuf3;
+            }
+            if (k->location == RemoteUnwindProfile::kRegisterIsCFA) {
+                asprintf (&tbuf2, "[reg %d (%s) is the same as the cfa] ", k->regno, regmap->unwind_regno_to_name(k->regno));
+                int newlen = strlen (tbuf1) + strlen (tbuf2) + 1;
+                tbuf3 = (char *) malloc (newlen);
+                strcpy (tbuf3, tbuf1);
+                strcat (tbuf3, tbuf2);
+                free (tbuf1);
+                free (tbuf2);
+                tbuf1 = tbuf3;
+            }
+        }
+        procinfo->logDebug ("%s", tbuf1);
+        free (tbuf1);
+    }
+}
+
+template <typename A, typename R>
+int stepWithAssembly (A& addressSpace, uint64_t pc, RemoteUnwindProfile* profile, R& registers) {
+    R newRegisters(registers);
+    RemoteProcInfo *procinfo = addressSpace.getRemoteProcInfo();
+    if (pc > profile->fEnd)
+        ABORT("stepWithAssembly called with pc not in RemoteUnwindProfile's bounds");
+
+    if (procinfo && (procinfo->getDebugLoggingLevel() & UNW_LOG_LEVEL_DEBUG))
+        printProfile (addressSpace, pc, profile, registers);
+
+    std::map<uint64_t, RemoteUnwindProfile::CFALocation>::iterator i = profile->cfa.lower_bound (pc);
+    if (i == profile->cfa.begin() && i == profile->cfa.end())
+        return UNW_EINVAL;
+    if (i == profile->cfa.end()) {
+        --i;
+    } else {
+        if (i != profile->cfa.begin() && i->first != pc)
+          --i;
+    }
+
+    uint64_t cfa = registers.getRegister (i->second.regno) + i->second.offset;
+    
+    std::map<uint64_t, std::vector<RemoteUnwindProfile::SavedReg> >::iterator j;
+
+    for (j = profile->saved_registers.begin(); j != profile->saved_registers.end() && j->first <= pc; ++j) {
+        std::vector<RemoteUnwindProfile::SavedReg>::iterator k = j->second.begin();
+        for (; k != j->second.end(); ++k) {
+            RemoteUnwindProfile::SavedReg sr = *k;
+            if (sr.type == RemoteUnwindProfile::kGeneralPurposeRegister) {
+                uint64_t result;
+                int err = 0;
+                switch (sr.location) {
+                    case RemoteUnwindProfile::kRegisterOffsetFromCFA: 
+                        result = addressSpace.getP(cfa + sr.value, err);
+                        break;
+                    case RemoteUnwindProfile::kRegisterIsCFA:
+                            result = cfa;
+                        break;
+                    default:
+                        ABORT("Unknown saved register location in stepWithAssembly.");
+                }
+                // If we failed to read remote memory, stop unwinding.
+                if (err)
+                    return UNW_STEP_END;
+                newRegisters.setRegister (sr.regno, result);
+            }
+        }
+    }
+    newRegisters.setSP(cfa);
+    uint64_t ip = addressSpace.getP(cfa + profile->returnAddress.value);
+    if (ip == 0) 
+      return UNW_STEP_END;
+    newRegisters.setIP(ip);
+    registers = newRegisters;
+    return UNW_STEP_SUCCESS;
+}
+
+}; // namespace lldb_private
+
+#endif // SUPPORT_REMOTE_UNWINDING
+#endif  //ASSEMBLY_INSTRUCTIONS_HPP
diff --git a/source/Plugins/Process/Utility/libunwind/src/AssemblyParser.hpp b/source/Plugins/Process/Utility/libunwind/src/AssemblyParser.hpp
new file mode 100644
index 0000000..b34f93f
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/AssemblyParser.hpp
@@ -0,0 +1,409 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- AssemblyParser.hpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Disassemble the prologue instructions in functions, create a profile
+// of stack movements and register saves performed therein.
+
+#ifndef __ASSEMBLY_PARSER_HPP
+#define __ASSEMBLY_PARSER_HPP
+
+#if defined (SUPPORT_REMOTE_UNWINDING)
+
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS
+#endif
+#ifndef __STDC_CONSTANT_MACROS
+#define __STDC_CONSTANT_MACROS
+#endif
+#include <limits.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <map>
+#include <vector>
+
+#include "libunwind.h"
+#include "RemoteProcInfo.hpp"
+#include "Registers.hpp"
+#include "FileAbstraction.hpp"
+#include "AddressSpace.hpp"
+#include "RemoteUnwindProfile.h"
+
+namespace lldb_private
+{
+
+// Analyze the instructions in an x86_64/i386 function prologue, fill out an RemoteUnwindProfile.
+
+class AssemblyParse_x86 {
+public:
+    AssemblyParse_x86 (RemoteProcInfo& procinfo, unw_accessors_t *acc, unw_addr_space_t as, void *arg) : fArg(arg), fAccessors(acc), fAs(as), fRemoteProcInfo(procinfo) {
+        fRegisterMap = fRemoteProcInfo.getRegisterMap();
+        if (fRemoteProcInfo.getTargetArch() == UNW_TARGET_X86_64) {
+            fStackPointerRegnum = UNW_X86_64_RSP;
+            fFramePointerRegnum = UNW_X86_64_RBP;
+            fWordSize = 8;
+        } else {
+            fStackPointerRegnum = UNW_X86_ESP;
+            fFramePointerRegnum = UNW_X86_EBP;
+            fWordSize = 4;
+        }
+    }
+
+    uint32_t extract_4_LE (uint8_t *b) {
+        uint32_t v = 0;
+        for (int i = 3; i >= 0; i--)
+            v = (v << 8) | b[i];
+        return v;
+    }
+
+    bool push_rbp_pattern_p ();
+    bool push_0_pattern_p ();
+    bool mov_rsp_rbp_pattern_p ();
+    bool sub_rsp_pattern_p (int *amount);
+    bool push_reg_p (int *regno);
+    bool mov_reg_to_local_stack_frame_p (int *regno, int *rbp_offset);
+    bool ret_pattern_p ();
+    bool profileFunction (uint64_t start, uint64_t end, RemoteUnwindProfile& profile);
+
+private:
+
+    void *fArg;
+    uint8_t*           fCurInsnByteBuf;
+    int                fCurInsnSize;
+    RemoteProcInfo&    fRemoteProcInfo;
+    RemoteRegisterMap  *fRegisterMap;
+    unw_accessors_t    *fAccessors;
+    unw_addr_space_t   fAs;
+    int                fWordSize;
+    int                fStackPointerRegnum;
+    int                fFramePointerRegnum;
+};
+
+// Macro to detect if this is a REX mode prefix byte. 
+#define REX_W_PREFIX_P(opcode) (((opcode) & (~0x5)) == 0x48)
+
+// The high bit which should be added to the source register number (the "R" bit)
+#define REX_W_SRCREG(opcode) (((opcode) & 0x4) >> 2)
+
+// The high bit which should be added to the destination register number (the "B" bit)
+#define REX_W_DSTREG(opcode) ((opcode) & 0x1)
+
+// pushq %rbp [0x55]
+bool AssemblyParse_x86::push_rbp_pattern_p () {
+    uint8_t *p = fCurInsnByteBuf;
+    if (*p == 0x55)
+      return true;
+    return false;
+}
+
+// pushq $0 ; the first instruction in start() [0x6a 0x00]
+bool AssemblyParse_x86::push_0_pattern_p ()
+{
+    uint8_t *p = fCurInsnByteBuf;
+    if (*p == 0x6a && *(p + 1) == 0x0)
+        return true;
+    return false;
+}
+
+// movq %rsp, %rbp [0x48 0x8b 0xec] or [0x48 0x89 0xe5]
+// movl %esp, %ebp [0x8b 0xec] or [0x89 0xe5]
+bool AssemblyParse_x86::mov_rsp_rbp_pattern_p () {
+    uint8_t *p = fCurInsnByteBuf;
+    if (fWordSize == 8 && *p == 0x48)
+      p++;
+    if (*(p) == 0x8b && *(p + 1) == 0xec)
+        return true;
+    if (*(p) == 0x89 && *(p + 1) == 0xe5)
+        return true;
+    return false;
+}
+
+// subq $0x20, %rsp 
+bool AssemblyParse_x86::sub_rsp_pattern_p (int *amount) {
+    uint8_t *p = fCurInsnByteBuf;
+    if (fWordSize == 8 && *p == 0x48)
+      p++;
+    // 8-bit immediate operand
+    if (*p == 0x83 && *(p + 1) == 0xec) {
+        *amount = (int8_t) *(p + 2);
+        return true;
+    }
+    // 32-bit immediate operand
+    if (*p == 0x81 && *(p + 1) == 0xec) {
+        *amount = (int32_t) extract_4_LE (p + 2);
+        return true;
+    }
+    // Not handled:  [0x83 0xc4] for imm8 with neg values
+    // [0x81 0xc4] for imm32 with neg values
+    return false;
+}
+
+// pushq %rbx
+// pushl $ebx
+bool AssemblyParse_x86::push_reg_p (int *regno) {
+    uint8_t *p = fCurInsnByteBuf;
+    int regno_prefix_bit = 0;
+    // If we have a rex prefix byte, check to see if a B bit is set
+    if (fWordSize == 8 && *p == 0x41) {
+        regno_prefix_bit = 1 << 3;
+        p++;
+    }
+    if (*p >= 0x50 && *p <= 0x57) {
+        int r = (*p - 0x50) | regno_prefix_bit;
+        if (fRegisterMap->machine_regno_to_unwind_regno (r, *regno) == true) {
+            return true;
+        }
+    }
+    return false;
+}
+
+// Look for an instruction sequence storing a nonvolatile register
+// on to the stack frame.
+
+//  movq %rax, -0x10(%rbp) [0x48 0x89 0x45 0xf0]
+//  movl %eax, -0xc(%ebp)  [0x89 0x45 0xf4]
+bool AssemblyParse_x86::mov_reg_to_local_stack_frame_p (int *regno, int *rbp_offset) {
+    uint8_t *p = fCurInsnByteBuf;
+    int src_reg_prefix_bit = 0;
+    int target_reg_prefix_bit = 0;
+
+    if (fWordSize == 8 && REX_W_PREFIX_P (*p)) {
+        src_reg_prefix_bit = REX_W_SRCREG (*p) << 3;
+        target_reg_prefix_bit = REX_W_DSTREG (*p) << 3;
+        if (target_reg_prefix_bit == 1) {
+            // rbp/ebp don't need a prefix bit - we know this isn't the
+            // reg we care about.
+            return false;
+        }
+        p++;
+    }
+
+    if (*p == 0x89) {
+        /* Mask off the 3-5 bits which indicate the destination register
+           if this is a ModR/M byte.  */
+        int opcode_destreg_masked_out = *(p + 1) & (~0x38);
+
+        /* Is this a ModR/M byte with Mod bits 01 and R/M bits 101 
+           and three bits between them, e.g. 01nnn101
+           We're looking for a destination of ebp-disp8 or ebp-disp32.   */
+        int immsize;
+        if (opcode_destreg_masked_out == 0x45)
+          immsize = 2;
+        else if (opcode_destreg_masked_out == 0x85)
+          immsize = 4;
+        else
+          return false;
+
+        int offset = 0;
+        if (immsize == 2)
+          offset = (int8_t) *(p + 2);
+        if (immsize == 4)
+          offset = (uint32_t) extract_4_LE (p + 2);
+        if (offset > 0)
+          return false;
+
+        int savedreg = ((*(p + 1) >> 3) & 0x7) | src_reg_prefix_bit;
+        if (fRegisterMap->machine_regno_to_unwind_regno (savedreg, *regno) == true) {
+            *rbp_offset = offset > 0 ? offset : -offset;
+            return true;
+        }
+    }
+    return false;
+}
+
+// ret [0xc9] or [0xc2 imm8] or [0xca imm8]
+bool AssemblyParse_x86::ret_pattern_p () {
+    uint8_t *p = fCurInsnByteBuf;
+    if (*p == 0xc9 || *p == 0xc2 || *p == 0xca || *p == 0xc3)
+        return true;
+    return false;
+}
+
+bool AssemblyParse_x86::profileFunction (uint64_t start, uint64_t end, RemoteUnwindProfile& profile) {
+    if (start == -1 || end == 0)
+        return false;
+
+    profile.fStart = start;
+    profile.fEnd = end;
+    profile.fRegSizes[RemoteUnwindProfile::kGeneralPurposeRegister] = fWordSize;
+    profile.fRegSizes[RemoteUnwindProfile::kFloatingPointRegister] = 8;
+    profile.fRegSizes[RemoteUnwindProfile::kVectorRegister] = 16;
+
+    // On function entry, the CFA is rsp+fWordSize
+
+    RemoteUnwindProfile::CFALocation initial_cfaloc;
+    initial_cfaloc.regno = fStackPointerRegnum;
+    initial_cfaloc.offset = fWordSize;
+    profile.cfa[start] = initial_cfaloc;
+
+    // The return address is at CFA - fWordSize
+    // CFA doesn't change value during the lifetime of the function (hence "C")
+    // so the returnAddress is the same for the duration of the function.
+
+    profile.returnAddress.regno = 0;
+    profile.returnAddress.location = RemoteUnwindProfile::kRegisterOffsetFromCFA;
+    profile.returnAddress.value = -fWordSize;
+    profile.returnAddress.adj = 0;
+    profile.returnAddress.type = RemoteUnwindProfile::kGeneralPurposeRegister;
+
+    // The caller's rsp has the same value as the CFA at all points during 
+    // this function's lifetime.  
+
+    RemoteUnwindProfile::SavedReg rsp_loc;
+    rsp_loc.regno = fStackPointerRegnum;
+    rsp_loc.location = RemoteUnwindProfile::kRegisterIsCFA;
+    rsp_loc.value = 0;
+    rsp_loc.adj = 0;
+    rsp_loc.type = RemoteUnwindProfile::kGeneralPurposeRegister;
+    profile.saved_registers[start].push_back(rsp_loc);
+    profile.fRegistersSaved[fStackPointerRegnum] = 1;
+
+    int non_prologue_insn_count = 0;
+    int insn_count = 0;
+    uint64_t cur_addr = start;
+    uint64_t first_insn_past_prologue = start;
+    int push_rbp_seen = 0;
+    int current_cfa_register = fStackPointerRegnum;
+    int sp_adjustments = 0;
+
+    while (cur_addr < end && non_prologue_insn_count < 10)
+    {
+        int offset, regno;
+        uint64_t next_addr;
+        insn_count++;
+        int is_prologue_insn = 0;
+
+        if (fAccessors->instruction_length (fAs, cur_addr, &fCurInsnSize, fArg) != 0) {
+            /* An error parsing the instruction; stop scanning.  */
+            break;
+        }
+        fCurInsnByteBuf = (uint8_t *) malloc (fCurInsnSize);
+        if (fRemoteProcInfo.getBytes (cur_addr, fCurInsnSize, fCurInsnByteBuf, fArg) == 0)
+          return false;
+        next_addr = cur_addr + fCurInsnSize;
+
+        // start () opens with a 'push $0x0' which is in the saved ip slot on the stack -
+        // so we know to stop backtracing here.  We need to ignore this instruction.
+        if (push_0_pattern_p () && push_rbp_seen == 0 && insn_count == 1)
+        {
+            cur_addr = next_addr;
+            first_insn_past_prologue = next_addr;
+            continue;
+        }
+
+        if (push_rbp_pattern_p () && push_rbp_seen == 0)
+          {
+            if (current_cfa_register == fStackPointerRegnum) {
+                sp_adjustments -= fWordSize;
+                RemoteUnwindProfile::CFALocation cfaloc;
+                cfaloc.regno = fStackPointerRegnum;
+                cfaloc.offset = abs (sp_adjustments - fWordSize);
+                profile.cfa[next_addr] = cfaloc;
+            }
+
+            RemoteUnwindProfile::SavedReg sreg;
+            sreg.regno = fFramePointerRegnum;
+            sreg.location = RemoteUnwindProfile::kRegisterOffsetFromCFA;
+            sreg.value = sp_adjustments - fWordSize;
+            sreg.adj = 0;
+            sreg.type = RemoteUnwindProfile::kGeneralPurposeRegister;
+            profile.saved_registers[next_addr].push_back(sreg);
+
+            push_rbp_seen = 1;
+            profile.fRegistersSaved[fFramePointerRegnum] = 1;
+            is_prologue_insn = 1;
+            goto next_iteration;
+          }
+        if (mov_rsp_rbp_pattern_p ()) {
+            RemoteUnwindProfile::CFALocation cfaloc;
+            cfaloc.regno = fFramePointerRegnum;
+            cfaloc.offset = abs (sp_adjustments - fWordSize);
+            profile.cfa[next_addr] = cfaloc;
+            current_cfa_register = fFramePointerRegnum;
+            is_prologue_insn = 1;
+            goto next_iteration;
+        }
+        if (ret_pattern_p ()) {
+            break;
+        }
+        if (sub_rsp_pattern_p (&offset)) {
+            sp_adjustments -= offset;
+            if (current_cfa_register == fStackPointerRegnum) {
+               RemoteUnwindProfile::CFALocation cfaloc;
+               cfaloc.regno = fStackPointerRegnum;
+               cfaloc.offset = abs (sp_adjustments - fWordSize);
+               profile.cfa[next_addr] = cfaloc;
+            }
+            is_prologue_insn = 1;
+        }
+        if (push_reg_p (&regno)) {
+            sp_adjustments -= fWordSize;
+            if (current_cfa_register == fStackPointerRegnum) {
+                RemoteUnwindProfile::CFALocation cfaloc;
+                cfaloc.regno = fStackPointerRegnum;
+                cfaloc.offset = abs (sp_adjustments - fWordSize);
+                profile.cfa[next_addr] = cfaloc;
+                is_prologue_insn = 1;
+            }
+            if (fRegisterMap->nonvolatile_reg_p (regno) && profile.fRegistersSaved[regno] == 0) {
+                RemoteUnwindProfile::SavedReg sreg;
+                sreg.regno = regno;
+                sreg.location = RemoteUnwindProfile::kRegisterOffsetFromCFA;
+                sreg.value = sp_adjustments - fWordSize;
+                sreg.adj = 0;
+                sreg.type = RemoteUnwindProfile::kGeneralPurposeRegister;
+                profile.saved_registers[next_addr].push_back(sreg);
+                profile.fRegistersSaved[regno] = 1;
+                is_prologue_insn = 1;
+            }
+        }
+        if (mov_reg_to_local_stack_frame_p (&regno, &offset) 
+            && fRegisterMap->nonvolatile_reg_p (regno)
+            && profile.fRegistersSaved[regno] == 0) {
+                RemoteUnwindProfile::SavedReg sreg;
+                sreg.regno = regno;
+                sreg.location = RemoteUnwindProfile::kRegisterOffsetFromCFA;
+                sreg.value = offset - fWordSize;
+                sreg.adj = 0;
+                sreg.type = RemoteUnwindProfile::kGeneralPurposeRegister;
+                profile.saved_registers[next_addr].push_back(sreg);
+                profile.fRegistersSaved[regno] = 1;
+                is_prologue_insn = 1;
+        }
+next_iteration:
+        if (is_prologue_insn) {
+            first_insn_past_prologue = next_addr;
+            non_prologue_insn_count = 0;
+        }
+        cur_addr = next_addr;
+        non_prologue_insn_count++;
+    }
+    profile.fFirstInsnPastPrologue = first_insn_past_prologue;
+    return true;
+}
+
+
+
+
+bool AssemblyParse (RemoteProcInfo *procinfo, unw_accessors_t *acc, unw_addr_space_t as, uint64_t start, uint64_t end, RemoteUnwindProfile &profile, void *arg) {
+    if (procinfo->getTargetArch() == UNW_TARGET_X86_64 || procinfo->getTargetArch() == UNW_TARGET_I386) {
+        AssemblyParse_x86 parser(*procinfo, acc, as, arg);
+        return parser.profileFunction (start, end, profile);
+    } else {
+        ABORT("Only x86_64 and i386 assembly parsing supported at this time");
+        return false;
+    }
+}
+
+}; // namespace lldb_private
+
+#endif // SUPPORT_REMOTE_UNWINDING
+#endif  //ASSEMBLY_PARSER_HPP
diff --git a/source/Plugins/Process/Utility/libunwind/src/CompactUnwinder.hpp b/source/Plugins/Process/Utility/libunwind/src/CompactUnwinder.hpp
new file mode 100644
index 0000000..dda2308
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/CompactUnwinder.hpp
@@ -0,0 +1,1019 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- CompactUnwinder.hpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+ 
+//
+//	C++ interface to lower levels of libuwind 
+//
+
+#ifndef __COMPACT_UNWINDER_HPP__
+#define __COMPACT_UNWINDER_HPP__
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <libunwind.h>
+#include <mach-o/compact_unwind_encoding.h>
+
+#include "AddressSpace.hpp"
+#include "Registers.hpp"
+
+
+
+#define EXTRACT_BITS(value, mask) \
+	( (value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask)))-1) )
+
+#define SUPPORT_OLD_BINARIES 0 
+
+namespace lldb_private {
+
+
+
+///
+/// CompactUnwinder_x86 uses a compact unwind info to virtually "step" (aka unwind) by
+/// modifying a Registers_x86 register set
+///
+template <typename A>
+class CompactUnwinder_x86
+{
+public:
+
+	static int stepWithCompactEncoding(compact_unwind_encoding_t info, uint32_t functionStart, A& addressSpace, Registers_x86& registers);
+	
+private:
+	typename A::pint_t		pint_t;
+	
+	static void frameUnwind(A& addressSpace, Registers_x86& registers);
+	static void framelessUnwind(A& addressSpace, typename A::pint_t returnAddressLocation, Registers_x86& registers);
+	static int stepWithCompactEncodingEBPFrame(compact_unwind_encoding_t compactEncoding, uint32_t functionStart, A& addressSpace, Registers_x86& registers);
+	static int stepWithCompactEncodingFrameless(compact_unwind_encoding_t compactEncoding, uint32_t functionStart, A& addressSpace, Registers_x86& registers, bool indirectStackSize);
+#if SUPPORT_OLD_BINARIES
+	static int stepWithCompactEncodingCompat(compact_unwind_encoding_t compactEncoding, uint32_t functionStart, A& addressSpace, Registers_x86& registers);
+#endif
+};
+
+
+
+template <typename A>
+int CompactUnwinder_x86<A>::stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding, uint32_t functionStart, A& addressSpace, Registers_x86& registers)
+{
+	//fprintf(stderr, "stepWithCompactEncoding(0x%08X)\n", compactEncoding);
+	switch ( compactEncoding & UNWIND_X86_MODE_MASK ) {
+#if SUPPORT_OLD_BINARIES
+		case UNWIND_X86_MODE_COMPATIBILITY:
+			return stepWithCompactEncodingCompat(compactEncoding, functionStart, addressSpace, registers);
+#endif
+		case UNWIND_X86_MODE_EBP_FRAME:
+			return stepWithCompactEncodingEBPFrame(compactEncoding, functionStart, addressSpace, registers);
+		case UNWIND_X86_MODE_STACK_IMMD:
+			return stepWithCompactEncodingFrameless(compactEncoding, functionStart, addressSpace, registers, false);
+		case UNWIND_X86_MODE_STACK_IND:
+			return stepWithCompactEncodingFrameless(compactEncoding, functionStart, addressSpace, registers, true);
+	}
+	ABORT("invalid compact unwind encoding");
+}
+
+
+template <typename A>
+int CompactUnwinder_x86<A>::stepWithCompactEncodingEBPFrame(compact_unwind_encoding_t compactEncoding, uint32_t functionStart, 
+																	A& addressSpace, Registers_x86& registers)
+{
+	uint32_t savedRegistersOffset = EXTRACT_BITS(compactEncoding, UNWIND_X86_EBP_FRAME_OFFSET);
+	uint32_t savedRegistersLocations = EXTRACT_BITS(compactEncoding, UNWIND_X86_EBP_FRAME_REGISTERS);
+	
+	uint64_t savedRegisters = registers.getEBP() - 4*savedRegistersOffset;
+	for (int i=0; i < 5; ++i) {
+		switch (savedRegistersLocations & 0x7) {
+			case UNWIND_X86_REG_NONE:
+				// no register saved in this slot
+				break;
+			case UNWIND_X86_REG_EBX:
+				registers.setEBX(addressSpace.get32(savedRegisters));
+				break;
+			case UNWIND_X86_REG_ECX:
+				registers.setECX(addressSpace.get32(savedRegisters));
+				break;
+			case UNWIND_X86_REG_EDX:
+				registers.setEDX(addressSpace.get32(savedRegisters));
+				break;
+			case UNWIND_X86_REG_EDI:
+				registers.setEDI(addressSpace.get32(savedRegisters));
+				break;
+			case UNWIND_X86_REG_ESI:
+				registers.setESI(addressSpace.get32(savedRegisters));
+				break;
+			default:
+				DEBUG_MESSAGE("bad register for EBP frame, encoding=%08X for function starting at 0x%X\n", compactEncoding, functionStart);
+				ABORT("invalid compact unwind encoding");
+		}
+		savedRegisters += 4;
+		savedRegistersLocations = (savedRegistersLocations >> 3);
+	}
+	frameUnwind(addressSpace, registers);
+	return UNW_STEP_SUCCESS;
+}
+
+
+template <typename A>
+int CompactUnwinder_x86<A>::stepWithCompactEncodingFrameless(compact_unwind_encoding_t encoding, uint32_t functionStart, 
+																A& addressSpace, Registers_x86& registers, bool indirectStackSize)
+{
+	uint32_t stackSizeEncoded = EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_SIZE);
+	uint32_t stackAdjust = EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_ADJUST);
+	uint32_t regCount = EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT);
+	uint32_t permutation = EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION);
+	uint32_t stackSize = stackSizeEncoded*4;
+	if ( indirectStackSize ) {
+		// stack size is encoded in subl $xxx,%esp instruction
+		uint32_t subl = addressSpace.get32(functionStart+stackSizeEncoded);
+		stackSize = subl + 4*stackAdjust;
+	}
+	// decompress permutation
+	int permunreg[6];
+	switch ( regCount ) {
+		case 6:
+			permunreg[0] = permutation/120;
+			permutation -= (permunreg[0]*120);
+			permunreg[1] = permutation/24;
+			permutation -= (permunreg[1]*24);
+			permunreg[2] = permutation/6;
+			permutation -= (permunreg[2]*6);
+			permunreg[3] = permutation/2;
+			permutation -= (permunreg[3]*2);
+			permunreg[4] = permutation;
+			permunreg[5] = 0;
+			break;
+		case 5:
+			permunreg[0] = permutation/120;
+			permutation -= (permunreg[0]*120);
+			permunreg[1] = permutation/24;
+			permutation -= (permunreg[1]*24);
+			permunreg[2] = permutation/6;
+			permutation -= (permunreg[2]*6);
+			permunreg[3] = permutation/2;
+			permutation -= (permunreg[3]*2);
+			permunreg[4] = permutation;
+			break;
+		case 4:
+			permunreg[0] = permutation/60;
+			permutation -= (permunreg[0]*60);
+			permunreg[1] = permutation/12;
+			permutation -= (permunreg[1]*12);
+			permunreg[2] = permutation/3;
+			permutation -= (permunreg[2]*3);
+			permunreg[3] = permutation;
+			break;
+		case 3:
+			permunreg[0] = permutation/20;
+			permutation -= (permunreg[0]*20);
+			permunreg[1] = permutation/4;
+			permutation -= (permunreg[1]*4);
+			permunreg[2] = permutation;
+			break;
+		case 2:
+			permunreg[0] = permutation/5;
+			permutation -= (permunreg[0]*5);
+			permunreg[1] = permutation;
+			break;
+		case 1:
+			permunreg[0] = permutation;
+			break;
+	}
+	// re-number registers back to standard numbers
+	int registersSaved[6];
+	bool used[7] = { false, false, false, false, false, false, false };
+	for (uint32_t i=0; i < regCount; ++i) {
+		int renum = 0; 
+		for (int u=1; u < 7; ++u) {
+			if ( !used[u] ) {
+				if ( renum == permunreg[i] ) {
+					registersSaved[i] = u;
+					used[u] = true;
+					break;
+				}
+				++renum;
+			}
+		}
+	}
+	uint64_t savedRegisters = registers.getSP() + stackSize - 4 - 4*regCount;
+	for (uint32_t i=0; i < regCount; ++i) {
+		switch ( registersSaved[i] ) {
+			case UNWIND_X86_REG_EBX:
+				registers.setEBX(addressSpace.get32(savedRegisters));
+				break;
+			case UNWIND_X86_REG_ECX:
+				registers.setECX(addressSpace.get32(savedRegisters));
+				break;
+			case UNWIND_X86_REG_EDX:
+				registers.setEDX(addressSpace.get32(savedRegisters));
+				break;
+			case UNWIND_X86_REG_EDI:
+				registers.setEDI(addressSpace.get32(savedRegisters));
+				break;
+			case UNWIND_X86_REG_ESI:
+				registers.setESI(addressSpace.get32(savedRegisters));
+				break;
+			case UNWIND_X86_REG_EBP:
+				registers.setEBP(addressSpace.get32(savedRegisters));
+				break;
+			default:
+				DEBUG_MESSAGE("bad register for frameless, encoding=%08X for function starting at 0x%X\n", encoding, functionStart);
+				ABORT("invalid compact unwind encoding");
+		}
+		savedRegisters += 4;
+	}
+	framelessUnwind(addressSpace, savedRegisters, registers);
+	return UNW_STEP_SUCCESS;
+}
+
+
+#if SUPPORT_OLD_BINARIES
+template <typename A>
+int CompactUnwinder_x86<A>::stepWithCompactEncodingCompat(compact_unwind_encoding_t compactEncoding, uint32_t functionStart, A& addressSpace, Registers_x86& registers)
+{
+	//fprintf(stderr, "stepWithCompactEncoding(0x%08X)\n", compactEncoding);
+	typename A::pint_t savedRegisters;
+	uint32_t stackValue = EXTRACT_BITS(compactEncoding, UNWIND_X86_STACK_SIZE);
+	uint32_t stackSize;
+	uint32_t stackAdjust;
+	switch (compactEncoding & UNWIND_X86_CASE_MASK ) {
+		case UNWIND_X86_UNWIND_INFO_UNSPECIFIED:
+			return UNW_ENOINFO;
+	
+		case UNWIND_X86_EBP_FRAME_NO_REGS:
+			frameUnwind(addressSpace, registers);
+			return UNW_STEP_SUCCESS;
+			
+		case UNWIND_X86_EBP_FRAME_EBX:
+			savedRegisters = registers.getEBP() - 4;
+			registers.setEBX(addressSpace.get32(savedRegisters));
+			frameUnwind(addressSpace, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_EBP_FRAME_ESI:
+			savedRegisters = registers.getEBP() - 4;
+			registers.setESI(addressSpace.get32(savedRegisters));
+			frameUnwind(addressSpace, registers);
+			return UNW_STEP_SUCCESS;
+
+		case UNWIND_X86_EBP_FRAME_EDI:
+			savedRegisters = registers.getEBP() - 4;
+			registers.setEDI(addressSpace.get32(savedRegisters));
+			frameUnwind(addressSpace, registers);
+			return UNW_STEP_SUCCESS;
+
+		case UNWIND_X86_EBP_FRAME_EBX_ESI:
+			savedRegisters = registers.getEBP() - 8;
+			registers.setEBX(addressSpace.get32(savedRegisters));
+			registers.setESI(addressSpace.get32(savedRegisters+4));
+			frameUnwind(addressSpace, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_EBP_FRAME_ESI_EDI:
+			savedRegisters = registers.getEBP() - 8;
+			registers.setESI(addressSpace.get32(savedRegisters));
+			registers.setEDI(addressSpace.get32(savedRegisters+4));
+			frameUnwind(addressSpace, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_EBP_FRAME_EBX_ESI_EDI:
+			savedRegisters = registers.getEBP() - 12;
+			registers.setEBX(addressSpace.get32(savedRegisters));
+			registers.setESI(addressSpace.get32(savedRegisters+4));
+			registers.setEDI(addressSpace.get32(savedRegisters+8));
+			frameUnwind(addressSpace, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_EBP_FRAME_EBX_EDI:
+			savedRegisters = registers.getEBP() - 8;
+			registers.setEBX(addressSpace.get32(savedRegisters));
+			registers.setEDI(addressSpace.get32(savedRegisters+4));
+			frameUnwind(addressSpace, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_IMM_STK_NO_REGS:
+			stackSize = stackValue * 4;
+			savedRegisters = registers.getSP() + stackSize - 4 - 4*0;
+			framelessUnwind(addressSpace, savedRegisters+4*0, registers);
+			return UNW_STEP_SUCCESS;
+				
+		case UNWIND_X86_IMM_STK_EBX:
+			stackSize = stackValue * 4;
+			savedRegisters = registers.getSP() + stackSize - 4 - 4*1;
+			registers.setEBX(addressSpace.get32(savedRegisters));
+			framelessUnwind(addressSpace, savedRegisters+4*1, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_IMM_STK_ESI:
+			stackSize = stackValue * 4;
+			savedRegisters = registers.getSP() + stackSize - 4 - 4*1;
+			registers.setESI(addressSpace.get32(savedRegisters));
+			framelessUnwind(addressSpace, savedRegisters+4*1, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_IMM_STK_EDI:
+			stackSize = stackValue * 4;
+			savedRegisters = registers.getSP() + stackSize - 4 - 4*1;
+			registers.setEDI(addressSpace.get32(savedRegisters));
+			framelessUnwind(addressSpace, savedRegisters+4*1, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_IMM_STK_EBX_ESI:
+			stackSize = stackValue * 4;
+			savedRegisters = registers.getSP() + stackSize - 4 - 4*2;
+			registers.setEBX(addressSpace.get32(savedRegisters));
+			registers.setESI(addressSpace.get32(savedRegisters+4));
+			framelessUnwind(addressSpace, savedRegisters+4*2, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_IMM_STK_ESI_EDI:
+			stackSize = stackValue * 4;
+			savedRegisters = registers.getSP() + stackSize - 4 - 4*2;
+			registers.setESI(addressSpace.get32(savedRegisters));
+			registers.setEDI(addressSpace.get32(savedRegisters+4));
+			framelessUnwind(addressSpace, savedRegisters+4*2, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_IMM_STK_ESI_EDI_EBP:
+			stackSize = stackValue * 4;
+			savedRegisters = registers.getSP() + stackSize - 4 - 4*3;
+			registers.setESI(addressSpace.get32(savedRegisters));
+			registers.setEDI(addressSpace.get32(savedRegisters+4));
+			registers.setEBP(addressSpace.get32(savedRegisters+8));
+			framelessUnwind(addressSpace, savedRegisters+4*3, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_IMM_STK_EBX_ESI_EDI:
+			stackSize = stackValue * 4;
+			savedRegisters = registers.getSP() + stackSize - 4 - 4*3;
+			registers.setEBX(addressSpace.get32(savedRegisters));
+			registers.setESI(addressSpace.get32(savedRegisters+4));
+			registers.setEDI(addressSpace.get32(savedRegisters+8));
+			framelessUnwind(addressSpace, savedRegisters+4*3, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_IMM_STK_EBX_ESI_EDI_EBP:
+			stackSize = stackValue * 4;
+			savedRegisters = registers.getSP() + stackSize - 4 - 4*4;
+			registers.setEBX(addressSpace.get32(savedRegisters));
+			registers.setESI(addressSpace.get32(savedRegisters+4));
+			registers.setEDI(addressSpace.get32(savedRegisters+8));
+			registers.setEBP(addressSpace.get32(savedRegisters+12));
+			framelessUnwind(addressSpace, savedRegisters+4*4, registers);
+			return UNW_STEP_SUCCESS;
+
+		case UNWIND_X86_IND_STK_NO_REGS:
+			stackSize = addressSpace.get32(functionStart+stackValue);
+			stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_STACK_ADJUST);
+			stackSize += stackAdjust*4;
+			savedRegisters = registers.getSP() + stackSize - 4 - 4*0;
+			framelessUnwind(addressSpace, savedRegisters+4*0, registers);
+			return UNW_STEP_SUCCESS;
+
+		case UNWIND_X86_IND_STK_EBX:
+			stackSize = addressSpace.get32(functionStart+stackValue);
+			stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_STACK_ADJUST);
+			stackSize += stackAdjust*4;
+			savedRegisters = registers.getSP() + stackSize - 4 - 4*1;
+			registers.setEBX(addressSpace.get32(savedRegisters));
+			framelessUnwind(addressSpace, savedRegisters+4*1, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_IND_STK_ESI:
+			stackSize = addressSpace.get32(functionStart+stackValue);
+			stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_STACK_ADJUST);
+			stackSize += stackAdjust*4;
+			savedRegisters = registers.getSP() + stackSize - 4 - 4*1;
+			registers.setESI(addressSpace.get32(savedRegisters));
+			framelessUnwind(addressSpace, savedRegisters+4*1, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_IND_STK_EDI:
+			stackSize = addressSpace.get32(functionStart+stackValue);
+			stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_STACK_ADJUST);
+			stackSize += stackAdjust*4;
+			savedRegisters = registers.getSP() + stackSize - 4 - 4*1;
+			registers.setEDI(addressSpace.get32(savedRegisters));
+			return UNW_STEP_SUCCESS;
+			framelessUnwind(addressSpace, savedRegisters+4*1, registers);
+		
+		case UNWIND_X86_IND_STK_EBX_ESI:
+			stackSize = addressSpace.get32(functionStart+stackValue);
+			stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_STACK_ADJUST);
+			stackSize += stackAdjust*4;
+			savedRegisters = registers.getSP() + stackSize - 4 - 4*2;
+			registers.setEBX(addressSpace.get32(savedRegisters));
+			registers.setESI(addressSpace.get32(savedRegisters+4));
+			framelessUnwind(addressSpace, savedRegisters+4*2, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_IND_STK_ESI_EDI:
+			stackSize = addressSpace.get32(functionStart+stackValue);
+			stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_STACK_ADJUST);
+			stackSize += stackAdjust*4;
+			savedRegisters = registers.getSP() + stackSize - 4 - 4*2;
+			registers.setESI(addressSpace.get32(savedRegisters));
+			registers.setEDI(addressSpace.get32(savedRegisters+4));
+			framelessUnwind(addressSpace, savedRegisters+4*2, registers);
+			return UNW_STEP_SUCCESS;
+			
+		case UNWIND_X86_IND_STK_ESI_EDI_EBP:
+			stackSize = addressSpace.get32(functionStart+stackValue);
+			stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_STACK_ADJUST);
+			stackSize += stackAdjust*4;
+			savedRegisters = registers.getSP() + stackSize - 4 - 4*3;
+			registers.setESI(addressSpace.get32(savedRegisters));
+			registers.setEDI(addressSpace.get32(savedRegisters+4));
+			registers.setEBP(addressSpace.get32(savedRegisters+8));
+			framelessUnwind(addressSpace, savedRegisters+4*3, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_IND_STK_EBX_ESI_EDI:
+			stackSize = addressSpace.get32(functionStart+stackValue);
+			stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_STACK_ADJUST);
+			stackSize += stackAdjust*4;
+			savedRegisters = registers.getSP() + stackSize - 4 - 4*3;
+			registers.setEBX(addressSpace.get32(savedRegisters));
+			registers.setESI(addressSpace.get32(savedRegisters+4));
+			registers.setEDI(addressSpace.get32(savedRegisters+8));
+			framelessUnwind(addressSpace, savedRegisters+4*3, registers);
+			return UNW_STEP_SUCCESS;
+
+		case UNWIND_X86_IND_STK_EBX_ESI_EDI_EBP:
+			stackSize = addressSpace.get32(functionStart+stackValue);
+			stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_STACK_ADJUST);
+			stackSize += stackAdjust*4;
+			savedRegisters = registers.getSP() + stackSize - 4 - 4*4;
+			registers.setEBX(addressSpace.get32(savedRegisters));
+			registers.setESI(addressSpace.get32(savedRegisters+4));
+			registers.setEDI(addressSpace.get32(savedRegisters+8));
+			registers.setEBP(addressSpace.get32(savedRegisters+12));
+			framelessUnwind(addressSpace, savedRegisters+4*4, registers);
+			return UNW_STEP_SUCCESS;
+		
+		default:
+			DEBUG_MESSAGE("unknown compact unwind encoding %08X for function starting at 0x%X\n", 
+				compactEncoding & UNWIND_X86_CASE_MASK, functionStart);
+			ABORT("unknown compact unwind encoding");
+	}
+	return UNW_EINVAL;
+}
+#endif // SUPPORT_OLD_BINARIES
+
+
+
+template <typename A>
+void CompactUnwinder_x86<A>::frameUnwind(A& addressSpace, Registers_x86& registers)
+{
+	typename A::pint_t bp = registers.getEBP();
+	// ebp points to old ebp
+	registers.setEBP(addressSpace.get32(bp));
+	// old esp is ebp less saved ebp and return address
+	registers.setSP(bp+8);
+	// pop return address into eip
+	registers.setIP(addressSpace.get32(bp+4));
+}
+
+template <typename A>
+void CompactUnwinder_x86<A>::framelessUnwind(A& addressSpace, typename A::pint_t returnAddressLocation, Registers_x86& registers)
+{
+	// return address is on stack after last saved register
+	registers.setIP(addressSpace.get32(returnAddressLocation));
+	// old esp is before return address
+	registers.setSP(returnAddressLocation+4);
+}
+
+
+
+
+
+///
+/// CompactUnwinder_x86_64 uses a compact unwind info to virtually "step" (aka unwind) by
+/// modifying a Registers_x86_64 register set
+///
+template <typename A>
+class CompactUnwinder_x86_64
+{
+public:
+
+	static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A& addressSpace, Registers_x86_64& registers);
+	
+private:
+	typename A::pint_t		pint_t;
+	
+	static void frameUnwind(A& addressSpace, Registers_x86_64& registers);
+	static void framelessUnwind(A& addressSpace, uint64_t returnAddressLocation, Registers_x86_64& registers);
+	static int stepWithCompactEncodingRBPFrame(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A& addressSpace, Registers_x86_64& registers);
+	static int stepWithCompactEncodingFrameless(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A& addressSpace, Registers_x86_64& registers, bool indirectStackSize);
+#if SUPPORT_OLD_BINARIES
+	static int stepWithCompactEncodingCompat(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A& addressSpace, Registers_x86_64& registers);
+#endif
+};
+
+
+template <typename A>
+int CompactUnwinder_x86_64<A>::stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A& addressSpace, Registers_x86_64& registers)
+{
+	//fprintf(stderr, "stepWithCompactEncoding(0x%08X)\n", compactEncoding);
+	switch ( compactEncoding & UNWIND_X86_64_MODE_MASK ) {
+#if SUPPORT_OLD_BINARIES
+		case UNWIND_X86_64_MODE_COMPATIBILITY:
+			return stepWithCompactEncodingCompat(compactEncoding, functionStart, addressSpace, registers);
+#endif
+		case UNWIND_X86_64_MODE_RBP_FRAME:
+			return stepWithCompactEncodingRBPFrame(compactEncoding, functionStart, addressSpace, registers);
+		case UNWIND_X86_64_MODE_STACK_IMMD:
+			return stepWithCompactEncodingFrameless(compactEncoding, functionStart, addressSpace, registers, false);
+		case UNWIND_X86_64_MODE_STACK_IND:
+			return stepWithCompactEncodingFrameless(compactEncoding, functionStart, addressSpace, registers, true);
+	}
+	ABORT("invalid compact unwind encoding");
+}
+
+	
+template <typename A>
+int CompactUnwinder_x86_64<A>::stepWithCompactEncodingRBPFrame(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, 
+																	A& addressSpace, Registers_x86_64& registers)
+{
+	uint32_t savedRegistersOffset = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_OFFSET);
+	uint32_t savedRegistersLocations = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_REGISTERS);
+	
+	uint64_t savedRegisters = registers.getRBP() - 8*savedRegistersOffset;
+	for (int i=0; i < 5; ++i) {
+        int readerr = 0;
+		switch (savedRegistersLocations & 0x7) {
+			case UNWIND_X86_64_REG_NONE:
+				// no register saved in this slot
+				break;
+			case UNWIND_X86_64_REG_RBX:
+				registers.setRBX(addressSpace.get64(savedRegisters, readerr));
+				break;
+			case UNWIND_X86_64_REG_R12:
+				registers.setR12(addressSpace.get64(savedRegisters, readerr));
+				break;
+			case UNWIND_X86_64_REG_R13:
+				registers.setR13(addressSpace.get64(savedRegisters, readerr));
+				break;
+			case UNWIND_X86_64_REG_R14:
+				registers.setR14(addressSpace.get64(savedRegisters, readerr));
+				break;
+			case UNWIND_X86_64_REG_R15:
+				registers.setR15(addressSpace.get64(savedRegisters, readerr));
+				break;
+			default:
+				DEBUG_MESSAGE("bad register for RBP frame, encoding=%08X for function starting at 0x%llX\n", compactEncoding, functionStart);
+				ABORT("invalid compact unwind encoding");
+		}
+        // Error reading memory while doing a remote unwind?
+        if (readerr)
+            return UNW_STEP_END;
+
+		savedRegisters += 8;
+		savedRegistersLocations = (savedRegistersLocations >> 3);
+	}
+	frameUnwind(addressSpace, registers);
+	return UNW_STEP_SUCCESS;
+}
+
+		
+template <typename A>
+int CompactUnwinder_x86_64<A>::stepWithCompactEncodingFrameless(compact_unwind_encoding_t encoding, uint64_t functionStart, 
+																A& addressSpace, Registers_x86_64& registers, bool indirectStackSize)
+{
+	uint32_t stackSizeEncoded = EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE);
+	uint32_t stackAdjust = EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST);
+	uint32_t regCount = EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT);
+	uint32_t permutation = EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION);
+	uint32_t stackSize = stackSizeEncoded*8;
+	if ( indirectStackSize ) {
+		// stack size is encoded in subl $xxx,%esp instruction
+		uint32_t subl = addressSpace.get32(functionStart+stackSizeEncoded);
+		stackSize = subl + 8*stackAdjust;
+	}
+	// decompress permutation
+	int permunreg[6];
+	switch ( regCount ) {
+		case 6:
+			permunreg[0] = permutation/120;
+			permutation -= (permunreg[0]*120);
+			permunreg[1] = permutation/24;
+			permutation -= (permunreg[1]*24);
+			permunreg[2] = permutation/6;
+			permutation -= (permunreg[2]*6);
+			permunreg[3] = permutation/2;
+			permutation -= (permunreg[3]*2);
+			permunreg[4] = permutation;
+			permunreg[5] = 0;
+			break;
+		case 5:
+			permunreg[0] = permutation/120;
+			permutation -= (permunreg[0]*120);
+			permunreg[1] = permutation/24;
+			permutation -= (permunreg[1]*24);
+			permunreg[2] = permutation/6;
+			permutation -= (permunreg[2]*6);
+			permunreg[3] = permutation/2;
+			permutation -= (permunreg[3]*2);
+			permunreg[4] = permutation;
+			break;
+		case 4:
+			permunreg[0] = permutation/60;
+			permutation -= (permunreg[0]*60);
+			permunreg[1] = permutation/12;
+			permutation -= (permunreg[1]*12);
+			permunreg[2] = permutation/3;
+			permutation -= (permunreg[2]*3);
+			permunreg[3] = permutation;
+			break;
+		case 3:
+			permunreg[0] = permutation/20;
+			permutation -= (permunreg[0]*20);
+			permunreg[1] = permutation/4;
+			permutation -= (permunreg[1]*4);
+			permunreg[2] = permutation;
+			break;
+		case 2:
+			permunreg[0] = permutation/5;
+			permutation -= (permunreg[0]*5);
+			permunreg[1] = permutation;
+			break;
+		case 1:
+			permunreg[0] = permutation;
+			break;
+	}
+	// re-number registers back to standard numbers
+	int registersSaved[6];
+	bool used[7] = { false, false, false, false, false, false, false };
+	for (uint32_t i=0; i < regCount; ++i) {
+		int renum = 0; 
+		for (int u=1; u < 7; ++u) {
+			if ( !used[u] ) {
+				if ( renum == permunreg[i] ) {
+					registersSaved[i] = u;
+					used[u] = true;
+					break;
+				}
+				++renum;
+			}
+		}
+	}
+	uint64_t savedRegisters = registers.getSP() + stackSize - 8 - 8*regCount;
+	for (uint32_t i=0; i < regCount; ++i) {
+		switch ( registersSaved[i] ) {
+			case UNWIND_X86_64_REG_RBX:
+				registers.setRBX(addressSpace.get64(savedRegisters));
+				break;
+			case UNWIND_X86_64_REG_R12:
+				registers.setR12(addressSpace.get64(savedRegisters));
+				break;
+			case UNWIND_X86_64_REG_R13:
+				registers.setR13(addressSpace.get64(savedRegisters));
+				break;
+			case UNWIND_X86_64_REG_R14:
+				registers.setR14(addressSpace.get64(savedRegisters));
+				break;
+			case UNWIND_X86_64_REG_R15:
+				registers.setR15(addressSpace.get64(savedRegisters));
+				break;
+			case UNWIND_X86_64_REG_RBP:
+				registers.setRBP(addressSpace.get64(savedRegisters));
+				break;
+			default:
+				DEBUG_MESSAGE("bad register for frameless, encoding=%08X for function starting at 0x%llX\n", encoding, functionStart);
+				ABORT("invalid compact unwind encoding");
+		}
+		savedRegisters += 8;
+	}
+	framelessUnwind(addressSpace, savedRegisters, registers);
+	return UNW_STEP_SUCCESS;
+}
+
+#if SUPPORT_OLD_BINARIES
+template <typename A>
+int CompactUnwinder_x86_64<A>::stepWithCompactEncodingCompat(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A& addressSpace, Registers_x86_64& registers)
+{
+	uint64_t savedRegisters;
+	uint32_t stackValue = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_SIZE);
+	uint64_t stackSize;
+	uint32_t stackAdjust;
+	
+	switch (compactEncoding & UNWIND_X86_64_CASE_MASK ) {
+		case UNWIND_X86_64_UNWIND_INFO_UNSPECIFIED:
+			return UNW_ENOINFO;
+			
+		case UNWIND_X86_64_RBP_FRAME_NO_REGS:
+			frameUnwind(addressSpace, registers);
+			return UNW_STEP_SUCCESS;
+			
+		case UNWIND_X86_64_RBP_FRAME_RBX:
+			savedRegisters = registers.getRBP() - 8*1;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			frameUnwind(addressSpace, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_64_RBP_FRAME_RBX_R12:
+			savedRegisters = registers.getRBP() - 8*2;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			registers.setR12(addressSpace.get64(savedRegisters+8));
+			frameUnwind(addressSpace, registers);
+			return UNW_STEP_SUCCESS;
+
+		case UNWIND_X86_64_RBP_FRAME_RBX_R12_R13:
+			savedRegisters = registers.getRBP() - 8*3;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			registers.setR12(addressSpace.get64(savedRegisters+8));
+			registers.setR13(addressSpace.get64(savedRegisters+16));
+			frameUnwind(addressSpace, registers);
+			return UNW_STEP_SUCCESS;
+
+		case UNWIND_X86_64_RBP_FRAME_RBX_R12_R13_R14:
+			savedRegisters = registers.getRBP() - 8*4;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			registers.setR12(addressSpace.get64(savedRegisters+8));
+			registers.setR13(addressSpace.get64(savedRegisters+16));
+			registers.setR14(addressSpace.get64(savedRegisters+24));
+			frameUnwind(addressSpace, registers);
+			return UNW_STEP_SUCCESS;
+
+		case UNWIND_X86_64_RBP_FRAME_RBX_R12_R13_R14_R15:
+			savedRegisters = registers.getRBP() - 8*5;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			registers.setR12(addressSpace.get64(savedRegisters+8));
+			registers.setR13(addressSpace.get64(savedRegisters+16));
+			registers.setR14(addressSpace.get64(savedRegisters+24));
+			registers.setR15(addressSpace.get64(savedRegisters+32));
+			frameUnwind(addressSpace, registers);
+			return UNW_STEP_SUCCESS;
+	
+		case UNWIND_X86_64_IMM_STK_NO_REGS:
+			stackSize = stackValue * 8;
+			savedRegisters = registers.getSP() + stackSize - 8 - 8*0;
+			framelessUnwind(addressSpace, savedRegisters+8*0, registers);
+			return UNW_STEP_SUCCESS;
+				
+		case UNWIND_X86_64_IMM_STK_RBX:
+			stackSize = stackValue * 8;
+			savedRegisters = registers.getSP() + stackSize - 8 - 8*1;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			framelessUnwind(addressSpace, savedRegisters+8*1, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_64_IMM_STK_RBX_R12:
+			stackSize = stackValue * 8;
+			savedRegisters = registers.getSP() + stackSize - 8 - 8*2;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			registers.setR12(addressSpace.get64(savedRegisters+8));
+			framelessUnwind(addressSpace, savedRegisters+8*2, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_64_IMM_STK_RBX_RBP:
+			stackSize = stackValue * 8;
+			savedRegisters = registers.getSP() + stackSize - 8 - 8*2;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			registers.setRBP(addressSpace.get64(savedRegisters+8));
+			framelessUnwind(addressSpace, savedRegisters+8*2, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_64_IMM_STK_RBX_R12_R13:
+			stackSize = stackValue * 8;
+			savedRegisters = registers.getSP() + stackSize - 8 - 8*3;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			registers.setR12(addressSpace.get64(savedRegisters+8));
+			registers.setR13(addressSpace.get64(savedRegisters+16));
+			framelessUnwind(addressSpace, savedRegisters+8*3, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_64_IMM_STK_RBX_R12_R13_R14:
+			stackSize = stackValue * 8;
+			savedRegisters = registers.getSP() + stackSize - 8 - 8*4;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			registers.setR12(addressSpace.get64(savedRegisters+8));
+			registers.setR13(addressSpace.get64(savedRegisters+16));
+			registers.setR14(addressSpace.get64(savedRegisters+24));
+			framelessUnwind(addressSpace, savedRegisters+8*4, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_64_IMM_STK_RBX_R12_R13_R14_R15:
+			stackSize = stackValue * 8;
+			savedRegisters = registers.getSP() + stackSize - 8 - 8*5;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			registers.setR12(addressSpace.get64(savedRegisters+8));
+			registers.setR13(addressSpace.get64(savedRegisters+16));
+			registers.setR14(addressSpace.get64(savedRegisters+24));
+			registers.setR15(addressSpace.get64(savedRegisters+32));
+			framelessUnwind(addressSpace, savedRegisters+8*5, registers);
+			return UNW_STEP_SUCCESS;
+			
+		case UNWIND_X86_64_IMM_STK_RBX_RBP_R12_R13_R14_R15:
+			stackSize = stackValue * 8;
+			savedRegisters = registers.getSP() + stackSize - 8 - 8*6;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			registers.setRBP(addressSpace.get64(savedRegisters+8));
+			registers.setR12(addressSpace.get64(savedRegisters+16));
+			registers.setR13(addressSpace.get64(savedRegisters+24));
+			registers.setR14(addressSpace.get64(savedRegisters+32));
+			registers.setR15(addressSpace.get64(savedRegisters+40));
+			framelessUnwind(addressSpace, savedRegisters+8*6, registers);
+			return UNW_STEP_SUCCESS;
+
+		case UNWIND_X86_64_IMM_STK_RBX_RBP_R12:
+			stackSize = stackValue * 8;
+			savedRegisters = registers.getSP() + stackSize - 8 - 8*3;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			registers.setRBP(addressSpace.get64(savedRegisters+8));
+			registers.setR12(addressSpace.get64(savedRegisters+16));
+			framelessUnwind(addressSpace, savedRegisters+8*3, registers);
+			return UNW_STEP_SUCCESS;
+
+		case UNWIND_X86_64_IMM_STK_RBX_RBP_R12_R13:
+			stackSize = stackValue * 8;
+			savedRegisters = registers.getSP() + stackSize - 8 - 8*4;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			registers.setRBP(addressSpace.get64(savedRegisters+8));
+			registers.setR12(addressSpace.get64(savedRegisters+16));
+			registers.setR13(addressSpace.get64(savedRegisters+24));
+			framelessUnwind(addressSpace, savedRegisters+8*4, registers);
+			return UNW_STEP_SUCCESS;
+
+		case UNWIND_X86_64_IMM_STK_RBX_RBP_R12_R13_R14:
+			stackSize = stackValue * 8;
+			savedRegisters = registers.getSP() + stackSize - 8 - 8*5;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			registers.setRBP(addressSpace.get64(savedRegisters+8));
+			registers.setR12(addressSpace.get64(savedRegisters+16));
+			registers.setR13(addressSpace.get64(savedRegisters+24));
+			registers.setR14(addressSpace.get64(savedRegisters+32));
+			framelessUnwind(addressSpace, savedRegisters+8*5, registers);
+			return UNW_STEP_SUCCESS;
+
+		case UNWIND_X86_64_IND_STK_NO_REGS:
+			stackSize = addressSpace.get32(functionStart+stackValue);
+			stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_ADJUST);
+			stackSize += stackAdjust*8;
+			savedRegisters = registers.getSP() + stackSize - 8 - 8*0;
+			framelessUnwind(addressSpace, savedRegisters+8*0, registers);
+			return UNW_STEP_SUCCESS;
+				
+		case UNWIND_X86_64_IND_STK_RBX:
+			stackSize = addressSpace.get32(functionStart+stackValue);
+			stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_ADJUST);
+			stackSize += stackAdjust*8;
+			savedRegisters = registers.getSP() + stackSize - 8 - 8*1;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			framelessUnwind(addressSpace, savedRegisters+8*1, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_64_IND_STK_RBX_R12:
+			stackSize = addressSpace.get32(functionStart+stackValue);
+			stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_ADJUST);
+			stackSize += stackAdjust*8;
+			savedRegisters = registers.getSP() + stackSize - 8 - 8*2;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			registers.setR12(addressSpace.get64(savedRegisters+8));
+			framelessUnwind(addressSpace, savedRegisters+8*2, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_64_IND_STK_RBX_RBP:
+			stackSize = addressSpace.get32(functionStart+stackValue);
+			stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_ADJUST);
+			stackSize += stackAdjust*8;
+			savedRegisters = registers.getSP() + stackSize - 8 - 8*2;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			registers.setRBP(addressSpace.get64(savedRegisters+8));
+			framelessUnwind(addressSpace, savedRegisters+8*2, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_64_IND_STK_RBX_R12_R13:
+			stackSize = addressSpace.get32(functionStart+stackValue);
+			stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_ADJUST);
+			stackSize += stackAdjust*8;
+			savedRegisters = registers.getSP() + stackSize - 8 - 8*3;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			registers.setR12(addressSpace.get64(savedRegisters+8));
+			registers.setR13(addressSpace.get64(savedRegisters+16));
+			framelessUnwind(addressSpace, savedRegisters+8*3, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_64_IND_STK_RBX_R12_R13_R14:
+			stackSize = addressSpace.get32(functionStart+stackValue);
+			stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_ADJUST);
+			stackSize += stackAdjust*8;
+			savedRegisters = registers.getSP() + stackSize - 8 - 8*4;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			registers.setR12(addressSpace.get64(savedRegisters+8));
+			registers.setR13(addressSpace.get64(savedRegisters+16));
+			registers.setR14(addressSpace.get64(savedRegisters+24));
+			framelessUnwind(addressSpace, savedRegisters+8*4, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_64_IND_STK_RBX_R12_R13_R14_R15:
+			stackSize = addressSpace.get32(functionStart+stackValue);
+			stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_ADJUST);
+			stackSize += stackAdjust*8;
+			savedRegisters = registers.getSP() + stackSize - 8 - 8*5;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			registers.setR12(addressSpace.get64(savedRegisters+8));
+			registers.setR13(addressSpace.get64(savedRegisters+16));
+			registers.setR14(addressSpace.get64(savedRegisters+24));
+			registers.setR15(addressSpace.get64(savedRegisters+32));
+			framelessUnwind(addressSpace, savedRegisters+8*5, registers);
+			return UNW_STEP_SUCCESS;
+			
+		case UNWIND_X86_64_IND_STK_RBX_RBP_R12_R13_R14_R15:
+			stackSize = addressSpace.get32(functionStart+stackValue);
+			stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_ADJUST);
+			stackSize += stackAdjust*8;
+			savedRegisters = registers.getSP() + stackSize - 8 - 8*6;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			registers.setRBP(addressSpace.get64(savedRegisters+8));
+			registers.setR12(addressSpace.get64(savedRegisters+16));
+			registers.setR13(addressSpace.get64(savedRegisters+24));
+			registers.setR14(addressSpace.get64(savedRegisters+32));
+			registers.setR15(addressSpace.get64(savedRegisters+40));
+			framelessUnwind(addressSpace, savedRegisters+8*6, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_64_IND_STK_RBX_RBP_R12:
+			stackSize = addressSpace.get32(functionStart+stackValue);
+			stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_ADJUST);
+			stackSize += stackAdjust*8;
+			savedRegisters = registers.getSP() + stackSize - 8 - 8*3;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			registers.setRBP(addressSpace.get64(savedRegisters+8));
+			registers.setR12(addressSpace.get64(savedRegisters+16));
+			framelessUnwind(addressSpace, savedRegisters+8*3, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_64_IND_STK_RBX_RBP_R12_R13:
+			stackSize = addressSpace.get32(functionStart+stackValue);
+			stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_ADJUST);
+			stackSize += stackAdjust*8;
+			savedRegisters = registers.getSP() + stackSize - 8 - 8*4;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			registers.setRBP(addressSpace.get64(savedRegisters+8));
+			registers.setR12(addressSpace.get64(savedRegisters+16));
+			registers.setR13(addressSpace.get64(savedRegisters+24));
+			framelessUnwind(addressSpace, savedRegisters+8*4, registers);
+			return UNW_STEP_SUCCESS;
+		
+		case UNWIND_X86_64_IND_STK_RBX_RBP_R12_R13_R14:
+			stackSize = addressSpace.get32(functionStart+stackValue);
+			stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_ADJUST);
+			stackSize += stackAdjust*8;
+			savedRegisters = registers.getSP() + stackSize - 8 - 8*5;
+			registers.setRBX(addressSpace.get64(savedRegisters));
+			registers.setRBP(addressSpace.get64(savedRegisters+8));
+			registers.setR12(addressSpace.get64(savedRegisters+16));
+			registers.setR13(addressSpace.get64(savedRegisters+24));
+			registers.setR14(addressSpace.get64(savedRegisters+32));
+			framelessUnwind(addressSpace, savedRegisters+8*5, registers);
+			return UNW_STEP_SUCCESS;
+		
+		default:
+			DEBUG_MESSAGE("unknown compact unwind encoding %08X for function starting at 0x%llX\n", 
+				compactEncoding & UNWIND_X86_64_CASE_MASK, functionStart);
+			ABORT("unknown compact unwind encoding");
+	}
+	return UNW_EINVAL;
+}
+#endif // SUPPORT_OLD_BINARIES
+
+
+template <typename A>
+void CompactUnwinder_x86_64<A>::frameUnwind(A& addressSpace, Registers_x86_64& registers)
+{
+	uint64_t rbp = registers.getRBP();
+	// ebp points to old ebp
+	registers.setRBP(addressSpace.get64(rbp));
+	// old esp is ebp less saved ebp and return address
+	registers.setSP(rbp+16);
+	// pop return address into eip
+	registers.setIP(addressSpace.get64(rbp+8));
+}
+
+template <typename A>
+void CompactUnwinder_x86_64<A>::framelessUnwind(A& addressSpace, uint64_t returnAddressLocation, Registers_x86_64& registers)
+{
+	// return address is on stack after last saved register
+	registers.setIP(addressSpace.get64(returnAddressLocation));
+	// old esp is before return address
+	registers.setSP(returnAddressLocation+8);
+}
+
+
+}; // namespace lldb_private
+
+
+
+#endif // __COMPACT_UNWINDER_HPP__
+
+
+
+
diff --git a/source/Plugins/Process/Utility/libunwind/src/DwarfInstructions.hpp b/source/Plugins/Process/Utility/libunwind/src/DwarfInstructions.hpp
new file mode 100644
index 0000000..589c30b
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/DwarfInstructions.hpp
@@ -0,0 +1,1686 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- DwarfInstructions.hpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+ 
+//
+// processor specific parsing of dwarf unwind instructions
+//
+
+#ifndef __DWARF_INSTRUCTIONS_HPP__
+#define __DWARF_INSTRUCTIONS_HPP__
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <algorithm>
+#include <vector>
+
+#include <libunwind.h>
+#include <mach-o/compact_unwind_encoding.h>
+
+#include "dwarf2.h"
+#include "AddressSpace.hpp"
+#include "Registers.hpp"
+#include "DwarfParser.hpp"
+#include "InternalMacros.h"
+//#include "CompactUnwinder.hpp"
+
+#define EXTRACT_BITS(value, mask) \
+	( (value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask)))-1) )
+
+#define CFI_INVALID_ADDRESS ((pint_t)(-1))
+
+namespace lldb_private {
+
+///
+/// Used by linker when parsing __eh_frame section
+///  
+template <typename A>
+struct CFI_Reference {
+	typedef typename A::pint_t		pint_t;	
+	uint8_t		encodingOfTargetAddress;
+	uint32_t	offsetInCFI;
+	pint_t		targetAddress;
+};
+template <typename A>
+struct CFI_Atom_Info {
+	typedef typename A::pint_t		pint_t;	
+	pint_t			address;
+	uint32_t		size;
+	bool			isCIE;
+	union {
+		struct {
+			CFI_Reference<A>	function;
+			CFI_Reference<A>	cie;
+			CFI_Reference<A>	lsda;
+			uint32_t		compactUnwindInfo;
+		}			fdeInfo;
+		struct {
+			CFI_Reference<A>	personality;
+		}			cieInfo;
+	} u;
+};
+
+typedef void (*WarnFunc)(void* ref, uint64_t funcAddr, const char* msg);  
+
+///
+/// DwarfInstructions maps abtract dwarf unwind instructions to a particular architecture
+///  
+template <typename A, typename R>
+class DwarfInstructions
+{
+public:
+	typedef typename A::pint_t		pint_t;	
+	typedef typename A::sint_t		sint_t;	
+
+	static const char* parseCFIs(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength, 
+						CFI_Atom_Info<A>* infos, uint32_t infosCount, void* ref, WarnFunc warn);
+
+
+	static compact_unwind_encoding_t createCompactEncodingFromFDE(A& addressSpace, pint_t fdeStart, 
+																pint_t* lsda, pint_t* personality,
+																char warningBuffer[1024]);
+
+	static int stepWithDwarf(A& addressSpace, pint_t pc, pint_t fdeStart, R& registers);
+										
+private:
+
+	enum {
+		DW_X86_64_RET_ADDR = 16
+	};
+
+	enum {
+		DW_X86_RET_ADDR = 8
+	};
+
+	static pint_t evaluateExpression(pint_t expression, A& addressSpace, const R& registers, pint_t initialStackValue);
+	static pint_t getSavedRegister(A& addressSpace, const R& registers, pint_t cfa, 
+										const typename CFI_Parser<A>::RegisterLocation& savedReg);
+	static double getSavedFloatRegister(A& addressSpace, const R& registers, pint_t cfa, 
+										const typename CFI_Parser<A>::RegisterLocation& savedReg);
+	static v128 getSavedVectorRegister(A& addressSpace, const R& registers, pint_t cfa, 
+										const typename CFI_Parser<A>::RegisterLocation& savedReg);
+										
+	// x86 specific variants
+	static int    lastRestoreReg(const Registers_x86&);
+	static bool   isReturnAddressRegister(int regNum, const Registers_x86&);
+	static pint_t getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, const Registers_x86&);
+
+	static uint32_t getEBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool& failure);
+	static compact_unwind_encoding_t encodeToUseDwarf(const Registers_x86&);
+	static compact_unwind_encoding_t createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
+												const Registers_x86&, const typename CFI_Parser<A>::PrologInfo& prolog,
+												char warningBuffer[1024]);
+
+	// x86_64 specific variants
+	static int    lastRestoreReg(const Registers_x86_64&);
+	static bool   isReturnAddressRegister(int regNum, const Registers_x86_64&);
+	static pint_t getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, const Registers_x86_64&);
+
+	static uint32_t getRBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool& failure);
+	static compact_unwind_encoding_t encodeToUseDwarf(const Registers_x86_64&);
+	static compact_unwind_encoding_t createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
+												const Registers_x86_64&, const typename CFI_Parser<A>::PrologInfo& prolog,
+												char warningBuffer[1024]);
+	
+	// ppc specific variants
+	static int    lastRestoreReg(const Registers_ppc&);
+	static bool   isReturnAddressRegister(int regNum, const Registers_ppc&);
+	static pint_t getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, const Registers_ppc&);
+	static compact_unwind_encoding_t encodeToUseDwarf(const Registers_ppc&);
+	static compact_unwind_encoding_t createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
+												const Registers_ppc&, const typename CFI_Parser<A>::PrologInfo& prolog,
+												char warningBuffer[1024]);
+};
+
+
+											
+
+template <typename A, typename R>
+const char* DwarfInstructions<A,R>::parseCFIs(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength, 
+												CFI_Atom_Info<A>* infos, uint32_t infosCount, void* ref, WarnFunc warn)
+{
+	typename CFI_Parser<A>::CIE_Info cieInfo;
+	CFI_Atom_Info<A>* entry = infos;
+	CFI_Atom_Info<A>* end = &infos[infosCount];
+	const pint_t ehSectionEnd = ehSectionStart + sectionLength;
+	for (pint_t p=ehSectionStart; p < ehSectionEnd; ) {
+		pint_t currentCFI = p;
+		uint64_t cfiLength = addressSpace.get32(p);
+		p += 4;
+		if ( cfiLength == 0xffffffff ) {
+			// 0xffffffff means length is really next 8 bytes
+			cfiLength = addressSpace.get64(p);
+			p += 8;
+		}
+		if ( cfiLength == 0 ) 
+			return NULL;	// end marker
+		if ( entry >= end )
+			return "too little space allocated for parseCFIs";
+		pint_t nextCFI = p + cfiLength;
+		uint32_t id = addressSpace.get32(p);
+		if ( id == 0 ) {
+			// is CIE
+			const char* err = CFI_Parser<A>::parseCIE(addressSpace, currentCFI, &cieInfo);
+			if ( err != NULL ) 
+				return err;
+			entry->address = currentCFI;
+			entry->size = nextCFI - currentCFI;
+			entry->isCIE = true;
+			entry->u.cieInfo.personality.targetAddress = cieInfo.personality;
+			entry->u.cieInfo.personality.offsetInCFI = cieInfo.personalityOffsetInCIE;
+			entry->u.cieInfo.personality.encodingOfTargetAddress = cieInfo.personalityEncoding;
+			++entry;
+		}
+		else {
+			// is FDE
+			entry->address = currentCFI;
+			entry->size = nextCFI - currentCFI;
+			entry->isCIE = false;
+			entry->u.fdeInfo.function.targetAddress = CFI_INVALID_ADDRESS;
+			entry->u.fdeInfo.cie.targetAddress = CFI_INVALID_ADDRESS;
+			entry->u.fdeInfo.lsda.targetAddress = CFI_INVALID_ADDRESS;
+			uint32_t ciePointer = addressSpace.get32(p);
+			pint_t cieStart = p-ciePointer;
+			// validate pointer to CIE is within section
+			if ( (cieStart < ehSectionStart) || (cieStart > ehSectionEnd) )
+				return "FDE points to CIE outside __eh_frame section";
+			// optimize usual case where cie is same for all FDEs
+			if ( cieStart != cieInfo.cieStart ) {
+				const char* err = CFI_Parser<A>::parseCIE(addressSpace, cieStart, &cieInfo);
+				if ( err != NULL ) 
+					return err;
+			}
+			entry->u.fdeInfo.cie.targetAddress = cieStart;
+			entry->u.fdeInfo.cie.offsetInCFI = p-currentCFI;
+			entry->u.fdeInfo.cie.encodingOfTargetAddress = DW_EH_PE_sdata4 | DW_EH_PE_pcrel;
+			p += 4;
+			// parse pc begin and range
+			pint_t offsetOfFunctionAddress = p-currentCFI;
+			pint_t pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding);
+			pint_t pcRange = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding & 0x0F);
+			//fprintf(stderr, "FDE with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pcStart, (uint64_t)(pcStart+pcRange));
+			// test if pc is within the function this FDE covers
+			entry->u.fdeInfo.function.targetAddress = pcStart;
+			entry->u.fdeInfo.function.offsetInCFI = offsetOfFunctionAddress;
+			entry->u.fdeInfo.function.encodingOfTargetAddress = cieInfo.pointerEncoding;
+			// check for augmentation length
+			if ( cieInfo.fdesHaveAugmentationData ) {
+				uintptr_t augLen = addressSpace.getULEB128(p, nextCFI);
+				pint_t endOfAug = p + augLen;
+				if ( cieInfo.lsdaEncoding != 0 ) {
+					// peek at value (without indirection).  Zero means no lsda
+					pint_t lsdaStart = p;
+					if ( addressSpace.getEncodedP(p, nextCFI, cieInfo.lsdaEncoding & 0x0F) != 0 ) {
+						// reset pointer and re-parse lsda address
+						p = lsdaStart;
+						pint_t offsetOfLSDAAddress = p-currentCFI;
+						entry->u.fdeInfo.lsda.targetAddress = addressSpace.getEncodedP(p, nextCFI, cieInfo.lsdaEncoding);
+						entry->u.fdeInfo.lsda.offsetInCFI = offsetOfLSDAAddress;
+						entry->u.fdeInfo.lsda.encodingOfTargetAddress = cieInfo.lsdaEncoding;
+					}
+				}
+				p = endOfAug;
+			}
+			// compute compact unwind encoding
+			typename CFI_Parser<A>::FDE_Info fdeInfo;
+			fdeInfo.fdeStart = currentCFI;
+			fdeInfo.fdeLength = nextCFI - currentCFI;
+			fdeInfo.fdeInstructions = p;
+			fdeInfo.pcStart = pcStart;
+			fdeInfo.pcEnd = pcStart +  pcRange;
+			fdeInfo.lsda = entry->u.fdeInfo.lsda.targetAddress;
+			typename CFI_Parser<A>::PrologInfo prolog;
+			R dummy; // for proper selection of architecture specific functions
+			if ( CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, CFI_INVALID_ADDRESS, &prolog) ) {
+				char warningBuffer[1024];
+				entry->u.fdeInfo.compactUnwindInfo = createCompactEncodingFromProlog(addressSpace, fdeInfo.pcStart, dummy, prolog, warningBuffer);
+				if ( fdeInfo.lsda != CFI_INVALID_ADDRESS ) 
+					entry->u.fdeInfo.compactUnwindInfo |= UNWIND_HAS_LSDA;
+				if ( warningBuffer[0] != '\0' )
+					warn(ref, fdeInfo.pcStart, warningBuffer);
+			}
+			else {
+				warn(ref, CFI_INVALID_ADDRESS, "dwarf unwind instructions could not be parsed");
+				entry->u.fdeInfo.compactUnwindInfo = encodeToUseDwarf(dummy);
+			}
+			++entry;
+		}
+		p = nextCFI;
+	}
+	if ( entry != end )
+		return "wrong entry count for parseCFIs";
+	return NULL; // success
+}
+
+
+
+
+template <typename A, typename R>
+compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromFDE(A& addressSpace, pint_t fdeStart, 
+																		pint_t* lsda, pint_t* personality,
+																		char warningBuffer[1024])
+{
+	typename CFI_Parser<A>::FDE_Info fdeInfo;
+	typename CFI_Parser<A>::CIE_Info cieInfo;
+	R dummy; // for proper selection of architecture specific functions
+	if ( CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo, &cieInfo) == NULL ) {
+		typename CFI_Parser<A>::PrologInfo prolog;
+		if ( CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, CFI_INVALID_ADDRESS, &prolog) ) {
+			*lsda = fdeInfo.lsda;
+			*personality = cieInfo.personality;
+			compact_unwind_encoding_t encoding;
+			encoding = createCompactEncodingFromProlog(addressSpace, fdeInfo.pcStart, dummy, prolog, warningBuffer);
+			if ( fdeInfo.lsda != 0 ) 
+				encoding |= UNWIND_HAS_LSDA;
+			return encoding;
+		}
+		else {
+			strcpy(warningBuffer, "dwarf unwind instructions could not be parsed");
+			return encodeToUseDwarf(dummy);
+		}
+	}
+	else {
+		strcpy(warningBuffer, "dwarf FDE could not be parsed");
+		return encodeToUseDwarf(dummy);
+	}
+}
+
+
+template <typename A, typename R>
+typename A::pint_t DwarfInstructions<A,R>::getSavedRegister(A& addressSpace, const R& registers, pint_t cfa,
+													const typename CFI_Parser<A>::RegisterLocation& savedReg)
+{
+	switch ( savedReg.location ) {
+		case CFI_Parser<A>::kRegisterInCFA:
+			return addressSpace.getP(cfa + savedReg.value);
+
+		case CFI_Parser<A>::kRegisterAtExpression:
+			return addressSpace.getP(evaluateExpression(savedReg.value, addressSpace, registers, cfa));
+
+		case CFI_Parser<A>::kRegisterIsExpression:
+			return evaluateExpression(savedReg.value, addressSpace, registers, cfa);
+
+		case CFI_Parser<A>::kRegisterInRegister:
+			return registers.getRegister(savedReg.value);
+
+		case CFI_Parser<A>::kRegisterUnused:
+		case CFI_Parser<A>::kRegisterOffsetFromCFA:
+			// FIX ME
+			break;
+	}
+	ABORT("unsupported restore location for register");
+}
+
+template <typename A, typename R>
+double DwarfInstructions<A,R>::getSavedFloatRegister(A& addressSpace, const R& registers, pint_t cfa,
+													const typename CFI_Parser<A>::RegisterLocation& savedReg)
+{
+	switch ( savedReg.location ) {
+		case CFI_Parser<A>::kRegisterInCFA:
+			return addressSpace.getDouble(cfa + savedReg.value);
+
+		case CFI_Parser<A>::kRegisterAtExpression:
+			return addressSpace.getDouble(evaluateExpression(savedReg.value, addressSpace, registers, cfa));
+
+		case CFI_Parser<A>::kRegisterIsExpression:
+		case CFI_Parser<A>::kRegisterUnused:
+		case CFI_Parser<A>::kRegisterOffsetFromCFA:
+		case CFI_Parser<A>::kRegisterInRegister:
+			// FIX ME
+			break;
+	}
+	ABORT("unsupported restore location for float register");
+}
+
+template <typename A, typename R>
+v128 DwarfInstructions<A,R>::getSavedVectorRegister(A& addressSpace, const R& registers, pint_t cfa,
+													const typename CFI_Parser<A>::RegisterLocation& savedReg)
+{
+	switch ( savedReg.location ) {
+		case CFI_Parser<A>::kRegisterInCFA:
+			return addressSpace.getVector(cfa + savedReg.value);
+
+		case CFI_Parser<A>::kRegisterAtExpression:
+			return addressSpace.getVector(evaluateExpression(savedReg.value, addressSpace, registers, cfa));
+
+		case CFI_Parser<A>::kRegisterIsExpression:
+		case CFI_Parser<A>::kRegisterUnused:
+		case CFI_Parser<A>::kRegisterOffsetFromCFA:
+		case CFI_Parser<A>::kRegisterInRegister:
+			// FIX ME
+			break;
+	}
+	ABORT("unsupported restore location for vector register");
+}
+
+
+template <typename A, typename R>
+int DwarfInstructions<A,R>::stepWithDwarf(A& addressSpace, pint_t pc, pint_t fdeStart, R& registers)
+{
+	//fprintf(stderr, "stepWithDwarf(pc=0x%0llX, fdeStart=0x%0llX)\n", (uint64_t)pc, (uint64_t)fdeStart);
+	typename CFI_Parser<A>::FDE_Info fdeInfo;
+	typename CFI_Parser<A>::CIE_Info cieInfo;
+	if ( CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo, &cieInfo) == NULL ) {
+		typename CFI_Parser<A>::PrologInfo prolog;
+		if ( CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc, &prolog) ) {
+			R newRegisters = registers;
+			
+			// get pointer to cfa (architecture specific)
+			pint_t cfa = getCFA(addressSpace, prolog, registers);
+
+			// restore registers that dwarf says were saved
+			pint_t returnAddress = 0;
+			for (int i=0; i <= lastRestoreReg(newRegisters); ++i) {
+				if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterUnused ) {
+					if ( registers.validFloatRegister(i) )
+						newRegisters.setFloatRegister(i, getSavedFloatRegister(addressSpace, registers, cfa, prolog.savedRegisters[i]));
+					else if ( registers.validVectorRegister(i) )
+						newRegisters.setVectorRegister(i, getSavedVectorRegister(addressSpace, registers, cfa, prolog.savedRegisters[i]));
+					else if ( isReturnAddressRegister(i, registers) )
+						returnAddress = getSavedRegister(addressSpace, registers, cfa, prolog.savedRegisters[i]);
+					else if ( registers.validRegister(i) )
+						newRegisters.setRegister(i, getSavedRegister(addressSpace, registers, cfa, prolog.savedRegisters[i]));
+					else
+						return UNW_EBADREG;
+				}
+			}
+			
+			// by definition the CFA is the stack pointer at the call site, so restoring SP means setting it to CFA
+			newRegisters.setSP(cfa);
+
+			// return address is address after call site instruction, so setting IP to that does a return
+			newRegisters.setIP(returnAddress);
+			
+			// do the actual step by replacing the register set with the new ones
+			registers = newRegisters;
+
+			return UNW_STEP_SUCCESS;
+		}
+	}
+	return UNW_EBADFRAME;
+}
+
+
+
+template <typename A, typename R>
+typename A::pint_t DwarfInstructions<A,R>::evaluateExpression(pint_t expression, A& addressSpace, 
+														const R& registers, pint_t initialStackValue)
+{
+	const bool log = false;
+	pint_t p = expression;
+	pint_t expressionEnd = expression+20; // just need something until length is read
+	uint64_t length = addressSpace.getULEB128(p, expressionEnd);
+	expressionEnd = p + length;
+	if (log) fprintf(stderr, "evaluateExpression(): length=%llu\n", length);
+	pint_t stack[100];
+	pint_t* sp = stack;
+	*(++sp) = initialStackValue;
+	
+	while ( p < expressionEnd ) {
+		if (log) {
+			for(pint_t* t = sp; t > stack; --t) {
+				fprintf(stderr, "sp[] = 0x%llX\n", (uint64_t)(*t));
+			}
+		}
+		uint8_t opcode = addressSpace.get8(p++);
+		sint_t svalue;
+		pint_t value;
+		uint32_t reg;
+		switch (opcode) {
+			case DW_OP_addr:
+				// push immediate address sized value
+				value = addressSpace.getP(p);
+				p += sizeof(pint_t);
+				*(++sp) = value;
+				if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value);
+				break;
+		
+			case DW_OP_deref:
+				// pop stack, dereference, push result
+				value = *sp--;
+				*(++sp) = addressSpace.getP(value);
+				if (log) fprintf(stderr, "dereference 0x%llX\n", (uint64_t)value);
+				break;
+		
+			case DW_OP_const1u:
+				// push immediate 1 byte value
+				value = addressSpace.get8(p);
+				p += 1;
+				*(++sp) = value;
+				if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value);
+				break;
+				
+			case DW_OP_const1s:
+				// push immediate 1 byte signed value
+				svalue = (int8_t)addressSpace.get8(p);
+				p += 1;
+				*(++sp) = svalue;
+				if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)svalue);
+				break;
+		
+			case DW_OP_const2u:
+				// push immediate 2 byte value
+				value = addressSpace.get16(p);
+				p += 2;
+				*(++sp) = value;
+				if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value);
+				break;
+				
+			case DW_OP_const2s:
+				// push immediate 2 byte signed value
+				svalue = (int16_t)addressSpace.get16(p);
+				p += 2;
+				*(++sp) = svalue;
+				if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)svalue);
+				break;
+		
+			case DW_OP_const4u:
+				// push immediate 4 byte value
+				value = addressSpace.get32(p);
+				p += 4;
+				*(++sp) = value;
+				if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value);
+				break;
+				
+			case DW_OP_const4s:
+				// push immediate 4 byte signed value
+				svalue = (int32_t)addressSpace.get32(p);
+				p += 4;
+				*(++sp) = svalue;
+				if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)svalue);
+				break;
+				
+			case DW_OP_const8u:
+				// push immediate 8 byte value
+				value = addressSpace.get64(p);
+				p += 8;
+				*(++sp) = value;
+				if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value);
+				break;
+				
+			case DW_OP_const8s:
+				// push immediate 8 byte signed value
+				value = (int32_t)addressSpace.get64(p);
+				p += 8;
+				*(++sp) = value;
+				if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value);
+				break;
+		
+			case DW_OP_constu:
+				// push immediate ULEB128 value
+				value = addressSpace.getULEB128(p, expressionEnd);
+				*(++sp) = value;
+				if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value);
+				break;
+				
+			case DW_OP_consts:
+				// push immediate SLEB128 value
+				svalue = addressSpace.getSLEB128(p, expressionEnd);
+				*(++sp) = svalue;
+				if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)svalue);
+				break;
+		
+			case DW_OP_dup:
+				// push top of stack
+				value = *sp;
+				*(++sp) = value;
+				if (log) fprintf(stderr, "duplicate top of stack\n");
+				break;
+				
+			case DW_OP_drop:
+				// pop
+				--sp; 
+				if (log) fprintf(stderr, "pop top of stack\n");
+				break;
+				
+			case DW_OP_over:
+				// dup second
+				value = sp[-1];
+				*(++sp) = value;
+				if (log) fprintf(stderr, "duplicate second in stack\n");
+				break;
+
+			case DW_OP_pick:
+				// pick from
+				reg = addressSpace.get8(p);
+				p += 1;
+				value = sp[-reg];
+				*(++sp) = value;
+				if (log) fprintf(stderr, "duplicate %d in stack\n", reg);
+				break;
+
+			case DW_OP_swap:
+				// swap top two
+				value = sp[0];
+				sp[0] = sp[-1];
+				sp[-1] = value;
+				if (log) fprintf(stderr, "swap top of stack\n");
+				break;
+
+			case DW_OP_rot:
+				// rotate top three
+				value = sp[0];
+				sp[0] = sp[-1];
+				sp[-1] = sp[-2];
+				sp[-2] = value;
+				if (log) fprintf(stderr, "rotate top three of stack\n");
+				break;
+
+			case DW_OP_xderef:
+				// pop stack, dereference, push result
+				value = *sp--;
+				*sp = *((uint64_t*)value);
+				if (log) fprintf(stderr, "x-dereference 0x%llX\n", (uint64_t)value);
+				break;
+			
+			case DW_OP_abs:
+				svalue = *sp;
+				if ( svalue < 0 )
+					*sp = -svalue;
+				if (log) fprintf(stderr, "abs\n");
+				break;
+		
+			case DW_OP_and:
+				value = *sp--;
+				*sp &= value;
+				if (log) fprintf(stderr, "and\n");
+				break;
+			
+			case DW_OP_div:
+				svalue = *sp--;
+				*sp = *sp / svalue;
+				if (log) fprintf(stderr, "div\n");
+				break;
+			
+			case DW_OP_minus:
+				svalue = *sp--;
+				*sp = *sp - svalue;
+				if (log) fprintf(stderr, "minus\n");
+				break;
+
+			case DW_OP_mod:
+				svalue = *sp--;
+				*sp = *sp % svalue;
+				if (log) fprintf(stderr, "module\n");
+				break;
+
+			case DW_OP_mul:
+				svalue = *sp--;
+				*sp = *sp * svalue;
+				if (log) fprintf(stderr, "mul\n");
+				break;
+
+			case DW_OP_neg:
+				*sp =  0 - *sp;
+				if (log) fprintf(stderr, "neg\n");
+				break;
+
+			case DW_OP_not:
+				svalue = *sp;
+				*sp =  ~svalue;
+				if (log) fprintf(stderr, "not\n");
+				break;
+
+			case DW_OP_or:
+				value = *sp--;
+				*sp |= value;
+				if (log) fprintf(stderr, "or\n");
+				break;
+
+			case DW_OP_plus:
+				value = *sp--;
+				*sp += value;
+				if (log) fprintf(stderr, "plus\n");
+				break;
+
+			case DW_OP_plus_uconst:
+				// pop stack, add uelb128 constant, push result
+				*sp += addressSpace.getULEB128(p, expressionEnd);
+				if (log) fprintf(stderr, "add constant\n");
+				break;
+		
+			case DW_OP_shl:
+				value = *sp--;
+				*sp = *sp << value;
+				if (log) fprintf(stderr, "shift left\n");
+				break;
+			
+			case DW_OP_shr:
+				value = *sp--;
+				*sp = *sp >> value;
+				if (log) fprintf(stderr, "shift left\n");
+				break;
+				
+			case DW_OP_shra:
+				value = *sp--;
+				svalue = *sp;
+				*sp = svalue >> value;
+				if (log) fprintf(stderr, "shift left arithmetric\n");
+				break;
+			
+			case DW_OP_xor:
+				value = *sp--;
+				*sp ^= value;
+				if (log) fprintf(stderr, "xor\n");
+				break;
+
+			case DW_OP_skip:
+				svalue = (int16_t)addressSpace.get16(p);
+				p += 2;
+				p += svalue;
+				if (log) fprintf(stderr, "skip %lld\n", (uint64_t)svalue);
+				break;
+			
+			case DW_OP_bra:
+				svalue = (int16_t)addressSpace.get16(p);
+				p += 2;
+				if ( *sp-- )
+					p += svalue;
+				if (log) fprintf(stderr, "bra %lld\n", (uint64_t)svalue);
+				break;
+			
+			case DW_OP_eq:
+				value = *sp--;
+				*sp = (*sp == value);
+				if (log) fprintf(stderr, "eq\n");
+				break;
+			
+			case DW_OP_ge:
+				value = *sp--;
+				*sp = (*sp >= value);
+				if (log) fprintf(stderr, "ge\n");
+				break;
+				
+			case DW_OP_gt:
+				value = *sp--;
+				*sp = (*sp > value);
+				if (log) fprintf(stderr, "gt\n");
+				break;
+				
+			case DW_OP_le:
+				value = *sp--;
+				*sp = (*sp <= value);
+				if (log) fprintf(stderr, "le\n");
+				break;
+				
+			case DW_OP_lt:
+				value = *sp--;
+				*sp = (*sp < value);
+				if (log) fprintf(stderr, "lt\n");
+				break;
+				
+			case DW_OP_ne:
+				value = *sp--;
+				*sp = (*sp != value);
+				if (log) fprintf(stderr, "ne\n");
+				break;
+			
+			case DW_OP_lit0:
+			case DW_OP_lit1:
+			case DW_OP_lit2:
+			case DW_OP_lit3:
+			case DW_OP_lit4:
+			case DW_OP_lit5:
+			case DW_OP_lit6:
+			case DW_OP_lit7:
+			case DW_OP_lit8:
+			case DW_OP_lit9:
+			case DW_OP_lit10:
+			case DW_OP_lit11:
+			case DW_OP_lit12:
+			case DW_OP_lit13:
+			case DW_OP_lit14:
+			case DW_OP_lit15:
+			case DW_OP_lit16:
+			case DW_OP_lit17:
+			case DW_OP_lit18:
+			case DW_OP_lit19:
+			case DW_OP_lit20:
+			case DW_OP_lit21:
+			case DW_OP_lit22:
+			case DW_OP_lit23:
+			case DW_OP_lit24:
+			case DW_OP_lit25:
+			case DW_OP_lit26:
+			case DW_OP_lit27:
+			case DW_OP_lit28:
+			case DW_OP_lit29:
+			case DW_OP_lit30:
+			case DW_OP_lit31:
+				value = opcode - DW_OP_lit0;
+				*(++sp) = value;
+				if (log) fprintf(stderr, "push literal 0x%llX\n", (uint64_t)value);
+				break;
+		
+			case DW_OP_reg0:
+			case DW_OP_reg1:
+			case DW_OP_reg2:
+			case DW_OP_reg3:
+			case DW_OP_reg4:
+			case DW_OP_reg5:
+			case DW_OP_reg6:
+			case DW_OP_reg7:
+			case DW_OP_reg8:
+			case DW_OP_reg9:
+			case DW_OP_reg10:
+			case DW_OP_reg11:
+			case DW_OP_reg12:
+			case DW_OP_reg13:
+			case DW_OP_reg14:
+			case DW_OP_reg15:
+			case DW_OP_reg16:
+			case DW_OP_reg17:
+			case DW_OP_reg18:
+			case DW_OP_reg19:
+			case DW_OP_reg20:
+			case DW_OP_reg21:
+			case DW_OP_reg22:
+			case DW_OP_reg23:
+			case DW_OP_reg24:
+			case DW_OP_reg25:
+			case DW_OP_reg26:
+			case DW_OP_reg27:
+			case DW_OP_reg28:
+			case DW_OP_reg29:
+			case DW_OP_reg30:
+			case DW_OP_reg31:
+				reg = opcode - DW_OP_reg0;
+				*(++sp) = registers.getRegister(reg);
+				if (log) fprintf(stderr, "push reg %d\n", reg);
+				break;
+		
+			case DW_OP_regx:
+				reg = addressSpace.getULEB128(p, expressionEnd);
+				*(++sp) = registers.getRegister(reg);
+				if (log) fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t)svalue);
+				break;			
+
+			case DW_OP_breg0:
+			case DW_OP_breg1:
+			case DW_OP_breg2:
+			case DW_OP_breg3:
+			case DW_OP_breg4:
+			case DW_OP_breg5:
+			case DW_OP_breg6:
+			case DW_OP_breg7:
+			case DW_OP_breg8:
+			case DW_OP_breg9:
+			case DW_OP_breg10:
+			case DW_OP_breg11:
+			case DW_OP_breg12:
+			case DW_OP_breg13:
+			case DW_OP_breg14:
+			case DW_OP_breg15:
+			case DW_OP_breg16:
+			case DW_OP_breg17:
+			case DW_OP_breg18:
+			case DW_OP_breg19:
+			case DW_OP_breg20:
+			case DW_OP_breg21:
+			case DW_OP_breg22:
+			case DW_OP_breg23:
+			case DW_OP_breg24:
+			case DW_OP_breg25:
+			case DW_OP_breg26:
+			case DW_OP_breg27:
+			case DW_OP_breg28:
+			case DW_OP_breg29:
+			case DW_OP_breg30:
+			case DW_OP_breg31:
+				reg = opcode - DW_OP_breg0;
+				svalue = addressSpace.getSLEB128(p, expressionEnd);
+				*(++sp) = registers.getRegister(reg) + svalue;
+				if (log) fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t)svalue);
+				break;
+			
+			case DW_OP_bregx:
+				reg = addressSpace.getULEB128(p, expressionEnd);
+				svalue = addressSpace.getSLEB128(p, expressionEnd);
+				*(++sp) = registers.getRegister(reg) + svalue;
+				if (log) fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t)svalue);
+				break;
+			
+			case DW_OP_fbreg:
+				ABORT("DW_OP_fbreg not implemented");
+				break;
+				
+			case DW_OP_piece:
+				ABORT("DW_OP_piece not implemented");
+				break;
+				
+			case DW_OP_deref_size:
+				// pop stack, dereference, push result
+				value = *sp--;
+				switch ( addressSpace.get8(p++) ) {
+					case 1:
+						value = addressSpace.get8(value);
+						break;
+					case 2:
+						value = addressSpace.get16(value);
+						break;
+					case 4:
+						value = addressSpace.get32(value);
+						break;
+					case 8:
+						value = addressSpace.get64(value);
+						break;
+					default:
+						ABORT("DW_OP_deref_size with bad size");
+				}
+				*(++sp) = value;
+				if (log) fprintf(stderr, "sized dereference 0x%llX\n", (uint64_t)value);
+				break;
+			
+			case DW_OP_xderef_size:
+			case DW_OP_nop:
+			case DW_OP_push_object_addres:
+			case DW_OP_call2:
+			case DW_OP_call4:
+			case DW_OP_call_ref:
+			default:
+				ABORT("dwarf opcode not implemented");
+		}
+	
+	}
+	if (log) fprintf(stderr, "expression evaluates to 0x%llX\n", (uint64_t)*sp);
+	return *sp;
+}
+
+
+
+//
+//	x86_64 specific functions
+//
+
+template <typename A, typename R>
+int DwarfInstructions<A,R>::lastRestoreReg(const Registers_x86_64&) 
+{
+	COMPILE_TIME_ASSERT( (int)CFI_Parser<A>::kMaxRegisterNumber > (int)DW_X86_64_RET_ADDR );
+	return DW_X86_64_RET_ADDR; 
+}
+
+template <typename A, typename R>
+bool DwarfInstructions<A,R>::isReturnAddressRegister(int regNum, const Registers_x86_64&) 
+{
+	return (regNum == DW_X86_64_RET_ADDR); 
+}
+
+template <typename A, typename R>
+typename A::pint_t DwarfInstructions<A,R>::getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, 
+										const Registers_x86_64& registers)
+{
+	if ( prolog.cfaRegister != 0 )
+		return registers.getRegister(prolog.cfaRegister) + prolog.cfaRegisterOffset;
+	else if ( prolog.cfaExpression != 0 )
+		return evaluateExpression(prolog.cfaExpression, addressSpace, registers, 0);
+	else
+		ABORT("getCFA(): unknown location for x86_64 cfa");
+}
+
+
+
+template <typename A, typename R>
+compact_unwind_encoding_t DwarfInstructions<A,R>::encodeToUseDwarf(const Registers_x86_64&) 
+{
+	return UNWIND_X86_64_MODE_DWARF;
+}
+
+template <typename A, typename R>
+compact_unwind_encoding_t DwarfInstructions<A,R>::encodeToUseDwarf(const Registers_x86&) 
+{
+	return UNWIND_X86_MODE_DWARF;
+}
+
+
+
+template <typename A, typename R>
+uint32_t DwarfInstructions<A,R>::getRBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool& failure)
+{
+	if ( (regOffsetFromBaseOffset < 0) || (regOffsetFromBaseOffset > 32) ) {
+		failure = true;
+		return 0;
+	}
+	unsigned int slotIndex = regOffsetFromBaseOffset/8;
+	
+	switch ( reg ) {
+		case UNW_X86_64_RBX:
+			return UNWIND_X86_64_REG_RBX << (slotIndex*3);
+		case UNW_X86_64_R12:
+			return UNWIND_X86_64_REG_R12 << (slotIndex*3);
+		case UNW_X86_64_R13:
+			return UNWIND_X86_64_REG_R13 << (slotIndex*3);
+		case UNW_X86_64_R14:
+			return UNWIND_X86_64_REG_R14 << (slotIndex*3);
+		case UNW_X86_64_R15:
+			return UNWIND_X86_64_REG_R15 << (slotIndex*3);
+	}
+	
+	// invalid register
+	failure = true;
+	return 0;
+}
+
+
+
+template <typename A, typename R>
+compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
+												const Registers_x86_64& r, const typename CFI_Parser<A>::PrologInfo& prolog,
+												char warningBuffer[1024])
+{
+	warningBuffer[0] = '\0';
+	
+	// don't create compact unwind info for unsupported dwarf kinds
+	if ( prolog.registerSavedMoreThanOnce ) {
+		strcpy(warningBuffer, "register saved more than once (might be shrink wrap)");
+		return UNWIND_X86_64_MODE_DWARF;
+	}
+	if ( prolog.cfaOffsetWasNegative ) {
+		strcpy(warningBuffer, "cfa had negative offset (dwarf might contain epilog)");
+		return UNWIND_X86_64_MODE_DWARF;
+	}
+	if ( prolog.spExtraArgSize != 0 ) {
+		strcpy(warningBuffer, "dwarf uses DW_CFA_GNU_args_size");
+		return UNWIND_X86_64_MODE_DWARF;
+	}
+	
+	// figure out which kind of frame this function uses
+	bool standardRBPframe = ( 
+		 (prolog.cfaRegister == UNW_X86_64_RBP) 
+	  && (prolog.cfaRegisterOffset == 16)
+	  && (prolog.savedRegisters[UNW_X86_64_RBP].location == CFI_Parser<A>::kRegisterInCFA)
+	  && (prolog.savedRegisters[UNW_X86_64_RBP].value == -16) );
+	bool standardRSPframe = (prolog.cfaRegister == UNW_X86_64_RSP);
+	if ( !standardRBPframe && !standardRSPframe ) {
+		// no compact encoding for this
+		strcpy(warningBuffer, "does not use RBP or RSP based frame");
+		return UNWIND_X86_64_MODE_DWARF;
+	}
+	
+	// scan which registers are saved
+	int saveRegisterCount = 0;
+	bool rbxSaved = false;
+	bool r12Saved = false;
+	bool r13Saved = false;
+	bool r14Saved = false;
+	bool r15Saved = false;
+	bool rbpSaved = false;
+	for (int i=0; i < 64; ++i) {
+		if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterUnused ) {
+			if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterInCFA ) {
+				sprintf(warningBuffer, "register %d saved somewhere other that in frame", i);
+				return UNWIND_X86_64_MODE_DWARF;
+			}
+			switch (i) {
+				case UNW_X86_64_RBX:
+					rbxSaved = true;
+					++saveRegisterCount;
+					break;
+				case UNW_X86_64_R12:
+					r12Saved = true;
+					++saveRegisterCount;
+					break;
+				case UNW_X86_64_R13:
+					r13Saved = true;
+					++saveRegisterCount;
+					break;
+				case UNW_X86_64_R14:
+					r14Saved = true;
+					++saveRegisterCount;
+					break;
+				case UNW_X86_64_R15:
+					r15Saved = true;
+					++saveRegisterCount;
+					break;
+				case UNW_X86_64_RBP:
+					rbpSaved = true;
+					++saveRegisterCount;
+					break;
+				case DW_X86_64_RET_ADDR:
+					break;
+				default:
+					sprintf(warningBuffer, "non-standard register %d being saved in prolog", i);
+					return UNWIND_X86_64_MODE_DWARF;
+			}
+		}
+	}
+	const int64_t cfaOffsetRBX = prolog.savedRegisters[UNW_X86_64_RBX].value;
+	const int64_t cfaOffsetR12 = prolog.savedRegisters[UNW_X86_64_R12].value;
+	const int64_t cfaOffsetR13 = prolog.savedRegisters[UNW_X86_64_R13].value;
+	const int64_t cfaOffsetR14 = prolog.savedRegisters[UNW_X86_64_R14].value;
+	const int64_t cfaOffsetR15 = prolog.savedRegisters[UNW_X86_64_R15].value;
+	const int64_t cfaOffsetRBP = prolog.savedRegisters[UNW_X86_64_RBP].value;
+	
+	// encode standard RBP frames
+	compact_unwind_encoding_t  encoding = 0;
+	if ( standardRBPframe ) {
+		//		|              |
+		//		+--------------+   <- CFA
+		//		|   ret addr   |
+		//		+--------------+
+		//		|     rbp      |
+		//		+--------------+   <- rbp
+		//		~              ~
+		//		+--------------+   
+		//		|  saved reg3  |
+		//		+--------------+   <- CFA - offset+16
+		//		|  saved reg2  |
+		//		+--------------+   <- CFA - offset+8
+		//		|  saved reg1  |
+		//		+--------------+   <- CFA - offset
+		//		|              |
+		//		+--------------+
+		//		|              |
+		//						   <- rsp
+		//
+		encoding = UNWIND_X86_64_MODE_RBP_FRAME;
+		
+		// find save location of farthest register from rbp
+		int furthestCfaOffset = 0;
+		if ( rbxSaved & (cfaOffsetRBX < furthestCfaOffset) )
+			furthestCfaOffset = cfaOffsetRBX;
+		if ( r12Saved & (cfaOffsetR12 < furthestCfaOffset) )
+			furthestCfaOffset = cfaOffsetR12;
+		if ( r13Saved & (cfaOffsetR13 < furthestCfaOffset) )
+			furthestCfaOffset = cfaOffsetR13;
+		if ( r14Saved & (cfaOffsetR14 < furthestCfaOffset) )
+			furthestCfaOffset = cfaOffsetR14;
+		if ( r15Saved & (cfaOffsetR15 < furthestCfaOffset) )
+			furthestCfaOffset = cfaOffsetR15;
+		
+		if ( furthestCfaOffset == 0 ) {
+			// no registers saved, nothing more to encode
+			return encoding;
+		}
+		
+		// add stack offset to encoding
+		int rbpOffset = furthestCfaOffset + 16;
+		int encodedOffset = rbpOffset/(-8);
+		if ( encodedOffset > 255 ) {
+			strcpy(warningBuffer, "offset of saved registers too far to encode");
+			return UNWIND_X86_64_MODE_DWARF;
+		}
+		encoding |= (encodedOffset << __builtin_ctz(UNWIND_X86_64_RBP_FRAME_OFFSET));
+		
+		// add register saved from each stack location
+		bool encodingFailure = false;
+		if ( rbxSaved )
+			encoding |= getRBPEncodedRegister(UNW_X86_64_RBX, cfaOffsetRBX - furthestCfaOffset, encodingFailure);
+		if ( r12Saved )
+			encoding |= getRBPEncodedRegister(UNW_X86_64_R12, cfaOffsetR12 - furthestCfaOffset, encodingFailure);
+		if ( r13Saved )
+			encoding |= getRBPEncodedRegister(UNW_X86_64_R13, cfaOffsetR13 - furthestCfaOffset, encodingFailure);
+		if ( r14Saved )
+			encoding |= getRBPEncodedRegister(UNW_X86_64_R14, cfaOffsetR14 - furthestCfaOffset, encodingFailure);
+		if ( r15Saved )
+			encoding |= getRBPEncodedRegister(UNW_X86_64_R15, cfaOffsetR15 - furthestCfaOffset, encodingFailure);
+		
+		if ( encodingFailure ){
+			strcpy(warningBuffer, "saved registers not contiguous");
+			return UNWIND_X86_64_MODE_DWARF;
+		}
+
+		return encoding;
+	}
+	else {
+		//		|              |
+		//		+--------------+   <- CFA
+		//		|   ret addr   |
+		//		+--------------+
+		//		|  saved reg1  |
+		//		+--------------+   <- CFA - 16
+		//		|  saved reg2  |
+		//		+--------------+   <- CFA - 24
+		//		|  saved reg3  |
+		//		+--------------+   <- CFA - 32
+		//		|  saved reg4  |
+		//		+--------------+   <- CFA - 40
+		//		|  saved reg5  |
+		//		+--------------+   <- CFA - 48
+		//		|  saved reg6  |
+		//		+--------------+   <- CFA - 56
+		//		|              |
+		//						   <- esp
+		//
+
+		// for RSP based frames we need to encode stack size in unwind info
+		encoding = UNWIND_X86_64_MODE_STACK_IMMD;
+		uint64_t stackValue = prolog.cfaRegisterOffset / 8;
+		uint32_t stackAdjust = 0;
+		bool immedStackSize = true;
+		const uint32_t stackMaxImmedValue = EXTRACT_BITS(0xFFFFFFFF,UNWIND_X86_64_FRAMELESS_STACK_SIZE);
+		if ( stackValue > stackMaxImmedValue ) {
+			// stack size is too big to fit as an immediate value, so encode offset of subq instruction in function
+			pint_t functionContentAdjustStackIns = funcAddr + prolog.codeOffsetAtStackDecrement - 4;		
+			uint32_t stackDecrementInCode = addressSpace.get32(functionContentAdjustStackIns);
+			stackAdjust = (prolog.cfaRegisterOffset - stackDecrementInCode)/8;
+			stackValue = functionContentAdjustStackIns - funcAddr;
+			immedStackSize = false;
+			if ( stackAdjust > 7 ) {
+				strcpy(warningBuffer, "stack subq instruction is too different from dwarf stack size");
+				return UNWIND_X86_64_MODE_DWARF;
+			}
+			encoding = UNWIND_X86_64_MODE_STACK_IND;
+		}	
+		
+		
+		// validate that saved registers are all within 6 slots abutting return address
+		int registers[6];
+		for (int i=0; i < 6;++i)
+			registers[i] = 0;
+		if ( r15Saved ) {
+			if ( cfaOffsetR15 < -56 ) {
+				strcpy(warningBuffer, "r15 is saved too far from return address");
+				return UNWIND_X86_64_MODE_DWARF;
+			}
+			registers[(cfaOffsetR15+56)/8] = UNWIND_X86_64_REG_R15;
+		}
+		if ( r14Saved ) {
+			if ( cfaOffsetR14 < -56 ) {
+				strcpy(warningBuffer, "r14 is saved too far from return address");
+				return UNWIND_X86_64_MODE_DWARF;
+			}
+			registers[(cfaOffsetR14+56)/8] = UNWIND_X86_64_REG_R14;
+		}
+		if ( r13Saved ) {
+			if ( cfaOffsetR13 < -56 ) {
+				strcpy(warningBuffer, "r13 is saved too far from return address");
+				return UNWIND_X86_64_MODE_DWARF;
+			}
+			registers[(cfaOffsetR13+56)/8] = UNWIND_X86_64_REG_R13;
+		}
+		if ( r12Saved ) {
+			if ( cfaOffsetR12 < -56 ) {
+				strcpy(warningBuffer, "r12 is saved too far from return address");
+				return UNWIND_X86_64_MODE_DWARF;
+			}
+			registers[(cfaOffsetR12+56)/8] = UNWIND_X86_64_REG_R12;
+		}
+		if ( rbxSaved ) {
+			if ( cfaOffsetRBX < -56 ) {
+				strcpy(warningBuffer, "rbx is saved too far from return address");
+				return UNWIND_X86_64_MODE_DWARF;
+			}
+			registers[(cfaOffsetRBX+56)/8] = UNWIND_X86_64_REG_RBX;
+		}
+		if ( rbpSaved ) {
+			if ( cfaOffsetRBP < -56 ) {
+				strcpy(warningBuffer, "rbp is saved too far from return address");
+				return UNWIND_X86_64_MODE_DWARF;
+			}
+			registers[(cfaOffsetRBP+56)/8] = UNWIND_X86_64_REG_RBP;
+		}
+		
+		// validate that saved registers are contiguous and abut return address on stack
+		for (int i=0; i < saveRegisterCount; ++i) {
+			if ( registers[5-i] == 0 ) {
+				strcpy(warningBuffer, "registers not save contiguously in stack");
+				return UNWIND_X86_64_MODE_DWARF;
+			}
+		}
+				
+		// encode register permutation
+		// the 10-bits are encoded differently depending on the number of registers saved
+		int renumregs[6];
+		for (int i=6-saveRegisterCount; i < 6; ++i) {
+			int countless = 0;
+			for (int j=6-saveRegisterCount; j < i; ++j) {
+				if ( registers[j] < registers[i] )
+					++countless;
+			}
+			renumregs[i] = registers[i] - countless -1;
+		}
+		uint32_t permutationEncoding = 0;
+		switch ( saveRegisterCount ) {
+			case 6:
+				permutationEncoding |= (120*renumregs[0] + 24*renumregs[1] + 6*renumregs[2] + 2*renumregs[3] + renumregs[4]);
+				break;
+			case 5:
+				permutationEncoding |= (120*renumregs[1] + 24*renumregs[2] + 6*renumregs[3] + 2*renumregs[4] + renumregs[5]);
+				break;
+			case 4:
+				permutationEncoding |= (60*renumregs[2] + 12*renumregs[3] + 3*renumregs[4] + renumregs[5]);
+				break;
+			case 3:
+				permutationEncoding |= (20*renumregs[3] + 4*renumregs[4] + renumregs[5]);
+				break;
+			case 2:
+				permutationEncoding |= (5*renumregs[4] + renumregs[5]);
+				break;
+			case 1:
+				permutationEncoding |= (renumregs[5]);
+				break;
+		}
+		
+		encoding |= (stackValue << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_SIZE));
+		encoding |= (stackAdjust << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_ADJUST));
+		encoding |= (saveRegisterCount << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT));
+		encoding |= (permutationEncoding << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION));
+		return encoding;
+	}
+}
+
+
+
+
+//
+//	x86 specific functions
+//
+template <typename A, typename R>
+int DwarfInstructions<A,R>::lastRestoreReg(const Registers_x86&) 
+{
+	COMPILE_TIME_ASSERT( (int)CFI_Parser<A>::kMaxRegisterNumber > (int)DW_X86_RET_ADDR );
+	return DW_X86_RET_ADDR; 
+}
+
+template <typename A, typename R>
+bool DwarfInstructions<A,R>::isReturnAddressRegister(int regNum, const Registers_x86&) 
+{
+	return (regNum == DW_X86_RET_ADDR); 
+}
+
+template <typename A, typename R>
+typename A::pint_t DwarfInstructions<A,R>::getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, 
+										const Registers_x86& registers)
+{
+	if ( prolog.cfaRegister != 0 )
+		return registers.getRegister(prolog.cfaRegister) + prolog.cfaRegisterOffset;
+	else if ( prolog.cfaExpression != 0 )
+		return evaluateExpression(prolog.cfaExpression, addressSpace, registers, 0);
+	else
+		ABORT("getCFA(): unknown location for x86 cfa");
+}
+
+
+
+
+
+template <typename A, typename R>
+uint32_t DwarfInstructions<A,R>::getEBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool& failure)
+{
+	if ( (regOffsetFromBaseOffset < 0) || (regOffsetFromBaseOffset > 16) ) {
+		failure = true;
+		return 0;
+	}
+	unsigned int slotIndex = regOffsetFromBaseOffset/4;
+	
+	switch ( reg ) {
+		case UNW_X86_EBX:
+			return UNWIND_X86_REG_EBX << (slotIndex*3);
+		case UNW_X86_ECX:
+			return UNWIND_X86_REG_ECX << (slotIndex*3);
+		case UNW_X86_EDX:
+			return UNWIND_X86_REG_EDX << (slotIndex*3);
+		case UNW_X86_EDI:
+			return UNWIND_X86_REG_EDI << (slotIndex*3);
+		case UNW_X86_ESI:
+			return UNWIND_X86_REG_ESI << (slotIndex*3);
+	}
+	
+	// invalid register
+	failure = true;
+	return 0;
+}
+
+template <typename A, typename R>
+compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
+												const Registers_x86& r, const typename CFI_Parser<A>::PrologInfo& prolog,
+												char warningBuffer[1024])
+{
+	warningBuffer[0] = '\0';
+	
+	// don't create compact unwind info for unsupported dwarf kinds
+	if ( prolog.registerSavedMoreThanOnce ) {
+		strcpy(warningBuffer, "register saved more than once (might be shrink wrap)");
+		return UNWIND_X86_MODE_DWARF;
+	}
+	if ( prolog.spExtraArgSize != 0 ) {
+		strcpy(warningBuffer, "dwarf uses DW_CFA_GNU_args_size");
+		return UNWIND_X86_MODE_DWARF;
+	}
+	
+	// figure out which kind of frame this function uses
+	bool standardEBPframe = ( 
+		 (prolog.cfaRegister == UNW_X86_EBP) 
+	  && (prolog.cfaRegisterOffset == 8)
+	  && (prolog.savedRegisters[UNW_X86_EBP].location == CFI_Parser<A>::kRegisterInCFA)
+	  && (prolog.savedRegisters[UNW_X86_EBP].value == -8) );
+	bool standardESPframe = (prolog.cfaRegister == UNW_X86_ESP);
+	if ( !standardEBPframe && !standardESPframe ) {
+		// no compact encoding for this
+		strcpy(warningBuffer, "does not use EBP or ESP based frame");
+		return UNWIND_X86_MODE_DWARF;
+	}
+	
+	// scan which registers are saved
+	int saveRegisterCount = 0;
+	bool ebxSaved = false;
+	bool ecxSaved = false;
+	bool edxSaved = false;
+	bool esiSaved = false;
+	bool ediSaved = false;
+	bool ebpSaved = false;
+	for (int i=0; i < 64; ++i) {
+		if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterUnused ) {
+			if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterInCFA ) {
+				sprintf(warningBuffer, "register %d saved somewhere other that in frame", i);
+				return UNWIND_X86_MODE_DWARF;
+			}
+			switch (i) {
+				case UNW_X86_EBX:
+					ebxSaved = true;
+					++saveRegisterCount;
+					break;
+				case UNW_X86_ECX:
+					ecxSaved = true;
+					++saveRegisterCount;
+					break;
+				case UNW_X86_EDX:
+					edxSaved = true;
+					++saveRegisterCount;
+					break;
+				case UNW_X86_ESI:
+					esiSaved = true;
+					++saveRegisterCount;
+					break;
+				case UNW_X86_EDI:
+					ediSaved = true;
+					++saveRegisterCount;
+					break;
+				case UNW_X86_EBP:
+					ebpSaved = true;
+					++saveRegisterCount;
+					break;
+				case DW_X86_RET_ADDR:
+					break;
+				default:
+					sprintf(warningBuffer, "non-standard register %d being saved in prolog", i);
+					return UNWIND_X86_MODE_DWARF;
+			}
+		}
+	}
+	const int32_t cfaOffsetEBX = prolog.savedRegisters[UNW_X86_EBX].value;
+	const int32_t cfaOffsetECX = prolog.savedRegisters[UNW_X86_ECX].value;
+	const int32_t cfaOffsetEDX = prolog.savedRegisters[UNW_X86_EDX].value;
+	const int32_t cfaOffsetEDI = prolog.savedRegisters[UNW_X86_EDI].value;
+	const int32_t cfaOffsetESI = prolog.savedRegisters[UNW_X86_ESI].value;
+	const int32_t cfaOffsetEBP = prolog.savedRegisters[UNW_X86_EBP].value;
+	
+	// encode standard RBP frames
+	compact_unwind_encoding_t  encoding = 0;
+	if ( standardEBPframe ) {
+		//		|              |
+		//		+--------------+   <- CFA
+		//		|   ret addr   |
+		//		+--------------+
+		//		|     ebp      |
+		//		+--------------+   <- ebp
+		//		~              ~
+		//		+--------------+   
+		//		|  saved reg3  |
+		//		+--------------+   <- CFA - offset+8
+		//		|  saved reg2  |
+		//		+--------------+   <- CFA - offset+e
+		//		|  saved reg1  |
+		//		+--------------+   <- CFA - offset
+		//		|              |
+		//		+--------------+
+		//		|              |
+		//						   <- esp
+		//
+		encoding = UNWIND_X86_MODE_EBP_FRAME;
+		
+		// find save location of farthest register from ebp
+		int furthestCfaOffset = 0;
+		if ( ebxSaved & (cfaOffsetEBX < furthestCfaOffset) )
+			furthestCfaOffset = cfaOffsetEBX;
+		if ( ecxSaved & (cfaOffsetECX < furthestCfaOffset) )
+			furthestCfaOffset = cfaOffsetECX;
+		if ( edxSaved & (cfaOffsetEDX < furthestCfaOffset) )
+			furthestCfaOffset = cfaOffsetEDX;
+		if ( ediSaved & (cfaOffsetEDI < furthestCfaOffset) )
+			furthestCfaOffset = cfaOffsetEDI;
+		if ( esiSaved & (cfaOffsetESI < furthestCfaOffset) )
+			furthestCfaOffset = cfaOffsetESI;
+		
+		if ( furthestCfaOffset == 0 ) {
+			// no registers saved, nothing more to encode
+			return encoding;
+		}
+		
+		// add stack offset to encoding
+		int ebpOffset = furthestCfaOffset + 8;
+		int encodedOffset = ebpOffset/(-4);
+		if ( encodedOffset > 255 ) {
+			strcpy(warningBuffer, "offset of saved registers too far to encode");
+			return UNWIND_X86_MODE_DWARF;
+		}
+		encoding |= (encodedOffset << __builtin_ctz(UNWIND_X86_EBP_FRAME_OFFSET));
+		
+		// add register saved from each stack location
+		bool encodingFailure = false;
+		if ( ebxSaved )
+			encoding |= getEBPEncodedRegister(UNW_X86_EBX, cfaOffsetEBX - furthestCfaOffset, encodingFailure);
+		if ( ecxSaved )
+			encoding |= getEBPEncodedRegister(UNW_X86_ECX, cfaOffsetECX - furthestCfaOffset, encodingFailure);
+		if ( edxSaved )
+			encoding |= getEBPEncodedRegister(UNW_X86_EDX, cfaOffsetEDX - furthestCfaOffset, encodingFailure);
+		if ( ediSaved )
+			encoding |= getEBPEncodedRegister(UNW_X86_EDI, cfaOffsetEDI - furthestCfaOffset, encodingFailure);
+		if ( esiSaved )
+			encoding |= getEBPEncodedRegister(UNW_X86_ESI, cfaOffsetESI - furthestCfaOffset, encodingFailure);
+		
+		if ( encodingFailure ){
+			strcpy(warningBuffer, "saved registers not contiguous");
+			return UNWIND_X86_MODE_DWARF;
+		}
+
+		return encoding;
+	}
+	else {
+		//		|              |
+		//		+--------------+   <- CFA
+		//		|   ret addr   |
+		//		+--------------+
+		//		|  saved reg1  |
+		//		+--------------+   <- CFA - 8
+		//		|  saved reg2  |
+		//		+--------------+   <- CFA - 12
+		//		|  saved reg3  |
+		//		+--------------+   <- CFA - 16
+		//		|  saved reg4  |
+		//		+--------------+   <- CFA - 20
+		//		|  saved reg5  |
+		//		+--------------+   <- CFA - 24
+		//		|  saved reg6  |
+		//		+--------------+   <- CFA - 28
+		//		|              |
+		//						   <- esp
+		//
+
+		// for ESP based frames we need to encode stack size in unwind info
+		encoding = UNWIND_X86_MODE_STACK_IMMD;
+		uint64_t stackValue = prolog.cfaRegisterOffset / 4;
+		uint32_t stackAdjust = 0;
+		bool immedStackSize = true;
+		const uint32_t stackMaxImmedValue = EXTRACT_BITS(0xFFFFFFFF,UNWIND_X86_FRAMELESS_STACK_SIZE);
+		if ( stackValue > stackMaxImmedValue ) {
+			// stack size is too big to fit as an immediate value, so encode offset of subq instruction in function
+			pint_t functionContentAdjustStackIns = funcAddr + prolog.codeOffsetAtStackDecrement - 4;		
+			uint32_t stackDecrementInCode = addressSpace.get32(functionContentAdjustStackIns);
+			stackAdjust = (prolog.cfaRegisterOffset - stackDecrementInCode)/4;
+			stackValue = functionContentAdjustStackIns - funcAddr;
+			immedStackSize = false;
+			if ( stackAdjust > 7 ) {
+				strcpy(warningBuffer, "stack subq instruction is too different from dwarf stack size");
+				return UNWIND_X86_MODE_DWARF;
+			}
+			encoding = UNWIND_X86_MODE_STACK_IND;
+		}	
+		
+		
+		// validate that saved registers are all within 6 slots abutting return address
+		int registers[6];
+		for (int i=0; i < 6;++i)
+			registers[i] = 0;
+		if ( ebxSaved ) {
+			if ( cfaOffsetEBX < -28 ) {
+				strcpy(warningBuffer, "ebx is saved too far from return address");
+				return UNWIND_X86_MODE_DWARF;
+			}
+			registers[(cfaOffsetEBX+28)/4] = UNWIND_X86_REG_EBX;
+		}
+		if ( ecxSaved ) {
+			if ( cfaOffsetECX < -28 ) {
+				strcpy(warningBuffer, "ecx is saved too far from return address");
+				return UNWIND_X86_MODE_DWARF;
+			}
+			registers[(cfaOffsetECX+28)/4] = UNWIND_X86_REG_ECX;
+		}
+		if ( edxSaved ) {
+			if ( cfaOffsetEDX < -28 ) {
+				strcpy(warningBuffer, "edx is saved too far from return address");
+				return UNWIND_X86_MODE_DWARF;
+			}
+			registers[(cfaOffsetEDX+28)/4] = UNWIND_X86_REG_EDX;
+		}
+		if ( ediSaved ) {
+			if ( cfaOffsetEDI < -28 ) {
+				strcpy(warningBuffer, "edi is saved too far from return address");
+				return UNWIND_X86_MODE_DWARF;
+			}
+			registers[(cfaOffsetEDI+28)/4] = UNWIND_X86_REG_EDI;
+		}
+		if ( esiSaved ) {
+			if ( cfaOffsetESI < -28 ) {
+				strcpy(warningBuffer, "esi is saved too far from return address");
+				return UNWIND_X86_MODE_DWARF;
+			}
+			registers[(cfaOffsetESI+28)/4] = UNWIND_X86_REG_ESI;
+		}
+		if ( ebpSaved ) {
+			if ( cfaOffsetEBP < -28 ) {
+				strcpy(warningBuffer, "ebp is saved too far from return address");
+				return UNWIND_X86_MODE_DWARF;
+			}
+			registers[(cfaOffsetEBP+28)/4] = UNWIND_X86_REG_EBP;
+		}
+		
+		// validate that saved registers are contiguous and abut return address on stack
+		for (int i=0; i < saveRegisterCount; ++i) {
+			if ( registers[5-i] == 0 ) {
+				strcpy(warningBuffer, "registers not save contiguously in stack");
+				return UNWIND_X86_MODE_DWARF;
+			}
+		}
+				
+		// encode register permutation
+		// the 10-bits are encoded differently depending on the number of registers saved
+		int renumregs[6];
+		for (int i=6-saveRegisterCount; i < 6; ++i) {
+			int countless = 0;
+			for (int j=6-saveRegisterCount; j < i; ++j) {
+				if ( registers[j] < registers[i] )
+					++countless;
+			}
+			renumregs[i] = registers[i] - countless -1;
+		}
+		uint32_t permutationEncoding = 0;
+		switch ( saveRegisterCount ) {
+			case 6:
+				permutationEncoding |= (120*renumregs[0] + 24*renumregs[1] + 6*renumregs[2] + 2*renumregs[3] + renumregs[4]);
+				break;
+			case 5:
+				permutationEncoding |= (120*renumregs[1] + 24*renumregs[2] + 6*renumregs[3] + 2*renumregs[4] + renumregs[5]);
+				break;
+			case 4:
+				permutationEncoding |= (60*renumregs[2] + 12*renumregs[3] + 3*renumregs[4] + renumregs[5]);
+				break;
+			case 3:
+				permutationEncoding |= (20*renumregs[3] + 4*renumregs[4] + renumregs[5]);
+				break;
+			case 2:
+				permutationEncoding |= (5*renumregs[4] + renumregs[5]);
+				break;
+			case 1:
+				permutationEncoding |= (renumregs[5]);
+				break;
+		}
+		
+		encoding |= (stackValue << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_SIZE));
+		encoding |= (stackAdjust << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_ADJUST));
+		encoding |= (saveRegisterCount << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_REG_COUNT));
+		encoding |= (permutationEncoding << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION));
+		return encoding;
+	}
+}
+
+
+
+
+
+
+
+//
+//	ppc specific functions
+//
+template <typename A, typename R>
+int DwarfInstructions<A,R>::lastRestoreReg(const Registers_ppc&) 
+{
+	COMPILE_TIME_ASSERT( (int)CFI_Parser<A>::kMaxRegisterNumber > (int)UNW_PPC_SPEFSCR );
+	return UNW_PPC_SPEFSCR; 
+}
+
+template <typename A, typename R>
+bool DwarfInstructions<A,R>::isReturnAddressRegister(int regNum, const Registers_ppc&) 
+{
+	return (regNum == UNW_PPC_LR); 
+}
+
+template <typename A, typename R>
+typename A::pint_t DwarfInstructions<A,R>::getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, 
+										const Registers_ppc& registers)
+{	
+	if ( prolog.cfaRegister != 0 )
+		return registers.getRegister(prolog.cfaRegister) + prolog.cfaRegisterOffset;
+	else if ( prolog.cfaExpression != 0 )
+		return evaluateExpression(prolog.cfaExpression, addressSpace, registers, 0);
+	else
+		ABORT("getCFA(): unknown location for ppc cfa");
+}
+
+
+template <typename A, typename R>
+compact_unwind_encoding_t DwarfInstructions<A,R>::encodeToUseDwarf(const Registers_ppc&) 
+{
+	return UNWIND_X86_MODE_DWARF;
+}
+
+
+template <typename A, typename R>
+compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
+												const Registers_ppc& r, const typename CFI_Parser<A>::PrologInfo& prolog,
+												char warningBuffer[1024])
+{
+	warningBuffer[0] = '\0';
+	return UNWIND_X86_MODE_DWARF;
+}
+
+
+
+
+} // namespace lldb_private
+
+
+#endif // __DWARF_INSTRUCTIONS_HPP__
+
+
+
+
diff --git a/source/Plugins/Process/Utility/libunwind/src/DwarfParser.hpp b/source/Plugins/Process/Utility/libunwind/src/DwarfParser.hpp
new file mode 100644
index 0000000..b11cb8c
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/DwarfParser.hpp
@@ -0,0 +1,869 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- DwarfParser.hpp -----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+ 
+//
+// processor specific parsing of dwarf unwind instructions
+//
+
+#ifndef __DWARF_PARSER_HPP__
+#define __DWARF_PARSER_HPP__
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <vector>
+
+#include "libunwind.h"
+#include "dwarf2.h"
+
+#include "AddressSpace.hpp"
+#include "RemoteUnwindProfile.h"
+
+namespace lldb_private {
+
+
+///
+/// CFI_Parser does basic parsing of a CFI (Call Frame Information) records.
+/// See Dwarf Spec for details: 
+///    http://www.linux-foundation.org/spec/booksets/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
+///
+template <typename A>
+class CFI_Parser
+{
+public:
+	typedef typename A::pint_t		pint_t;	
+
+	///
+	/// Information encoded in a CIE (Common Information Entry)
+	///  
+	struct CIE_Info {
+		pint_t		cieStart;
+		pint_t		cieLength;
+		pint_t		cieInstructions;
+		uint8_t		pointerEncoding;
+		uint8_t		lsdaEncoding;
+		uint8_t		personalityEncoding;
+		uint8_t		personalityOffsetInCIE;
+		pint_t		personality;
+		int			codeAlignFactor;
+		int			dataAlignFactor;
+		bool		isSignalFrame;
+		bool		fdesHaveAugmentationData;
+	};
+	
+	///
+	/// Information about an FDE (Frame Description Entry)
+	///  
+	struct FDE_Info {
+		pint_t		fdeStart;
+		pint_t		fdeLength;
+		pint_t		fdeInstructions;
+		pint_t		pcStart;
+		pint_t		pcEnd;
+		pint_t		lsda;
+	};
+
+	///
+	/// Used by linker when parsing __eh_frame section
+	///  
+	struct FDE_Reference {
+		pint_t		address;
+		uint32_t	offsetInFDE;
+		uint8_t		encodingOfAddress;
+	};
+	struct FDE_Atom_Info {
+		pint_t			fdeAddress;
+		FDE_Reference	function;
+		FDE_Reference	cie;
+		FDE_Reference	lsda;
+	};
+	struct CIE_Atom_Info {
+		pint_t			cieAddress;
+		FDE_Reference	personality;
+	};
+	
+	
+	///
+	/// Information about a frame layout and registers saved determined 
+	/// by "running" the dwarf FDE "instructions"
+	///  
+	enum { kMaxRegisterNumber = 120 };
+	enum RegisterSavedWhere { kRegisterUnused, kRegisterInCFA, kRegisterOffsetFromCFA,
+							kRegisterInRegister, kRegisterAtExpression, kRegisterIsExpression } ;
+	struct RegisterLocation {
+		RegisterSavedWhere	location;
+		int64_t				value;
+	};
+	struct PrologInfo {
+		uint32_t			cfaRegister;		
+		int32_t				cfaRegisterOffset;	// CFA = (cfaRegister)+cfaRegisterOffset
+		int64_t				cfaExpression;		// CFA = expression
+		bool				registersInOtherRegisters;
+		bool				registerSavedMoreThanOnce;
+		bool				cfaOffsetWasNegative;
+		uint32_t			spExtraArgSize;
+		uint32_t			codeOffsetAtStackDecrement;
+		
+		RegisterLocation	savedRegisters[kMaxRegisterNumber];	// from where to restore registers
+	};
+
+	struct PrologInfoStackEntry {
+								PrologInfoStackEntry(PrologInfoStackEntry* n, const PrologInfo& i)
+									: next(n), info(i) {}
+		PrologInfoStackEntry*	next;
+		PrologInfo				info;
+	};
+
+	static bool findFDE(A& addressSpace, pint_t pc, pint_t ehSectionStart, uint32_t sectionLength, pint_t fdeHint, FDE_Info* fdeInfo, CIE_Info* cieInfo);
+
+#if defined (SUPPORT_REMOTE_UNWINDING)
+    static bool functionFuncBoundsViaFDE(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength, std::vector<FuncBounds> &funcbounds);
+#endif
+
+	static const char* decodeFDE(A& addressSpace, pint_t fdeStart, FDE_Info* fdeInfo, CIE_Info* cieInfo);
+	static bool parseFDEInstructions(A& addressSpace, const FDE_Info& fdeInfo, const CIE_Info& cieInfo, pint_t upToPC, PrologInfo* results);
+	static const char* getCFIs(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength, 
+								std::vector<FDE_Atom_Info>& fdes, std::vector<CIE_Atom_Info>& cies);
+	static uint32_t getCFICount(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength);
+
+	static const char* parseCIE(A& addressSpace, pint_t cie, CIE_Info* cieInfo);
+
+private:
+	static bool parseInstructions(A& addressSpace, pint_t instructions, pint_t instructionsEnd, const CIE_Info& cieInfo, 
+								pint_t pcoffset, PrologInfoStackEntry*& rememberStack, PrologInfo* results);
+
+};
+
+
+///
+/// Parse a FDE into a CIE_Info and an FDE_Info 
+///  
+template <typename A>
+const char* CFI_Parser<A>::decodeFDE(A& addressSpace, pint_t fdeStart, FDE_Info* fdeInfo, CIE_Info* cieInfo)
+{
+	pint_t p = fdeStart;
+	uint64_t cfiLength = addressSpace.get32(p);
+	p += 4;
+	if ( cfiLength == 0xffffffff ) {
+		// 0xffffffff means length is really next 8 bytes
+		cfiLength = addressSpace.get64(p);
+		p += 8;
+	}
+	if ( cfiLength == 0 ) 
+		return "FDE has zero length";	// end marker
+	uint32_t ciePointer = addressSpace.get32(p);
+	if ( ciePointer == 0 ) 
+		return "FDE is really a CIE";	// this is a CIE not an FDE
+	pint_t nextCFI = p + cfiLength;
+	pint_t cieStart = p-ciePointer;
+	const char* err = parseCIE(addressSpace, cieStart, cieInfo);
+	if (err != NULL)
+		return err;
+	p += 4;
+	// parse pc begin and range
+	pint_t pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
+	pint_t pcRange = addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F);
+	// parse rest of info
+	fdeInfo->lsda = 0;
+	// check for augmentation length
+	if ( cieInfo->fdesHaveAugmentationData ) {
+		uintptr_t augLen = addressSpace.getULEB128(p, nextCFI);
+		pint_t endOfAug = p + augLen;
+		if ( cieInfo->lsdaEncoding != 0 ) {
+			// peek at value (without indirection).  Zero means no lsda
+			pint_t lsdaStart = p;
+			if ( addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0 ) {
+				// reset pointer and re-parse lsda address
+				p = lsdaStart;
+				fdeInfo->lsda = addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
+			}
+		}
+		p = endOfAug;
+	}
+	fdeInfo->fdeStart = fdeStart;
+	fdeInfo->fdeLength = nextCFI - fdeStart;
+	fdeInfo->fdeInstructions = p;
+	fdeInfo->pcStart = pcStart;
+	fdeInfo->pcEnd = pcStart+pcRange;
+	return NULL; // success
+}
+
+
+///
+/// Scan an eh_frame section to find an FDE for a pc
+///  
+template <typename A>
+bool CFI_Parser<A>::findFDE(A& addressSpace, pint_t pc, pint_t ehSectionStart, uint32_t sectionLength, pint_t fdeHint, FDE_Info* fdeInfo, CIE_Info* cieInfo)
+{
+	//fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc);
+	pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart;
+	const pint_t ehSectionEnd = p + sectionLength;
+	while ( p < ehSectionEnd ) {
+		pint_t currentCFI = p;
+		//fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p);
+		uint64_t cfiLength = addressSpace.get32(p);
+		p += 4;
+		if ( cfiLength == 0xffffffff ) {
+			// 0xffffffff means length is really next 8 bytes
+			cfiLength = addressSpace.get64(p);
+			p += 8;
+		}
+		if ( cfiLength == 0 ) 
+			return false;	// end marker
+		uint32_t id = addressSpace.get32(p);
+		if ( id == 0 ) {
+			// skip over CIEs
+			p += cfiLength;
+		}
+		else {
+			// process FDE to see if it covers pc
+			pint_t nextCFI = p + cfiLength;
+			uint32_t ciePointer = addressSpace.get32(p);
+			pint_t cieStart = p-ciePointer;
+			// validate pointer to CIE is within section
+			if ( (ehSectionStart <= cieStart) && (cieStart < ehSectionEnd) ) {
+				if ( parseCIE(addressSpace, cieStart, cieInfo) == NULL ) {
+					p += 4;
+					// parse pc begin and range
+					pint_t pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
+					pint_t pcRange = addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F);
+					//fprintf(stderr, "FDE with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pcStart, (uint64_t)(pcStart+pcRange));
+					// test if pc is within the function this FDE covers
+					if ( (pcStart < pc) && (pc <= pcStart+pcRange) ) {
+						// parse rest of info
+						fdeInfo->lsda = 0;
+						// check for augmentation length
+						if ( cieInfo->fdesHaveAugmentationData ) {
+							uintptr_t augLen = addressSpace.getULEB128(p, nextCFI);
+							pint_t endOfAug = p + augLen;
+							if ( cieInfo->lsdaEncoding != 0 ) {
+								// peek at value (without indirection).  Zero means no lsda
+								pint_t lsdaStart = p;
+								if ( addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0 ) {
+									// reset pointer and re-parse lsda address
+									p = lsdaStart;
+									fdeInfo->lsda = addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
+								}
+							}
+							p = endOfAug;
+						}
+						fdeInfo->fdeStart = currentCFI;
+						fdeInfo->fdeLength = nextCFI - currentCFI;
+						fdeInfo->fdeInstructions = p;
+						fdeInfo->pcStart = pcStart;
+						fdeInfo->pcEnd = pcStart+pcRange;
+						//fprintf(stderr, "findFDE(pc=0x%llX) found with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pc, (uint64_t)pcStart, (uint64_t)(pcStart+pcRange));
+						return true;
+					}
+					else {
+						//fprintf(stderr, "findFDE(pc=0x%llX) not found with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pc, (uint64_t)pcStart, (uint64_t)(pcStart+pcRange));
+						// pc is not in begin/range, skip this FDE
+					}
+				}
+				else {
+					// malformed CIE, now augmentation describing pc range encoding
+					//fprintf(stderr, "malformed CIE\n");
+				}
+			}
+			else {
+				// malformed FDE.  CIE is bad
+				//fprintf(stderr, "malformed FDE, cieStart=0x%llX, ehSectionStart=0x%llX, ehSectionEnd=0x%llX\n",
+				//	(uint64_t)cieStart, (uint64_t)ehSectionStart, (uint64_t)ehSectionEnd);
+			}
+			p = nextCFI;
+		}
+	}
+	//fprintf(stderr, "findFDE(pc=0x%llX) not found\n",(uint64_t)pc);
+	return false;
+}
+
+#if defined (SUPPORT_REMOTE_UNWINDING)
+/// Scan an eh_frame section to find all the function start addresses 
+/// This is only made for working with libunwind-remote.  It copies
+/// the eh_frame section into local memory and steps through it quickly
+/// to find the start addresses of the CFIs.
+///  
+template <typename A>
+bool CFI_Parser<A>::functionFuncBoundsViaFDE(A& addressSpace, pint_t ehSectionStart, 
+					     uint32_t sectionLength, std::vector<FuncBounds> &funcbounds)
+{
+	//fprintf(stderr, "functionFuncBoundsViaFDE(0x%llX)\n", (long long)pc);
+	pint_t p = ehSectionStart;
+	const pint_t ehSectionEnd = p + sectionLength;
+    pint_t lastCieSeen = (pint_t) -1;
+    CIE_Info cieInfo;
+	while ( p < ehSectionEnd ) {
+		//fprintf(stderr, "functionFuncBoundsViaFDE() CFI at 0x%llX\n", (long long)p);
+		uint64_t cfiLength = addressSpace.get32(p);
+		p += 4;
+		if ( cfiLength == 0xffffffff ) {
+			// 0xffffffff means length is really next 8 bytes
+			cfiLength = addressSpace.get64(p);
+			p += 8;
+		}
+		if ( cfiLength == 0 ) 
+			return false;	// end marker
+		uint32_t id = addressSpace.get32(p);
+		if ( id == 0 ) {
+			// skip over CIEs
+			p += cfiLength;
+		}
+		else {
+			// process FDE to see if it covers pc
+			pint_t nextCFI = p + cfiLength;
+			uint32_t ciePointer = addressSpace.get32(p);
+			pint_t cieStart = p-ciePointer;
+			// validate pointer to CIE is within section
+			if ( (ehSectionStart <= cieStart) && (cieStart < ehSectionEnd) ) {
+                const char *errmsg;
+                // don't re-parse the cie if this fde is pointing to one we already parsed
+                if (cieStart == lastCieSeen) {
+                    errmsg = NULL;
+                }
+                else {
+                    errmsg = parseCIE(addressSpace, cieStart, &cieInfo);
+                    if (errmsg == NULL)
+                        lastCieSeen = cieStart;
+                }
+				if ( errmsg == NULL ) {
+					p += 4;
+					// parse pc begin and range
+					pint_t pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding);
+					pint_t pcRange = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding & 0x0F);
+					//fprintf(stderr, "FDE with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pcStart, (uint64_t)(pcStart+pcRange));
+                    funcbounds.push_back(FuncBounds(pcStart, pcStart + pcRange));
+				}
+				else {
+					// malformed CIE, now augmentation describing pc range encoding
+					//fprintf(stderr, "malformed CIE\n");
+                    return false;
+				}
+			}
+			else {
+				// malformed FDE.  CIE is bad
+				//fprintf(stderr, "malformed FDE, cieStart=0x%llX, ehSectionStart=0x%llX, ehSectionEnd=0x%llX\n",
+				//	(uint64_t)cieStart, (uint64_t)ehSectionStart, (uint64_t)ehSectionEnd);
+                return false;
+			}
+			p = nextCFI;
+		}
+	}
+	return true;
+}
+#endif // SUPPORT_REMOTE_UNWINDING
+
+
+
+///
+/// Extract info from a CIE
+///  
+template <typename A>
+const char* CFI_Parser<A>::parseCIE(A& addressSpace, pint_t cie, CIE_Info* cieInfo)
+{
+	//fprintf(stderr, "parseCIE(0x%llX)\n", (long long)cie);
+	cieInfo->pointerEncoding = 0;
+	cieInfo->lsdaEncoding = 0;
+	cieInfo->personalityEncoding = 0;
+	cieInfo->personalityOffsetInCIE = 0;
+	cieInfo->personality = 0;
+	cieInfo->codeAlignFactor = 0;
+	cieInfo->dataAlignFactor = 0;
+	cieInfo->isSignalFrame = false;
+	cieInfo->fdesHaveAugmentationData = false;
+	cieInfo->cieStart = cie;
+	pint_t p = cie;
+	uint64_t cieLength = addressSpace.get32(p);
+	p += 4;
+	pint_t cieContentEnd = p + cieLength;
+	if ( cieLength == 0xffffffff ) {
+		// 0xffffffff means length is really next 8 bytes
+		cieLength = addressSpace.get64(p);
+		p += 8;
+		cieContentEnd = p + cieLength;
+	}
+	if ( cieLength == 0 ) 
+		return false;	
+	// CIE ID is always 0
+	if ( addressSpace.get32(p) != 0 ) 
+		return "CIE ID is not zero";
+	p += 4;
+	// Version is always 1 or 3
+	uint8_t version = addressSpace.get8(p);
+	if ( (version != 1) && (version != 3) )
+		return "CIE version is not 1 or 3";
+	++p;
+	// save start of augmentation string and find end
+	pint_t strStart = p;
+	while ( addressSpace.get8(p) != 0 )
+		++p;
+	++p;
+	// parse code aligment factor
+	cieInfo->codeAlignFactor = addressSpace.getULEB128(p, cieContentEnd);
+	// parse data alignment factor
+	cieInfo->dataAlignFactor = addressSpace.getSLEB128(p, cieContentEnd);
+	// parse return address register
+	addressSpace.getULEB128(p, cieContentEnd);
+	// parse augmentation data based on augmentation string
+	const char* result = NULL;
+	if ( addressSpace.get8(strStart) == 'z' ) {
+		// parse augmentation data length 
+		addressSpace.getULEB128(p, cieContentEnd);
+		for (pint_t s=strStart; addressSpace.get8(s) != '\0'; ++s) {
+			switch ( addressSpace.get8(s) ) {
+				case 'z':
+					cieInfo->fdesHaveAugmentationData = true;
+					break;
+				case 'P':
+					cieInfo->personalityEncoding = addressSpace.get8(p);
+					++p;
+					cieInfo->personalityOffsetInCIE = p-cie;
+					cieInfo->personality = addressSpace.getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding);
+					break;
+				case 'L':
+					cieInfo->lsdaEncoding = addressSpace.get8(p);
+					++p;
+					break;
+				case 'R':
+					cieInfo->pointerEncoding = addressSpace.get8(p);
+					++p;
+					break;
+				case 'S':
+					cieInfo->isSignalFrame = true;
+					break;
+				default:
+					// ignore unknown letters
+					break;
+			}
+		}
+	}
+	cieInfo->cieLength = cieContentEnd - cieInfo->cieStart;
+	cieInfo->cieInstructions = p;
+	return result;
+}
+
+
+template <typename A>
+uint32_t CFI_Parser<A>::getCFICount(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength)
+{
+	uint32_t count = 0;
+	const pint_t ehSectionEnd = ehSectionStart + sectionLength;
+	for (pint_t p=ehSectionStart; p < ehSectionEnd; ) {
+		uint64_t cfiLength = addressSpace.get32(p);
+		p += 4;
+		if ( cfiLength == 0xffffffff ) {
+			// 0xffffffff means length is really next 8 bytes
+			cfiLength = addressSpace.get64(p);
+			p += 8;
+		}
+		if ( cfiLength == 0 ) 
+			return count;	// end marker
+		++count;
+		p += cfiLength;
+	}
+	return count;
+}
+
+
+
+template <typename A>
+const char* CFI_Parser<A>::getCFIs(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength, 
+								  std::vector<FDE_Atom_Info>& fdes, std::vector<CIE_Atom_Info>& cies)
+{
+	const pint_t ehSectionEnd = ehSectionStart + sectionLength;
+	for (pint_t p=ehSectionStart; p < ehSectionEnd; ) {
+		pint_t currentCFI = p;
+		uint64_t cfiLength = addressSpace.get32(p);
+		p += 4;
+		if ( cfiLength == 0xffffffff ) {
+			// 0xffffffff means length is really next 8 bytes
+			cfiLength = addressSpace.get64(p);
+			p += 8;
+		}
+		if ( cfiLength == 0 ) 
+			return NULL;	// end marker
+		uint32_t id = addressSpace.get32(p);
+		if ( id == 0 ) {
+			// is CIE
+			CIE_Info cieInfo;
+			const char* err = parseCIE(addressSpace, currentCFI, &cieInfo);
+			if ( err != NULL ) 
+				return err;
+			CIE_Atom_Info entry;
+			entry.cieAddress = currentCFI;
+			entry.personality.address = cieInfo.personality;
+			entry.personality.offsetInFDE = cieInfo.personalityOffsetInCIE;
+			entry.personality.encodingOfAddress = cieInfo.personalityEncoding;
+			cies.push_back(entry);
+			p += cfiLength;
+		}
+		else {
+			// is FDE
+			FDE_Atom_Info entry;
+			entry.fdeAddress = currentCFI;
+			entry.function.address = 0;
+			entry.cie.address = 0;
+			entry.lsda.address = 0;
+			pint_t nextCFI = p + cfiLength;
+			uint32_t ciePointer = addressSpace.get32(p);
+			pint_t cieStart = p-ciePointer;
+			// validate pointer to CIE is within section
+			if ( (cieStart < ehSectionStart) || (cieStart > ehSectionEnd) )
+				return "FDE points to CIE outside __eh_frame section";
+			CIE_Info cieInfo;
+			const char* err = parseCIE(addressSpace, cieStart, &cieInfo);
+			if ( err != NULL ) 
+				return err;
+			entry.cie.address = cieStart;
+			entry.cie.offsetInFDE = p-currentCFI;
+			entry.cie.encodingOfAddress = DW_EH_PE_sdata4 | DW_EH_PE_pcrel;
+			p += 4;
+			// parse pc begin and range
+			pint_t offsetOfFunctionAddress = p-currentCFI;
+			pint_t pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding);
+			pint_t pcRange = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding & 0x0F);
+			//fprintf(stderr, "FDE with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pcStart, (uint64_t)(pcStart+pcRange));
+			// test if pc is within the function this FDE covers
+			entry.function.address = pcStart;
+			entry.function.offsetInFDE = offsetOfFunctionAddress;
+			entry.function.encodingOfAddress = cieInfo.pointerEncoding;
+			// skip over augmentation length
+			if ( cieInfo.fdesHaveAugmentationData ) {
+				uintptr_t augLen = addressSpace.getULEB128(p, nextCFI);
+				pint_t endOfAug = p + augLen;
+				if ( (cieInfo.lsdaEncoding != 0) && (addressSpace.getP(p) != 0) ) {
+					pint_t offsetOfLSDAAddress = p-currentCFI;
+					entry.lsda.address = addressSpace.getEncodedP(p, nextCFI, cieInfo.lsdaEncoding);
+					entry.lsda.offsetInFDE = offsetOfLSDAAddress;
+					entry.lsda.encodingOfAddress = cieInfo.lsdaEncoding;
+				}
+				p = endOfAug;
+			}
+			fdes.push_back(entry);
+			p = nextCFI;
+		}
+	}
+	return NULL; // success
+}
+
+	
+
+///
+/// "run" the dwarf instructions and create the abstact PrologInfo for an FDE
+///  
+template <typename A>
+bool CFI_Parser<A>::parseFDEInstructions(A& addressSpace, const FDE_Info& fdeInfo, const CIE_Info& cieInfo, pint_t upToPC, PrologInfo* results)
+{
+	// clear results
+	bzero(results, sizeof(PrologInfo));
+	PrologInfoStackEntry* rememberStack = NULL;
+
+	// parse CIE then FDE instructions
+	return parseInstructions(addressSpace, cieInfo.cieInstructions, cieInfo.cieStart+cieInfo.cieLength, 
+						cieInfo, (pint_t)(-1), rememberStack, results)
+	    && parseInstructions(addressSpace, fdeInfo.fdeInstructions, fdeInfo.fdeStart+fdeInfo.fdeLength, 
+							cieInfo, upToPC-fdeInfo.pcStart, rememberStack, results);
+}
+
+
+///
+/// "run" the dwarf instructions
+///  
+template <typename A>
+bool CFI_Parser<A>::parseInstructions(A& addressSpace, pint_t instructions, pint_t instructionsEnd, const CIE_Info& cieInfo,
+									pint_t pcoffset, PrologInfoStackEntry*& rememberStack, PrologInfo* results)
+{
+	const bool logDwarf = false;
+	pint_t p = instructions;
+	uint32_t codeOffset = 0;
+	PrologInfo initialState = *results;
+	
+	// see Dwarf Spec, section 6.4.2 for details on unwind opcodes
+	while ( (p < instructionsEnd) && (codeOffset < pcoffset) ) {
+		uint64_t reg;
+		uint64_t reg2;
+		int64_t offset;
+		uint64_t length;
+		uint8_t opcode = addressSpace.get8(p);
+		uint8_t operand;
+		PrologInfoStackEntry* entry;
+		++p;
+		switch (opcode) {
+			case DW_CFA_nop:
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_nop\n");
+				break;
+			case DW_CFA_set_loc:
+				codeOffset = addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding);
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_set_loc\n");
+				break;
+			case DW_CFA_advance_loc1:
+				codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor);
+				p += 1;
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_advance_loc1: new offset=%u\n", codeOffset);
+				break;
+			case DW_CFA_advance_loc2:
+				codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor);
+				p += 2;
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_advance_loc2: new offset=%u\n", codeOffset);
+				break;
+			case DW_CFA_advance_loc4:
+				codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor);
+				p += 4;
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_advance_loc4: new offset=%u\n", codeOffset);
+				break;
+			case DW_CFA_offset_extended:
+				reg = addressSpace.getULEB128(p, instructionsEnd);
+				offset = addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
+				if ( reg > kMaxRegisterNumber ) {
+					fprintf(stderr, "malformed DW_CFA_offset_extended dwarf unwind, reg too big\n");
+					return false;
+				}
+				if ( results->savedRegisters[reg].location != kRegisterUnused ) 
+					results->registerSavedMoreThanOnce = true;
+				results->savedRegisters[reg].location = kRegisterInCFA;
+				results->savedRegisters[reg].value = offset;
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_offset_extended(reg=%lld, offset=%lld)\n", reg, offset);
+				break;
+			case DW_CFA_restore_extended:
+				reg = addressSpace.getULEB128(p, instructionsEnd);;
+				if ( reg > kMaxRegisterNumber ) {
+					fprintf(stderr, "malformed DW_CFA_restore_extended dwarf unwind, reg too big\n");
+					return false;
+				}
+				results->savedRegisters[reg] = initialState.savedRegisters[reg];
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_restore_extended(reg=%lld)\n", reg);
+				break;
+			case DW_CFA_undefined:
+				reg = addressSpace.getULEB128(p, instructionsEnd);
+				if ( reg > kMaxRegisterNumber ) {
+					fprintf(stderr, "malformed DW_CFA_undefined dwarf unwind, reg too big\n");
+					return false;
+				}
+				results->savedRegisters[reg].location = kRegisterUnused;
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_undefined(reg=%lld)\n", reg);
+				break;
+			case DW_CFA_same_value:
+				reg = addressSpace.getULEB128(p, instructionsEnd);
+				if ( reg > kMaxRegisterNumber ) {
+					fprintf(stderr, "malformed DW_CFA_same_value dwarf unwind, reg too big\n");
+					return false;
+				}
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_same_value(reg=%lld)\n", reg);
+				break;
+			case DW_CFA_register:
+				reg = addressSpace.getULEB128(p, instructionsEnd);
+				reg2 = addressSpace.getULEB128(p, instructionsEnd);
+				if ( reg > kMaxRegisterNumber ) {
+					fprintf(stderr, "malformed DW_CFA_register dwarf unwind, reg too big\n");
+					return false;
+				}
+				if ( reg2 > kMaxRegisterNumber ) {
+					fprintf(stderr, "malformed DW_CFA_register dwarf unwind, reg2 too big\n");
+					return false;
+				}
+				results->savedRegisters[reg].location = kRegisterInRegister;
+				results->savedRegisters[reg].value = reg2;
+				results->registersInOtherRegisters = true;
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_register(reg=%lld, reg2=%lld)\n", reg, reg2);
+				break;
+			case DW_CFA_remember_state:
+				// avoid operator new, because that would be an upward dependency
+				entry = (PrologInfoStackEntry*)malloc(sizeof(PrologInfoStackEntry));
+				if ( entry != NULL ) {
+					entry->next = rememberStack;
+					entry->info = *results;
+					rememberStack = entry;
+				}
+				else {
+					return false;
+				}
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_remember_state\n");
+				break;
+			case DW_CFA_restore_state:
+				if ( rememberStack != NULL ) {
+					PrologInfoStackEntry* top = rememberStack;
+					*results = top->info;
+					rememberStack = top->next;
+					free((char*)top);
+				}
+				else {
+					return false;
+				}
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_restore_state\n");
+				break;
+			case DW_CFA_def_cfa:
+				reg = addressSpace.getULEB128(p, instructionsEnd);
+				offset = addressSpace.getULEB128(p, instructionsEnd);
+				if ( reg > kMaxRegisterNumber ) {
+					fprintf(stderr, "malformed DW_CFA_def_cfa dwarf unwind, reg too big\n");
+					return false;
+				}
+				results->cfaRegister = reg;
+				results->cfaRegisterOffset = offset;
+				if ( offset > 0x80000000 ) 
+					results->cfaOffsetWasNegative = true;
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa(reg=%lld, offset=%lld)\n", reg, offset);
+				break;
+			case DW_CFA_def_cfa_register:
+				reg = addressSpace.getULEB128(p, instructionsEnd);
+				if ( reg > kMaxRegisterNumber ) {
+					fprintf(stderr, "malformed DW_CFA_def_cfa_register dwarf unwind, reg too big\n");
+					return false;
+				}
+				results->cfaRegister = reg;
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa_register(%lld)\n", reg);
+				break;
+			case DW_CFA_def_cfa_offset:
+				results->cfaRegisterOffset = addressSpace.getULEB128(p, instructionsEnd);
+				results->codeOffsetAtStackDecrement = codeOffset;
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa_offset(%d)\n", results->cfaRegisterOffset);
+				break;
+			case DW_CFA_def_cfa_expression:
+				results->cfaRegister = 0;
+				results->cfaExpression = p;
+				length = addressSpace.getULEB128(p, instructionsEnd);
+				p += length;
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa_expression(expression=0x%llX, length=%llu)\n", 
+													results->cfaExpression, length);
+				break;
+			case DW_CFA_expression:
+				reg = addressSpace.getULEB128(p, instructionsEnd);
+				if ( reg > kMaxRegisterNumber ) {
+					fprintf(stderr, "malformed DW_CFA_expression dwarf unwind, reg too big\n");
+					return false;
+				}
+				results->savedRegisters[reg].location = kRegisterAtExpression;
+				results->savedRegisters[reg].value = p;
+				length = addressSpace.getULEB128(p, instructionsEnd);
+				p += length;
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_expression(reg=%lld, expression=0x%llX, length=%llu)\n", 
+													reg, results->savedRegisters[reg].value, length);
+				break;
+			case DW_CFA_offset_extended_sf:
+				reg = addressSpace.getULEB128(p, instructionsEnd);
+				if ( reg > kMaxRegisterNumber ) {
+					fprintf(stderr, "malformed DW_CFA_offset_extended_sf dwarf unwind, reg too big\n");
+					return false;
+				}
+				offset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
+				if ( results->savedRegisters[reg].location != kRegisterUnused ) 
+					results->registerSavedMoreThanOnce = true;
+				results->savedRegisters[reg].location = kRegisterInCFA;
+				results->savedRegisters[reg].value = offset;
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_offset_extended_sf(reg=%lld, offset=%lld)\n", reg, offset);
+				break;
+			case DW_CFA_def_cfa_sf:
+				reg = addressSpace.getULEB128(p, instructionsEnd);
+				offset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
+				if ( reg > kMaxRegisterNumber ) {
+					fprintf(stderr, "malformed DW_CFA_def_cfa_sf dwarf unwind, reg too big\n");
+					return false;
+				}
+				results->cfaRegister = reg;
+				results->cfaRegisterOffset = offset;
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa_sf(reg=%lld, offset=%lld)\n", reg, offset);
+				break;
+			case DW_CFA_def_cfa_offset_sf:
+				results->cfaRegisterOffset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
+				results->codeOffsetAtStackDecrement = codeOffset;
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa_offset_sf(%d)\n", results->cfaRegisterOffset);
+				break;
+			case DW_CFA_val_offset:
+				reg = addressSpace.getULEB128(p, instructionsEnd);
+				offset = addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
+				results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
+				results->savedRegisters[reg].value = offset;
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_val_offset(reg=%lld, offset=%lld\n", reg, offset);
+				break;
+			case DW_CFA_val_offset_sf:
+				reg = addressSpace.getULEB128(p, instructionsEnd);
+				if ( reg > kMaxRegisterNumber ) {
+					fprintf(stderr, "malformed DW_CFA_val_offset_sf dwarf unwind, reg too big\n");
+					return false;
+				}
+				offset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
+				results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
+				results->savedRegisters[reg].value = offset;
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_val_offset_sf(reg=%lld, offset=%lld\n", reg, offset);
+				break;
+			case DW_CFA_val_expression:
+				reg = addressSpace.getULEB128(p, instructionsEnd);
+				if ( reg > kMaxRegisterNumber ) {
+					fprintf(stderr, "malformed DW_CFA_val_expression dwarf unwind, reg too big\n");
+					return false;
+				}
+				results->savedRegisters[reg].location = kRegisterIsExpression;
+				results->savedRegisters[reg].value = p;
+				length = addressSpace.getULEB128(p, instructionsEnd);
+				p += length;
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_val_expression(reg=%lld, expression=0x%llX, length=%lld)\n", 
+													reg, results->savedRegisters[reg].value, length);
+				break;
+			case DW_CFA_GNU_args_size:
+				offset = addressSpace.getULEB128(p, instructionsEnd);
+				results->spExtraArgSize = offset;
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_GNU_args_size(%lld)\n", offset);
+				break;
+			case DW_CFA_GNU_negative_offset_extended:
+				reg = addressSpace.getULEB128(p, instructionsEnd);
+				if ( reg > kMaxRegisterNumber ) {
+					fprintf(stderr, "malformed DW_CFA_GNU_negative_offset_extended dwarf unwind, reg too big\n");
+					return false;
+				}
+				offset = addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
+				if ( results->savedRegisters[reg].location != kRegisterUnused ) 
+					results->registerSavedMoreThanOnce = true;
+				results->savedRegisters[reg].location = kRegisterInCFA;
+				results->savedRegisters[reg].value = -offset;
+				if ( logDwarf ) fprintf(stderr, "DW_CFA_GNU_negative_offset_extended(%lld)\n", offset);
+				break;
+			default:
+				operand = opcode & 0x3F;
+				switch ( opcode & 0xC0 ) {
+					case DW_CFA_offset:
+						reg = operand;
+						offset = addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
+						if ( results->savedRegisters[reg].location != kRegisterUnused ) 
+							results->registerSavedMoreThanOnce = true;
+						results->savedRegisters[reg].location = kRegisterInCFA;
+						results->savedRegisters[reg].value = offset;
+						if ( logDwarf ) fprintf(stderr, "DW_CFA_offset(reg=%d, offset=%lld)\n", operand, offset);
+						break;
+					case DW_CFA_advance_loc:
+						codeOffset += operand * cieInfo.codeAlignFactor;
+						if ( logDwarf ) fprintf(stderr, "DW_CFA_advance_loc: new offset=%u\n", codeOffset);
+						break;
+					case DW_CFA_restore:
+						// <rdar://problem/7503075> Python crashes when handling an exception thrown by an obj-c object
+						// libffi uses DW_CFA_restore in the middle of some custom dward, so it is not a good epilog flag
+						//return true; // gcc-4.5 starts the epilog with this
+						reg = operand;
+						results->savedRegisters[reg] = initialState.savedRegisters[reg];
+						if ( logDwarf ) fprintf(stderr, "DW_CFA_restore(reg=%lld)\n", reg);
+						break;
+					default: 
+						if ( logDwarf ) fprintf(stderr, "unknown CFA opcode 0x%02X\n", opcode);
+						return false;
+				}
+		}
+	}
+
+	return true;
+}
+
+
+} // namespace lldb_private 
+
+
+#endif // __DWARF_PARSER_HPP__
+
+
+
+
diff --git a/source/Plugins/Process/Utility/libunwind/src/FileAbstraction.hpp b/source/Plugins/Process/Utility/libunwind/src/FileAbstraction.hpp
new file mode 100644
index 0000000..a4af020
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/FileAbstraction.hpp
@@ -0,0 +1,135 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- FileAbstraction.hpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __FILE_ABSTRACTION__
+#define __FILE_ABSTRACTION__
+
+
+#include <stdint.h>
+#include <string.h>
+#include <libkern/OSByteOrder.h>
+
+#ifdef __OPTIMIZE__
+#define INLINE	__attribute__((always_inline))
+#else
+#define INLINE
+#endif
+
+//
+// This abstraction layer is for use with file formats that have 64-bit/32-bit and Big-Endian/Little-Endian variants
+//
+// For example: to make a utility that handles 32-bit little enidan files use:  Pointer32<LittleEndian>
+//
+//
+//		get16()			read a 16-bit number from an E endian struct
+//		set16()			write a 16-bit number to an E endian struct
+//		get32()			read a 32-bit number from an E endian struct
+//		set32()			write a 32-bit number to an E endian struct
+//		get64()			read a 64-bit number from an E endian struct
+//		set64()			write a 64-bit number to an E endian struct
+//
+//		getBits()		read a bit field from an E endian struct (bitCount=number of bits in field, firstBit=bit index of field)
+//		setBits()		write a bit field to an E endian struct (bitCount=number of bits in field, firstBit=bit index of field)
+//
+//		getBitsRaw()	read a bit field from a struct with native endianness
+//		setBitsRaw()	write a bit field from a struct with native endianness
+//
+
+class BigEndian
+{
+public:
+	static uint16_t	get16(const uint16_t& from)				INLINE { return OSReadBigInt16(&from, 0); }
+	static void		set16(uint16_t& into, uint16_t value)	INLINE { OSWriteBigInt16(&into, 0, value); }
+	
+	static uint32_t	get32(const uint32_t& from)				INLINE { return OSReadBigInt32(&from, 0); }
+	static void		set32(uint32_t& into, uint32_t value)	INLINE { OSWriteBigInt32(&into, 0, value); }
+	
+	static uint64_t get64(const uint64_t& from)				INLINE { return OSReadBigInt64(&from, 0); }
+	static void		set64(uint64_t& into, uint64_t value)	INLINE { OSWriteBigInt64(&into, 0, value); }
+	
+	static uint32_t	getBits(const uint32_t& from, 
+						uint8_t firstBit, uint8_t bitCount)	INLINE { return getBitsRaw(get32(from), firstBit, bitCount); }
+	static void		setBits(uint32_t& into, uint32_t value,
+						uint8_t firstBit, uint8_t bitCount)	INLINE { uint32_t temp = get32(into); setBitsRaw(temp, value, firstBit, bitCount); set32(into, temp); }
+
+	static uint32_t	getBitsRaw(const uint32_t& from, 
+						uint8_t firstBit, uint8_t bitCount)	INLINE { return ((from >> (32-firstBit-bitCount)) & ((1<<bitCount)-1)); }
+	static void		setBitsRaw(uint32_t& into, uint32_t value,
+						uint8_t firstBit, uint8_t bitCount)	INLINE { uint32_t temp = into; 
+																							const uint32_t mask = ((1<<bitCount)-1); 
+																							temp &= ~(mask << (32-firstBit-bitCount)); 
+																							temp |= ((value & mask) << (32-firstBit-bitCount)); 
+																							into = temp; }
+	enum { little_endian = 0 };
+};
+
+
+class LittleEndian
+{
+public:
+	static uint16_t	get16(const uint16_t& from)				INLINE { return OSReadLittleInt16(&from, 0); }
+	static void		set16(uint16_t& into, uint16_t value)	INLINE { OSWriteLittleInt16(&into, 0, value); }
+	
+	static uint32_t	get32(const uint32_t& from)				INLINE { return OSReadLittleInt32(&from, 0); }
+	static void		set32(uint32_t& into, uint32_t value)	INLINE { OSWriteLittleInt32(&into, 0, value); }
+	
+	static uint64_t get64(const uint64_t& from)				INLINE { return OSReadLittleInt64(&from, 0); }
+	static void		set64(uint64_t& into, uint64_t value)	INLINE { OSWriteLittleInt64(&into, 0, value); }
+
+	static uint32_t	getBits(const uint32_t& from,
+						uint8_t firstBit, uint8_t bitCount)	INLINE { return getBitsRaw(get32(from), firstBit, bitCount); }
+	static void		setBits(uint32_t& into, uint32_t value,
+						uint8_t firstBit, uint8_t bitCount)	INLINE { uint32_t temp = get32(into); setBitsRaw(temp, value, firstBit, bitCount); set32(into, temp); }
+
+	static uint32_t	getBitsRaw(const uint32_t& from,
+						uint8_t firstBit, uint8_t bitCount)	INLINE { return ((from >> firstBit) & ((1<<bitCount)-1)); }
+	static void		setBitsRaw(uint32_t& into, uint32_t value,
+						uint8_t firstBit, uint8_t bitCount)	INLINE {  uint32_t temp = into; 
+																							const uint32_t mask = ((1<<bitCount)-1); 
+																							temp &= ~(mask << firstBit); 
+																							temp |= ((value & mask) << firstBit); 
+																							into = temp; }
+	enum { little_endian = 1 };
+};
+
+
+template <typename _E>
+class Pointer32
+{
+public:
+	typedef uint32_t	uint_t;
+	typedef int32_t	    int_t;
+	typedef _E			E;
+	
+	static uint64_t	getP(const uint_t& from)				INLINE { return _E::get32(from); }
+	static void		setP(uint_t& into, uint64_t value)		INLINE { _E::set32(into, value); }
+};
+
+
+template <typename _E>
+class Pointer64
+{
+public:
+	typedef uint64_t	uint_t;
+	typedef int64_t	    int_t;
+	typedef _E			E;
+	
+	static uint64_t	getP(const uint_t& from)				INLINE { return _E::get64(from); }
+	static void		setP(uint_t& into, uint64_t value)		INLINE { _E::set64(into, value); }
+};
+
+
+
+
+
+
+#endif // __FILE_ABSTRACTION__
+
+
diff --git a/source/Plugins/Process/Utility/libunwind/src/InternalMacros.h b/source/Plugins/Process/Utility/libunwind/src/InternalMacros.h
new file mode 100644
index 0000000..4048390
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/InternalMacros.h
@@ -0,0 +1,89 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- InternalMacros.h ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef INTERNAL_MACROS_H
+#define INTERNAL_MACROS_H
+
+#include <assert.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+	extern void __assert_rtn(const char *, const char *, int, const char *) __attribute__((noreturn));
+#ifdef __cplusplus
+}
+#endif
+
+#define UNW_STEP_SUCCESS 1
+#define UNW_STEP_END     0
+
+
+struct v128 { unsigned int vec[4]; };
+
+
+#define EXPORT __attribute__((visibility("default"))) 
+
+#define COMPILE_TIME_ASSERT( expr )    \
+		extern int compile_time_assert_failed[ ( expr ) ? 1 : -1 ] __attribute__( ( unused ) );
+
+#define ABORT(msg) __assert_rtn(__func__, __FILE__, __LINE__, msg) 
+
+#if NDEBUG
+	#define DEBUG_MESSAGE(msg, ...)  
+	#define DEBUG_PRINT_API(msg, ...)
+	#define DEBUG_PRINT_UNWINDING_TEST 0
+	#define DEBUG_PRINT_UNWINDING(msg, ...)
+	#define DEBUG_LOG_NON_ZERO(x) x;
+	#define INITIALIZE_DEBUG_PRINT_API
+	#define INITIALIZE_DEBUG_PRINT_UNWINDING
+#else
+	#define DEBUG_MESSAGE(msg, ...)  fprintf(stderr, "libuwind: " msg, __VA_ARGS__)
+	#ifdef __cplusplus
+		extern "C" {
+	#endif
+		extern  bool logAPIs();
+		extern  bool logUnwinding();
+	#ifdef __cplusplus
+		}
+	#endif
+	#define DEBUG_LOG_NON_ZERO(x) { int _err = x; if ( _err != 0 ) fprintf(stderr, "libuwind: " #x "=%d in %s", _err, __FUNCTION__); }
+	#define DEBUG_PRINT_API(msg, ...) do { if ( logAPIs() ) fprintf(stderr,  msg, __VA_ARGS__); } while(0)
+	#define DEBUG_PRINT_UNWINDING(msg, ...) do { if ( logUnwinding() ) fprintf(stderr,  msg, __VA_ARGS__); } while(0)
+	#define DEBUG_PRINT_UNWINDING_TEST logUnwinding()
+	#define INITIALIZE_DEBUG_PRINT_API bool logAPIs() { static bool log = (getenv("LIBUNWIND_PRINT_APIS") != NULL); return log; }
+	#define INITIALIZE_DEBUG_PRINT_UNWINDING bool logUnwinding() { static bool log = (getenv("LIBUNWIND_PRINT_UNWINDING") != NULL); return log; }
+#endif
+
+
+// note hack for <rdar://problem/6175741>
+// Once libgcc_s.dylib vectors to libSystem, then we can remove the $ld$hide$os10.6$ lines
+#if __ppc__
+	#define NOT_HERE_BEFORE_10_6(sym) \
+		extern const char sym##_tmp3 __asm("$ld$hide$os10.3$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp3 = 0; \
+ 		extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
+		extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp5 = 0; 
+	#define NEVER_HERE(sym) \
+		extern const char sym##_tmp3 __asm("$ld$hide$os10.3$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp3 = 0; \
+ 		extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
+		extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp5 = 0; \
+		extern const char sym##_tmp6 __asm("$ld$hide$os10.6$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp6 = 0;
+#else
+	#define NOT_HERE_BEFORE_10_6(sym) \
+ 		extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
+		extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp5 = 0; 
+	#define NEVER_HERE(sym) \
+ 		extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
+		extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp5 = 0; \
+		extern const char sym##_tmp6 __asm("$ld$hide$os10.6$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp6 = 0;
+#endif
+
+
+
+#endif // INTERNAL_MACROS_H
diff --git a/source/Plugins/Process/Utility/libunwind/src/Registers.hpp b/source/Plugins/Process/Utility/libunwind/src/Registers.hpp
new file mode 100644
index 0000000..291c724
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/Registers.hpp
@@ -0,0 +1,985 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- Registers.hpp -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+ 
+//
+//	C++ interface to lower levels of libuwind 
+//
+
+#ifndef __REGISTERS_HPP__
+#define __REGISTERS_HPP__
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <mach-o/loader.h>
+#include <mach-o/getsect.h>
+#include <mach/ppc/thread_status.h>
+#include <mach/i386/thread_status.h>
+
+#include "libunwind.h"
+#include "InternalMacros.h"
+
+namespace lldb_private {
+
+
+///
+/// Registers_x86 holds the register state of a thread in a 32-bit intel process.  
+///
+class Registers_x86
+{
+public:	
+					Registers_x86();
+					Registers_x86(const void* registers);
+
+	bool			validRegister(int num) const;
+	uint32_t		getRegister(int num) const;
+	void			setRegister(int num, uint32_t value);
+	bool			validFloatRegister(int num) const { return false; }
+	double			getFloatRegister(int num) const;
+	void			setFloatRegister(int num, double value); 
+	bool			validVectorRegister(int num) const { return false; }
+	v128			getVectorRegister(int num) const;
+	void			setVectorRegister(int num, v128 value);
+	const char*		getRegisterName(int num);
+	void			jumpto() {}
+	
+	uint32_t		getSP() const			{ return fRegisters.__esp; }
+	void			setSP(uint32_t value)	{ fRegisters.__esp = value; }
+	uint32_t		getIP()	const			{ return fRegisters.__eip; }
+	void			setIP(uint32_t value)	{ fRegisters.__eip = value; }
+	uint32_t		getEBP() const			{ return fRegisters.__ebp; }
+	void			setEBP(uint32_t value)	{ fRegisters.__ebp = value; }
+	uint32_t		getEBX() const			{ return fRegisters.__ebx; }
+	void			setEBX(uint32_t value)	{ fRegisters.__ebx = value; }
+	uint32_t		getECX() const			{ return fRegisters.__ecx; }
+	void			setECX(uint32_t value)	{ fRegisters.__ecx = value; }
+	uint32_t		getEDX() const			{ return fRegisters.__edx; }
+	void			setEDX(uint32_t value)	{ fRegisters.__edx = value; }
+	uint32_t		getESI() const			{ return fRegisters.__esi; }
+	void			setESI(uint32_t value)	{ fRegisters.__esi = value; }
+	uint32_t		getEDI() const			{ return fRegisters.__edi; }
+	void			setEDI(uint32_t value)	{ fRegisters.__edi = value; }
+	
+private:
+	i386_thread_state_t  fRegisters;
+};
+
+inline Registers_x86::Registers_x86(const void* registers)
+{
+	COMPILE_TIME_ASSERT( sizeof(Registers_x86) < sizeof(unw_context_t) );
+	fRegisters = *((i386_thread_state_t*)registers); 
+}
+
+inline Registers_x86::Registers_x86()
+{
+	bzero(&fRegisters, sizeof(fRegisters)); 
+}
+
+
+inline bool Registers_x86::validRegister(int regNum) const
+{
+	if ( regNum == UNW_REG_IP )
+		return true;
+	if ( regNum == UNW_REG_SP )
+		return true;
+	if ( regNum < 0 )
+		return false;
+	if ( regNum > 7 )
+		return false;
+	return true;
+}
+
+inline uint32_t Registers_x86::getRegister(int regNum) const
+{
+	switch ( regNum ) {
+		case UNW_REG_IP:
+			return fRegisters.__eip;
+		case UNW_REG_SP:
+			return fRegisters.__esp;
+		case UNW_X86_EAX:
+			return fRegisters.__eax;
+		case UNW_X86_ECX:
+			return fRegisters.__ecx;
+		case UNW_X86_EDX:
+			return fRegisters.__edx;
+		case UNW_X86_EBX:
+			return fRegisters.__ebx;
+		case UNW_X86_EBP:
+			return fRegisters.__ebp;
+		case UNW_X86_ESP:
+			return fRegisters.__esp;
+		case UNW_X86_ESI:
+			return fRegisters.__esi;
+		case UNW_X86_EDI:
+			return fRegisters.__edi;
+	}
+	ABORT("unsupported x86 register");
+}
+
+inline void Registers_x86::setRegister(int regNum, uint32_t value)
+{
+	switch ( regNum ) {
+		case UNW_REG_IP:
+			fRegisters.__eip = value;
+			return;
+		case UNW_REG_SP:
+			fRegisters.__esp = value;
+			return;
+		case UNW_X86_EAX:
+			fRegisters.__eax = value;
+			return;
+		case UNW_X86_ECX:
+			fRegisters.__ecx = value;
+			return;
+		case UNW_X86_EDX:
+			fRegisters.__edx = value;
+			return;
+		case UNW_X86_EBX:
+			fRegisters.__ebx = value;
+			return;
+		case UNW_X86_EBP:
+			fRegisters.__ebp = value;
+			return;
+		case UNW_X86_ESP:
+			fRegisters.__esp = value;
+			return;
+		case UNW_X86_ESI:
+			fRegisters.__esi = value;
+			return;
+		case UNW_X86_EDI:
+			fRegisters.__edi = value;
+			return;
+	}
+	ABORT("unsupported x86 register");
+}
+
+inline const char* Registers_x86::getRegisterName(int regNum)
+{
+	switch ( regNum ) {
+		case UNW_REG_IP:
+			return "ip";
+		case UNW_REG_SP:
+			return "esp";
+		case UNW_X86_EAX:
+			return "eax";
+		case UNW_X86_ECX:
+			return "ecx";
+		case UNW_X86_EDX:
+			return "edx";
+		case UNW_X86_EBX:
+			return "ebx";
+		case UNW_X86_EBP:
+			return "ebp";
+		case UNW_X86_ESP:
+			return "esp";
+		case UNW_X86_ESI:
+			return "esi";
+		case UNW_X86_EDI:
+			return "edi";
+		default:
+			return "unknown register";
+	}
+}
+
+inline double Registers_x86::getFloatRegister(int num) const
+{
+	ABORT("no x86 float registers");
+}
+
+inline void Registers_x86::setFloatRegister(int num, double value)
+{
+	ABORT("no x86 float registers");
+}
+
+inline v128 Registers_x86::getVectorRegister(int num) const
+{
+	ABORT("no x86 vector registers");
+}
+
+inline void Registers_x86::setVectorRegister(int num, v128 value)
+{
+	ABORT("no x86 vector registers");
+}
+
+
+
+
+///
+/// Registers_x86_64  holds the register state of a thread in a 64-bit intel process.  
+///
+class Registers_x86_64
+{
+public:	
+					Registers_x86_64();
+					Registers_x86_64(const void* registers); 
+
+	bool			validRegister(int num) const;
+	uint64_t		getRegister(int num) const;
+	void			setRegister(int num, uint64_t value);
+	bool			validFloatRegister(int num) const{ return false; }
+	double			getFloatRegister(int num) const;
+	void			setFloatRegister(int num, double value);
+	bool			validVectorRegister(int num) const { return false; }
+	v128			getVectorRegister(int num) const;
+	void			setVectorRegister(int num, v128 value);
+	const char*		getRegisterName(int num);
+	void			jumpto() {}
+	uint64_t		getSP()	const			{ return fRegisters.__rsp; }
+	void			setSP(uint64_t value)	{ fRegisters.__rsp = value; }
+	uint64_t		getIP()	const			{ return fRegisters.__rip; }
+	void			setIP(uint64_t value)	{ fRegisters.__rip = value; }
+	uint64_t		getRBP() const			{ return fRegisters.__rbp; }
+	void			setRBP(uint64_t value)	{ fRegisters.__rbp = value; }
+	uint64_t		getRBX() const			{ return fRegisters.__rbx; }
+	void			setRBX(uint64_t value)	{ fRegisters.__rbx = value; }
+	uint64_t		getR12() const			{ return fRegisters.__r12; }
+	void			setR12(uint64_t value)	{ fRegisters.__r12 = value; }
+	uint64_t		getR13() const			{ return fRegisters.__r13; }
+	void			setR13(uint64_t value)	{ fRegisters.__r13 = value; }
+	uint64_t		getR14() const			{ return fRegisters.__r14; }
+	void			setR14(uint64_t value)	{ fRegisters.__r14 = value; }
+	uint64_t		getR15() const			{ return fRegisters.__r15; }
+	void			setR15(uint64_t value)	{ fRegisters.__r15 = value; }
+private:
+	x86_thread_state64_t fRegisters;
+};
+
+inline Registers_x86_64::Registers_x86_64(const void* registers)
+{
+	COMPILE_TIME_ASSERT( sizeof(Registers_x86_64) < sizeof(unw_context_t) );
+	fRegisters = *((x86_thread_state64_t*)registers); 
+}
+
+inline Registers_x86_64::Registers_x86_64()
+{
+	bzero(&fRegisters, sizeof(fRegisters)); 
+}
+
+
+inline bool Registers_x86_64::validRegister(int regNum) const
+{
+	if ( regNum == UNW_REG_IP )
+		return true;
+	if ( regNum == UNW_REG_SP )
+		return true;
+	if ( regNum < 0 )
+		return false;
+	if ( regNum > 15 )
+		return false;
+	return true;
+}
+
+inline uint64_t Registers_x86_64::getRegister(int regNum) const
+{
+	switch ( regNum ) {
+		case UNW_REG_IP:
+			return fRegisters.__rip;
+		case UNW_REG_SP:
+			return fRegisters.__rsp;
+		case UNW_X86_64_RAX:
+			return fRegisters.__rax;
+		case UNW_X86_64_RDX:
+			return fRegisters.__rdx;
+		case UNW_X86_64_RCX:
+			return fRegisters.__rcx;
+		case UNW_X86_64_RBX:
+			return fRegisters.__rbx;
+		case UNW_X86_64_RSI:
+			return fRegisters.__rsi;
+		case UNW_X86_64_RDI:
+			return fRegisters.__rdi;
+		case UNW_X86_64_RBP:
+			return fRegisters.__rbp;
+		case UNW_X86_64_RSP:
+			return fRegisters.__rsp;
+		case UNW_X86_64_R8:
+			return fRegisters.__r8;
+		case UNW_X86_64_R9:
+			return fRegisters.__r9;
+		case UNW_X86_64_R10:
+			return fRegisters.__r10;
+		case UNW_X86_64_R11:
+			return fRegisters.__r11;
+		case UNW_X86_64_R12:
+			return fRegisters.__r12;
+		case UNW_X86_64_R13:
+			return fRegisters.__r13;
+		case UNW_X86_64_R14:
+			return fRegisters.__r14;
+		case UNW_X86_64_R15:
+			return fRegisters.__r15;
+	}
+	ABORT("unsupported x86_64 register");
+}
+
+inline void Registers_x86_64::setRegister(int regNum, uint64_t value)
+{
+	switch ( regNum ) {
+		case UNW_REG_IP:
+			fRegisters.__rip = value;
+			return;
+		case UNW_REG_SP:
+			fRegisters.__rsp = value;
+			return;
+		case UNW_X86_64_RAX:
+			fRegisters.__rax = value;
+			return;
+		case UNW_X86_64_RDX:
+			fRegisters.__rdx = value;
+			return;
+		case UNW_X86_64_RCX:
+			fRegisters.__rcx = value;
+			return;
+		case UNW_X86_64_RBX:
+			fRegisters.__rbx = value;
+			return;
+		case UNW_X86_64_RSI:
+			fRegisters.__rsi = value;
+			return;
+		case UNW_X86_64_RDI:
+			fRegisters.__rdi = value;
+			return;
+		case UNW_X86_64_RBP:
+			fRegisters.__rbp = value;
+			return;
+		case UNW_X86_64_RSP:
+			fRegisters.__rsp = value;
+			return;
+		case UNW_X86_64_R8:
+			fRegisters.__r8 = value;
+			return;
+		case UNW_X86_64_R9:
+			fRegisters.__r9 = value;
+			return;
+		case UNW_X86_64_R10:
+			fRegisters.__r10 = value;
+			return;
+		case UNW_X86_64_R11:
+			fRegisters.__r11 = value;
+			return;
+		case UNW_X86_64_R12:
+			fRegisters.__r12 = value;
+			return;
+		case UNW_X86_64_R13:
+			fRegisters.__r13 = value;
+			return;
+		case UNW_X86_64_R14:
+			fRegisters.__r14 = value;
+			return;
+		case UNW_X86_64_R15:
+			fRegisters.__r15 = value;
+			return;
+	}
+	ABORT("unsupported x86_64 register");
+}
+
+inline const char* Registers_x86_64::getRegisterName(int regNum)
+{
+	switch ( regNum ) {
+		case UNW_REG_IP:
+			return "rip";
+		case UNW_REG_SP:
+			return "rsp";
+		case UNW_X86_64_RAX:
+			return "rax";
+		case UNW_X86_64_RDX:
+			return "rdx";
+		case UNW_X86_64_RCX:
+			return "rcx";
+		case UNW_X86_64_RBX:
+			return "rbx";
+		case UNW_X86_64_RSI:
+			return "rsi";
+		case UNW_X86_64_RDI:
+			return "rdi";
+		case UNW_X86_64_RBP:
+			return "rbp";
+		case UNW_X86_64_RSP:
+			return "rsp";
+		case UNW_X86_64_R8:
+			return "r8";
+		case UNW_X86_64_R9:
+			return "r9";
+		case UNW_X86_64_R10:
+			return "r10";
+		case UNW_X86_64_R11:
+			return "r11";
+		case UNW_X86_64_R12:
+			return "r12";
+		case UNW_X86_64_R13:
+			return "r13";
+		case UNW_X86_64_R14:
+			return "r14";
+		case UNW_X86_64_R15:
+			return "r15";
+		default:
+			return "unknown register";
+	}
+}
+
+double Registers_x86_64::getFloatRegister(int num) const
+{
+	ABORT("no x86_64 float registers");
+}
+
+void Registers_x86_64::setFloatRegister(int num, double value)
+{
+	ABORT("no x86_64 float registers");
+}
+
+inline v128 Registers_x86_64::getVectorRegister(int num) const
+{
+	ABORT("no x86_64 vector registers");
+}
+
+inline void Registers_x86_64::setVectorRegister(int num, v128 value)
+{
+	ABORT("no x86_64 vector registers");
+}
+
+
+///
+/// Registers_ppc holds the register state of a thread in a 32-bit PowerPC process.  
+///
+class Registers_ppc
+{
+public:	
+					Registers_ppc();
+					Registers_ppc(const void* registers);
+
+	bool			validRegister(int num) const;
+	uint32_t		getRegister(int num) const;
+	void			setRegister(int num, uint32_t value);
+	bool			validFloatRegister(int num) const;
+	double			getFloatRegister(int num) const;
+	void			setFloatRegister(int num, double value);
+	bool			validVectorRegister(int num) const;
+	v128			getVectorRegister(int num) const;
+	void			setVectorRegister(int num, v128 value);
+	void			jumpto() {}
+	const char*		getRegisterName(int num);
+	uint64_t		getSP() const			{ return fRegisters.__r1; }
+	void			setSP(uint64_t value)	{ fRegisters.__r1 = value; }
+	uint64_t		getIP() const			{ return fRegisters.__srr0; }
+	void			setIP(uint64_t value)	{ fRegisters.__srr0 = value; }
+private:	
+	ppc_thread_state_t	fRegisters;
+	ppc_float_state_t	fFloatRegisters;
+	v128				fVectorRegisters[32];	// offset 424 
+};
+
+
+
+inline Registers_ppc::Registers_ppc(const void* registers) 
+{
+	COMPILE_TIME_ASSERT( sizeof(Registers_ppc) < sizeof(unw_context_t) );
+	fRegisters = *((ppc_thread_state_t*)registers); 
+	fFloatRegisters = *((ppc_float_state_t*)((char*)registers+160));
+	memcpy(fVectorRegisters, ((char*)registers+424), sizeof(fVectorRegisters));
+}
+
+inline Registers_ppc::Registers_ppc() 
+{ 
+	bzero(&fRegisters, sizeof(fRegisters)); 
+	bzero(&fFloatRegisters, sizeof(fFloatRegisters)); 
+	bzero(&fVectorRegisters, sizeof(fVectorRegisters)); 
+}
+
+
+inline bool Registers_ppc::validRegister(int regNum) const
+{
+	if ( regNum == UNW_REG_IP )
+		return true;
+	if ( regNum == UNW_REG_SP )
+		return true;
+	if ( regNum == UNW_PPC_VRSAVE )
+		return true;
+	if ( regNum < 0 )
+		return false;
+	if ( regNum <= UNW_PPC_R31 )
+		return true;
+	if ( regNum == UNW_PPC_MQ )
+		return true;
+	if ( regNum == UNW_PPC_LR )
+		return true;
+	if ( regNum == UNW_PPC_CTR )
+		return true;
+	if ( (UNW_PPC_CR0 <= regNum) && (regNum <= UNW_PPC_CR7) )
+		return true;
+	return false;
+}
+
+
+inline uint32_t Registers_ppc::getRegister(int regNum) const
+{
+	switch ( regNum ) {
+		case UNW_REG_IP:
+			return fRegisters.__srr0;
+		case UNW_REG_SP:
+			return fRegisters.__r1;
+		case UNW_PPC_R0:
+			return fRegisters.__r0;
+		case UNW_PPC_R1:
+			return fRegisters.__r1;
+		case UNW_PPC_R2:
+			return fRegisters.__r2;
+		case UNW_PPC_R3:
+			return fRegisters.__r3;
+		case UNW_PPC_R4:
+			return fRegisters.__r4;
+		case UNW_PPC_R5:
+			return fRegisters.__r5;
+		case UNW_PPC_R6:
+			return fRegisters.__r6;
+		case UNW_PPC_R7:
+			return fRegisters.__r7;
+		case UNW_PPC_R8:
+			return fRegisters.__r8;
+		case UNW_PPC_R9:
+			return fRegisters.__r9;
+		case UNW_PPC_R10:
+			return fRegisters.__r10;
+		case UNW_PPC_R11:
+			return fRegisters.__r11;
+		case UNW_PPC_R12:
+			return fRegisters.__r12;
+		case UNW_PPC_R13:
+			return fRegisters.__r13;
+		case UNW_PPC_R14:
+			return fRegisters.__r14;
+		case UNW_PPC_R15:
+			return fRegisters.__r15;
+		case UNW_PPC_R16:
+			return fRegisters.__r16;
+		case UNW_PPC_R17:
+			return fRegisters.__r17;
+		case UNW_PPC_R18:
+			return fRegisters.__r18;
+		case UNW_PPC_R19:
+			return fRegisters.__r19;
+		case UNW_PPC_R20:
+			return fRegisters.__r20;
+		case UNW_PPC_R21:
+			return fRegisters.__r21;
+		case UNW_PPC_R22:
+			return fRegisters.__r22;
+		case UNW_PPC_R23:
+			return fRegisters.__r23;
+		case UNW_PPC_R24:
+			return fRegisters.__r24;
+		case UNW_PPC_R25:
+			return fRegisters.__r25;
+		case UNW_PPC_R26:
+			return fRegisters.__r26;
+		case UNW_PPC_R27:
+			return fRegisters.__r27;
+		case UNW_PPC_R28:
+			return fRegisters.__r28;
+		case UNW_PPC_R29:
+			return fRegisters.__r29;
+		case UNW_PPC_R30:
+			return fRegisters.__r30;
+		case UNW_PPC_R31:
+			return fRegisters.__r31;
+		case UNW_PPC_LR:
+			return fRegisters.__lr;
+		case UNW_PPC_CR0:
+			return (fRegisters.__cr & 0xF0000000);
+		case UNW_PPC_CR1:
+			return (fRegisters.__cr & 0x0F000000);
+		case UNW_PPC_CR2:
+			return (fRegisters.__cr & 0x00F00000);
+		case UNW_PPC_CR3:
+			return (fRegisters.__cr & 0x000F0000);
+		case UNW_PPC_CR4:
+			return (fRegisters.__cr & 0x0000F000);
+		case UNW_PPC_CR5:
+			return (fRegisters.__cr & 0x00000F00);
+		case UNW_PPC_CR6:
+			return (fRegisters.__cr & 0x000000F0);
+		case UNW_PPC_CR7:
+			return (fRegisters.__cr & 0x0000000F);
+		case UNW_PPC_VRSAVE:
+			return fRegisters.__vrsave;
+	}
+	ABORT("unsupported ppc register");
+}
+
+
+inline void Registers_ppc::setRegister(int regNum, uint32_t value)
+{
+	//fprintf(stderr, "Registers_ppc::setRegister(%d, 0x%08X)\n", regNum, value);	
+	switch ( regNum ) {
+		case UNW_REG_IP:
+			fRegisters.__srr0 = value;
+			return;
+		case UNW_REG_SP:
+			fRegisters.__r1 = value;
+			return;
+		case UNW_PPC_R0:
+			fRegisters.__r0 = value;
+			return;
+		case UNW_PPC_R1:
+			fRegisters.__r1 = value;
+			return;
+		case UNW_PPC_R2:
+			fRegisters.__r2 = value;
+			return;
+		case UNW_PPC_R3:
+			fRegisters.__r3 = value;
+			return;
+		case UNW_PPC_R4:
+			fRegisters.__r4 = value;
+			return;
+		case UNW_PPC_R5:
+			fRegisters.__r5 = value;
+			return;
+		case UNW_PPC_R6:
+			fRegisters.__r6 = value;
+			return;
+		case UNW_PPC_R7:
+			fRegisters.__r7 = value;
+			return;
+		case UNW_PPC_R8:
+			fRegisters.__r8 = value;
+			return;
+		case UNW_PPC_R9:
+			fRegisters.__r9 = value;
+			return;
+		case UNW_PPC_R10:
+			fRegisters.__r10 = value;
+			return;
+		case UNW_PPC_R11:
+			fRegisters.__r11 = value;
+			return;
+		case UNW_PPC_R12:
+			fRegisters.__r12 = value;
+			return;
+		case UNW_PPC_R13:
+			fRegisters.__r13 = value;
+			return;
+		case UNW_PPC_R14:
+			fRegisters.__r14 = value;
+			return;
+		case UNW_PPC_R15:
+			fRegisters.__r15 = value;
+			return;
+		case UNW_PPC_R16:
+			fRegisters.__r16 = value;
+			return;
+		case UNW_PPC_R17:
+			fRegisters.__r17 = value;
+			return;
+		case UNW_PPC_R18:
+			fRegisters.__r18 = value;
+			return;
+		case UNW_PPC_R19:
+			fRegisters.__r19 = value;
+			return;
+		case UNW_PPC_R20:
+			fRegisters.__r20 = value;
+			return;
+		case UNW_PPC_R21:
+			fRegisters.__r21 = value;
+			return;
+		case UNW_PPC_R22:
+			fRegisters.__r22 = value;
+			return;
+		case UNW_PPC_R23:
+			fRegisters.__r23 = value;
+			return;
+		case UNW_PPC_R24:
+			fRegisters.__r24 = value;
+			return;
+		case UNW_PPC_R25:
+			fRegisters.__r25 = value;
+			return;
+		case UNW_PPC_R26:
+			fRegisters.__r26 = value;
+			return;
+		case UNW_PPC_R27:
+			fRegisters.__r27 = value;
+			return;
+		case UNW_PPC_R28:
+			fRegisters.__r28 = value;
+			return;
+		case UNW_PPC_R29:
+			fRegisters.__r29 = value;
+			return;
+		case UNW_PPC_R30:
+			fRegisters.__r30 = value;
+			return;
+		case UNW_PPC_R31:
+			fRegisters.__r31 = value;
+			return;
+		case UNW_PPC_MQ:
+			fRegisters.__mq = value;
+			return;
+		case UNW_PPC_LR:
+			fRegisters.__lr = value;
+			return;
+		case UNW_PPC_CTR:
+			fRegisters.__ctr = value;
+			return;
+		case UNW_PPC_CR0:
+			fRegisters.__cr &= 0x0FFFFFFF;
+			fRegisters.__cr |= (value & 0xF0000000);
+			return;
+		case UNW_PPC_CR1:
+			fRegisters.__cr &= 0xF0FFFFFF;
+			fRegisters.__cr |= (value & 0x0F000000);
+			return;
+		case UNW_PPC_CR2:
+			fRegisters.__cr &= 0xFF0FFFFF;
+			fRegisters.__cr |= (value & 0x00F00000);
+			return;
+		case UNW_PPC_CR3:
+			fRegisters.__cr &= 0xFFF0FFFF;
+			fRegisters.__cr |= (value & 0x000F0000);
+			return;
+		case UNW_PPC_CR4:
+			fRegisters.__cr &= 0xFFFF0FFF;
+			fRegisters.__cr |= (value & 0x0000F000);
+			return;
+		case UNW_PPC_CR5:
+			fRegisters.__cr &= 0xFFFFF0FF;
+			fRegisters.__cr |= (value & 0x00000F00);
+			return;
+		case UNW_PPC_CR6:
+			fRegisters.__cr &= 0xFFFFFF0F;
+			fRegisters.__cr |= (value & 0x000000F0);
+			return;
+		case UNW_PPC_CR7:
+			fRegisters.__cr &= 0xFFFFFFF0;
+			fRegisters.__cr |= (value & 0x0000000F);
+			return;
+		case UNW_PPC_VRSAVE:
+			fRegisters.__vrsave = value;
+			return;
+			// not saved
+			return;
+		case UNW_PPC_XER:
+			fRegisters.__xer = value;
+			return;
+		case UNW_PPC_AP:
+		case UNW_PPC_VSCR:
+		case UNW_PPC_SPEFSCR:
+			// not saved
+			return;
+	}
+	ABORT("unsupported ppc register");
+}
+
+inline bool Registers_ppc::validFloatRegister(int regNum) const
+{
+	if ( regNum < UNW_PPC_F0 )
+		return false;
+	if ( regNum > UNW_PPC_F31 )
+		return false;
+	return true;
+}
+
+inline double Registers_ppc::getFloatRegister(int regNum) const
+{
+	assert(validFloatRegister(regNum));
+	return fFloatRegisters.__fpregs[regNum-UNW_PPC_F0];
+}
+
+inline void Registers_ppc::setFloatRegister(int regNum, double value)
+{
+	//fprintf(stderr, "Registers_ppc::setFloatRegister(%d, %g))\n", regNum, value);
+	assert(validFloatRegister(regNum));
+	fFloatRegisters.__fpregs[regNum-UNW_PPC_F0] = value;
+}
+
+
+inline bool Registers_ppc::validVectorRegister(int regNum) const
+{
+	if ( regNum < UNW_PPC_V0 )
+		return false;
+	if ( regNum > UNW_PPC_V31 )
+		return false;
+	return true;
+}
+
+v128 Registers_ppc::getVectorRegister(int regNum) const
+{
+	assert(validVectorRegister(regNum));
+	v128 result = fVectorRegisters[regNum-UNW_PPC_V0];
+	//fprintf(stderr, "Registers_ppc::getVectorRegister(this=%p, %d) => <0x%08X, 0x%08X, 0x%08X, 0x%08X> \n", 
+	//		this, regNum, result.vec[0], result.vec[1], result.vec[2], result.vec[3]);
+	return result;
+}
+
+void Registers_ppc::setVectorRegister(int regNum, v128 value) 
+{
+	assert(validVectorRegister(regNum));
+	//fprintf(stderr, "Registers_ppc::setVectorRegister(this=%p, %d) <0x%08X, 0x%08X, 0x%08X, 0x%08X> => <0x%08X, 0x%08X, 0x%08X, 0x%08X> \n", 
+	//		this, regNum, fVectorRegisters[regNum-UNW_PPC_V0].vec[0], fVectorRegisters[regNum-UNW_PPC_V0].vec[1], fVectorRegisters[regNum-UNW_PPC_V0].vec[2], 
+	//			fVectorRegisters[regNum-UNW_PPC_V0].vec[3], value.vec[0], value.vec[1], value.vec[2], value.vec[3]);
+	fVectorRegisters[regNum-UNW_PPC_V0] = value;
+}
+
+
+inline const char* Registers_ppc::getRegisterName(int regNum)
+{
+	switch ( regNum ) {
+		case UNW_REG_IP:
+			return "ip";
+		case UNW_REG_SP:
+			return "sp";
+		case UNW_PPC_R0:
+			return "r0";
+		case UNW_PPC_R1:
+			return "r1";
+		case UNW_PPC_R2:
+			return "r2";
+		case UNW_PPC_R3:
+			return "r3";
+		case UNW_PPC_R4:
+			return "r4";
+		case UNW_PPC_R5:
+			return "r5";
+		case UNW_PPC_R6:
+			return "r6";
+		case UNW_PPC_R7:
+			return "r7";
+		case UNW_PPC_R8:
+			return "r8";
+		case UNW_PPC_R9:
+			return "r9";
+		case UNW_PPC_R10:
+			return "r10";
+		case UNW_PPC_R11:
+			return "r11";
+		case UNW_PPC_R12:
+			return "r12";
+		case UNW_PPC_R13:
+			return "r13";
+		case UNW_PPC_R14:
+			return "r14";
+		case UNW_PPC_R15:
+			return "r15";
+		case UNW_PPC_R16:
+			return "r16";
+		case UNW_PPC_R17:
+			return "r17";
+		case UNW_PPC_R18:
+			return "r18";
+		case UNW_PPC_R19:
+			return "r19";
+		case UNW_PPC_R20:
+			return "r20";
+		case UNW_PPC_R21:
+			return "r21";
+		case UNW_PPC_R22:
+			return "r22";
+		case UNW_PPC_R23:
+			return "r23";
+		case UNW_PPC_R24:
+			return "r24";
+		case UNW_PPC_R25:
+			return "r25";
+		case UNW_PPC_R26:
+			return "r26";
+		case UNW_PPC_R27:
+			return "r27";
+		case UNW_PPC_R28:
+			return "r28";
+		case UNW_PPC_R29:
+			return "r29";
+		case UNW_PPC_R30:
+			return "r30";
+		case UNW_PPC_R31:
+			return "r31";
+		case UNW_PPC_F0:
+			return "fp0";
+		case UNW_PPC_F1:
+			return "fp1";
+		case UNW_PPC_F2:
+			return "fp2";
+		case UNW_PPC_F3:
+			return "fp3";
+		case UNW_PPC_F4:
+			return "fp4";
+		case UNW_PPC_F5:
+			return "fp5";
+		case UNW_PPC_F6:
+			return "fp6";
+		case UNW_PPC_F7:
+			return "fp7";
+		case UNW_PPC_F8:
+			return "fp8";
+		case UNW_PPC_F9:
+			return "fp9";
+		case UNW_PPC_F10:
+			return "fp10";
+		case UNW_PPC_F11:
+			return "fp11";
+		case UNW_PPC_F12:
+			return "fp12";
+		case UNW_PPC_F13:
+			return "fp13";
+		case UNW_PPC_F14:
+			return "fp14";
+		case UNW_PPC_F15:
+			return "fp15";
+		case UNW_PPC_F16:
+			return "fp16";
+		case UNW_PPC_F17:
+			return "fp17";
+		case UNW_PPC_F18:
+			return "fp18";
+		case UNW_PPC_F19:
+			return "fp19";
+		case UNW_PPC_F20:
+			return "fp20";
+		case UNW_PPC_F21:
+			return "fp21";
+		case UNW_PPC_F22:
+			return "fp22";
+		case UNW_PPC_F23:
+			return "fp23";
+		case UNW_PPC_F24:
+			return "fp24";
+		case UNW_PPC_F25:
+			return "fp25";
+		case UNW_PPC_F26:
+			return "fp26";
+		case UNW_PPC_F27:
+			return "fp27";
+		case UNW_PPC_F28:
+			return "fp28";
+		case UNW_PPC_F29:
+			return "fp29";
+		case UNW_PPC_F30:
+			return "fp30";
+		case UNW_PPC_F31:
+			return "fp31";
+		case UNW_PPC_LR:
+			return "lr";
+		default:
+			return "unknown register";
+	}
+
+
+}
+
+
+} // namespace lldb_private 
+
+
+
+#endif // __REGISTERS_HPP__
+
+
+
+
diff --git a/source/Plugins/Process/Utility/libunwind/src/Registers.s b/source/Plugins/Process/Utility/libunwind/src/Registers.s
new file mode 100644
index 0000000..45dae3b
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/Registers.s
@@ -0,0 +1,261 @@
+
+
+#if __i386__
+	.text
+	.globl __ZN12lldb_private13Registers_x866jumptoEv
+	.private_extern __ZN12lldb_private13Registers_x866jumptoEv
+__ZN12lldb_private13Registers_x866jumptoEv:
+#
+# void lldb_private::Registers_x86::jumpto()
+#
+# On entry: 
+#	+					    +
+#   +-----------------------+
+#	+ thread_state pointer  +
+#   +-----------------------+
+#	+ return address	    +
+#   +-----------------------+   <-- SP
+#	+					    +
+	movl	 4(%esp), %eax
+	# set up eax and ret on new stack location
+	movl	28(%eax), %edx # edx holds new stack pointer
+	subl	$8,%edx
+	movl	%edx, 28(%eax)
+	movl	0(%eax), %ebx
+	movl	%ebx, 0(%edx)
+	movl	40(%eax), %ebx
+	movl	%ebx, 4(%edx)
+	# we now have ret and eax pushed onto where new stack will be
+	# restore all registers
+	movl	 4(%eax), %ebx
+	movl	 8(%eax), %ecx
+	movl	12(%eax), %edx
+	movl	16(%eax), %edi
+	movl	20(%eax), %esi
+	movl	24(%eax), %ebp
+	movl	28(%eax), %esp
+	# skip ss
+	# skip eflags
+	pop		%eax	# eax was already pushed on new stack
+	ret				# eip was already pushed on new stack
+	# skip cs
+	# skip ds
+	# skip es
+	# skip fs
+	# skip gs
+
+#elif __x86_64__
+
+	.text	
+	.globl __ZN12lldb_private16Registers_x86_646jumptoEv
+	.private_extern __ZN12lldb_private16Registers_x86_646jumptoEv
+__ZN12lldb_private16Registers_x86_646jumptoEv:
+#
+# void lldb_private::Registers_x86_64::jumpto()
+#
+# On entry, thread_state pointer is in rdi
+
+	movq	56(%rdi), %rax # rax holds new stack pointer
+	subq	$16, %rax
+	movq	%rax, 56(%rdi)
+	movq	32(%rdi), %rbx	# store new rdi on new stack
+	movq	%rbx, 0(%rax)
+	movq	128(%rdi), %rbx # store new rip on new stack
+	movq	%rbx, 8(%rax)
+	# restore all registers
+	movq	  0(%rdi), %rax
+	movq	  8(%rdi), %rbx
+	movq	 16(%rdi), %rcx
+	movq	 24(%rdi), %rdx
+	# restore rdi later
+	movq	 40(%rdi), %rsi
+	movq	 48(%rdi), %rbp
+	# restore rsp later
+	movq	 64(%rdi), %r8
+	movq	 72(%rdi), %r9
+	movq	 80(%rdi), %r10
+	movq	 88(%rdi), %r11
+	movq	 96(%rdi), %r12
+	movq	104(%rdi), %r13
+	movq	112(%rdi), %r14
+	movq	120(%rdi), %r15
+	# skip rflags
+	# skip cs
+	# skip fs
+	# skip gs
+	movq	56(%rdi), %rsp	# cut back rsp to new location
+	pop		%rdi			# rdi was saved here earlier
+	ret						# rip was saved here
+
+
+#elif __ppc__
+
+	.text	
+	.globl __ZN12lldb_private13Registers_ppc6jumptoEv
+	.private_extern __ZN12lldb_private13Registers_ppc6jumptoEv
+__ZN12lldb_private13Registers_ppc6jumptoEv:
+;
+; void lldb_private::Registers_ppc::jumpto()
+;
+; On entry:
+;	thread_state pointer is in r3
+;
+
+	; restore integral registerrs
+	; skip r0 for now
+	; skip r1 for now
+	lwz		 r2, 16(r3)
+	; skip r3 for now
+	; skip r4 for now
+	; skip r5 for now
+	lwz		 r6, 32(r3)
+	lwz		 r7, 36(r3)
+	lwz		 r8, 40(r3)
+	lwz		 r9, 44(r3)
+	lwz		r10, 48(r3)
+	lwz		r11, 52(r3)
+	lwz		r12, 56(r3)
+	lwz		r13, 60(r3)
+	lwz		r14, 64(r3)
+	lwz		r15, 68(r3)
+	lwz		r16, 72(r3)
+	lwz		r17, 76(r3)
+	lwz		r18, 80(r3)
+	lwz		r19, 84(r3)
+	lwz		r20, 88(r3)
+	lwz		r21, 92(r3)
+	lwz		r22, 96(r3)
+	lwz		r23,100(r3)
+	lwz		r24,104(r3)
+	lwz		r25,108(r3)
+	lwz		r26,112(r3)
+	lwz		r27,116(r3)
+	lwz		r28,120(r3)
+	lwz		r29,124(r3)
+	lwz		r30,128(r3)
+	lwz		r31,132(r3)
+	
+	; restore float registers
+	lfd		f0, 160(r3)
+	lfd		f1, 168(r3)
+	lfd		f2, 176(r3)
+	lfd		f3, 184(r3)
+	lfd		f4, 192(r3)
+	lfd		f5, 200(r3)
+	lfd		f6, 208(r3)
+	lfd		f7, 216(r3)
+	lfd		f8, 224(r3)
+	lfd		f9, 232(r3)
+	lfd		f10,240(r3)
+	lfd		f11,248(r3)
+	lfd		f12,256(r3)
+	lfd		f13,264(r3)
+	lfd		f14,272(r3)
+	lfd		f15,280(r3)
+	lfd		f16,288(r3)
+	lfd		f17,296(r3)
+	lfd		f18,304(r3)
+	lfd		f19,312(r3)
+	lfd		f20,320(r3)
+	lfd		f21,328(r3)
+	lfd		f22,336(r3)
+	lfd		f23,344(r3)
+	lfd		f24,352(r3)
+	lfd		f25,360(r3)
+	lfd		f26,368(r3)
+	lfd		f27,376(r3)
+	lfd		f28,384(r3)
+	lfd		f29,392(r3)
+	lfd		f30,400(r3)
+	lfd		f31,408(r3)
+ 	
+	; restore vector registers if any are in use
+	lwz		r5,156(r3)	; test VRsave
+	cmpwi	r5,0
+	beq		Lnovec
+	
+	subi	r4,r1,16
+	rlwinm	r4,r4,0,0,27	; mask low 4-bits
+	; r4 is now a 16-byte aligned pointer into the red zone
+	; the fVectorRegisters may not be 16-byte aligned so copy via red zone temp buffer
+	
+	
+#define LOAD_VECTOR_UNALIGNEDl(_index) \
+	andis.	r0,r5,(1<<(15-_index))	@\
+	beq		Ldone  ## _index 		@\
+	lwz		r0, 424+_index*16(r3)	@\
+	stw		r0, 0(r4)				@\
+	lwz		r0, 424+_index*16+4(r3)	@\
+	stw		r0, 4(r4)				@\
+	lwz		r0, 424+_index*16+8(r3)	@\
+	stw		r0, 8(r4)				@\
+	lwz		r0, 424+_index*16+12(r3)@\
+	stw		r0, 12(r4)				@\
+	lvx		v ## _index,0,r4		@\
+Ldone  ## _index:
+	
+#define LOAD_VECTOR_UNALIGNEDh(_index) \
+	andi.	r0,r5,(1<<(31-_index))	@\
+	beq		Ldone  ## _index		@\
+	lwz		r0, 424+_index*16(r3)	@\
+	stw		r0, 0(r4)				@\
+	lwz		r0, 424+_index*16+4(r3)	@\
+	stw		r0, 4(r4)				@\
+	lwz		r0, 424+_index*16+8(r3)	@\
+	stw		r0, 8(r4)				@\
+	lwz		r0, 424+_index*16+12(r3)@\
+	stw		r0, 12(r4)				@\
+	lvx		v ## _index,0,r4		@\
+	Ldone  ## _index:
+
+
+	LOAD_VECTOR_UNALIGNEDl(0)
+	LOAD_VECTOR_UNALIGNEDl(1)
+	LOAD_VECTOR_UNALIGNEDl(2)
+	LOAD_VECTOR_UNALIGNEDl(3)
+	LOAD_VECTOR_UNALIGNEDl(4)
+	LOAD_VECTOR_UNALIGNEDl(5)
+	LOAD_VECTOR_UNALIGNEDl(6)
+	LOAD_VECTOR_UNALIGNEDl(7)
+	LOAD_VECTOR_UNALIGNEDl(8)
+	LOAD_VECTOR_UNALIGNEDl(9)
+	LOAD_VECTOR_UNALIGNEDl(10)
+	LOAD_VECTOR_UNALIGNEDl(11)
+	LOAD_VECTOR_UNALIGNEDl(12)
+	LOAD_VECTOR_UNALIGNEDl(13)
+	LOAD_VECTOR_UNALIGNEDl(14)
+	LOAD_VECTOR_UNALIGNEDl(15)
+	LOAD_VECTOR_UNALIGNEDh(16)
+	LOAD_VECTOR_UNALIGNEDh(17)
+	LOAD_VECTOR_UNALIGNEDh(18)
+	LOAD_VECTOR_UNALIGNEDh(19)
+	LOAD_VECTOR_UNALIGNEDh(20)
+	LOAD_VECTOR_UNALIGNEDh(21)
+	LOAD_VECTOR_UNALIGNEDh(22)
+	LOAD_VECTOR_UNALIGNEDh(23)
+	LOAD_VECTOR_UNALIGNEDh(24)
+	LOAD_VECTOR_UNALIGNEDh(25)
+	LOAD_VECTOR_UNALIGNEDh(26)
+	LOAD_VECTOR_UNALIGNEDh(27)
+	LOAD_VECTOR_UNALIGNEDh(28)
+	LOAD_VECTOR_UNALIGNEDh(29)
+	LOAD_VECTOR_UNALIGNEDh(30)
+	LOAD_VECTOR_UNALIGNEDh(31)
+
+Lnovec:		
+	lwz		r0, 136(r3) ; __cr
+	mtocrf	255,r0
+	lwz		r0, 148(r3) ; __ctr
+	mtctr	r0
+	lwz		r0, 0(r3)	; __ssr0
+	mtctr	r0
+	lwz		r0, 8(r3)   ; do r0 now
+	lwz		r5,28(r3)	; do r5 now
+	lwz		r4,24(r3)	; do r4 now
+	lwz		r1,12(r3)	; do sp now
+	lwz		r3,20(r3)   ; do r3 last
+	bctr
+
+
+#endif
+
diff --git a/source/Plugins/Process/Utility/libunwind/src/RemoteDebuggerDummyUnwinder.hpp b/source/Plugins/Process/Utility/libunwind/src/RemoteDebuggerDummyUnwinder.hpp
new file mode 100644
index 0000000..1db3faf
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/RemoteDebuggerDummyUnwinder.hpp
@@ -0,0 +1,88 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- RemoteDebuggerDummyUnwinder.hpp -------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Code to unwind past a debugger's dummy frame inserted when it does an
+// inferior function call.
+// In this case we'll need to get the saved register context from the debugger -
+// it may be in the debugger's local memory or it may be saved in a nonstandard
+// location in the inferior process' memory.
+
+#ifndef __REMOTE_DEBUGGER_DUMMY_UNWINDER_HPP__
+#define __REMOTE_DEBUGGER_DUMMY_UNWINDER_HPP__
+
+#if defined (SUPPORT_REMOTE_UNWINDING)
+
+#include "libunwind.h"
+#include "Registers.hpp"
+#include "AddressSpace.hpp"
+#include "RemoteRegisterMap.hpp"
+#include "RemoteProcInfo.hpp"
+
+namespace lldb_private
+{
+
+template <typename A>
+int stepOutOfDebuggerDummyFrame (A& addressSpace, Registers_x86_64& registers,
+                                 RemoteProcInfo *procinfo, uint64_t ip, 
+                                uint64_t sp, void* arg) 
+{
+    Registers_x86_64 newRegisters(registers);
+    RemoteRegisterMap *rmap = addressSpace.getRemoteProcInfo()->getRegisterMap();
+    unw_word_t regv;
+    for (int i = UNW_X86_64_RAX; i <= UNW_X86_64_R15; i++) {
+        int driver_regnum;
+        if (!rmap->unwind_regno_to_caller_regno (i, driver_regnum))
+            continue;
+        if (addressSpace.accessors()->access_reg_inf_func_call (procinfo->wrap(), ip, sp, driver_regnum, &regv, 0, arg))
+            newRegisters.setRegister(i, regv);
+    }
+    if (!addressSpace.accessors()->access_reg_inf_func_call (procinfo->wrap(), ip, sp, rmap->caller_regno_for_ip(), &regv, 0, arg))
+        return UNW_EUNSPEC;
+    newRegisters.setIP (regv);
+    registers = newRegisters;
+    return UNW_STEP_SUCCESS;
+}
+
+template <typename A>
+int stepOutOfDebuggerDummyFrame (A& addressSpace, Registers_x86& registers,
+                                 RemoteProcInfo *procinfo, uint64_t ip, 
+                                uint64_t sp, void* arg)
+{
+    Registers_x86 newRegisters(registers);
+    RemoteRegisterMap *rmap = addressSpace.getRemoteProcInfo()->getRegisterMap();
+    unw_word_t regv;
+    for (int i = UNW_X86_EAX; i <= UNW_X86_EDI; i++) {
+        int driver_regnum;
+        if (!rmap->unwind_regno_to_caller_regno (i, driver_regnum))
+            continue;
+        if (addressSpace.accessors()->access_reg_inf_func_call (procinfo->wrap(), ip, sp, driver_regnum, &regv, 0, arg))
+            newRegisters.setRegister(i, regv);
+    }
+    if (!addressSpace.accessors()->access_reg_inf_func_call (procinfo->wrap(), ip, sp, rmap->caller_regno_for_ip(), &regv, 0, arg))
+        return UNW_EUNSPEC;
+    newRegisters.setIP (regv);
+    registers = newRegisters;
+    return UNW_STEP_SUCCESS;
+}
+
+template <typename A>
+int stepOutOfDebuggerDummyFrame (A& addressSpace, Registers_ppc& registers,
+                                 uint64_t ip, uint64_t sp) 
+{
+    ABORT ("stepping out of a debugger dummy frame not supported on ppc");
+    return UNW_EUNSPEC;
+}
+
+}; // namespace lldb_private
+
+#endif // SUPPORT_REMOTE_UNWINDING
+
+#endif // __REMOTE_DEBUGGER_DUMMY_UNWINDER_HPP__
+
diff --git a/source/Plugins/Process/Utility/libunwind/src/RemoteProcInfo.hpp b/source/Plugins/Process/Utility/libunwind/src/RemoteProcInfo.hpp
new file mode 100644
index 0000000..3640dc6
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/RemoteProcInfo.hpp
@@ -0,0 +1,977 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- RemoteProcInfo.hpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//  This file defines the primary object created when unw_create_addr_space()
+//  is called.  This object tracks the list of known images in memory 
+//  (dylibs, bundles, etc), it maintains a link to a RemoteRegisterMap for this
+//  architecture, it caches the remote process memory in a local store and all
+//  read/writes are filtered through its accessors which will use the memory
+//  caches.  It maintains a logging level set by the driver program and puts
+//  timing/debug messages out on a FILE* provided to it.
+
+//  RemoteProcInfo is not specific to any particular unwind so it does not
+//  maintain an "arg" argument (an opaque pointer that the driver program uses
+//  to track the process/thread being unwound).  
+
+#ifndef __REMOTE_PROC_INFO_HPP__
+#define __REMOTE_PROC_INFO_HPP__
+
+#if defined (SUPPORT_REMOTE_UNWINDING)
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <stdarg.h>
+#include <sys/time.h>
+#include <mach-o/loader.h>
+#include <mach-o/getsect.h>
+#include <mach/ppc/thread_status.h>
+#include <mach/i386/thread_status.h>
+#include <Availability.h>
+
+#include <map>
+#include <vector>
+#include <algorithm>
+
+#include "FileAbstraction.hpp"
+#include "libunwind.h"
+#include "InternalMacros.h"
+#include "dwarf2.h"
+#include "RemoteUnwindProfile.h"
+#include "Registers.hpp"
+#include "RemoteRegisterMap.hpp"
+
+namespace lldb_private
+{
+class RemoteProcInfo;
+
+///
+/// unw_addr_space_remote is the concrete instance that a unw_addr_space_t points to when examining
+/// a remote process.
+///
+struct unw_addr_space_remote
+{
+   enum unw_as_type type;      // should always be UNW_REMOTE
+   RemoteProcInfo* ras;
+};
+
+class RemoteMemoryBlob
+{
+public:
+  typedef void (*free_callback_with_arg)(void *, void*);
+  typedef void (*free_callback)(void *);
+
+  /* This object is constructed with a callback to free the memory;
+     that callback takes a pointer to the memory region and optionally
+     takes an additional argument -- the "void* arg" passed around for
+     remote unwinds, in case the driver program allocated this e.g. with
+     mach_vm_read, and needs the token to vm_deallocate it.  */
+
+  RemoteMemoryBlob (uint8_t *buf, free_callback_with_arg to_free, 
+                 uint64_t startaddr, uint64_t len, uint64_t mh, void *arg) : 
+                    fBuf(buf), fToFreeWithArg(to_free), fToFree(NULL), 
+                    fStartAddr(startaddr), fLen(len), fMachHeader(mh),
+                    fArg(arg) { }
+  RemoteMemoryBlob (uint8_t *buf, free_callback to_free, uint64_t startaddr, 
+                 uint64_t len, uint64_t mh, void *arg) : 
+                    fBuf(buf), fToFree(to_free), fToFreeWithArg(NULL), 
+                    fStartAddr(startaddr), fLen(len), fMachHeader(mh),
+                    fArg(NULL) { }
+
+  // the following is to create a dummy RMB object for lower_bound's use in
+  // searching.
+  RemoteMemoryBlob (uint64_t startaddr) : fStartAddr(startaddr), fToFree(NULL),
+                    fBuf(NULL), fToFreeWithArg(NULL), fArg(NULL), fMachHeader(-1),
+                    fLen(0) { }
+  ~RemoteMemoryBlob () {
+    if (fToFreeWithArg)
+      fToFreeWithArg(fBuf, fArg);
+    else if (fToFree)
+      fToFree(fBuf);
+  }
+  bool contains_addr (uint64_t addr) {
+    if (fStartAddr <= addr &&  addr < fStartAddr + fLen)
+      return true;
+    else
+      return false;
+  }
+  uint8_t *get_blob_range (uint64_t remote_process_addr, int len) {
+    if (this->contains_addr (remote_process_addr) == false)
+      return NULL;
+    if (this->contains_addr (remote_process_addr + len) == false)
+      return NULL;
+    return fBuf + (remote_process_addr - fStartAddr);
+  }
+  uint64_t getMh ()       const { return fMachHeader; }
+  uint64_t getStartAddr() const { return fStartAddr; }
+  uint64_t getLength()    const { return fLen; }
+private:
+  uint8_t *fBuf;
+  free_callback fToFree;
+  free_callback_with_arg fToFreeWithArg;
+  uint64_t fStartAddr;
+  uint64_t fLen;
+  uint64_t fMachHeader;
+  void    *fArg;
+};
+
+inline bool operator<(const RemoteMemoryBlob &b1, const RemoteMemoryBlob &b2) {
+    if (b1.getStartAddr() < b2.getStartAddr())
+        return true;
+    else
+        return false;
+}
+
+// One of these for each image in memory (executable, dylib, bundle, etc)
+
+struct RemoteImageEntry
+{
+  RemoteImageEntry () : mach_header(0), text_start(0), text_end(0), eh_frame_start(0), eh_frame_len(0), compact_unwind_info_start(0), compact_unwind_info_len(0) { }
+  ~RemoteImageEntry () {
+      std::map<uint64_t, RemoteUnwindProfile *>::iterator i;
+      for (i = profiles.begin(); i != profiles.end(); ++i)
+        delete i->second;
+  }
+  uint64_t mach_header;
+  uint64_t text_start;
+  uint64_t text_end;
+  uint64_t eh_frame_start;
+  uint64_t eh_frame_len;
+  uint64_t compact_unwind_info_start;
+  uint64_t compact_unwind_info_len;
+
+  // unwind profiles created for thsi binary image so far,
+  // key is the start address of the profile.
+  std::map<uint64_t, RemoteUnwindProfile *> profiles;
+
+  // a list of function address bounds for this binary image -
+  // end addresses should be accurate and not inferred from potentially
+  // incomplete start-address data (e.g. nlist records).
+  std::vector<FuncBounds> func_bounds;
+};
+
+class RemoteImages
+{
+public:
+    RemoteImages (unw_targettype_t targarch) : fTargetArch(targarch) { }
+    ~RemoteImages ();
+    void removeAllImageProfiles();
+    void removeOneImageProfiles(uint64_t mh);
+    RemoteImageEntry *remoteEntryForTextAddr (uint64_t pc);
+    bool addFuncBounds (uint64_t mh, std::vector<FuncBounds> &startAddrs);
+    bool haveFuncBounds (uint64_t mh);
+    bool findFuncBounds (uint32_t pc, uint32_t &startAddr, uint32_t &endAddr);
+    bool findFuncBounds (uint64_t pc, uint64_t &startAddr, uint64_t &endAddr);
+    void addImage (uint64_t mh, uint64_t text_start, uint64_t text_end, uint64_t eh_frame, uint64_t eh_frame_len, uint64_t compact_unwind_start, uint64_t compact_unwind_len);
+    bool addProfile (RemoteProcInfo* procinfo, unw_accessors_t *acc, unw_addr_space_t as, uint64_t start, uint64_t end, void *arg);
+    RemoteUnwindProfile* findProfileByTextAddr (uint64_t pc);
+    void addMemBlob (RemoteMemoryBlob *blob);
+    uint8_t *getMemBlobMemory (uint64_t addr, int len);
+private:
+    RemoteImages();
+    std::map<uint64_t, RemoteImageEntry> fImages;
+    std::vector<RemoteMemoryBlob *> fMemBlobs;
+    unw_targettype_t fTargetArch;
+};
+
+RemoteImages::~RemoteImages () {
+    std::map<uint64_t, std::vector<RemoteMemoryBlob *> >::iterator i;
+    std::vector<RemoteMemoryBlob *>::iterator j;
+    for (j = fMemBlobs.begin(); j != fMemBlobs.end(); ++j) {
+        delete *j;
+    }
+    fMemBlobs.erase(fMemBlobs.begin(), fMemBlobs.end());
+}
+
+void RemoteImages::removeAllImageProfiles() {
+    fImages.erase(fImages.begin(), fImages.end());
+    std::vector<RemoteMemoryBlob *>::iterator j;
+    for (j = fMemBlobs.begin(); j != fMemBlobs.end(); ++j)
+        delete *j;
+    fMemBlobs.erase(fMemBlobs.begin(), fMemBlobs.end());
+}
+
+void RemoteImages::removeOneImageProfiles(uint64_t mh) {
+    std::map<uint64_t, RemoteImageEntry>::iterator i;
+    i = fImages.find(mh);
+    if (i != fImages.end())
+        fImages.erase(i);
+
+    std::vector<RemoteMemoryBlob *>::iterator j;
+    for (j = fMemBlobs.begin(); j != fMemBlobs.end(); ++j) {
+        if ((*j)->getMh() == mh) {
+            delete *j;
+            break; 
+        }
+    }
+    if (j != fMemBlobs.end())
+        fMemBlobs.erase(j);
+}
+
+RemoteImageEntry *RemoteImages::remoteEntryForTextAddr (uint64_t pc) {
+    std::map<uint64_t, RemoteImageEntry>::iterator i = fImages.lower_bound (pc);
+    if (i == fImages.begin() && i == fImages.end())
+        return NULL;
+    if (i == fImages.end()) {
+        --i;
+    } else {
+        if (i != fImages.begin() && i->first != pc)
+          --i;
+    }
+    if (i->second.text_start <= pc && i->second.text_end > pc)
+      {
+        return &(i->second);
+      }
+    else
+      {
+        return NULL;
+      }
+}
+
+bool RemoteImages::addFuncBounds (uint64_t mh, std::vector<FuncBounds> &startAddrs) {
+    RemoteImageEntry *img = NULL;
+    std::map<uint64_t, RemoteImageEntry>::iterator i = fImages.find (mh);
+    if (i == fImages.end())
+        return false;
+    img = &i->second;
+    img->func_bounds = startAddrs;
+    std::sort(img->func_bounds.begin(), img->func_bounds.end());
+    return true;
+}
+
+bool RemoteImages::haveFuncBounds (uint64_t mh) {
+    RemoteImageEntry *img = NULL;
+    std::map<uint64_t, RemoteImageEntry>::iterator i = fImages.find (mh);
+    if (i == fImages.end())
+        return false;
+    img = &i->second;
+    if (img->func_bounds.size() > 0)
+        return true;
+    return false;
+}
+
+bool RemoteImages::findFuncBounds (uint64_t pc, uint64_t &startAddr, uint64_t &endAddr) {
+    RemoteImageEntry *img = NULL;
+    startAddr = endAddr = 0;
+    std::map<uint64_t, RemoteImageEntry>::iterator i = fImages.lower_bound (pc);
+    if (i == fImages.begin() && i == fImages.end())
+        return false;
+    if (i == fImages.end()) {
+        --i;
+    } else {
+        if (i != fImages.begin() && i->first != pc)
+            --i;
+    }
+    if (i->second.text_start <= pc && i->second.text_end > pc)
+      {
+        img = &i->second;
+      }
+    else
+      return false;
+    std::vector<FuncBounds>::iterator j;
+    j = std::lower_bound(img->func_bounds.begin(), img->func_bounds.end(), FuncBounds (pc, pc));
+    if (j == img->func_bounds.begin() && j == img->func_bounds.end())
+        return false;
+    if (j == img->func_bounds.end()) {
+        --j;
+    } else {
+        if (j != img->func_bounds.begin() && j->fStart != pc)
+            --j;
+    }
+    if (j->fStart <= pc && j->fEnd > pc) {
+        startAddr = j->fStart;
+        endAddr = j->fEnd;
+        return true;
+    }
+    return false;
+}
+
+// Add 32-bit version of findFuncBounds so we can avoid templatizing all of these functions
+// just to handle 64 and 32 bit unwinds.
+
+bool RemoteImages::findFuncBounds (uint32_t pc, uint32_t &startAddr, uint32_t &endAddr) {
+    uint64_t big_startAddr = startAddr;
+    uint64_t big_endAddr = endAddr;
+    bool ret;
+    ret = findFuncBounds (pc, big_startAddr, big_endAddr);
+    startAddr = (uint32_t) big_startAddr & 0xffffffff;
+    endAddr = (uint32_t) big_endAddr & 0xffffffff;
+    return ret;
+}
+
+// Make sure we don't cache the same memory range more than once
+// I'm not checking the length of the blobs to check for overlap -
+// as this is used today, the only duplication will be with the same
+// start address.
+
+void RemoteImages::addMemBlob (RemoteMemoryBlob *blob) { 
+    std::vector<RemoteMemoryBlob *>::iterator i;
+    for (i = fMemBlobs.begin(); i != fMemBlobs.end(); ++i) {
+        if (blob->getStartAddr() == (*i)->getStartAddr())
+            return;
+    }
+    fMemBlobs.push_back(blob); 
+    std::sort(fMemBlobs.begin(), fMemBlobs.end());
+}
+
+uint8_t *RemoteImages::getMemBlobMemory (uint64_t addr, int len) {
+    uint8_t *res = NULL;
+    std::vector<RemoteMemoryBlob *>::iterator j;
+    RemoteMemoryBlob *searchobj = new RemoteMemoryBlob(addr);
+    j = std::lower_bound (fMemBlobs.begin(), fMemBlobs.end(), searchobj);
+    delete searchobj;
+    if (j == fMemBlobs.end() && j == fMemBlobs.begin())
+        return NULL;
+    if (j == fMemBlobs.end()) {
+        --j;
+    } else {
+        if (j != fMemBlobs.begin() && (*j)->getStartAddr() != addr)
+            --j;
+    }
+    res = (*j)->get_blob_range (addr, len);
+    if (res != NULL)
+        return res;
+    for (j = fMemBlobs.begin(); j != fMemBlobs.end(); ++j) {
+        res = (*j)->get_blob_range (addr, len);
+        if (res != NULL)
+            break;
+    }
+    return res;
+}
+
+void RemoteImages::addImage (uint64_t mh, uint64_t text_start, 
+                             uint64_t text_end, uint64_t eh_frame, 
+                             uint64_t eh_frame_len, 
+                             uint64_t compact_unwind_start,
+                             uint64_t compact_unwind_len) {
+    struct RemoteImageEntry img;
+    img.mach_header = mh;
+    img.text_start = text_start;
+    img.text_end = text_end;
+    img.eh_frame_start = eh_frame;
+    img.eh_frame_len = eh_frame_len;
+    img.compact_unwind_info_start = compact_unwind_start;
+    img.compact_unwind_info_len = compact_unwind_len;
+    fImages[mh] = img;
+}
+
+// The binary image for this start/end address must already be present
+bool RemoteImages::addProfile (RemoteProcInfo* procinfo, unw_accessors_t *acc, unw_addr_space_t as, uint64_t start, uint64_t end, void *arg) {
+    RemoteImageEntry *img = NULL;
+    std::map<uint64_t, RemoteImageEntry>::iterator i = fImages.lower_bound (start);
+    if (i == fImages.begin() && i == fImages.end())
+        return false;
+    if (i == fImages.end()) {
+        --i;
+    } else {
+        if (i != fImages.begin() && i->first != start) {
+            --i;
+        }
+    }
+    if (i->second.text_start <= start && i->second.text_end > start)
+      {
+        img = &i->second;
+      }
+    else
+      return false;
+    RemoteUnwindProfile* profile = new RemoteUnwindProfile;
+    if (AssemblyParse (procinfo, acc, as, start, end, *profile, arg)) {
+        img->profiles[start] = profile;
+        return true;
+    }
+    return false;
+}
+
+RemoteUnwindProfile* RemoteImages::findProfileByTextAddr (uint64_t pc) {
+    RemoteImageEntry *img = NULL;
+    std::map<uint64_t, RemoteImageEntry>::iterator i = fImages.lower_bound (pc);
+    if (i == fImages.begin() && i == fImages.end())
+        return NULL;
+    if (i == fImages.end()) {
+        --i;
+    } else {
+        if (i != fImages.begin() && i->first != pc)
+          --i;
+    }
+    if (i->second.text_start <= pc && i->second.text_end > pc)
+      {
+        img = &i->second;
+      }
+    else
+      return false;
+    std::map<uint64_t, RemoteUnwindProfile *>::iterator j;
+    j = img->profiles.lower_bound (pc);
+    if (j == img->profiles.begin() && j == img->profiles.end())
+        return NULL;
+    if (j == img->profiles.end()) {
+        --j;
+    } else {
+        if (j != img->profiles.begin() && j->first != pc)
+          --j;
+    }
+    if (j->second->fStart <= pc && j->second->fEnd > pc)
+      {
+        return j->second;
+      }
+    return NULL;
+}
+
+///
+/// RemoteProcInfo is used as a template parameter to UnwindCursor when 
+/// unwinding a thread that has a custom set of accessors.  It calls the 
+/// custom accessors for all data.
+///
+class RemoteProcInfo
+{
+public:
+
+// libunwind documentation specifies that unw_create_addr_space defaults to 
+//  UNW_CACHE_NONE but that's going to work very poorly for us so we're 
+// defaulting to UNW_CACHE_GLOBAL.
+
+    RemoteProcInfo(unw_accessors_t* accessors, unw_targettype_t targarch) : 
+                    fAccessors(*accessors), fCachingPolicy(UNW_CACHE_GLOBAL), 
+                    fTargetArch(targarch), fImages(targarch), fLogging(NULL), 
+                    fLogLevel(UNW_LOG_LEVEL_NONE)
+    {
+        fWrapper.type = UNW_REMOTE;
+        fWrapper.ras = this;
+        fRemoteRegisterMap = new RemoteRegisterMap(accessors, targarch);
+        if (fTargetArch == UNW_TARGET_X86_64 || fTargetArch == UNW_TARGET_I386
+            || fTargetArch == UNW_TARGET_ARM)
+            fLittleEndian = true;
+        else
+            fLittleEndian = false;
+    }
+
+    ~RemoteProcInfo () {
+        delete fRemoteRegisterMap;
+    }
+
+    bool haveProfile (uint64_t pc) {
+        if (fImages.findProfileByTextAddr (pc))
+          return true;
+        else
+          return false;
+    }
+
+    // returns NULL if profile does not yet exist.
+    RemoteUnwindProfile* findProfile (uint64_t pc) {
+        return fImages.findProfileByTextAddr (pc);
+    }
+
+    // returns NULL if the binary image is not yet added.
+    bool addProfile (unw_accessors_t *acc, unw_addr_space_t as, uint64_t start, uint64_t end, void *arg) {
+        if (fImages.addProfile (this, acc, as, start, end, arg))
+          return true;
+        else
+          return false;
+    }
+
+    bool haveImageEntry (uint64_t pc, void *arg);
+
+    bool getImageAddresses (uint64_t pc, uint64_t &mh, uint64_t &text_start, uint64_t &text_end, 
+                            uint64_t &eh_frame_start, uint64_t &eh_frame_len, uint64_t &compact_unwind_start, 
+                            void *arg);
+    bool getImageAddresses (uint64_t pc, uint32_t &mh, uint32_t &text_start, uint32_t &text_end, 
+                            uint32_t &eh_frame_start, uint32_t &eh_frame_len, uint32_t &compact_unwind_start, 
+                            void *arg);
+
+    bool addFuncBounds (uint64_t mh, std::vector<FuncBounds> &startAddrs)    { return fImages.addFuncBounds (mh, startAddrs); }
+    bool haveFuncBounds (uint64_t mh)                                        { return fImages.haveFuncBounds (mh); }
+    bool findStartAddr (uint64_t pc, uint32_t &startAddr, uint32_t &endAddr) { return fImages.findFuncBounds (pc, startAddr, endAddr); }
+    bool findStartAddr (uint64_t pc, uint64_t &startAddr, uint64_t &endAddr) { return fImages.findFuncBounds (pc, startAddr, endAddr); }
+    uint8_t *getMemBlobMemory (uint64_t addr, int len) { return fImages.getMemBlobMemory (addr, len); }
+
+
+    // Functions to pull memory from the target into the debugger.
+
+    int getBytes(uint64_t addr, uint64_t extent, uint8_t* buf, void* arg)
+    {
+        int err = readRaw(addr, extent, buf, arg);
+
+        if(err)
+            return 0;
+
+        return 1;
+    }
+
+#define DECLARE_INT_ACCESSOR(bits)                                              \
+    uint##bits##_t get##bits(uint64_t addr, void* arg)                            \
+    {                                                                           \
+        uint##bits##_t ret;                                                     \
+        int err = readRaw(addr, (unw_word_t)(bits / 8), (uint8_t*)&ret, arg);   \
+                                                                                \
+        if(err)                                                                 \
+            ABORT("Invalid memory access in the target");                       \
+                                                                                \
+        return ret;                                                             \
+    }
+    DECLARE_INT_ACCESSOR(8)
+    DECLARE_INT_ACCESSOR(16)
+    DECLARE_INT_ACCESSOR(32)
+    DECLARE_INT_ACCESSOR(64)
+#undef DECLARE_INT_ACCESSOR
+
+// 'err' is set to 0 if there were no errors reading this
+// memory.  Non-zero values indicate that the memory was not
+// read successfully.  This method should be preferred over the
+// method above which asserts on failure.
+
+#define DECLARE_INT_ACCESSOR_ERR(bits)                                          \
+    uint##bits##_t get##bits(uint64_t addr, int &err, void* arg)                  \
+    {                                                                           \
+        uint##bits##_t ret;                                                     \
+        err = readRaw(addr, (unw_word_t)(bits / 8), (uint8_t*)&ret, arg);       \
+                                                                                \
+        return ret;                                                             \
+    }
+    DECLARE_INT_ACCESSOR_ERR(8)
+    DECLARE_INT_ACCESSOR_ERR(16)
+    DECLARE_INT_ACCESSOR_ERR(32)
+    DECLARE_INT_ACCESSOR_ERR(64)
+#undef DECLARE_INT_ACCESSOR_ERR
+
+    double getDouble(uint64_t addr, void* arg)
+    {
+        double ret;
+        int err = readRaw(addr, (unw_word_t)(sizeof(ret) / 8), (uint8_t*)&ret, arg);
+        if(err)
+            ABORT("Invalid memory access in the target");
+        return ret;
+    }
+
+    v128 getVector(uint64_t addr, void* arg)
+    {
+        v128 ret;
+        int err = readRaw(addr, (unw_word_t)(sizeof(ret) / 8), (uint8_t*)&ret, arg);
+        if(err)
+            ABORT("Invalid memory access in the target");
+        return ret;
+    }
+
+    // Pull an unsigned LEB128 from the target into the debugger as a uint64_t.
+    uint64_t getULEB128(uint64_t& addr, uint64_t end, void* arg)
+    {
+        uint64_t lAddr = addr;
+        uint64_t ret = 0;
+        uint8_t shift = 0;
+        uint64_t byte;
+        do {
+            if(lAddr == end)
+                ABORT("Truncated LEB128 number in the target");
+
+            byte = (uint64_t)get8(lAddr, arg);
+            lAddr++;
+
+            if(((shift == 63) && (byte > 0x01)) || (shift > 63))
+                ABORT("LEB128 number is larger than is locally representible");
+
+            ret |= ((byte & 0x7f) << shift);
+            shift += 7;
+        } while((byte & 0x80) == 0x80);
+        addr = lAddr;
+        return ret;
+    }
+
+    // Pull an unsigned LEB128 from the target into the debugger as a uint64_t.
+    uint64_t getULEB128(uint32_t& addr, uint32_t end, void* arg)
+    {
+        uint32_t lAddr = addr;
+        uint64_t ret = 0;
+        uint8_t shift = 0;
+        uint64_t byte;
+        do {
+            if(lAddr == end)
+                ABORT("Truncated LEB128 number in the target");
+
+            byte = (uint64_t)get8(lAddr, arg);
+            lAddr++;
+
+            if(((shift == 63) && (byte > 0x01)) || (shift > 63))
+                ABORT("LEB128 number is larger than is locally representible");
+
+            ret |= ((byte & 0x7f) << shift);
+            shift += 7;
+        } while((byte & 0x80) == 0x80);
+        addr = lAddr;
+        return ret;
+    }
+
+
+    // Pull a signed LEB128 from the target into the debugger as a uint64_t.
+    int64_t getSLEB128(uint64_t& addr, uint64_t end, void* arg)
+    {
+        uint64_t lAddr = addr;
+        uint64_t ret = 0;
+        uint8_t shift = 0;
+        uint64_t byte;
+        do {
+            if(lAddr == end)
+                ABORT("Truncated LEB128 number in the target");
+            byte = (uint64_t)get8(lAddr, arg);
+            lAddr++;
+            if(((shift == 63) && (byte > 0x01)) || (shift > 63))
+                ABORT("LEB128 number is larger than is locally representible");
+            ret |= ((byte & 0x7f) << shift);
+            shift += 7;
+        } while((byte & 0x80) == 0x80);
+        // Sign-extend
+        if((shift < (sizeof(int64_t) * 8)) && (byte & 0x40))
+            ret |= -(1 << shift);
+        addr = lAddr;
+        return ret;
+    }
+
+    // Pull a signed LEB128 from the target into the debugger as a uint64_t.
+    int64_t getSLEB128(uint32_t& addr, uint32_t end, void* arg)
+    {
+        uint32_t lAddr = addr;
+        uint64_t ret = 0;
+        uint8_t shift = 0;
+        uint64_t byte;
+        do {
+            if(lAddr == end)
+                ABORT("Truncated LEB128 number in the target");
+            byte = (uint64_t)get8(lAddr, arg);
+            lAddr++;
+            if(((shift == 63) && (byte > 0x01)) || (shift > 63))
+                ABORT("LEB128 number is larger than is locally representible");
+            ret |= ((byte & 0x7f) << shift);
+            shift += 7;
+        } while((byte & 0x80) == 0x80);
+        // Sign-extend
+        if((shift < (sizeof(int64_t) * 8)) && (byte & 0x40))
+            ret |= -(1 << shift);
+        addr = lAddr;
+        return ret;
+    }
+
+
+    uint64_t getP (uint64_t addr, void *arg) {
+        switch (fTargetArch) {
+            case UNW_TARGET_X86_64:
+              return get64(addr, arg);
+              break;
+            case UNW_TARGET_I386:
+              return get32(addr, arg);
+              break;
+        }
+        ABORT("Unknown target architecture.");
+        return 0;
+    }
+
+    uint64_t getP (uint64_t addr, int& err, void *arg) {
+        switch (fTargetArch) {
+            case UNW_TARGET_X86_64:
+              return get64(addr, err, arg);
+              break;
+            case UNW_TARGET_I386:
+              return get32(addr, err, arg);
+              break;
+        }
+        ABORT("Unknown target architecture.");
+        return 0;
+    }
+
+    bool findFunctionName(uint64_t addr, char *buf, size_t bufLen, unw_word_t *offset, void* arg);
+    bool findFunctionBounds(uint64_t addr, uint64_t& low, uint64_t& high, void* arg);
+    int setCachingPolicy(unw_caching_policy_t policy);
+
+    void setLoggingLevel(FILE *f, unw_log_level_t level);
+    void logInfo(const char *fmt, ...);
+    void logAPI(const char *fmt, ...);
+    void logVerbose(const char *fmt, ...);
+    void logDebug(const char *fmt, ...);
+    struct timeval *timestamp_start ();
+    void timestamp_stop (struct timeval *tstart, const char *fmt, ...);
+
+    void flushAllCaches()                       { fImages.removeAllImageProfiles(); }
+    void flushCacheByMachHeader(uint64_t mh)    { fImages.removeOneImageProfiles(mh); }
+    unw_targettype_t getTargetArch()            { return fTargetArch; }
+    unw_accessors_t* getAccessors ()            { return &fAccessors; }
+    RemoteRegisterMap* getRegisterMap()         { return fRemoteRegisterMap; }
+    unw_addr_space_t wrap ()                    { return (unw_addr_space_t) &fWrapper; }
+    bool remoteIsLittleEndian ()                { return fLittleEndian; }
+    unw_log_level_t getDebugLoggingLevel()      { return fLogLevel; }
+    void addMemBlob (RemoteMemoryBlob *blob)    { fImages.addMemBlob(blob); }
+    unw_caching_policy_t getCachingPolicy()     { return fCachingPolicy; }
+
+private:
+    int readRaw(uint64_t addr, uint64_t extent, uint8_t *valp, void* arg)
+    {
+        uint8_t *t = this->getMemBlobMemory (addr, extent);
+        if (t) {
+            memcpy (valp, t, extent);
+            return 0;
+        }
+        return fAccessors.access_raw((unw_addr_space_t)this, addr, extent, valp, 0, arg);
+    }
+
+    struct unw_addr_space_remote    fWrapper;
+    unw_accessors_t                 fAccessors;
+    unw_caching_policy_t            fCachingPolicy;
+    unw_targettype_t                fTargetArch;
+    unw_addr_space_t                fAddrSpace;
+    RemoteImages                    fImages;
+    RemoteRegisterMap               *fRemoteRegisterMap;
+    FILE                            *fLogging;
+    unw_log_level_t                 fLogLevel;
+    bool                            fLittleEndian;
+};
+
+// Find an image containing the given pc, returns false if absent and
+// we can't add it via the accessors.
+bool RemoteProcInfo::haveImageEntry (uint64_t pc, void *arg) {
+    if (fImages.remoteEntryForTextAddr (pc) == NULL) {
+        unw_word_t mh, text_start, text_end, eh_frame, eh_frame_len, compact_unwind, compact_unwind_len;
+        if (fAccessors.find_image_info (wrap(), pc, &mh, &text_start, 
+                                        &text_end, &eh_frame, &eh_frame_len, &compact_unwind, &compact_unwind_len, arg) == UNW_ESUCCESS) {
+            fImages.addImage (mh, text_start, text_end, eh_frame, eh_frame_len, compact_unwind, compact_unwind_len);
+            if (fCachingPolicy != UNW_CACHE_NONE) {
+                if (compact_unwind_len != 0) {
+                    logVerbose ("Creating RemoteMemoryBlob of compact unwind info image at mh 0x%llx, %lld bytes", mh, (uint64_t) compact_unwind_len);
+                    uint8_t *buf = (uint8_t*) malloc (compact_unwind_len);
+                    if (this->getBytes (compact_unwind, compact_unwind_len, buf, arg)) {
+                        RemoteMemoryBlob *b = new RemoteMemoryBlob(buf, free, compact_unwind, compact_unwind_len, mh, NULL);
+                        fImages.addMemBlob (b);
+                    }
+                } else if (eh_frame_len != 0) {
+                    logVerbose ("Creating RemoteMemoryBlob of eh_frame for image at mh 0x%llx, %lld bytes", mh, (uint64_t) compact_unwind_len);
+                    uint8_t *buf = (uint8_t*) malloc (eh_frame_len);
+                    if (this->getBytes (eh_frame, eh_frame_len, buf, arg)) {
+                        RemoteMemoryBlob *b = new RemoteMemoryBlob(buf, free, eh_frame, eh_frame_len, mh, NULL);
+                        fImages.addMemBlob (b);
+                    }
+                }
+            }
+        } else {
+            return false;  /// find_image_info failed
+        }
+    } else {
+        return true;
+    }
+    return true;
+}
+
+bool RemoteProcInfo::getImageAddresses (uint64_t pc, uint64_t &mh, uint64_t &text_start, uint64_t &text_end, 
+                        uint64_t &eh_frame_start, uint64_t &eh_frame_len, uint64_t &compact_unwind_start, 
+                        void *arg) {
+    // Make sure we have this RemoteImageEntry already - fetch it now if needed.
+    if (haveImageEntry (pc, arg) == false) {
+        return false;
+    }
+    RemoteImageEntry *r = fImages.remoteEntryForTextAddr (pc);
+    if (r) {
+        mh = r->mach_header;
+        text_start = r->text_start;
+        text_end = r->text_end;
+        eh_frame_start = r->eh_frame_start;
+        eh_frame_len = r->eh_frame_len;
+        compact_unwind_start = r->compact_unwind_info_start;
+        return true;
+    }
+    return false;
+}
+
+
+bool RemoteProcInfo::findFunctionName(uint64_t addr, char *buf, size_t bufLen, unw_word_t *offset, void* arg)
+{
+    if(fAccessors.get_proc_name(wrap(), addr, buf, bufLen, offset, arg) == UNW_ESUCCESS)
+        return true;
+    else
+        return false;
+}
+
+bool RemoteProcInfo::findFunctionBounds(uint64_t addr, uint64_t& low, uint64_t& high, void* arg)
+{
+    if (fAccessors.get_proc_bounds(wrap(), addr, &low, &high, arg) == UNW_ESUCCESS
+        && high != 0)
+        return true;
+    else
+        return false;
+}
+
+int RemoteProcInfo::setCachingPolicy(unw_caching_policy_t policy)
+{
+    if(policy == UNW_CACHE_NONE && fCachingPolicy != UNW_CACHE_NONE)
+    {
+        flushAllCaches();
+    }
+
+    if(!(policy == UNW_CACHE_NONE || policy == UNW_CACHE_GLOBAL || policy == UNW_CACHE_PER_THREAD))
+        return UNW_EINVAL;
+
+    fCachingPolicy = policy;
+
+    return UNW_ESUCCESS;
+}
+
+void RemoteProcInfo::setLoggingLevel(FILE *f, unw_log_level_t level)
+{
+    fLogLevel = level;
+    fLogging = f;
+}
+
+void RemoteProcInfo::logInfo(const char *fmt, ...)
+{
+    if (fLogging == NULL || fLogLevel == UNW_LOG_LEVEL_NONE)
+        return;
+    if (fLogLevel & UNW_LOG_LEVEL_INFO) {
+        va_list ap;
+        va_start (ap, fmt);
+        vfprintf (fLogging, fmt, ap);
+        fputs ("\n", fLogging);
+        va_end (ap);
+    }
+}
+
+void RemoteProcInfo::logAPI(const char *fmt, ...)
+{
+    if (fLogging == NULL || fLogLevel == UNW_LOG_LEVEL_NONE)
+        return;
+    if (fLogLevel & UNW_LOG_LEVEL_API) {
+        va_list ap;
+        va_start (ap, fmt);
+        vfprintf (fLogging, fmt, ap);
+        fputs ("\n", fLogging);
+        va_end (ap);
+    }
+}
+
+void RemoteProcInfo::logVerbose(const char *fmt, ...)
+{
+    if (fLogging == NULL || fLogLevel == UNW_LOG_LEVEL_NONE)
+        return;
+    if (fLogLevel & UNW_LOG_LEVEL_VERBOSE) {
+        va_list ap;
+        va_start (ap, fmt);
+        vfprintf (fLogging, fmt, ap);
+        fputs ("\n", fLogging);
+        va_end (ap);
+    }
+}
+
+void RemoteProcInfo::logDebug(const char *fmt, ...)
+{
+    if (fLogging == NULL || fLogLevel == UNW_LOG_LEVEL_NONE)
+        return;
+    if (fLogLevel & UNW_LOG_LEVEL_DEBUG) {
+        va_list ap;
+        va_start (ap, fmt);
+        vfprintf (fLogging, fmt, ap);
+        fputs ("\n", fLogging);
+        va_end (ap);
+    }
+}
+
+struct timeval *RemoteProcInfo::timestamp_start ()
+{
+    if (fLogging == NULL || fLogLevel == UNW_LOG_LEVEL_NONE)
+        return NULL;
+    if (fLogLevel & UNW_LOG_LEVEL_TIMINGS) {
+        struct timeval *t = (struct timeval *) malloc (sizeof (struct timeval));
+        if (gettimeofday (t, NULL) != 0) {
+            free (t);
+            return NULL;
+        }
+        return t;
+    }
+    return NULL;
+}
+
+void RemoteProcInfo::timestamp_stop (struct timeval *tstart, const char *fmt, ...)
+{
+    if (fLogging == NULL || fLogLevel == UNW_LOG_LEVEL_NONE || tstart == NULL)
+        return;
+    if (fLogLevel & UNW_LOG_LEVEL_TIMINGS) {
+        struct timeval tend;
+        if (gettimeofday (&tend, NULL) != 0) {
+            free (tstart);
+            return;
+        }
+        struct timeval result;
+        timersub (&tend, tstart, &result);
+        va_list ap;
+        va_start (ap, fmt);
+        vprintf (fmt, ap);
+        printf (" duration %0.5fs\n", (double) ((result.tv_sec * 1000000) + result.tv_usec) / 1000000.0);
+        va_end (ap);
+        free (tstart);
+    }
+}
+
+
+// Initialize the register context at the start of a remote unwind.
+
+void getRemoteContext (RemoteProcInfo* procinfo, Registers_x86_64& r, void *arg) {
+    unw_accessors_t* accessors = procinfo->getAccessors();
+    unw_addr_space_t addrSpace = procinfo->wrap();
+    RemoteRegisterMap* regmap = procinfo->getRegisterMap();
+    uint64_t rv;
+
+    // now that we have a selected process/thread, ask about the valid registers.
+    regmap->scan_caller_regs (addrSpace, arg);
+
+#define FILLREG(reg) {int caller_reg; regmap->unwind_regno_to_caller_regno ((reg), caller_reg); accessors->access_reg (addrSpace, caller_reg, &rv, 0, arg); r.setRegister ((reg), rv);}
+    FILLREG (UNW_X86_64_RAX);
+    FILLREG (UNW_X86_64_RDX);
+    FILLREG (UNW_X86_64_RCX);
+    FILLREG (UNW_X86_64_RBX);
+    FILLREG (UNW_X86_64_RSI);
+    FILLREG (UNW_X86_64_RDI);
+    FILLREG (UNW_X86_64_RBP);
+    FILLREG (UNW_X86_64_RSP);
+    FILLREG (UNW_X86_64_R8);
+    FILLREG (UNW_X86_64_R9);
+    FILLREG (UNW_X86_64_R10);
+    FILLREG (UNW_X86_64_R11);
+    FILLREG (UNW_X86_64_R12);
+    FILLREG (UNW_X86_64_R13);
+    FILLREG (UNW_X86_64_R14);
+    FILLREG (UNW_X86_64_R15);
+    FILLREG (UNW_REG_IP);
+#undef FILLREG
+}
+
+void getRemoteContext (RemoteProcInfo* procinfo, Registers_x86& r, void *arg) {
+    unw_accessors_t* accessors = procinfo->getAccessors();
+    unw_addr_space_t addrSpace = procinfo->wrap();
+    RemoteRegisterMap* regmap = procinfo->getRegisterMap();
+    uint64_t rv;
+
+    // now that we have a selected process/thread, ask about the valid registers.
+    regmap->scan_caller_regs (addrSpace, arg);
+
+#define FILLREG(reg) {int caller_reg; regmap->unwind_regno_to_caller_regno ((reg), caller_reg); accessors->access_reg (addrSpace, caller_reg, &rv, 0, arg); r.setRegister ((reg), rv);}
+    FILLREG (UNW_X86_EAX);
+    FILLREG (UNW_X86_ECX);
+    FILLREG (UNW_X86_EDX);
+    FILLREG (UNW_X86_EBX);
+    FILLREG (UNW_X86_EBP);
+    FILLREG (UNW_X86_ESP);
+    FILLREG (UNW_X86_ESI);
+    FILLREG (UNW_X86_EDI);
+    FILLREG (UNW_REG_IP);
+#undef FILLREG
+}
+
+
+void getRemoteContext (RemoteProcInfo* procinfo, Registers_ppc& r, void *arg) {
+    ABORT("ppc get remote context not implemented.");
+}
+
+}; // namespace lldb_private
+
+
+
+#endif // SUPPORT_REMOTE_UNWINDING
+#endif // __REMOTE_PROC_INFO_HPP__
diff --git a/source/Plugins/Process/Utility/libunwind/src/RemoteRegisterMap.hpp b/source/Plugins/Process/Utility/libunwind/src/RemoteRegisterMap.hpp
new file mode 100644
index 0000000..19caae9
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/RemoteRegisterMap.hpp
@@ -0,0 +1,405 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- RemoteRegisterMap.hpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Provide conversions between reigster names, the libunwind internal enums, 
+// and the register numbers the program calling libunwind are using.
+
+#ifndef __REMOTE_REGISTER_MAP_HPP__
+#define __REMOTE_REGISTER_MAP_HPP__
+
+#if defined (SUPPORT_REMOTE_UNWINDING)
+
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS
+#endif
+#ifndef __STDC_CONSTANT_MACROS
+#define __STDC_CONSTANT_MACROS
+#endif
+
+#include "libunwind.h"
+#include <vector>
+
+namespace lldb_private
+{
+class RemoteRegisterMap {
+public:
+    RemoteRegisterMap (unw_accessors_t *accessors, unw_targettype_t target);
+    ~RemoteRegisterMap ();
+    void initialize_x86_64 ();
+    void initialize_i386 ();
+    bool name_to_caller_regno (const char *name, int& callerr);
+    bool name_to_unwind_regno (const char *name, int& unwindr);
+    bool unwind_regno_to_caller_regno (int unwindr, int& callerr);
+    bool nonvolatile_reg_p (int unwind_regno);
+    bool argument_regnum_p (int unwind_regno);
+    const char *ip_register_name();
+    const char *sp_register_name();
+    int caller_regno_for_ip ();
+    int caller_regno_for_sp ();
+    int unwind_regno_for_frame_pointer ();
+    int unwind_regno_for_stack_pointer ();
+    int wordsize ()                         { return fWordSize; }
+    void scan_caller_regs (unw_addr_space_t as, void *arg);
+
+    bool unwind_regno_to_machine_regno (int unwindr, int& machiner);
+    bool machine_regno_to_unwind_regno (int machr, int& unwindr);
+    bool caller_regno_to_unwind_regno (int callerr, int& unwindr);
+    const char* unwind_regno_to_name (int unwindr);
+    int byte_size_for_regtype (unw_regtype_t type);
+
+private:
+
+    // A structure that collects everything we need to know about a
+    // given register in one place.
+    struct reg {
+        int unwind_regno;    // What libunwind-remote uses internally
+        int caller_regno;    // What the libunwind-remote driver program uses
+        int eh_frame_regno;  // What the eh_frame section uses
+        int machine_regno;   // What the actual bits/bytes are in instructions
+        char *name;
+        unw_regtype_t type;
+        reg () : unwind_regno(-1), machine_regno(-1), caller_regno(-1), 
+                 eh_frame_regno(-1), name(NULL), type(UNW_NOT_A_REG) { }
+    };
+
+    unw_accessors_t fAccessors;
+    unw_targettype_t fTarget;
+    std::vector<RemoteRegisterMap::reg> fRegMap;
+    int fWordSize;
+};
+
+void RemoteRegisterMap::initialize_x86_64 () {
+#define DEFREG(ureg, ehno, machno, regn) {RemoteRegisterMap::reg r; r.unwind_regno = ureg; r.name = regn; r.eh_frame_regno = ehno; r.machine_regno = machno; r.type = UNW_INTEGER_REG; fRegMap.push_back(r); }
+    DEFREG (UNW_X86_64_RAX, 0,  0,  strdup ("rax"));
+    DEFREG (UNW_X86_64_RDX, 1,  2,  strdup ("rdx"));
+    DEFREG (UNW_X86_64_RCX, 2,  1,  strdup ("rcx"));
+    DEFREG (UNW_X86_64_RBX, 3,  3,  strdup ("rbx"));
+    DEFREG (UNW_X86_64_RSI, 4,  6,  strdup ("rsi"));
+    DEFREG (UNW_X86_64_RDI, 5,  7,  strdup ("rdi"));
+    DEFREG (UNW_X86_64_RBP, 6,  5,  strdup ("rbp"));
+    DEFREG (UNW_X86_64_RSP, 7,  4,  strdup ("rsp"));
+    DEFREG (UNW_X86_64_R8,  8,  8,  strdup ("r8"));
+    DEFREG (UNW_X86_64_R9,  9,  9,  strdup ("r9"));
+    DEFREG (UNW_X86_64_R10, 10, 10, strdup ("r10"));
+    DEFREG (UNW_X86_64_R11, 11, 11, strdup ("r11"));
+    DEFREG (UNW_X86_64_R12, 12, 12, strdup ("r12"));
+    DEFREG (UNW_X86_64_R13, 13, 13, strdup ("r13"));
+    DEFREG (UNW_X86_64_R14, 14, 14, strdup ("r14"));
+    DEFREG (UNW_X86_64_R15, 15, 15, strdup ("r15"));
+#undef DEFREG
+    RemoteRegisterMap::reg r;
+    r.name = strdup ("rip");
+    r.type = UNW_INTEGER_REG; 
+    r.eh_frame_regno = 16;
+    fRegMap.push_back(r);
+}
+
+void RemoteRegisterMap::initialize_i386 () {
+#define DEFREG(ureg, ehno, machno, regn) {RemoteRegisterMap::reg r; r.unwind_regno = ureg; r.name = regn; r.eh_frame_regno = ehno; r.machine_regno = machno; r.type = UNW_INTEGER_REG; fRegMap.push_back(r); }
+    DEFREG (UNW_X86_EAX, 0,  0,  strdup ("eax"));
+    DEFREG (UNW_X86_ECX, 1,  1,  strdup ("ecx"));
+    DEFREG (UNW_X86_EDX, 2,  2,  strdup ("edx"));
+    DEFREG (UNW_X86_EBX, 3,  3,  strdup ("ebx"));
+    // i386 EH frame info has the next two swapped,
+    // v. gcc/config/i386/darwin.h:DWARF2_FRAME_REG_OUT.
+    DEFREG (UNW_X86_EBP, 4,  5,  strdup ("ebp"));
+    DEFREG (UNW_X86_ESP, 5,  4,  strdup ("esp"));
+    DEFREG (UNW_X86_ESI, 6,  6,  strdup ("esi"));
+    DEFREG (UNW_X86_EDI, 7,  7,  strdup ("edi"));
+#undef DEFREG
+    RemoteRegisterMap::reg r;
+    r.name = strdup ("eip");
+    r.type = UNW_INTEGER_REG; 
+    r.eh_frame_regno = 8;
+    fRegMap.push_back(r);
+}
+
+
+RemoteRegisterMap::RemoteRegisterMap (unw_accessors_t *accessors, unw_targettype_t target) {
+    fAccessors = *accessors;
+    fTarget = target;
+    switch (target) {
+        case UNW_TARGET_X86_64:
+            this->initialize_x86_64();
+            fWordSize = 8;
+            break;
+        case UNW_TARGET_I386:
+            this->initialize_i386();
+            fWordSize = 4;
+            break;
+        default:
+            ABORT("RemoteRegisterMap called with unknown target");
+    }
+}
+
+RemoteRegisterMap::~RemoteRegisterMap () {
+    std::vector<RemoteRegisterMap::reg>::iterator j;
+    for (j = fRegMap.begin(); j != fRegMap.end(); ++j)
+        free (j->name);
+}
+
+bool RemoteRegisterMap::name_to_caller_regno (const char *name, int& callerr) {
+    if (name == NULL)
+        return false;
+    for (std::vector<RemoteRegisterMap::reg>::iterator j = fRegMap.begin(); j != fRegMap.end(); ++j)
+        if (strcasecmp (j->name, name) == 0) {
+            callerr = j->caller_regno;
+            return true;
+        }
+    return false;
+}
+
+bool RemoteRegisterMap::unwind_regno_to_caller_regno (int unwindr, int& callerr) {
+    if (unwindr == UNW_REG_IP) {
+      callerr = this->caller_regno_for_ip ();
+      return true;
+    }
+    if (unwindr == UNW_REG_SP) {
+      callerr = this->caller_regno_for_sp ();
+      return true;
+    }
+    for (std::vector<RemoteRegisterMap::reg>::iterator j = fRegMap.begin(); j != fRegMap.end(); ++j)
+        if (j->unwind_regno == unwindr && j->caller_regno != -1) {
+            callerr = j->caller_regno;
+            return true;
+        }
+    return false;
+}
+
+bool RemoteRegisterMap::nonvolatile_reg_p (int unwind_regno) {
+    if (fTarget == UNW_TARGET_X86_64) {
+        switch (unwind_regno) {
+            case UNW_X86_64_RBX:
+            case UNW_X86_64_RSP:
+            case UNW_X86_64_RBP:  // not actually a nonvolatile but often treated as such by convention
+            case UNW_X86_64_R12:
+            case UNW_X86_64_R13:
+            case UNW_X86_64_R14:
+            case UNW_X86_64_R15:
+            case UNW_REG_IP:
+            case UNW_REG_SP:
+                return true;
+                break;
+            default:
+                return false;
+        }
+    }
+    if (fTarget == UNW_TARGET_I386) {
+        switch (unwind_regno) {
+            case UNW_X86_EBX:
+            case UNW_X86_EBP:  // not actually a nonvolatile but often treated as such by convention
+            case UNW_X86_ESI:
+            case UNW_X86_EDI:
+            case UNW_X86_ESP:
+            case UNW_REG_IP:
+            case UNW_REG_SP:
+                return true;
+                break;
+            default:
+                return false;
+        }
+    }
+    return false;
+}
+
+
+bool RemoteRegisterMap::argument_regnum_p (int unwind_regno) {
+    if (fTarget == UNW_TARGET_X86_64) {
+        switch (unwind_regno) {
+            case UNW_X86_64_RDI: /* arg 1 */
+            case UNW_X86_64_RSI: /* arg 2 */
+            case UNW_X86_64_RDX: /* arg 3 */
+            case UNW_X86_64_RCX: /* arg 4 */
+            case UNW_X86_64_R8:  /* arg 5 */
+            case UNW_X86_64_R9:  /* arg 6 */
+                return true;
+                break;
+            default:
+                return false;
+        }
+    }
+    return false;
+}
+
+const char *RemoteRegisterMap::ip_register_name () {
+    switch (fTarget) {
+        case UNW_TARGET_X86_64:
+            return "rip";
+        case UNW_TARGET_I386:
+            return "eip";
+        default:
+            ABORT("unsupported architecture");
+    }
+    return NULL;
+}
+
+const char *RemoteRegisterMap::sp_register_name () {
+    switch (fTarget) {
+        case UNW_TARGET_X86_64:
+            return "rsp";
+        case UNW_TARGET_I386:
+            return "esp";
+        default:
+            ABORT("unsupported architecture");
+    }
+    return NULL;
+}
+
+int RemoteRegisterMap::caller_regno_for_ip () {
+    int callerr;
+    if (this->name_to_caller_regno (this->ip_register_name(), callerr))
+        return callerr;
+    return -1;
+}
+
+int RemoteRegisterMap::caller_regno_for_sp () {
+    int callerr;
+    if (this->name_to_caller_regno (this->sp_register_name(), callerr))
+        return callerr;
+    return -1;
+}
+
+int RemoteRegisterMap::unwind_regno_for_frame_pointer () {
+    switch (fTarget) {
+        case UNW_TARGET_X86_64:
+            return UNW_X86_64_RBP;
+        case UNW_TARGET_I386:
+            return UNW_X86_EBP;
+        default:
+            ABORT("cannot be reached");
+    }
+    return -1;
+}
+
+int RemoteRegisterMap::unwind_regno_for_stack_pointer () {
+    switch (fTarget) {
+        case UNW_TARGET_X86_64:
+            return UNW_X86_64_RSP;
+        case UNW_TARGET_I386:
+            return UNW_X86_ESP;
+        default:
+            ABORT("cannot be reached");
+    }
+    return -1;
+}
+
+// This call requires a "arg" which specifies a given process/thread to
+// complete unlike the rest of the RegisterMap functions.  Ideally this
+// would be in the ctor but the register map is created when an 
+// AddressSpace is created and we don't have a process/thread yet.
+
+void RemoteRegisterMap::scan_caller_regs (unw_addr_space_t as, void *arg) {
+    for (int i = 0; i < 256; i++) {
+        unw_regtype_t type;
+        char namebuf[16];
+        if (fAccessors.reg_info (as, i, &type, namebuf, sizeof (namebuf), arg) == UNW_ESUCCESS
+            && type != UNW_NOT_A_REG) {
+            std::vector<RemoteRegisterMap::reg>::iterator j;
+            for (j = fRegMap.begin(); j != fRegMap.end(); ++j) {
+                if (strcasecmp (j->name, namebuf) == 0) {
+                    j->caller_regno = i;
+                    // if we haven't picked up a reg type yet it will be UNW_NOT_A_REG via the ctor
+                    if (j->type == UNW_NOT_A_REG)
+                        j->type = type;
+                    if (j->type != type) {
+                        ABORT("Caller and libunwind disagree about type of register");
+                    break;
+                    }
+                }
+            }
+            // caller knows about a register we don't have a libunwind entry for
+            if (j == fRegMap.end()) {
+                RemoteRegisterMap::reg r;
+                r.name = strdup (namebuf);
+                r.caller_regno = i;
+                r.type = type;
+                fRegMap.push_back(r);
+            }
+        }
+    }
+}
+
+
+bool RemoteRegisterMap::name_to_unwind_regno (const char *name, int& unwindr) {
+    if (name == NULL)
+        return false;
+    for (std::vector<RemoteRegisterMap::reg>::iterator j = fRegMap.begin(); j != fRegMap.end(); ++j)
+        if (strcasecmp (j->name, name) == 0) {
+            unwindr = j->unwind_regno;
+            return true;
+        }
+    return false;
+}
+
+bool RemoteRegisterMap::unwind_regno_to_machine_regno (int unwindr, int& machiner) {
+    if (unwindr == UNW_REG_IP)
+      unwindr = this->caller_regno_for_ip ();
+    if (unwindr == UNW_REG_SP)
+      unwindr = this->caller_regno_for_sp ();
+    for (std::vector<RemoteRegisterMap::reg>::iterator j = fRegMap.begin(); j != fRegMap.end(); ++j)
+        if (j->unwind_regno == unwindr && j->machine_regno != -1) {
+            machiner = j->machine_regno;
+            return true;
+        }
+    return false;
+}
+bool RemoteRegisterMap::machine_regno_to_unwind_regno (int machr, int& unwindr) {
+    for (std::vector<RemoteRegisterMap::reg>::iterator j = fRegMap.begin(); j != fRegMap.end(); ++j)
+        if (j->machine_regno == machr && j->unwind_regno != -1) {
+            unwindr = j->unwind_regno;
+            return true;
+        }
+    return false;
+}
+bool RemoteRegisterMap::caller_regno_to_unwind_regno (int callerr, int& unwindr) {
+    if (this->caller_regno_for_ip() == callerr) {
+        unwindr = UNW_REG_IP;
+        return true;
+    }
+    if (this->caller_regno_for_sp() == callerr) {
+        unwindr = UNW_REG_SP;
+        return true;
+    }
+    for (std::vector<RemoteRegisterMap::reg>::iterator j = fRegMap.begin(); j != fRegMap.end(); ++j)
+        if (j->caller_regno == callerr && j->unwind_regno != -1) {
+            unwindr = j->unwind_regno;
+            return true;
+        }
+    return false;
+}
+
+const char* RemoteRegisterMap::unwind_regno_to_name (int unwindr) {
+    for (std::vector<RemoteRegisterMap::reg>::iterator j = fRegMap.begin(); j != fRegMap.end(); ++j)
+        if (j->unwind_regno == unwindr && j->name != NULL) {
+            return j->name;
+        }
+    return NULL;
+}
+
+int RemoteRegisterMap::byte_size_for_regtype (unw_regtype_t type) {
+    switch (type) {
+        case UNW_TARGET_X86_64:
+        case UNW_TARGET_I386:
+            if (type == UNW_INTEGER_REG)        return fWordSize;
+            if (type == UNW_FLOATING_POINT_REG) return 8;
+            if (type == UNW_VECTOR_REG)         return 16;
+        default:
+            ABORT("cannot be reached");
+    }
+    return -1;
+}
+
+
+}; // namespace lldb_private
+
+#endif // SUPPORT_REMOTE_UNWINDING
+
+#endif // __REMOTE_REGISTER_MAP_HPP__
+
diff --git a/source/Plugins/Process/Utility/libunwind/src/RemoteUnwindProfile.h b/source/Plugins/Process/Utility/libunwind/src/RemoteUnwindProfile.h
new file mode 100644
index 0000000..b03551c
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/RemoteUnwindProfile.h
@@ -0,0 +1,85 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- RemoteUnwindProfile.h -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __UNWIND_PROFILE_H__
+#define __UNWIND_PROFILE_H__
+#if defined (SUPPORT_REMOTE_UNWINDING)
+
+#include <vector>
+
+// The architecture-independent profile of a function's prologue
+
+namespace lldb_private 
+{
+
+class RemoteUnwindProfile {
+public:
+    RemoteUnwindProfile () : fRegistersSaved(32, 0), fRegSizes(10, 0) { }
+    struct CFALocation {
+        int regno;
+        int offset;
+    };
+    enum RegisterSavedWhere { kRegisterOffsetFromCFA, kRegisterIsCFA };
+    enum RegisterType { kGeneralPurposeRegister = 0, kFloatingPointRegister, kVectorRegister };
+    struct SavedReg {
+        int regno;
+        RegisterSavedWhere location;
+        int64_t value;
+        int adj;    // Used in kRegisterInRegister e.g. when we recover the caller's rsp by
+                    // taking the contents of rbp and subtracting 16.
+        RegisterType type;
+    };
+    // In the following maps the key is the address after which this change has effect.
+    //
+    //  0  push %rbp
+    //  1  mov  %rsp, %rbp
+    //  2  sub  $16, %rsp
+    //
+    // At saved_registers<2> we'll find the record stating that rsp is now stored in rbp.
+
+    std::map<uint64_t, CFALocation> cfa;
+    std::map<uint64_t, std::vector<SavedReg> > saved_registers;
+
+    struct CFALocation initial_cfa;  // At entry to the function
+
+    std::vector<uint8_t> fRegistersSaved;
+    std::vector<uint8_t> fRegSizes;
+    SavedReg returnAddress;
+    uint64_t fStart, fEnd;           // low and high pc values for this function.
+                                     // END is the addr of the first insn outside the function.
+    uint64_t fFirstInsnPastPrologue;
+};
+
+class RemoteProcInfo;
+
+bool AssemblyParse (RemoteProcInfo *procinfo, unw_accessors_t *as, unw_addr_space_t as, uint64_t start, uint64_t end, RemoteUnwindProfile &profile, void *arg);
+
+
+class FuncBounds {
+    public:
+    FuncBounds (uint64_t low, uint64_t high) : fStart(low), fEnd(high) { }
+    uint64_t fStart;
+    uint64_t fEnd;
+};
+
+inline bool operator<(const FuncBounds &ap1, const FuncBounds &ap2) {
+    if (ap1.fStart < ap2.fStart)
+        return true;
+    if (ap1.fStart == ap2.fStart && ap1.fEnd < ap2.fEnd)
+        return true;
+    return false;
+}
+
+
+};
+#endif
+
+
+#endif // __UNWIND_PROFILE_H__
diff --git a/source/Plugins/Process/Utility/libunwind/src/Unwind-sjlj.c b/source/Plugins/Process/Utility/libunwind/src/Unwind-sjlj.c
new file mode 100644
index 0000000..5845283
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/Unwind-sjlj.c
@@ -0,0 +1,466 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- Unwind-sjlj.c -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+/* 
+ * 
+ *  Implements setjump-longjump based C++ exceptions
+ * 
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+#include <setjmp.h>
+
+#include "unwind.h"
+#include "InternalMacros.h"
+
+//
+// ARM uses setjump/longjump based C++ exceptions.
+// Other architectures use "zero cost" exceptions.
+// 
+// With SJLJ based exceptions any function that has a catch clause or needs to do any clean up when
+// an exception propagates through it, needs to call _Unwind_SjLj_Register() at the start of the
+// function and _Unwind_SjLj_Unregister() at the end.  The register function is called with the
+// address of a block of memory in the function's stack frame.  The runtime keeps a linked list
+// (stack) of these blocks - one per thread.  The calling function also sets the personality
+// and lsda fields of the block. 
+//
+//
+#if __arm__
+
+struct _Unwind_FunctionContext
+{
+	// next function in stack of handlers
+	struct _Unwind_FunctionContext*		prev;
+
+	// set by calling function before registering to be the landing pad
+	uintptr_t							resumeLocation;
+	
+	// set by personality handler to be parameters passed to landing pad function
+	uintptr_t							resumeParameters[4];
+
+	// set by calling function before registering
+	__personality_routine				personality;	// arm offset=24	
+	uintptr_t							lsda;			// arm offset=28
+
+	// variable length array, contains registers to restore
+	// 0 = r7, 1 = pc, 2 = sp
+	void*								jbuf[];
+};
+
+
+#if FOR_DYLD
+	// implemented in dyld 
+	extern struct _Unwind_FunctionContext* __Unwind_SjLj_GetTopOfFunctionStack(); 
+	extern void __Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext* fc);
+#else
+	static pthread_key_t sPerThreadTopOfFunctionStack = 0; 
+	static pthread_once_t sOnceFlag = PTHREAD_ONCE_INIT;
+
+	static void __Unwind_SjLj_MakeTopOfFunctionStackKey()
+	{
+		pthread_key_create(&sPerThreadTopOfFunctionStack, NULL);
+	}
+
+	static struct _Unwind_FunctionContext* __Unwind_SjLj_GetTopOfFunctionStack()
+	{
+		pthread_once(&sOnceFlag, __Unwind_SjLj_MakeTopOfFunctionStackKey);
+		return (struct _Unwind_FunctionContext*)pthread_getspecific(sPerThreadTopOfFunctionStack);
+	}
+
+	static void __Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext* fc)
+	{
+		pthread_once(&sOnceFlag, __Unwind_SjLj_MakeTopOfFunctionStackKey);
+		pthread_setspecific(sPerThreadTopOfFunctionStack, fc);
+	}
+#endif
+
+
+//
+// Called at start of each function that catches exceptions
+//
+EXPORT void	_Unwind_SjLj_Register(struct _Unwind_FunctionContext* fc)
+{
+	fc->prev = __Unwind_SjLj_GetTopOfFunctionStack();
+	__Unwind_SjLj_SetTopOfFunctionStack(fc);
+}
+
+
+//
+// Called at end of each function that catches exceptions
+//
+EXPORT void	_Unwind_SjLj_Unregister(struct _Unwind_FunctionContext* fc)
+{
+	__Unwind_SjLj_SetTopOfFunctionStack(fc->prev);
+}
+
+
+static _Unwind_Reason_Code unwind_phase1(struct _Unwind_Exception* exception_object)
+{
+	_Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
+	DEBUG_PRINT_UNWINDING("unwind_phase1: initial function-context=%p\n", c); 
+
+	// walk each frame looking for a place to stop
+	for (bool handlerNotFound = true; handlerNotFound; c = c->prev) {
+
+		// check for no more frames
+		if ( c == NULL ) {
+			DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): reached bottom => _URC_END_OF_STACK\n", exception_object); 
+			return _URC_END_OF_STACK;
+		}
+		
+		DEBUG_PRINT_UNWINDING("unwind_phase1: function-context=%p\n", c); 
+		// if there is a personality routine, ask it if it will want to stop at this frame
+		if ( c->personality != NULL ) {
+			DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): calling personality function %p\n", exception_object, c->personality);
+			_Unwind_Reason_Code personalityResult = (*c->personality)(1, _UA_SEARCH_PHASE, 
+						exception_object->exception_class, exception_object, 
+						(struct _Unwind_Context*)c);
+			switch ( personalityResult ) {
+				case _URC_HANDLER_FOUND:
+					// found a catch clause or locals that need destructing in this frame
+					// stop search and remember function context
+					handlerNotFound = false;
+					exception_object->private_2 = (uintptr_t)c;
+					DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND\n", exception_object);
+					return _URC_NO_REASON;
+					
+				case _URC_CONTINUE_UNWIND:
+					DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", exception_object);
+					// continue unwinding
+					break;
+					
+				default:
+					// something went wrong
+					DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n", exception_object);
+					return _URC_FATAL_PHASE1_ERROR;
+			}
+		}
+	}
+	return _URC_NO_REASON;
+}
+
+
+static _Unwind_Reason_Code unwind_phase2(struct _Unwind_Exception* exception_object)
+{
+	DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p)\n", exception_object); 
+	
+	// walk each frame until we reach where search phase said to stop
+	_Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
+	while ( true ) {
+		DEBUG_PRINT_UNWINDING("unwind_phase2s(ex_ojb=%p): function-context=%p\n", exception_object, c); 
+
+		// check for no more frames
+		if ( c == NULL ) {
+			DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached bottom => _URC_END_OF_STACK\n", exception_object); 
+			return _URC_END_OF_STACK;
+		}
+		
+		// if there is a personality routine, tell it we are unwinding
+		if ( c->personality != NULL ) {
+			_Unwind_Action action = _UA_CLEANUP_PHASE;
+			if ( (uintptr_t)c == exception_object->private_2 )
+				action = (_Unwind_Action)(_UA_CLEANUP_PHASE|_UA_HANDLER_FRAME); // tell personality this was the frame it marked in phase 1
+			_Unwind_Reason_Code personalityResult = (*c->personality)(1, action, 
+						exception_object->exception_class, exception_object, 
+						(struct _Unwind_Context*)c);
+			switch ( personalityResult ) {
+				case _URC_CONTINUE_UNWIND:
+					// continue unwinding
+					DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", exception_object);
+					if ( (uintptr_t)c == exception_object->private_2 ) {
+						// phase 1 said we would stop at this frame, but we did not...
+						ABORT("during phase1 personality function said it would stop here, but now if phase2 it did not stop here");
+					}
+					break;
+				case _URC_INSTALL_CONTEXT:
+					DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT, will resume at landing pad %p\n", exception_object, c->jbuf[1]);
+					// personality routine says to transfer control to landing pad
+					// we may get control back if landing pad calls _Unwind_Resume()
+					__Unwind_SjLj_SetTopOfFunctionStack(c);
+					__builtin_longjmp(c->jbuf, 1);
+					// unw_resume() only returns if there was an error
+					return _URC_FATAL_PHASE2_ERROR;
+				default:
+					// something went wrong
+					DEBUG_MESSAGE("personality function returned unknown result %d", personalityResult);
+					return _URC_FATAL_PHASE2_ERROR;
+			}
+		}
+		c = c->prev;
+	}
+
+	// clean up phase did not resume at the frame that the search phase said it would
+	return _URC_FATAL_PHASE2_ERROR;
+}
+
+
+static _Unwind_Reason_Code unwind_phase2_forced(struct _Unwind_Exception* exception_object, 
+												_Unwind_Stop_Fn stop, void* stop_parameter)
+{
+	// walk each frame until we reach where search phase said to stop
+	_Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
+	while ( true ) {
+
+		// get next frame (skip over first which is _Unwind_RaiseException)
+		if ( c == NULL ) {
+			DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached bottom => _URC_END_OF_STACK\n", exception_object); 
+			return _URC_END_OF_STACK;
+		}
+				
+		// call stop function at each frame
+		_Unwind_Action action = (_Unwind_Action)(_UA_FORCE_UNWIND|_UA_CLEANUP_PHASE);
+		_Unwind_Reason_Code stopResult = (*stop)(1, action, 
+						exception_object->exception_class, exception_object, 
+						(struct _Unwind_Context*)c, stop_parameter);
+		DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): stop function returned %d\n", exception_object, stopResult);
+		if ( stopResult != _URC_NO_REASON ) {
+			DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): stopped by stop function\n", exception_object);
+			return _URC_FATAL_PHASE2_ERROR;
+		}
+		
+		// if there is a personality routine, tell it we are unwinding
+		if ( c->personality != NULL ) {
+			__personality_routine p = (__personality_routine)c->personality;
+			DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling personality function %p\n", exception_object, p);
+			_Unwind_Reason_Code personalityResult = (*p)(1, action, 
+						exception_object->exception_class, exception_object, 
+						(struct _Unwind_Context*)c);
+			switch ( personalityResult ) {
+				case _URC_CONTINUE_UNWIND:
+					DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned _URC_CONTINUE_UNWIND\n", exception_object);
+					// destructors called, continue unwinding
+					break;
+				case _URC_INSTALL_CONTEXT:
+					DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned _URC_INSTALL_CONTEXT\n", exception_object);
+					// we may get control back if landing pad calls _Unwind_Resume()
+					__Unwind_SjLj_SetTopOfFunctionStack(c);
+					__builtin_longjmp(c->jbuf, 1);
+					break;
+				default:
+					// something went wrong
+					DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned %d, _URC_FATAL_PHASE2_ERROR\n", 
+						exception_object, personalityResult);
+					return _URC_FATAL_PHASE2_ERROR;
+			}
+		}
+		c = c->prev;
+	}
+
+	// call stop function one last time and tell it we've reached the end of the stack
+	DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop function with _UA_END_OF_STACK\n", exception_object);
+	_Unwind_Action lastAction = (_Unwind_Action)(_UA_FORCE_UNWIND|_UA_CLEANUP_PHASE|_UA_END_OF_STACK);
+	(*stop)(1, lastAction, exception_object->exception_class, exception_object, (struct _Unwind_Context*)c, stop_parameter);
+	
+	// clean up phase did not resume at the frame that the search phase said it would
+	return _URC_FATAL_PHASE2_ERROR;
+}
+
+
+//
+// Called by __cxa_throw.  Only returns if there is a fatal error
+//
+EXPORT _Unwind_Reason_Code _Unwind_SjLj_RaiseException(struct _Unwind_Exception* exception_object)
+{
+	DEBUG_PRINT_API("_Unwind_SjLj_RaiseException(ex_obj=%p)\n", exception_object);
+
+	// mark that this is a non-forced unwind, so _Unwind_Resume() can do the right thing
+	exception_object->private_1	= 0;
+	exception_object->private_2	= 0;
+
+	// phase 1: the search phase
+	_Unwind_Reason_Code phase1 = unwind_phase1(exception_object);
+	if ( phase1 != _URC_NO_REASON )
+		return phase1;
+	
+	// phase 2: the clean up phase
+	return unwind_phase2(exception_object);  
+}
+
+
+//
+// When _Unwind_RaiseException() is in phase2, it hands control
+// to the personality function at each frame.  The personality
+// may force a jump to a landing pad in that function, the landing
+// pad code may then call _Unwind_Resume() to continue with the
+// unwinding.  Note: the call to _Unwind_Resume() is from compiler
+// geneated user code.  All other _Unwind_* routines are called 
+// by the C++ runtime __cxa_* routines. 
+//
+// Re-throwing an exception is implemented by having the code call
+// __cxa_rethrow() which in turn calls _Unwind_Resume_or_Rethrow()
+//
+EXPORT void _Unwind_SjLj_Resume(struct _Unwind_Exception* exception_object)
+{
+	DEBUG_PRINT_API("_Unwind_SjLj_Resume(ex_obj=%p)\n", exception_object);
+	
+	if ( exception_object->private_1 != 0 ) 
+		unwind_phase2_forced(exception_object, (_Unwind_Stop_Fn)exception_object->private_1, (void*)exception_object->private_2);  
+	else
+		unwind_phase2(exception_object);  
+	
+	// clients assume _Unwind_Resume() does not return, so all we can do is abort.
+	ABORT("_Unwind_SjLj_Resume() can't return");
+}
+
+
+//
+//  Called by __cxa_rethrow()
+//
+EXPORT _Unwind_Reason_Code _Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception* exception_object)
+{
+	DEBUG_PRINT_API("__Unwind_SjLj_Resume_or_Rethrow(ex_obj=%p), private_1=%ld\n", exception_object, exception_object->private_1);
+	// if this is non-forced and a stopping place was found, then this is a re-throw
+	// call _Unwind_RaiseException() as if this was a new exception
+	if ( exception_object->private_1 == 0 )
+		_Unwind_SjLj_RaiseException(exception_object); 
+	
+	// call through to _Unwind_Resume() which distiguishes between forced and regular exceptions
+	_Unwind_SjLj_Resume(exception_object); 
+	ABORT("__Unwind_SjLj_Resume_or_Rethrow() called _Unwind_SjLj_Resume() which unexpectedly returned");
+}
+
+
+//
+// Called by personality handler during phase 2 to get LSDA for current frame
+//
+EXPORT uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context* context)
+{
+	_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t)context;
+	DEBUG_PRINT_API("_Unwind_GetLanguageSpecificData(context=%p) => 0x%0lX\n", context, ufc->lsda);
+	return ufc->lsda;
+}
+
+
+//
+// Called by personality handler during phase 2 to get register values
+//
+EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context* context, int index)
+{
+	DEBUG_PRINT_API("_Unwind_GetGR(context=%p, reg=%d)\n", context, index);
+	_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t)context;
+	return ufc->resumeParameters[index];
+}
+
+
+
+//
+// Called by personality handler during phase 2 to alter register values
+//
+EXPORT void _Unwind_SetGR(struct _Unwind_Context* context, int index, uintptr_t new_value)
+{
+	DEBUG_PRINT_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0lX)\n", context, index, new_value);
+	_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t)context;
+	ufc->resumeParameters[index] = new_value;
+}
+
+
+//
+// Called by personality handler during phase 2 to get instruction pointer
+//
+EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context* context)
+{
+	_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t)context;
+	DEBUG_PRINT_API("_Unwind_GetIP(context=%p) => 0x%lX\n", context, ufc->resumeLocation+1);
+	return ufc->resumeLocation+1;
+}
+
+//
+// Called by personality handler during phase 2 to get instruction pointer
+// ipBefore is a boolean that says if IP is already adjusted to be the call
+// site address.  Normally IP is the return address.
+//
+EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context* context, int* ipBefore)
+{
+	_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t)context;
+	*ipBefore = 0;
+	DEBUG_PRINT_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%lX\n", context, ipBefore, ufc->resumeLocation+1);
+	return ufc->resumeLocation+1; 
+}
+
+
+//
+// Called by personality handler during phase 2 to alter instruction pointer
+//
+EXPORT void _Unwind_SetIP(struct _Unwind_Context* context, uintptr_t new_value)
+{
+	DEBUG_PRINT_API("_Unwind_SetIP(context=%p, value=0x%0lX)\n", context, new_value);
+	_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t)context;
+	ufc->resumeLocation = new_value-1;
+}
+
+//
+// Called by personality handler during phase 2 to find the start of the function
+//
+EXPORT uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context* context)
+{
+	// Not supported or needed for sjlj based unwinding
+	DEBUG_PRINT_API("_Unwind_GetRegionStart(context=%p)\n", context);
+	return 0;
+}
+
+//
+// Called by personality handler during phase 2 if a foreign exception is caught 
+//
+EXPORT void _Unwind_DeleteException(struct _Unwind_Exception* exception_object)
+{
+	DEBUG_PRINT_API("_Unwind_DeleteException(ex_obj=%p)\n", exception_object);
+	if ( exception_object->exception_cleanup != NULL )
+		(*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, exception_object);
+}
+
+
+//
+// Called by personality handler during phase 2 to get base address for data relative encodings
+//
+EXPORT uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context* context)
+{
+	// Not supported or needed for sjlj based unwinding
+	DEBUG_PRINT_API("_Unwind_GetDataRelBase(context=%p)\n", context);
+	ABORT("_Unwind_GetDataRelBase() not implemented");
+}
+
+
+//
+// Called by personality handler during phase 2 to get base address for text relative encodings
+//
+EXPORT uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context* context)
+{
+	// Not supported or needed for sjlj based unwinding
+	DEBUG_PRINT_API("_Unwind_GetTextRelBase(context=%p)\n", context);
+	ABORT("_Unwind_GetTextRelBase() not implemented");
+}
+
+
+
+//
+// Called by personality handler to get Call Frame Area for current frame
+//
+EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context* context)
+{
+	DEBUG_PRINT_API("_Unwind_GetCFA(context=%p)\n", context);
+	if ( context != NULL ) {
+		_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t)context;
+		// setjmp/longjmp based exceptions don't have a true CFA
+		// the SP in the jmpbuf is the closest approximation
+		return (uintptr_t)ufc->jbuf[2];
+	}
+	return 0;
+}
+
+
+
+
+
+#endif // __arm__
diff --git a/source/Plugins/Process/Utility/libunwind/src/UnwindCursor.hpp b/source/Plugins/Process/Utility/libunwind/src/UnwindCursor.hpp
new file mode 100644
index 0000000..e940b8b
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/UnwindCursor.hpp
@@ -0,0 +1,1307 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- UnwindCursor.hpp ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+ 
+//
+//	C++ interface to lower levels of libuwind 
+//
+
+#ifndef __UNWINDCURSOR_HPP__
+#define __UNWINDCURSOR_HPP__
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <stdarg.h>
+
+#include "libunwind.h"
+
+#include "AddressSpace.hpp"
+#include "Registers.hpp"
+#include "DwarfInstructions.hpp"
+
+#include "AssemblyParser.hpp"
+#include "AssemblyInstructions.hpp"
+#include "RemoteProcInfo.hpp"
+#include "ArchDefaultUnwinder.hpp"
+#include "RemoteDebuggerDummyUnwinder.hpp"
+
+#include "CompactUnwinder.hpp"
+#include "InternalMacros.h"
+
+// private keymgr stuff
+#define KEYMGR_GCC3_DW2_OBJ_LIST   302  
+extern "C" {
+	extern void	 _keymgr_set_and_unlock_processwide_ptr(int key, void* ptr);
+	extern void* _keymgr_get_and_lock_processwide_ptr(int key);
+};
+
+// undocumented libgcc "struct object"
+struct libgcc_object 
+{
+	void*			start;
+	void*			unused1;
+	void*			unused2;
+	void*			fde;
+	unsigned long	encoding;
+	void*			fde_end;
+	libgcc_object*	next;
+};
+
+// undocumented libgcc "struct km_object_info" referenced by KEYMGR_GCC3_DW2_OBJ_LIST
+struct libgcc_object_info {
+  struct libgcc_object*		seen_objects;
+  struct libgcc_object*		unseen_objects;
+  unsigned					spare[2];
+};
+
+
+
+
+namespace lldb_private {
+
+#if !FOR_DYLD
+template <typename A>
+class DwarfFDECache 
+{
+public:
+	typedef typename A::pint_t	pint_t;
+	static pint_t					findFDE(pint_t mh, pint_t pc);
+	static void						add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde);
+	static void						removeAllIn(pint_t mh);
+	static void						iterateCacheEntries(void (*func)(unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh));
+private:
+	static void						dyldUnloadHook(const struct mach_header* mh, intptr_t vmaddr_slide);
+	
+	struct entry { pint_t mh; pint_t ip_start; pint_t ip_end; pint_t fde; };
+
+	// these fields are all static to avoid needing an initializer
+	// there is only one instance of this class per process
+	static pthread_rwlock_t			fgLock;	
+	static bool						fgRegisteredForDyldUnloads;	
+	// can't use std::vector<> here because this code must live in libSystem.dylib (which is below libstdc++.dylib)
+	static entry*					fgBuffer;
+	static entry*					fgBufferUsed;
+	static entry*					fgBufferEnd;
+	static entry					fgInitialBuffer[64];
+};
+
+template <typename A> typename DwarfFDECache<A>::entry* DwarfFDECache<A>::fgBuffer		= fgInitialBuffer;
+template <typename A> typename DwarfFDECache<A>::entry* DwarfFDECache<A>::fgBufferUsed	= fgInitialBuffer;
+template <typename A> typename DwarfFDECache<A>::entry* DwarfFDECache<A>::fgBufferEnd	= &fgInitialBuffer[64];
+template <typename A> typename DwarfFDECache<A>::entry  DwarfFDECache<A>::fgInitialBuffer[64];
+
+template <typename A>
+pthread_rwlock_t DwarfFDECache<A>::fgLock = PTHREAD_RWLOCK_INITIALIZER;
+
+template <typename A> 
+bool DwarfFDECache<A>::fgRegisteredForDyldUnloads = false;
+
+
+template <typename A>
+typename A::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc)
+{
+	pint_t result = NULL;
+	DEBUG_LOG_NON_ZERO(::pthread_rwlock_rdlock(&fgLock));
+	for(entry* p=fgBuffer; p < fgBufferUsed; ++p) {
+		if ( (mh == p->mh) || (mh == 0) ) {
+			if ( (p->ip_start <= pc) && (pc < p->ip_end) ) {
+				result = p->fde;
+				break;
+			}
+		}
+	}
+	DEBUG_LOG_NON_ZERO(::pthread_rwlock_unlock(&fgLock));
+	//fprintf(stderr, "DwarfFDECache::findFDE(mh=0x%llX, pc=0x%llX) => 0x%llX\n", (uint64_t)mh, (uint64_t)pc, (uint64_t)result);
+	return result;
+}
+
+template <typename A>
+void DwarfFDECache<A>::add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde)
+{
+	//fprintf(stderr, "DwarfFDECache::add(mh=0x%llX, ip_start=0x%llX, ip_end=0x%llX, fde=0x%llX) pthread=%p\n", 
+	//		(uint64_t)mh, (uint64_t)ip_start, (uint64_t)ip_end, (uint64_t)fde, pthread_self());
+	DEBUG_LOG_NON_ZERO(::pthread_rwlock_wrlock(&fgLock));
+	if ( fgBufferUsed >= fgBufferEnd ) {
+		int oldSize = fgBufferEnd - fgBuffer;
+		int newSize = oldSize*4;
+		entry* newBuffer = (entry*)malloc(newSize*sizeof(entry));	// can't use operator new in libSystem.dylib
+		memcpy(newBuffer, fgBuffer, oldSize*sizeof(entry));
+		//fprintf(stderr, "DwarfFDECache::add() growing buffer to %d\n",  newSize);
+		if ( fgBuffer != fgInitialBuffer )
+			free(fgBuffer);
+		fgBuffer = newBuffer;
+		fgBufferUsed = &newBuffer[oldSize];
+		fgBufferEnd = &newBuffer[newSize];
+	}
+	fgBufferUsed->mh = mh;
+	fgBufferUsed->ip_start = ip_start;
+	fgBufferUsed->ip_end = ip_end;
+	fgBufferUsed->fde = fde;
+	++fgBufferUsed;
+#if !defined (SUPPORT_REMOTE_UNWINDING)
+	if ( !fgRegisteredForDyldUnloads ) {
+		_dyld_register_func_for_remove_image(&dyldUnloadHook);
+		fgRegisteredForDyldUnloads = true;
+	}
+#endif
+	DEBUG_LOG_NON_ZERO(::pthread_rwlock_unlock(&fgLock));
+}
+
+
+
+template <typename A>
+void DwarfFDECache<A>::removeAllIn(pint_t mh)
+{
+	DEBUG_LOG_NON_ZERO(::pthread_rwlock_wrlock(&fgLock));
+	entry* d=fgBuffer;
+	for(const entry* s=fgBuffer; s < fgBufferUsed; ++s) {
+		if ( s->mh != mh ) {
+			if ( d != s ) 
+				*d = *s;
+			++d;
+		}
+	}
+	fgBufferUsed = d;
+	DEBUG_LOG_NON_ZERO(::pthread_rwlock_unlock(&fgLock));
+}
+
+
+template <typename A>
+void DwarfFDECache<A>::dyldUnloadHook(const struct mach_header* mh, intptr_t vmaddr_slide)
+{
+#if !defined (SUPPORT_REMOTE_UNWINDING)
+	removeAllIn((pint_t)mh);
+#endif
+}
+
+template <typename A>
+void DwarfFDECache<A>::iterateCacheEntries(void (*func)(unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh))
+{
+	DEBUG_LOG_NON_ZERO(::pthread_rwlock_wrlock(&fgLock));
+	for(entry* p=fgBuffer; p < fgBufferUsed; ++p) {
+		(*func)(p->ip_start, p->ip_end, p->fde, p->mh);
+	}
+	DEBUG_LOG_NON_ZERO(::pthread_rwlock_unlock(&fgLock));
+}
+#endif // !FOR_DYLD
+
+
+
+
+#define arrayoffsetof(type, index, field) ((size_t)(&((type *)0)[index].field))
+
+template <typename A>
+class UnwindSectionHeader {
+public:
+					UnwindSectionHeader(A& addressSpace, typename A::pint_t addr) : fAddressSpace(addressSpace), fAddr(addr) {}
+
+	uint32_t		version() const								INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_section_header, version)); }
+	uint32_t		commonEncodingsArraySectionOffset() const	INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_section_header, commonEncodingsArraySectionOffset)); }
+	uint32_t		commonEncodingsArrayCount() const			INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_section_header, commonEncodingsArrayCount)); }
+	uint32_t		personalityArraySectionOffset() const		INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_section_header, personalityArraySectionOffset)); }
+	uint32_t		personalityArrayCount() const				INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_section_header, personalityArrayCount)); }
+	uint32_t		indexSectionOffset() const					INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_section_header, indexSectionOffset)); }
+	uint32_t		indexCount() const							INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_section_header, indexCount)); }
+private:
+	A&						fAddressSpace;
+	typename A::pint_t		fAddr;
+};
+
+template <typename A>
+class UnwindSectionIndexArray {
+public:
+					UnwindSectionIndexArray(A& addressSpace, typename A::pint_t addr) : fAddressSpace(addressSpace), fAddr(addr) {}
+
+	uint32_t		functionOffset(int index) const					INLINE { return fAddressSpace.get32(fAddr + arrayoffsetof(unwind_info_section_header_index_entry, index, functionOffset)); }
+	uint32_t		secondLevelPagesSectionOffset(int index) const	INLINE { return fAddressSpace.get32(fAddr + arrayoffsetof(unwind_info_section_header_index_entry, index, secondLevelPagesSectionOffset)); }
+	uint32_t		lsdaIndexArraySectionOffset(int index) const	INLINE { return fAddressSpace.get32(fAddr + arrayoffsetof(unwind_info_section_header_index_entry, index, lsdaIndexArraySectionOffset)); }
+private:
+	A&						fAddressSpace;
+	typename A::pint_t		fAddr;
+};
+
+
+template <typename A>
+class UnwindSectionRegularPageHeader {
+public:
+					UnwindSectionRegularPageHeader(A& addressSpace, typename A::pint_t addr) : fAddressSpace(addressSpace), fAddr(addr) {}
+
+	uint32_t		kind() const				INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_regular_second_level_page_header, kind)); }
+	uint16_t		entryPageOffset() const		INLINE { return fAddressSpace.get16(fAddr + offsetof(unwind_info_regular_second_level_page_header, entryPageOffset)); }
+	uint16_t		entryCount() const			INLINE { return fAddressSpace.get16(fAddr + offsetof(unwind_info_regular_second_level_page_header, entryCount)); }
+private:
+	A&						fAddressSpace;
+	typename A::pint_t		fAddr;
+};
+
+
+template <typename A>
+class UnwindSectionRegularArray {
+public:
+					UnwindSectionRegularArray(A& addressSpace, typename A::pint_t addr) : fAddressSpace(addressSpace), fAddr(addr) {}
+
+	uint32_t		functionOffset(int index) const		INLINE { return fAddressSpace.get32(fAddr + arrayoffsetof(unwind_info_regular_second_level_entry, index, functionOffset)); }
+	uint32_t		encoding(int index) const			INLINE { return fAddressSpace.get32(fAddr + arrayoffsetof(unwind_info_regular_second_level_entry, index, encoding)); }
+private:
+	A&						fAddressSpace;
+	typename A::pint_t		fAddr;
+};
+
+
+template <typename A>
+class UnwindSectionCompressedPageHeader {
+public:
+					UnwindSectionCompressedPageHeader(A& addressSpace, typename A::pint_t addr) : fAddressSpace(addressSpace), fAddr(addr) {}
+
+	uint32_t		kind() const				INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_compressed_second_level_page_header, kind)); }
+	uint16_t		entryPageOffset() const		INLINE { return fAddressSpace.get16(fAddr + offsetof(unwind_info_compressed_second_level_page_header, entryPageOffset)); }
+	uint16_t		entryCount() const			INLINE { return fAddressSpace.get16(fAddr + offsetof(unwind_info_compressed_second_level_page_header, entryCount)); }
+	uint16_t		encodingsPageOffset() const	INLINE { return fAddressSpace.get16(fAddr + offsetof(unwind_info_compressed_second_level_page_header, encodingsPageOffset)); }
+	uint16_t		encodingsCount() const		INLINE { return fAddressSpace.get16(fAddr + offsetof(unwind_info_compressed_second_level_page_header, encodingsCount)); }
+private:
+	A&						fAddressSpace;
+	typename A::pint_t		fAddr;
+};
+
+
+template <typename A>
+class UnwindSectionCompressedArray {
+public:
+					UnwindSectionCompressedArray(A& addressSpace, typename A::pint_t addr) : fAddressSpace(addressSpace), fAddr(addr) {}
+
+	uint32_t		functionOffset(int index) const		INLINE { return UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET( fAddressSpace.get32(fAddr + index*sizeof(uint32_t)) ); }
+	uint16_t		encodingIndex(int index) const		INLINE { return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX( fAddressSpace.get32(fAddr + index*sizeof(uint32_t)) ); }
+private:
+	A&						fAddressSpace;
+	typename A::pint_t		fAddr;
+};
+
+
+template <typename A>
+class UnwindSectionLsdaArray {
+public:
+					UnwindSectionLsdaArray(A& addressSpace, typename A::pint_t addr) : fAddressSpace(addressSpace), fAddr(addr) {}
+
+	uint32_t		functionOffset(int index) const		INLINE { return fAddressSpace.get32(fAddr + arrayoffsetof(unwind_info_section_header_lsda_index_entry, index, functionOffset)); }
+	int32_t			lsdaOffset(int index) const			INLINE { return fAddressSpace.get32(fAddr + arrayoffsetof(unwind_info_section_header_lsda_index_entry, index, lsdaOffset)); }
+private:
+	A&						fAddressSpace;
+	typename A::pint_t		fAddr;
+};
+
+
+template <typename A, typename R>
+class UnwindCursor
+{
+public:
+						UnwindCursor(unw_context_t* context, A& as);
+	virtual				~UnwindCursor() {}
+	virtual bool		validReg(int);
+	virtual uint64_t	getReg(int);
+	virtual int	        getReg(int, uint64_t*);
+	virtual int		    setReg(int, uint64_t);
+	virtual bool		validFloatReg(int);
+	virtual double		getFloatReg(int);
+	virtual int		    getFloatReg(int, double*);
+	virtual int 		setFloatReg(int, double);
+    virtual int         step();
+	virtual void		getInfo(unw_proc_info_t*);
+	virtual void		jumpto();
+	virtual const char*	getRegisterName(int num);
+	virtual bool		isSignalFrame();
+	virtual bool		getFunctionName(char* buf, size_t bufLen, unw_word_t* offset);
+	virtual void		setInfoBasedOnIPRegister(bool isReturnAddress=false);
+
+	void		        operator delete(void* p, size_t size) {}
+
+protected:
+	typedef typename A::pint_t		pint_t;	
+	typedef uint32_t				EncodedUnwindInfo;
+
+	virtual bool				getInfoFromCompactEncodingSection(pint_t pc, pint_t mh, pint_t unwindSectionStart);
+	virtual bool				getInfoFromDwarfSection(pint_t pc, pint_t mh, pint_t ehSectionStart, uint32_t sectionLength, uint32_t sectionOffsetOfFDE);
+
+	virtual int					stepWithDwarfFDE() 
+							{ return DwarfInstructions<A,R>::stepWithDwarf(fAddressSpace, this->getReg(UNW_REG_IP), fInfo.unwind_info, fRegisters); }
+	
+    virtual int                 stepWithCompactEncoding() { R dummy; return stepWithCompactEncoding(dummy); }
+	int					stepWithCompactEncoding(Registers_x86_64&) 
+							{ return CompactUnwinder_x86_64<A>::stepWithCompactEncoding(fInfo.format, fInfo.start_ip, fAddressSpace, fRegisters); }
+	int					stepWithCompactEncoding(Registers_x86&) 
+							{ return CompactUnwinder_x86<A>::stepWithCompactEncoding(fInfo.format, fInfo.start_ip, fAddressSpace, fRegisters); }
+	int					stepWithCompactEncoding(Registers_ppc&) 
+							{ return UNW_EINVAL; }
+
+#if FOR_DYLD
+  #if __ppc__
+	virtual bool				mustUseDwarf() const { return true; }
+  #else
+	virtual bool				mustUseDwarf() const { return false; }
+  #endif
+#else
+    virtual bool                mustUseDwarf() const { R dummy; uint32_t offset; return dwarfWithOffset(dummy, offset); }
+#endif
+
+    virtual bool                dwarfWithOffset(uint32_t& offset) const { R dummy; return dwarfWithOffset(dummy, offset); }
+	virtual bool				dwarfWithOffset(Registers_x86_64&, uint32_t& offset) const { 
+							if ( (fInfo.format & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF ) {
+								offset = (fInfo.format & UNWIND_X86_64_DWARF_SECTION_OFFSET);
+								return true;
+							}
+#if SUPPORT_OLD_BINARIES
+							if ( (fInfo.format & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_COMPATIBILITY ) {
+								if ( (fInfo.format & UNWIND_X86_64_CASE_MASK) == UNWIND_X86_64_UNWIND_REQUIRES_DWARF ) {
+									offset = 0;
+									return true;
+								}
+							}
+#endif
+							return false;
+						}
+	virtual bool				dwarfWithOffset(Registers_x86&, uint32_t& offset) const { 
+							if ( (fInfo.format & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_DWARF ) {
+								offset = (fInfo.format & UNWIND_X86_DWARF_SECTION_OFFSET);
+								return true;
+							}
+#if SUPPORT_OLD_BINARIES
+							if ( (fInfo.format & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_COMPATIBILITY ) {
+								if ( (fInfo.format & UNWIND_X86_CASE_MASK) == UNWIND_X86_UNWIND_REQUIRES_DWARF ) {
+									offset = 0;
+									return true;
+								}
+							}
+#endif
+							return false;
+						}
+	virtual bool				dwarfWithOffset(Registers_ppc&, uint32_t& offset) const { return true; }
+	
+
+    virtual compact_unwind_encoding_t       dwarfEncoding() const { R dummy; return dwarfEncoding(dummy); }
+	virtual compact_unwind_encoding_t		dwarfEncoding(Registers_x86_64&) const { return UNWIND_X86_64_MODE_DWARF; }
+	virtual compact_unwind_encoding_t		dwarfEncoding(Registers_x86&)	const { return UNWIND_X86_MODE_DWARF; }
+	virtual compact_unwind_encoding_t		dwarfEncoding(Registers_ppc&)	const { return 0; }
+
+	unw_proc_info_t				fInfo;
+	R							fRegisters;
+	A&							fAddressSpace;
+	bool						fUnwindInfoMissing;
+	bool						fIsSignalFrame;
+};
+
+typedef UnwindCursor<LocalAddressSpace,Registers_x86> AbstractUnwindCursor;
+
+template <typename A, typename R>
+UnwindCursor<A,R>::UnwindCursor(unw_context_t* context, A& as)
+  : fRegisters(context), fAddressSpace(as), fUnwindInfoMissing(false), fIsSignalFrame(false)
+{
+	COMPILE_TIME_ASSERT( sizeof(UnwindCursor<A,R>) < sizeof(unw_cursor_t) );
+
+	bzero(&fInfo, sizeof(fInfo));
+}
+
+template <typename A, typename R>
+bool UnwindCursor<A,R>::validReg(int regNum) 
+{ 
+	return fRegisters.validRegister(regNum); 
+}
+
+template <typename A, typename R>
+uint64_t UnwindCursor<A,R>::getReg(int regNum) 
+{ 
+	return fRegisters.getRegister(regNum); 
+}
+
+template <typename A, typename R>
+int UnwindCursor<A,R>::getReg(int regNum, uint64_t *valp) 
+{ 
+	*valp = fRegisters.getRegister(regNum);
+    return UNW_ESUCCESS;
+}
+
+template <typename A, typename R>
+int UnwindCursor<A,R>::setReg(int regNum, uint64_t value) 
+{ 
+	fRegisters.setRegister(regNum, value); 
+    return UNW_ESUCCESS;
+}
+
+template <typename A, typename R>
+bool UnwindCursor<A,R>::validFloatReg(int regNum) 
+{ 
+	return fRegisters.validFloatRegister(regNum); 
+}
+
+template <typename A, typename R>
+double UnwindCursor<A,R>::getFloatReg(int regNum) 
+{ 
+	return fRegisters.getFloatRegister(regNum); 
+}
+
+template <typename A, typename R>
+int UnwindCursor<A,R>::getFloatReg(int regNum, double *valp) 
+{ 
+	*valp = fRegisters.getFloatRegister(regNum); 
+    return UNW_ESUCCESS;
+}
+
+template <typename A, typename R>
+int UnwindCursor<A,R>::setFloatReg(int regNum, double value) 
+{ 
+	fRegisters.setFloatRegister(regNum, value); 
+    return UNW_ESUCCESS;
+}
+
+template <typename A, typename R>
+void UnwindCursor<A,R>::jumpto() 
+{ 
+#if !defined (SUPPORT_REMOTE_UNWINDING)
+	fRegisters.jumpto(); 
+#endif
+}
+
+template <typename A, typename R>
+const char* UnwindCursor<A,R>::getRegisterName(int regNum) 
+{ 
+	return fRegisters.getRegisterName(regNum); 
+}
+
+template <typename A, typename R>
+bool UnwindCursor<A,R>::isSignalFrame() 
+{ 
+	 return fIsSignalFrame;
+}
+
+
+template <typename A, typename R>
+bool UnwindCursor<A,R>::getInfoFromDwarfSection(pint_t pc, pint_t mh, pint_t ehSectionStart, uint32_t sectionLength, uint32_t sectionOffsetOfFDE)
+{
+	typename CFI_Parser<A>::FDE_Info fdeInfo;
+	typename CFI_Parser<A>::CIE_Info cieInfo;
+	bool foundFDE = false;
+	bool foundInCache = false;
+	// if compact encoding table gave offset into dwarf section, go directly there
+	if ( sectionOffsetOfFDE != 0 ) {
+		foundFDE = CFI_Parser<A>::findFDE(fAddressSpace, pc, ehSectionStart, sectionLength, ehSectionStart+sectionOffsetOfFDE, &fdeInfo, &cieInfo);
+	}
+#if !FOR_DYLD
+	if ( !foundFDE ) {
+		// otherwise, search cache of previously found FDEs
+		pint_t cachedFDE = DwarfFDECache<A>::findFDE(mh, pc);
+		//fprintf(stderr, "getInfoFromDwarfSection(pc=0x%llX) cachedFDE=0x%llX\n", (uint64_t)pc, (uint64_t)cachedFDE);
+		if ( cachedFDE != 0 ) {
+			foundFDE = CFI_Parser<A>::findFDE(fAddressSpace, pc, ehSectionStart, sectionLength, cachedFDE, &fdeInfo, &cieInfo);
+			foundInCache = foundFDE;
+			//fprintf(stderr, "cachedFDE=0x%llX, foundInCache=%d\n", (uint64_t)cachedFDE, foundInCache);
+		}
+	}
+#endif
+	if ( !foundFDE ) {
+		// still not found, do full scan of __eh_frame section
+		foundFDE = CFI_Parser<A>::findFDE(fAddressSpace, pc, ehSectionStart, sectionLength, 0, &fdeInfo, &cieInfo);
+	}
+	if ( foundFDE ) {
+		typename CFI_Parser<A>::PrologInfo prolog;
+		if ( CFI_Parser<A>::parseFDEInstructions(fAddressSpace, fdeInfo, cieInfo, pc, &prolog) ) {
+			// save off parsed FDE info
+			fInfo.start_ip			= fdeInfo.pcStart;
+			fInfo.end_ip			= fdeInfo.pcEnd;
+			fInfo.lsda				= fdeInfo.lsda;
+			fInfo.handler			= cieInfo.personality;
+			fInfo.gp				= prolog.spExtraArgSize;  // some frameless functions need SP altered when resuming in function
+			fInfo.flags				= 0;
+			fInfo.format			= dwarfEncoding();  
+			fInfo.unwind_info		= fdeInfo.fdeStart;
+			fInfo.unwind_info_size	= fdeInfo.fdeLength;
+			fInfo.extra				= (unw_word_t)mh;
+			if ( !foundInCache && (sectionOffsetOfFDE == 0) ) {
+				// don't add to cache entries the compact encoding table can find quickly
+				//fprintf(stderr, "getInfoFromDwarfSection(pc=0x%0llX), mh=0x%llX, start_ip=0x%0llX, fde=0x%0llX, personality=0x%0llX\n", 
+				//	(uint64_t)pc, (uint64_t)mh, fInfo.start_ip, fInfo.unwind_info, fInfo.handler);
+#if !FOR_DYLD
+				DwarfFDECache<A>::add(mh, fdeInfo.pcStart, fdeInfo.pcEnd, fdeInfo.fdeStart);
+#endif
+			}
+			return true;
+		}
+	}
+	//DEBUG_MESSAGE("can't find/use FDE for pc=0x%llX\n", (uint64_t)pc);
+	return false;
+}
+
+template <typename A, typename R>
+bool UnwindCursor<A,R>::getInfoFromCompactEncodingSection(pint_t pc, pint_t mh, pint_t unwindSectionStart)
+{	
+	const bool log = false;
+	if ( log ) fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n", (uint64_t)pc, (uint64_t)mh);
+	
+	const UnwindSectionHeader<A> sectionHeader(fAddressSpace, unwindSectionStart);
+	if ( sectionHeader.version() != UNWIND_SECTION_VERSION )
+		return false;
+	
+	// do a binary search of top level index to find page with unwind info
+	uint32_t targetFunctionOffset = pc - mh;
+	const UnwindSectionIndexArray<A> topIndex(fAddressSpace, unwindSectionStart + sectionHeader.indexSectionOffset());
+	uint32_t low = 0;
+	uint32_t high = sectionHeader.indexCount();
+	const uint32_t last = high - 1;
+	while ( low < high ) {
+		uint32_t mid = (low + high)/2;
+		//if ( log ) fprintf(stderr, "\tmid=%d, low=%d, high=%d, *mid=0x%08X\n", mid, low, high, topIndex.functionOffset(mid));
+		if ( topIndex.functionOffset(mid) <= targetFunctionOffset ) {
+			if ( (mid == last) || (topIndex.functionOffset(mid+1) > targetFunctionOffset) ) {
+				low = mid;
+				break;
+			}
+			else {
+				low = mid+1;
+			}
+		}
+		else {
+			high = mid;
+		}
+	}
+	const uint32_t firstLevelFunctionOffset = topIndex.functionOffset(low);
+	const uint32_t firstLevelNextPageFunctionOffset = topIndex.functionOffset(low+1);
+	const pint_t secondLevelAddr    = unwindSectionStart+topIndex.secondLevelPagesSectionOffset(low);
+	const pint_t lsdaArrayStartAddr = unwindSectionStart+topIndex.lsdaIndexArraySectionOffset(low);
+	const pint_t lsdaArrayEndAddr   = unwindSectionStart+topIndex.lsdaIndexArraySectionOffset(low+1);
+	if ( log ) fprintf(stderr, "\tfirst level search for result index=%d to secondLevelAddr=0x%llX\n", 
+			low, (uint64_t)secondLevelAddr);
+	// do a binary search of second level page index
+	uint32_t encoding = 0;
+	pint_t funcStart = 0;
+	pint_t funcEnd = 0;
+	pint_t lsda = 0;
+	pint_t personality = 0;
+	uint32_t pageKind = fAddressSpace.get32(secondLevelAddr);
+	if ( pageKind == UNWIND_SECOND_LEVEL_REGULAR ) {
+		// regular page
+		UnwindSectionRegularPageHeader<A> pageHeader(fAddressSpace, secondLevelAddr);
+		UnwindSectionRegularArray<A> pageIndex(fAddressSpace, secondLevelAddr + pageHeader.entryPageOffset());
+		// binary search looks for entry with e where index[e].offset <= pc < index[e+1].offset
+		if ( log ) fprintf(stderr, "\tbinary search for targetFunctionOffset=0x%08llX in regular page starting at secondLevelAddr=0x%llX\n", 
+			(uint64_t)targetFunctionOffset, (uint64_t)secondLevelAddr);
+		uint32_t low = 0;
+		uint32_t high = pageHeader.entryCount();
+		while ( low < high ) {
+			uint32_t mid = (low + high)/2;
+			if ( pageIndex.functionOffset(mid) <= targetFunctionOffset ) {
+				if ( mid == (uint32_t)(pageHeader.entryCount()-1) ) {
+					// at end of table
+					low = mid;
+					funcEnd = firstLevelNextPageFunctionOffset + mh;
+					break;
+				}
+				else if ( pageIndex.functionOffset(mid+1) > targetFunctionOffset ) {
+					// next is too big, so we found it
+					low = mid;
+					funcEnd = pageIndex.functionOffset(low+1) + mh;
+					break;
+				}
+				else {
+					low = mid+1;
+				}
+			}
+			else {
+				high = mid;
+			}
+		}
+		encoding  = pageIndex.encoding(low);
+		funcStart = pageIndex.functionOffset(low) + mh;
+		if ( pc < funcStart  ) {
+			if ( log ) fprintf(stderr, "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n", (uint64_t)pc, (uint64_t)funcStart, (uint64_t)funcEnd);
+			return false;
+		}
+		if ( pc > funcEnd ) {
+			if ( log ) fprintf(stderr, "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n", (uint64_t)pc, (uint64_t)funcStart, (uint64_t)funcEnd);
+			return false;
+		}
+	}
+	else if ( pageKind == UNWIND_SECOND_LEVEL_COMPRESSED ) {
+		// compressed page
+		UnwindSectionCompressedPageHeader<A> pageHeader(fAddressSpace, secondLevelAddr);
+		UnwindSectionCompressedArray<A> pageIndex(fAddressSpace, secondLevelAddr + pageHeader.entryPageOffset());
+		const uint32_t targetFunctionPageOffset = targetFunctionOffset - firstLevelFunctionOffset;
+		// binary search looks for entry with e where index[e].offset <= pc < index[e+1].offset
+		if ( log ) fprintf(stderr, "\tbinary search of compressed page starting at secondLevelAddr=0x%llX\n", (uint64_t)secondLevelAddr);
+		uint32_t low = 0;
+		const uint32_t last = pageHeader.entryCount() - 1;
+		uint32_t high = pageHeader.entryCount();
+		while ( low < high ) {
+			uint32_t mid = (low + high)/2;
+			if ( pageIndex.functionOffset(mid) <= targetFunctionPageOffset ) {
+				if ( (mid == last) || (pageIndex.functionOffset(mid+1) > targetFunctionPageOffset) ) {
+					low = mid;
+					break;
+				}
+				else {
+					low = mid+1;
+				}
+			}
+			else {
+				high = mid;
+			}
+		}
+		funcStart = pageIndex.functionOffset(low) + firstLevelFunctionOffset + mh;
+		if ( low < last )
+			funcEnd = pageIndex.functionOffset(low+1) + firstLevelFunctionOffset + mh;
+		else
+			funcEnd = firstLevelNextPageFunctionOffset + mh;
+		if ( pc < funcStart  ) {
+			DEBUG_MESSAGE("malformed __unwind_info, pc=0x%llX not in second level compressed unwind table. funcStart=0x%llX\n", (uint64_t)pc, (uint64_t)funcStart);
+			return false;
+		}
+		if ( pc > funcEnd ) {
+			DEBUG_MESSAGE("malformed __unwind_info, pc=0x%llX not in second level compressed unwind table. funcEnd=0x%llX\n", (uint64_t)pc, (uint64_t)funcEnd);
+			return false;
+		}
+		uint16_t encodingIndex = pageIndex.encodingIndex(low);
+		if ( encodingIndex < sectionHeader.commonEncodingsArrayCount() ) {
+			// encoding is in common table in section header
+			encoding = fAddressSpace.get32(unwindSectionStart+sectionHeader.commonEncodingsArraySectionOffset()+encodingIndex*sizeof(uint32_t));
+		}
+		else {
+			// encoding is in page specific table
+			uint16_t pageEncodingIndex = encodingIndex-sectionHeader.commonEncodingsArrayCount();
+			encoding = fAddressSpace.get32(secondLevelAddr+pageHeader.encodingsPageOffset()+pageEncodingIndex*sizeof(uint32_t));
+		}
+	}
+	else {
+		DEBUG_MESSAGE("malformed __unwind_info at 0x%0llX bad second level page\n", (uint64_t)unwindSectionStart);
+		return false;
+	}
+
+	// look up LSDA, if encoding says function has one
+	if ( encoding & UNWIND_HAS_LSDA ) {
+		UnwindSectionLsdaArray<A>  lsdaIndex(fAddressSpace, lsdaArrayStartAddr);
+		uint32_t funcStartOffset = funcStart - mh;
+		uint32_t low = 0;
+		uint32_t high = (lsdaArrayEndAddr-lsdaArrayStartAddr)/sizeof(unwind_info_section_header_lsda_index_entry);
+		// binary search looks for entry with exact match for functionOffset
+		if ( log ) fprintf(stderr, "\tbinary search of lsda table for targetFunctionOffset=0x%08X\n", funcStartOffset);
+		while ( low < high ) {
+			uint32_t mid = (low + high)/2;
+			if ( lsdaIndex.functionOffset(mid) == funcStartOffset ) {
+				lsda = lsdaIndex.lsdaOffset(mid) + mh;
+				break;
+			}
+			else if ( lsdaIndex.functionOffset(mid) < funcStartOffset ) {
+				low = mid+1;
+			}
+			else {
+				high = mid;
+			}
+		}
+		if ( lsda == 0 ) {
+			DEBUG_MESSAGE("found encoding 0x%08X with HAS_LSDA bit set for pc=0x%0llX, but lsda table has no entry\n", encoding, (uint64_t)pc);
+			return false;
+		}
+	}
+
+	// extact personality routine, if encoding says function has one
+	uint32_t personalityIndex = (encoding & UNWIND_PERSONALITY_MASK) >> (__builtin_ctz(UNWIND_PERSONALITY_MASK));	
+	if ( personalityIndex != 0 ) {
+		--personalityIndex; // change 1-based to zero-based index
+		if ( personalityIndex > sectionHeader.personalityArrayCount() ) {
+			DEBUG_MESSAGE("found encoding 0x%08X with personality index %d, but personality table has only %d entires\n", 
+							encoding, personalityIndex, sectionHeader.personalityArrayCount());
+			return false;
+		}
+		int32_t personalityDelta = fAddressSpace.get32(unwindSectionStart+sectionHeader.personalityArraySectionOffset()+personalityIndex*sizeof(uint32_t));
+		pint_t personalityPointer = personalityDelta + mh;
+		personality = fAddressSpace.getP(personalityPointer);
+		if (log ) fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), personalityDelta=0x%08X, personality=0x%08llX\n", 
+			(uint64_t)pc, personalityDelta, (uint64_t)personality);
+	}
+	
+	if (log ) fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), encoding=0x%08X, lsda=0x%08llX for funcStart=0x%llX\n", 
+						(uint64_t)pc, encoding, (uint64_t)lsda, (uint64_t)funcStart);
+	fInfo.start_ip			= funcStart; 
+	fInfo.end_ip			= funcEnd;
+	fInfo.lsda				= lsda; 
+	fInfo.handler			= personality;
+	fInfo.gp				= 0;
+	fInfo.flags				= 0;
+	fInfo.format			= encoding;
+	fInfo.unwind_info		= 0;
+	fInfo.unwind_info_size	= 0;
+	fInfo.extra				= mh;
+	return true;
+}
+
+template <typename A, typename R>
+void UnwindCursor<A,R>::setInfoBasedOnIPRegister(bool isReturnAddress)
+{
+	pint_t pc = this->getReg(UNW_REG_IP);
+	
+	// if the last line of a function is a "throw" the compile sometimes
+	// emits no instructions after the call to __cxa_throw.  This means 
+	// the return address is actually the start of the next function.
+	// To disambiguate this, back up the pc when we know it is a return
+	// address.  
+	if ( isReturnAddress ) 
+		--pc;
+	
+	// ask address space object to find unwind sections for this pc
+	pint_t mh;
+	pint_t dwarfStart;
+	pint_t dwarfLength;
+	pint_t compactStart;
+	if ( fAddressSpace.findUnwindSections(pc, mh, dwarfStart, dwarfLength, compactStart) ) {
+		// if there is a compact unwind encoding table, look there first
+		if ( compactStart != 0 ) {
+			if ( this->getInfoFromCompactEncodingSection(pc, mh, compactStart) ) {
+#if !FOR_DYLD
+				// found info in table, done unless encoding says to use dwarf
+				uint32_t offsetInDwarfSection;
+				if ( (dwarfStart != 0) && dwarfWithOffset(offsetInDwarfSection) ) {
+					if ( this->getInfoFromDwarfSection(pc, mh, dwarfStart, dwarfLength, offsetInDwarfSection) ) {
+						// found info in dwarf, done
+						return;
+					}
+				}
+#endif
+				// if unwind table has entry, but entry says there is no unwind info, note that
+				if ( fInfo.format == 0 )
+					fUnwindInfoMissing = true;
+
+				// old compact encoding 
+				if ( !mustUseDwarf() ) {
+					return;
+				}	
+			}
+		}
+#if !FOR_DYLD || __ppc__
+		// if there is dwarf unwind info, look there next
+		if ( dwarfStart != 0 ) {
+			if ( this->getInfoFromDwarfSection(pc, mh, dwarfStart, dwarfLength, 0) ) {
+				// found info in dwarf, done
+				return;
+			}
+		}
+#endif
+	}
+	
+#if !FOR_DYLD 
+	// the PC is not in code loaded by dyld, look through __register_frame() registered FDEs
+	pint_t cachedFDE = DwarfFDECache<A>::findFDE(0, pc);
+	if ( cachedFDE != 0 ) {
+		typename CFI_Parser<A>::FDE_Info fdeInfo;
+		typename CFI_Parser<A>::CIE_Info cieInfo;
+		const char* msg = CFI_Parser<A>::decodeFDE(fAddressSpace, cachedFDE, &fdeInfo, &cieInfo);
+		if ( msg == NULL ) {
+			typename CFI_Parser<A>::PrologInfo prolog;
+			if ( CFI_Parser<A>::parseFDEInstructions(fAddressSpace, fdeInfo, cieInfo, pc, &prolog) ) {
+				// save off parsed FDE info
+				fInfo.start_ip			= fdeInfo.pcStart;
+				fInfo.end_ip			= fdeInfo.pcEnd;
+				fInfo.lsda				= fdeInfo.lsda;
+				fInfo.handler			= cieInfo.personality;
+				fInfo.gp				= prolog.spExtraArgSize;  // some frameless functions need SP altered when resuming in function
+				fInfo.flags				= 0;
+				fInfo.format			= dwarfEncoding();  
+				fInfo.unwind_info		= fdeInfo.fdeStart;
+				fInfo.unwind_info_size	= fdeInfo.fdeLength;
+				fInfo.extra				= 0;
+				return;
+			}
+		}
+	}
+	
+#if !defined (SUPPORT_REMOTE_UNWINDING)
+	// lastly check for old style keymgr registration of dynamically generated FDEs
+	
+	// acquire exclusive access to libgcc_object_info
+	libgcc_object_info* head = (libgcc_object_info*)_keymgr_get_and_lock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST);
+	if ( head != NULL ) {
+		// look at each FDE in keymgr
+		for (libgcc_object* ob = head->unseen_objects; ob != NULL; ob = ob->next) {
+			typename CFI_Parser<A>::FDE_Info fdeInfo;
+			typename CFI_Parser<A>::CIE_Info cieInfo;
+			const char* msg = CFI_Parser<A>::decodeFDE(fAddressSpace, (pint_t)ob->fde, &fdeInfo, &cieInfo);
+			if ( msg == NULL ) {
+				// see if this FDE is for a function that includes the pc we are looking for
+				if ( (fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd) ) {
+					typename CFI_Parser<A>::PrologInfo prolog;
+					if ( CFI_Parser<A>::parseFDEInstructions(fAddressSpace, fdeInfo, cieInfo, pc, &prolog) ) {
+						// save off parsed FDE info
+						fInfo.start_ip			= fdeInfo.pcStart;
+						fInfo.end_ip			= fdeInfo.pcEnd;
+						fInfo.lsda				= fdeInfo.lsda;
+						fInfo.handler			= cieInfo.personality;
+						fInfo.gp				= prolog.spExtraArgSize;  // some frameless functions need SP altered when resuming in function
+						fInfo.flags				= 0;
+						fInfo.format			= dwarfEncoding();  
+						fInfo.unwind_info		= fdeInfo.fdeStart;
+						fInfo.unwind_info_size	= fdeInfo.fdeLength;
+						fInfo.extra				= 0;
+						_keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, head);
+						return;
+					}
+				}
+			}
+		}
+	}
+	// release libgcc_object_info 
+	_keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, head);
+#endif // !SUPPORT_REMOTE_UNWINDING
+
+#endif // !FOR_DYLD
+
+	// no unwind info, flag that we can't reliable unwind
+	fUnwindInfoMissing = true;
+}
+
+
+template <typename A, typename R>
+int UnwindCursor<A,R>::step()
+{
+	// bottom of stack is defined as when no more unwind info
+	if ( fUnwindInfoMissing )
+			return UNW_STEP_END;
+
+	// apply unwinding to register set
+	int result;
+	if ( this->mustUseDwarf() )
+		result = this->stepWithDwarfFDE();
+	else
+		result = this->stepWithCompactEncoding();
+	
+	// update info based on new PC
+	if ( result == UNW_STEP_SUCCESS ) {
+		this->setInfoBasedOnIPRegister(true);
+		if ( fUnwindInfoMissing )
+			return UNW_STEP_END;
+	}
+
+	return result;
+}
+
+
+template <typename A, typename R>
+void UnwindCursor<A,R>::getInfo(unw_proc_info_t* info)
+{
+	*info = fInfo;
+}
+
+
+template <typename A, typename R>
+bool UnwindCursor<A,R>::getFunctionName(char* buf, size_t bufLen, unw_word_t* offset)
+{
+	return fAddressSpace.findFunctionName(this->getReg(UNW_REG_IP), buf, bufLen, offset);
+}
+
+#if defined (SUPPORT_REMOTE_UNWINDING)
+template <typename A, typename R>
+class RemoteUnwindCursor : UnwindCursor<A,R>
+{
+public:
+	typedef typename A::pint_t	pint_t;
+                        RemoteUnwindCursor(A& as, unw_context_t* regs, void* arg);
+    virtual bool        validReg(int);
+    virtual int         getReg(int r, uint64_t*);
+    virtual int         setReg(int, uint64_t);
+    virtual bool        validFloatReg(int);
+    virtual int         getFloatReg(int, double*);
+    virtual int         setFloatReg(int, double);
+    virtual const char* getRegisterName(int);
+    virtual int         step();
+    virtual void        setRemoteContext(void*);
+    virtual bool        remoteUnwindCursor () const {return this->fAddressSpace.getRemoteProcInfo() != NULL; }
+    virtual int         endOfPrologueInsns(unw_word_t, unw_word_t, unw_word_t*);
+	void		        operator delete(void* p, size_t size) {}
+private:
+    virtual bool        caller_regno_to_unwind_regno (int, int&);
+
+    bool                fIsLeafFrame;
+    bool                fIsFirstFrame;
+    void*               fArg;
+};
+
+typedef RemoteUnwindCursor<LocalAddressSpace,Registers_x86_64> AbstractRemoteUnwindCursor;
+
+template <typename A, typename R>
+RemoteUnwindCursor<A,R>::RemoteUnwindCursor(A& as, unw_context_t* regs, void* arg)
+   : UnwindCursor<A,R>::UnwindCursor(regs, as), fIsFirstFrame (false), fIsLeafFrame(false), fArg(arg)
+{
+    COMPILE_TIME_ASSERT( sizeof(RemoteUnwindCursor<A,R>) < sizeof(unw_cursor_t) );
+}
+
+template <typename A, typename R>
+bool RemoteUnwindCursor<A,R>::validReg(int r)
+{
+    int unwind_regno;
+    if (!caller_regno_to_unwind_regno(r, unwind_regno))
+        return false;
+    return UnwindCursor<A,R>::fRegisters.validRegister(unwind_regno);
+}
+
+template <typename A, typename R>
+int RemoteUnwindCursor<A,R>::getReg(int regNum, uint64_t *valp)
+{
+    RemoteProcInfo *procinfo = UnwindCursor<A,R>::fAddressSpace.getRemoteProcInfo ();
+    if (procinfo == NULL) {
+       ABORT("getRemoteReg called with a local unwind, use getReg instead.");
+    }
+
+    RemoteRegisterMap *regmap = procinfo->getRegisterMap ();
+    int unwind_regno;
+    if (regmap->caller_regno_to_unwind_regno (regNum, unwind_regno) == false)
+        return UNW_EBADREG;
+    regNum = unwind_regno;
+
+    // we always return nonvolatile registers.  If we have the entire register state available
+    // for this frame then we can return any register requested.
+    if (regmap->nonvolatile_reg_p (regNum) == true || fIsLeafFrame == true) {
+        return this->UnwindCursor<A,R>::getReg (unwind_regno, valp);
+    }
+    return UNW_EREGUNAVAILABLE;
+}
+
+template <typename A, typename R>
+int RemoteUnwindCursor<A,R>::setReg(int regNum, uint64_t val)
+{
+    RemoteProcInfo *procinfo = UnwindCursor<A,R>::fAddressSpace.getRemoteProcInfo ();
+    if (procinfo == NULL) {
+       ABORT("setRemoteReg called with a local unwind, use setReg instead.");
+    }
+
+    RemoteRegisterMap *regmap = procinfo->getRegisterMap ();
+    int unwind_regno;
+    if (regmap->caller_regno_to_unwind_regno (regNum, unwind_regno) == false)
+        return UNW_EBADREG;
+    regNum = unwind_regno;
+
+    // Only allow the registers to be set if the unwind cursor is pointing to the
+    // first frame.  We need to track where registers were retrieved from in memory
+    // in every other frame.  Until then, we prohibit register setting in all but
+    // the first frame.
+    if (fIsFirstFrame) {
+        return this->setReg(unwind_regno, val);
+    }
+    return UNW_EREGUNAVAILABLE;
+}
+
+template <typename A, typename R>
+bool RemoteUnwindCursor<A,R>::validFloatReg(int r)
+{
+    int unwind_regno;
+    if (!caller_regno_to_unwind_regno(r, unwind_regno))
+        return false;
+    return UnwindCursor<A,R>::fRegisters.validFloatRegister(unwind_regno);
+}
+
+template <typename A, typename R>
+int RemoteUnwindCursor<A,R>::getFloatReg(int regNum, double *valp)
+{
+    RemoteProcInfo *procinfo = UnwindCursor<A,R>::fAddressSpace.getRemoteProcInfo ();
+    if (procinfo == NULL) {
+       ABORT("getRemoteReg called with a local unwind, use getReg instead.");
+    }
+
+    RemoteRegisterMap *regmap = procinfo->getRegisterMap ();
+    int unwind_regno;
+    if (regmap->caller_regno_to_unwind_regno (regNum, unwind_regno) == false)
+        return UNW_EBADREG;
+    regNum = unwind_regno;
+
+    // we always return nonvolatile registers.  If we have the entire register state available
+    // for this frame then we can return any register requested.
+    if (regmap->nonvolatile_reg_p (regNum) == true || fIsLeafFrame == true) {
+        return this->UnwindCursor<A,R>::getFloatReg (unwind_regno, valp);
+    }
+    return UNW_EREGUNAVAILABLE;
+}
+
+template <typename A, typename R>
+int RemoteUnwindCursor<A,R>::setFloatReg(int regNum, double val)
+{
+    RemoteProcInfo *procinfo = UnwindCursor<A,R>::fAddressSpace.getRemoteProcInfo ();
+    if (procinfo == NULL) {
+       ABORT("setRemoteReg called with a local unwind, use setReg instead.");
+    }
+
+    RemoteRegisterMap *regmap = procinfo->getRegisterMap ();
+    int unwind_regno;
+    if (regmap->caller_regno_to_unwind_regno (regNum, unwind_regno) == false)
+        return UNW_EBADREG;
+    regNum = unwind_regno;
+
+    // Only allow the registers to be set if the unwind cursor is pointing to the
+    // first frame.  We need to track where registers were retrieved from in memory
+    // in every other frame.  Until then, we prohibit register setting in all but
+    // the first frame.
+    if (fIsFirstFrame) {
+        return this->setFloatReg(unwind_regno, val);
+    }
+    return UNW_EREGUNAVAILABLE;
+}
+
+
+template <typename A, typename R>
+const char* RemoteUnwindCursor<A,R>::getRegisterName(int r) 
+{ 
+    int t;
+    if (!this->caller_regno_to_unwind_regno(r, t))
+        return NULL;
+    r = t;
+	return this->UnwindCursor<A,R>::getRegisterName(r);
+}
+
+template <typename A, typename R>
+int RemoteUnwindCursor<A,R>::step()
+{
+    pint_t pc = this->UnwindCursor<A,R>::getReg(UNW_REG_IP);
+    pint_t sp = this->UnwindCursor<A,R>::getReg(UNW_REG_SP);
+    RemoteProcInfo *procinfo = UnwindCursor<A,R>::fAddressSpace.getRemoteProcInfo();
+    bool frame_is_sigtramp = false;
+    bool frame_is_inferior_function_call_dummy = false;
+
+    if (procinfo == NULL) {
+       ABORT("stepRemote called with local unwind, use step() instead.");
+       return UNW_EUNSPEC;
+    }
+    struct timeval *step_remote = procinfo->timestamp_start();
+    procinfo->logVerbose ("stepRemote stepping out of frame with pc value 0x%llx", pc);
+
+    // We'll be off of the first frame once we finish this step.
+    fIsFirstFrame = false;
+
+    if (UnwindCursor<A,R>::fAddressSpace.accessors() 
+        && UnwindCursor<A,R>::fAddressSpace.accessors()->proc_is_sigtramp != NULL
+        && UnwindCursor<A,R>::fAddressSpace.accessors()->proc_is_sigtramp (procinfo->wrap(), pc, fArg)) {
+        frame_is_sigtramp = true;
+    } 
+    if (UnwindCursor<A,R>::fAddressSpace.accessors() 
+        && UnwindCursor<A,R>::fAddressSpace.accessors()->proc_is_inferior_function_call != NULL
+        && UnwindCursor<A,R>::fAddressSpace.accessors()->proc_is_inferior_function_call (procinfo->wrap(), pc, sp, fArg)) {
+        frame_is_inferior_function_call_dummy = true;
+    }
+
+    // If the function we're unwinding can't be a leaf function, 
+    // use the eh_frame or compact unwind info if possible.
+    // The caller should pass couldBeLeafFunc == 0 on the first step of a new context 
+    // but we can't trust them in that.
+
+    if ((fIsLeafFrame == false && frame_is_inferior_function_call_dummy == false)
+        || frame_is_sigtramp) {
+        R saved_registers(UnwindCursor<A,R>::fRegisters);
+        this->setInfoBasedOnIPRegister(true);
+        // bottom of stack is defined as when no more unwind info
+        if ( !UnwindCursor<A,R>::fUnwindInfoMissing ) {
+            int result;
+            const char *method;
+            if ( this->mustUseDwarf() ) {
+                result = this->stepWithDwarfFDE();
+                method = "dwarf";
+            }
+            else {
+                result = this->stepWithCompactEncoding();
+                method = "compact unwind";
+            }
+            if ( result == UNW_STEP_SUCCESS ) {
+                procinfo->logInfo ("Stepped via %s", method);
+                procinfo->timestamp_stop (step_remote, "stepRemote");
+                if (frame_is_sigtramp)
+                    fIsLeafFrame = true;
+                return result;
+            }
+        }
+        UnwindCursor<A,R>::fRegisters = saved_registers;
+    }
+
+    if (frame_is_sigtramp || frame_is_inferior_function_call_dummy)
+        fIsLeafFrame = true;  // this will be true once we complete this stepRemote()
+    else
+        fIsLeafFrame = false;
+
+    if (frame_is_inferior_function_call_dummy) {
+        if (stepOutOfDebuggerDummyFrame (UnwindCursor<A,R>::fAddressSpace, UnwindCursor<A,R>::fRegisters, procinfo, pc, sp, fArg) == UNW_STEP_SUCCESS) {
+            procinfo->logInfo ("Stepped via stepOutOfDebuggerDummyFrame");
+            procinfo->timestamp_stop (step_remote, "stepRemote");
+            return UNW_STEP_SUCCESS;
+        }
+    }
+
+    // If we haven't already seen this function we'll need to get the function bounds via 
+    // eh frame info (if available) - it's the most accurate function bounds in a 
+    // stripped binary.  After that we'll ask the driver program (via the get_proc_bounds accessor).
+
+    if (procinfo->haveProfile (pc) == false) {
+
+        uint64_t text_start, text_end, eh_frame_start, eh_frame_len, compact_unwind_start, mh;
+        uint64_t start_addr, end_addr;
+        if (pc == 0) {
+            int ret = stepByArchitectureDefault (UnwindCursor<A,R>::fAddressSpace, UnwindCursor<A,R>::fRegisters, pc);
+            procinfo->logInfo ("Stepped via stepByArchitectureDefault");
+            procinfo->timestamp_stop (step_remote, "stepRemote");
+            return ret;
+        }
+
+        // If the address is not contained in any image's address range either we've walked off
+        // the stack into random memory or we're backtracing through jit'ed code on the heap.
+        // Let's assume the latter and follow the architecture's default stack walking scheme.
+
+        if (!procinfo->getImageAddresses (pc, mh, text_start, text_end, eh_frame_start, eh_frame_len, compact_unwind_start, fArg)) {
+            int ret = stepByArchitectureDefault (UnwindCursor<A,R>::fAddressSpace, UnwindCursor<A,R>::fRegisters, pc);
+            procinfo->logInfo ("Stepped via stepByArchitectureDefault");
+            procinfo->timestamp_stop (step_remote, "stepRemote");
+            return ret;
+        }
+        if (procinfo->haveFuncBounds (mh) == false) {
+            struct timeval *get_func_bounds = procinfo->timestamp_start();
+            std::vector<FuncBounds> func_bounds;
+            // CFI entries are usually around 38 bytes but under-estimate a bit 
+            // because we're not distinguishing between CIEs and FDEs.
+            if (eh_frame_len > 0)
+                func_bounds.reserve (eh_frame_len / 16);
+            if (procinfo->getCachingPolicy() != UNW_CACHE_NONE) {    
+                // cache the entire eh frame section - we'll need to read the whole
+                // thing anyway so we might as well save it.
+                uint8_t *eh_buf = (uint8_t *)malloc (eh_frame_len);
+                if (UnwindCursor<A,R>::fAddressSpace.getBytes (eh_frame_start, eh_frame_len, eh_buf) == 0)
+                  return UNW_EUNSPEC;
+                RemoteMemoryBlob *ehmem = new RemoteMemoryBlob(eh_buf, free, eh_frame_start, eh_frame_len, mh, NULL);
+                procinfo->addMemBlob (ehmem);
+            }
+            
+            if (CFI_Parser<A>::functionFuncBoundsViaFDE(UnwindCursor<A,R>::fAddressSpace, eh_frame_start, eh_frame_len, func_bounds)) {
+                procinfo->addFuncBounds(mh, func_bounds);
+                procinfo->logVerbose ("Added %d function bounds", (int) func_bounds.size());
+                procinfo->timestamp_stop (get_func_bounds, "getting function bounds from EH frame FDEs");
+            }
+        }
+        if (procinfo->findStartAddr (pc, start_addr, end_addr)) {
+        // If end_addr is 0, we might be looking at the final function in this binary image
+            if (start_addr != 0 && end_addr == 0)
+                end_addr = text_end;
+            procinfo->logVerbose ("Got function bounds from func bounds vector, 0x%llx-0x%llx", start_addr, end_addr);
+        } else {
+            if (UnwindCursor<A,R>::fAddressSpace.accessors()->get_proc_bounds (procinfo->wrap(), pc, &start_addr, &end_addr, fArg) != UNW_ESUCCESS) {
+                int ret = stepByArchitectureDefault (UnwindCursor<A,R>::fAddressSpace, UnwindCursor<A,R>::fRegisters, pc);
+                procinfo->logInfo ("Stepped via stepByArchitectureDefault");
+                procinfo->timestamp_stop (step_remote, "stepRemote");
+                return ret;
+            }
+            else {
+                procinfo->logVerbose ("Got function bounds from get_proc_bounds callback, 0x%llx-0x%llx", start_addr, end_addr);
+            }
+        }
+        if (start_addr != 0) {
+            procinfo->addProfile (UnwindCursor<A,R>::fAddressSpace.accessors(), UnwindCursor<A,R>::fAddressSpace.wrap(), start_addr, end_addr, fArg);
+        }
+    }
+
+    RemoteUnwindProfile *profile = procinfo->findProfile (pc);
+    if (profile == NULL)
+      return UNW_ENOINFO;
+
+    int retval = stepWithAssembly (UnwindCursor<A,R>::fAddressSpace, pc, profile, UnwindCursor<A,R>::fRegisters);
+    if (retval >= 0) {
+        procinfo->logInfo ("Stepped via stepWithAssembly");
+        procinfo->timestamp_stop (step_remote, "stepRemote");
+        return retval;
+    }
+
+    retval = stepByArchitectureDefault (UnwindCursor<A,R>::fAddressSpace, UnwindCursor<A,R>::fRegisters, pc);
+    procinfo->logInfo ("Stepped via stepByArchitectureDefault");
+    procinfo->timestamp_stop (step_remote, "stepRemote");
+    return retval;
+}
+
+template <typename A, typename R>
+void RemoteUnwindCursor<A,R>::setRemoteContext(void *arg)
+{
+    // fill in the register state for the currently executing frame.
+    getRemoteContext (UnwindCursor<A,R>::fAddressSpace.getRemoteProcInfo(), UnwindCursor<A,R>::fRegisters, arg);
+
+    // Flag that this unwind cursor is pointing at the zeroth frame.  We don't
+    // want to use compact unwind info / eh frame info to unwind out of this
+    // frame. 
+
+    fIsLeafFrame = true;
+    fIsFirstFrame = true;
+}
+
+// This needs to be done in many of the functions and in libuwind.cxx in one or two
+// places so I'm defining a convenience method.
+template <typename A, typename R>
+bool RemoteUnwindCursor<A,R>::caller_regno_to_unwind_regno (int caller_regno, int& unwind_regno)
+{
+    RemoteProcInfo *procinfo = UnwindCursor<A,R>::fAddressSpace.getRemoteProcInfo ();
+    if (procinfo == NULL) {
+        unwind_regno = caller_regno;
+        return true;
+    }
+    if (procinfo->getRegisterMap()->caller_regno_to_unwind_regno (caller_regno, unwind_regno))
+        return true;
+    return false;
+}
+
+template <typename A, typename R>
+int RemoteUnwindCursor<A,R>::endOfPrologueInsns (unw_word_t start, unw_word_t end, unw_word_t *endofprologue)
+{
+    RemoteProcInfo *procinfo = UnwindCursor<A,R>::fAddressSpace.getRemoteProcInfo();
+    *endofprologue = start;
+    if (procinfo == NULL) {
+       ABORT("findEndOfPrologueSetup called with local unwind.");
+       return UNW_EUNSPEC;
+    }
+    if (procinfo->haveProfile (start) == false) {
+        uint64_t text_start, text_end, eh_frame_start, eh_frame_len, compact_unwind_start, mh;
+        if (!procinfo->getImageAddresses (start, mh, text_start, text_end, eh_frame_start, eh_frame_len, compact_unwind_start, fArg))
+            return UNW_EUNSPEC;
+        if (end == 0) {
+            if (procinfo->haveFuncBounds (mh) == false) {
+                std::vector<FuncBounds> func_bounds;
+                // CFI entries are usually around 38 bytes but under-estimate a bit 
+                // because we're not distinguishing between CIEs and FDEs.
+                if (eh_frame_len > 0)
+                    func_bounds.reserve (eh_frame_len / 16);
+                if (procinfo->getCachingPolicy() != UNW_CACHE_NONE) {
+                    // cache the entire eh frame section - we'll need to read the whole
+                    // thing anyway so we might as well save it.
+                    uint8_t *eh_buf = (uint8_t *)malloc (eh_frame_len);
+                    if (UnwindCursor<A,R>::fAddressSpace.getBytes (eh_frame_start, eh_frame_len, eh_buf) == 0)
+                      return UNW_EUNSPEC;
+                    RemoteMemoryBlob *ehmem = new RemoteMemoryBlob(eh_buf, free, eh_frame_start, eh_frame_len, mh, NULL);
+                    procinfo->addMemBlob (ehmem);
+                }
+                if (CFI_Parser<A>::functionFuncBoundsViaFDE(UnwindCursor<A,R>::fAddressSpace, eh_frame_start, eh_frame_len, func_bounds)) {
+                    procinfo->addFuncBounds(mh, func_bounds);
+                }
+            }
+            uint64_t bounded_start, bounded_end;
+            if (procinfo->findStartAddr (start, bounded_start, bounded_end)) {
+                end = bounded_end;
+            } else {
+                if (UnwindCursor<A,R>::fAddressSpace.accessors()->get_proc_bounds (procinfo->wrap(), start, &bounded_start, &bounded_end, fArg) != UNW_ESUCCESS) 
+                    if (bounded_end != 0)
+                        end = bounded_end;
+            }
+        }
+        if (procinfo->addProfile (UnwindCursor<A,R>::fAddressSpace.accessors(), UnwindCursor<A,R>::fAddressSpace.wrap(), start, end, fArg) == false)
+            return UNW_EUNSPEC;
+    }
+    RemoteUnwindProfile *profile = procinfo->findProfile (start);
+    if (profile == NULL)
+      return UNW_ENOINFO;
+    *endofprologue = profile->fFirstInsnPastPrologue;
+    return UNW_ESUCCESS;
+}
+
+#endif // SUPPORT_REMOTE_UNWINDING
+
+
+}; // namespace lldb_private 
+
+
+#endif // __UNWINDCURSOR_HPP__
diff --git a/source/Plugins/Process/Utility/libunwind/src/UnwindLevel1-gcc-ext.c b/source/Plugins/Process/Utility/libunwind/src/UnwindLevel1-gcc-ext.c
new file mode 100644
index 0000000..7103c71
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/UnwindLevel1-gcc-ext.c
@@ -0,0 +1,282 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- UnwindLevel1-gcc-ext.c ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+/* 
+ *  Implements gcc extensions to the C++ ABI Exception Handling Level 1 as documented at:
+ *			<http://www.codesourcery.com/cxx-abi/abi-eh.html>
+ *  using libunwind
+ * 
+ */
+ 
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libunwind.h"
+#include "unwind.h"
+#include "libunwind_priv.h"
+#include "InternalMacros.h"
+
+
+#if __ppc__ || __i386__ ||  __x86_64__
+
+//
+//  Called by __cxa_rethrow()
+//
+EXPORT _Unwind_Reason_Code _Unwind_Resume_or_Rethrow(struct _Unwind_Exception* exception_object)
+{
+	DEBUG_PRINT_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld\n", exception_object, exception_object->private_1);
+	// if this is non-forced and a stopping place was found, then this is a re-throw
+	// call _Unwind_RaiseException() as if this was a new exception
+	if ( exception_object->private_1 == 0 )
+		_Unwind_RaiseException(exception_object); 
+	
+	// call through to _Unwind_Resume() which distiguishes between forced and regular exceptions
+	_Unwind_Resume(exception_object); 
+	ABORT("_Unwind_Resume_or_Rethrow() called _Unwind_RaiseException() which unexpectedly returned");
+}
+
+
+
+//
+// Called by personality handler during phase 2 to get base address for data relative encodings
+//
+EXPORT uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context* context)
+{
+	DEBUG_PRINT_API("_Unwind_GetDataRelBase(context=%p)\n", context);
+	ABORT("_Unwind_GetDataRelBase() not implemented");
+}
+
+//
+// Called by personality handler during phase 2 to get base address for text relative encodings
+//
+EXPORT uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context* context)
+{
+	DEBUG_PRINT_API("_Unwind_GetTextRelBase(context=%p)\n", context);
+	ABORT("_Unwind_GetTextRelBase() not implemented");
+}
+
+
+
+//
+//  Scans unwind information to find the function that contains the
+//  specified code address "pc".
+//
+EXPORT void*  _Unwind_FindEnclosingFunction(void* pc)
+{
+	DEBUG_PRINT_API("_Unwind_FindEnclosingFunction(pc=%p)\n", pc);
+	ABORT("_Unwind_FindEnclosingFunction() not implemented");
+}
+
+
+//
+// Walk every frame and call trace function at each one.  If trace function
+// returns anything other than _URC_NO_REASON, then walk is terminated.
+//
+EXPORT _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn callback, void* ref)
+{
+	unw_cursor_t cursor; 
+	unw_context_t uc;
+	unw_getcontext(&uc);
+	unw_init_local(&cursor, &uc);
+	
+	DEBUG_PRINT_API("_Unwind_Backtrace(callback=%p)\n", callback);
+
+	// walk each frame 
+	while ( true ) {
+
+		// ask libuwind to get next frame (skip over first frame which is _Unwind_Backtrace())
+		if ( unw_step(&cursor) <= 0 ) {
+			DEBUG_PRINT_UNWINDING(" _backtrace: ended because cursor reached bottom of stack, returning %d\n", _URC_END_OF_STACK);
+			return _URC_END_OF_STACK;
+		}
+		
+		// debugging
+		if ( DEBUG_PRINT_UNWINDING_TEST ) {
+			char				functionName[512];
+			unw_proc_info_t		frameInfo;
+			unw_word_t			offset;
+			unw_get_proc_name(&cursor, functionName, 512, &offset);
+			unw_get_proc_info(&cursor, &frameInfo);
+			DEBUG_PRINT_UNWINDING(" _backtrace: start_ip=0x%llX, func=%s, lsda=0x%llX, context=%p\n", 
+							 frameInfo.start_ip, functionName, frameInfo.lsda, &cursor);
+		}
+		
+		// call trace function with this frame
+		_Unwind_Reason_Code result = (*callback)((struct _Unwind_Context*)(&cursor), ref);
+		if ( result != _URC_NO_REASON ) {
+			DEBUG_PRINT_UNWINDING(" _backtrace: ended because callback returned %d\n",  result);
+			return result;
+		}
+	}
+}
+
+
+//
+// Find dwarf unwind info for an address 'pc' in some function.
+//
+EXPORT const void* _Unwind_Find_FDE(const void* pc, struct dwarf_eh_bases* bases)
+{
+	// This is slow, but works. 
+	// We create an unwind cursor then alter the IP to be pc 
+	unw_cursor_t	cursor; 
+	unw_context_t	uc;
+	unw_proc_info_t	info;
+	unw_getcontext(&uc);
+	unw_init_local(&cursor, &uc);
+	unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(long)pc);
+	unw_get_proc_info(&cursor, &info);
+	bases->tbase = info.extra;
+	bases->dbase = 0;	// dbase not used on Mac OS X
+	bases->func = info.start_ip;
+	DEBUG_PRINT_API("_Unwind_Find_FDE(pc=%p) => %p\n", pc, (void*)(long)info.unwind_info);
+	return (void*)(long)info.unwind_info;
+}
+
+
+
+EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context* context)
+{
+	unw_cursor_t* cursor = (unw_cursor_t*)context;
+	unw_word_t result;
+	unw_get_reg(cursor, UNW_REG_SP, &result);
+	DEBUG_PRINT_API("_Unwind_GetCFA(context=%p) => 0x%llX\n", context, (uint64_t)result);
+	return result;
+}
+
+
+//
+// Called by personality handler during phase 2 to get instruction pointer.
+// ipBefore is a boolean that says if IP is already adjusted to be the call
+// site address.  Normally IP is the return address.
+//
+EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context* context, int* ipBefore)
+{
+	DEBUG_PRINT_API("_Unwind_GetIPInfo(context=%p)\n", context);
+	*ipBefore = 0;
+	return _Unwind_GetIP(context);
+}
+
+
+//
+// Called by programs with dynamic code generators that want
+// to register a dynamically generated FDE.
+// This function has existed on Mac OS X since 10.4, but
+// never worked before.  
+//
+EXPORT void	__register_frame(const void* fde)
+{
+	DEBUG_PRINT_API("__register_frame(%p)\n", fde);
+	_unw_add_dynamic_fde((unw_word_t)(uintptr_t)fde);
+}
+
+
+//
+// Called by programs with dynamic code generators that want
+// to unregister a dynamically generated FDE.
+// This function has existed on Mac OS X since 10.4, but
+// never worked before.  
+//
+EXPORT void	__deregister_frame(const void* fde)
+{
+	DEBUG_PRINT_API("__deregister_frame(%p)\n", fde);
+	_unw_remove_dynamic_fde((unw_word_t)(uintptr_t)fde);
+}
+
+
+
+//
+// The following register/deregister functions are gcc extensions.  
+// They have existed on Mac OS X, but have never worked because Mac OS X
+// before 10.6 used keymgr to track known FDEs, but these functions
+// never got updated to use keymgr.
+// For now, we implement these as do-nothing functions to keep any existing
+// applications working.  We also add the not in 10.6 symbol so that nwe
+// application won't be able to use them.
+//
+
+EXPORT void	__register_frame_info_bases(const void* fde, void* ob, void* tb, void* db)
+{
+	DEBUG_PRINT_API("__register_frame_info_bases(%p,%p, %p, %p)\n", fde, ob, tb, db);
+	// do nothing, this function never worked in Mac OS X
+}
+
+EXPORT void	__register_frame_info(const void* fde, void* ob)
+{
+	DEBUG_PRINT_API("__register_frame_info(%p, %p)\n", fde, ob);
+	// do nothing, this function never worked in Mac OS X
+}
+
+
+EXPORT void	__register_frame_info_table_bases(const void* fde, void* ob, void* tb, void* db)
+{
+	DEBUG_PRINT_API("__register_frame_info_table_bases(%p,%p, %p, %p)\n", fde, ob, tb, db);
+	// do nothing, this function never worked in Mac OS X
+}
+
+EXPORT void	__register_frame_info_table(const void* fde, void* ob)
+{
+	DEBUG_PRINT_API("__register_frame_info_table(%p, %p)\n", fde, ob);
+	// do nothing, this function never worked in Mac OS X
+}
+
+EXPORT void	__register_frame_table(const void* fde)
+{
+	DEBUG_PRINT_API("__register_frame_table(%p)\n", fde);
+	// do nothing, this function never worked in Mac OS X
+}
+
+EXPORT void* __deregister_frame_info(const void* fde)
+{
+	DEBUG_PRINT_API("__deregister_frame_info(%p)\n", fde);
+	// do nothing, this function never worked in Mac OS X
+	return NULL;
+}
+
+EXPORT void* __deregister_frame_info_bases(const void* fde)
+{
+	DEBUG_PRINT_API("__deregister_frame_info_bases(%p)\n", fde);
+	// do nothing, this function never worked in Mac OS X
+	return NULL;
+}
+
+
+
+
+//
+// symbols in libSystem.dylib in 10.6 and later, but are in libgcc_s.dylib in earlier versions
+//
+NOT_HERE_BEFORE_10_6(_Unwind_Backtrace)
+NOT_HERE_BEFORE_10_6(_Unwind_FindEnclosingFunction)
+NOT_HERE_BEFORE_10_6(_Unwind_GetCFA)
+NOT_HERE_BEFORE_10_6(_Unwind_GetDataRelBase)
+NOT_HERE_BEFORE_10_6(_Unwind_GetTextRelBase)
+NOT_HERE_BEFORE_10_6(_Unwind_Resume_or_Rethrow)
+NOT_HERE_BEFORE_10_6(_Unwind_GetIPInfo)
+
+NOT_HERE_BEFORE_10_6(__register_frame)
+NOT_HERE_BEFORE_10_6(__deregister_frame)
+
+
+//
+// symbols in libSystem.dylib for compatibility, but we don't want any new code using them
+//
+NEVER_HERE(__register_frame_info_bases)
+NEVER_HERE(__register_frame_info)
+NEVER_HERE(__register_frame_info_table_bases)
+NEVER_HERE(__register_frame_info_table)
+NEVER_HERE(__register_frame_table)
+NEVER_HERE(__deregister_frame_info)
+NEVER_HERE(__deregister_frame_info_bases)
+
+
+#endif // __ppc__ || __i386__ ||  __x86_64__
+
diff --git a/source/Plugins/Process/Utility/libunwind/src/UnwindLevel1.c b/source/Plugins/Process/Utility/libunwind/src/UnwindLevel1.c
new file mode 100644
index 0000000..3aa2b6f
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/UnwindLevel1.c
@@ -0,0 +1,443 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- UnwindLevel1.c ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+/* 
+ * 
+ *  Implements C++ ABI Exception Handling Level 1 as documented at:
+ *			<http://www.codesourcery.com/cxx-abi/abi-eh.html>
+ *  using libunwind
+ * 
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libunwind.h"
+#include "unwind.h"
+#include "InternalMacros.h"
+
+#if __ppc__ || __i386__ ||  __x86_64__
+
+static _Unwind_Reason_Code unwind_phase1(unw_context_t* uc, struct _Unwind_Exception* exception_object)
+{
+	unw_cursor_t cursor1; 
+	unw_init_local(&cursor1, uc);
+	
+	// walk each frame looking for a place to stop
+	for (bool handlerNotFound = true; handlerNotFound; ) {
+
+		// ask libuwind to get next frame (skip over first which is _Unwind_RaiseException)
+		int stepResult = unw_step(&cursor1);
+		if ( stepResult == 0 ) {
+			DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached bottom => _URC_END_OF_STACK\n", exception_object); 
+			return _URC_END_OF_STACK;
+		}
+		else if ( stepResult < 0 ) {
+			DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step failed => _URC_FATAL_PHASE1_ERROR\n", exception_object); 
+			return _URC_FATAL_PHASE1_ERROR;
+		}
+		
+		// see if frame has code to run (has personality routine)
+		unw_proc_info_t frameInfo;
+		unw_word_t sp;
+		if ( unw_get_proc_info(&cursor1, &frameInfo) != UNW_ESUCCESS ) {
+			DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info failed => _URC_FATAL_PHASE1_ERROR\n", exception_object);
+			return _URC_FATAL_PHASE1_ERROR;
+		}
+		
+		// debugging
+		if ( DEBUG_PRINT_UNWINDING_TEST ) {
+			char functionName[512];
+			unw_word_t	offset;
+			if ( (unw_get_proc_name(&cursor1, functionName, 512, &offset) != UNW_ESUCCESS) || (frameInfo.start_ip+offset > frameInfo.end_ip) )
+				strcpy(functionName, ".anonymous.");
+			unw_word_t pc;
+			unw_get_reg(&cursor1, UNW_REG_IP, &pc);
+			DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): pc=0x%llX, start_ip=0x%llX, func=%s, lsda=0x%llX, personality=0x%llX\n", 
+							exception_object, pc, frameInfo.start_ip, functionName, frameInfo.lsda, frameInfo.handler);
+		}
+		
+		// if there is a personality routine, ask it if it will want to stop at this frame
+		if ( frameInfo.handler != 0 ) {
+			__personality_routine p = (__personality_routine)(long)(frameInfo.handler);
+			DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): calling personality function %p\n", exception_object, p);
+			_Unwind_Reason_Code personalityResult = (*p)(1, _UA_SEARCH_PHASE, 
+						exception_object->exception_class, exception_object, 
+						(struct _Unwind_Context*)(&cursor1));
+			switch ( personalityResult ) {
+				case _URC_HANDLER_FOUND:
+					// found a catch clause or locals that need destructing in this frame
+					// stop search and remember stack pointer at the frame
+					handlerNotFound = false;
+					unw_get_reg(&cursor1, UNW_REG_SP, &sp);
+					exception_object->private_2 = sp;
+					DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND\n", exception_object);
+					return _URC_NO_REASON;
+					
+				case _URC_CONTINUE_UNWIND:
+					DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", exception_object);
+					// continue unwinding
+					break;
+					
+				default:
+					// something went wrong
+					DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n", exception_object);
+					return _URC_FATAL_PHASE1_ERROR;
+			}
+		}
+	}
+	return _URC_NO_REASON;
+}
+
+
+static _Unwind_Reason_Code unwind_phase2(unw_context_t* uc, struct _Unwind_Exception* exception_object)
+{
+	unw_cursor_t cursor2; 
+	unw_init_local(&cursor2, uc);
+	
+	DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p)\n", exception_object); 
+	
+	// walk each frame until we reach where search phase said to stop
+	while ( true ) {
+
+		// ask libuwind to get next frame (skip over first which is _Unwind_RaiseException)
+		int stepResult = unw_step(&cursor2);
+		if ( stepResult == 0 ) {
+			DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached bottom => _URC_END_OF_STACK\n", exception_object); 
+			return _URC_END_OF_STACK;
+		}
+		else if ( stepResult < 0 ) {
+			DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step failed => _URC_FATAL_PHASE1_ERROR\n", exception_object); 
+			return _URC_FATAL_PHASE2_ERROR;
+		}
+		
+		// get info about this frame
+		unw_word_t sp;
+		unw_proc_info_t frameInfo;
+		unw_get_reg(&cursor2, UNW_REG_SP, &sp);
+		if ( unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS ) {
+			DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info failed => _URC_FATAL_PHASE1_ERROR\n", exception_object);
+			return _URC_FATAL_PHASE2_ERROR;
+		}
+		
+		// debugging
+		if ( DEBUG_PRINT_UNWINDING_TEST ) {
+			char functionName[512];
+			unw_word_t	offset;
+			if ( (unw_get_proc_name(&cursor2, functionName, 512, &offset) != UNW_ESUCCESS) || (frameInfo.start_ip+offset > frameInfo.end_ip) )
+				strcpy(functionName, ".anonymous.");
+			DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): start_ip=0x%llX, func=%s, sp=0x%llX, lsda=0x%llX, personality=0x%llX\n", 
+							exception_object, frameInfo.start_ip, functionName, sp, frameInfo.lsda, frameInfo.handler);
+		}
+		
+		// if there is a personality routine, tell it we are unwinding
+		if ( frameInfo.handler != 0 ) {
+			__personality_routine p = (__personality_routine)(long)(frameInfo.handler);
+			_Unwind_Action action = _UA_CLEANUP_PHASE;
+			if ( sp == exception_object->private_2 )
+				action = (_Unwind_Action)(_UA_CLEANUP_PHASE|_UA_HANDLER_FRAME); // tell personality this was the frame it marked in phase 1
+			_Unwind_Reason_Code personalityResult = (*p)(1, action, 
+						exception_object->exception_class, exception_object, 
+						(struct _Unwind_Context*)(&cursor2));
+			switch ( personalityResult ) {
+				case _URC_CONTINUE_UNWIND:
+					// continue unwinding
+					DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", exception_object);
+					if ( sp == exception_object->private_2 ) {
+						// phase 1 said we would stop at this frame, but we did not...
+						ABORT("during phase1 personality function said it would stop here, but now if phase2 it did not stop here");
+					}
+					break;
+				case _URC_INSTALL_CONTEXT:
+					DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT\n", exception_object);
+					// personality routine says to transfer control to landing pad
+					// we may get control back if landing pad calls _Unwind_Resume()
+					if ( DEBUG_PRINT_UNWINDING_TEST ) {
+						unw_word_t pc;
+						unw_word_t sp;
+						unw_get_reg(&cursor2, UNW_REG_IP, &pc);
+						unw_get_reg(&cursor2, UNW_REG_SP, &sp);
+						DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering user code with ip=0x%llX, sp=0x%llX\n", exception_object, pc, sp);
+					}
+					unw_resume(&cursor2);
+					// unw_resume() only returns if there was an error
+					return _URC_FATAL_PHASE2_ERROR;
+				default:
+					// something went wrong
+					DEBUG_MESSAGE("personality function returned unknown result %d", personalityResult);
+					return _URC_FATAL_PHASE2_ERROR;
+			}
+		}
+	}
+
+	// clean up phase did not resume at the frame that the search phase said it would
+	return _URC_FATAL_PHASE2_ERROR;
+}
+
+
+static _Unwind_Reason_Code unwind_phase2_forced(unw_context_t* uc, struct _Unwind_Exception* exception_object, 
+												_Unwind_Stop_Fn stop, void* stop_parameter)
+{
+	unw_cursor_t cursor2; 
+	unw_init_local(&cursor2, uc);
+	
+	// walk each frame until we reach where search phase said to stop
+	while ( unw_step(&cursor2) > 0 ) {
+		
+		// get info about this frame
+		unw_proc_info_t frameInfo;
+		if ( unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS ) {
+			DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step failed => _URC_END_OF_STACK\n", exception_object); 
+			return _URC_FATAL_PHASE1_ERROR;
+		}
+		
+		// debugging
+		if ( DEBUG_PRINT_UNWINDING_TEST ) {
+			char functionName[512];
+			unw_word_t	offset;
+			if ( (unw_get_proc_name(&cursor2, functionName, 512, &offset) != UNW_ESUCCESS) || (frameInfo.start_ip+offset > frameInfo.end_ip) )
+				strcpy(functionName, ".anonymous.");
+			DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): start_ip=0x%llX, func=%s, lsda=0x%llX, personality=0x%llX\n", 
+							exception_object, frameInfo.start_ip, functionName, frameInfo.lsda, frameInfo.handler);
+		}
+		
+		// call stop function at each frame
+		_Unwind_Action action = (_Unwind_Action)(_UA_FORCE_UNWIND|_UA_CLEANUP_PHASE);
+		_Unwind_Reason_Code stopResult = (*stop)(1, action, 
+						exception_object->exception_class, exception_object, 
+						(struct _Unwind_Context*)(&cursor2), stop_parameter);
+		DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): stop function returned %d\n", exception_object, stopResult);
+		if ( stopResult != _URC_NO_REASON ) {
+			DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): stopped by stop function\n", exception_object);
+			return _URC_FATAL_PHASE2_ERROR;
+		}
+		
+		// if there is a personality routine, tell it we are unwinding
+		if ( frameInfo.handler != 0 ) {
+			__personality_routine p = (__personality_routine)(long)(frameInfo.handler);
+			DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling personality function %p\n", exception_object, p);
+			_Unwind_Reason_Code personalityResult = (*p)(1, action, 
+						exception_object->exception_class, exception_object, 
+						(struct _Unwind_Context*)(&cursor2));
+			switch ( personalityResult ) {
+				case _URC_CONTINUE_UNWIND:
+					DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned _URC_CONTINUE_UNWIND\n", exception_object);
+					// destructors called, continue unwinding
+					break;
+				case _URC_INSTALL_CONTEXT:
+					DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned _URC_INSTALL_CONTEXT\n", exception_object);
+					// we may get control back if landing pad calls _Unwind_Resume()
+					unw_resume(&cursor2);
+					break;
+				default:
+					// something went wrong
+					DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned %d, _URC_FATAL_PHASE2_ERROR\n", 
+						exception_object, personalityResult);
+					return _URC_FATAL_PHASE2_ERROR;
+			}
+		}
+	}
+
+	// call stop function one last time and tell it we've reached the end of the stack
+	DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop function with _UA_END_OF_STACK\n", exception_object);
+	_Unwind_Action lastAction = (_Unwind_Action)(_UA_FORCE_UNWIND|_UA_CLEANUP_PHASE|_UA_END_OF_STACK);
+	(*stop)(1, lastAction, exception_object->exception_class, exception_object, (struct _Unwind_Context*)(&cursor2), stop_parameter);
+	
+	// clean up phase did not resume at the frame that the search phase said it would
+	return _URC_FATAL_PHASE2_ERROR;
+}
+
+
+//
+// Called by __cxa_throw.  Only returns if there is a fatal error
+//
+EXPORT _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception* exception_object)
+{
+	DEBUG_PRINT_API("_Unwind_RaiseException(ex_obj=%p)\n", exception_object);
+	unw_context_t uc;
+	unw_getcontext(&uc);
+
+	// mark that this is a non-forced unwind, so _Unwind_Resume() can do the right thing
+	exception_object->private_1	= 0;
+	exception_object->private_2	= 0;
+
+	// phase 1: the search phase
+	_Unwind_Reason_Code phase1 = unwind_phase1(&uc, exception_object);
+	if ( phase1 != _URC_NO_REASON )
+		return phase1;
+	
+	// phase 2: the clean up phase
+	return unwind_phase2(&uc, exception_object);  
+}
+
+
+//
+// When _Unwind_RaiseException() is in phase2, it hands control
+// to the personality function at each frame.  The personality
+// may force a jump to a landing pad in that function, the landing
+// pad code may then call _Unwind_Resume() to continue with the
+// unwinding.  Note: the call to _Unwind_Resume() is from compiler
+// geneated user code.  All other _Unwind_* routines are called 
+// by the C++ runtime __cxa_* routines. 
+//
+// Re-throwing an exception is implemented by having the code call
+// __cxa_rethrow() which in turn calls _Unwind_Resume_or_Rethrow()
+//
+EXPORT void _Unwind_Resume(struct _Unwind_Exception* exception_object)
+{
+	DEBUG_PRINT_API("_Unwind_Resume(ex_obj=%p)\n", exception_object);
+	unw_context_t uc;
+	unw_getcontext(&uc);
+	
+	if ( exception_object->private_1 != 0 ) 
+		unwind_phase2_forced(&uc, exception_object, (_Unwind_Stop_Fn)exception_object->private_1, (void*)exception_object->private_2);  
+	else
+		unwind_phase2(&uc, exception_object);  
+	
+	// clients assume _Unwind_Resume() does not return, so all we can do is abort.
+	ABORT("_Unwind_Resume() can't return");
+}
+
+
+
+//
+// Not used by C++.  
+// Unwinds stack, calling "stop" function at each frame
+// Could be used to implement longjmp().
+//
+EXPORT _Unwind_Reason_Code _Unwind_ForcedUnwind(struct _Unwind_Exception* exception_object, _Unwind_Stop_Fn stop, void* stop_parameter)
+{
+	DEBUG_PRINT_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)\n", exception_object, stop);
+	unw_context_t uc;
+	unw_getcontext(&uc);
+
+	// mark that this is a forced unwind, so _Unwind_Resume() can do the right thing
+	exception_object->private_1	= (uintptr_t)stop;
+	exception_object->private_2	= (uintptr_t)stop_parameter;
+	
+	// doit
+	return unwind_phase2_forced(&uc, exception_object, stop, stop_parameter);  
+}
+
+
+//
+// Called by personality handler during phase 2 to get LSDA for current frame
+//
+EXPORT uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context* context)
+{
+	unw_cursor_t* cursor = (unw_cursor_t*)context;
+	unw_proc_info_t frameInfo;
+	uintptr_t result = 0;
+	if ( unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS ) 
+		result = frameInfo.lsda;
+	DEBUG_PRINT_API("_Unwind_GetLanguageSpecificData(context=%p) => 0x%lX\n", context, result);
+	if ( result != 0 ) {
+		if ( *((uint8_t*)result) != 0xFF ) 
+			DEBUG_MESSAGE("lsda at 0x%lX does not start with 0xFF\n", result);
+	}
+	return result;
+}
+
+
+//
+// Called by personality handler during phase 2 to get register values
+//
+EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context* context, int index)
+{
+	unw_cursor_t* cursor = (unw_cursor_t*)context;
+	unw_word_t result;
+	unw_get_reg(cursor, index, &result);
+	DEBUG_PRINT_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%llX\n", context, index, (uint64_t)result);
+	return result;
+}
+
+
+//
+// Called by personality handler during phase 2 to alter register values
+//
+EXPORT void _Unwind_SetGR(struct _Unwind_Context* context, int index, uintptr_t new_value)
+{
+	DEBUG_PRINT_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0llX)\n", context, index, (uint64_t)new_value);
+	unw_cursor_t* cursor = (unw_cursor_t*)context;
+	unw_set_reg(cursor, index, new_value);
+}
+
+
+//
+// Called by personality handler during phase 2 to get instruction pointer
+//
+EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context* context)
+{
+	unw_cursor_t* cursor = (unw_cursor_t*)context;
+	unw_word_t result;
+	unw_get_reg(cursor, UNW_REG_IP, &result);
+	DEBUG_PRINT_API("_Unwind_GetIP(context=%p) => 0x%llX\n", context, (uint64_t)result);
+	return result;
+}
+
+
+//
+// Called by personality handler during phase 2 to alter instruction pointer
+//
+EXPORT void _Unwind_SetIP(struct _Unwind_Context* context, uintptr_t new_value)
+{
+	DEBUG_PRINT_API("_Unwind_SetIP(context=%p, value=0x%0llX)\n", context, (uint64_t)new_value);
+	unw_cursor_t* cursor = (unw_cursor_t*)context;
+	unw_set_reg(cursor, UNW_REG_IP, new_value);
+}
+
+
+//
+// Called by personality handler during phase 2 to find the start of the function
+//
+EXPORT uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context* context)
+{
+	unw_cursor_t* cursor = (unw_cursor_t*)context;
+	unw_proc_info_t frameInfo;
+	uintptr_t result = 0;
+	if ( unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS ) 
+		result = frameInfo.start_ip;
+	DEBUG_PRINT_API("_Unwind_GetRegionStart(context=%p) => 0x%lX\n", context, result);
+	return result;
+}
+
+
+//
+// Called by personality handler during phase 2 if a foreign exception is caught 
+//
+EXPORT void _Unwind_DeleteException(struct _Unwind_Exception* exception_object)
+{
+	DEBUG_PRINT_API("_Unwind_DeleteException(ex_obj=%p)\n", exception_object);
+	if ( exception_object->exception_cleanup != NULL )
+		(*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, exception_object);
+}
+
+
+
+
+//
+// symbols in libSystem.dylib in 10.6 and later, but are in libgcc_s.dylib in earlier versions
+//
+NOT_HERE_BEFORE_10_6(_Unwind_DeleteException)
+NOT_HERE_BEFORE_10_6(_Unwind_Find_FDE)
+NOT_HERE_BEFORE_10_6(_Unwind_ForcedUnwind)
+NOT_HERE_BEFORE_10_6(_Unwind_GetGR)
+NOT_HERE_BEFORE_10_6(_Unwind_GetIP)
+NOT_HERE_BEFORE_10_6(_Unwind_GetLanguageSpecificData)
+NOT_HERE_BEFORE_10_6(_Unwind_GetRegionStart)
+NOT_HERE_BEFORE_10_6(_Unwind_RaiseException)
+NOT_HERE_BEFORE_10_6(_Unwind_Resume)
+NOT_HERE_BEFORE_10_6(_Unwind_SetGR)
+NOT_HERE_BEFORE_10_6(_Unwind_SetIP)
+
+#endif // __ppc__ || __i386__ ||  __x86_64__
diff --git a/source/Plugins/Process/Utility/libunwind/src/dwarf2.h b/source/Plugins/Process/Utility/libunwind/src/dwarf2.h
new file mode 100644
index 0000000..8341433
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/dwarf2.h
@@ -0,0 +1,245 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- dwarf2.h ------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+/* These constants were taken from version 3 of the DWARF standard,
+   which is Copyright (c) 2005 Free Standards Group, and
+   Copyright (c) 1992, 1993 UNIX International, Inc.  
+*/
+
+
+#ifndef __DWARF2__
+#define __DWARF2__
+
+namespace lldb_private {
+
+// dwarf unwind instructions
+enum {
+	DW_CFA_nop                 = 0x0,
+	DW_CFA_set_loc             = 0x1,
+	DW_CFA_advance_loc1        = 0x2,
+	DW_CFA_advance_loc2        = 0x3,
+	DW_CFA_advance_loc4        = 0x4,
+	DW_CFA_offset_extended     = 0x5,
+	DW_CFA_restore_extended    = 0x6,
+	DW_CFA_undefined           = 0x7,
+	DW_CFA_same_value          = 0x8,
+	DW_CFA_register            = 0x9,
+	DW_CFA_remember_state      = 0xA,
+	DW_CFA_restore_state       = 0xB,
+	DW_CFA_def_cfa             = 0xC,
+	DW_CFA_def_cfa_register    = 0xD,
+	DW_CFA_def_cfa_offset      = 0xE,
+	DW_CFA_def_cfa_expression  = 0xF,
+	DW_CFA_expression         = 0x10,
+	DW_CFA_offset_extended_sf = 0x11,
+	DW_CFA_def_cfa_sf         = 0x12,
+	DW_CFA_def_cfa_offset_sf  = 0x13,
+	DW_CFA_val_offset         = 0x14,
+	DW_CFA_val_offset_sf      = 0x15,
+	DW_CFA_val_expression     = 0x16,
+	DW_CFA_advance_loc        = 0x40, // high 2 bits are 0x1, lower 6 bits are delta
+	DW_CFA_offset             = 0x80, // high 2 bits are 0x2, lower 6 bits are register
+	DW_CFA_restore            = 0xC0, // high 2 bits are 0x3, lower 6 bits are register
+	
+	// GNU extensions
+    DW_CFA_GNU_window_save				= 0x2D,
+    DW_CFA_GNU_args_size				= 0x2E,
+    DW_CFA_GNU_negative_offset_extended = 0x2F
+};
+
+
+// FSF exception handling Pointer-Encoding constants 
+// Used in CFI augmentation by gcc compiler
+enum {
+	DW_EH_PE_ptr       = 0x00,
+	DW_EH_PE_uleb128   = 0x01,
+	DW_EH_PE_udata2    = 0x02,
+	DW_EH_PE_udata4    = 0x03,
+	DW_EH_PE_udata8    = 0x04,
+	DW_EH_PE_signed    = 0x08,
+	DW_EH_PE_sleb128   = 0x09,
+	DW_EH_PE_sdata2    = 0x0A,
+	DW_EH_PE_sdata4    = 0x0B,
+	DW_EH_PE_sdata8    = 0x0C,
+	DW_EH_PE_absptr    = 0x00,
+	DW_EH_PE_pcrel     = 0x10,
+	DW_EH_PE_textrel   = 0x20,
+	DW_EH_PE_datarel   = 0x30,
+	DW_EH_PE_funcrel   = 0x40,
+	DW_EH_PE_aligned   = 0x50,
+	DW_EH_PE_indirect  = 0x80,
+	DW_EH_PE_omit      = 0xFF
+};
+
+
+// DWARF  expressions
+enum {
+	DW_OP_addr               = 0x03, // constant address (size target specific)
+	DW_OP_deref              = 0x06,
+	DW_OP_const1u            = 0x08, // 1-byte constant
+	DW_OP_const1s            = 0x09, // 1-byte constant
+	DW_OP_const2u            = 0x0A, // 2-byte constant
+	DW_OP_const2s            = 0x0B, // 2-byte constant
+	DW_OP_const4u            = 0x0C, // 4-byte constant
+	DW_OP_const4s            = 0x0D, // 4-byte constant
+	DW_OP_const8u            = 0x0E, // 8-byte constant
+	DW_OP_const8s            = 0x0F, // 8-byte constant
+	DW_OP_constu             = 0x10, // ULEB128 constant
+	DW_OP_consts             = 0x11, // SLEB128 constant
+	DW_OP_dup                = 0x12,
+	DW_OP_drop               = 0x13,
+	DW_OP_over               = 0x14,
+	DW_OP_pick               = 0x15, // 1-byte stack index
+	DW_OP_swap               = 0x16,
+	DW_OP_rot                = 0x17,
+	DW_OP_xderef             = 0x18,
+	DW_OP_abs                = 0x19,
+	DW_OP_and                = 0x1A,
+	DW_OP_div                = 0x1B,
+	DW_OP_minus              = 0x1C,
+	DW_OP_mod                = 0x1D,
+	DW_OP_mul                = 0x1E,
+	DW_OP_neg                = 0x1F,
+	DW_OP_not                = 0x20,
+	DW_OP_or                 = 0x21,
+	DW_OP_plus               = 0x22,
+	DW_OP_plus_uconst        = 0x23, // ULEB128 addend
+	DW_OP_shl                = 0x24,
+	DW_OP_shr                = 0x25,
+	DW_OP_shra               = 0x26,
+	DW_OP_xor                = 0x27,
+	DW_OP_skip               = 0x2F, // signed 2-byte constant
+	DW_OP_bra                = 0x28, // signed 2-byte constant
+	DW_OP_eq                 = 0x29,
+	DW_OP_ge                 = 0x2A,
+	DW_OP_gt                 = 0x2B,
+	DW_OP_le                 = 0x2C,
+	DW_OP_lt                 = 0x2D,
+	DW_OP_ne                 = 0x2E,
+	DW_OP_lit0               = 0x30, // Literal 0
+	DW_OP_lit1               = 0x31, // Literal 1
+	DW_OP_lit2               = 0x32, // Literal 2
+	DW_OP_lit3               = 0x33, // Literal 3
+	DW_OP_lit4               = 0x34, // Literal 4
+	DW_OP_lit5               = 0x35, // Literal 5
+	DW_OP_lit6               = 0x36, // Literal 6
+	DW_OP_lit7               = 0x37, // Literal 7
+	DW_OP_lit8               = 0x38, // Literal 8
+	DW_OP_lit9               = 0x39, // Literal 9
+	DW_OP_lit10              = 0x3A, // Literal 10
+	DW_OP_lit11              = 0x3B, // Literal 11
+	DW_OP_lit12              = 0x3C, // Literal 12
+	DW_OP_lit13              = 0x3D, // Literal 13
+	DW_OP_lit14              = 0x3E, // Literal 14
+	DW_OP_lit15              = 0x3F, // Literal 15
+	DW_OP_lit16              = 0x40, // Literal 16
+	DW_OP_lit17              = 0x41, // Literal 17
+	DW_OP_lit18              = 0x42, // Literal 18
+	DW_OP_lit19              = 0x43, // Literal 19
+	DW_OP_lit20              = 0x44, // Literal 20
+	DW_OP_lit21              = 0x45, // Literal 21
+	DW_OP_lit22              = 0x46, // Literal 22
+	DW_OP_lit23              = 0x47, // Literal 23
+	DW_OP_lit24              = 0x48, // Literal 24
+	DW_OP_lit25              = 0x49, // Literal 25
+	DW_OP_lit26              = 0x4A, // Literal 26
+	DW_OP_lit27              = 0x4B, // Literal 27
+	DW_OP_lit28              = 0x4C, // Literal 28
+	DW_OP_lit29              = 0x4D, // Literal 29
+	DW_OP_lit30              = 0x4E, // Literal 30
+	DW_OP_lit31              = 0x4F, // Literal 31
+	DW_OP_reg0               = 0x50, // Contents of reg0
+	DW_OP_reg1               = 0x51, // Contents of reg1
+	DW_OP_reg2               = 0x52, // Contents of reg2
+	DW_OP_reg3               = 0x53, // Contents of reg3
+	DW_OP_reg4               = 0x54, // Contents of reg4
+	DW_OP_reg5               = 0x55, // Contents of reg5
+	DW_OP_reg6               = 0x56, // Contents of reg6
+	DW_OP_reg7               = 0x57, // Contents of reg7
+	DW_OP_reg8               = 0x58, // Contents of reg8
+	DW_OP_reg9               = 0x59, // Contents of reg9
+	DW_OP_reg10              = 0x5A, // Contents of reg10
+	DW_OP_reg11              = 0x5B, // Contents of reg11
+	DW_OP_reg12              = 0x5C, // Contents of reg12
+	DW_OP_reg13              = 0x5D, // Contents of reg13
+	DW_OP_reg14              = 0x5E, // Contents of reg14
+	DW_OP_reg15              = 0x5F, // Contents of reg15
+	DW_OP_reg16              = 0x60, // Contents of reg16
+	DW_OP_reg17              = 0x61, // Contents of reg17
+	DW_OP_reg18              = 0x62, // Contents of reg18
+	DW_OP_reg19              = 0x63, // Contents of reg19
+	DW_OP_reg20              = 0x64, // Contents of reg20
+	DW_OP_reg21              = 0x65, // Contents of reg21
+	DW_OP_reg22              = 0x66, // Contents of reg22
+	DW_OP_reg23              = 0x67, // Contents of reg23
+	DW_OP_reg24              = 0x68, // Contents of reg24
+	DW_OP_reg25              = 0x69, // Contents of reg25
+	DW_OP_reg26              = 0x6A, // Contents of reg26
+	DW_OP_reg27              = 0x6B, // Contents of reg27
+	DW_OP_reg28              = 0x6C, // Contents of reg28
+	DW_OP_reg29              = 0x6D, // Contents of reg29
+	DW_OP_reg30              = 0x6E, // Contents of reg30
+	DW_OP_reg31              = 0x6F, // Contents of reg31
+	DW_OP_breg0              = 0x70, // base register 0 + SLEB128 offset
+	DW_OP_breg1              = 0x71, // base register 1 + SLEB128 offset
+	DW_OP_breg2              = 0x72, // base register 2 + SLEB128 offset
+	DW_OP_breg3              = 0x73, // base register 3 + SLEB128 offset
+	DW_OP_breg4              = 0x74, // base register 4 + SLEB128 offset
+	DW_OP_breg5              = 0x75, // base register 5 + SLEB128 offset
+	DW_OP_breg6              = 0x76, // base register 6 + SLEB128 offset
+	DW_OP_breg7              = 0x77, // base register 7 + SLEB128 offset
+	DW_OP_breg8              = 0x78, // base register 8 + SLEB128 offset
+	DW_OP_breg9              = 0x79, // base register 9 + SLEB128 offset
+	DW_OP_breg10             = 0x7A, // base register 10 + SLEB128 offset
+	DW_OP_breg11             = 0x7B, // base register 11 + SLEB128 offset
+	DW_OP_breg12             = 0x7C, // base register 12 + SLEB128 offset
+	DW_OP_breg13             = 0x7D, // base register 13 + SLEB128 offset
+	DW_OP_breg14             = 0x7E, // base register 14 + SLEB128 offset
+	DW_OP_breg15             = 0x7F, // base register 15 + SLEB128 offset
+	DW_OP_breg16             = 0x80, // base register 16 + SLEB128 offset
+	DW_OP_breg17             = 0x81, // base register 17 + SLEB128 offset
+	DW_OP_breg18             = 0x82, // base register 18 + SLEB128 offset
+	DW_OP_breg19             = 0x83, // base register 19 + SLEB128 offset
+	DW_OP_breg20             = 0x84, // base register 20 + SLEB128 offset
+	DW_OP_breg21             = 0x85, // base register 21 + SLEB128 offset
+	DW_OP_breg22             = 0x86, // base register 22 + SLEB128 offset
+	DW_OP_breg23             = 0x87, // base register 23 + SLEB128 offset
+	DW_OP_breg24             = 0x88, // base register 24 + SLEB128 offset
+	DW_OP_breg25             = 0x89, // base register 25 + SLEB128 offset
+	DW_OP_breg26             = 0x8A, // base register 26 + SLEB128 offset
+	DW_OP_breg27             = 0x8B, // base register 27 + SLEB128 offset
+	DW_OP_breg28             = 0x8C, // base register 28 + SLEB128 offset
+	DW_OP_breg29             = 0x8D, // base register 29 + SLEB128 offset
+	DW_OP_breg30             = 0x8E, // base register 30 + SLEB128 offset
+	DW_OP_breg31             = 0x8F, // base register 31 + SLEB128 offset
+	DW_OP_regx               = 0x90, // ULEB128 register
+	DW_OP_fbreg              = 0x91, // SLEB128 offset
+	DW_OP_bregx              = 0x92, // ULEB128 register followed by SLEB128 offset
+	DW_OP_piece              = 0x93, // ULEB128 size of piece addressed
+	DW_OP_deref_size         = 0x94, // 1-byte size of data retrieved
+	DW_OP_xderef_size        = 0x95, // 1-byte size of data retrieved
+	DW_OP_nop                = 0x96,
+	DW_OP_push_object_addres = 0x97,
+	DW_OP_call2              = 0x98, // 2-byte offset of DIE
+	DW_OP_call4              = 0x99, // 4-byte offset of DIE
+	DW_OP_call_ref           = 0x9A, // 4- or 8-byte offset of DIE
+	DW_OP_lo_user            = 0xE0,
+	DW_OP_APPLE_uninit       = 0xF0,
+	DW_OP_hi_user            = 0xFF
+};
+
+
+}; // namespace lldb_private
+
+
+#endif
+
+
+
diff --git a/source/Plugins/Process/Utility/libunwind/src/libunwind_priv.h b/source/Plugins/Process/Utility/libunwind/src/libunwind_priv.h
new file mode 100644
index 0000000..fe25780
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/libunwind_priv.h
@@ -0,0 +1,35 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- libunwind_priv.h ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __LIBUNWIND_PRIV__
+#define __LIBUNWIND_PRIV__
+
+namespace lldb_private {
+#include "libunwind.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+	// SPI
+	extern void unw_iterate_dwarf_unwind_cache(void (*func)(unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh));
+
+	// IPI
+	extern void _unw_add_dynamic_fde(unw_word_t fde);
+	extern void _unw_remove_dynamic_fde(unw_word_t fde);
+
+#ifdef __cplusplus
+}
+#endif
+
+}; // namespace lldb_private
+
+
+#endif
+
diff --git a/source/Plugins/Process/Utility/libunwind/src/libuwind.cxx b/source/Plugins/Process/Utility/libunwind/src/libuwind.cxx
new file mode 100644
index 0000000..e7e66a4
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/libuwind.cxx
@@ -0,0 +1,421 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/
+//===-- libuwind.cxx --------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+ 
+#if __ppc__ || __i386__ ||  __x86_64__
+
+#include <mach/mach_types.h>
+#include <mach/machine.h>
+#include <new>
+
+#include "libunwind.h"
+#include "libunwind_priv.h"
+
+#include "UnwindCursor.hpp"
+#include "AddressSpace.hpp"
+
+#include "RemoteProcInfo.hpp"
+
+namespace lldb_private {
+
+// setup debug logging hooks
+INITIALIZE_DEBUG_PRINT_API
+INITIALIZE_DEBUG_PRINT_UNWINDING
+
+// internal object to represent this processes address space
+static LocalAddressSpace sThisAddressSpace;
+
+#pragma mark Local API
+
+///
+/// record the registers and stack position of the caller 
+///
+extern int unw_getcontext(unw_context_t*);
+// note: unw_getcontext() implemented in assembly
+
+///
+/// create a cursor of a thread in this process given 'context' recorded by unw_getcontext()
+///
+EXPORT int unw_init_local(unw_cursor_t* cursor, unw_context_t* context)
+{
+	DEBUG_PRINT_API("unw_init_local(cursor=%p, context=%p)\n", cursor, context);
+	// use "placement new" to allocate UnwindCursor in the cursor buffer
+#if __i386__
+	new ((void*)cursor) UnwindCursor<LocalAddressSpace,Registers_x86>(context, sThisAddressSpace);
+#elif __x86_64__
+	new ((void*)cursor) UnwindCursor<LocalAddressSpace,Registers_x86_64>(context, sThisAddressSpace);
+#elif __ppc__
+	new ((void*)cursor) UnwindCursor<LocalAddressSpace,Registers_ppc>(context, sThisAddressSpace);
+#endif
+	AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
+	co->setInfoBasedOnIPRegister(NULL);
+
+	return UNW_ESUCCESS;
+}
+
+///
+/// move cursor to next frame 
+///
+EXPORT int unw_step(unw_cursor_t* cursor)
+{
+	DEBUG_PRINT_API("unw_step(cursor=%p)\n", cursor);
+	AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
+    return co->step();
+}
+
+///
+/// get value of specified register at cursor position in stack frame
+///
+EXPORT int unw_get_reg(unw_cursor_t* cursor, unw_regnum_t regNum, unw_word_t* value)
+{
+	DEBUG_PRINT_API("unw_get_reg(cursor=%p, regNum=%d, &value=%p)\n", cursor, regNum, value);
+	AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
+
+    if (co->validReg(regNum) == 0)
+        return UNW_EBADREG;
+	return co->getReg(regNum, value);
+}
+
+///
+/// get value of specified float register at cursor position in stack frame
+///
+EXPORT int unw_get_fpreg(unw_cursor_t* cursor, unw_regnum_t regNum, unw_fpreg_t* value)
+{
+	DEBUG_PRINT_API("unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)\n", cursor, regNum, value);
+	AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
+
+	if ( co->validFloatReg(regNum) ) {
+		return co->getFloatReg(regNum, value);
+	}
+	return UNW_EBADREG;
+}
+
+///
+/// set value of specified register at cursor position in stack frame
+///
+EXPORT int unw_set_reg(unw_cursor_t* cursor, unw_regnum_t regNum, unw_word_t value)
+{
+	DEBUG_PRINT_API("unw_set_reg(cursor=%p, regNum=%d, value=0x%llX)\n", cursor, regNum, value);
+	AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
+
+	if ( co->validReg(regNum) ) {
+		co->setReg(regNum, value);
+		// specical case altering IP to re-find info (being called by personality function)
+		if ( regNum == UNW_REG_IP ) {
+			unw_proc_info_t info;
+			co->getInfo(&info);
+			uint64_t orgArgSize = info.gp;
+			uint64_t orgFuncStart = info.start_ip;
+			co->setInfoBasedOnIPRegister(false);
+			// and adjust REG_SP if there was a DW_CFA_GNU_args_size
+			if ( (orgFuncStart == info.start_ip) && (orgArgSize != 0) )
+				co->setReg(UNW_REG_SP, co->getReg(UNW_REG_SP) + orgArgSize);
+		}
+		return UNW_ESUCCESS;
+	}
+	return UNW_EBADREG;
+}
+
+///
+/// set value of specified float register at cursor position in stack frame
+///
+EXPORT int unw_set_fpreg(unw_cursor_t* cursor, unw_regnum_t regNum, unw_fpreg_t value)
+{
+	DEBUG_PRINT_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%g)\n", cursor, regNum, value);
+	AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
+
+	if ( co->validFloatReg(regNum) ) {
+		return co->setFloatReg(regNum, value);
+	}
+	return UNW_EBADREG;
+}
+
+///
+/// resume execution at cursor position (aka longjump) 
+///
+EXPORT int unw_resume(unw_cursor_t* cursor)
+{
+	DEBUG_PRINT_API("unw_resume(cursor=%p)\n", cursor);
+	AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
+
+	co->jumpto();
+	return UNW_EUNSPEC;
+}
+
+///
+/// returns the name of a register
+///
+EXPORT const char* unw_regname(unw_cursor_t* cursor, unw_regnum_t regNum)
+{
+	DEBUG_PRINT_API("unw_regname(cursor=%p, regNum=%d)\n", cursor, regNum);
+	AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
+	return co->getRegisterName(regNum);
+}
+
+///
+/// get unwind info at cursor position in stack frame 
+///
+EXPORT int unw_get_proc_info(unw_cursor_t* cursor, unw_proc_info_t* info)
+{
+	DEBUG_PRINT_API("unw_get_proc_info(cursor=%p, &info=%p)\n", cursor, info);
+	AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
+	co->getInfo(info);
+	if ( info->end_ip == 0 )
+		return UNW_ENOINFO;
+	else
+		return UNW_ESUCCESS;
+}
+
+///
+/// checks if a register is a floating-point register 
+///
+EXPORT int unw_is_fpreg(unw_cursor_t* cursor, unw_regnum_t regNum)
+{
+	DEBUG_PRINT_API("unw_is_fpreg(cursor=%p, regNum=%d)\n", cursor, regNum);
+	AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
+	return co->validFloatReg(regNum);
+}
+
+///
+/// checks if current frame is signal trampoline 
+///
+EXPORT int unw_is_signal_frame(unw_cursor_t* cursor)
+{
+	DEBUG_PRINT_API("unw_is_signal_frame(cursor=%p)\n", cursor);
+	AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
+	return co->isSignalFrame();
+}
+
+///
+/// get name of function at cursor position in stack frame 
+///
+EXPORT int unw_get_proc_name(unw_cursor_t* cursor, char* buf, size_t bufLen, unw_word_t* offset)
+{
+	DEBUG_PRINT_API("unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%ld)\n", cursor, buf, bufLen);
+	AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
+	if ( co->getFunctionName(buf, bufLen, offset) )
+		return UNW_ESUCCESS;
+	else
+		return UNW_EUNSPEC;
+}
+
+#pragma mark Remote API
+ 
+#if defined (SUPPORT_REMOTE_UNWINDING)
+EXPORT int unw_init_remote(unw_cursor_t *cursor, unw_addr_space_t as, void *arg)
+{
+    DEBUG_PRINT_API("init_remote(c=%p, as=%p, arg=%p)\n", cursor, as, arg);
+	
+    // API docs at http://www.nongnu.org/libunwind/docs.html say we should 
+    // handle a local address space but we're not doing the "remote" unwinding
+    // with local process accessors so punt on that.
+
+    if(as->type != UNW_REMOTE)
+    {
+        ABORT("unw_init_remote was passed a non-remote address space");
+        return UNW_EINVAL;
+    }
+
+	unw_accessors_t* acc = unw_get_accessors(as);
+	if(!acc) {
+		ABORT("unw_get_accessors returned NULL");
+		return UNW_EINVAL;
+	}
+	
+    unw_addr_space_remote* remote = (unw_addr_space_remote*)as;
+	
+    // use "placement new" to allocate UnwindCursor in the cursor buffer
+    // It isn't really necessary to use placement new in the remote API but we'll stay consistent
+    // with the rest of the code here.
+    switch ( remote->ras->getTargetArch() ) {
+        case UNW_TARGET_I386:
+	{
+                Registers_x86 *r = new Registers_x86;
+                OtherAddressSpace<Pointer32<LittleEndian> > *addrSpace = new OtherAddressSpace<Pointer32<LittleEndian> >(as, arg);
+                getRemoteContext (remote->ras, *r, arg);
+                unw_context_t *context = (unw_context_t*) r;
+                new ((void*)cursor) RemoteUnwindCursor<OtherAddressSpace<Pointer32<LittleEndian> >, Registers_x86>(*addrSpace, context, arg);
+                break;
+	}
+            break;
+        case UNW_TARGET_X86_64:
+	{
+                Registers_x86_64 *r = new Registers_x86_64;
+                OtherAddressSpace<Pointer64<LittleEndian> > *addrSpace = new OtherAddressSpace<Pointer64<LittleEndian> >(as, arg);
+                getRemoteContext (remote->ras, *r, arg);
+                unw_context_t *context = (unw_context_t*) r;
+                new ((void*)cursor) RemoteUnwindCursor<OtherAddressSpace<Pointer64<LittleEndian> >, Registers_x86_64>(*addrSpace, context, arg);
+                break;
+	}
+
+        case UNW_TARGET_PPC:
+              ABORT("ppc not supported for remote unwinds");
+            break;
+
+        case UNW_TARGET_ARM:
+              ABORT("arm not supported for remote unwinds");
+            break;
+
+        default:
+            return UNW_EUNSPEC;
+    }
+	
+    AbstractRemoteUnwindCursor* co = (AbstractRemoteUnwindCursor*)cursor;
+    co->setRemoteContext(arg);
+	
+	return UNW_ESUCCESS;
+}
+
+// The documentation disagrees about whether or not this returns a pointer.  Now it does.
+EXPORT unw_accessors_t* unw_get_accessors(unw_addr_space_t as)
+{
+	if(as->type != UNW_REMOTE)
+	{
+		ABORT("unw_get_accessors was passed a non-remote address space");
+		return NULL;
+	}
+	unw_addr_space_remote* remote = (unw_addr_space_remote*)as;
+	
+	if(remote->type != UNW_REMOTE)
+		return NULL;
+	
+    return remote->ras->getAccessors();
+}
+
+EXPORT unw_addr_space_t unw_create_addr_space(unw_accessors_t *ap, unw_targettype_t targarch)
+{
+	unw_addr_space_remote* remote = (unw_addr_space_remote*)malloc(sizeof(unw_addr_space_remote));
+	remote->type = UNW_REMOTE;
+    remote->ras = new RemoteProcInfo(ap, targarch);
+	return (unw_addr_space_t)remote;
+}
+
+EXPORT void unw_flush_caches(unw_addr_space_t as)
+{
+	if(as->type != UNW_REMOTE)
+	{
+		ABORT("unw_flush_caches was passed a non-remote address space");
+		return;
+	}
+	unw_addr_space_remote* remote = (unw_addr_space_remote*)as;
+	remote->ras->flushAllCaches();
+	
+	return;
+}
+
+EXPORT void unw_image_was_unloaded (unw_addr_space_t as, unw_word_t mh)
+{
+	if(as->type != UNW_REMOTE)
+	{
+		ABORT("unw_image_was_unloaded was passed a non-remote address space");
+		return;
+	}
+	unw_addr_space_remote* remote = (unw_addr_space_remote*)as;
+	remote->ras->flushCacheByMachHeader(mh);
+
+	return;
+}
+
+
+EXPORT int unw_set_caching_policy(unw_addr_space_t as, unw_caching_policy_t policy)
+{
+	if(as->type != UNW_REMOTE)
+	{
+		ABORT("unw_set_caching_policy was passed a non-remote address space");
+		return UNW_EINVAL;
+	}
+	unw_addr_space_remote* remote = (unw_addr_space_remote*)as;
+	return remote->ras->setCachingPolicy(policy);
+}
+
+EXPORT unw_addr_space_t unw_local_addr_space = (unw_addr_space_t)&sThisAddressSpace;
+
+///
+/// delete an address_space object
+///
+EXPORT void unw_destroy_addr_space(unw_addr_space_t asp)
+{
+    if(asp->type != UNW_REMOTE) {
+        ABORT("unw_destroy_addr_space was passed a non-remote address space");
+        return;
+    }
+
+    unw_addr_space_remote* remote = (unw_addr_space_remote*)asp;
+    delete remote->ras;
+}
+
+EXPORT void unw_set_logging_level(unw_addr_space_t as, FILE *f, unw_log_level_t level)
+{
+    if (as->type != UNW_REMOTE) {
+        ABORT("unw_set_logging_level was passed a non-remote address space");
+        return;
+    }
+
+	unw_addr_space_remote* remote = (unw_addr_space_remote*)as;
+	return remote->ras->setLoggingLevel(f, level);
+}
+
+
+EXPORT int unw_end_of_prologue_setup(unw_cursor_t* cursor, unw_word_t start, unw_word_t end, unw_word_t *endofprologue) 
+{
+    AbstractRemoteUnwindCursor* co = (AbstractRemoteUnwindCursor*)cursor;
+    if (!co->remoteUnwindCursor())
+        ABORT("unw_end_of_prologue_setup called with a non-remote unwind cursor.");
+
+    return co->endOfPrologueInsns (start, end, endofprologue);
+}
+
+
+#endif // SUPPORT_REMOTE_UNWINDING
+
+#pragma mark Dynamic unwinding API
+
+#if !FOR_DYLD
+///
+/// SPI: walks cached dwarf entries
+///
+EXPORT void unw_iterate_dwarf_unwind_cache(void (*func)(unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh))
+{
+	DEBUG_PRINT_API("unw_iterate_dwarf_unwind_cache(func=%p)\n", func);
+	DwarfFDECache<LocalAddressSpace>::iterateCacheEntries(func);
+}
+#endif // !FOR_DYLD
+
+#if !FOR_DYLD
+//
+// IPI: for __register_frame()
+//
+void _unw_add_dynamic_fde(unw_word_t fde)
+{
+	CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
+	CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
+	const char* message = CFI_Parser<LocalAddressSpace>::decodeFDE(sThisAddressSpace, (LocalAddressSpace::pint_t)fde, & fdeInfo, &cieInfo);
+	if ( message == NULL ) {
+		// dynamically registered FDEs don't have a mach_header group they are in.  Use fde as mh_group
+		unw_word_t mh_group = fdeInfo.fdeStart;
+		DwarfFDECache<LocalAddressSpace>::add(mh_group, fdeInfo.pcStart, fdeInfo.pcEnd, fdeInfo.fdeStart);
+	}
+	else {
+		DEBUG_MESSAGE("_unw_add_dynamic_fde: bad fde: %s", message);
+	}
+}
+
+//
+// IPI: for __deregister_frame()
+//
+void _unw_remove_dynamic_fde(unw_word_t fde)
+{
+	// fde is own mh_group
+	DwarfFDECache<LocalAddressSpace>::removeAllIn(fde);
+}
+#endif
+
+}; // namespace lldb_private
+
+#endif // __ppc__ || __i386__ ||  __x86_64__
diff --git a/source/Plugins/Process/Utility/libunwind/src/unw_getcontext.s b/source/Plugins/Process/Utility/libunwind/src/unw_getcontext.s
new file mode 100644
index 0000000..8d3a451
--- /dev/null
+++ b/source/Plugins/Process/Utility/libunwind/src/unw_getcontext.s
@@ -0,0 +1,229 @@
+
+#if __i386__ || __x86_64__ || __ppc__
+
+	.text
+	.globl _unw_getcontext
+_unw_getcontext:
+
+#endif  // __i386__ || __x86_64__ || __ppc__
+
+
+#if __i386__
+
+#
+# extern int unw_getcontext(unw_context_t* thread_state)
+#
+# On entry: 
+#	+					    +
+#   +-----------------------+
+#	+ thread_state pointer  +
+#   +-----------------------+
+#	+ return address	    +
+#   +-----------------------+   <-- SP
+#	+					    +
+#
+	push	%eax
+	movl	8(%esp), %eax
+	movl	%ebx,  4(%eax)
+	movl	%ecx,  8(%eax)
+	movl	%edx, 12(%eax)
+	movl	%edi, 16(%eax)
+	movl	%esi, 20(%eax)
+	movl	%ebp, 24(%eax)
+	movl	%esp, %edx
+	addl	$8, %edx
+	movl	%edx, 28(%eax)	# store what sp was at call site as esp
+	# skip ss
+	# skip eflags
+	movl	4(%esp), %edx
+	movl	%edx, 40(%eax)	# store return address as eip
+	# skip cs
+	# skip ds
+	# skip es
+	# skip fs
+	# skip gs
+	movl	(%esp), %edx
+	movl	%edx, (%eax)	# store original eax
+	popl	%eax
+	xorl	%eax, %eax		# return UNW_ESUCCESS
+	ret
+
+#elif __x86_64__
+
+#
+# extern int unw_getcontext(unw_context_t* thread_state)
+#
+# On entry: 
+#	thread_state pointer is in rdi
+#
+	movq	%rax,   (%rdi)
+	movq	%rbx,  8(%rdi)
+	movq	%rcx, 16(%rdi)
+	movq	%rdx, 24(%rdi)
+	movq	%rdi, 32(%rdi)
+	movq	%rsi, 40(%rdi)
+	movq	%rbp, 48(%rdi)
+	movq	%rsp, 56(%rdi)
+	addq	$8,   56(%rdi)
+	movq	%r8,  64(%rdi)
+	movq	%r9,  72(%rdi)
+	movq	%r10, 80(%rdi)
+	movq	%r11, 88(%rdi)
+	movq	%r12, 96(%rdi)
+	movq	%r13,104(%rdi)
+	movq	%r14,112(%rdi)
+	movq	%r15,120(%rdi)
+	movq	(%rsp),%rsi
+	movq	%rsi,128(%rdi) # store return address as rip
+	# skip rflags
+	# skip cs
+	# skip fs
+	# skip gs
+	xorl	%eax, %eax		# return UNW_ESUCCESS
+	ret
+
+#elif __ppc__
+
+;
+; extern int unw_getcontext(unw_context_t* thread_state)
+;
+; On entry: 
+;	thread_state pointer is in r3
+;
+	stw		r0,  8(r3)	 
+	mflr	r0
+	stw		r0,  0(r3)	; store lr as ssr0
+	stw		r1, 12(r3)	
+	stw		r2, 16(r3)	
+	stw		r3, 20(r3)	
+	stw		r4, 24(r3)	
+	stw		r5, 28(r3)	
+	stw		r6, 32(r3)	
+	stw		r7, 36(r3)	
+	stw		r8, 40(r3)	
+	stw		r9, 44(r3)	
+	stw	   r10, 48(r3)	
+	stw	   r11, 52(r3)	
+	stw	   r12, 56(r3)	
+	stw	   r13, 60(r3)	
+	stw	   r14, 64(r3)	
+	stw	   r15, 68(r3)	
+	stw	   r16, 72(r3)	
+	stw	   r17, 76(r3)	
+	stw	   r18, 80(r3)	
+	stw	   r19, 84(r3)	
+	stw	   r20, 88(r3)	
+	stw	   r21, 92(r3)	
+	stw	   r22, 96(r3)	
+	stw	   r23,100(r3)	
+	stw	   r24,104(r3)	
+	stw	   r25,108(r3)	
+	stw	   r26,112(r3)	
+	stw	   r27,116(r3)	
+	stw	   r28,120(r3)	
+	stw	   r29,124(r3)	
+	stw	   r30,128(r3)	
+	stw	   r31,132(r3)	
+	
+	; save VRSave register
+	mfspr	r0,256
+	stw		r0,156(r3)	
+	; save CR registers
+	mfcr	r0
+	stw		r0,136(r3)	
+	; save CTR register
+	mfctr	r0
+	stw		r0,148(r3)	
+
+	; save float registers
+	stfd		f0, 160(r3)
+	stfd		f1, 168(r3)
+	stfd		f2, 176(r3)
+	stfd		f3, 184(r3)
+	stfd		f4, 192(r3)
+	stfd		f5, 200(r3)
+	stfd		f6, 208(r3)
+	stfd		f7, 216(r3)
+	stfd		f8, 224(r3)
+	stfd		f9, 232(r3)
+	stfd		f10,240(r3)
+	stfd		f11,248(r3)
+	stfd		f12,256(r3)
+	stfd		f13,264(r3)
+	stfd		f14,272(r3)
+	stfd		f15,280(r3)
+	stfd		f16,288(r3)
+	stfd		f17,296(r3)
+	stfd		f18,304(r3)
+	stfd		f19,312(r3)
+	stfd		f20,320(r3)
+	stfd		f21,328(r3)
+	stfd		f22,336(r3)
+	stfd		f23,344(r3)
+	stfd		f24,352(r3)
+	stfd		f25,360(r3)
+	stfd		f26,368(r3)
+	stfd		f27,376(r3)
+	stfd		f28,384(r3)
+	stfd		f29,392(r3)
+	stfd		f30,400(r3)
+	stfd		f31,408(r3)
+
+
+	; save vector registers
+
+	subi	r4,r1,16
+	rlwinm	r4,r4,0,0,27	; mask low 4-bits
+	; r4 is now a 16-byte aligned pointer into the red zone
+
+#define SAVE_VECTOR_UNALIGNED(_vec, _offset) \
+	stvx	_vec,0,r4			@\
+	lwz		r5, 0(r4)			@\
+	stw		r5, _offset(r3)		@\
+	lwz		r5, 4(r4)			@\
+	stw		r5, _offset+4(r3)	@\
+	lwz		r5, 8(r4)			@\
+	stw		r5, _offset+8(r3)	@\
+	lwz		r5, 12(r4)			@\
+	stw		r5, _offset+12(r3)
+	
+	SAVE_VECTOR_UNALIGNED( v0, 424+0x000)
+	SAVE_VECTOR_UNALIGNED( v1, 424+0x010)
+	SAVE_VECTOR_UNALIGNED( v2, 424+0x020)
+	SAVE_VECTOR_UNALIGNED( v3, 424+0x030)
+	SAVE_VECTOR_UNALIGNED( v4, 424+0x040)
+	SAVE_VECTOR_UNALIGNED( v5, 424+0x050)
+	SAVE_VECTOR_UNALIGNED( v6, 424+0x060)
+	SAVE_VECTOR_UNALIGNED( v7, 424+0x070)
+	SAVE_VECTOR_UNALIGNED( v8, 424+0x080)
+	SAVE_VECTOR_UNALIGNED( v9, 424+0x090)
+	SAVE_VECTOR_UNALIGNED(v10, 424+0x0A0)
+	SAVE_VECTOR_UNALIGNED(v11, 424+0x0B0)
+	SAVE_VECTOR_UNALIGNED(v12, 424+0x0C0)
+	SAVE_VECTOR_UNALIGNED(v13, 424+0x0D0)
+	SAVE_VECTOR_UNALIGNED(v14, 424+0x0E0)
+	SAVE_VECTOR_UNALIGNED(v15, 424+0x0F0)
+	SAVE_VECTOR_UNALIGNED(v16, 424+0x100)
+	SAVE_VECTOR_UNALIGNED(v17, 424+0x110)
+	SAVE_VECTOR_UNALIGNED(v18, 424+0x120)
+	SAVE_VECTOR_UNALIGNED(v19, 424+0x130)
+	SAVE_VECTOR_UNALIGNED(v20, 424+0x140)
+	SAVE_VECTOR_UNALIGNED(v21, 424+0x150)
+	SAVE_VECTOR_UNALIGNED(v22, 424+0x160)
+	SAVE_VECTOR_UNALIGNED(v23, 424+0x170)
+	SAVE_VECTOR_UNALIGNED(v24, 424+0x180)
+	SAVE_VECTOR_UNALIGNED(v25, 424+0x190)
+	SAVE_VECTOR_UNALIGNED(v26, 424+0x1A0)
+	SAVE_VECTOR_UNALIGNED(v27, 424+0x1B0)
+	SAVE_VECTOR_UNALIGNED(v28, 424+0x1C0)
+	SAVE_VECTOR_UNALIGNED(v29, 424+0x1D0)
+	SAVE_VECTOR_UNALIGNED(v30, 424+0x1E0)
+	SAVE_VECTOR_UNALIGNED(v31, 424+0x1F0)
+
+	li	r3, 0		; return UNW_ESUCCESS
+	blr
+
+
+
+#endif
+
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
new file mode 100644
index 0000000..cac2101
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -0,0 +1,813 @@
+//===-- GDBRemoteCommunication.cpp ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "GDBRemoteCommunication.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/ConnectionFileDescriptor.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/State.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/TimeValue.h"
+
+// Project includes
+#include "StringExtractorGDBRemote.h"
+#include "ProcessGDBRemote.h"
+#include "ProcessGDBRemoteLog.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// GDBRemoteCommunication constructor
+//----------------------------------------------------------------------
+GDBRemoteCommunication::GDBRemoteCommunication() :
+    Communication("gdb-remote.packets"),
+    m_send_acks (true),
+    m_rx_packet_listener ("gdbremote.rx_packet"),
+    m_sequence_mutex (Mutex::eMutexTypeRecursive),
+    m_is_running (false),
+    m_async_mutex (Mutex::eMutexTypeRecursive),
+    m_async_packet_predicate (false),
+    m_async_packet (),
+    m_async_response (),
+    m_async_timeout (UINT32_MAX),
+    m_async_signal (-1),
+    m_arch(),
+    m_os(),
+    m_vendor(),
+    m_byte_order(eByteOrderHost),
+    m_pointer_byte_size(0)
+{
+    m_rx_packet_listener.StartListeningForEvents(this,
+                                                 Communication::eBroadcastBitPacketAvailable  |
+                                                 Communication::eBroadcastBitReadThreadDidExit);
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+GDBRemoteCommunication::~GDBRemoteCommunication()
+{
+    m_rx_packet_listener.StopListeningForEvents(this,
+                                                Communication::eBroadcastBitPacketAvailable  |
+                                                Communication::eBroadcastBitReadThreadDidExit);
+    if (IsConnected())
+    {
+        StopReadThread();
+        Disconnect();
+    }
+}
+
+
+char
+GDBRemoteCommunication::CalculcateChecksum (const char *payload, size_t payload_length)
+{
+    int checksum = 0;
+
+    // We only need to compute the checksum if we are sending acks
+    if (m_send_acks)
+    {
+        for (int i = 0; i < payload_length; ++i)
+            checksum += payload[i];
+    }
+    return checksum & 255;
+}
+
+size_t
+GDBRemoteCommunication::SendAck (char ack_char)
+{
+    Mutex::Locker locker(m_sequence_mutex);
+    ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS, "send packet: %c", ack_char);
+    ConnectionStatus status = eConnectionStatusSuccess;
+    return Write (&ack_char, 1, status, NULL) == 1;
+}
+
+size_t
+GDBRemoteCommunication::SendPacketAndWaitForResponse
+(
+    const char *payload,
+    StringExtractorGDBRemote &response,
+    uint32_t timeout_seconds,
+    bool send_async
+)
+{
+    return SendPacketAndWaitForResponse (payload, 
+                                         ::strlen (payload),
+                                         response,
+                                         timeout_seconds,
+                                         send_async);
+}
+
+size_t
+GDBRemoteCommunication::SendPacketAndWaitForResponse
+(
+    const char *payload,
+    size_t payload_length,
+    StringExtractorGDBRemote &response,
+    uint32_t timeout_seconds,
+    bool send_async
+)
+{
+    Mutex::Locker locker;
+    TimeValue timeout_time;
+    timeout_time = TimeValue::Now();
+    timeout_time.OffsetWithSeconds (timeout_seconds);
+
+    if (locker.TryLock (m_sequence_mutex.GetMutex()))
+    {
+        if (SendPacketNoLock (payload, strlen(payload)))
+            return WaitForPacketNoLock (response, &timeout_time);
+    }
+    else
+    {
+        if (send_async)
+        {
+            Mutex::Locker async_locker (m_async_mutex);
+            m_async_packet.assign(payload, payload_length);
+            m_async_timeout = timeout_seconds;
+            m_async_packet_predicate.SetValue (true, eBroadcastNever);
+            
+            bool timed_out = false;
+            if (SendInterrupt(1, &timed_out))
+            {
+                if (m_async_packet_predicate.WaitForValueEqualTo (false, &timeout_time, &timed_out))
+                {
+                    response = m_async_response;
+                    return response.GetStringRef().size();
+                }
+            }
+//            if (timed_out)
+//                m_error.SetErrorString("Timeout.");
+//            else
+//                m_error.SetErrorString("Unknown error.");
+        }
+        else
+        {
+//            m_error.SetErrorString("Sequence mutex is locked.");
+        }
+    }
+    return 0;
+}
+
+//template<typename _Tp>
+//class ScopedValueChanger
+//{
+//public:
+//    // Take a value reference and the value to assing it to when this class
+//    // instance goes out of scope.
+//    ScopedValueChanger (_Tp &value_ref, _Tp value) :
+//        m_value_ref (value_ref),
+//        m_value (value)
+//    {
+//    }
+//
+//    // This object is going out of scope, change the value pointed to by
+//    // m_value_ref to the value we got during construction which was stored in
+//    // m_value;
+//    ~ScopedValueChanger ()
+//    {
+//        m_value_ref = m_value;
+//    }
+//protected:
+//    _Tp &m_value_ref;   // A reference to the value we wil change when this object destructs
+//    _Tp m_value;        // The value to assign to m_value_ref when this goes out of scope.
+//};
+
+StateType
+GDBRemoteCommunication::SendContinuePacketAndWaitForResponse
+(
+    ProcessGDBRemote *process,
+    const char *payload,
+    size_t packet_length,
+    StringExtractorGDBRemote &response
+)
+{
+    Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS);
+    if (log)
+        log->Printf ("GDBRemoteCommunication::%s ()", __FUNCTION__);
+
+    Mutex::Locker locker(m_sequence_mutex);
+    m_is_running.SetValue (true, eBroadcastNever);
+
+//    ScopedValueChanger<bool> restore_running_to_false (m_is_running, false);
+    StateType state = eStateRunning;
+
+    if (SendPacket(payload, packet_length) == 0)
+        state = eStateInvalid;
+
+    while (state == eStateRunning)
+    {
+        if (log)
+            log->Printf ("GDBRemoteCommunication::%s () WaitForPacket(...)", __FUNCTION__);
+
+        if (WaitForPacket (response, (TimeValue*)NULL))
+        {
+            if (response.Empty())
+                state = eStateInvalid;
+            else
+            {
+                const char stop_type = response.GetChar();
+                if (log)
+                    log->Printf ("GDBRemoteCommunication::%s () got '%c' packet", __FUNCTION__, stop_type);
+                switch (stop_type)
+                {
+                case 'T':
+                case 'S':
+                    if (m_async_signal != -1)
+                    {
+                        // Save off the async signal we are supposed to send
+                        const int async_signal = m_async_signal;
+                        // Clear the async signal member so we don't end up
+                        // sending the signal multiple times...
+                        m_async_signal = -1;
+                        // Check which signal we stopped with
+                        uint8_t signo = response.GetHexU8(255);
+                        if (signo == async_signal)
+                        {
+                            // We already stopped with a signal that we wanted
+                            // to stop with, so we are done
+                            response.SetFilePos (0);
+                        }
+                        else
+                        {
+                            // We stopped with a different signal that the one
+                            // we wanted to stop with, so now we must resume
+                            // with the signal we want
+                            char signal_packet[32];
+                            int signal_packet_len = 0;
+                            signal_packet_len = ::snprintf (signal_packet,
+                                                            sizeof (signal_packet),
+                                                            "C%2.2x",
+                                                            async_signal);
+
+                            if (SendPacket(signal_packet, signal_packet_len) == 0)
+                            {
+                                state = eStateInvalid;
+                                break;
+                            }
+                            else
+                                continue;
+                        }
+                    }
+                    else if (m_async_packet_predicate.GetValue())
+                    {
+                        // We are supposed to send an asynchronous packet while
+                        // we are running. 
+                        m_async_response.Clear();
+                        if (!m_async_packet.empty())
+                        {
+                            SendPacketAndWaitForResponse (m_async_packet.data(), 
+                                                          m_async_packet.size(),
+                                                          m_async_response,
+                                                          m_async_timeout,
+                                                          false);
+                        }
+                        // Let the other thread that was trying to send the async
+                        // packet know that the packet has been sent.
+                        m_async_packet_predicate.SetValue(false, eBroadcastAlways);
+
+                        // Continue again
+                        if (SendPacket("c", 1) == 0)
+                        {
+                            state = eStateInvalid;
+                            break;
+                        }
+                        else
+                            continue;
+                    }
+                    // Stop with signal and thread info
+                    state = eStateStopped;
+                    break;
+
+                case 'W':
+                    // process exited
+                    state = eStateExited;
+                    break;
+
+                case 'O':
+                    // STDOUT
+                    {
+                        std::string inferior_stdout;
+                        inferior_stdout.reserve(response.GetBytesLeft () / 2);
+                        char ch;
+                        while ((ch = response.GetHexU8()) != '\0')
+                            inferior_stdout.append(1, ch);
+                        process->AppendSTDOUT (inferior_stdout.c_str(), inferior_stdout.size());
+                    }
+                    break;
+
+                case 'E':
+                    // ERROR
+                    state = eStateInvalid;
+                    break;
+
+                default:
+                    if (log)
+                        log->Printf ("GDBRemoteCommunication::%s () got unrecognized async packet: '%s'", __FUNCTION__, stop_type);
+                    break;
+                }
+            }
+        }
+        else
+        {
+            if (log)
+                log->Printf ("GDBRemoteCommunication::%s () WaitForPacket(...) => false", __FUNCTION__);
+            state = eStateInvalid;
+        }
+    }
+    if (log)
+        log->Printf ("GDBRemoteCommunication::%s () => %s", __FUNCTION__, StateAsCString(state));
+    response.SetFilePos(0);
+    m_is_running.SetValue (false, eBroadcastOnChange);
+    return state;
+}
+
+size_t
+GDBRemoteCommunication::SendPacket (const char *payload)
+{
+    Mutex::Locker locker(m_sequence_mutex);
+    return SendPacketNoLock (payload, ::strlen (payload));
+}
+
+size_t
+GDBRemoteCommunication::SendPacket (const char *payload, size_t payload_length)
+{
+    Mutex::Locker locker(m_sequence_mutex);
+    return SendPacketNoLock (payload, payload_length);
+}
+
+size_t
+GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_length)
+{
+    if (IsConnected())
+    {
+        StreamString packet(0, 4, eByteOrderBig);
+
+        packet.PutChar('$');
+        packet.Write (payload, payload_length);
+        packet.PutChar('#');
+        packet.PutHex8(CalculcateChecksum (payload, payload_length));
+
+        ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS, "send packet: %s", packet.GetData());
+        ConnectionStatus status = eConnectionStatusSuccess;
+        size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL);
+        if (bytes_written == packet.GetSize())
+        {
+            if (m_send_acks)
+                GetAck (1) == '+';
+        }
+        return bytes_written;
+   }
+    //m_error.SetErrorString("Not connected.");
+    return 0;
+}
+
+char
+GDBRemoteCommunication::GetAck (uint32_t timeout_seconds)
+{
+    StringExtractorGDBRemote response;
+    if (WaitForPacket (response, timeout_seconds) == 1)
+        return response.GetChar();
+    return 0;
+}
+
+bool
+GDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker)
+{
+    return locker.TryLock (m_sequence_mutex.GetMutex());
+}
+
+bool
+GDBRemoteCommunication::SendAsyncSignal (int signo)
+{
+    m_async_signal = signo;
+    bool timed_out = false;
+    if (SendInterrupt(1, &timed_out))
+        return true;
+    m_async_signal = -1;
+    return false;
+}
+
+bool
+GDBRemoteCommunication::SendInterrupt (uint32_t seconds_to_wait_for_stop, bool *timed_out)
+{
+    if (timed_out)
+        *timed_out = false;
+
+    if (IsConnected() && IsRunning())
+    {
+        // Only send an interrupt if our debugserver is running...
+        if (m_sequence_mutex.TryLock() != 0)
+        {
+            // Someone has the mutex locked waiting for a response or for the
+            // inferior to stop, so send the interrupt on the down low...
+            char ctrl_c = '\x03';
+            ConnectionStatus status = eConnectionStatusSuccess;
+            TimeValue timeout;
+            if (seconds_to_wait_for_stop)
+            {
+                timeout = TimeValue::Now();
+                timeout.OffsetWithSeconds (seconds_to_wait_for_stop);
+            }
+            ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS, "send packet: \\x03");
+            if (Write (&ctrl_c, 1, status, NULL) > 0)
+            {
+                if (seconds_to_wait_for_stop)
+                    m_is_running.WaitForValueEqualTo (false, &timeout, timed_out);
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+size_t
+GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &response, uint32_t timeout_seconds)
+{
+    TimeValue timeout_time;
+    timeout_time = TimeValue::Now();
+    timeout_time.OffsetWithSeconds (timeout_seconds);
+    return WaitForPacketNoLock (response, &timeout_time);
+}
+
+size_t
+GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &response, TimeValue* timeout_time_ptr)
+{
+    Mutex::Locker locker(m_sequence_mutex);
+    return WaitForPacketNoLock (response, timeout_time_ptr);
+}
+
+size_t
+GDBRemoteCommunication::WaitForPacketNoLock (StringExtractorGDBRemote &response, TimeValue* timeout_time_ptr)
+{
+    bool checksum_error = false;
+    response.Clear ();
+
+    EventSP event_sp;
+
+    if (m_rx_packet_listener.WaitForEvent (timeout_time_ptr, event_sp))
+    {
+        const uint32_t event_type = event_sp->GetType();
+        if (event_type | Communication::eBroadcastBitPacketAvailable)
+        {
+            const EventDataBytes *event_bytes = EventDataBytes::GetEventDataFromEvent(event_sp.get());
+            if (event_bytes)
+            {
+                const char * packet_data =  (const char *)event_bytes->GetBytes();
+                ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS, "read packet: %s", packet_data);
+                const size_t packet_size =  event_bytes->GetByteSize();
+                if (packet_data && packet_size > 0)
+                {
+                    std::string &response_str = response.GetStringRef();
+                    if (packet_data[0] == '$')
+                    {
+                        assert (packet_size >= 4);  // Must have at least '$#CC' where CC is checksum
+                        assert (packet_data[packet_size-3] == '#');
+                        assert (::isxdigit (packet_data[packet_size-2]));  // Must be checksum hex byte
+                        assert (::isxdigit (packet_data[packet_size-1]));  // Must be checksum hex byte
+                        response_str.assign (packet_data + 1, packet_size - 4);
+                        if (m_send_acks)
+                        {
+                            char packet_checksum = strtol (&packet_data[packet_size-2], NULL, 16);
+                            char actual_checksum = CalculcateChecksum (response_str.data(), response_str.size());
+                            checksum_error = packet_checksum != actual_checksum;
+                            // Send the ack or nack if needed
+                            if (checksum_error)
+                                SendAck('-');
+                            else
+                                SendAck('+');
+                        }
+                    }
+                    else
+                    {
+                        response_str.assign (packet_data, packet_size);
+                    }
+                    return response_str.size();
+                }
+            }
+        }
+        else if (Communication::eBroadcastBitReadThreadDidExit)
+        {
+            // Our read thread exited on us so just fall through and return zero...
+        }
+    }
+    return 0;
+}
+
+void
+GDBRemoteCommunication::AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast)
+{
+    // Put the packet data into the buffer in a thread safe fashion
+    Mutex::Locker locker(m_bytes_mutex);
+    m_bytes.append ((const char *)src, src_len);
+
+    // Parse up the packets into gdb remote packets
+    while (!m_bytes.empty())
+    {
+        // end_idx must be one past the last valid packet byte. Start
+        // it off with an invalid value that is the same as the current
+        // index.
+        size_t end_idx = 0;
+
+        switch (m_bytes[0])
+        {
+            case '+':       // Look for ack
+            case '-':       // Look for cancel
+            case '\x03':    // ^C to halt target
+                end_idx = 1;  // The command is one byte long...
+                break;
+
+            case '$':
+                // Look for a standard gdb packet?
+                end_idx = m_bytes.find('#');
+                if (end_idx != std::string::npos)
+                {
+                    if (end_idx + 2 < m_bytes.size())
+                    {
+                        end_idx += 3;
+                    }
+                    else
+                    {
+                        // Checksum bytes aren't all here yet
+                        end_idx = std::string::npos;
+                    }
+                }
+                break;
+
+            default:
+                break;
+        }
+
+        if (end_idx == std::string::npos)
+        {
+            //ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE, "GDBRemoteCommunication::%s packet not yet complete: '%s'",__FUNCTION__, m_bytes.c_str());
+            return;
+        }
+        else if (end_idx > 0)
+        {
+            // We have a valid packet...
+            assert (end_idx <= m_bytes.size());
+            std::auto_ptr<EventDataBytes> event_bytes_ap (new EventDataBytes (&m_bytes[0], end_idx));
+            ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "got full packet: %s", event_bytes_ap->GetBytes());
+            BroadcastEvent (eBroadcastBitPacketAvailable, event_bytes_ap.release());
+            m_bytes.erase(0, end_idx);
+        }
+        else
+        {
+            assert (1 <= m_bytes.size());
+            ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "GDBRemoteCommunication::%s tossing junk byte at %c",__FUNCTION__, m_bytes[0]);
+            m_bytes.erase(0, 1);
+        }
+    }
+}
+
+lldb::pid_t
+GDBRemoteCommunication::GetCurrentProcessID (uint32_t timeout_seconds)
+{
+    StringExtractorGDBRemote response;
+    if (SendPacketAndWaitForResponse("qC", strlen("qC"), response, timeout_seconds, false))
+    {
+        if (response.GetChar() == 'Q')
+            if (response.GetChar() == 'C')
+                return response.GetHexMaxU32 (false, LLDB_INVALID_PROCESS_ID);
+    }
+    return LLDB_INVALID_PROCESS_ID;
+}
+
+bool
+GDBRemoteCommunication::GetLaunchSuccess (uint32_t timeout_seconds, std::string &error_str)
+{
+    error_str.clear();
+    StringExtractorGDBRemote response;
+    if (SendPacketAndWaitForResponse("qLaunchSuccess", strlen("qLaunchSuccess"), response, timeout_seconds, false))
+    {
+        if (response.IsOKPacket())
+            return true;
+        if (response.GetChar() == 'E')
+        {
+            // A string the describes what failed when launching...
+            error_str = response.GetStringRef().substr(1);
+        }
+        else
+        {
+            error_str.assign ("unknown error occurred launching process");
+        }
+    }
+    else
+    {
+        error_str.assign ("failed to send the qLaunchSuccess packet");
+    }
+    return false;
+}
+
+int
+GDBRemoteCommunication::SendArgumentsPacket (char const *argv[], uint32_t timeout_seconds)
+{
+    if (argv && argv[0])
+    {
+        StreamString packet;
+        packet.PutChar('A');
+        const char *arg;
+        for (uint32_t i = 0; (arg = argv[i]) != NULL; ++i)
+        {
+            const int arg_len = strlen(arg);
+            if (i > 0)
+                packet.PutChar(',');
+            packet.Printf("%i,%i,", arg_len * 2, i);
+            packet.PutBytesAsRawHex8(arg, arg_len, eByteOrderHost, eByteOrderHost);
+        }
+
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, timeout_seconds, false))
+        {
+            if (response.IsOKPacket())
+                return 0;
+            uint8_t error = response.GetError();
+            if (error)
+                return error;
+        }
+    }
+    return -1;
+}
+
+int
+GDBRemoteCommunication::SendEnvironmentPacket (char const *name_equal_value, uint32_t timeout_seconds)
+{
+    if (name_equal_value && name_equal_value[0])
+    {
+        StreamString packet;
+        packet.Printf("QEnvironment:%s", name_equal_value);
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, timeout_seconds, false))
+        {
+            if (response.IsOKPacket())
+                return 0;
+            uint8_t error = response.GetError();
+            if (error)
+                return error;
+        }
+    }
+    return -1;
+}
+
+bool
+GDBRemoteCommunication::GetHostInfo (uint32_t timeout_seconds)
+{
+    m_arch.Clear();
+    m_os.Clear();
+    m_vendor.Clear();
+    m_byte_order = eByteOrderHost;
+    m_pointer_byte_size = 0;
+
+    StringExtractorGDBRemote response;
+    if (SendPacketAndWaitForResponse ("qHostInfo", response, timeout_seconds, false))
+    {
+        if (response.IsUnsupportedPacket())
+            return false;
+
+        
+        std::string name;
+        std::string value;
+        while (response.GetNameColonValue(name, value))
+        {
+            if (name.compare("cputype") == 0)
+            {
+                // exception type in big endian hex
+                m_arch.SetCPUType(Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0));
+            }
+            else if (name.compare("cpusubtype") == 0)
+            {
+                // exception count in big endian hex
+                m_arch.SetCPUSubtype(Args::StringToUInt32 (value.c_str(), 0, 0));
+            }
+            else if (name.compare("ostype") == 0)
+            {
+                // exception data in big endian hex
+                m_os.SetCString(value.c_str());
+            }
+            else if (name.compare("vendor") == 0)
+            {
+                m_vendor.SetCString(value.c_str());
+            }
+            else if (name.compare("endian") == 0)
+            {
+                if (value.compare("little") == 0)
+                    m_byte_order = eByteOrderLittle;
+                else if (value.compare("big") == 0)
+                    m_byte_order = eByteOrderBig;
+                else if (value.compare("pdp") == 0)
+                    m_byte_order = eByteOrderPDP;
+            }
+            else if (name.compare("ptrsize") == 0)
+            {
+                m_pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0);
+            }
+        }
+    }
+    return HostInfoIsValid();
+}
+
+int
+GDBRemoteCommunication::SendAttach 
+(
+    lldb::pid_t pid, 
+    uint32_t timeout_seconds, 
+    StringExtractorGDBRemote& response
+)
+{
+    if (pid != LLDB_INVALID_PROCESS_ID)
+    {
+        StreamString packet;
+        packet.Printf("vAttach;%x", pid);
+        
+        if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, timeout_seconds, false))
+        {
+            if (response.IsErrorPacket())
+                return response.GetError();
+            return 0;
+        }
+    }
+    return -1;
+}
+
+const lldb_private::ArchSpec &
+GDBRemoteCommunication::GetHostArchitecture ()
+{
+    if (!HostInfoIsValid ())
+        GetHostInfo (1);
+    return m_arch;
+}
+
+const lldb_private::ConstString &
+GDBRemoteCommunication::GetOSString ()
+{
+    if (!HostInfoIsValid ())
+        GetHostInfo (1);
+    return m_os;
+}
+
+const lldb_private::ConstString &
+GDBRemoteCommunication::GetVendorString()
+{
+    if (!HostInfoIsValid ())
+        GetHostInfo (1);
+    return m_vendor;
+}
+
+lldb::ByteOrder
+GDBRemoteCommunication::GetByteOrder ()
+{
+    if (!HostInfoIsValid ())
+        GetHostInfo (1);
+    return m_byte_order;
+}
+
+uint32_t
+GDBRemoteCommunication::GetAddressByteSize ()
+{
+    if (!HostInfoIsValid ())
+        GetHostInfo (1);
+    return m_pointer_byte_size;
+}
+
+addr_t
+GDBRemoteCommunication::AllocateMemory (size_t size, uint32_t permissions, uint32_t timeout_seconds)
+{
+    char packet[64];
+    ::snprintf (packet, sizeof(packet), "_M%zx,%s%s%s", size,
+                permissions & lldb::ePermissionsReadable ? "r" : "",
+                permissions & lldb::ePermissionsWritable ? "w" : "",
+                permissions & lldb::ePermissionsExecutable ? "x" : "");
+    StringExtractorGDBRemote response;
+    if (SendPacketAndWaitForResponse (packet, response, timeout_seconds, false))
+    {
+        if (!response.IsErrorPacket())
+            return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
+    }
+    return LLDB_INVALID_ADDRESS;
+}
+
+bool
+GDBRemoteCommunication::DeallocateMemory (addr_t addr, uint32_t timeout_seconds)
+{
+    char packet[64];
+    snprintf(packet, sizeof(packet), "_m%llx", (uint64_t)addr);
+    StringExtractorGDBRemote response;
+    if (SendPacketAndWaitForResponse (packet, response, timeout_seconds, false))
+    {
+        if (!response.IsOKPacket())
+            return true;
+    }
+    return false;
+}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
new file mode 100644
index 0000000..051fa44
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -0,0 +1,270 @@
+//===-- GDBRemoteCommunication.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_GDBRemoteCommunication_h_
+#define liblldb_GDBRemoteCommunication_h_
+
+// C Includes
+// C++ Includes
+#include <list>
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Communication.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Listener.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Host/Predicate.h"
+
+#include "StringExtractorGDBRemote.h"
+
+class ProcessGDBRemote;
+
+class GDBRemoteCommunication :
+    public lldb_private::Communication
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    GDBRemoteCommunication();
+
+    virtual
+    ~GDBRemoteCommunication();
+
+    size_t
+    SendPacket (const char *payload);
+
+    size_t
+    SendPacket (const char *payload,
+                size_t payload_length);
+
+    size_t
+    SendPacketAndWaitForResponse (const char *send_payload,
+                                  StringExtractorGDBRemote &response,
+                                  uint32_t timeout_seconds,
+                                  bool send_async);
+
+    size_t
+    SendPacketAndWaitForResponse (const char *send_payload,
+                                  size_t send_length,
+                                  StringExtractorGDBRemote &response,
+                                  uint32_t timeout_seconds,
+                                  bool send_async);
+
+    lldb::StateType
+    SendContinuePacketAndWaitForResponse (ProcessGDBRemote *process,
+                                          const char *packet_payload,
+                                          size_t packet_length,
+                                          StringExtractorGDBRemote &response);
+
+    // Wait for a packet within 'nsec' seconds
+    size_t
+    WaitForPacket (StringExtractorGDBRemote &response,
+                   uint32_t nsec);
+
+    // Wait for a packet with an absolute timeout time. If 'timeout' is NULL
+    // wait indefinitely.
+    size_t
+    WaitForPacket (StringExtractorGDBRemote &response,
+                   lldb_private::TimeValue* timeout);
+
+    char
+    GetAck (uint32_t timeout_seconds);
+
+    size_t
+    SendAck (char ack_char);
+
+    char
+    CalculcateChecksum (const char *payload,
+                        size_t payload_length);
+
+    void
+    SetAckMode (bool enabled)
+    {
+        m_send_acks = enabled;
+    }
+
+    bool
+    SendAsyncSignal (int signo);
+
+    bool
+    SendInterrupt (uint32_t seconds_to_wait_for_stop, bool *timed_out = NULL);
+
+    bool
+    GetSequenceMutex(lldb_private::Mutex::Locker& locker);
+
+    //------------------------------------------------------------------
+    // Communication overrides
+    //------------------------------------------------------------------
+    virtual void
+    AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast);
+
+
+    lldb::pid_t
+    GetCurrentProcessID (uint32_t timeout_seconds);
+
+    bool
+    GetLaunchSuccess (uint32_t timeout_seconds, std::string &error_str);
+
+    //------------------------------------------------------------------
+    /// Sends a GDB remote protocol 'A' packet that delivers program
+    /// arguments to the remote server.
+    ///
+    /// @param[in] argv
+    ///     A NULL terminated array of const C strings to use as the
+    ///     arguments.
+    ///
+    /// @param[in] timeout_seconds
+    ///     The number of seconds to wait for a response from the remote
+    ///     server.
+    ///
+    /// @return
+    ///     Zero if the response was "OK", a positive value if the
+    ///     the response was "Exx" where xx are two hex digits, or
+    ///     -1 if the call is unsupported or any other unexpected
+    ///     response was received.
+    //------------------------------------------------------------------
+    int
+    SendArgumentsPacket (char const *argv[], uint32_t timeout_seconds);
+
+    //------------------------------------------------------------------
+    /// Sends a "QEnvironment:NAME=VALUE" packet that will build up the
+    /// environment that will get used when launching an application
+    /// in conjunction with the 'A' packet. This function can be called
+    /// multiple times in a row in order to pass on the desired
+    /// environment that the inferior should be launched with.
+    ///
+    /// @param[in] name_equal_value
+    ///     A NULL terminated C string that contains a single enironment
+    ///     in the format "NAME=VALUE".
+    ///
+    /// @param[in] timeout_seconds
+    ///     The number of seconds to wait for a response from the remote
+    ///     server.
+    ///
+    /// @return
+    ///     Zero if the response was "OK", a positive value if the
+    ///     the response was "Exx" where xx are two hex digits, or
+    ///     -1 if the call is unsupported or any other unexpected
+    ///     response was received.
+    //------------------------------------------------------------------
+    int
+    SendEnvironmentPacket (char const *name_equal_value,
+                           uint32_t timeout_seconds);
+
+    //------------------------------------------------------------------
+    /// Sends a "vAttach:PID" where PID is in hex. 
+    ///
+    /// @param[in] pid
+    ///     A process ID for the remote gdb server to attach to.
+    ///
+    /// @param[in] timeout_seconds
+    ///     The number of seconds to wait for a response from the remote
+    ///     server.
+    ///
+    /// @param[out] response
+    ///     The response received from the gdb server. If the return
+    ///     value is zero, \a response will contain a stop reply 
+    ///     packet.
+    ///
+    /// @return
+    ///     Zero if the attach was successful, or an error indicating
+    ///     an error code.
+    //------------------------------------------------------------------
+    int
+    SendAttach (lldb::pid_t pid, 
+                uint32_t timeout_seconds, 
+                StringExtractorGDBRemote& response);
+
+
+    lldb::addr_t
+    AllocateMemory (size_t size, uint32_t permissions, uint32_t timeout_seconds);
+
+    bool
+    DeallocateMemory (lldb::addr_t addr, uint32_t timeout_seconds);
+
+    bool
+    IsRunning() const
+    {
+        return m_is_running.GetValue();
+    }
+    
+    bool
+    GetHostInfo (uint32_t timeout_seconds);
+
+    bool 
+    HostInfoIsValid () const
+    {
+        return m_pointer_byte_size != 0;
+    }
+
+    const lldb_private::ArchSpec &
+    GetHostArchitecture ();
+    
+    const lldb_private::ConstString &
+    GetOSString ();
+    
+    const lldb_private::ConstString &
+    GetVendorString();
+    
+    lldb::ByteOrder
+    GetByteOrder ();
+
+    uint32_t
+    GetAddressByteSize ();
+
+protected:
+    typedef std::list<std::string> packet_collection;
+
+    size_t
+    SendPacketNoLock (const char *payload, 
+                      size_t payload_length);
+
+    size_t
+    WaitForPacketNoLock (StringExtractorGDBRemote &response, 
+                         lldb_private::TimeValue* timeout_time_ptr);
+
+    //------------------------------------------------------------------
+    // Classes that inherit from GDBRemoteCommunication can see and modify these
+    //------------------------------------------------------------------
+    bool m_send_acks;
+    lldb_private::Listener m_rx_packet_listener;
+    lldb_private::Mutex m_sequence_mutex;    // Restrict access to sending/receiving packets to a single thread at a time
+    lldb_private::Predicate<bool> m_is_running;
+
+    // If we need to send a packet while the target is running, the m_async_XXX
+    // member variables take care of making this happen.
+    lldb_private::Mutex m_async_mutex;
+    lldb_private::Predicate<bool> m_async_packet_predicate;
+    std::string m_async_packet;
+    StringExtractorGDBRemote m_async_response;
+    uint32_t m_async_timeout;
+    int m_async_signal; // We were asked to deliver a signal to the inferior process.
+    
+    lldb_private::ArchSpec m_arch;      // Results from the qHostInfo call
+    uint32_t m_cpusubtype;              // Results from the qHostInfo call
+    lldb_private::ConstString m_os;     // Results from the qHostInfo call
+    lldb_private::ConstString m_vendor; // Results from the qHostInfo call
+    lldb::ByteOrder m_byte_order;       // Results from the qHostInfo call
+    uint32_t m_pointer_byte_size;       // Results from the qHostInfo call
+    
+    
+private:
+    //------------------------------------------------------------------
+    // For GDBRemoteCommunication only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunication);
+};
+
+#endif  // liblldb_GDBRemoteCommunication_h_
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
new file mode 100644
index 0000000..a64e74d
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -0,0 +1,508 @@
+//===-- GDBRemoteRegisterContext.cpp ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GDBRemoteRegisterContext.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/StreamString.h"
+// Project includes
+#include "StringExtractorGDBRemote.h"
+#include "ProcessGDBRemote.h"
+#include "ThreadGDBRemote.h"
+#include "ARM_GCC_Registers.h"
+#include "ARM_DWARF_Registers.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// GDBRemoteRegisterContext constructor
+//----------------------------------------------------------------------
+GDBRemoteRegisterContext::GDBRemoteRegisterContext
+(
+    ThreadGDBRemote &thread,
+    StackFrame *frame,
+    GDBRemoteDynamicRegisterInfo &reg_info,
+    bool read_all_at_once
+) :
+    RegisterContext (thread, frame),
+    m_reg_info (reg_info),
+    m_reg_valid (),
+    m_reg_data (),
+    m_read_all_at_once (read_all_at_once)
+{
+    // 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.
+    m_reg_valid.resize (reg_info.GetNumRegisters());
+
+    // Make a heap based buffer that is big enough to store all registers
+    DataBufferSP reg_data_sp(new DataBufferHeap (reg_info.GetRegisterDataByteSize(), 0));
+    m_reg_data.SetData (reg_data_sp);
+
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+GDBRemoteRegisterContext::~GDBRemoteRegisterContext()
+{
+}
+
+ProcessGDBRemote &
+GDBRemoteRegisterContext::GetGDBProcess()
+{
+    return static_cast<ProcessGDBRemote &>(m_thread.GetProcess());
+}
+
+ThreadGDBRemote &
+GDBRemoteRegisterContext::GetGDBThread()
+{
+    return static_cast<ThreadGDBRemote &>(m_thread);
+}
+
+void
+GDBRemoteRegisterContext::Invalidate ()
+{
+    SetAllRegisterValid (false);
+}
+
+void
+GDBRemoteRegisterContext::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
+GDBRemoteRegisterContext::GetRegisterCount ()
+{
+    return m_reg_info.GetNumRegisters ();
+}
+
+const lldb::RegisterInfo *
+GDBRemoteRegisterContext::GetRegisterInfoAtIndex (uint32_t reg)
+{
+    return m_reg_info.GetRegisterInfoAtIndex (reg);
+}
+
+size_t
+GDBRemoteRegisterContext::GetRegisterSetCount ()
+{
+    return m_reg_info.GetNumRegisterSets ();
+}
+
+
+
+const lldb::RegisterSet *
+GDBRemoteRegisterContext::GetRegisterSet (uint32_t reg_set)
+{
+    return m_reg_info.GetRegisterSet (reg_set);
+}
+
+
+
+bool
+GDBRemoteRegisterContext::ReadRegisterValue (uint32_t reg, Scalar &value)
+{
+    // Read the register
+    if (ReadRegisterBytes (reg, m_reg_data))
+    {
+        const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
+        uint32_t offset = reg_info->byte_offset;
+        switch (reg_info->encoding)
+        {
+        case eEncodingUint:
+            switch (reg_info->byte_size)
+            {
+            case 1:
+            case 2:
+            case 4:
+                value = m_reg_data.GetMaxU32 (&offset, reg_info->byte_size);
+                return true;
+
+            case 8:
+                value = m_reg_data.GetMaxU64 (&offset, reg_info->byte_size);
+                return true;
+            }
+            break;
+
+        case eEncodingSint:
+            switch (reg_info->byte_size)
+            {
+            case 1:
+            case 2:
+            case 4:
+                value = (int32_t)m_reg_data.GetMaxU32 (&offset, reg_info->byte_size);
+                return true;
+
+            case 8:
+                value = m_reg_data.GetMaxS64 (&offset, reg_info->byte_size);
+                return true;
+            }
+            break;
+
+        case eEncodingIEEE754:
+            switch (reg_info->byte_size)
+            {
+            case sizeof (float):
+                value = m_reg_data.GetFloat (&offset);
+                return true;
+
+            case sizeof (double):
+                value = m_reg_data.GetDouble (&offset);
+                return true;
+
+            case sizeof (long double):
+                value = m_reg_data.GetLongDouble (&offset);
+                return true;
+            }
+            break;
+        }
+    }
+    return false;
+}
+
+
+bool
+GDBRemoteRegisterContext::ReadRegisterBytes (uint32_t reg, DataExtractor &data)
+{
+    GDBRemoteCommunication &gdb_comm = GetGDBProcess().GetGDBRemote();
+// FIXME: This check isn't right because IsRunning checks the Public state, but this
+// is work you need to do - for instance in ShouldStop & friends - before the public 
+// state has been changed.
+//    if (gdb_comm.IsRunning())
+//        return false;
+
+    if (m_reg_valid_stop_id != m_thread.GetProcess().GetStopID())
+    {
+        Invalidate();
+        m_reg_valid_stop_id = m_thread.GetProcess().GetStopID();
+    }
+    const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
+    assert (reg_info);
+    if (m_reg_valid[reg] == false)
+    {
+        Mutex::Locker locker;
+        if (gdb_comm.GetSequenceMutex (locker))
+        {
+            if (GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
+            {
+                char packet[32];
+                StringExtractorGDBRemote response;
+                int packet_len;
+                if (m_read_all_at_once)
+                {
+                    // Get all registers in one packet
+                    packet_len = ::snprintf (packet, sizeof(packet), "g");
+                    assert (packet_len < (sizeof(packet) - 1));
+                    if (gdb_comm.SendPacketAndWaitForResponse(packet, response, 1, false))
+                    {
+                        if (response.IsNormalPacket())
+                            if (response.GetHexBytes ((void *)m_reg_data.GetDataStart(), m_reg_data.GetByteSize(), '\xcc') == m_reg_data.GetByteSize())
+                                SetAllRegisterValid (true);
+                    }
+                }
+                else
+                {
+                    // Get each register individually
+                    packet_len = ::snprintf (packet, sizeof(packet), "p%x", reg, false);
+                    assert (packet_len < (sizeof(packet) - 1));
+                    if (gdb_comm.SendPacketAndWaitForResponse(packet, response, 1, false))
+                        if (response.GetHexBytes ((uint8_t*)m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size), reg_info->byte_size, '\xcc') == reg_info->byte_size)
+                            m_reg_valid[reg] = true;
+                }
+            }
+        }
+    }
+
+    bool reg_is_valid = m_reg_valid[reg];
+    if (reg_is_valid)
+    {
+        if (&data != &m_reg_data)
+        {
+            // If we aren't extracting into our own buffer (which
+            // only happens when this function is called from
+            // ReadRegisterValue(uint32_t, Scalar&)) then
+            // we transfer bytes from our buffer into the data
+            // buffer that was passed in
+            data.SetByteOrder (m_reg_data.GetByteOrder());
+            data.SetData (m_reg_data, reg_info->byte_offset, reg_info->byte_size);
+        }
+    }
+    return reg_is_valid;
+}
+
+
+bool
+GDBRemoteRegisterContext::WriteRegisterValue (uint32_t reg, const Scalar &value)
+{
+    const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
+    if (reg_info)
+    {
+        DataExtractor data;
+        if (value.GetData (data, reg_info->byte_size))
+            return WriteRegisterBytes (reg, data, 0);
+    }
+    return false;
+}
+
+
+bool
+GDBRemoteRegisterContext::WriteRegisterBytes (uint32_t reg, DataExtractor &data, uint32_t data_offset)
+{
+    GDBRemoteCommunication &gdb_comm = GetGDBProcess().GetGDBRemote();
+// FIXME: This check isn't right because IsRunning checks the Public state, but this
+// is work you need to do - for instance in ShouldStop & friends - before the public 
+// state has been changed.
+//    if (gdb_comm.IsRunning())
+//        return false;
+
+    const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
+
+    if (reg_info)
+    {
+        // Grab a pointer to where we are going to put this register
+        uint8_t *dst = (uint8_t *)m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size);
+
+        if (dst == NULL)
+            return false;
+
+        // Grab a pointer to where we are going to grab the new value from
+        const uint8_t *src = data.PeekData(0, reg_info->byte_size);
+
+        if (src == NULL)
+            return false;
+
+        if (data.GetByteOrder() == m_reg_data.GetByteOrder())
+        {
+            // No swapping, just copy the bytes
+            ::memcpy (dst, src, reg_info->byte_size);
+        }
+        else
+        {
+            // Swap the bytes
+            for (uint32_t i=0; i<reg_info->byte_size; ++i)
+                dst[i] = src[reg_info->byte_size - 1 - i];
+        }
+
+        Mutex::Locker locker;
+        if (gdb_comm.GetSequenceMutex (locker))
+        {
+            if (GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
+            {
+                uint32_t offset, end_offset;
+                StreamString packet;
+                StringExtractorGDBRemote response;
+                if (m_read_all_at_once)
+                {
+                    // Get all registers in one packet
+                    packet.PutChar ('G');
+                    offset = 0;
+                    end_offset = m_reg_data.GetByteSize();
+
+                    packet.PutBytesAsRawHex8 (m_reg_data.GetDataStart(),
+                                              m_reg_data.GetByteSize(),
+                                              eByteOrderHost,
+                                              eByteOrderHost);
+                    
+                    // Invalidate all register values
+                    Invalidate ();
+                    
+                    if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
+                                                              packet.GetString().size(),
+                                                              response,
+                                                              1,
+                                                              false))
+                    {
+                        SetAllRegisterValid (false);
+                        if (response.IsOKPacket())
+                        {
+                            return true;
+                        }
+                    }
+                }
+                else
+                {
+                    // Get each register individually
+                    packet.Printf ("P%x=", reg);
+                    packet.PutBytesAsRawHex8 (m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size),
+                                              reg_info->byte_size,
+                                              eByteOrderHost,
+                                              eByteOrderHost);
+
+                    // Invalidate just this register
+                    m_reg_valid[reg] = false;
+                    if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
+                                                              packet.GetString().size(),
+                                                              response,
+                                                              1,
+                                                              false))
+                    {
+                        if (response.IsOKPacket())
+                        {
+                            return true;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return false;
+}
+
+
+bool
+GDBRemoteRegisterContext::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
+{
+    GDBRemoteCommunication &gdb_comm = GetGDBProcess().GetGDBRemote();
+    StringExtractorGDBRemote response;
+    if (gdb_comm.SendPacketAndWaitForResponse("g", response, 1, false))
+    {
+        if (response.IsErrorPacket())
+            return false;
+            
+        response.GetStringRef().insert(0, 1, 'G');
+        data_sp.reset (new DataBufferHeap(response.GetStringRef().data(), 
+                                          response.GetStringRef().size()));
+        return true;
+    }
+    return false;
+}
+
+bool
+GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
+{
+    GDBRemoteCommunication &gdb_comm = GetGDBProcess().GetGDBRemote();
+    StringExtractorGDBRemote response;
+    if (gdb_comm.SendPacketAndWaitForResponse((const char *)data_sp->GetBytes(), 
+                                              data_sp->GetByteSize(), 
+                                              response, 
+                                              1, 
+                                              false))
+    {
+        if (response.IsOKPacket())
+            return true;
+    }
+    return false;
+}
+
+
+uint32_t
+GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
+{
+    return m_reg_info.ConvertRegisterKindToRegisterNumber (kind, num);
+}
+
+void
+GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters()
+{
+    static lldb::RegisterInfo
+    g_register_infos[] =
+    {
+        //  NAME        ALT     SZ  OFF   ENCODING           FORMAT          NUM      COMPILER            DWARF               GENERIC
+        //  ======      ======= ==  ====  =============      ============    ===  ===============     ===============     =========
+        {   "r0",       NULL,   4,    0,  eEncodingUint,     eFormatHex,      0,  { gcc_r0,               dwarf_r0,           LLDB_INVALID_REGNUM     }},
+        {   "r1",       NULL,   4,    4,  eEncodingUint,     eFormatHex,      1,  { gcc_r1,               dwarf_r1,           LLDB_INVALID_REGNUM     }},
+        {   "r2",       NULL,   4,    8,  eEncodingUint,     eFormatHex,      2,  { gcc_r2,               dwarf_r2,           LLDB_INVALID_REGNUM     }},
+        {   "r3",       NULL,   4,   12,  eEncodingUint,     eFormatHex,      3,  { gcc_r3,               dwarf_r3,           LLDB_INVALID_REGNUM     }},
+        {   "r4",       NULL,   4,   16,  eEncodingUint,     eFormatHex,      4,  { gcc_r4,               dwarf_r4,           LLDB_INVALID_REGNUM     }},
+        {   "r5",       NULL,   4,   20,  eEncodingUint,     eFormatHex,      5,  { gcc_r5,               dwarf_r5,           LLDB_INVALID_REGNUM     }},
+        {   "r6",       NULL,   4,   24,  eEncodingUint,     eFormatHex,      6,  { gcc_r6,               dwarf_r6,           LLDB_INVALID_REGNUM     }},
+        {   "r7",       NULL,   4,   28,  eEncodingUint,     eFormatHex,      7,  { gcc_r7,               dwarf_r7,           LLDB_REGNUM_GENERIC_FP  }},
+        {   "r8",       NULL,   4,   32,  eEncodingUint,     eFormatHex,      8,  { gcc_r8,               dwarf_r8,           LLDB_INVALID_REGNUM     }},
+        {   "r9",       NULL,   4,   36,  eEncodingUint,     eFormatHex,      9,  { gcc_r9,               dwarf_r9,           LLDB_INVALID_REGNUM     }},
+        {   "r10",      NULL,   4,   40,  eEncodingUint,     eFormatHex,     10,  { gcc_r10,              dwarf_r10,          LLDB_INVALID_REGNUM     }},
+        {   "r11",      NULL,   4,   44,  eEncodingUint,     eFormatHex,     11,  { gcc_r11,              dwarf_r11,          LLDB_INVALID_REGNUM     }},
+        {   "r12",      NULL,   4,   48,  eEncodingUint,     eFormatHex,     12,  { gcc_r12,              dwarf_r12,          LLDB_INVALID_REGNUM     }},
+        {   "sp",      "r13",   4,   52,  eEncodingUint,     eFormatHex,     13,  { gcc_sp,               dwarf_sp,           LLDB_REGNUM_GENERIC_SP  }},
+        {   "lr",      "r14",   4,   56,  eEncodingUint,     eFormatHex,     14,  { gcc_lr,               dwarf_lr,           LLDB_REGNUM_GENERIC_RA  }},
+        {   "pc",      "r15",   4,   60,  eEncodingUint,     eFormatHex,     15,  { gcc_pc,               dwarf_pc,           LLDB_REGNUM_GENERIC_PC  }},
+        {   NULL,       NULL,  12,   64,  eEncodingIEEE754,  eFormatFloat,   16,  { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
+        {   NULL,       NULL,  12,   76,  eEncodingIEEE754,  eFormatFloat,   17,  { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
+        {   NULL,       NULL,  12,   88,  eEncodingIEEE754,  eFormatFloat,   18,  { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
+        {   NULL,       NULL,  12,  100,  eEncodingIEEE754,  eFormatFloat,   19,  { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
+        {   NULL,       NULL,  12,  112,  eEncodingIEEE754,  eFormatFloat,   20,  { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
+        {   NULL,       NULL,  12,  124,  eEncodingIEEE754,  eFormatFloat,   21,  { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
+        {   NULL,       NULL,  12,  136,  eEncodingIEEE754,  eFormatFloat,   22,  { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
+        {   NULL,       NULL,  12,  148,  eEncodingIEEE754,  eFormatFloat,   23,  { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
+        {   NULL,       NULL,  12,  160,  eEncodingIEEE754,  eFormatFloat,   24,  { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
+        {   "cpsr",     "psr",  4,  172,  eEncodingUint,     eFormatHex,     25,  { gcc_cpsr,             dwarf_cpsr,         LLDB_REGNUM_GENERIC_FLAGS   }},
+        {   "s0",       NULL,   4,  176,  eEncodingIEEE754,  eFormatFloat,   26,  { LLDB_INVALID_REGNUM,  dwarf_s0,           LLDB_INVALID_REGNUM     }},
+        {   "s1",       NULL,   4,  180,  eEncodingIEEE754,  eFormatFloat,   27,  { LLDB_INVALID_REGNUM,  dwarf_s1,           LLDB_INVALID_REGNUM     }},
+        {   "s2",       NULL,   4,  184,  eEncodingIEEE754,  eFormatFloat,   28,  { LLDB_INVALID_REGNUM,  dwarf_s2,           LLDB_INVALID_REGNUM     }},
+        {   "s3",       NULL,   4,  188,  eEncodingIEEE754,  eFormatFloat,   29,  { LLDB_INVALID_REGNUM,  dwarf_s3,           LLDB_INVALID_REGNUM     }},
+        {   "s4",       NULL,   4,  192,  eEncodingIEEE754,  eFormatFloat,   30,  { LLDB_INVALID_REGNUM,  dwarf_s4,           LLDB_INVALID_REGNUM     }},
+        {   "s5",       NULL,   4,  196,  eEncodingIEEE754,  eFormatFloat,   31,  { LLDB_INVALID_REGNUM,  dwarf_s5,           LLDB_INVALID_REGNUM     }},
+        {   "s6",       NULL,   4,  200,  eEncodingIEEE754,  eFormatFloat,   32,  { LLDB_INVALID_REGNUM,  dwarf_s6,           LLDB_INVALID_REGNUM     }},
+        {   "s7",       NULL,   4,  204,  eEncodingIEEE754,  eFormatFloat,   33,  { LLDB_INVALID_REGNUM,  dwarf_s7,           LLDB_INVALID_REGNUM     }},
+        {   "s8",       NULL,   4,  208,  eEncodingIEEE754,  eFormatFloat,   34,  { LLDB_INVALID_REGNUM,  dwarf_s8,           LLDB_INVALID_REGNUM     }},
+        {   "s9",       NULL,   4,  212,  eEncodingIEEE754,  eFormatFloat,   35,  { LLDB_INVALID_REGNUM,  dwarf_s9,           LLDB_INVALID_REGNUM     }},
+        {   "s10",      NULL,   4,  216,  eEncodingIEEE754,  eFormatFloat,   36,  { LLDB_INVALID_REGNUM,  dwarf_s10,          LLDB_INVALID_REGNUM     }},
+        {   "s11",      NULL,   4,  220,  eEncodingIEEE754,  eFormatFloat,   37,  { LLDB_INVALID_REGNUM,  dwarf_s11,          LLDB_INVALID_REGNUM     }},
+        {   "s12",      NULL,   4,  224,  eEncodingIEEE754,  eFormatFloat,   38,  { LLDB_INVALID_REGNUM,  dwarf_s12,          LLDB_INVALID_REGNUM     }},
+        {   "s13",      NULL,   4,  228,  eEncodingIEEE754,  eFormatFloat,   39,  { LLDB_INVALID_REGNUM,  dwarf_s13,          LLDB_INVALID_REGNUM     }},
+        {   "s14",      NULL,   4,  232,  eEncodingIEEE754,  eFormatFloat,   40,  { LLDB_INVALID_REGNUM,  dwarf_s14,          LLDB_INVALID_REGNUM     }},
+        {   "s15",      NULL,   4,  236,  eEncodingIEEE754,  eFormatFloat,   41,  { LLDB_INVALID_REGNUM,  dwarf_s15,          LLDB_INVALID_REGNUM     }},
+        {   "s16",      NULL,   4,  240,  eEncodingIEEE754,  eFormatFloat,   42,  { LLDB_INVALID_REGNUM,  dwarf_s16,          LLDB_INVALID_REGNUM     }},
+        {   "s17",      NULL,   4,  244,  eEncodingIEEE754,  eFormatFloat,   43,  { LLDB_INVALID_REGNUM,  dwarf_s17,          LLDB_INVALID_REGNUM     }},
+        {   "s18",      NULL,   4,  248,  eEncodingIEEE754,  eFormatFloat,   44,  { LLDB_INVALID_REGNUM,  dwarf_s18,          LLDB_INVALID_REGNUM     }},
+        {   "s19",      NULL,   4,  252,  eEncodingIEEE754,  eFormatFloat,   45,  { LLDB_INVALID_REGNUM,  dwarf_s19,          LLDB_INVALID_REGNUM     }},
+        {   "s20",      NULL,   4,  256,  eEncodingIEEE754,  eFormatFloat,   46,  { LLDB_INVALID_REGNUM,  dwarf_s20,          LLDB_INVALID_REGNUM     }},
+        {   "s21",      NULL,   4,  260,  eEncodingIEEE754,  eFormatFloat,   47,  { LLDB_INVALID_REGNUM,  dwarf_s21,          LLDB_INVALID_REGNUM     }},
+        {   "s22",      NULL,   4,  264,  eEncodingIEEE754,  eFormatFloat,   48,  { LLDB_INVALID_REGNUM,  dwarf_s22,          LLDB_INVALID_REGNUM     }},
+        {   "s23",      NULL,   4,  268,  eEncodingIEEE754,  eFormatFloat,   49,  { LLDB_INVALID_REGNUM,  dwarf_s23,          LLDB_INVALID_REGNUM     }},
+        {   "s24",      NULL,   4,  272,  eEncodingIEEE754,  eFormatFloat,   50,  { LLDB_INVALID_REGNUM,  dwarf_s24,          LLDB_INVALID_REGNUM     }},
+        {   "s25",      NULL,   4,  276,  eEncodingIEEE754,  eFormatFloat,   51,  { LLDB_INVALID_REGNUM,  dwarf_s25,          LLDB_INVALID_REGNUM     }},
+        {   "s26",      NULL,   4,  280,  eEncodingIEEE754,  eFormatFloat,   52,  { LLDB_INVALID_REGNUM,  dwarf_s26,          LLDB_INVALID_REGNUM     }},
+        {   "s27",      NULL,   4,  284,  eEncodingIEEE754,  eFormatFloat,   53,  { LLDB_INVALID_REGNUM,  dwarf_s27,          LLDB_INVALID_REGNUM     }},
+        {   "s28",      NULL,   4,  288,  eEncodingIEEE754,  eFormatFloat,   54,  { LLDB_INVALID_REGNUM,  dwarf_s28,          LLDB_INVALID_REGNUM     }},
+        {   "s29",      NULL,   4,  292,  eEncodingIEEE754,  eFormatFloat,   55,  { LLDB_INVALID_REGNUM,  dwarf_s29,          LLDB_INVALID_REGNUM     }},
+        {   "s30",      NULL,   4,  296,  eEncodingIEEE754,  eFormatFloat,   56,  { LLDB_INVALID_REGNUM,  dwarf_s30,          LLDB_INVALID_REGNUM     }},
+        {   "s31",      NULL,   4,  300,  eEncodingIEEE754,  eFormatFloat,   57,  { LLDB_INVALID_REGNUM,  dwarf_s31,          LLDB_INVALID_REGNUM     }},
+        {   "fpscr",    NULL,   4,  304,  eEncodingUint,     eFormatHex,     58,  { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM     }},
+        {   "d16",      NULL,   8,  308,  eEncodingIEEE754,  eFormatFloat,   59,  { LLDB_INVALID_REGNUM,  dwarf_d16,          LLDB_INVALID_REGNUM     }},
+        {   "d17",      NULL,   8,  316,  eEncodingIEEE754,  eFormatFloat,   60,  { LLDB_INVALID_REGNUM,  dwarf_d17,          LLDB_INVALID_REGNUM     }},
+        {   "d18",      NULL,   8,  324,  eEncodingIEEE754,  eFormatFloat,   61,  { LLDB_INVALID_REGNUM,  dwarf_d18,          LLDB_INVALID_REGNUM     }},
+        {   "d19",      NULL,   8,  332,  eEncodingIEEE754,  eFormatFloat,   62,  { LLDB_INVALID_REGNUM,  dwarf_d19,          LLDB_INVALID_REGNUM     }},
+        {   "d20",      NULL,   8,  340,  eEncodingIEEE754,  eFormatFloat,   63,  { LLDB_INVALID_REGNUM,  dwarf_d20,          LLDB_INVALID_REGNUM     }},
+        {   "d21",      NULL,   8,  348,  eEncodingIEEE754,  eFormatFloat,   64,  { LLDB_INVALID_REGNUM,  dwarf_d21,          LLDB_INVALID_REGNUM     }},
+        {   "d22",      NULL,   8,  356,  eEncodingIEEE754,  eFormatFloat,   65,  { LLDB_INVALID_REGNUM,  dwarf_d22,          LLDB_INVALID_REGNUM     }},
+        {   "d23",      NULL,   8,  364,  eEncodingIEEE754,  eFormatFloat,   66,  { LLDB_INVALID_REGNUM,  dwarf_d23,          LLDB_INVALID_REGNUM     }},
+        {   "d24",      NULL,   8,  372,  eEncodingIEEE754,  eFormatFloat,   67,  { LLDB_INVALID_REGNUM,  dwarf_d24,          LLDB_INVALID_REGNUM     }},
+        {   "d25",      NULL,   8,  380,  eEncodingIEEE754,  eFormatFloat,   68,  { LLDB_INVALID_REGNUM,  dwarf_d25,          LLDB_INVALID_REGNUM     }},
+        {   "d26",      NULL,   8,  388,  eEncodingIEEE754,  eFormatFloat,   69,  { LLDB_INVALID_REGNUM,  dwarf_d26,          LLDB_INVALID_REGNUM     }},
+        {   "d27",      NULL,   8,  396,  eEncodingIEEE754,  eFormatFloat,   70,  { LLDB_INVALID_REGNUM,  dwarf_d27,          LLDB_INVALID_REGNUM     }},
+        {   "d28",      NULL,   8,  404,  eEncodingIEEE754,  eFormatFloat,   71,  { LLDB_INVALID_REGNUM,  dwarf_d28,          LLDB_INVALID_REGNUM     }},
+        {   "d29",      NULL,   8,  412,  eEncodingIEEE754,  eFormatFloat,   72,  { LLDB_INVALID_REGNUM,  dwarf_d29,          LLDB_INVALID_REGNUM     }},
+        {   "d30",      NULL,   8,  420,  eEncodingIEEE754,  eFormatFloat,   73,  { LLDB_INVALID_REGNUM,  dwarf_d30,          LLDB_INVALID_REGNUM     }},
+        {   "d31",      NULL,   8,  428,  eEncodingIEEE754,  eFormatFloat,   74,  { LLDB_INVALID_REGNUM,  dwarf_d31,          LLDB_INVALID_REGNUM     }},
+    };
+    static const uint32_t num_registers = sizeof (g_register_infos)/sizeof (lldb::RegisterInfo);
+    static ConstString gpr_reg_set ("General Purpose Registers");
+    static ConstString vfp_reg_set ("Floating Point Registers");
+    for (uint32_t i=0; i<num_registers; ++i)
+    {
+        ConstString name;
+        ConstString alt_name;
+        if (g_register_infos[i].name && g_register_infos[i].name[0])
+            name.SetCString(g_register_infos[i].name);
+        if (g_register_infos[i].alt_name && g_register_infos[i].alt_name[0])
+            alt_name.SetCString(g_register_infos[i].alt_name);
+
+        AddRegister (g_register_infos[i], name, alt_name, i < 26 ? gpr_reg_set : vfp_reg_set);
+    }
+}
+
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
new file mode 100644
index 0000000..67acdef
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -0,0 +1,250 @@
+//===-- GDBRemoteRegisterContext.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_GDBRemoteRegisterContext_h_
+#define lldb_GDBRemoteRegisterContext_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Target/RegisterContext.h"
+
+
+class ThreadGDBRemote;
+class ProcessGDBRemote;
+
+class GDBRemoteDynamicRegisterInfo
+{
+public:
+    GDBRemoteDynamicRegisterInfo () :
+        m_regs (),
+        m_sets (),
+        m_set_reg_nums (),
+        m_reg_names (),
+        m_reg_alt_names (),
+        m_set_names (),
+        m_reg_data_byte_size (0)
+    {
+    }
+
+    ~GDBRemoteDynamicRegisterInfo ()
+    {
+    }
+
+    void
+    AddRegister (lldb::RegisterInfo &reg_info, lldb_private::ConstString &reg_name, lldb_private::ConstString &reg_alt_name, lldb_private::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
+    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
+    GetNumRegisters() const
+    {
+        return m_regs.size();
+    }
+
+    size_t
+    GetNumRegisterSets() const
+    {
+        return m_sets.size();
+    }
+
+    size_t
+    GetRegisterDataByteSize() const
+    {
+        return m_reg_data_byte_size;
+    }
+
+    const lldb::RegisterInfo *
+    GetRegisterInfoAtIndex (uint32_t i) const
+    {
+        if (i < m_regs.size())
+            return &m_regs[i];
+        return NULL;
+    }
+
+    const lldb::RegisterSet *
+    GetRegisterSet (uint32_t i) const
+    {
+        if (i < m_sets.size())
+            return &m_sets[i];
+        return NULL;
+    }
+
+    uint32_t
+    GetRegisterSetIndexByName (lldb_private::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);
+        lldb::RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL };
+        m_sets.push_back (new_set);
+        return m_sets.size() - 1;
+    }
+
+    uint32_t
+    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
+    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();
+    }
+
+    void
+    HardcodeARMRegisters();
+
+protected:
+    //------------------------------------------------------------------
+    // Classes that inherit from GDBRemoteRegisterContext can see and modify these
+    //------------------------------------------------------------------
+    typedef std::vector <lldb::RegisterInfo> reg_collection;
+    typedef std::vector <lldb::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
+};
+
+class GDBRemoteRegisterContext : public lldb_private::RegisterContext
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    GDBRemoteRegisterContext (ThreadGDBRemote &thread,
+                              lldb_private::StackFrame *frame,
+                              GDBRemoteDynamicRegisterInfo &reg_info,
+                              bool read_all_at_once);
+
+    virtual
+    ~GDBRemoteRegisterContext ();
+
+    //------------------------------------------------------------------
+    // Subclasses must override these functions
+    //------------------------------------------------------------------
+    virtual void
+    Invalidate ();
+
+    virtual size_t
+    GetRegisterCount ();
+
+    virtual const lldb::RegisterInfo *
+    GetRegisterInfoAtIndex (uint32_t reg);
+
+    virtual size_t
+    GetRegisterSetCount ();
+
+    virtual const lldb::RegisterSet *
+    GetRegisterSet (uint32_t reg_set);
+
+    virtual bool
+    ReadRegisterValue (uint32_t reg, lldb_private::Scalar &value);
+
+    virtual bool
+    ReadRegisterBytes (uint32_t reg, lldb_private::DataExtractor &data);
+
+    virtual bool
+    ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+
+    virtual bool
+    WriteRegisterValue (uint32_t reg, const lldb_private::Scalar &value);
+
+    virtual bool
+    WriteRegisterBytes (uint32_t reg, lldb_private::DataExtractor &data, uint32_t data_offset);
+
+    virtual bool
+    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+
+    virtual uint32_t
+    ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+
+protected:
+
+    void
+    SetAllRegisterValid (bool b);
+
+    ProcessGDBRemote &
+    GetGDBProcess();
+
+    ThreadGDBRemote &
+    GetGDBThread();
+
+    GDBRemoteDynamicRegisterInfo &m_reg_info;
+    std::vector<bool> m_reg_valid;
+    uint32_t m_reg_valid_stop_id;
+    lldb_private::DataExtractor m_reg_data;
+    bool m_read_all_at_once;
+
+private:
+    //------------------------------------------------------------------
+    // For GDBRemoteRegisterContext only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (GDBRemoteRegisterContext);
+};
+
+#endif  // lldb_GDBRemoteRegisterContext_h_
diff --git a/source/Plugins/Process/gdb-remote/GDBServer.cpp b/source/Plugins/Process/gdb-remote/GDBServer.cpp
new file mode 100644
index 0000000..a88ec7b
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/GDBServer.cpp
@@ -0,0 +1,1148 @@
+//===-- GDBServer.cpp -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <getopt.h>
+#include <netinet/in.h>
+#include <sys/select.h>
+#include <sys/sysctl.h>
+#include <string>
+#include <vector>
+#include <asl.h>
+
+#include "GDBServerLog.h"
+#include "GDBRemoteSession.h"
+
+using namespace lldb;
+
+//----------------------------------------------------------------------
+// Run loop modes which determine which run loop function will be called
+//----------------------------------------------------------------------
+typedef enum
+{
+    eDCGSRunLoopModeInvalid = 0,
+    eDCGSRunLoopModeGetStartModeFromRemoteProtocol,
+    eDCGSRunLoopModeInferiorAttaching,
+    eDCGSRunLoopModeInferiorLaunching,
+    eDCGSRunLoopModeInferiorExecuting,
+    eDCGSRunLoopModeInferiorKillOrDetach,
+    eDCGSRunLoopModeExit
+} GSRunLoopMode;
+
+typedef enum
+{
+    eLaunchFlavorDefault = 0,
+    eLaunchFlavorPosixSpawn,
+#if defined (__arm__)
+    eLaunchFlavorSpringBoard,
+#endif
+    eLaunchFlavorForkExec,
+} GSLaunchFlavor;
+
+typedef lldb::shared_ptr<GDBRemoteSession> GDBRemoteSP;
+
+typedef struct HandleBroadcastEventInfo
+{
+    TargetSP target_sp;
+    GDBRemoteSP remote_sp;
+    GSRunLoopMode mode;
+
+    Target *
+    GetTarget ()
+    {
+        return target_sp.get();
+    }
+
+    Process *
+    GetProcess()
+    {
+        if (target_sp.get())
+            return target_sp->GetProcess().get();
+        return NULL;
+    }
+
+    GDBRemoteSession *
+    GetRemote ()
+    {
+        return remote_sp.get();
+    }
+
+};
+
+
+//----------------------------------------------------------------------
+// Global Variables
+//----------------------------------------------------------------------
+static int g_lockdown_opt  = 0;
+static int g_applist_opt = 0;
+static GSLaunchFlavor g_launch_flavor = eLaunchFlavorDefault;
+int g_isatty = 0;
+
+//----------------------------------------------------------------------
+// Run Loop function prototypes
+//----------------------------------------------------------------------
+void GSRunLoopGetStartModeFromRemote (HandleBroadcastEventInfo *info);
+void GSRunLoopInferiorExecuting (HandleBroadcastEventInfo *info);
+
+
+//----------------------------------------------------------------------
+// Get our program path and arguments from the remote connection.
+// We will need to start up the remote connection without a PID, get the
+// arguments, wait for the new process to finish launching and hit its
+// entry point,  and then return the run loop mode that should come next.
+//----------------------------------------------------------------------
+void
+GSRunLoopGetStartModeFromRemote (HandleBroadcastEventInfo *info)
+{
+    std::string packet;
+
+    Target *target = info->GetTarget();
+    GDBRemoteSession *remote = info->GetRemote();
+    if (target != NULL && remote != NULL)
+    {
+        // Spin waiting to get the A packet.
+        while (1)
+        {
+            gdb_err_t err = gdb_err;
+            GDBRemoteSession::PacketEnum type;
+
+            err = remote->HandleReceivedPacket (&type);
+
+            // check if we tried to attach to a process
+            if (type == GDBRemoteSession::vattach || type == GDBRemoteSession::vattachwait)
+            {
+                if (err == gdb_success)
+                {
+                    info->mode = eDCGSRunLoopModeInferiorExecuting;
+                    return;
+                }
+                else
+                {
+                    Log::STDERR ("error: attach failed.");
+                    info->mode = eDCGSRunLoopModeExit;
+                    return;
+                }
+            }
+
+            if (err == gdb_success)
+            {
+                // If we got our arguments we are ready to launch using the arguments
+                // and any environment variables we received.
+                if (type == GDBRemoteSession::set_argv)
+                {
+                    info->mode = eDCGSRunLoopModeInferiorLaunching;
+                    return;
+                }
+            }
+            else if (err == gdb_not_connected)
+            {
+                Log::STDERR ("error: connection lost.");
+                info->mode = eDCGSRunLoopModeExit;
+                return;
+            }
+            else
+            {
+                // a catch all for any other gdb remote packets that failed
+                GDBServerLog::LogIf (GS_LOG_MINIMAL, "%s Error getting packet.",__FUNCTION__);
+                continue;
+            }
+
+            GDBServerLog::LogIf (GS_LOG_MINIMAL, "#### %s", __FUNCTION__);
+        }
+    }
+    info->mode = eDCGSRunLoopModeExit;
+}
+
+
+//----------------------------------------------------------------------
+// This run loop mode will wait for the process to launch and hit its
+// entry point. It will currently ignore all events except for the
+// process state changed event, where it watches for the process stopped
+// or crash process state.
+//----------------------------------------------------------------------
+GSRunLoopMode
+GSRunLoopLaunchInferior (HandleBroadcastEventInfo *info)
+{
+    // The Process stuff takes a c array, the GSContext has a vector...
+    // So make up a c array.
+    Target *target = info->GetTarget();
+    GDBRemoteSession *remote = info->GetRemote();
+    Process* process = info->GetProcess();
+
+    if (process == NULL)
+        return eDCGSRunLoopModeExit;
+
+    GDBServerLog::LogIf (GS_LOG_MINIMAL, "%s Launching '%s'...", __FUNCTION__, target->GetExecutableModule()->GetFileSpec().GetFilename().AsCString());
+
+    // Our launch type hasn't been set to anything concrete, so we need to
+    // figure our how we are going to launch automatically.
+
+    GSLaunchFlavor launch_flavor = g_launch_flavor;
+    if (launch_flavor == eLaunchFlavorDefault)
+    {
+        // Our default launch method is posix spawn
+        launch_flavor = eLaunchFlavorPosixSpawn;
+
+#if defined (__arm__)
+        // Check if we have an app bundle, if so launch using SpringBoard.
+        if (strstr(inferior_argv[0], ".app"))
+        {
+            launch_flavor = eLaunchFlavorSpringBoard;
+        }
+#endif
+    }
+
+    //ctx.SetLaunchFlavor(launch_flavor);
+
+    const char *stdio_file = NULL;
+    lldb::pid_t pid = process->Launch (remote->GetARGV(), remote->GetENVP(), stdio_file, stdio_file, stdio_file);
+
+    if (pid == LLDB_INVALID_PROCESS_ID)
+    {
+        Log::STDERR ("error: process launch failed: %s", process->GetError().AsCString());
+    }
+    else
+    {
+        if (remote->IsConnected())
+        {
+            // It we are connected already, the next thing gdb will do is ask
+            // whether the launch succeeded, and if not, whether there is an
+            // error code.  So we need to fetch one packet from gdb before we wait
+            // on the stop from the target.
+            gdb_err_t err = gdb_err;
+            GDBRemoteSession::PacketEnum type;
+
+            err = remote->HandleReceivedPacket (&type);
+
+            if (err != gdb_success)
+            {
+                GDBServerLog::LogIf (GS_LOG_MINIMAL, "%s Error getting packet.", __FUNCTION__);
+                return eDCGSRunLoopModeExit;
+            }
+            if (type != GDBRemoteSession::query_launch_success)
+            {
+                GDBServerLog::LogIf (GS_LOG_MINIMAL, "%s Didn't get the expected qLaunchSuccess packet.", __FUNCTION__);
+            }
+        }
+    }
+
+    Listener listener("GSRunLoopLaunchInferior");
+    listener.StartListeningForEvents (process, Process::eBroadcastBitStateChanged);
+    while (process->GetID() != LLDB_INVALID_PROCESS_ID)
+    {
+        uint32_t event_mask = 0;
+        while (listener.WaitForEvent(NULL, &event_mask))
+        {
+            if (event_mask & Process::eBroadcastBitStateChanged)
+            {
+                Event event;
+                StateType event_state;
+                while ((event_state = process->GetNextEvent (&event)))
+                if (StateIsStoppedState(event_state))
+                {
+                    GDBServerLog::LogIf (GS_LOG_EVENTS, "%s process %4.4x stopped with state %s", __FUNCTION__, pid, StateAsCString(event_state));
+
+                    switch (event_state)
+                    {
+                    default:
+                    case eStateInvalid:
+                    case eStateUnloaded:
+                    case eStateAttaching:
+                    case eStateLaunching:
+                    case eStateSuspended:
+                        break;  // Ignore
+
+                    case eStateRunning:
+                    case eStateStepping:
+                        // Still waiting to stop at entry point...
+                        break;
+
+                    case eStateStopped:
+                    case eStateCrashed:
+                        return eDCGSRunLoopModeInferiorExecuting;
+
+                    case eStateDetached:
+                    case eStateExited:
+                        pid = LLDB_INVALID_PROCESS_ID;
+                        return eDCGSRunLoopModeExit;
+                    }
+                }
+
+                if (event_state = eStateInvalid)
+                    break;
+            }
+        }
+    }
+
+    return eDCGSRunLoopModeExit;
+}
+
+
+//----------------------------------------------------------------------
+// This run loop mode will wait for the process to launch and hit its
+// entry point. It will currently ignore all events except for the
+// process state changed event, where it watches for the process stopped
+// or crash process state.
+//----------------------------------------------------------------------
+GSRunLoopMode
+GSRunLoopLaunchAttaching (HandleBroadcastEventInfo *info, lldb::pid_t& pid)
+{
+    Process* process = info->GetProcess();
+
+    GDBServerLog::LogIf (GS_LOG_MINIMAL, "%s Attaching to pid %i...", __FUNCTION__, pid);
+    pid = process->Attach(pid);
+
+    if (pid == LLDB_INVALID_PROCESS_ID)
+        return eDCGSRunLoopModeExit;
+    return eDCGSRunLoopModeInferiorExecuting;
+}
+
+//----------------------------------------------------------------------
+// Watch for signals:
+// SIGINT: so we can halt our inferior. (disabled for now)
+// SIGPIPE: in case our child process dies
+//----------------------------------------------------------------------
+lldb::pid_t g_pid;
+int g_sigpipe_received = 0;
+void
+signal_handler(int signo)
+{
+    GDBServerLog::LogIf (GS_LOG_MINIMAL, "%s (%s)", __FUNCTION__, Host::GetSignalAsCString(signo));
+
+    switch (signo)
+    {
+//  case SIGINT:
+//      DNBProcessKill (g_pid, signo);
+//      break;
+
+    case SIGPIPE:
+        g_sigpipe_received = 1;
+        break;
+    }
+}
+
+// Return the new run loop mode based off of the current process state
+void
+HandleProcessStateChange (HandleBroadcastEventInfo *info, bool initialize)
+{
+    Process *process = info->GetProcess();
+    if (process == NULL)
+    {
+        info->mode = eDCGSRunLoopModeExit;
+        return;
+    }
+
+    if (process->GetID() == LLDB_INVALID_PROCESS_ID)
+    {
+        GDBServerLog::LogIf (GS_LOG_MINIMAL, "#### %s error: pid invalid, exiting...", __FUNCTION__);
+        info->mode = eDCGSRunLoopModeExit;
+        return;
+    }
+    StateType pid_state = process->GetState ();
+
+    GDBServerLog::LogIf (GS_LOG_MINIMAL, "%s (info, initialize=%i)  pid_state = %s", __FUNCTION__, (int)initialize, StateAsCString(pid_state));
+
+    switch (pid_state)
+    {
+    case eStateInvalid:
+    case eStateUnloaded:
+        // Something bad happened
+        info->mode = eDCGSRunLoopModeExit;
+        return;
+
+    case eStateAttaching:
+    case eStateLaunching:
+        info->mode = eDCGSRunLoopModeInferiorExecuting;
+        return;
+
+    case eStateSuspended:
+    case eStateCrashed:
+    case eStateStopped:
+        if (initialize == false)
+        {
+            // Compare the last stop count to our current notion of a stop count
+            // to make sure we don't notify more than once for a given stop.
+            static uint32_t g_prev_stop_id = 0;
+            uint32_t stop_id = process->GetStopID();
+            bool pid_stop_count_changed = g_prev_stop_id != stop_id;
+            if (pid_stop_count_changed)
+            {
+                info->GetRemote()->FlushSTDIO();
+
+                if (stop_id == 1)
+                {
+                    GDBServerLog::LogIf (GS_LOG_MINIMAL, "%s (&remote, initialize=%i)  pid_state = %s pid_stop_count %u (old %u)) Notify??? no, first stop...", __FUNCTION__, (int)initialize, StateAsCString (pid_state), stop_id, g_prev_stop_id);
+                }
+                else
+                {
+
+                    GDBServerLog::LogIf (GS_LOG_MINIMAL, "%s (&remote, initialize=%i)  pid_state = %s pid_stop_count %u (old %u)) Notify??? YES!!!", __FUNCTION__, (int)initialize, StateAsCString (pid_state), stop_id, g_prev_stop_id);
+                    info->GetRemote()->NotifyThatProcessStopped ();
+                }
+            }
+            else
+            {
+                GDBServerLog::LogIf (GS_LOG_MINIMAL, "%s (&remote, initialize=%i)  pid_state = %s pid_stop_count %u (old %u)) Notify??? skipping...", __FUNCTION__, (int)initialize, StateAsCString (pid_state), stop_id, g_prev_stop_id);
+            }
+        }
+        info->mode = eDCGSRunLoopModeInferiorExecuting;
+        return;
+
+    case eStateStepping:
+    case eStateRunning:
+        info->mode = eDCGSRunLoopModeInferiorExecuting;
+        return;
+
+    case eStateExited:
+        info->GetRemote()->HandlePacket_last_signal (NULL);
+        info->mode = eDCGSRunLoopModeExit;
+        return;
+
+    }
+
+    // Catch all...
+    info->mode = eDCGSRunLoopModeExit;
+}
+
+bool
+CommunicationHandleBroadcastEvent (Broadcaster *broadcaster, uint32_t event_mask, void *baton)
+{
+    HandleBroadcastEventInfo *info = (HandleBroadcastEventInfo *)baton;
+    Process *process = info->GetProcess();
+
+    if (process == NULL)
+    {
+        info->mode = eDCGSRunLoopModeExit;
+        return true;
+    }
+
+    if (event_mask & Communication::eBroadcastBitPacketAvailable)
+    {
+        if (process->IsRunning())
+        {
+            if (info->GetRemote()->HandleAsyncPacket() == gdb_not_connected)
+                info->mode = eDCGSRunLoopModeExit;
+        }
+        else
+        {
+            if (info->GetRemote()->HandleReceivedPacket() == gdb_not_connected)
+                info->mode = eDCGSRunLoopModeExit;
+        }
+    }
+    if (event_mask & Communication::eBroadcastBitReadThreadDidExit)
+    {
+        info->mode = eDCGSRunLoopModeExit;
+    }
+    if (event_mask & Communication::eBroadcastBitDisconnected)
+    {
+        info->mode = eDCGSRunLoopModeExit;
+    }
+
+    return true;
+
+}
+
+bool
+ProcessHandleBroadcastEvent (Broadcaster *broadcaster, uint32_t event_mask, void *baton)
+{
+    HandleBroadcastEventInfo *info = (HandleBroadcastEventInfo *)baton;
+    Process *process = info->GetProcess();
+    if (process == NULL)
+    {
+        info->mode = eDCGSRunLoopModeExit;
+        return true;
+    }
+
+    if (event_mask & Process::eBroadcastBitStateChanged)
+    {
+        // Consume all available process events with no timeout
+        Event event;
+        StateType process_state;
+        while ((process_state = process->GetNextEvent (&event)) != eStateInvalid)
+        {
+            if (StateIsStoppedState(process_state))
+                info->GetRemote()->FlushSTDIO();
+            HandleProcessStateChange (info, false);
+
+            if (info->mode != eDCGSRunLoopModeInferiorExecuting)
+                break;
+        }
+    }
+    else
+    if (event_mask & (Process::eBroadcastBitSTDOUT | Process::eBroadcastBitSTDERR))
+    {
+        info->GetRemote()->FlushSTDIO();
+    }
+    return true;
+}
+
+// This function handles the case where our inferior program is stopped and
+// we are waiting for gdb remote protocol packets. When a packet occurs that
+// makes the inferior run, we need to leave this function with a new state
+// as the return code.
+void
+GSRunLoopInferiorExecuting (HandleBroadcastEventInfo *info)
+{
+    GDBServerLog::LogIf (GS_LOG_MINIMAL, "#### %s", __FUNCTION__);
+
+    // Init our mode and set 'is_running' based on the current process state
+    HandleProcessStateChange (info, true);
+
+    uint32_t desired_mask, acquired_mask;
+    Listener listener("GSRunLoopInferiorExecuting");
+
+    desired_mask =  Communication::eBroadcastBitPacketAvailable |
+                    Communication::eBroadcastBitReadThreadDidExit  |
+                    Communication::eBroadcastBitDisconnected;
+
+    acquired_mask = listener.StartListeningForEvents (&(info->GetRemote()->GetPacketComm()),
+                                      desired_mask,
+                                      CommunicationHandleBroadcastEvent,
+                                      info);
+
+    assert (acquired_mask == desired_mask);
+    desired_mask = GDBRemotePacket::eBroadcastBitPacketAvailable;
+
+    acquired_mask = listener.StartListeningForEvents (&(info->GetRemote()->GetPacketComm()),
+                                            desired_mask,
+                                            CommunicationHandleBroadcastEvent,
+                                            info);
+
+    assert (acquired_mask == desired_mask);
+
+    desired_mask =  Process::eBroadcastBitStateChanged |
+                    Process::eBroadcastBitSTDOUT |
+                    Process::eBroadcastBitSTDERR ;
+    acquired_mask = listener.StartListeningForEvents (info->GetProcess (),
+                                      desired_mask,
+                                      ProcessHandleBroadcastEvent,
+                                      info);
+
+    assert (acquired_mask == desired_mask);
+
+    Process *process = info->GetProcess();
+
+    while (process->IsAlive())
+    {
+        if (!info->GetRemote()->IsConnected())
+        {
+            info->mode = eDCGSRunLoopModeInferiorKillOrDetach;
+            break;
+        }
+
+        // We want to make sure we consume all process state changes and have
+        // whomever is notifying us to wait for us to reset the event bit before
+        // continuing.
+        //ctx.Events().SetResetAckMask (GSContext::event_proc_state_changed);
+        uint32_t event_mask = 0;
+        Broadcaster *broadcaster = listener.WaitForEvent(NULL, &event_mask);
+        if (broadcaster)
+        {
+            listener.HandleBroadcastEvent(broadcaster, event_mask);
+        }
+    }
+}
+
+
+//----------------------------------------------------------------------
+// Convenience function to set up the remote listening port
+// Returns 1 for success 0 for failure.
+//----------------------------------------------------------------------
+
+static bool
+StartListening (HandleBroadcastEventInfo *info, int listen_port)
+{
+    if (!info->GetRemote()->IsConnected())
+    {
+        Log::STDOUT ("Listening to port %i...\n", listen_port);
+        char connect_url[256];
+        snprintf(connect_url, sizeof(connect_url), "listen://%i", listen_port);
+
+        Communication &comm = info->remote_sp->GetPacketComm();
+        comm.SetConnection (new ConnectionFileDescriptor);
+
+        if (comm.Connect (connect_url))
+        {
+            if (comm.StartReadThread())
+                return true;
+
+            Log::STDERR ("Failed to start the communication read thread.\n", connect_url);
+            comm.Disconnect();
+        }
+        else
+        {
+            Log::STDERR ("Failed to connection to %s.\n", connect_url);
+        }
+        return false;
+    }
+    return true;
+}
+
+//----------------------------------------------------------------------
+// ASL Logging callback that can be registered with DNBLogSetLogDCScriptInterpreter::Type
+//----------------------------------------------------------------------
+//void
+//ASLLogDCScriptInterpreter::Type(void *baton, uint32_t flags, const char *format, va_list args)
+//{
+//    if (format == NULL)
+//      return;
+//    static aslmsg g_aslmsg = NULL;
+//    if (g_aslmsg == NULL)
+//    {
+//        g_aslmsg = ::asl_new (ASL_TYPE_MSG);
+//        char asl_key_sender[PATH_MAX];
+//        snprintf(asl_key_sender, sizeof(asl_key_sender), "com.apple.dc-gdbserver-%g", dc_gdbserverVersionNumber);
+//        ::asl_set (g_aslmsg, ASL_KEY_SENDER, asl_key_sender);
+//    }
+//
+//    int asl_level;
+//    if (flags & DNBLOG_FLAG_FATAL)        asl_level = ASL_LEVEL_CRIT;
+//    else if (flags & DNBLOG_FLAG_ERROR)   asl_level = ASL_LEVEL_ERR;
+//    else if (flags & DNBLOG_FLAG_WARNING) asl_level = ASL_LEVEL_WARNING;
+//    else if (flags & DNBLOG_FLAG_VERBOSE) asl_level = ASL_LEVEL_WARNING; //ASL_LEVEL_INFO;
+//    else                                  asl_level = ASL_LEVEL_WARNING; //ASL_LEVEL_DEBUG;
+//
+//    ::asl_vlog (NULL, g_aslmsg, asl_level, format, args);
+//}
+
+//----------------------------------------------------------------------
+// FILE based Logging callback that can be registered with
+// DNBLogSetLogDCScriptInterpreter::Type
+//----------------------------------------------------------------------
+void
+FileLogDCScriptInterpreter::Type(void *baton, uint32_t flags, const char *format, va_list args)
+{
+    if (baton == NULL || format == NULL)
+      return;
+
+    ::vfprintf ((FILE *)baton, format, args);
+    ::fprintf ((FILE *)baton, "\n");
+}
+
+//----------------------------------------------------------------------
+// option descriptors for getopt_long()
+//----------------------------------------------------------------------
+static struct option g_long_options[] =
+{
+    { "arch",       required_argument,  NULL,               'c' },
+    { "attach",     required_argument,  NULL,               'a' },
+    { "debug",      no_argument,        NULL,               'g' },
+    { "verbose",    no_argument,        NULL,               'v' },
+    { "lockdown",   no_argument,        &g_lockdown_opt,    1   },  // short option "-k"
+    { "applist",    no_argument,        &g_applist_opt,     1   },  // short option "-t"
+    { "log-file",   required_argument,  NULL,               'l' },
+    { "log-flags",  required_argument,  NULL,               'f' },
+    { "launch",     required_argument,  NULL,               'x' },  // Valid values are "auto", "posix-spawn", "fork-exec", "springboard" (arm only)
+    { "waitfor",    required_argument,  NULL,               'w' },  // Wait for a process whose namet starts with ARG
+    { "waitfor-interval", required_argument,    NULL,       'i' },  // Time in usecs to wait between sampling the pid list when waiting for a process by name
+    { "waitfor-duration", required_argument,    NULL,       'd' },  // The time in seconds to wait for a process to show up by name
+    { NULL,         0,                  NULL,               0   }
+};
+
+extern const double dc_gdbserverVersionNumber;
+int
+main (int argc, char *argv[])
+{
+    Initialize();
+    Host::ThreadCreated ("[main]");
+
+    g_isatty = ::isatty (STDIN_FILENO);
+
+//  signal (SIGINT, signal_handler);
+    signal (SIGPIPE, signal_handler);
+
+    Log *log = GDBServerLog::GetLogIfAllCategoriesSet(GS_LOG_ALL);
+    const char *this_exe_name = argv[0];
+    int i;
+    int attach_pid = LLDB_INVALID_PROCESS_ID;
+    for (i=0; i<argc; i++)
+        GDBServerLog::LogIf(GS_LOG_DEBUG, "argv[%i] = %s", i, argv[i]);
+
+    FILE* log_file = NULL;
+    uint32_t log_flags = 0;
+    // Parse our options
+    int ch;
+    int long_option_index = 0;
+    int debug = 0;
+    std::string waitfor_pid_name;           // Wait for a process that starts with this name
+    std::string attach_pid_name;
+    useconds_t waitfor_interval = 1000;     // Time in usecs between process lists polls when waiting for a process by name, default 1 msec.
+    useconds_t waitfor_duration = 0;        // Time in seconds to wait for a process by name, 0 means wait forever.
+    ArchSpec arch;
+    GSRunLoopMode start_mode = eDCGSRunLoopModeExit;
+
+    while ((ch = getopt_long(argc, argv, "a:c:d:gi:vktl:f:w:x:", g_long_options, &long_option_index)) != -1)
+    {
+//      DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n",
+//                    ch, (uint8_t)ch,
+//                    g_long_options[long_option_index].name,
+//                    g_long_options[long_option_index].has_arg ? '=' : ' ',
+//                    optarg ? optarg : "");
+        switch (ch)
+        {
+        case 0:   // Any optional that auto set themselves will return 0
+            break;
+
+        case 'c':
+            arch.SetArch(optarg);
+            if (!arch.IsValid())
+            {
+                Log::STDERR ("error: invalid arch string '%s'\n", optarg);
+                exit (8);
+            }
+            break;
+
+        case 'a':
+            if (optarg && optarg[0])
+            {
+                if (isdigit(optarg[0]))
+                {
+                    char *end = NULL;
+                    attach_pid = strtoul(optarg, &end, 0);
+                    if (end == NULL || *end != '\0')
+                    {
+                        Log::STDERR ("error: invalid pid option '%s'\n", optarg);
+                        exit (4);
+                    }
+                }
+                else
+                {
+                    attach_pid_name = optarg;
+                }
+                start_mode = eDCGSRunLoopModeInferiorAttaching;
+            }
+            break;
+
+        // --waitfor=NAME
+        case 'w':
+            if (optarg && optarg[0])
+            {
+                waitfor_pid_name = optarg;
+                start_mode = eDCGSRunLoopModeInferiorAttaching;
+            }
+            break;
+
+        // --waitfor-interval=USEC
+        case 'i':
+            if (optarg && optarg[0])
+            {
+                char *end = NULL;
+                waitfor_interval = strtoul(optarg, &end, 0);
+                if (end == NULL || *end != '\0')
+                {
+                    Log::STDERR ("error: invalid waitfor-interval option value '%s'.\n", optarg);
+                    exit (6);
+                }
+            }
+            break;
+
+        // --waitfor-duration=SEC
+        case 'd':
+            if (optarg && optarg[0])
+            {
+                char *end = NULL;
+                waitfor_duration = strtoul(optarg, &end, 0);
+                if (end == NULL || *end != '\0')
+                {
+                    Log::STDERR ("error: invalid waitfor-duration option value '%s'.\n", optarg);
+                    exit (7);
+                }
+            }
+            break;
+
+        case 'x':
+            if (optarg && optarg[0])
+            {
+                if (strcasecmp(optarg, "auto") == 0)
+                    g_launch_flavor = eLaunchFlavorDefault;
+                else if (strcasestr(optarg, "posix") == optarg)
+                    g_launch_flavor = eLaunchFlavorPosixSpawn;
+                else if (strcasestr(optarg, "fork") == optarg)
+                    g_launch_flavor = eLaunchFlavorForkExec;
+#if defined (__arm__)
+                else if (strcasestr(optarg, "spring") == optarg)
+                    g_launch_flavor = eLaunchFlavorSpringBoard;
+#endif
+                else
+                {
+                    Log::STDERR ("error: invalid TYPE for the --launch=TYPE (-x TYPE) option: '%s'\n", optarg);
+                    Log::STDERR ("Valid values TYPE are:\n");
+                    Log::STDERR ("  auto    Auto-detect the best launch method to use.\n");
+                    Log::STDERR ("  posix   Launch the executable using posix_spawn.\n");
+                    Log::STDERR ("  fork    Launch the executable using fork and exec.\n");
+#if defined (__arm__)
+                    Log::STDERR ("  spring  Launch the executable through Springboard.\n");
+#endif
+                    exit (5);
+                }
+            }
+            break;
+
+        case 'l': // Set Log File
+            if (optarg && optarg[0])
+            {
+                if (strcasecmp(optarg, "stdout") == 0)
+                    log_file = stdout;
+                else if (strcasecmp(optarg, "stderr") == 0)
+                    log_file = stderr;
+                else
+                    log_file = fopen(optarg, "w+");
+
+                if (log_file == NULL)
+                {
+                    const char *errno_str = strerror(errno);
+                    Log::STDERR ("Failed to open log file '%s' for writing: errno = %i (%s)", optarg, errno, errno_str ? errno_str : "unknown error");
+                }
+            }
+            break;
+
+        case 'f': // Log Flags
+            if (optarg && optarg[0])
+                log_flags = strtoul(optarg, NULL, 0);
+            break;
+
+        case 'g':
+            debug = 1;
+            //DNBLogSetDebug(1);
+            break;
+
+        case 't':
+            g_applist_opt = 1;
+            break;
+
+        case 'k':
+            g_lockdown_opt = 1;
+            break;
+
+        case 'v':
+            //DNBLogSetVerbose(1);
+            break;
+        }
+    }
+
+    // Skip any options we consumed with getopt_long
+    argc -= optind;
+    argv += optind;
+
+    // It is ok for us to set NULL as the logfile (this will disable any logging)
+
+//    if (log_file != NULL)
+//    {
+//        DNBLogSetLogDCScriptInterpreter::Type(FileLogDCScriptInterpreter::Type, log_file);
+//        // If our log file was set, yet we have no log flags, log everything!
+//        if (log_flags == 0)
+//            log_flags = LOG_ALL | LOG_DCGS_ALL;
+//
+//        DNBLogSetLogMask (log_flags);
+//    }
+//    else
+//    {
+//        // Enable DNB logging
+//        DNBLogSetLogDCScriptInterpreter::Type(ASLLogDCScriptInterpreter::Type, NULL);
+//        DNBLogSetLogMask (log_flags);
+//
+//    }
+
+    // as long as we're dropping remotenub in as a replacement for gdbserver,
+    // explicitly note that this is not gdbserver.
+
+    Log::STDOUT ("debugserver-%g \n", dc_gdbserverVersionNumber);
+    int listen_port = -1;
+    if (g_lockdown_opt == 0 && g_applist_opt == 0)
+    {
+        // Make sure we at least have port
+        if (argc < 1)
+        {
+            Log::STDERR ("Usage: %s host:port [program-name program-arg1 program-arg2 ...]\n", this_exe_name);
+            exit (1);
+        }
+        // accept 'localhost:' prefix on port number
+
+        std::string host_str;
+        std::string port_str(argv[0]);
+
+        // We just used the host:port arg...
+        argc--;
+        argv++;
+
+        size_t port_idx = port_str.find(':');
+        if (port_idx != std::string::npos)
+        {
+            host_str.assign(port_str, 0, port_idx);
+            port_str.erase(0, port_idx + 1);
+        }
+
+        if (port_str.empty())
+        {
+            Log::STDERR ("error: no port specified\nUsage: %s host:port [program-name program-arg1 program-arg2 ...]\n", this_exe_name);
+            exit (2);
+        }
+        else if (port_str.find_first_not_of("0123456789") != std::string::npos)
+        {
+            Log::STDERR ("error: port must be an integer: %s\nUsage: %s host:port [program-name program-arg1 program-arg2 ...]\n", port_str.c_str(), this_exe_name);
+            exit (3);
+        }
+        //DNBLogDebug("host_str = '%s'  port_str = '%s'", host_str.c_str(), port_str.c_str());
+        listen_port = atoi (port_str.c_str());
+    }
+
+
+    // We must set up some communications now.
+
+    FileSpec exe_spec;
+    if (argv[0])
+        exe_spec.SetFile (argv[0]);
+
+    HandleBroadcastEventInfo info;
+    info.target_sp = TargetList::SharedList().CreateTarget(&exe_spec, &arch);
+    ProcessSP process_sp (info.target_sp->CreateProcess ());
+    info.remote_sp.reset (new GDBRemoteSession (process_sp));
+
+    info.remote_sp->SetLog (log);
+    StreamString sstr;
+    sstr.Printf("ConnectionFileDescriptor(%s)", argv[0]);
+
+    if (info.remote_sp.get() == NULL)
+    {
+        Log::STDERR ("error: failed to create a GDBRemoteSession class\n");
+        return -1;
+    }
+
+
+
+    //  If we know we're waiting to attach, we don't need any of this other info.
+    if (start_mode != eDCGSRunLoopModeInferiorAttaching)
+    {
+        if (argc == 0 || g_lockdown_opt)
+        {
+            if (g_lockdown_opt != 0)
+            {
+                // Work around for SIGPIPE crashes due to posix_spawn issue. We have to close
+                // STDOUT and STDERR, else the first time we try and do any, we get SIGPIPE and
+                // die as posix_spawn is doing bad things with our file descriptors at the moment.
+                int null = open("/dev/null", O_RDWR);
+                dup2(null, STDOUT_FILENO);
+                dup2(null, STDERR_FILENO);
+            }
+            else if (g_applist_opt != 0)
+            {
+//                // List all applications we are able to see
+//                std::string applist_plist;
+//                int err = ListApplications(applist_plist, false, false);
+//                if (err == 0)
+//                {
+//                    fputs (applist_plist.c_str(), stdout);
+//                }
+//                else
+//                {
+//                    Log::STDERR ("error: ListApplications returned error %i\n", err);
+//                }
+//                // Exit with appropriate error if we were asked to list the applications
+//                // with no other args were given (and we weren't trying to do this over
+//                // lockdown)
+//                return err;
+                return 0;
+            }
+
+            //DNBLogDebug("Get args from remote protocol...");
+            start_mode = eDCGSRunLoopModeGetStartModeFromRemoteProtocol;
+        }
+        else
+        {
+            start_mode = eDCGSRunLoopModeInferiorLaunching;
+            // Fill in the argv array in the context from the rest of our args.
+            // Skip the name of this executable and the port number
+            info.remote_sp->SetArguments (argc, argv);
+        }
+    }
+
+    if (start_mode == eDCGSRunLoopModeExit)
+      return -1;
+
+    info.mode = start_mode;
+
+    while (info.mode != eDCGSRunLoopModeExit)
+    {
+        switch (info.mode)
+        {
+        case eDCGSRunLoopModeGetStartModeFromRemoteProtocol:
+ #if defined (__arm__)
+            if (g_lockdown_opt)
+            {
+                if (!info.remote_sp->GetCommunication()->IsConnected())
+                {
+                    if (info.remote_sp->GetCommunication()->ConnectToService () != gdb_success)
+                    {
+                        Log::STDERR ("Failed to get connection from a remote gdb process.\n");
+                        info.mode = eDCGSRunLoopModeExit;
+                    }
+                    else if (g_applist_opt != 0)
+                    {
+                        // List all applications we are able to see
+                        std::string applist_plist;
+                        if (ListApplications(applist_plist, false, false) == 0)
+                        {
+                            //DNBLogDebug("Task list: %s", applist_plist.c_str());
+
+                            info.remote_sp->GetCommunication()->Write(applist_plist.c_str(), applist_plist.size());
+                            // Issue a read that will never yield any data until the other side
+                            // closes the socket so this process doesn't just exit and cause the
+                            // socket to close prematurely on the other end and cause data loss.
+                            std::string buf;
+                            info.remote_sp->GetCommunication()->Read(buf);
+                        }
+                        info.remote_sp->GetCommunication()->Disconnect(false);
+                        info.mode = eDCGSRunLoopModeExit;
+                        break;
+                    }
+                    else
+                    {
+                        // Start watching for remote packets
+                        info.remote_sp->StartReadRemoteDataThread();
+                    }
+                }
+            }
+            else
+#endif
+            {
+                if (StartListening (&info, listen_port))
+                    Log::STDOUT ("Got a connection, waiting for process information for launching or attaching.\n");
+                else
+                    info.mode = eDCGSRunLoopModeExit;
+            }
+
+            if (info.mode != eDCGSRunLoopModeExit)
+                GSRunLoopGetStartModeFromRemote (&info);
+            break;
+
+        case eDCGSRunLoopModeInferiorAttaching:
+            if (!waitfor_pid_name.empty())
+            {
+                // Set our end wait time if we are using a waitfor-duration
+                // option that may have been specified
+
+                TimeValue attach_timeout_abstime;
+                if (waitfor_duration != 0)
+                {
+                    attach_timeout_abstime = TimeValue::Now();
+                    attach_timeout_abstime.OffsetWithSeconds (waitfor_duration);
+                }
+                GSLaunchFlavor launch_flavor = g_launch_flavor;
+                if (launch_flavor == eLaunchFlavorDefault)
+                {
+                    // Our default launch method is posix spawn
+                    launch_flavor = eLaunchFlavorPosixSpawn;
+
+#if defined (__arm__)
+                    // Check if we have an app bundle, if so launch using SpringBoard.
+                    if (waitfor_pid_name.find (".app") != std::string::npos)
+                    {
+                        launch_flavor = eLaunchFlavorSpringBoard;
+                    }
+#endif
+                }
+
+                //ctx.SetLaunchFlavor(launch_flavor);
+
+
+                lldb::pid_t pid = info.GetProcess()->Attach (waitfor_pid_name.c_str());
+                if (pid == LLDB_INVALID_PROCESS_ID)
+                {
+                    info.GetRemote()->GetLaunchError() = info.GetProcess()->GetError();
+                    Log::STDERR ("error: failed to attach to process named: \"%s\" %s", waitfor_pid_name.c_str(), info.GetRemote()->GetLaunchError().AsCString());
+                    info.mode = eDCGSRunLoopModeExit;
+                }
+                else
+                {
+                    info.mode = eDCGSRunLoopModeInferiorExecuting;
+                }
+            }
+            else if (attach_pid != LLDB_INVALID_PROCESS_ID)
+            {
+                Log::STDOUT ("Attaching to process %i...\n", attach_pid);
+                info.mode = GSRunLoopLaunchAttaching (&info, attach_pid);
+                if (info.mode != eDCGSRunLoopModeInferiorExecuting)
+                {
+                    const char *error_str = info.GetRemote()->GetLaunchError().AsCString();
+                    Log::STDERR ("error: failed to attach process %i: %s\n", attach_pid, error_str ? error_str : "unknown error.");
+                    info.mode = eDCGSRunLoopModeExit;
+                }
+            }
+            else if (!attach_pid_name.empty ())
+            {
+                lldb::pid_t pid = info.GetProcess()->Attach (waitfor_pid_name.c_str());
+                if (pid == LLDB_INVALID_PROCESS_ID)
+                {
+                    info.GetRemote()->GetLaunchError() = info.GetProcess()->GetError();
+                    Log::STDERR ("error: failed to attach to process named: \"%s\" %s", waitfor_pid_name.c_str(), info.GetRemote()->GetLaunchError().AsCString());
+                    info.mode = eDCGSRunLoopModeExit;
+                }
+                else
+                {
+                    info.mode = eDCGSRunLoopModeInferiorExecuting;
+                }
+            }
+            else
+            {
+                Log::STDERR ("error: asked to attach with empty name and invalid PID.");
+                info.mode = eDCGSRunLoopModeExit;
+            }
+
+            if (info.mode != eDCGSRunLoopModeExit)
+            {
+                if (StartListening (&info, listen_port))
+                    Log::STDOUT ("Got a connection, waiting for debugger instructions for process %d.\n", attach_pid);
+                else
+                    info.mode = eDCGSRunLoopModeExit;
+            }
+            break;
+
+        case eDCGSRunLoopModeInferiorLaunching:
+            info.mode = GSRunLoopLaunchInferior (&info);
+
+            if (info.mode == eDCGSRunLoopModeInferiorExecuting)
+            {
+                if (StartListening (&info, listen_port))
+                    Log::STDOUT ("Got a connection, waiting for debugger instructions for task \"%s\".\n", argv[0]);
+                else
+                    info.mode = eDCGSRunLoopModeExit;
+            }
+            else
+            {
+                Log::STDERR ("error: failed to launch process %s: %s\n", argv[0], info.GetRemote()->GetLaunchError().AsCString());
+            }
+            break;
+
+        case eDCGSRunLoopModeInferiorExecuting:
+            GSRunLoopInferiorExecuting (&info);
+            break;
+
+        case eDCGSRunLoopModeInferiorKillOrDetach:
+            {
+                Process *process = info.GetProcess();
+                if (process && process->IsAlive())
+                {
+                    process->Kill(SIGCONT);
+                    process->Kill(SIGKILL);
+                }
+            }
+            info.mode = eDCGSRunLoopModeExit;
+            break;
+
+        default:
+          info.mode = eDCGSRunLoopModeExit;
+        case eDCGSRunLoopModeExit:
+            break;
+        }
+    }
+
+    return 0;
+}
diff --git a/source/Plugins/Process/gdb-remote/GDBServerLog.cpp b/source/Plugins/Process/gdb-remote/GDBServerLog.cpp
new file mode 100644
index 0000000..2d4116e
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/GDBServerLog.cpp
@@ -0,0 +1,80 @@
+//===-- GDBServerLog.cpp ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//----------------------------------------------------------------------
+//
+//  GDBServerLog.cpp
+//  liblldb
+//
+//  Created by Greg Clayton on 6/19/09.
+//
+//
+//----------------------------------------------------------------------
+
+#include "GDBServerLog.h"
+
+using namespace lldb;
+
+static Log *
+LogAccessor (bool get, Log *log)
+{
+    static Log* g_log = NULL; // Leak for now as auto_ptr was being cleaned up
+                                // by global constructors before other threads
+                                // were done with it.
+    if (get)
+    {
+//      // Debug code below for enabling logging by default
+//      if (g_log == NULL)
+//      {
+//          g_log = new Log("/dev/stdout", false);
+//          g_log->GetMask().SetAllFlagBits(GS_LOG_ALL);
+//          g_log->GetOptions().Set(LLDB_LOG_OPTION_THREADSAFE | LLDB_LOG_OPTION_PREPEND_THREAD_NAME);
+//      }
+    }
+    else
+    {
+        if (g_log)
+            delete g_log;
+        g_log = log;
+    }
+
+    return g_log;
+}
+
+Log *
+GDBServerLog::GetLogIfAllCategoriesSet (uint32_t mask)
+{
+    Log *log = LogAccessor (true, NULL);
+    if (log && mask)
+    {
+        uint32_t log_mask = log->GetMask().GetAllFlagBits();
+        if ((log_mask & mask) != mask)
+            return NULL;
+    }
+    return log;
+}
+
+void
+GDBServerLog::SetLog (Log *log)
+{
+    LogAccessor (false, log);
+}
+
+
+void
+GDBServerLog::LogIf (uint32_t mask, const char *format, ...)
+{
+    Log *log = GDBServerLog::GetLogIfAllCategoriesSet (mask);
+    if (log)
+    {
+        va_list args;
+        va_start (args, format);
+        log->VAPrintf (format, args);
+        va_end (args);
+    }
+}
diff --git a/source/Plugins/Process/gdb-remote/GDBServerLog.h b/source/Plugins/Process/gdb-remote/GDBServerLog.h
new file mode 100644
index 0000000..3dec808
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/GDBServerLog.h
@@ -0,0 +1,55 @@
+//===-- GDBServerLog.h ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//----------------------------------------------------------------------
+//
+//  GDBServerLog.h
+//  liblldb
+//
+//  Created by Greg Clayton on 6/19/09.
+//
+//
+//----------------------------------------------------------------------
+
+#ifndef liblldb_GDBServerLog_h_
+#define liblldb_GDBServerLog_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+
+#include "lldb/Core/Log.h"
+
+// Project includes
+#define GS_LOG_VERBOSE  (1u << 0)
+#define GS_LOG_DEBUG        (1u << 1)
+#define GS_LOG_PACKETS  (1u << 2)
+#define GS_LOG_EVENTS       (1u << 3)
+#define GS_LOG_MINIMAL  (1u << 4)
+#define GS_LOG_ALL      (UINT32_MAX)
+#define GS_LOG_DEFAULT  (GS_LOG_VERBOSE     |\
+                             GS_LOG_PACKETS)
+
+namespace lldb {
+
+class GDBServerLog
+{
+public:
+    static Log *
+    GetLog (uint32_t mask = 0);
+
+    static void
+    SetLog (Log *log);
+
+    static void
+    LogIf (uint32_t mask, const char *format, ...);
+};
+
+} // namespace lldb
+
+#endif  // liblldb_GDBServerLog_h_
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
new file mode 100644
index 0000000..e08679c
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -0,0 +1,2272 @@
+//===-- ProcessGDBRemote.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 <mach/mach.h>
+#include <mach-o/dyld.h>
+#include <spawn.h>
+#include <sys/fcntl.h>
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <unistd.h>
+
+// C++ Includes
+#include <algorithm>
+#include <map>
+
+// Other libraries and framework includes
+
+#include "lldb/Breakpoint/WatchpointLocation.h"
+#include "lldb/Core/Args.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/ConnectionFileDescriptor.h"
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Core/InputReader.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/State.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Host/TimeValue.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/TargetList.h"
+#include "PseudoTerminal.h"
+
+// Project includes
+#include "lldb/Host/Host.h"
+#include "StringExtractorGDBRemote.h"
+#include "GDBRemoteRegisterContext.h"
+#include "ProcessGDBRemote.h"
+#include "ProcessGDBRemoteLog.h"
+#include "ThreadGDBRemote.h"
+#include "libunwind.h"
+#include "MacOSXLibunwindCallbacks.h"
+
+#if defined (__i386__) || defined (__x86_64__)
+#define MACH_EXC_DATA0_SOFTWARE_BREAKPOINT EXC_I386_BPT
+#define MACH_EXC_DATA0_TRACE EXC_I386_SGL
+#elif defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__)
+#define MACH_EXC_DATA0_SOFTWARE_BREAKPOINT EXC_PPC_BREAKPOINT
+#elif defined (__arm__)
+#define MACH_EXC_DATA0_SOFTWARE_BREAKPOINT EXC_ARM_BREAKPOINT
+#endif
+
+
+#define DEBUGSERVER_BASENAME    "debugserver"
+using namespace lldb;
+using namespace lldb_private;
+
+static inline uint16_t
+get_random_port ()
+{
+    return (arc4random() % (UINT16_MAX - 1000u)) + 1000u;
+}
+
+
+const char *
+ProcessGDBRemote::GetPluginNameStatic()
+{
+    return "process.gdb-remote";
+}
+
+const char *
+ProcessGDBRemote::GetPluginDescriptionStatic()
+{
+    return "GDB Remote protocol based debugging plug-in.";
+}
+
+void
+ProcessGDBRemote::Terminate()
+{
+    PluginManager::UnregisterPlugin (ProcessGDBRemote::CreateInstance);
+}
+
+
+Process*
+ProcessGDBRemote::CreateInstance (Target &target, Listener &listener)
+{
+    return new ProcessGDBRemote (target, listener);
+}
+
+bool
+ProcessGDBRemote::CanDebug(Target &target)
+{
+    // For now we are just making sure the file exists for a given module
+    ModuleSP exe_module_sp(target.GetExecutableModule());
+    if (exe_module_sp.get())
+        return exe_module_sp->GetFileSpec().Exists();
+    return false;
+}
+
+//----------------------------------------------------------------------
+// ProcessGDBRemote constructor
+//----------------------------------------------------------------------
+ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
+    Process (target, listener),
+    m_dynamic_loader_ap (),
+    m_byte_order (eByteOrderHost),
+    m_flags (0),
+    m_stdio_communication ("gdb-remote.stdio"),
+    m_stdio_mutex (Mutex::eMutexTypeRecursive),
+    m_stdout_data (),
+    m_arch_spec (),
+    m_gdb_comm(),
+    m_debugserver_pid (LLDB_INVALID_PROCESS_ID),
+    m_debugserver_monitor (0),
+    m_register_info (),
+    m_curr_tid (LLDB_INVALID_THREAD_ID),
+    m_curr_tid_run (LLDB_INVALID_THREAD_ID),
+    m_async_broadcaster ("lldb.process.gdb-remote.async-broadcaster"),
+    m_async_thread (LLDB_INVALID_HOST_THREAD),
+    m_z0_supported (1),
+    m_continue_packet(),
+    m_dispatch_queue_offsets_addr (LLDB_INVALID_ADDRESS),
+    m_libunwind_target_type (UNW_TARGET_UNSPECIFIED),
+    m_libunwind_addr_space (NULL),
+    m_waiting_for_attach (false),
+    m_packet_timeout (1),
+    m_max_memory_size (512)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ProcessGDBRemote::~ProcessGDBRemote()
+{
+    //  m_mach_process.UnregisterNotificationCallbacks (this);
+    Clear();
+}
+
+//----------------------------------------------------------------------
+// PluginInterface
+//----------------------------------------------------------------------
+const char *
+ProcessGDBRemote::GetPluginName()
+{
+    return "Process debugging plug-in that uses the GDB remote protocol";
+}
+
+const char *
+ProcessGDBRemote::GetShortPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+ProcessGDBRemote::GetPluginVersion()
+{
+    return 1;
+}
+
+void
+ProcessGDBRemote::GetPluginCommandHelp (const char *command, Stream *strm)
+{
+    strm->Printf("TODO: fill this in\n");
+}
+
+Error
+ProcessGDBRemote::ExecutePluginCommand (Args &command, Stream *strm)
+{
+    Error error;
+    error.SetErrorString("No plug-in commands are currently supported.");
+    return error;
+}
+
+Log *
+ProcessGDBRemote::EnablePluginLogging (Stream *strm, Args &command)
+{
+    return NULL;
+}
+
+void
+ProcessGDBRemote::BuildDynamicRegisterInfo ()
+{
+    char register_info_command[64];
+    m_register_info.Clear();
+    StringExtractorGDBRemote::Type packet_type = StringExtractorGDBRemote::eResponse;
+    uint32_t reg_offset = 0;
+    uint32_t reg_num = 0;
+    for (; packet_type == StringExtractorGDBRemote::eResponse; ++reg_num)
+    {
+        ::snprintf (register_info_command, sizeof(register_info_command), "qRegisterInfo%x", reg_num);
+        StringExtractorGDBRemote response;
+        if (m_gdb_comm.SendPacketAndWaitForResponse(register_info_command, response, 2, false))
+        {
+            packet_type = response.GetType();
+            if (packet_type == StringExtractorGDBRemote::eResponse)
+            {
+                std::string name;
+                std::string value;
+                ConstString reg_name;
+                ConstString alt_name;
+                ConstString set_name;
+                RegisterInfo reg_info = { NULL,                 // Name
+                    NULL,                 // Alt name
+                    0,                    // byte size
+                    reg_offset,           // offset
+                    eEncodingUint,        // encoding
+                    eFormatHex,           // formate
+                    reg_num,              // native register number
+                    {
+                        LLDB_INVALID_REGNUM, // GCC reg num
+                        LLDB_INVALID_REGNUM, // DWARF reg num
+                        LLDB_INVALID_REGNUM, // generic reg num
+                        reg_num              // GDB reg num
+                    }
+                };
+
+                while (response.GetNameColonValue(name, value))
+                {
+                    if (name.compare("name") == 0)
+                    {
+                        reg_name.SetCString(value.c_str());
+                    }
+                    else if (name.compare("alt-name") == 0)
+                    {
+                        alt_name.SetCString(value.c_str());
+                    }
+                    else if (name.compare("bitsize") == 0)
+                    {
+                        reg_info.byte_size = Args::StringToUInt32(value.c_str(), 0, 0) / CHAR_BIT;
+                    }
+                    else if (name.compare("offset") == 0)
+                    {
+                        uint32_t offset = Args::StringToUInt32(value.c_str(), UINT32_MAX, 0);
+                        if (offset != offset)
+                        {
+                            reg_offset = offset;
+                            reg_info.byte_offset = offset;
+                        }
+                    }
+                    else if (name.compare("encoding") == 0)
+                    {
+                        if (value.compare("uint") == 0)
+                            reg_info.encoding = eEncodingUint;
+                        else if (value.compare("sint") == 0)
+                            reg_info.encoding = eEncodingSint;
+                        else if (value.compare("ieee754") == 0)
+                            reg_info.encoding = eEncodingIEEE754;
+                        else if (value.compare("vector") == 0)
+                            reg_info.encoding = eEncodingVector;
+                    }
+                    else if (name.compare("format") == 0)
+                    {
+                        if (value.compare("binary") == 0)
+                            reg_info.format = eFormatBinary;
+                        else if (value.compare("decimal") == 0)
+                            reg_info.format = eFormatDecimal;
+                        else if (value.compare("hex") == 0)
+                            reg_info.format = eFormatHex;
+                        else if (value.compare("float") == 0)
+                            reg_info.format = eFormatFloat;
+                        else if (value.compare("vector-sint8") == 0)
+                            reg_info.format = eFormatVectorOfSInt8;
+                        else if (value.compare("vector-uint8") == 0)
+                            reg_info.format = eFormatVectorOfUInt8;
+                        else if (value.compare("vector-sint16") == 0)
+                            reg_info.format = eFormatVectorOfSInt16;
+                        else if (value.compare("vector-uint16") == 0)
+                            reg_info.format = eFormatVectorOfUInt16;
+                        else if (value.compare("vector-sint32") == 0)
+                            reg_info.format = eFormatVectorOfSInt32;
+                        else if (value.compare("vector-uint32") == 0)
+                            reg_info.format = eFormatVectorOfUInt32;
+                        else if (value.compare("vector-float32") == 0)
+                            reg_info.format = eFormatVectorOfFloat32;
+                        else if (value.compare("vector-uint128") == 0)
+                            reg_info.format = eFormatVectorOfUInt128;
+                    }
+                    else if (name.compare("set") == 0)
+                    {
+                        set_name.SetCString(value.c_str());
+                    }
+                    else if (name.compare("gcc") == 0)
+                    {
+                        reg_info.kinds[eRegisterKindGCC] = Args::StringToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0);
+                    }
+                    else if (name.compare("dwarf") == 0)
+                    {
+                        reg_info.kinds[eRegisterKindDWARF] = Args::StringToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0);
+                    }
+                    else if (name.compare("generic") == 0)
+                    {
+                        if (value.compare("pc") == 0)
+                            reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
+                        else if (value.compare("sp") == 0)
+                            reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
+                        else if (value.compare("fp") == 0)
+                            reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
+                        else if (value.compare("ra") == 0)
+                            reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
+                        else if (value.compare("flags") == 0)
+                            reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
+                    }
+                }
+
+                assert (reg_info.byte_size != 0);
+                reg_offset += reg_info.byte_size;
+                m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name);
+            }
+        }
+        else
+        {
+            packet_type = StringExtractorGDBRemote::eError;
+        }
+    }
+
+    if (reg_num == 0)
+    {
+        // We didn't get anything. See if we are debugging ARM and fill with
+        // a hard coded register set until we can get an updated debugserver
+        // down on the devices.
+        ArchSpec arm_arch ("arm");
+        if (GetTarget().GetArchitecture() == arm_arch)
+            m_register_info.HardcodeARMRegisters();
+    }
+    m_register_info.Finalize ();
+}
+
+Error
+ProcessGDBRemote::WillLaunch (Module* module)
+{
+    return WillLaunchOrAttach ();
+}
+
+Error
+ProcessGDBRemote::WillAttach (lldb::pid_t pid)
+{
+    return WillLaunchOrAttach ();
+}
+
+Error
+ProcessGDBRemote::WillAttach (const char *process_name, bool wait_for_launch)
+{
+    return WillLaunchOrAttach ();
+}
+
+Error
+ProcessGDBRemote::WillLaunchOrAttach ()
+{
+    Error error;
+    // TODO: this is hardcoded for macosx right now. We need this to be more dynamic
+    m_dynamic_loader_ap.reset(DynamicLoader::FindPlugin(this, "dynamic-loader.macosx-dyld"));
+
+    if (m_dynamic_loader_ap.get() == NULL)
+        error.SetErrorString("unable to find the dynamic loader named 'dynamic-loader.macosx-dyld'");
+    m_stdio_communication.Clear ();
+    
+    return error;
+}
+
+//----------------------------------------------------------------------
+// Process Control
+//----------------------------------------------------------------------
+Error
+ProcessGDBRemote::DoLaunch
+(
+    Module* module,
+    char const *argv[],
+    char const *envp[],
+    const char *stdin_path,
+    const char *stdout_path,
+    const char *stderr_path
+)
+{
+    //  ::LogSetBitMask (GDBR_LOG_DEFAULT);
+    //  ::LogSetOptions (LLDB_LOG_OPTION_THREADSAFE | LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD);
+    //  ::LogSetLogFile ("/dev/stdout");
+    Error error;
+
+    ObjectFile * object_file = module->GetObjectFile();
+    if (object_file)
+    {
+        ArchSpec inferior_arch(module->GetArchitecture());
+        char host_port[128];
+        snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
+
+        bool start_debugserver_with_inferior_args = false;
+        if (start_debugserver_with_inferior_args)
+        {
+            // We want to launch debugserver with the inferior program and its
+            // arguments on the command line. We should only do this if we
+            // the GDB server we are talking to doesn't support the 'A' packet.
+            error = StartDebugserverProcess (host_port,
+                                             argv,
+                                             envp,
+                                             NULL, //stdin_path,
+                                             LLDB_INVALID_PROCESS_ID,
+                                             NULL, false,
+                                             inferior_arch);
+            if (error.Fail())
+                return error;
+
+            error = ConnectToDebugserver (host_port);
+            if (error.Success())
+            {
+                SetID (m_gdb_comm.GetCurrentProcessID (m_packet_timeout));
+            }
+        }
+        else
+        {
+            error = StartDebugserverProcess (host_port,
+                                             NULL,
+                                             NULL,
+                                             NULL, //stdin_path,
+                                             LLDB_INVALID_PROCESS_ID,
+                                             NULL, false,
+                                             inferior_arch);
+            if (error.Fail())
+                return error;
+
+            error = ConnectToDebugserver (host_port);
+            if (error.Success())
+            {
+                // Send the environment and the program + arguments after we connect
+                if (envp)
+                {
+                    const char *env_entry;
+                    for (int i=0; (env_entry = envp[i]); ++i)
+                    {
+                        if (m_gdb_comm.SendEnvironmentPacket(env_entry, m_packet_timeout) != 0)
+                            break;
+                    }
+                }
+
+                const uint32_t arg_timeout_seconds = 10;
+                int arg_packet_err = m_gdb_comm.SendArgumentsPacket (argv, arg_timeout_seconds);
+                if (arg_packet_err == 0)
+                {
+                    std::string error_str;
+                    if (m_gdb_comm.GetLaunchSuccess (m_packet_timeout, error_str))
+                    {
+                        SetID (m_gdb_comm.GetCurrentProcessID (m_packet_timeout));
+                    }
+                    else
+                    {
+                        error.SetErrorString (error_str.c_str());
+                    }
+                }
+                else
+                {
+                    error.SetErrorStringWithFormat("'A' packet returned an error: %i.\n", arg_packet_err);
+                }
+                
+                SetID (m_gdb_comm.GetCurrentProcessID (m_packet_timeout));
+            }
+        }
+
+        if (GetID() == LLDB_INVALID_PROCESS_ID)
+        {
+            KillDebugserverProcess ();
+            return error;
+        }
+    
+        StringExtractorGDBRemote response;
+        if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, response, m_packet_timeout, false))
+            SetPrivateState (SetThreadStopInfo (response));
+
+    }
+    else
+    {
+        // Set our user ID to an invalid process ID.
+        SetID(LLDB_INVALID_PROCESS_ID);
+        error.SetErrorStringWithFormat("Failed to get object file from '%s' for arch %s.\n", module->GetFileSpec().GetFilename().AsCString(), module->GetArchitecture().AsCString());
+    }
+
+    // Return the process ID we have
+    return error;
+}
+
+
+Error
+ProcessGDBRemote::ConnectToDebugserver (const char *host_port)
+{
+    Error error;
+    // Sleep and wait a bit for debugserver to start to listen...
+    std::auto_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
+    if (conn_ap.get())
+    {
+        std::string connect_url("connect://");
+        connect_url.append (host_port);
+        const uint32_t max_retry_count = 50;
+        uint32_t retry_count = 0;
+        while (!m_gdb_comm.IsConnected())
+        {
+            if (conn_ap->Connect(connect_url.c_str(), &error) == eConnectionStatusSuccess)
+            {
+                m_gdb_comm.SetConnection (conn_ap.release());
+                break;
+            }
+            retry_count++;
+
+            if (retry_count >= max_retry_count)
+                break;
+
+            usleep (100000);
+        }
+    }
+
+    if (!m_gdb_comm.IsConnected())
+    {
+        if (error.Success())
+            error.SetErrorString("not connected to remote gdb server");
+        return error;
+    }
+
+    m_gdb_comm.SetAckMode (true);
+    if (m_gdb_comm.StartReadThread(&error))
+    {
+        // Send an initial ack
+        m_gdb_comm.SendAck('+');
+
+        if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
+            m_debugserver_monitor = Host::StartMonitoringChildProcess (MonitorDebugserverProcess,
+                                                                       (void*)(intptr_t)GetID(),    // Pass the inferior pid in the thread argument (which is a void *)
+                                                                       m_debugserver_pid,
+                                                                       false);
+
+        StringExtractorGDBRemote response;
+        if (m_gdb_comm.SendPacketAndWaitForResponse("QStartNoAckMode", response, 1, false))
+        {
+            if (response.IsOKPacket())
+                m_gdb_comm.SetAckMode (false);
+        }
+
+        BuildDynamicRegisterInfo ();
+    }
+    return error;
+}
+
+void
+ProcessGDBRemote::DidLaunchOrAttach ()
+{
+    ProcessGDBRemoteLog::LogIf (GDBR_LOG_PROCESS, "ProcessGDBRemote::DidLaunch()");
+    if (GetID() == LLDB_INVALID_PROCESS_ID)
+    {
+        m_dynamic_loader_ap.reset();
+    }
+    else
+    {
+        m_dispatch_queue_offsets_addr = LLDB_INVALID_ADDRESS;
+
+        Module * exe_module = GetTarget().GetExecutableModule ().get();
+        assert(exe_module);
+
+        m_arch_spec = exe_module->GetArchitecture();
+
+        ObjectFile *exe_objfile = exe_module->GetObjectFile();
+        assert(exe_objfile);
+
+        m_byte_order = exe_objfile->GetByteOrder();
+        assert (m_byte_order != eByteOrderInvalid);
+
+        StreamString strm;
+
+        ArchSpec inferior_arch;
+        // See if the GDB server supports the qHostInfo information
+        const char *vendor = m_gdb_comm.GetVendorString().AsCString();
+        const char *os_type = m_gdb_comm.GetOSString().AsCString();
+        
+        if (m_arch_spec.IsValid() && m_arch_spec == ArchSpec ("arm"))
+        {
+            // For ARM we can't trust the arch of the process as it could
+            // have an armv6 object file, but be running on armv7 kernel.
+            inferior_arch = m_gdb_comm.GetHostArchitecture();
+        }
+        
+        if (!inferior_arch.IsValid())
+            inferior_arch = m_arch_spec;
+
+        if (vendor == NULL)
+            vendor = Host::GetVendorString().AsCString("apple");
+        
+        if (os_type == NULL)
+            os_type = Host::GetOSString().AsCString("darwin");
+
+        strm.Printf ("%s-%s-%s", inferior_arch.AsCString(), vendor, os_type);
+
+        std::transform (strm.GetString().begin(), 
+                        strm.GetString().end(), 
+                        strm.GetString().begin(), 
+                        ::tolower);
+
+        m_target_triple.SetCString(strm.GetString().c_str());
+    }
+}
+
+void
+ProcessGDBRemote::DidLaunch ()
+{
+    DidLaunchOrAttach ();
+    if (m_dynamic_loader_ap.get())
+        m_dynamic_loader_ap->DidLaunch();
+}
+
+Error
+ProcessGDBRemote::DoAttach (pid_t attach_pid)
+{
+    Error error;
+    // Clear out and clean up from any current state
+    Clear();
+    // HACK: require arch be set correctly at the target level until we can
+    // figure out a good way to determine the arch of what we are attaching to
+    m_arch_spec = m_target.GetArchitecture();
+
+    //Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS);
+    if (attach_pid != LLDB_INVALID_PROCESS_ID)
+    {
+        SetPrivateState (eStateAttaching);
+        char host_port[128];
+        snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
+        error = StartDebugserverProcess (host_port,
+                                         NULL,
+                                         NULL,
+                                         NULL,
+                                         LLDB_INVALID_PROCESS_ID,
+                                         NULL, false,
+                                         m_arch_spec);
+        
+        if (error.Fail())
+        {
+            const char *error_string = error.AsCString();
+            if (error_string == NULL)
+                error_string = "unable to launch " DEBUGSERVER_BASENAME;
+
+            SetExitStatus (-1, error_string);
+        }
+        else
+        {
+            error = ConnectToDebugserver (host_port);
+            if (error.Success())
+            {
+                char packet[64];
+                const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%x", attach_pid);
+                StringExtractorGDBRemote response;
+                StateType stop_state = m_gdb_comm.SendContinuePacketAndWaitForResponse (this, 
+                                                                                        packet, 
+                                                                                        packet_len, 
+                                                                                        response);
+                switch (stop_state)
+                {
+                case eStateStopped:
+                case eStateCrashed:
+                case eStateSuspended:
+                    SetID (attach_pid);
+                    m_last_stop_packet = response;
+                    m_last_stop_packet.SetFilePos (0);
+                    SetPrivateState (stop_state);
+                    break;
+
+                case eStateExited:
+                    m_last_stop_packet = response;
+                    m_last_stop_packet.SetFilePos (0);
+                    response.SetFilePos(1);
+                    SetExitStatus(response.GetHexU8(), NULL);
+                    break;
+
+                default:
+                    SetExitStatus(-1, "unable to attach to process");
+                    break;
+                }
+
+            }
+        }
+    }
+
+    lldb::pid_t pid = GetID();
+    if (pid == LLDB_INVALID_PROCESS_ID)
+    {
+        KillDebugserverProcess();
+    }
+    return error;
+}
+
+size_t
+ProcessGDBRemote::AttachInputReaderCallback
+(
+    void *baton, 
+    InputReader *reader, 
+    lldb::InputReaderAction notification,
+    const char *bytes, 
+    size_t bytes_len
+)
+{
+    if (notification == eInputReaderGotToken)
+    {
+        ProcessGDBRemote *gdb_process = (ProcessGDBRemote *)baton;
+        if (gdb_process->m_waiting_for_attach)
+            gdb_process->m_waiting_for_attach = false;
+        reader->SetIsDone(true);
+        return 1;
+    }
+    return 0;
+}
+
+Error
+ProcessGDBRemote::DoAttach (const char *process_name, bool wait_for_launch)
+{
+    Error error;
+    // Clear out and clean up from any current state
+    Clear();
+    // HACK: require arch be set correctly at the target level until we can
+    // figure out a good way to determine the arch of what we are attaching to
+    m_arch_spec = m_target.GetArchitecture();
+
+    //Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS);
+    if (process_name && process_name[0])
+    {
+
+        SetPrivateState (eStateAttaching);
+        char host_port[128];
+        snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
+        error = StartDebugserverProcess (host_port,
+                                         NULL,
+                                         NULL,
+                                         NULL,
+                                         LLDB_INVALID_PROCESS_ID,
+                                         NULL, false,
+                                         m_arch_spec);
+        if (error.Fail())
+        {
+            const char *error_string = error.AsCString();
+            if (error_string == NULL)
+                error_string = "unable to launch " DEBUGSERVER_BASENAME;
+
+            SetExitStatus (-1, error_string);
+        }
+        else
+        {
+            error = ConnectToDebugserver (host_port);
+            if (error.Success())
+            {
+                StreamString packet;
+                
+                packet.PutCString("vAttach");
+                if (wait_for_launch)
+                    packet.PutCString("Wait");
+                packet.PutChar(';');
+                packet.PutBytesAsRawHex8(process_name, strlen(process_name), eByteOrderHost, eByteOrderHost);
+                StringExtractorGDBRemote response;
+                StateType stop_state = m_gdb_comm.SendContinuePacketAndWaitForResponse (this, 
+                                                                                        packet.GetData(), 
+                                                                                        packet.GetSize(), 
+                                                                                        response);
+                switch (stop_state)
+                {
+                case eStateStopped:
+                case eStateCrashed:
+                case eStateSuspended:
+                    SetID (m_gdb_comm.GetCurrentProcessID(m_packet_timeout));
+                    m_last_stop_packet = response;
+                    m_last_stop_packet.SetFilePos (0);
+                    SetPrivateState (stop_state);
+                    break;
+
+                case eStateExited:
+                    m_last_stop_packet = response;
+                    m_last_stop_packet.SetFilePos (0);
+                    response.SetFilePos(1);
+                    SetExitStatus(response.GetHexU8(), NULL);
+                    break;
+
+                default:
+                    SetExitStatus(-1, "unable to attach to process");
+                    break;
+                }
+            }
+        }
+    }
+
+    lldb::pid_t pid = GetID();
+    if (pid == LLDB_INVALID_PROCESS_ID)
+    {
+        KillDebugserverProcess();
+    }
+    return error;
+}
+
+//                              
+//        if (wait_for_launch)
+//        {
+//            InputReaderSP reader_sp (new InputReader());
+//            StreamString instructions;
+//            instructions.Printf("Hit any key to cancel waiting for '%s' to launch...", process_name);
+//            error = reader_sp->Initialize (AttachInputReaderCallback, // callback
+//                                                this, // baton
+//                                                eInputReaderGranularityByte,
+//                                                NULL, // End token
+//                                                false);
+//            
+//            StringExtractorGDBRemote response;
+//            m_waiting_for_attach = true;
+//            FILE *reader_out_fh = reader_sp->GetOutputFileHandle();
+//            while (m_waiting_for_attach)
+//            {
+//                // Wait for one second for the stop reply packet
+//                if (m_gdb_comm.WaitForPacket(response, 1))
+//                {
+//                    // Got some sort of packet, see if it is the stop reply packet?
+//                    char ch = response.GetChar(0);
+//                    if (ch == 'T')
+//                    {
+//                        m_waiting_for_attach = false;
+//                    }
+//                }
+//                else
+//                {
+//                    // Put a period character every second
+//                    fputc('.', reader_out_fh);
+//                }
+//            }
+//        }
+//    }
+//    return GetID();
+//}
+
+void
+ProcessGDBRemote::DidAttach ()
+{
+    DidLaunchOrAttach ();
+    if (m_dynamic_loader_ap.get())
+        m_dynamic_loader_ap->DidAttach();
+}
+
+Error
+ProcessGDBRemote::WillResume ()
+{
+    m_continue_packet.Clear();
+    // Start the continue packet we will use to run the target. Each thread
+    // will append what it is supposed to be doing to this packet when the
+    // ThreadList::WillResume() is called. If a thread it supposed
+    // to stay stopped, then don't append anything to this string.
+    m_continue_packet.Printf("vCont");
+    return Error();
+}
+
+Error
+ProcessGDBRemote::DoResume ()
+{
+    ProcessGDBRemoteLog::LogIf (GDBR_LOG_PROCESS, "ProcessGDBRemote::Resume()");
+    m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (m_continue_packet.GetData(), m_continue_packet.GetSize()));
+    return Error();
+}
+
+size_t
+ProcessGDBRemote::GetSoftwareBreakpointTrapOpcode (BreakpointSite* bp_site)
+{
+    const uint8_t *trap_opcode = NULL;
+    uint32_t trap_opcode_size = 0;
+
+    static const uint8_t g_arm_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 };
+    //static const uint8_t g_thumb_breakpooint_opcode[] = { 0xFE, 0xDE };
+    static const uint8_t g_ppc_breakpoint_opcode[] = { 0x7F, 0xC0, 0x00, 0x08 };
+    static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC };
+
+    switch (m_arch_spec.GetCPUType())
+    {
+        case CPU_TYPE_ARM:
+            // TODO: fill this in for ARM. We need to dig up the symbol for
+            // the address in the breakpoint locaiton and figure out if it is
+            // an ARM or Thumb breakpoint.
+            trap_opcode = g_arm_breakpoint_opcode;
+            trap_opcode_size = sizeof(g_arm_breakpoint_opcode);
+            break;
+
+        case CPU_TYPE_POWERPC:
+        case CPU_TYPE_POWERPC64:
+            trap_opcode = g_ppc_breakpoint_opcode;
+            trap_opcode_size = sizeof(g_ppc_breakpoint_opcode);
+            break;
+
+        case CPU_TYPE_I386:
+        case CPU_TYPE_X86_64:
+            trap_opcode = g_i386_breakpoint_opcode;
+            trap_opcode_size = sizeof(g_i386_breakpoint_opcode);
+            break;
+
+        default:
+            assert(!"Unhandled architecture in ProcessGDBRemote::GetSoftwareBreakpointTrapOpcode()");
+            return 0;
+    }
+
+    if (trap_opcode && trap_opcode_size)
+    {
+        if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
+            return trap_opcode_size;
+    }
+    return 0;
+}
+
+uint32_t
+ProcessGDBRemote::UpdateThreadListIfNeeded ()
+{
+    // locker will keep a mutex locked until it goes out of scope
+    Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_THREAD);
+    if (log && log->GetMask().IsSet(GDBR_LOG_VERBOSE))
+        log->Printf ("ProcessGDBRemote::%s (pid = %i)", __FUNCTION__, GetID());
+
+    const uint32_t stop_id = GetStopID();
+    if (m_thread_list.GetSize(false) == 0 || stop_id != m_thread_list.GetStopID())
+    {
+        // 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);
+
+        Error err;
+        StringExtractorGDBRemote response;
+        for (m_gdb_comm.SendPacketAndWaitForResponse("qfThreadInfo", response, 1, false);
+             response.IsNormalPacket();
+             m_gdb_comm.SendPacketAndWaitForResponse("qsThreadInfo", response, 1, false))
+        {
+            char ch = response.GetChar();
+            if (ch == 'l')
+                break;
+            if (ch == 'm')
+            {
+                do
+                {
+                    tid_t tid = response.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID);
+
+                    if (tid != LLDB_INVALID_THREAD_ID)
+                    {
+                        ThreadSP thread_sp (GetThreadList().FindThreadByID (tid, false));
+                        if (thread_sp)
+                            thread_sp->GetRegisterContext()->Invalidate();
+                        else
+                            thread_sp.reset (new ThreadGDBRemote (*this, tid));
+                        curr_thread_list.AddThread(thread_sp);
+                    }
+
+                    ch = response.GetChar();
+                } while (ch == ',');
+            }
+        }
+
+        m_thread_list = curr_thread_list;
+
+        SetThreadStopInfo (m_last_stop_packet);
+    }
+    return GetThreadList().GetSize(false);
+}
+
+
+StateType
+ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
+{
+    const char stop_type = stop_packet.GetChar();
+    switch (stop_type)
+    {
+    case 'T':
+    case 'S':
+        {
+            // Stop with signal and thread info
+            const uint8_t signo = stop_packet.GetHexU8();
+            std::string name;
+            std::string value;
+            std::string thread_name;
+            uint32_t exc_type = 0;
+            std::vector<uint64_t> exc_data;
+            uint32_t tid = LLDB_INVALID_THREAD_ID;
+            addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS;
+            uint32_t exc_data_count = 0;
+            while (stop_packet.GetNameColonValue(name, value))
+            {
+                if (name.compare("metype") == 0)
+                {
+                    // exception type in big endian hex
+                    exc_type = Args::StringToUInt32 (value.c_str(), 0, 16);
+                }
+                else if (name.compare("mecount") == 0)
+                {
+                    // exception count in big endian hex
+                    exc_data_count = Args::StringToUInt32 (value.c_str(), 0, 16);
+                }
+                else if (name.compare("medata") == 0)
+                {
+                    // exception data in big endian hex
+                    exc_data.push_back(Args::StringToUInt64 (value.c_str(), 0, 16));
+                }
+                else if (name.compare("thread") == 0)
+                {
+                    // thread in big endian hex
+                    tid = Args::StringToUInt32 (value.c_str(), 0, 16);
+                }
+                else if (name.compare("name") == 0)
+                {
+                    thread_name.swap (value);
+                }
+                else if (name.compare("dispatchqaddr") == 0)
+                {
+                    thread_dispatch_qaddr = Args::StringToUInt64 (value.c_str(), 0, 16);
+                }
+            }
+            ThreadSP thread_sp (m_thread_list.FindThreadByID(tid, false));
+
+            if (thread_sp)
+            {
+                ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get());
+
+                gdb_thread->SetThreadDispatchQAddr (thread_dispatch_qaddr);
+                gdb_thread->SetName (thread_name.empty() ? thread_name.c_str() : NULL);
+                Thread::StopInfo& stop_info = gdb_thread->GetStopInfoRef();
+                gdb_thread->SetStopInfoStopID (GetStopID());
+                if (exc_type != 0)
+                {
+                    if (exc_type == EXC_SOFTWARE && exc_data.size() == 2 && exc_data[0] == EXC_SOFT_SIGNAL)
+                    {
+                        stop_info.SetStopReasonWithSignal(exc_data[1]);
+                    }
+#if defined (MACH_EXC_DATA0_SOFTWARE_BREAKPOINT)
+                    else if (exc_type == EXC_BREAKPOINT && exc_data[0] == MACH_EXC_DATA0_SOFTWARE_BREAKPOINT)
+                    {
+                        addr_t pc = gdb_thread->GetRegisterContext()->GetPC();
+                        user_id_t break_id = GetBreakpointSiteList().FindIDByAddress(pc);
+                        if (break_id == LLDB_INVALID_BREAK_ID)
+                        {
+                            //log->Printf("got EXC_BREAKPOINT at 0x%llx but didn't find a breakpoint site.\n", pc);
+                            stop_info.SetStopReasonWithException(exc_type, exc_data.size());
+                            for (uint32_t i=0; i<exc_data.size(); ++i)
+                                stop_info.SetExceptionDataAtIndex(i, exc_data[i]);
+                        }
+                        else
+                        {
+                            stop_info.Clear ();
+                            stop_info.SetStopReasonWithBreakpointSiteID (break_id);
+                        }
+                    }
+#endif
+#if defined (MACH_EXC_DATA0_TRACE)
+                    else if (exc_type == EXC_BREAKPOINT && exc_data[0] == MACH_EXC_DATA0_TRACE)
+                    {
+                        stop_info.SetStopReasonToTrace ();
+                    }
+#endif
+                    else
+                    {
+                        stop_info.SetStopReasonWithException(exc_type, exc_data.size());
+                        for (uint32_t i=0; i<exc_data.size(); ++i)
+                            stop_info.SetExceptionDataAtIndex(i, exc_data[i]);
+                    }
+                }
+                else if (signo)
+                {
+                    stop_info.SetStopReasonWithSignal(signo);
+                }
+                else
+                {
+                    stop_info.SetStopReasonToNone();
+                }
+            }
+            return eStateStopped;
+        }
+        break;
+
+    case 'W':
+        // process exited
+        return eStateExited;
+
+    default:
+        break;
+    }
+    return eStateInvalid;
+}
+
+void
+ProcessGDBRemote::RefreshStateAfterStop ()
+{
+    // We must be attaching if we don't already have a valid architecture
+    if (!m_arch_spec.IsValid())
+    {
+        Module *exe_module = GetTarget().GetExecutableModule().get();
+        if (exe_module)
+            m_arch_spec = exe_module->GetArchitecture();
+    }
+    // Let all threads recover from stopping and do any clean up based
+    // on the previous thread state (if any).
+    m_thread_list.RefreshStateAfterStop();
+
+    // Discover new threads:
+    UpdateThreadListIfNeeded ();
+}
+
+Error
+ProcessGDBRemote::DoHalt ()
+{
+    Error error;
+    if (m_gdb_comm.IsRunning())
+    {
+        bool timed_out = false;
+        if (!m_gdb_comm.SendInterrupt (2, &timed_out))
+        {
+            if (timed_out)
+                error.SetErrorString("timed out sending interrupt packet");
+            else
+                error.SetErrorString("unknown error sending interrupt packet");
+        }
+    }
+    return error;
+}
+
+Error
+ProcessGDBRemote::WillDetach ()
+{
+    Error error;
+    const StateType state = m_private_state.GetValue();
+
+    if (IsRunning(state))
+        error.SetErrorString("Process must be stopped in order to detach.");
+
+    return error;
+}
+
+
+Error
+ProcessGDBRemote::DoDestroy ()
+{
+    Error error;
+    Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS);
+    if (log)
+        log->Printf ("ProcessGDBRemote::DoDestroy()");
+
+    // Interrupt if our inferior is running...
+    m_gdb_comm.SendInterrupt (1);
+    DisableAllBreakpointSites ();
+    SetExitStatus(-1, "process killed");
+
+    StringExtractorGDBRemote response;
+    if (m_gdb_comm.SendPacketAndWaitForResponse("k", response, 2, false))
+    {
+        if (log)
+        {
+            if (response.IsOKPacket())
+                log->Printf ("ProcessGDBRemote::DoDestroy() kill was successful");
+            else
+                log->Printf ("ProcessGDBRemote::DoDestroy() kill failed: %s", response.GetStringRef().c_str());
+        }
+    }
+
+    StopAsyncThread ();
+    m_gdb_comm.StopReadThread();
+    KillDebugserverProcess ();
+    return error;
+}
+
+ByteOrder
+ProcessGDBRemote::GetByteOrder () const
+{
+    return m_byte_order;
+}
+
+//------------------------------------------------------------------
+// Process Queries
+//------------------------------------------------------------------
+
+bool
+ProcessGDBRemote::IsAlive ()
+{
+    return m_gdb_comm.IsConnected();
+}
+
+addr_t
+ProcessGDBRemote::GetImageInfoAddress()
+{
+    if (!m_gdb_comm.IsRunning())
+    {
+        StringExtractorGDBRemote response;
+        if (m_gdb_comm.SendPacketAndWaitForResponse("qShlibInfoAddr", ::strlen ("qShlibInfoAddr"), response, 2, false))
+        {
+            if (response.IsNormalPacket())
+                return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
+        }
+    }
+    return LLDB_INVALID_ADDRESS;
+}
+
+DynamicLoader *
+ProcessGDBRemote::GetDynamicLoader()
+{
+    return m_dynamic_loader_ap.get();
+}
+
+//------------------------------------------------------------------
+// Process Memory
+//------------------------------------------------------------------
+size_t
+ProcessGDBRemote::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error)
+{
+    if (size > m_max_memory_size)
+    {
+        // Keep memory read sizes down to a sane limit. This function will be
+        // called multiple times in order to complete the task by 
+        // lldb_private::Process so it is ok to do this.
+        size = m_max_memory_size;
+    }
+
+    char packet[64];
+    const int packet_len = ::snprintf (packet, sizeof(packet), "m%llx,%zx", (uint64_t)addr, size);
+    assert (packet_len + 1 < sizeof(packet));
+    StringExtractorGDBRemote response;
+    if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, 2, true))
+    {
+        if (response.IsNormalPacket())
+        {
+            error.Clear();
+            return response.GetHexBytes(buf, size, '\xdd');
+        }
+        else if (response.IsErrorPacket())
+            error.SetErrorStringWithFormat("gdb remote returned an error: %s", response.GetStringRef().c_str());
+        else if (response.IsUnsupportedPacket())
+            error.SetErrorStringWithFormat("'%s' packet unsupported", packet);
+        else
+            error.SetErrorStringWithFormat("unexpected response to '%s': '%s'", packet, response.GetStringRef().c_str());
+    }
+    else
+    {
+        error.SetErrorStringWithFormat("failed to sent packet: '%s'", packet);
+    }
+    return 0;
+}
+
+size_t
+ProcessGDBRemote::DoWriteMemory (addr_t addr, const void *buf, size_t size, Error &error)
+{
+    StreamString packet;
+    packet.Printf("M%llx,%zx:", addr, size);
+    packet.PutBytesAsRawHex8(buf, size, eByteOrderHost, eByteOrderHost);
+    StringExtractorGDBRemote response;
+    if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, 2, true))
+    {
+        if (response.IsOKPacket())
+        {
+            error.Clear();
+            return size;
+        }
+        else if (response.IsErrorPacket())
+            error.SetErrorStringWithFormat("gdb remote returned an error: %s", response.GetStringRef().c_str());
+        else if (response.IsUnsupportedPacket())
+            error.SetErrorStringWithFormat("'%s' packet unsupported", packet.GetString().c_str());
+        else
+            error.SetErrorStringWithFormat("unexpected response to '%s': '%s'", packet.GetString().c_str(), response.GetStringRef().c_str());
+    }
+    else
+    {
+        error.SetErrorStringWithFormat("failed to sent packet: '%s'", packet.GetString().c_str());
+    }
+    return 0;
+}
+
+lldb::addr_t
+ProcessGDBRemote::DoAllocateMemory (size_t size, uint32_t permissions, Error &error)
+{
+    addr_t allocated_addr = m_gdb_comm.AllocateMemory (size, permissions, m_packet_timeout);
+    if (allocated_addr == LLDB_INVALID_ADDRESS)
+        error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %u", size, permissions);
+    else
+        error.Clear();
+    return allocated_addr;
+}
+
+Error
+ProcessGDBRemote::DoDeallocateMemory (lldb::addr_t addr)
+{
+    Error error; 
+    if (!m_gdb_comm.DeallocateMemory (addr, m_packet_timeout))
+        error.SetErrorStringWithFormat("unable to deallocate memory at 0x%llx", addr);
+    return error;
+}
+
+
+//------------------------------------------------------------------
+// Process STDIO
+//------------------------------------------------------------------
+
+size_t
+ProcessGDBRemote::GetSTDOUT (char *buf, size_t buf_size, Error &error)
+{
+    Mutex::Locker locker(m_stdio_mutex);
+    size_t bytes_available = m_stdout_data.size();
+    if (bytes_available > 0)
+    {
+        ProcessGDBRemoteLog::LogIf (GDBR_LOG_PROCESS, "ProcessGDBRemote::%s (&%p[%u]) ...", __FUNCTION__, buf, buf_size);
+        if (bytes_available > buf_size)
+        {
+            memcpy(buf, m_stdout_data.data(), buf_size);
+            m_stdout_data.erase(0, buf_size);
+            bytes_available = buf_size;
+        }
+        else
+        {
+            memcpy(buf, m_stdout_data.data(), bytes_available);
+            m_stdout_data.clear();
+
+            //ResetEventBits(eBroadcastBitSTDOUT);
+        }
+    }
+    return bytes_available;
+}
+
+size_t
+ProcessGDBRemote::GetSTDERR (char *buf, size_t buf_size, Error &error)
+{
+    // Can we get STDERR through the remote protocol?
+    return 0;
+}
+
+size_t
+ProcessGDBRemote::PutSTDIN (const char *src, size_t src_len, Error &error)
+{
+    if (m_stdio_communication.IsConnected())
+    {
+        ConnectionStatus status;
+        m_stdio_communication.Write(src, src_len, status, NULL);
+    }
+    return 0;
+}
+
+Error
+ProcessGDBRemote::EnableBreakpoint (BreakpointSite *bp_site)
+{
+    Error error;
+    assert (bp_site != NULL);
+
+    Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS);
+    user_id_t site_id = bp_site->GetID();
+    const addr_t addr = bp_site->GetLoadAddress();
+    if (log)
+        log->Printf ("ProcessGDBRemote::EnableBreakpoint (size_id = %d) address = 0x%llx", site_id, (uint64_t)addr);
+
+    if (bp_site->IsEnabled())
+    {
+        if (log)
+            log->Printf ("ProcessGDBRemote::EnableBreakpoint (size_id = %d) address = 0x%llx -- SUCCESS (already enabled)", site_id, (uint64_t)addr);
+        return error;
+    }
+    else
+    {
+        const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site);
+
+        if (bp_site->HardwarePreferred())
+        {
+            // Try and set hardware breakpoint, and if that fails, fall through
+            // and set a software breakpoint?
+        }
+
+        if (m_z0_supported)
+        {
+            char packet[64];
+            const int packet_len = ::snprintf (packet, sizeof(packet), "Z0,%llx,%zx", addr, bp_op_size);
+            assert (packet_len + 1 < sizeof(packet));
+            StringExtractorGDBRemote response;
+            if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, 2, true))
+            {
+                if (response.IsUnsupportedPacket())
+                {
+                    // Disable z packet support and try again
+                    m_z0_supported = 0;
+                    return EnableBreakpoint (bp_site);
+                }
+                else if (response.IsOKPacket())
+                {
+                    bp_site->SetEnabled(true);
+                    bp_site->SetType (BreakpointSite::eExternal);
+                    return error;
+                }
+                else
+                {
+                    uint8_t error_byte = response.GetError();
+                    if (error_byte)
+                        error.SetErrorStringWithFormat("%x packet failed with error: %i (0x%2.2x).\n", packet, error_byte, error_byte);
+                }
+            }
+        }
+        else
+        {
+            return EnableSoftwareBreakpoint (bp_site);
+        }
+    }
+
+    if (log)
+    {
+        const char *err_string = error.AsCString();
+        log->Printf ("ProcessGDBRemote::EnableBreakpoint() error for breakpoint at 0x%8.8llx: %s",
+                     bp_site->GetLoadAddress(),
+                     err_string ? err_string : "NULL");
+    }
+    // We shouldn't reach here on a successful breakpoint enable...
+    if (error.Success())
+        error.SetErrorToGenericError();
+    return error;
+}
+
+Error
+ProcessGDBRemote::DisableBreakpoint (BreakpointSite *bp_site)
+{
+    Error error;
+    assert (bp_site != NULL);
+    addr_t addr = bp_site->GetLoadAddress();
+    user_id_t site_id = bp_site->GetID();
+    Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS);
+    if (log)
+        log->Printf ("ProcessGDBRemote::DisableBreakpoint (site_id = %d) addr = 0x%8.8llx", site_id, (uint64_t)addr);
+
+    if (bp_site->IsEnabled())
+    {
+        const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site);
+
+        if (bp_site->IsHardware())
+        {
+            // TODO: disable hardware breakpoint...
+        }
+        else
+        {
+            if (m_z0_supported)
+            {
+                char packet[64];
+                const int packet_len = ::snprintf (packet, sizeof(packet), "z0,%llx,%zx", addr, bp_op_size);
+                assert (packet_len + 1 < sizeof(packet));
+                StringExtractorGDBRemote response;
+                if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, 2, true))
+                {
+                    if (response.IsUnsupportedPacket())
+                    {
+                        error.SetErrorString("Breakpoint site was set with Z packet, yet remote debugserver states z packets are not supported.");
+                    }
+                    else if (response.IsOKPacket())
+                    {
+                        if (log)
+                            log->Printf ("ProcessGDBRemote::DisableBreakpoint (site_id = %d) addr = 0x%8.8llx -- SUCCESS", site_id, (uint64_t)addr);
+                        bp_site->SetEnabled(false);
+                        return error;
+                    }
+                    else
+                    {
+                        uint8_t error_byte = response.GetError();
+                        if (error_byte)
+                            error.SetErrorStringWithFormat("%x packet failed with error: %i (0x%2.2x).\n", packet, error_byte, error_byte);
+                    }
+                }
+            }
+            else
+            {
+                return DisableSoftwareBreakpoint (bp_site);
+            }
+        }
+    }
+    else
+    {
+        if (log)
+            log->Printf ("ProcessGDBRemote::DisableBreakpoint (site_id = %d) addr = 0x%8.8llx -- SUCCESS (already disabled)", site_id, (uint64_t)addr);
+        return error;
+    }
+
+    if (error.Success())
+        error.SetErrorToGenericError();
+    return error;
+}
+
+Error
+ProcessGDBRemote::EnableWatchpoint (WatchpointLocation *wp)
+{
+    Error error;
+    if (wp)
+    {
+        user_id_t watchID = wp->GetID();
+        addr_t addr = wp->GetLoadAddress();
+        Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS);
+        if (log)
+            log->Printf ("ProcessGDBRemote::EnableWatchpoint(watchID = %d)", watchID);
+        if (wp->IsEnabled())
+        {
+            if (log)
+                log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %d) addr = 0x%8.8llx: watchpoint already enabled.", watchID, (uint64_t)addr);
+            return error;
+        }
+        else
+        {
+            // Pass down an appropriate z/Z packet...
+            error.SetErrorString("watchpoints not supported");
+        }
+    }
+    else
+    {
+        error.SetErrorString("Watchpoint location argument was NULL.");
+    }
+    if (error.Success())
+        error.SetErrorToGenericError();
+    return error;
+}
+
+Error
+ProcessGDBRemote::DisableWatchpoint (WatchpointLocation *wp)
+{
+    Error error;
+    if (wp)
+    {
+        user_id_t watchID = wp->GetID();
+
+        Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS);
+
+        addr_t addr = wp->GetLoadAddress();
+        if (log)
+            log->Printf ("ProcessGDBRemote::DisableWatchpoint (watchID = %d) addr = 0x%8.8llx", watchID, (uint64_t)addr);
+
+        if (wp->IsHardware())
+        {
+            // Pass down an appropriate z/Z packet...
+            error.SetErrorString("watchpoints not supported");
+        }
+        // TODO: clear software watchpoints if we implement them
+    }
+    else
+    {
+        error.SetErrorString("Watchpoint location argument was NULL.");
+    }
+    if (error.Success())
+        error.SetErrorToGenericError();
+    return error;
+}
+
+void
+ProcessGDBRemote::Clear()
+{
+    m_flags = 0;
+    m_thread_list.Clear();
+    {
+        Mutex::Locker locker(m_stdio_mutex);
+        m_stdout_data.clear();
+    }
+    DestoryLibUnwindAddressSpace();
+}
+
+Error
+ProcessGDBRemote::DoSignal (int signo)
+{
+    Error error;
+    Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS);
+    if (log)
+        log->Printf ("ProcessGDBRemote::DoSignal (signal = %d)", signo);
+
+    if (!m_gdb_comm.SendAsyncSignal (signo))
+        error.SetErrorStringWithFormat("failed to send signal %i", signo);
+    return error;
+}
+
+
+Error
+ProcessGDBRemote::DoDetach()
+{
+    Error error;
+    Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS);
+    if (log)
+        log->Printf ("ProcessGDBRemote::DoDetach()");
+
+    //    if (DoSIGSTOP (true))
+    //    {
+    //        CloseChildFileDescriptors ();
+    //
+    //        // Scope for "locker" so we can reply to all of our exceptions (the SIGSTOP
+    //        // exception).
+    //        {
+    //            Mutex::Locker locker(m_exception_messages_mutex);
+    //            ReplyToAllExceptions();
+    //        }
+    //
+    //        // Shut down the exception thread and cleanup our exception remappings
+    //        Task().ShutDownExceptionThread();
+    //
+    //        pid_t pid = GetID();
+    //
+    //        // Detach from our process while we are stopped.
+    //        errno = 0;
+    //
+    //        // Detach from our process
+    //        ::ptrace (PT_DETACH, pid, (caddr_t)1, 0);
+    //
+    //        error.SetErrorToErrno();
+    //
+    //        if (log || error.Fail())
+    //            error.PutToLog(log, "::ptrace (PT_DETACH, %u, (caddr_t)1, 0)", pid);
+    //
+    //        // Resume our task
+    //        Task().Resume();
+    //
+    //        // NULL our task out as we have already retored all exception ports
+    //        Task().Clear();
+    //
+    //        // Clear out any notion of the process we once were
+    //        Clear();
+    //
+    //        SetPrivateState (eStateDetached);
+    //        return true;
+    //    }
+    return error;
+}
+
+void
+ProcessGDBRemote::STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len)
+{
+    ProcessGDBRemote *process = (ProcessGDBRemote *)baton;
+    process->AppendSTDOUT(static_cast<const char *>(src), src_len);
+}
+
+void
+ProcessGDBRemote::AppendSTDOUT (const char* s, size_t len)
+{
+    ProcessGDBRemoteLog::LogIf (GDBR_LOG_PROCESS, "ProcessGDBRemote::%s (<%d> %s) ...", __FUNCTION__, len, s);
+    Mutex::Locker locker(m_stdio_mutex);
+    m_stdout_data.append(s, len);
+
+    // FIXME: Make a real data object for this and put it out.
+    BroadcastEventIfUnique (eBroadcastBitSTDOUT);
+}
+
+
+Error
+ProcessGDBRemote::StartDebugserverProcess
+(
+    const char *debugserver_url,    // The connection string to use in the spawned debugserver ("localhost:1234" or "/dev/tty...")
+    char const *inferior_argv[],    // Arguments for the inferior program including the path to the inferior itself as the first argument
+    char const *inferior_envp[],    // Environment to pass along to the inferior program
+    char const *stdio_path,
+    lldb::pid_t attach_pid,         // If inferior inferior_argv == NULL, and attach_pid != LLDB_INVALID_PROCESS_ID then attach to this attach_pid
+    const char *attach_name,        // Wait for the next process to launch whose basename matches "attach_name"
+    bool wait_for_launch,           // Wait for the process named "attach_name" to launch
+    ArchSpec& inferior_arch         // The arch of the inferior that we will launch
+)
+{
+    Error error;
+    if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID)
+    {
+        // If we locate debugserver, keep that located version around
+        static FileSpec g_debugserver_file_spec;
+
+        FileSpec debugserver_file_spec;
+        char debugserver_path[PATH_MAX];
+
+        // Always check to see if we have an environment override for the path
+        // to the debugserver to use and use it if we do.
+        const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
+        if (env_debugserver_path)
+            debugserver_file_spec.SetFile (env_debugserver_path);
+        else
+            debugserver_file_spec = g_debugserver_file_spec;
+        bool debugserver_exists = debugserver_file_spec.Exists();
+        if (!debugserver_exists)
+        {
+            // The debugserver binary is in the LLDB.framework/Resources
+            // directory. 
+            FileSpec framework_file_spec (Host::GetModuleFileSpecForHostAddress ((void *)lldb_private::Initialize));
+            const char *framework_dir = framework_file_spec.GetDirectory().AsCString();
+            const char *lldb_framework = ::strstr (framework_dir, "/LLDB.framework");
+
+            if (lldb_framework)
+            {
+                int len = lldb_framework - framework_dir + strlen ("/LLDB.framework");
+                ::snprintf (debugserver_path,
+                            sizeof(debugserver_path),
+                            "%.*s/Resources/%s",
+                            len,
+                            framework_dir,
+                            DEBUGSERVER_BASENAME);
+                debugserver_file_spec.SetFile (debugserver_path);
+                debugserver_exists = debugserver_file_spec.Exists();
+            }
+
+            if (debugserver_exists)
+            {
+                g_debugserver_file_spec = debugserver_file_spec;
+            }
+            else
+            {
+                g_debugserver_file_spec.Clear();
+                debugserver_file_spec.Clear();
+            }
+        }
+
+        if (debugserver_exists)
+        {
+            debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path));
+
+            m_stdio_communication.Clear();
+            posix_spawnattr_t attr;
+
+            Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS);
+
+            Error local_err;    // Errors that don't affect the spawning.
+            if (log)
+                log->Printf ("%s ( path='%s', argv=%p, envp=%p, arch=%s )", __FUNCTION__, debugserver_path, inferior_argv, inferior_envp, inferior_arch.AsCString());
+            error.SetError( ::posix_spawnattr_init (&attr), eErrorTypePOSIX);
+            if (error.Fail() || log)
+                error.PutToLog(log, "::posix_spawnattr_init ( &attr )");
+            if (error.Fail())
+                return error;;
+
+#if !defined (__arm__)
+
+            // We don't need to do this for ARM, and we really shouldn't now that we
+            // have multiple CPU subtypes and no posix_spawnattr call that allows us
+            // to set which CPU subtype to launch...
+            cpu_type_t cpu = inferior_arch.GetCPUType();
+            if (cpu != 0 && cpu != CPU_TYPE_ANY && cpu != LLDB_INVALID_CPUTYPE)
+            {
+                size_t ocount = 0;
+                error.SetError( ::posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &ocount), eErrorTypePOSIX);
+                if (error.Fail() || log)
+                    error.PutToLog(log, "::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = 0x%8.8x, count => %zu )", cpu, ocount);
+
+                if (error.Fail() != 0 || ocount != 1)
+                    return error;
+            }
+
+#endif
+
+            Args debugserver_args;
+            char arg_cstr[PATH_MAX];
+            bool launch_process = true;
+
+            if (inferior_argv == NULL && attach_pid != LLDB_INVALID_PROCESS_ID)
+                launch_process = false;
+            else if (attach_name)
+                launch_process = false; // Wait for a process whose basename matches that in inferior_argv[0]
+
+            bool pass_stdio_path_to_debugserver = true;
+            lldb_utility::PseudoTerminal pty;
+            if (stdio_path == NULL)
+            {
+                pass_stdio_path_to_debugserver = false;
+                if (pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, NULL, 0))
+                {
+                    struct termios stdin_termios;
+                    if (::tcgetattr (pty.GetMasterFileDescriptor(), &stdin_termios) == 0)
+                    {
+                        stdin_termios.c_lflag &= ~ECHO;     // Turn off echoing
+                        stdin_termios.c_lflag &= ~ICANON;   // Get one char at a time
+                        ::tcsetattr (pty.GetMasterFileDescriptor(), TCSANOW, &stdin_termios);
+                    }
+                    stdio_path = pty.GetSlaveName (NULL, 0);
+                }
+            }
+
+            // Start args with "debugserver /file/path -r --"
+            debugserver_args.AppendArgument(debugserver_path);
+            debugserver_args.AppendArgument(debugserver_url);
+            debugserver_args.AppendArgument("--native-regs");   // use native registers, not the GDB registers
+            debugserver_args.AppendArgument("--setsid");        // make debugserver run in its own session so
+                                                        // signals generated by special terminal key
+                                                        // sequences (^C) don't affect debugserver
+
+            // Only set the inferior
+            if (launch_process)
+            {
+                if (stdio_path && pass_stdio_path_to_debugserver)
+                {
+                    debugserver_args.AppendArgument("-s");    // short for --stdio-path
+                    StreamString strm;
+                    strm.Printf("'%s'", stdio_path);
+                    debugserver_args.AppendArgument(strm.GetData());    // path to file to have inferior open as it's STDIO
+                }
+            }
+
+            const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
+            if (env_debugserver_log_file)
+            {
+                ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-file=%s", env_debugserver_log_file);
+                debugserver_args.AppendArgument(arg_cstr);
+            }
+
+            const char *env_debugserver_log_flags = getenv("LLDB_DEBUGSERVER_LOG_FLAGS");
+            if (env_debugserver_log_flags)
+            {
+                ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags);
+                debugserver_args.AppendArgument(arg_cstr);
+            }
+//            debugserver_args.AppendArgument("--log-file=/tmp/debugserver.txt");
+//            debugserver_args.AppendArgument("--log-flags=0x800e0e");
+
+            // Now append the program arguments
+            if (launch_process)
+            {
+                if (inferior_argv)
+                {
+                    // Terminate the debugserver args so we can now append the inferior args
+                    debugserver_args.AppendArgument("--");
+
+                    for (int i = 0; inferior_argv[i] != NULL; ++i)
+                        debugserver_args.AppendArgument (inferior_argv[i]);
+                }
+                else
+                {
+                    // Will send environment entries with the 'QEnvironment:' packet
+                    // Will send arguments with the 'A' packet
+                }
+            }
+            else if (attach_pid != LLDB_INVALID_PROCESS_ID)
+            {
+                ::snprintf (arg_cstr, sizeof(arg_cstr), "--attach=%u", attach_pid);
+                debugserver_args.AppendArgument (arg_cstr);
+            }
+            else if (attach_name && attach_name[0])
+            {
+                if (wait_for_launch)
+                    debugserver_args.AppendArgument ("--waitfor");
+                else
+                    debugserver_args.AppendArgument ("--attach");
+                debugserver_args.AppendArgument (attach_name);
+            }
+
+            Error file_actions_err;
+            posix_spawn_file_actions_t file_actions;
+#if DONT_CLOSE_DEBUGSERVER_STDIO
+            file_actions_err.SetErrorString ("Remove this after uncommenting the code block below.");
+#else
+            file_actions_err.SetError( ::posix_spawn_file_actions_init (&file_actions), eErrorTypePOSIX);
+            if (file_actions_err.Success())
+            {
+                ::posix_spawn_file_actions_addclose (&file_actions, STDIN_FILENO);
+                ::posix_spawn_file_actions_addclose (&file_actions, STDOUT_FILENO);
+                ::posix_spawn_file_actions_addclose (&file_actions, STDERR_FILENO);
+            }
+#endif
+
+            if (log)
+            {
+                StreamString strm;
+                debugserver_args.Dump (&strm);
+                log->Printf("%s arguments:\n%s", debugserver_args.GetArgumentAtIndex(0), strm.GetData());
+            }
+
+            error.SetError(::posix_spawnp (&m_debugserver_pid,
+                                             debugserver_path,
+                                             file_actions_err.Success() ? &file_actions : NULL,
+                                             &attr,
+                                             debugserver_args.GetArgumentVector(),
+                                             (char * const*)inferior_envp),
+                             eErrorTypePOSIX);
+
+            if (file_actions_err.Success())
+                ::posix_spawn_file_actions_destroy (&file_actions);
+
+            // We have seen some cases where posix_spawnp was returning a valid
+            // looking pid even when an error was returned, so clear it out
+            if (error.Fail())
+                m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
+
+            if (error.Fail() || log)
+                error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", m_debugserver_pid, debugserver_path, NULL, &attr, inferior_argv, inferior_envp);
+
+//            if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
+//            {
+//                std::auto_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor (pty.ReleaseMasterFileDescriptor(), true));
+//                if (conn_ap.get())
+//                {
+//                    m_stdio_communication.SetConnection(conn_ap.release());
+//                    if (m_stdio_communication.IsConnected())
+//                    {
+//                        m_stdio_communication.SetReadThreadBytesReceivedCallback (STDIOReadThreadBytesReceived, this);
+//                        m_stdio_communication.StartReadThread();
+//                    }
+//                }
+//            }
+        }
+        else
+        {
+            error.SetErrorStringWithFormat ("Unable to locate " DEBUGSERVER_BASENAME ".\n");
+        }
+
+        if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
+            StartAsyncThread ();
+    }
+    return error;
+}
+
+bool
+ProcessGDBRemote::MonitorDebugserverProcess
+(
+    void *callback_baton,
+    lldb::pid_t debugserver_pid,
+    int signo,          // Zero for no signal
+    int exit_status     // Exit value of process if signal is zero
+)
+{
+    // We pass in the ProcessGDBRemote inferior process it and name it
+    // "gdb_remote_pid". The process ID is passed in the "callback_baton"
+    // pointer value itself, thus we need the double cast...
+
+    // "debugserver_pid" argument passed in is the process ID for
+    // debugserver that we are tracking...
+
+    lldb::pid_t gdb_remote_pid = (lldb::pid_t)(intptr_t)callback_baton;
+    TargetSP target_sp(Debugger::GetSharedInstance().GetTargetList().FindTargetWithProcessID (gdb_remote_pid));
+    if (target_sp)
+    {
+        ProcessSP process_sp (target_sp->GetProcessSP());
+        if (process_sp)
+        {
+            // Sleep for a half a second to make sure our inferior process has
+            // time to set its exit status before we set it incorrectly when
+            // both the debugserver and the inferior process shut down.
+            usleep (500000);
+            // If our process hasn't yet exited, debugserver might have died.
+            // If the process did exit, the we are reaping it.
+            if (process_sp->GetState() != eStateExited)
+            {
+                char error_str[1024];
+                if (signo)
+                {
+                    const char *signal_cstr = process_sp->GetUnixSignals().GetSignalAsCString (signo);
+                    if (signal_cstr)
+                        ::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with signal %s", signal_cstr);
+                    else
+                        ::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with signal %i", signo);
+                }
+                else
+                {
+                    ::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with an exit status of 0x%8.8x", exit_status);
+                }
+
+                process_sp->SetExitStatus (-1, error_str);
+            }
+            else
+            {
+                ProcessGDBRemote *gdb_process = (ProcessGDBRemote *)process_sp.get();
+                // Debugserver has exited we need to let our ProcessGDBRemote
+                // know that it no longer has a debugserver instance
+                gdb_process->m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
+                // We are returning true to this function below, so we can
+                // forget about the monitor handle.
+                gdb_process->m_debugserver_monitor = 0;
+            }
+        }
+    }
+    return true;
+}
+
+void
+ProcessGDBRemote::KillDebugserverProcess ()
+{
+    if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
+    {
+        ::kill (m_debugserver_pid, SIGINT);
+        m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
+    }
+}
+
+void
+ProcessGDBRemote::Initialize()
+{
+    static bool g_initialized = false;
+
+    if (g_initialized == false)
+    {
+        g_initialized = true;
+        PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                       GetPluginDescriptionStatic(),
+                                       CreateInstance);
+
+        Log::Callbacks log_callbacks = {
+            ProcessGDBRemoteLog::DisableLog,
+            ProcessGDBRemoteLog::EnableLog,
+            ProcessGDBRemoteLog::ListLogCategories
+        };
+
+        Log::RegisterLogChannel (ProcessGDBRemote::GetPluginNameStatic(), log_callbacks);
+    }
+}
+
+bool
+ProcessGDBRemote::SetCurrentGDBRemoteThread (int tid)
+{
+    if (m_curr_tid == tid)
+        return true;
+
+    char packet[32];
+    const int packet_len = ::snprintf (packet, sizeof(packet), "Hg%x", tid);
+    assert (packet_len + 1 < sizeof(packet));
+    StringExtractorGDBRemote response;
+    if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, 2, false))
+    {
+        if (response.IsOKPacket())
+        {
+            m_curr_tid = tid;
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+ProcessGDBRemote::SetCurrentGDBRemoteThreadForRun (int tid)
+{
+    if (m_curr_tid_run == tid)
+        return true;
+
+    char packet[32];
+    const int packet_len = ::snprintf (packet, sizeof(packet), "Hg%x", tid);
+    assert (packet_len + 1 < sizeof(packet));
+    StringExtractorGDBRemote response;
+    if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, 2, false))
+    {
+        if (response.IsOKPacket())
+        {
+            m_curr_tid_run = tid;
+            return true;
+        }
+    }
+    return false;
+}
+
+void
+ProcessGDBRemote::ResetGDBRemoteState ()
+{
+    // Reset and GDB remote state
+    m_curr_tid = LLDB_INVALID_THREAD_ID;
+    m_curr_tid_run = LLDB_INVALID_THREAD_ID;
+    m_z0_supported = 1;
+}
+
+
+bool
+ProcessGDBRemote::StartAsyncThread ()
+{
+    ResetGDBRemoteState ();
+
+    Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS);
+
+    if (log)
+        log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__);
+
+    // Create a thread that watches our internal state and controls which
+    // events make it to clients (into the DCProcess event queue).
+    m_async_thread = Host::ThreadCreate ("<lldb.process.gdb-remote.async>", ProcessGDBRemote::AsyncThread, this, NULL);
+    return m_async_thread != LLDB_INVALID_HOST_THREAD;
+}
+
+void
+ProcessGDBRemote::StopAsyncThread ()
+{
+    Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS);
+
+    if (log)
+        log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__);
+
+    m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit);
+
+    // Stop the stdio thread
+    if (m_async_thread != LLDB_INVALID_HOST_THREAD)
+    {
+        Host::ThreadJoin (m_async_thread, NULL, NULL);
+    }
+}
+
+
+void *
+ProcessGDBRemote::AsyncThread (void *arg)
+{
+    ProcessGDBRemote *process = (ProcessGDBRemote*) arg;
+
+    Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS);
+    if (log)
+        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID());
+
+    Listener listener ("ProcessGDBRemote::AsyncThread");
+    EventSP event_sp;
+    const uint32_t desired_event_mask = eBroadcastBitAsyncContinue |
+                                        eBroadcastBitAsyncThreadShouldExit;
+
+    if (listener.StartListeningForEvents (&process->m_async_broadcaster, desired_event_mask) == desired_event_mask)
+    {
+        bool done = false;
+        while (!done)
+        {
+            if (log)
+                log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID());
+            if (listener.WaitForEvent (NULL, event_sp))
+            {
+                const uint32_t event_type = event_sp->GetType();
+                switch (event_type)
+                {
+                    case eBroadcastBitAsyncContinue:
+                        {
+                            const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get());
+
+                            if (continue_packet)
+                            {
+                                const char *continue_cstr = (const char *)continue_packet->GetBytes ();
+                                const size_t continue_cstr_len = continue_packet->GetByteSize ();
+                                if (log)
+                                    log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr);
+
+                                process->SetPrivateState(eStateRunning);
+                                StringExtractorGDBRemote response;
+                                StateType stop_state = process->GetGDBRemote().SendContinuePacketAndWaitForResponse (process, continue_cstr, continue_cstr_len, response);
+
+                                switch (stop_state)
+                                {
+                                case eStateStopped:
+                                case eStateCrashed:
+                                case eStateSuspended:
+                                    process->m_last_stop_packet = response;
+                                    process->m_last_stop_packet.SetFilePos (0);
+                                    process->SetPrivateState (stop_state);
+                                    break;
+
+                                case eStateExited:
+                                    process->m_last_stop_packet = response;
+                                    process->m_last_stop_packet.SetFilePos (0);
+                                    response.SetFilePos(1);
+                                    process->SetExitStatus(response.GetHexU8(), NULL);
+                                    done = true;
+                                    break;
+
+                                case eStateInvalid:
+                                    break;
+
+                                default:
+                                    process->SetPrivateState (stop_state);
+                                    break;
+                                }
+                            }
+                        }
+                        break;
+
+                    case eBroadcastBitAsyncThreadShouldExit:
+                        if (log)
+                            log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) got eBroadcastBitAsyncThreadShouldExit...", __FUNCTION__, arg, process->GetID());
+                        done = true;
+                        break;
+
+                    default:
+                        if (log)
+                            log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type);
+                        done = true;
+                        break;
+                }
+            }
+            else
+            {
+                if (log)
+                    log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID());
+                done = true;
+            }
+        }
+    }
+
+    if (log)
+        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, arg, process->GetID());
+
+    process->m_async_thread = LLDB_INVALID_HOST_THREAD;
+    return NULL;
+}
+
+lldb_private::unw_addr_space_t
+ProcessGDBRemote::GetLibUnwindAddressSpace ()
+{
+    unw_targettype_t target_type = UNW_TARGET_UNSPECIFIED;
+    if (m_target.GetArchitecture().GetCPUType() == CPU_TYPE_I386)
+        target_type = UNW_TARGET_I386;
+    if (m_target.GetArchitecture().GetCPUType() == CPU_TYPE_X86_64)
+        target_type = UNW_TARGET_X86_64;
+
+    if (m_libunwind_addr_space)
+    {
+        if (m_libunwind_target_type != target_type)
+            DestoryLibUnwindAddressSpace();
+        else
+            return m_libunwind_addr_space;
+    }
+    unw_accessors_t callbacks = get_macosx_libunwind_callbacks ();
+    m_libunwind_addr_space = unw_create_addr_space (&callbacks, target_type);
+    if (m_libunwind_addr_space)
+        m_libunwind_target_type = target_type;
+    else
+        m_libunwind_target_type = UNW_TARGET_UNSPECIFIED;
+    return m_libunwind_addr_space;
+}
+
+void
+ProcessGDBRemote::DestoryLibUnwindAddressSpace ()
+{
+    if (m_libunwind_addr_space)
+    {
+        unw_destroy_addr_space (m_libunwind_addr_space);
+        m_libunwind_addr_space = NULL;
+    }
+    m_libunwind_target_type = UNW_TARGET_UNSPECIFIED;
+}
+
+
+const char *
+ProcessGDBRemote::GetDispatchQueueNameForThread
+(
+    addr_t thread_dispatch_qaddr,
+    std::string &dispatch_queue_name
+)
+{
+    dispatch_queue_name.clear();
+    if (thread_dispatch_qaddr != 0 && thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
+    {
+        // Cache the dispatch_queue_offsets_addr value so we don't always have
+        // to look it up
+        if (m_dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS)
+        {
+            ModuleSP module_sp(GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libSystem.B.dylib")));
+            if (module_sp.get() == NULL)
+                return NULL;
+
+            const Symbol *dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (ConstString("dispatch_queue_offsets"), eSymbolTypeData);
+            if (dispatch_queue_offsets_symbol)
+                m_dispatch_queue_offsets_addr = dispatch_queue_offsets_symbol->GetValue().GetLoadAddress(this);
+
+            if (m_dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS)
+                return NULL;
+        }
+
+        uint8_t memory_buffer[8];
+        DataExtractor data(memory_buffer, sizeof(memory_buffer), GetByteOrder(), GetAddressByteSize());
+
+        // Excerpt from src/queue_private.h
+        struct dispatch_queue_offsets_s
+        {
+            uint16_t dqo_version;
+            uint16_t dqo_label;
+            uint16_t dqo_label_size;
+        } dispatch_queue_offsets;
+
+
+        Error error;
+        if (ReadMemory (m_dispatch_queue_offsets_addr, memory_buffer, sizeof(dispatch_queue_offsets), error) == sizeof(dispatch_queue_offsets))
+        {
+            uint32_t data_offset = 0;
+            if (data.GetU16(&data_offset, &dispatch_queue_offsets.dqo_version, sizeof(dispatch_queue_offsets)/sizeof(uint16_t)))
+            {
+                if (ReadMemory (thread_dispatch_qaddr, &memory_buffer, data.GetAddressByteSize(), error) == data.GetAddressByteSize())
+                {
+                    data_offset = 0;
+                    lldb::addr_t queue_addr = data.GetAddress(&data_offset);
+                    lldb::addr_t label_addr = queue_addr + dispatch_queue_offsets.dqo_label;
+                    dispatch_queue_name.resize(dispatch_queue_offsets.dqo_label_size, '\0');
+                    size_t bytes_read = ReadMemory (label_addr, &dispatch_queue_name[0], dispatch_queue_offsets.dqo_label_size, error);
+                    if (bytes_read < dispatch_queue_offsets.dqo_label_size)
+                        dispatch_queue_name.erase (bytes_read);
+                }
+            }
+        }
+    }
+    if (dispatch_queue_name.empty())
+        return NULL;
+    return dispatch_queue_name.c_str();
+}
+
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
new file mode 100644
index 0000000..cd5bab0
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -0,0 +1,404 @@
+//===-- ProcessGDBRemote.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_ProcessGDBRemote_h_
+#define liblldb_ProcessGDBRemote_h_
+
+// C Includes
+
+// C++ Includes
+#include <list>
+
+// Other libraries and framework includes
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Broadcaster.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/InputReader.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ThreadSafeValue.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+
+#include "GDBRemoteCommunication.h"
+#include "StringExtractor.h"
+#include "GDBRemoteRegisterContext.h"
+#include "libunwind.h"
+
+class ThreadGDBRemote;
+
+class ProcessGDBRemote : public lldb_private::Process
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    static Process*
+    CreateInstance (lldb_private::Target& target, lldb_private::Listener &listener);
+
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static const char *
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    ProcessGDBRemote(lldb_private::Target& target, lldb_private::Listener &listener);
+
+    virtual
+    ~ProcessGDBRemote();
+
+    //------------------------------------------------------------------
+    // Check if a given Process
+    //------------------------------------------------------------------
+    virtual bool
+    CanDebug (lldb_private::Target &target);
+
+    //------------------------------------------------------------------
+    // Creating a new process, or attaching to an existing one
+    //------------------------------------------------------------------
+    virtual lldb_private::Error
+    WillLaunch (lldb_private::Module* module);
+
+    virtual lldb_private::Error
+    DoLaunch (lldb_private::Module* module,
+              char const *argv[],           // Can be NULL
+              char const *envp[],           // Can be NULL
+              const char *stdin_path,       // Can be NULL
+              const char *stdout_path,  // Can be NULL
+              const char *stderr_path); // Can be NULL
+
+    virtual void
+    DidLaunch ();
+
+    virtual lldb_private::Error
+    WillAttach (lldb::pid_t pid);
+
+    virtual lldb_private::Error
+    WillAttach (const char *process_name, bool wait_for_launch);
+
+    lldb_private::Error
+    WillLaunchOrAttach ();
+
+    virtual lldb_private::Error
+    DoAttach (lldb::pid_t pid);
+    
+    virtual lldb_private::Error
+    DoAttach (const char *process_name, bool wait_for_launch);
+
+    virtual void
+    DidAttach ();
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual const char *
+    GetPluginName();
+
+    virtual const char *
+    GetShortPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+    virtual void
+    GetPluginCommandHelp (const char *command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Error
+    ExecutePluginCommand (lldb_private::Args &command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Log *
+    EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
+
+    //------------------------------------------------------------------
+    // Process Control
+    //------------------------------------------------------------------
+    virtual lldb_private::Error
+    WillResume ();
+
+    virtual lldb_private::Error
+    DoResume ();
+
+    virtual lldb_private::Error
+    DoHalt ();
+
+    virtual lldb_private::Error
+    WillDetach ();
+
+    virtual lldb_private::Error
+    DoDetach ();
+
+    virtual lldb_private::Error
+    DoSignal (int signal);
+
+    virtual lldb_private::Error
+    DoDestroy ();
+
+    virtual void
+    RefreshStateAfterStop();
+
+    //------------------------------------------------------------------
+    // Process Queries
+    //------------------------------------------------------------------
+    virtual bool
+    IsAlive ();
+
+    virtual lldb::addr_t
+    GetImageInfoAddress();
+
+    //------------------------------------------------------------------
+    // Process Memory
+    //------------------------------------------------------------------
+    virtual size_t
+    DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error);
+
+    virtual size_t
+    DoWriteMemory (lldb::addr_t addr, const void *buf, size_t size, lldb_private::Error &error);
+
+    virtual lldb::addr_t
+    DoAllocateMemory (size_t size, uint32_t permissions, lldb_private::Error &error);
+
+    virtual lldb_private::Error
+    DoDeallocateMemory (lldb::addr_t ptr);
+
+    //------------------------------------------------------------------
+    // Process STDIO
+    //------------------------------------------------------------------
+    virtual size_t
+    GetSTDOUT (char *buf, size_t buf_size, lldb_private::Error &error);
+
+    virtual size_t
+    GetSTDERR (char *buf, size_t buf_size, lldb_private::Error &error);
+
+    virtual size_t
+    PutSTDIN (const char *buf, size_t buf_size, lldb_private::Error &error);
+
+    //----------------------------------------------------------------------
+    // Process Breakpoints
+    //----------------------------------------------------------------------
+    virtual size_t
+    GetSoftwareBreakpointTrapOpcode (lldb_private::BreakpointSite *bp_site);
+
+    //----------------------------------------------------------------------
+    // Process Breakpoints
+    //----------------------------------------------------------------------
+    virtual lldb_private::Error
+    EnableBreakpoint (lldb_private::BreakpointSite *bp_site);
+
+    virtual lldb_private::Error
+    DisableBreakpoint (lldb_private::BreakpointSite *bp_site);
+
+    //----------------------------------------------------------------------
+    // Process Watchpoints
+    //----------------------------------------------------------------------
+    virtual lldb_private::Error
+    EnableWatchpoint (lldb_private::WatchpointLocation *wp_loc);
+
+    virtual lldb_private::Error
+    DisableWatchpoint (lldb_private::WatchpointLocation *wp_loc);
+
+    virtual lldb::ByteOrder
+    GetByteOrder () const;
+
+    virtual lldb_private::DynamicLoader *
+    GetDynamicLoader ();
+
+protected:
+    friend class ThreadGDBRemote;
+    friend class GDBRemoteCommunication;
+    friend class GDBRemoteRegisterContext;
+
+    bool
+    SetCurrentGDBRemoteThread (int tid);
+
+    bool
+    SetCurrentGDBRemoteThreadForRun (int tid);
+
+    //----------------------------------------------------------------------
+    // Accessors
+    //----------------------------------------------------------------------
+    bool
+    IsRunning ( lldb::StateType state )
+    {
+        return    state == lldb::eStateRunning || IsStepping(state);
+    }
+
+    bool
+    IsStepping ( lldb::StateType state)
+    {
+        return    state == lldb::eStateStepping;
+    }
+    bool
+    CanResume ( lldb::StateType state)
+    {
+        return state == lldb::eStateStopped;
+    }
+
+    bool
+    HasExited (lldb::StateType state)
+    {
+        return state == lldb::eStateExited;
+    }
+
+    bool
+    ProcessIDIsValid ( ) const;
+
+    static void
+    STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len);
+
+    void
+    AppendSTDOUT (const char* s, size_t len);
+
+    lldb_private::ArchSpec&
+    GetArchSpec()
+    {
+        return m_arch_spec;
+    }
+    const lldb_private::ArchSpec&
+    GetArchSpec() const
+    {
+        return m_arch_spec;
+    }
+
+    void
+    Clear ( );
+
+    lldb_private::Flags &
+    GetFlags ()
+    {
+        return m_flags;
+    }
+
+    const lldb_private::Flags &
+    GetFlags () const
+    {
+        return m_flags;
+    }
+
+    uint32_t
+    UpdateThreadListIfNeeded ();
+
+    lldb_private::Error
+    StartDebugserverProcess (const char *debugserver_url,      // The connection string to use in the spawned debugserver ("localhost:1234" or "/dev/tty...")
+                             char const *inferior_argv[],
+                             char const *inferior_envp[],
+                             const char *stdin_path,
+                             lldb::pid_t attach_pid,         // If inferior inferior_argv == NULL, then attach to this pid
+                             const char *attach_pid_name,    // Wait for the next process to launch whose basename matches "attach_wait_name"
+                             bool wait_for_launch,           // Wait for the process named "attach_wait_name" to launch
+                             lldb_private::ArchSpec& arch_spec);
+
+    void
+    KillDebugserverProcess ();
+
+    void
+    BuildDynamicRegisterInfo ();
+
+    GDBRemoteCommunication &
+    GetGDBRemote()
+    {
+        return m_gdb_comm;
+    }
+
+    //------------------------------------------------------------------
+    /// Broadcaster event bits definitions.
+    //------------------------------------------------------------------
+    enum
+    {
+        eBroadcastBitAsyncContinue                  = (1 << 0),
+        eBroadcastBitAsyncThreadShouldExit          = (1 << 1)
+    };
+
+
+    std::auto_ptr<lldb_private::DynamicLoader> m_dynamic_loader_ap;
+    lldb_private::Flags m_flags;            // Process specific flags (see eFlags enums)
+    lldb_private::Communication m_stdio_communication;
+    lldb_private::Mutex m_stdio_mutex;      // Multithreaded protection for stdio
+    std::string m_stdout_data;
+    lldb_private::ArchSpec m_arch_spec;
+    lldb::ByteOrder m_byte_order;
+    GDBRemoteCommunication m_gdb_comm;
+    lldb::pid_t m_debugserver_pid;
+    uint32_t m_debugserver_monitor;
+    StringExtractor m_last_stop_packet;
+    GDBRemoteDynamicRegisterInfo m_register_info;
+    lldb_private::Broadcaster m_async_broadcaster;
+    lldb::thread_t m_async_thread;
+    // Current GDB remote state. Any members added here need to be reset to
+    // proper default values in ResetGDBRemoteState ().
+    lldb::tid_t m_curr_tid;         // Current gdb remote protocol thread index for all other operations
+    lldb::tid_t m_curr_tid_run;     // Current gdb remote protocol thread index for continue, step, etc
+    uint32_t m_z0_supported:1;      // Set to non-zero if Z0 and z0 packets are supported
+    lldb_private::StreamString m_continue_packet;
+    lldb::addr_t m_dispatch_queue_offsets_addr;
+    uint32_t m_packet_timeout;
+    size_t m_max_memory_size;       // The maximum number of bytes to read/write when reading and writing memory
+    lldb_private::unw_targettype_t m_libunwind_target_type;
+    lldb_private::unw_addr_space_t m_libunwind_addr_space; // libunwind address space object for this process.
+    bool m_waiting_for_attach;
+
+    void
+    ResetGDBRemoteState ();
+
+    bool
+    StartAsyncThread ();
+
+    void
+    StopAsyncThread ();
+
+    static void *
+    AsyncThread (void *arg);
+
+    static bool
+    MonitorDebugserverProcess (void *callback_baton,
+                               lldb::pid_t pid,
+                               int signo,           // Zero for no signal
+                               int exit_status);    // Exit value of process if signal is zero
+
+    lldb::StateType
+    SetThreadStopInfo (StringExtractor& stop_packet);
+
+    void
+    DidLaunchOrAttach ();
+
+    lldb_private::Error
+    ConnectToDebugserver (const char *host_port);
+
+    const char *
+    GetDispatchQueueNameForThread (lldb::addr_t thread_dispatch_qaddr,
+                                   std::string &dispatch_queue_name);
+
+    static size_t
+    AttachInputReaderCallback (void *baton, 
+                               lldb_private::InputReader *reader, 
+                               lldb::InputReaderAction notification,
+                               const char *bytes, 
+                               size_t bytes_len);
+
+private:
+    //------------------------------------------------------------------
+    // For ProcessGDBRemote only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (ProcessGDBRemote);
+
+    lldb_private::unw_addr_space_t
+    GetLibUnwindAddressSpace ();
+
+    void 
+    DestoryLibUnwindAddressSpace ();
+};
+
+#endif  // liblldb_ProcessGDBRemote_h_
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp
new file mode 100644
index 0000000..051ce8f
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp
@@ -0,0 +1,121 @@
+//===-- ProcessGDBRemoteLog.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ProcessGDBRemoteLog.h"
+
+#include "lldb/Core/Args.h"
+#include "lldb/Core/StreamFile.h"
+
+#include "ProcessGDBRemote.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+static Log* g_log = NULL; // Leak for now as auto_ptr was being cleaned up
+                          // by global constructors before other threads
+                          // were done with it.
+Log *
+ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (uint32_t mask)
+{
+    Log *log = g_log;
+    if (log && mask)
+    {
+        uint32_t log_mask = log->GetMask().GetAllFlagBits();
+        if ((log_mask & mask) != mask)
+            return NULL;
+    }
+    return log;
+}
+
+void
+ProcessGDBRemoteLog::DisableLog ()
+{
+    if (g_log)
+    {
+        delete g_log;
+        g_log = NULL;
+    }
+}
+
+Log *
+ProcessGDBRemoteLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &args, Stream *feedback_strm)
+{
+    DisableLog ();
+    g_log = new Log (log_stream_sp);
+    if (g_log)
+    {
+        uint32_t flag_bits = 0;
+        bool got_unknown_category = false;
+        const size_t argc = args.GetArgumentCount();
+        for (size_t i=0; i<argc; ++i)
+        {
+            const char *arg = args.GetArgumentAtIndex(i);
+
+            if      (::strcasecmp (arg, "all")        == 0   ) flag_bits |= GDBR_LOG_ALL;
+            else if (::strcasestr (arg, "break")      == arg ) flag_bits |= GDBR_LOG_BREAKPOINTS;
+            else if (::strcasecmp (arg, "default")    == 0   ) flag_bits |= GDBR_LOG_DEFAULT;
+            else if (::strcasecmp (arg, "packets")    == 0   ) flag_bits |= GDBR_LOG_PACKETS;
+            else if (::strcasecmp (arg, "memory")     == 0   ) flag_bits |= GDBR_LOG_MEMORY;
+            else if (::strcasecmp (arg, "data-short") == 0   ) flag_bits |= GDBR_LOG_MEMORY_DATA_SHORT;
+            else if (::strcasecmp (arg, "data-long")  == 0   ) flag_bits |= GDBR_LOG_MEMORY_DATA_LONG;
+            else if (::strcasecmp (arg, "process")    == 0   ) flag_bits |= GDBR_LOG_PROCESS;
+            else if (::strcasecmp (arg, "step")       == 0   ) flag_bits |= GDBR_LOG_STEP;
+            else if (::strcasecmp (arg, "thread")     == 0   ) flag_bits |= GDBR_LOG_THREAD;
+            else if (::strcasecmp (arg, "verbose")    == 0   ) flag_bits |= GDBR_LOG_VERBOSE;
+            else if (::strcasestr (arg, "watch")      == arg ) flag_bits |= GDBR_LOG_WATCHPOINTS;
+            else
+            {
+                feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
+                if (got_unknown_category == false)
+                {
+                    got_unknown_category = true;
+                    ListLogCategories (feedback_strm);
+                }
+            }
+        }
+        if (flag_bits == 0)
+            flag_bits = GDBR_LOG_DEFAULT;
+        g_log->GetMask().SetAllFlagBits(flag_bits);
+        g_log->GetOptions().SetAllFlagBits(log_options);
+    }
+    return g_log;
+}
+
+void
+ProcessGDBRemoteLog::ListLogCategories (Stream *strm)
+{
+    strm->Printf("Logging categories for '%s':\n"
+        "\tall - turn on all available logging categories\n"
+        "\tbreak - log breakpoints\n"
+        "\tdefault - enable the default set of logging categories for liblldb\n"
+        "\tpackets - log gdb remote packets\n"
+        "\tmemory - log memory reads and writes\n"
+        "\tdata-short - log memory bytes for memory reads and writes for short transactions only\n"
+        "\tdata-long - log memory bytes for memory reads and writes for all transactions\n"
+        "\tprocess - log process events and activities\n"
+        "\tthread - log thread events and activities\n"
+        "\tstep - log step related activities\n"
+        "\tverbose - enable verbose loggging\n"
+        "\twatch - log watchpoint related activities\n", ProcessGDBRemote::GetPluginNameStatic());
+}
+
+
+void
+ProcessGDBRemoteLog::LogIf (uint32_t mask, const char *format, ...)
+{
+    Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (mask);
+    if (log)
+    {
+        va_list args;
+        va_start (args, format);
+        log->VAPrintf (format, args);
+        va_end (args);
+    }
+}
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h
new file mode 100644
index 0000000..97580d3
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h
@@ -0,0 +1,53 @@
+//===-- ProcessGDBRemoteLog.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_ProcessGDBRemoteLog_h_
+#define liblldb_ProcessGDBRemoteLog_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+
+// Project includes
+#include "lldb/Core/Log.h"
+
+#define GDBR_LOG_VERBOSE                  (1u << 0)
+#define GDBR_LOG_PROCESS                  (1u << 1)
+#define GDBR_LOG_THREAD                   (1u << 2)
+#define GDBR_LOG_PACKETS                  (1u << 3)
+#define GDBR_LOG_MEMORY                   (1u << 4)    // Log memory reads/writes calls
+#define GDBR_LOG_MEMORY_DATA_SHORT        (1u << 5)    // Log short memory reads/writes bytes
+#define GDBR_LOG_MEMORY_DATA_LONG         (1u << 6)    // Log all memory reads/writes bytes
+#define GDBR_LOG_BREAKPOINTS              (1u << 7)
+#define GDBR_LOG_WATCHPOINTS              (1u << 8)
+#define GDBR_LOG_STEP                     (1u << 9)
+#define GDBR_LOG_COMM                     (1u << 10)
+#define GDBR_LOG_ALL                      (UINT32_MAX)
+#define GDBR_LOG_DEFAULT                  GDBR_LOG_PACKETS
+
+class ProcessGDBRemoteLog
+{
+public:
+    static lldb_private::Log *
+    GetLogIfAllCategoriesSet(uint32_t mask = 0);
+
+    static void
+    DisableLog ();
+
+    static lldb_private::Log *
+    EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, lldb_private::Args &args, lldb_private::Stream *feedback_strm);
+
+    static void
+    ListLogCategories (lldb_private::Stream *strm);
+
+    static void
+    LogIf (uint32_t mask, const char *format, ...);
+};
+
+#endif  // liblldb_ProcessGDBRemoteLog_h_
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
new file mode 100644
index 0000000..37485ed
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -0,0 +1,296 @@
+//===-- ThreadGDBRemote.cpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "ThreadGDBRemote.h"
+
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Unwind.h"
+#include "lldb/Breakpoint/WatchpointLocation.h"
+
+#include "LibUnwindRegisterContext.h"
+#include "ProcessGDBRemote.h"
+#include "ProcessGDBRemoteLog.h"
+#include "StringExtractorGDBRemote.h"
+#include "UnwindLibUnwind.h"
+#include "UnwindMacOSXFrameBackchain.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Thread Registers
+//----------------------------------------------------------------------
+
+ThreadGDBRemote::ThreadGDBRemote (ProcessGDBRemote &process, lldb::tid_t tid) :
+    Thread(process, tid),
+    m_stop_info_stop_id (0),
+    m_stop_info (this),
+    m_thread_name (),
+    m_dispatch_queue_name (),
+    m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS),
+    m_unwinder_ap ()
+{
+//    ProcessGDBRemoteLog::LogIf(GDBR_LOG_THREAD | GDBR_LOG_VERBOSE, "ThreadGDBRemote::ThreadGDBRemote ( pid = %i, tid = 0x%4.4x, )", m_process.GetID(), GetID());
+    ProcessGDBRemoteLog::LogIf(GDBR_LOG_THREAD, "%p: ThreadGDBRemote::ThreadGDBRemote (pid = %i, tid = 0x%4.4x)", this, m_process.GetID(), GetID());
+}
+
+ThreadGDBRemote::~ThreadGDBRemote ()
+{
+    ProcessGDBRemoteLog::LogIf(GDBR_LOG_THREAD, "%p: ThreadGDBRemote::~ThreadGDBRemote (pid = %i, tid = 0x%4.4x)", this, m_process.GetID(), GetID());
+}
+
+
+const char *
+ThreadGDBRemote::GetInfo ()
+{
+    return NULL;
+}
+
+
+const char *
+ThreadGDBRemote::GetName ()
+{
+    if (m_thread_name.empty())
+        return NULL;
+    return m_thread_name.c_str();
+}
+
+
+const char *
+ThreadGDBRemote::GetQueueName ()
+{
+    // Always re-fetch the dispatch queue name since it can change
+    if (m_thread_dispatch_qaddr != 0 || m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
+        return GetGDBProcess().GetDispatchQueueNameForThread (m_thread_dispatch_qaddr, m_dispatch_queue_name);
+    return NULL;
+}
+
+bool
+ThreadGDBRemote::WillResume (StateType resume_state)
+{
+    // TODO: cache for next time in case we can match things up??
+    ClearStackFrames();
+    int signo = GetResumeSignal();
+    m_stop_info.Clear();
+    switch (resume_state)
+    {
+    case eStateSuspended:
+    case eStateStopped:
+        // Don't append anything for threads that should stay stopped.
+        break;
+
+    case eStateRunning:
+        if (m_process.GetUnixSignals().SignalIsValid (signo))
+            GetGDBProcess().m_continue_packet.Printf(";C%2.2x:%4.4x", signo, GetID());
+        else
+            GetGDBProcess().m_continue_packet.Printf(";c:%4.4x", GetID());
+        break;
+
+    case eStateStepping:
+        if (m_process.GetUnixSignals().SignalIsValid (signo))
+            GetGDBProcess().m_continue_packet.Printf(";S%2.2x:%4.4x", signo, GetID());
+        else
+            GetGDBProcess().m_continue_packet.Printf(";s:%4.4x", GetID());
+        break;
+    }
+    Thread::WillResume(resume_state);
+    return true;
+}
+
+void
+ThreadGDBRemote::RefreshStateAfterStop()
+{
+    // Invalidate all registers in our register context
+    GetRegisterContext()->Invalidate();
+}
+
+Unwind *
+ThreadGDBRemote::GetUnwinder ()
+{
+    if (m_unwinder_ap.get() == NULL)
+    {
+        const ArchSpec target_arch (GetProcess().GetTarget().GetArchitecture ());
+        if (target_arch == ArchSpec("x86_64") ||  target_arch == ArchSpec("i386"))
+        {
+            m_unwinder_ap.reset (new UnwindLibUnwind (*this, GetGDBProcess().GetLibUnwindAddressSpace()));
+        }
+        else
+        {
+            m_unwinder_ap.reset (new UnwindMacOSXFrameBackchain (*this));
+        }
+    }
+    return m_unwinder_ap.get();
+}
+
+uint32_t
+ThreadGDBRemote::GetStackFrameCount()
+{
+    Unwind *unwinder = GetUnwinder ();
+    if (unwinder)
+        return unwinder->GetFrameCount();
+    return 0;
+}
+
+// Make sure that GetStackFrameAtIndex() does NOT call GetStackFrameCount() when
+// getting the stack frame at index zero! This way GetStackFrameCount() (via
+// GetStackFRameData()) can call this function to get the first frame in order
+// to provide the first frame to a lower call for efficiency sake (avoid
+// redundant lookups in the frame symbol context).
+lldb::StackFrameSP
+ThreadGDBRemote::GetStackFrameAtIndex (uint32_t idx)
+{
+
+    StackFrameSP frame_sp (m_frames.GetFrameAtIndex(idx));
+
+    if (frame_sp.get())
+        return frame_sp;
+
+    // Don't try and fetch a frame while process is running
+// FIXME: This check isn't right because IsRunning checks the Public state, but this
+// is work you need to do - for instance in ShouldStop & friends - before the public 
+// state has been changed.
+//    if (m_process.IsRunning())
+//        return frame_sp;
+
+    // Special case the first frame (idx == 0) so that we don't need to
+    // know how many stack frames there are to get it. If we need any other
+    // frames, then we do need to know if "idx" is a valid index.
+    if (idx == 0)
+    {
+        // If this is the first frame, we want to share the thread register
+        // context with the stack frame at index zero.
+        GetRegisterContext();
+        assert (m_reg_context_sp.get());
+        frame_sp.reset (new StackFrame (idx, *this, m_reg_context_sp, m_reg_context_sp->GetSP(), m_reg_context_sp->GetPC()));
+    }
+    else if (idx < GetStackFrameCount())
+    {
+        Unwind *unwinder = GetUnwinder ();
+        if (unwinder)
+        {
+            addr_t pc, cfa;
+            if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc))
+                frame_sp.reset (new StackFrame (idx, *this, cfa, pc));
+        }
+    }
+    m_frames.SetFrameAtIndex(idx, frame_sp);
+    return frame_sp;
+}
+
+void
+ThreadGDBRemote::ClearStackFrames ()
+{
+    Unwind *unwinder = GetUnwinder ();
+    if (unwinder)
+        unwinder->Clear();
+    Thread::ClearStackFrames();
+}
+
+
+bool
+ThreadGDBRemote::ThreadIDIsValid (lldb::tid_t thread)
+{
+    return thread != 0;
+}
+
+void
+ThreadGDBRemote::Dump(Log *log, uint32_t index)
+{
+}
+
+
+bool
+ThreadGDBRemote::ShouldStop (bool &step_more)
+{
+    return true;
+}
+RegisterContext *
+ThreadGDBRemote::GetRegisterContext ()
+{
+    if (m_reg_context_sp.get() == NULL)
+        m_reg_context_sp.reset (CreateRegisterContextForFrame (NULL));
+    return m_reg_context_sp.get();
+}
+
+RegisterContext *
+ThreadGDBRemote::CreateRegisterContextForFrame (StackFrame *frame)
+{
+    const bool read_all_registers_at_once = false;
+    uint32_t frame_idx = 0;
+    
+    if (frame)
+        frame_idx = frame->GetID();
+
+    if (frame_idx == 0)
+        return new GDBRemoteRegisterContext (*this, frame, GetGDBProcess().m_register_info, read_all_registers_at_once);
+    else if (m_unwinder_ap.get() && frame_idx < m_unwinder_ap->GetFrameCount())
+        return m_unwinder_ap->CreateRegisterContextForFrame (frame);
+    return NULL;
+}
+
+bool
+ThreadGDBRemote::SaveFrameZeroState (RegisterCheckpoint &checkpoint)
+{
+    lldb::StackFrameSP frame_sp(GetStackFrameAtIndex (0));
+    if (frame_sp)
+    {
+        checkpoint.SetStackID(frame_sp->GetStackID());
+        return frame_sp->GetRegisterContext()->ReadAllRegisterValues (checkpoint.GetData());
+    }
+    return false;
+}
+
+bool
+ThreadGDBRemote::RestoreSaveFrameZero (const RegisterCheckpoint &checkpoint)
+{
+    lldb::StackFrameSP frame_sp(GetStackFrameAtIndex (0));
+    if (frame_sp)
+    {
+        bool ret = frame_sp->GetRegisterContext()->WriteAllRegisterValues (checkpoint.GetData());
+        frame_sp->GetRegisterContext()->Invalidate();
+        ClearStackFrames();
+        return ret;
+    }
+    return false;
+}
+
+bool
+ThreadGDBRemote::GetRawStopReason (StopInfo *stop_info)
+{
+    if (m_stop_info_stop_id != m_process.GetStopID())
+    {
+        char packet[256];
+        const int packet_len = snprintf(packet, sizeof(packet), "qThreadStopInfo%x", GetID());
+        assert (packet_len < (sizeof(packet) - 1));
+        StringExtractorGDBRemote stop_packet;
+        if (GetGDBProcess().GetGDBRemote().SendPacketAndWaitForResponse(packet, stop_packet, 1, false))
+        {
+            std::string copy(stop_packet.GetStringRef());
+            GetGDBProcess().SetThreadStopInfo (stop_packet);
+            // The process should have set the stop info stop ID and also
+            // filled this thread in with valid stop info
+            if (m_stop_info_stop_id != m_process.GetStopID())
+            {
+                //ProcessGDBRemoteLog::LogIf(GDBR_LOG_THREAD, "warning: qThreadStopInfo problem: '%s' => '%s'", packet, stop_packet.GetStringRef().c_str());
+                printf("warning: qThreadStopInfo problem: '%s' => '%s'\n\torig '%s'\n", packet, stop_packet.GetStringRef().c_str(), copy.c_str()); /// REMOVE THIS
+                return false;
+            }
+        }
+    }
+    *stop_info = m_stop_info;
+    return true;
+}
+
+
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
new file mode 100644
index 0000000..3fa4ae0
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
@@ -0,0 +1,156 @@
+//===-- ThreadGDBRemote.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_ThreadGDBRemote_h_
+#define liblldb_ThreadGDBRemote_h_
+
+#include <string>
+
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+#include "MachException.h"
+#include "libunwind.h"
+
+class StringExtractor;
+class ProcessGDBRemote;
+
+class ThreadGDBRemote : public lldb_private::Thread
+{
+public:
+    ThreadGDBRemote (ProcessGDBRemote &process, lldb::tid_t tid);
+
+    virtual
+    ~ThreadGDBRemote ();
+
+    virtual bool
+    WillResume (lldb::StateType resume_state);
+
+    virtual void
+    RefreshStateAfterStop();
+
+    virtual const char *
+    GetInfo ();
+
+    virtual const char *
+    GetName ();
+
+    virtual const char *
+    GetQueueName ();
+
+    virtual lldb_private::RegisterContext *
+    GetRegisterContext ();
+
+    virtual lldb_private::RegisterContext *
+    CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+
+    virtual bool
+    SaveFrameZeroState (RegisterCheckpoint &checkpoint);
+
+    virtual bool
+    RestoreSaveFrameZero (const RegisterCheckpoint &checkpoint);
+
+    virtual uint32_t
+    GetStackFrameCount();
+
+    virtual lldb::StackFrameSP
+    GetStackFrameAtIndex (uint32_t idx);
+
+    virtual void
+    ClearStackFrames ();
+
+    ProcessGDBRemote &
+    GetGDBProcess ()
+    {
+        return (ProcessGDBRemote &)m_process;
+    }
+
+    const ProcessGDBRemote &
+    GetGDBProcess () const
+    {
+        return (ProcessGDBRemote &)m_process;
+    }
+
+    void
+    Dump (lldb_private::Log *log, uint32_t index);
+
+    static bool
+    ThreadIDIsValid (lldb::tid_t thread);
+
+    bool
+    ShouldStop (bool &step_more);
+
+    const char *
+    GetBasicInfoAsString ();
+
+    lldb_private::Thread::StopInfo &
+    GetStopInfoRef ()
+    {
+        return m_stop_info;
+    }
+
+    uint32_t
+    GetStopInfoStopID()
+    {
+        return m_stop_info_stop_id;
+    }
+
+    void
+    SetStopInfoStopID (uint32_t stop_id)
+    {
+        m_stop_info_stop_id = stop_id;
+    }
+
+    void
+    SetName (const char *name)
+    {
+        if (name && name[0])
+            m_thread_name.assign (name);
+        else
+            m_thread_name.clear();
+    }
+
+    lldb::addr_t
+    GetThreadDispatchQAddr ()
+    {
+        return m_thread_dispatch_qaddr;
+    }
+
+    void
+    SetThreadDispatchQAddr (lldb::addr_t thread_dispatch_qaddr)
+    {
+        m_thread_dispatch_qaddr = thread_dispatch_qaddr;
+    }
+
+protected:
+    //------------------------------------------------------------------
+    // Member variables.
+    //------------------------------------------------------------------
+    uint32_t m_stop_info_stop_id;
+    lldb_private::Thread::StopInfo m_stop_info;
+    std::string m_thread_name;
+    std::string m_dispatch_queue_name;
+    lldb::addr_t m_thread_dispatch_qaddr;
+    std::auto_ptr<lldb_private::Unwind> m_unwinder_ap;
+    //------------------------------------------------------------------
+    // Member variables.
+    //------------------------------------------------------------------
+
+    lldb_private::Unwind *
+    GetUnwinder ();
+
+    void
+    SetStopInfoFromPacket (StringExtractor &stop_packet, uint32_t stop_id);
+
+    virtual bool
+    GetRawStopReason (StopInfo *stop_info);
+
+
+};
+
+#endif  // liblldb_ThreadGDBRemote_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
new file mode 100644
index 0000000..989e494
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
@@ -0,0 +1,211 @@
+//===-- DWARFAbbreviationDeclaration.cpp ------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFAbbreviationDeclaration.h"
+
+#include "lldb/Core/dwarf.h"
+
+#include "DWARFFormValue.h"
+
+using namespace lldb_private;
+
+DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() :
+    m_code  (InvalidCode),
+    m_tag   (0),
+    m_has_children (0),
+    m_attributes()
+{
+}
+
+DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration(dw_tag_t tag, uint8_t has_children) :
+    m_code  (InvalidCode),
+    m_tag   (tag),
+    m_has_children (has_children),
+    m_attributes()
+{
+}
+
+bool
+DWARFAbbreviationDeclaration::Extract(const DataExtractor& data, uint32_t* offset_ptr)
+{
+    return Extract(data, offset_ptr, data.GetULEB128(offset_ptr));
+}
+
+bool
+DWARFAbbreviationDeclaration::Extract(const DataExtractor& data, uint32_t* offset_ptr, dw_uleb128_t code)
+{
+    m_code = code;
+    m_attributes.clear();
+    if (m_code)
+    {
+        m_tag = data.GetULEB128(offset_ptr);
+        m_has_children = data.GetU8(offset_ptr);
+
+        while (data.ValidOffset(*offset_ptr))
+        {
+            dw_attr_t attr = data.GetULEB128(offset_ptr);
+            dw_form_t form = data.GetULEB128(offset_ptr);
+
+            if (attr && form)
+                m_attributes.push_back(DWARFAttribute(attr, form));
+            else
+                break;
+        }
+
+        return m_tag != 0;
+    }
+    else
+    {
+        m_tag = 0;
+        m_has_children = 0;
+    }
+
+    return false;
+}
+
+
+void
+DWARFAbbreviationDeclaration::Dump(Stream *s)  const
+{
+//  *ostrm_ptr << std::setfill(' ') << std::dec << '[' << std::setw(3) << std::right << m_code << ']' << ' ' << std::setw(30) << std::left << DW_TAG_value_to_name(m_tag) << DW_CHILDREN_value_to_name(m_has_children) << std::endl;
+//
+//  DWARFAttribute::const_iterator pos;
+//
+//  for (pos = m_attributes.begin(); pos != m_attributes.end(); ++pos)
+//      *ostrm_ptr << "      " << std::setw(29) << std::left << DW_AT_value_to_name(pos->attr()) << ' ' << DW_FORM_value_to_name(pos->form()) << std::endl;
+//
+//  *ostrm_ptr << std::endl;
+}
+
+
+
+bool
+DWARFAbbreviationDeclaration::IsValid()
+{
+    return m_code != 0 && m_tag != 0;
+}
+
+
+void
+DWARFAbbreviationDeclaration::CopyExcludingAddressAttributes(const DWARFAbbreviationDeclaration& abbr_decl, const uint32_t idx)
+{
+    m_code = abbr_decl.Code();  // Invalidate the code since that can't be copied safely.
+    m_tag = abbr_decl.Tag();
+    m_has_children = abbr_decl.HasChildren();
+
+    const DWARFAttribute::collection& attributes = abbr_decl.Attributes();
+    const uint32_t num_abbr_decl_attributes = attributes.size();
+
+    dw_attr_t attr;
+    dw_form_t form;
+    uint32_t i;
+
+    for (i = 0; i < num_abbr_decl_attributes; ++i)
+    {
+        attributes[i].get(attr, form);
+        switch (attr)
+        {
+        case DW_AT_location:
+        case DW_AT_frame_base:
+            // Only add these if they are location expressions (have a single
+            // value) and not location lists (have a lists of location
+            // expressions which are only valid over specific address ranges)
+            if (DWARFFormValue::IsBlockForm(form))
+                m_attributes.push_back(DWARFAttribute(attr, form));
+            break;
+
+        case DW_AT_low_pc:
+        case DW_AT_high_pc:
+        case DW_AT_ranges:
+        case DW_AT_entry_pc:
+            // Don't add these attributes
+            if (i >= idx)
+                break;
+            // Fall through and add attribute
+        default:
+            // Add anything that isn't address related
+            m_attributes.push_back(DWARFAttribute(attr, form));
+            break;
+        }
+    }
+}
+
+void
+DWARFAbbreviationDeclaration::CopyChangingStringToStrp(
+    const DWARFAbbreviationDeclaration& abbr_decl,
+    const DataExtractor& debug_info_data,
+    dw_offset_t debug_info_offset,
+    const DWARFCompileUnit* cu,
+    const uint32_t strp_min_len
+)
+{
+    m_code = InvalidCode;
+    m_tag = abbr_decl.Tag();
+    m_has_children = abbr_decl.HasChildren();
+
+    const DWARFAttribute::collection& attributes = abbr_decl.Attributes();
+    const uint32_t num_abbr_decl_attributes = attributes.size();
+
+    dw_attr_t attr;
+    dw_form_t form;
+    uint32_t i;
+    dw_offset_t offset = debug_info_offset;
+
+    for (i = 0; i < num_abbr_decl_attributes; ++i)
+    {
+        attributes[i].get(attr, form);
+        dw_offset_t attr_offset = offset;
+        DWARFFormValue::SkipValue(form, debug_info_data, &offset, cu);
+
+        if (form == DW_FORM_string && ((offset - attr_offset) >= strp_min_len))
+            m_attributes.push_back(DWARFAttribute(attr, DW_FORM_strp));
+        else
+            m_attributes.push_back(DWARFAttribute(attr, form));
+    }
+}
+
+
+uint32_t
+DWARFAbbreviationDeclaration::FindAttributeIndex(dw_attr_t attr) const
+{
+    uint32_t i;
+    const uint32_t kNumAttributes = m_attributes.size();
+    for (i = 0; i < kNumAttributes; ++i)
+    {
+        if (m_attributes[i].get_attr() == attr)
+            return i;
+    }
+    return DW_INVALID_INDEX;
+}
+
+
+bool
+DWARFAbbreviationDeclaration::operator == (const DWARFAbbreviationDeclaration& rhs) const
+{
+    return Tag()            == rhs.Tag()
+        && HasChildren()    == rhs.HasChildren()
+        && Attributes()     == rhs.Attributes();
+}
+
+#if 0
+DWARFAbbreviationDeclaration::Append(BinaryStreamBuf& out_buff) const
+{
+    out_buff.Append32_as_ULEB128(Code());
+    out_buff.Append32_as_ULEB128(Tag());
+    out_buff.Append8(HasChildren());
+    const uint32_t kNumAttributes = m_attributes.size();
+    for (uint32_t i = 0; i < kNumAttributes; ++i)
+    {
+        out_buff.Append32_as_ULEB128(m_attributes[i].attr());
+        out_buff.Append32_as_ULEB128(m_attributes[i].form());
+    }
+    out_buff.Append8(0);    // Output a zero for attr (faster than using Append32_as_ULEB128)
+    out_buff.Append8(0);    // Output a zero for attr (faster than using Append32_as_ULEB128)
+}
+#endif  // 0
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
new file mode 100644
index 0000000..7959f26
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
@@ -0,0 +1,77 @@
+//===-- DWARFAbbreviationDeclaration.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_DWARFAbbreviationDeclaration_h_
+#define liblldb_DWARFAbbreviationDeclaration_h_
+
+#include "SymbolFileDWARF.h"
+#include "DWARFAttribute.h"
+
+class DWARFCompileUnit;
+
+class DWARFAbbreviationDeclaration
+{
+public:
+    enum { InvalidCode = 0 };
+                    DWARFAbbreviationDeclaration();
+
+                    // For hand crafting an abbreviation declaration
+                    DWARFAbbreviationDeclaration(dw_tag_t tag, uint8_t has_children);
+    void            AddAttribute(const DWARFAttribute& attr)
+                    {
+                        m_attributes.push_back(attr);
+                    }
+
+    dw_uleb128_t    Code() const { return m_code; }
+    void            SetCode(dw_uleb128_t code) { m_code = code; }
+    dw_tag_t        Tag() const { return m_tag; }
+    bool            HasChildren() const { return m_has_children; }
+    uint32_t        NumAttributes() const { return m_attributes.size(); }
+    dw_attr_t       GetAttrByIndex(uint32_t idx) const { return m_attributes.size() > idx ? m_attributes[idx].get_attr() : 0; }
+    dw_form_t       GetFormByIndex(uint32_t idx) const { return m_attributes.size() > idx ? m_attributes[idx].get_form() : 0; }
+    bool            GetAttrAndFormByIndex(uint32_t idx, dw_attr_t& attr, dw_form_t& form) const
+                    {
+                        if (m_attributes.size() > idx)
+                        {
+                            m_attributes[idx].get(attr, form);
+                            return true;
+                        }
+                        attr = form = 0;
+                        return false;
+                    }
+
+                    // idx is assumed to be valid when calling GetAttrAndFormByIndexUnchecked()
+    void            GetAttrAndFormByIndexUnchecked(uint32_t idx, dw_attr_t& attr, dw_form_t& form) const
+                    {
+                        m_attributes[idx].get(attr, form);
+                    }
+    void            CopyExcludingAddressAttributes(const DWARFAbbreviationDeclaration& abbr_decl, const uint32_t idx);
+    void            CopyChangingStringToStrp(
+                        const DWARFAbbreviationDeclaration& abbr_decl,
+                        const lldb_private::DataExtractor& debug_info_data,
+                        dw_offset_t debug_info_offset,
+                        const DWARFCompileUnit* cu,
+                        const uint32_t strp_min_len);
+    uint32_t        FindAttributeIndex(dw_attr_t attr) const;
+    bool            Extract(const lldb_private::DataExtractor& data, uint32_t* offset_ptr);
+    bool            Extract(const lldb_private::DataExtractor& data, uint32_t* offset_ptr, dw_uleb128_t code);
+//  void            Append(BinaryStreamBuf& out_buff) const;
+    bool            IsValid();
+    void            Dump(lldb_private::Stream *s) const;
+    bool            operator == (const DWARFAbbreviationDeclaration& rhs) const;
+//  DWARFAttribute::collection& Attributes() { return m_attributes; }
+    const DWARFAttribute::collection& Attributes() const { return m_attributes; }
+protected:
+    dw_uleb128_t        m_code;
+    dw_tag_t            m_tag;
+    uint8_t             m_has_children;
+    DWARFAttribute::collection m_attributes;
+};
+
+#endif  // liblldb_DWARFAbbreviationDeclaration_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
new file mode 100644
index 0000000..0b44926
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
@@ -0,0 +1,45 @@
+//===-- DWARFAttribute.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_DWARFAttribute_h_
+#define liblldb_DWARFAttribute_h_
+
+#include "DWARFDefines.h"
+#include <vector>
+
+class DWARFAttribute
+{
+public:
+    DWARFAttribute(dw_attr_t attr, dw_form_t form) :
+        m_attr_form ( attr << 16 | form )
+    {
+    }
+
+    void        set(dw_attr_t attr, dw_form_t form) { m_attr_form = (attr << 16) | form; }
+    void        set_attr(dw_attr_t attr) { m_attr_form = (m_attr_form & 0x0000ffffu) | (attr << 16); }
+    void        set_form(dw_form_t form) { m_attr_form = (m_attr_form & 0xffff0000u) | form; }
+    dw_attr_t   get_attr() const { return m_attr_form >> 16; }
+    dw_form_t   get_form() const { return m_attr_form; }
+    void        get(dw_attr_t& attr, dw_form_t& form)  const
+    {
+        register uint32_t attr_form = m_attr_form;
+        attr = attr_form >> 16;
+        form = attr_form;
+    }
+    bool        operator == (const DWARFAttribute& rhs) const { return m_attr_form == rhs.m_attr_form; }
+    typedef std::vector<DWARFAttribute> collection;
+    typedef collection::iterator iterator;
+    typedef collection::const_iterator const_iterator;
+
+protected:
+    uint32_t    m_attr_form;    // Upper 16 bits is attribute, lower 16 bits is form
+};
+
+
+#endif  // liblldb_DWARFAttribute_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
new file mode 100644
index 0000000..e7f92c6
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
@@ -0,0 +1,770 @@
+//===-- DWARFCompileUnit.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFCompileUnit.h"
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/Timer.h"
+
+#include "DWARFDebugAbbrev.h"
+#include "DWARFDebugAranges.h"
+#include "DWARFDIECollection.h"
+#include "DWARFFormValue.h"
+#include "LogChannelDWARF.h"
+#include "SymbolFileDWARF.h"
+
+using namespace lldb_private;
+using namespace std;
+
+extern int g_verbose;
+
+DWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF* m_dwarf2Data) :
+    m_dwarf2Data    ( m_dwarf2Data ),
+    m_offset        ( DW_INVALID_OFFSET ),
+    m_length        ( 0 ),
+    m_version       ( 0 ),
+    m_abbrevs       ( NULL ),
+    m_addr_size     ( DWARFCompileUnit::GetDefaultAddressSize() ),
+    m_base_addr     ( 0 ),
+    m_die_array     (),
+    m_aranges_ap    (),
+    m_user_data     ( NULL )
+{
+}
+
+void
+DWARFCompileUnit::Clear()
+{
+    m_offset        = DW_INVALID_OFFSET;
+    m_length        = 0;
+    m_version       = 0;
+    m_abbrevs       = NULL;
+    m_addr_size     = DWARFCompileUnit::GetDefaultAddressSize();
+    m_base_addr     = 0;
+    m_die_array.clear();
+    m_aranges_ap.reset();
+    m_user_data     = NULL;
+}
+
+bool
+DWARFCompileUnit::Extract(const DataExtractor &debug_info, uint32_t* offset_ptr)
+{
+    Clear();
+
+    m_offset = *offset_ptr;
+
+    if (debug_info.ValidOffset(*offset_ptr))
+    {
+        dw_offset_t abbr_offset;
+        const DWARFDebugAbbrev *abbr = m_dwarf2Data->DebugAbbrev();
+        m_length        = debug_info.GetU32(offset_ptr);
+        m_version       = debug_info.GetU16(offset_ptr);
+        abbr_offset     = debug_info.GetU32(offset_ptr);
+        m_addr_size     = debug_info.GetU8 (offset_ptr);
+
+        bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset()-1);
+        bool version_OK = SymbolFileDWARF::SupportedVersion(m_version);
+        bool abbr_offset_OK = m_dwarf2Data->get_debug_abbrev_data().ValidOffset(abbr_offset);
+        bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8));
+
+        if (length_OK && version_OK && addr_size_OK && abbr_offset_OK && abbr != NULL)
+        {
+            m_abbrevs = abbr->GetAbbreviationDeclarationSet(abbr_offset);
+            return true;
+        }
+
+        // reset the offset to where we tried to parse from if anything went wrong
+        *offset_ptr = m_offset;
+    }
+
+    return false;
+}
+
+
+dw_offset_t
+DWARFCompileUnit::Extract(dw_offset_t offset, const DataExtractor& debug_info_data, const DWARFAbbreviationDeclarationSet* abbrevs)
+{
+    Clear();
+
+    m_offset = offset;
+
+    if (debug_info_data.ValidOffset(offset))
+    {
+        m_length        = debug_info_data.GetU32(&offset);
+        m_version       = debug_info_data.GetU16(&offset);
+        bool abbrevs_OK = debug_info_data.GetU32(&offset) == abbrevs->GetOffset();
+        m_abbrevs       = abbrevs;
+        m_addr_size     = debug_info_data.GetU8 (&offset);
+
+        bool version_OK = SymbolFileDWARF::SupportedVersion(m_version);
+        bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8));
+
+        if (version_OK && addr_size_OK && abbrevs_OK && debug_info_data.ValidOffset(offset))
+            return offset;
+    }
+    return DW_INVALID_OFFSET;
+}
+
+void
+DWARFCompileUnit::ClearDIEs(bool keep_compile_unit_die)
+{
+    if (m_die_array.size() > 1)
+    {
+        // std::vectors never get any smaller when resized to a smaller size,
+        // or when clear() or erase() are called, the size will report that it
+        // is smaller, but the memory allocated remains intact (call capacity()
+        // to see this). So we need to create a temporary vector and swap the
+        // contents which will cause just the internal pointers to be swapped
+        // so that when "tmp_array" goes out of scope, it will destroy the
+        // contents.
+
+        // Save at least the compile unit DIE
+        DWARFDebugInfoEntry::collection tmp_array;
+        m_die_array.swap(tmp_array);
+        if (keep_compile_unit_die)
+            m_die_array.push_back(tmp_array.front());
+    }
+}
+
+//----------------------------------------------------------------------
+// ParseCompileUnitDIEsIfNeeded
+//
+// Parses a compile unit and indexes its DIEs if it already hasn't been
+// done.
+//----------------------------------------------------------------------
+size_t
+DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only)
+{
+    const size_t initial_die_array_size = m_die_array.size();
+    if ((cu_die_only && initial_die_array_size > 0) || initial_die_array_size > 1)
+        return 0; // Already parsed
+
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "%8.8x: DWARFCompileUnit::ExtractDIEsIfNeeded( cu_die_only = %i )",
+                        m_offset,
+                        cu_die_only);
+
+    // Set the offset to that of the first DIE
+    uint32_t offset = GetFirstDIEOffset();
+    const dw_offset_t next_cu_offset = GetNextCompileUnitOffset();
+    DWARFDebugInfoEntry die;
+        // Keep a flat array of the DIE for binary lookup by DIE offset
+    Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
+//        if (log)
+//            log->Printf("0x%8.8x: Compile Unit: length = 0x%8.8x, version = 0x%4.4x, abbr_offset = 0x%8.8x, addr_size = 0x%2.2x",
+//                        cu->GetOffset(),
+//                        cu->GetLength(),
+//                        cu->GetVersion(),
+//                        cu->GetAbbrevOffset(),
+//                        cu->GetAddressByteSize());
+
+    uint32_t depth = 0;
+    // We are in our compile unit, parse starting at the offset
+    // we were told to parse
+    while (die.Extract(m_dwarf2Data, this, &offset))
+    {
+        if (log)
+            log->Printf("0x%8.8x: %*.*s%s%s",
+                        die.GetOffset(),
+                        depth * 2, depth * 2, "",
+                        DW_TAG_value_to_name (die.Tag()),
+                        die.HasChildren() ? " *" : "");
+        if (cu_die_only)
+        {
+            AddDIE(die);
+            return 1;
+        }
+        else if (depth == 0 && initial_die_array_size == 1)
+        {
+            // Don't append the CU die as we already did that
+        }
+        else
+        {
+            AddDIE(die);
+        }
+
+        const DWARFAbbreviationDeclaration* abbrDecl = die.GetAbbreviationDeclarationPtr();
+        if (abbrDecl)
+        {
+            // Normal DIE
+            if (abbrDecl->HasChildren())
+                ++depth;
+        }
+        else
+        {
+            // NULL DIE.
+            if (depth > 0)
+                --depth;
+            else
+                break;  // We are done with this compile unit!
+        }
+
+        assert(offset <= next_cu_offset);
+    }
+    SetDIERelations();
+    return m_die_array.size();
+}
+
+
+dw_offset_t
+DWARFCompileUnit::GetAbbrevOffset() const
+{
+    return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET;
+}
+
+
+
+bool
+DWARFCompileUnit::Verify(Stream *s) const
+{
+    const DataExtractor& debug_info = m_dwarf2Data->get_debug_info_data();
+    bool valid_offset = debug_info.ValidOffset(m_offset);
+    bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset()-1);
+    bool version_OK = SymbolFileDWARF::SupportedVersion(m_version);
+    bool abbr_offset_OK = m_dwarf2Data->get_debug_abbrev_data().ValidOffset(GetAbbrevOffset());
+    bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8));
+    bool verbose = s->GetVerbose();
+    if (valid_offset && length_OK && version_OK && addr_size_OK && abbr_offset_OK)
+    {
+        if (verbose)
+            s->Printf("    0x%8.8x: OK\n", m_offset);
+        return true;
+    }
+    else
+    {
+        s->Printf("    0x%8.8x: ", m_offset);
+
+        m_dwarf2Data->get_debug_info_data().Dump (s, m_offset, lldb::eFormatHex, 1, Size(), 32, LLDB_INVALID_ADDRESS, 0, 0);
+        s->EOL();
+        if (valid_offset)
+        {
+            if (!length_OK)
+                s->Printf("        The length (0x%8.8x) for this compile unit is too large for the .debug_info provided.\n", m_length);
+            if (!version_OK)
+                s->Printf("        The 16 bit compile unit header version is not supported.\n");
+            if (!abbr_offset_OK)
+                s->Printf("        The offset into the .debug_abbrev section (0x%8.8x) is not valid.\n", GetAbbrevOffset());
+            if (!addr_size_OK)
+                s->Printf("        The address size is unsupported: 0x%2.2x\n", m_addr_size);
+        }
+        else
+            s->Printf("        The start offset of the compile unit header in the .debug_info is invalid.\n");
+    }
+    return false;
+}
+
+
+void
+DWARFCompileUnit::Dump(Stream *s) const
+{
+    s->Printf("0x%8.8x: Compile Unit: length = 0x%8.8x, version = 0x%4.4x, abbr_offset = 0x%8.8x, addr_size = 0x%2.2x (next CU at {0x%8.8x})\n",
+                m_offset, m_length, m_version, GetAbbrevOffset(), m_addr_size, GetNextCompileUnitOffset());
+}
+
+
+static uint8_t g_default_addr_size = 4;
+
+uint8_t
+DWARFCompileUnit::GetAddressByteSize(const DWARFCompileUnit* cu)
+{
+    if (cu)
+        return cu->GetAddressByteSize();
+    return DWARFCompileUnit::GetDefaultAddressSize();
+}
+
+uint8_t
+DWARFCompileUnit::GetDefaultAddressSize()
+{
+    return g_default_addr_size;
+}
+
+void
+DWARFCompileUnit::SetDefaultAddressSize(uint8_t addr_size)
+{
+    g_default_addr_size = addr_size;
+}
+
+bool
+DWARFCompileUnit::LookupAddress
+(
+    const dw_addr_t address,
+    DWARFDebugInfoEntry** function_die_handle,
+    DWARFDebugInfoEntry** block_die_handle
+)
+{
+    bool success = false;
+
+    if (function_die_handle != NULL && DIE())
+    {
+        if (m_aranges_ap.get() == NULL)
+        {
+            m_aranges_ap.reset(new DWARFDebugAranges());
+            m_die_array.front().BuildFunctionAddressRangeTable(m_dwarf2Data, this, m_aranges_ap.get());
+        }
+
+        // Re-check the aranges auto pointer contents in case it was created above
+        if (m_aranges_ap.get() != NULL)
+        {
+            *function_die_handle = GetDIEPtr(m_aranges_ap->FindAddress(address));
+            if (*function_die_handle != NULL)
+            {
+                success = true;
+                if (block_die_handle != NULL)
+                {
+                    DWARFDebugInfoEntry* child = (*function_die_handle)->GetFirstChild();
+                    while (child)
+                    {
+                        if (child->LookupAddress(address, m_dwarf2Data, this, NULL, block_die_handle))
+                            break;
+                        child = child->GetSibling();
+                    }
+                }
+            }
+        }
+    }
+    return success;
+}
+
+//----------------------------------------------------------------------
+// SetDIERelations()
+//
+// We read in all of the DIE entries into our flat list of DIE entries
+// and now we need to go back through all of them and set the parent,
+// sibling and child pointers for quick DIE navigation.
+//----------------------------------------------------------------------
+void
+DWARFCompileUnit::SetDIERelations()
+{
+#if 0
+    // Compute average bytes per DIE
+    //
+    // We can figure out what the average number of bytes per DIE is
+    // to help us pre-allocate the correct number of m_die_array
+    // entries so we don't end up doing a lot of memory copies as we
+    // are creating our DIE array when parsing
+    //
+    // Enable this code by changing "#if 0" above to "#if 1" and running
+    // the dsymutil or dwarfdump with a bunch of dwarf files and see what
+    // the running average ends up being in the stdout log.
+    static size_t g_total_cu_debug_info_size = 0;
+    static size_t g_total_num_dies = 0;
+    static size_t g_min_bytes_per_die = UINT_MAX;
+    static size_t g_max_bytes_per_die = 0;
+    const size_t num_dies = m_die_array.size();
+    const size_t cu_debug_info_size = GetDebugInfoSize();
+    const size_t bytes_per_die = cu_debug_info_size / num_dies;
+    if (g_min_bytes_per_die > bytes_per_die)
+        g_min_bytes_per_die = bytes_per_die;
+    if (g_max_bytes_per_die < bytes_per_die)
+        g_max_bytes_per_die = bytes_per_die;
+    if (g_total_cu_debug_info_size == 0)
+    {
+        cout << "                    min max avg" << endl
+             << "n dies cu size  bpd bpd bpd bpd" << endl
+             << "------ -------- --- === === ===" << endl;
+    }
+    g_total_cu_debug_info_size += cu_debug_info_size;
+    g_total_num_dies += num_dies;
+    const size_t avg_bytes_per_die = g_total_cu_debug_info_size / g_total_num_dies;
+    cout
+        << DECIMAL_WIDTH(6) << num_dies << ' '
+        << DECIMAL_WIDTH(8) << cu_debug_info_size  << ' '
+        << DECIMAL_WIDTH(3) << bytes_per_die << ' '
+        << DECIMAL_WIDTH(3) << g_min_bytes_per_die << ' '
+        << DECIMAL_WIDTH(3) << g_max_bytes_per_die << ' '
+        << DECIMAL_WIDTH(3) << avg_bytes_per_die
+        << endl;
+#endif
+    if (m_die_array.empty())
+        return;
+    DWARFDebugInfoEntry* die_array_begin = &m_die_array.front();
+    DWARFDebugInfoEntry* die_array_end = &m_die_array.back();
+    DWARFDebugInfoEntry* curr_die;
+    // We purposely are skipping the last element in the array in the loop below
+    // so that we can always have a valid next item
+    for (curr_die = die_array_begin;  curr_die < die_array_end;  ++curr_die)
+    {
+        // Since our loop doesn't include the last element, we can always
+        // safely access the next die in the array.
+        DWARFDebugInfoEntry* next_die = curr_die + 1;
+
+        const DWARFAbbreviationDeclaration* curr_die_abbrev = curr_die->GetAbbreviationDeclarationPtr();
+
+        if (curr_die_abbrev)
+        {
+            // Normal DIE
+            if (curr_die_abbrev->HasChildren())
+                next_die->SetParent(curr_die);
+            else
+                curr_die->SetSibling(next_die);
+        }
+        else
+        {
+            // NULL DIE that terminates a sibling chain
+            DWARFDebugInfoEntry* parent = curr_die->GetParent();
+            if (parent)
+                parent->SetSibling(next_die);
+        }
+    }
+
+    // Since we skipped the last element, we need to fix it up!
+    if (die_array_begin < die_array_end)
+        curr_die->SetParent(die_array_begin);
+
+#if 0
+    // The code below will dump the DIE relations in case any modification
+    // is done to the above code. This dump can be used in a diff to make
+    // sure that no functionality is lost.
+    {
+        DWARFDebugInfoEntry::const_iterator pos;
+        DWARFDebugInfoEntry::const_iterator end = m_die_array.end();
+        puts("offset    parent   sibling  child");
+        puts("--------  -------- -------- --------");
+        for (pos = m_die_array.begin(); pos != end; ++pos)
+        {
+            const DWARFDebugInfoEntry& die_ref = *pos;
+            const DWARFDebugInfoEntry* p = die_ref.GetParent();
+            const DWARFDebugInfoEntry* s = die_ref.GetSibling();
+            const DWARFDebugInfoEntry* c = die_ref.GetFirstChild();
+            printf("%.8x: %.8x %.8x %.8x\n", die_ref.GetOffset(),
+                p ? p->GetOffset() : 0,
+                s ? s->GetOffset() : 0,
+                c ? c->GetOffset() : 0);
+        }
+    }
+#endif
+
+}
+//----------------------------------------------------------------------
+// Compare function DWARFDebugAranges::Range structures
+//----------------------------------------------------------------------
+static bool CompareDIEOffset (const DWARFDebugInfoEntry& die1, const DWARFDebugInfoEntry& die2)
+{
+    return die1.GetOffset() < die2.GetOffset();
+}
+
+//----------------------------------------------------------------------
+// GetDIEPtr()
+//
+// Get the DIE (Debug Information Entry) with the specified offset.
+//----------------------------------------------------------------------
+DWARFDebugInfoEntry*
+DWARFCompileUnit::GetDIEPtr(dw_offset_t die_offset)
+{
+    if (die_offset != DW_INVALID_OFFSET)
+    {
+        ExtractDIEsIfNeeded (false);
+        DWARFDebugInfoEntry compare_die;
+        compare_die.SetOffset(die_offset);
+        DWARFDebugInfoEntry::iterator end = m_die_array.end();
+        DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, compare_die, CompareDIEOffset);
+        if (pos != end)
+        {
+            if (die_offset == (*pos).GetOffset())
+                return &(*pos);
+        }
+    }
+    return NULL;    // Not found in any compile units
+}
+
+//----------------------------------------------------------------------
+// GetDIEPtrContainingOffset()
+//
+// Get the DIE (Debug Information Entry) that contains the specified
+// .debug_info offset.
+//----------------------------------------------------------------------
+const DWARFDebugInfoEntry*
+DWARFCompileUnit::GetDIEPtrContainingOffset(dw_offset_t die_offset)
+{
+    if (die_offset != DW_INVALID_OFFSET)
+    {
+        ExtractDIEsIfNeeded (false);
+        DWARFDebugInfoEntry compare_die;
+        compare_die.SetOffset(die_offset);
+        DWARFDebugInfoEntry::iterator end = m_die_array.end();
+        DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, compare_die, CompareDIEOffset);
+        if (pos != end)
+        {
+            if (die_offset >= (*pos).GetOffset())
+            {
+                DWARFDebugInfoEntry::iterator next = pos + 1;
+                if (next != end)
+                {
+                    if (die_offset < (*next).GetOffset())
+                        return &(*pos);
+                }
+            }
+        }
+    }
+    return NULL;    // Not found in any compile units
+}
+
+
+
+size_t
+DWARFCompileUnit::AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& dies, uint32_t depth) const
+{
+    size_t old_size = dies.Size();
+    DWARFDebugInfoEntry::const_iterator pos;
+    DWARFDebugInfoEntry::const_iterator end = m_die_array.end();
+    for (pos = m_die_array.begin(); pos != end; ++pos)
+    {
+        if (pos->Tag() == tag)
+            dies.Insert(&(*pos));
+    }
+
+    // Return the number of DIEs added to the collection
+    return dies.Size() - old_size;
+}
+
+void
+DWARFCompileUnit::AddGlobalDIEByIndex (uint32_t die_idx)
+{
+    m_global_die_indexes.push_back (die_idx);
+}
+
+
+void
+DWARFCompileUnit::AddGlobal (const DWARFDebugInfoEntry* die)
+{
+    // Indexes to all file level global and static variables
+    m_global_die_indexes;
+    
+    if (m_die_array.empty())
+        return;
+    
+    const DWARFDebugInfoEntry* first_die = &m_die_array[0];
+    const DWARFDebugInfoEntry* end = first_die + m_die_array.size();
+    if (first_die <= die && die < end)
+        m_global_die_indexes.push_back (die - first_die);
+}
+
+
+void
+DWARFCompileUnit::Index 
+(
+    lldb_private::UniqueCStringMap<dw_offset_t>& name_to_function_die,
+    lldb_private::UniqueCStringMap<dw_offset_t>& name_to_inlined_die,
+    lldb_private::UniqueCStringMap<dw_offset_t>& name_to_global_die,
+    lldb_private::UniqueCStringMap<dw_offset_t>& name_to_type_die
+)
+{
+
+    const DataExtractor* debug_str = &m_dwarf2Data->get_debug_str_data();
+
+    DWARFDebugInfoEntry::const_iterator pos;
+    DWARFDebugInfoEntry::const_iterator begin = m_die_array.begin();
+    DWARFDebugInfoEntry::const_iterator end = m_die_array.end();
+    for (pos = begin; pos != end; ++pos)
+    {
+        const DWARFDebugInfoEntry &die = *pos;
+        
+        const dw_tag_t tag = die.Tag();
+    
+        switch (tag)
+        {
+        case DW_TAG_subprogram:
+        case DW_TAG_inlined_subroutine:
+        case DW_TAG_base_type:
+        case DW_TAG_class_type:
+        case DW_TAG_constant:
+        case DW_TAG_enumeration_type:
+        case DW_TAG_string_type:
+        case DW_TAG_subroutine_type:
+        case DW_TAG_structure_type:
+        case DW_TAG_union_type:
+        case DW_TAG_typedef:
+        case DW_TAG_namespace:
+        case DW_TAG_variable:
+            break;
+            
+        default:
+            continue;
+        }
+
+        DWARFDebugInfoEntry::Attributes attributes;
+        const char *name = NULL;
+        const char *mangled = NULL;
+        bool is_variable = false;
+        bool is_declaration = false;
+        bool is_artificial = false;
+        bool has_address = false;
+        bool has_location = false;
+        bool is_global_or_static_variable = false;
+        const size_t num_attributes = die.GetAttributes(m_dwarf2Data, this, attributes);
+        if (num_attributes > 0)
+        {
+            uint32_t i;
+
+            dw_tag_t tag = die.Tag();
+            
+            is_variable = tag == DW_TAG_variable;
+
+            for (i=0; i<num_attributes; ++i)
+            {
+                dw_attr_t attr = attributes.AttributeAtIndex(i);
+                DWARFFormValue form_value;
+                switch (attr)
+                {
+                case DW_AT_name:
+                    if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
+                        name = form_value.AsCString(debug_str);
+                    break;
+
+                case DW_AT_declaration:
+                    if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
+                        is_declaration = form_value.Unsigned() != 0;
+                    break;
+
+                case DW_AT_artificial:
+                    if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
+                        is_artificial = form_value.Unsigned() != 0;
+                    break;
+
+                case DW_AT_MIPS_linkage_name:
+                    if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
+                        mangled = form_value.AsCString(debug_str);
+                    break;
+
+                case DW_AT_low_pc:
+                case DW_AT_ranges:
+                case DW_AT_entry_pc:
+                    has_address = true;
+                    break;
+
+                case DW_AT_location:
+                    has_location = true;
+                    if (tag == DW_TAG_variable)
+                    {
+                        const DWARFDebugInfoEntry* parent_die = die.GetParent();
+                        while ( parent_die != NULL )
+                        {
+                            switch (parent_die->Tag())
+                            {
+                            case DW_TAG_subprogram:
+                            case DW_TAG_lexical_block:
+                            case DW_TAG_inlined_subroutine:
+                                // Even if this is a function level static, we don't add it. We could theoretically
+                                // add these if we wanted to by introspecting into the DW_AT_location and seeing
+                                // if the location describes a hard coded address, but we dont want the performance
+                                // penalty of that right now.
+                                is_global_or_static_variable = false;
+//                              if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
+//                              {
+//                                  // If we have valid block data, then we have location expression bytes
+//                                  // that are fixed (not a location list).
+//                                  const uint8_t *block_data = form_value.BlockData();
+//                                  if (block_data)
+//                                  {
+//                                      uint32_t block_length = form_value.Unsigned();
+//                                      if (block_length == 1 + attributes.CompileUnitAtIndex(i)->GetAddressByteSize())
+//                                      {
+//                                          if (block_data[0] == DW_OP_addr)
+//                                              add_die = true;
+//                                      }
+//                                  }
+//                              }
+                                parent_die = NULL;  // Terminate the while loop.
+                                break;
+
+                            case DW_TAG_compile_unit:
+                                is_global_or_static_variable = true;
+                                parent_die = NULL;  // Terminate the while loop.
+                                break;
+
+                            default:
+                                parent_die = parent_die->GetParent();   // Keep going in the while loop.
+                                break;
+                            }
+                        }
+                    }
+                    break;
+                }
+            }
+        }
+
+        switch (tag)
+        {
+        case DW_TAG_subprogram:
+            if (has_address)
+            {
+                if (name && name[0])
+                {
+                    if ((name[0] == '-' || name[0] == '+') && name[1] == '[')
+                    {
+                        int name_len = strlen (name);
+                        // Objective C methods must have at least:
+                        //      "-[" or "+[" prefix
+                        //      One character for a class name
+                        //      One character for the space between the class name
+                        //      One character for the method name
+                        //      "]" suffix
+                        if (name_len >= 6 && name[name_len - 1] == ']')
+                        {
+                            const char *method_name = strchr (name, ' ');
+                            if (method_name)
+                            {
+                                // Skip the space
+                                ++method_name;
+                                // Extract the objective C basename and add it to the
+                                // accelerator tables
+                                size_t method_name_len = name_len - (method_name - name) - 1;
+                                ConstString method_const_str (method_name, method_name_len);
+                                name_to_function_die.Append(method_const_str.AsCString(), die.GetOffset());
+                            }
+                        }
+                    }
+                    name_to_function_die.Append(ConstString(name).AsCString(), die.GetOffset());
+                }
+                if (mangled && mangled[0])
+                    name_to_function_die.Append(ConstString(mangled).AsCString(), die.GetOffset());
+            }
+            break;
+
+        case DW_TAG_inlined_subroutine:
+            if (has_address)
+            {
+                if (name && name[0])
+                    name_to_inlined_die.Append(ConstString(name).AsCString(), die.GetOffset());
+                if (mangled && mangled[0])
+                    name_to_inlined_die.Append(ConstString(mangled).AsCString(), die.GetOffset());
+            }
+            break;
+        
+        case DW_TAG_base_type:
+        case DW_TAG_class_type:
+        case DW_TAG_constant:
+        case DW_TAG_enumeration_type:
+        case DW_TAG_string_type:
+        case DW_TAG_subroutine_type:
+        case DW_TAG_structure_type:
+        case DW_TAG_union_type:
+        case DW_TAG_typedef:
+        case DW_TAG_namespace:
+            if (name && is_declaration == false)
+            {
+                name_to_type_die.Append(ConstString(name).AsCString(), die.GetOffset());
+            }
+            break;
+
+        case DW_TAG_variable:
+            if (name && has_location && is_global_or_static_variable)
+            {
+                AddGlobalDIEByIndex (std::distance (begin, pos));
+                name_to_global_die.Append(ConstString(name).AsCString(), die.GetOffset());
+            }
+            break;
+            
+        default:
+            continue;
+        }
+    }
+}
+
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
new file mode 100644
index 0000000..44bbbfe
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
@@ -0,0 +1,168 @@
+//===-- DWARFCompileUnit.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_DWARFCompileUnit_h_
+#define SymbolFileDWARF_DWARFCompileUnit_h_
+
+#include "SymbolFileDWARF.h"
+#include "DWARFDebugInfoEntry.h"
+
+class DWARFCompileUnit
+{
+public:
+    DWARFCompileUnit(SymbolFileDWARF* dwarf2Data);
+
+    bool        Extract(const lldb_private::DataExtractor &debug_info, uint32_t* offset_ptr);
+    dw_offset_t Extract(dw_offset_t offset, const lldb_private::DataExtractor& debug_info_data, const DWARFAbbreviationDeclarationSet* abbrevs);
+    size_t      ExtractDIEsIfNeeded (bool cu_die_only);
+    bool        LookupAddress(
+                    const dw_addr_t address,
+                    DWARFDebugInfoEntry** function_die,
+                    DWARFDebugInfoEntry** block_die);
+
+    size_t      AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& matching_dies, uint32_t depth = UINT_MAX) const;
+    void        Clear();
+    bool        Verify(lldb_private::Stream *s) const;
+    void        Dump(lldb_private::Stream *s) const;
+    dw_offset_t GetOffset() const { return m_offset; }
+    uint32_t    Size() const { return 11; /* Size in bytes of the compile unit header */ }
+    bool        ContainsDIEOffset(dw_offset_t die_offset) const { return die_offset >= GetFirstDIEOffset() && die_offset < GetNextCompileUnitOffset(); }
+    dw_offset_t GetFirstDIEOffset() const { return m_offset + Size(); }
+    dw_offset_t GetNextCompileUnitOffset() const { return m_offset + m_length + 4; }
+    size_t      GetDebugInfoSize() const { return m_length + 4 - Size(); /* Size in bytes of the .debug_info data associated with this compile unit. */ }
+    uint32_t    GetLength() const { return m_length; }
+    uint16_t    GetVersion() const { return m_version; }
+    const DWARFAbbreviationDeclarationSet*  GetAbbreviations() const { return m_abbrevs; }
+    dw_offset_t GetAbbrevOffset() const;
+    uint8_t     GetAddressByteSize() const { return m_addr_size; }
+    dw_addr_t   GetBaseAddress() const { return m_base_addr; }
+    void        ClearDIEs(bool keep_compile_unit_die);
+
+    void
+    SetBaseAddress(dw_addr_t base_addr)
+    {
+        m_base_addr = base_addr;
+    }
+
+    void
+    SetDIERelations();
+
+    const DWARFDebugInfoEntry*
+    GetCompileUnitDIEOnly()
+    {
+        ExtractDIEsIfNeeded (true);
+        if (m_die_array.empty())
+            return NULL;
+        return &m_die_array[0];
+    }
+
+    const DWARFDebugInfoEntry*
+    DIE()
+    {
+        ExtractDIEsIfNeeded (false);
+        if (m_die_array.empty())
+            return NULL;
+        return &m_die_array[0];
+    }
+
+    void
+    AddDIE(DWARFDebugInfoEntry& die)
+    {
+        // The average bytes per DIE entry has been seen to be
+        // around 14-20 so lets pre-reserve the needed memory for
+        // our DIE entries accordingly. Search forward for "Compute
+        // average bytes per DIE" to see #if'ed out code that does
+        // that determination.
+
+        // Only reserve the memory if we are adding children of
+        // the main compile unit DIE. The compile unit DIE is always
+        // the first entry, so if our size is 1, then we are adding
+        // the first compile unit child DIE and should reserve
+        // the memory.
+        if (m_die_array.empty())
+            m_die_array.reserve(GetDebugInfoSize() / 14);
+        m_die_array.push_back(die);
+    }
+
+    DWARFDebugInfoEntry*
+    GetDIEPtr (dw_offset_t die_offset);
+
+    const DWARFDebugInfoEntry*
+    GetDIEPtrContainingOffset (dw_offset_t die_offset);
+
+    static uint8_t
+    GetAddressByteSize(const DWARFCompileUnit* cu);
+
+    static uint8_t
+    GetDefaultAddressSize();
+    static void
+    SetDefaultAddressSize(uint8_t addr_size);
+
+    void *
+    GetUserData() const
+    {
+        return m_user_data;
+    }
+
+    void
+    SetUserData(void *d)
+    {
+        m_user_data = d;
+    }
+
+
+    void
+    AddGlobalDIEByIndex (uint32_t die_idx);
+
+    void
+    AddGlobal (const DWARFDebugInfoEntry* die);
+
+    size_t
+    GetNumGlobals () const
+    {
+        return m_global_die_indexes.size();
+    }
+    
+    const DWARFDebugInfoEntry *
+    GetGlobalDIEAtIndex (uint32_t idx)
+    {
+        if (idx < m_global_die_indexes.size())
+        {
+            uint32_t die_idx = m_global_die_indexes[idx];
+            if (die_idx < m_die_array.size())
+                return &m_die_array[die_idx];
+        }
+        return NULL;
+    }
+
+    void
+    Index (lldb_private::UniqueCStringMap<dw_offset_t>& name_to_function_die,
+           lldb_private::UniqueCStringMap<dw_offset_t>& name_to_inlined_die,
+           lldb_private::UniqueCStringMap<dw_offset_t>& name_to_global_die,
+           lldb_private::UniqueCStringMap<dw_offset_t>& name_to_type_die);
+
+protected:
+    SymbolFileDWARF*    m_dwarf2Data;
+    dw_offset_t         m_offset;
+    uint32_t            m_length;
+    uint16_t            m_version;
+    const DWARFAbbreviationDeclarationSet*
+                        m_abbrevs;
+    uint8_t             m_addr_size;
+    dw_addr_t           m_base_addr;
+    DWARFDebugInfoEntry::collection
+                        m_die_array;    // The compile unit debug information entry item
+    std::auto_ptr<DWARFDebugAranges>    m_aranges_ap;   // A table similar to the .debug_aranges table, but this one points to the exact DW_TAG_subprogram DIEs
+    std::vector<uint32_t> m_global_die_indexes; // Indexes to all file level global and static variables
+    void *              m_user_data;
+private:
+    DISALLOW_COPY_AND_ASSIGN (DWARFCompileUnit);
+};
+
+#endif  // SymbolFileDWARF_DWARFCompileUnit_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp
new file mode 100644
index 0000000..60aac74
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp
@@ -0,0 +1,56 @@
+//===-- DWARFDIECollection.cpp ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDIECollection.h"
+
+#include <algorithm>
+
+#include "lldb/Core/Stream.h"
+
+#include "DWARFDebugInfoEntry.h"
+
+using namespace lldb_private;
+using namespace std;
+
+bool
+DWARFDIECollection::Insert(const DWARFDebugInfoEntry *die)
+{
+    iterator end_pos = m_dies.end();
+    iterator insert_pos = upper_bound(m_dies.begin(), end_pos, die);
+    if (insert_pos != end_pos && (*insert_pos == die))
+        return false;
+    m_dies.insert(insert_pos, die);
+    return true;
+}
+
+const DWARFDebugInfoEntry *
+DWARFDIECollection::GetDIEPtrAtIndex(uint32_t idx) const
+{
+    if (idx < m_dies.size())
+        return m_dies[idx];
+    return NULL;
+}
+
+
+size_t
+DWARFDIECollection::Size() const
+{
+    return m_dies.size();
+}
+
+void
+DWARFDIECollection::Dump(Stream *s, const char* title) const
+{
+    if (title && title[0] != '\0')
+        s->Printf( "%s\n", title);
+    const_iterator end_pos = m_dies.end();
+    const_iterator pos;
+    for (pos = m_dies.begin(); pos != end_pos; ++pos)
+        s->Printf( "0x%8.8x\n", (*pos)->GetOffset());
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h b/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h
new file mode 100644
index 0000000..c374a14
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h
@@ -0,0 +1,48 @@
+//===-- DWARFDIECollection.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_DWARFDIECollection_h_
+#define SymbolFileDWARF_DWARFDIECollection_h_
+
+#include "SymbolFileDWARF.h"
+#include <vector>
+
+class DWARFDIECollection
+{
+public:
+    DWARFDIECollection() :
+        m_dies()
+    {
+    }
+    ~DWARFDIECollection()
+    {
+    }
+
+    void
+    Dump(lldb_private::Stream *s, const char* title) const;
+
+    const DWARFDebugInfoEntry*
+    GetDIEPtrAtIndex(uint32_t idx) const;
+
+    bool
+    Insert(const DWARFDebugInfoEntry *die);
+
+    size_t
+    Size() const;
+
+protected:
+    typedef std::vector<const DWARFDebugInfoEntry *>    collection;
+    typedef collection::iterator                iterator;
+    typedef collection::const_iterator          const_iterator;
+
+    collection m_dies;  // Ordered list of die offsets
+};
+
+
+#endif  // SymbolFileDWARF_DWARFDIECollection_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp
new file mode 100644
index 0000000..af6fc8e
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp
@@ -0,0 +1,202 @@
+//===-- DWARFDebugAbbrev.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugAbbrev.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Stream.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace std;
+
+//----------------------------------------------------------------------
+// DWARFAbbreviationDeclarationSet::Clear()
+//----------------------------------------------------------------------
+void
+DWARFAbbreviationDeclarationSet::Clear()
+{
+    m_idx_offset = 0;
+    m_decls.clear();
+}
+
+
+//----------------------------------------------------------------------
+// DWARFAbbreviationDeclarationSet::Extract()
+//----------------------------------------------------------------------
+bool
+DWARFAbbreviationDeclarationSet::Extract(const DataExtractor& data, uint32_t* offset_ptr)
+{
+    const uint32_t begin_offset = *offset_ptr;
+    m_offset = begin_offset;
+    Clear();
+    DWARFAbbreviationDeclaration abbrevDeclaration;
+    dw_uleb128_t prev_abbr_code = 0;
+    while (abbrevDeclaration.Extract(data, offset_ptr))
+    {
+        m_decls.push_back(abbrevDeclaration);
+        if (m_idx_offset == 0)
+            m_idx_offset = abbrevDeclaration.Code();
+        else
+        {
+            if (prev_abbr_code + 1 != abbrevDeclaration.Code())
+                m_idx_offset = UINT_MAX;    // Out of order indexes, we can't do O(1) lookups...
+        }
+        prev_abbr_code = abbrevDeclaration.Code();
+    }
+    return begin_offset != *offset_ptr;
+}
+
+
+//----------------------------------------------------------------------
+// DWARFAbbreviationDeclarationSet::Dump()
+//----------------------------------------------------------------------
+void
+DWARFAbbreviationDeclarationSet::Dump(Stream *s) const
+{
+    std::for_each (m_decls.begin(), m_decls.end(), bind2nd(std::mem_fun_ref(&DWARFAbbreviationDeclaration::Dump),s));
+}
+
+
+//----------------------------------------------------------------------
+// DWARFAbbreviationDeclarationSet::GetAbbreviationDeclaration()
+//----------------------------------------------------------------------
+const DWARFAbbreviationDeclaration*
+DWARFAbbreviationDeclarationSet::GetAbbreviationDeclaration(dw_uleb128_t abbrCode) const
+{
+    if (m_idx_offset == UINT_MAX)
+    {
+        DWARFAbbreviationDeclarationCollConstIter pos;
+        DWARFAbbreviationDeclarationCollConstIter end = m_decls.end();
+        for (pos = m_decls.begin(); pos != end; ++pos)
+        {
+            if (pos->Code() == abbrCode)
+                return &(*pos);
+        }
+    }
+    else
+    {
+        uint32_t idx = abbrCode - m_idx_offset;
+        if (idx < m_decls.size())
+            return &m_decls[idx];
+    }
+    return NULL;
+}
+
+//----------------------------------------------------------------------
+// DWARFAbbreviationDeclarationSet::AppendAbbrevDeclSequential()
+//
+// Append an abbreviation declaration with a sequential code for O(n)
+// lookups. Handy when creating an DWARFAbbreviationDeclarationSet.
+//----------------------------------------------------------------------
+dw_uleb128_t
+DWARFAbbreviationDeclarationSet::AppendAbbrevDeclSequential(const DWARFAbbreviationDeclaration& abbrevDecl)
+{
+    // Get the next abbreviation code based on our current array size
+    dw_uleb128_t code = m_decls.size()+1;
+
+    // Push the new declaration on the back
+    m_decls.push_back(abbrevDecl);
+
+    // Update the code for this new declaration
+    m_decls.back().SetCode(code);
+
+    return code;    // return the new abbreviation code!
+}
+
+
+//----------------------------------------------------------------------
+// Encode
+//
+// Encode the abbreviation table onto the end of the buffer provided
+// into a byte represenation as would be found in a ".debug_abbrev"
+// debug information section.
+//----------------------------------------------------------------------
+//void
+//DWARFAbbreviationDeclarationSet::Encode(BinaryStreamBuf& debug_abbrev_buf) const
+//{
+//  DWARFAbbreviationDeclarationCollConstIter pos;
+//  DWARFAbbreviationDeclarationCollConstIter end = m_decls.end();
+//  for (pos = m_decls.begin(); pos != end; ++pos)
+//      pos->Append(debug_abbrev_buf);
+//  debug_abbrev_buf.Append8(0);
+//}
+
+
+//----------------------------------------------------------------------
+// DWARFDebugAbbrev constructor
+//----------------------------------------------------------------------
+DWARFDebugAbbrev::DWARFDebugAbbrev() :
+    m_abbrevCollMap(),
+    m_prev_abbr_offset_pos(m_abbrevCollMap.end())
+{
+}
+
+
+//----------------------------------------------------------------------
+// DWARFDebugAbbrev::Parse()
+//----------------------------------------------------------------------
+void
+DWARFDebugAbbrev::Parse(const DataExtractor& data)
+{
+    uint32_t offset = 0;
+
+    while (data.ValidOffset(offset))
+    {
+        uint32_t initial_cu_offset = offset;
+        DWARFAbbreviationDeclarationSet abbrevDeclSet;
+
+        if (abbrevDeclSet.Extract(data, &offset))
+            m_abbrevCollMap[initial_cu_offset] = abbrevDeclSet;
+        else
+            break;
+    }
+    m_prev_abbr_offset_pos = m_abbrevCollMap.end();
+}
+
+//----------------------------------------------------------------------
+// DWARFDebugAbbrev::Dump()
+//----------------------------------------------------------------------
+void
+DWARFDebugAbbrev::Dump(Stream *s) const
+{
+    if (m_abbrevCollMap.empty())
+    {
+        s->PutCString("< EMPTY >\n");
+        return;
+    }
+
+    DWARFAbbreviationDeclarationCollMapConstIter pos;
+    for (pos = m_abbrevCollMap.begin(); pos != m_abbrevCollMap.end(); ++pos)
+    {
+        s->Printf("Abbrev table for offset: 0x%8.8x\n", pos->first);
+        pos->second.Dump(s);
+    }
+}
+
+
+//----------------------------------------------------------------------
+// DWARFDebugAbbrev::GetAbbreviationDeclarationSet()
+//----------------------------------------------------------------------
+const DWARFAbbreviationDeclarationSet*
+DWARFDebugAbbrev::GetAbbreviationDeclarationSet(dw_offset_t cu_abbr_offset) const
+{
+    DWARFAbbreviationDeclarationCollMapConstIter end = m_abbrevCollMap.end();
+    DWARFAbbreviationDeclarationCollMapConstIter pos;
+    if (m_prev_abbr_offset_pos != end && m_prev_abbr_offset_pos->first == cu_abbr_offset)
+        return &(m_prev_abbr_offset_pos->second);
+    else
+    {
+        pos = m_abbrevCollMap.find(cu_abbr_offset);
+        m_prev_abbr_offset_pos = pos;
+    }
+
+    if (pos != m_abbrevCollMap.end());
+        return &(pos->second);
+    return NULL;
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h
new file mode 100644
index 0000000..3185d98
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h
@@ -0,0 +1,74 @@
+//===-- DWARFDebugAbbrev.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_DWARFDebugAbbrev_h_
+#define SymbolFileDWARF_DWARFDebugAbbrev_h_
+
+#include <list>
+#include <map>
+
+#include "lldb/lldb-private.h"
+
+#include "DWARFDefines.h"
+#include "DWARFAbbreviationDeclaration.h"
+
+typedef std::vector<DWARFAbbreviationDeclaration>               DWARFAbbreviationDeclarationColl;
+typedef DWARFAbbreviationDeclarationColl::iterator              DWARFAbbreviationDeclarationCollIter;
+typedef DWARFAbbreviationDeclarationColl::const_iterator        DWARFAbbreviationDeclarationCollConstIter;
+
+
+class DWARFAbbreviationDeclarationSet
+{
+public:
+    DWARFAbbreviationDeclarationSet() :
+        m_offset(DW_INVALID_OFFSET),
+        m_idx_offset(0),
+        m_decls()
+        {
+        }
+
+    DWARFAbbreviationDeclarationSet(dw_offset_t offset, uint32_t idx_offset) :
+        m_offset(offset),
+        m_idx_offset(idx_offset),
+        m_decls()
+        {
+        }
+
+    void Clear();
+    dw_offset_t GetOffset() const { return m_offset; }
+    void Dump(lldb_private::Stream *s) const;
+    bool Extract(const lldb_private::DataExtractor& data, uint32_t* offset_ptr);
+    //void Encode(BinaryStreamBuf& debug_abbrev_buf) const;
+    dw_uleb128_t AppendAbbrevDeclSequential(const DWARFAbbreviationDeclaration& abbrevDecl);
+
+    const DWARFAbbreviationDeclaration* GetAbbreviationDeclaration(dw_uleb128_t abbrCode) const;
+private:
+    dw_offset_t m_offset;
+    uint32_t m_idx_offset;
+    std::vector<DWARFAbbreviationDeclaration> m_decls;
+};
+
+typedef std::map<dw_offset_t, DWARFAbbreviationDeclarationSet> DWARFAbbreviationDeclarationCollMap;
+typedef DWARFAbbreviationDeclarationCollMap::iterator DWARFAbbreviationDeclarationCollMapIter;
+typedef DWARFAbbreviationDeclarationCollMap::const_iterator DWARFAbbreviationDeclarationCollMapConstIter;
+
+
+class DWARFDebugAbbrev
+{
+public:
+    DWARFDebugAbbrev();
+    const DWARFAbbreviationDeclarationSet*  GetAbbreviationDeclarationSet(dw_offset_t cu_abbr_offset) const;
+    void Dump(lldb_private::Stream *s) const;
+    void Parse(const lldb_private::DataExtractor& data);
+protected:
+    DWARFAbbreviationDeclarationCollMap m_abbrevCollMap;
+    mutable DWARFAbbreviationDeclarationCollMapConstIter m_prev_abbr_offset_pos;
+};
+
+#endif  // SymbolFileDWARF_DWARFDebugAbbrev_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
new file mode 100644
index 0000000..57ef6ba
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
@@ -0,0 +1,274 @@
+//===-- DWARFDebugArangeSet.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugArangeSet.h"
+
+#include <assert.h>
+#include "lldb/Core/Stream.h"
+#include "SymbolFileDWARF.h"
+
+using namespace lldb_private;
+
+DWARFDebugArangeSet::DWARFDebugArangeSet() :
+    m_offset(DW_INVALID_OFFSET),
+    m_header(),
+    m_arange_descriptors()
+{
+    m_header.length     = 0;
+    m_header.version    = 0;
+    m_header.cu_offset  = 0;
+    m_header.addr_size  = 0;
+    m_header.seg_size   = 0;
+}
+
+void
+DWARFDebugArangeSet::Clear()
+{
+    m_offset = DW_INVALID_OFFSET;
+    m_header.length     = 0;
+    m_header.version    = 0;
+    m_header.cu_offset  = 0;
+    m_header.addr_size  = 0;
+    m_header.seg_size   = 0;
+    m_arange_descriptors.clear();
+}
+
+void
+DWARFDebugArangeSet::SetHeader
+(
+    uint16_t version,
+    uint32_t cu_offset,
+    uint8_t addr_size,
+    uint8_t seg_size
+)
+{
+    m_header.version    = version;
+    m_header.cu_offset  = cu_offset;
+    m_header.addr_size  = addr_size;
+    m_header.seg_size   = seg_size;
+}
+
+void
+DWARFDebugArangeSet::Compact()
+{
+    if (m_arange_descriptors.empty())
+        return;
+
+    // Iterate through all arange descriptors and combine any ranges that
+    // overlap or have matching boundaries. The m_arange_descriptors are assumed
+    // to be in ascending order after being built by adding descriptors
+    // using the AddDescriptor method.
+    uint32_t i = 0;
+    while (i + 1 < m_arange_descriptors.size())
+    {
+        if (m_arange_descriptors[i].end_address() >= m_arange_descriptors[i+1].address)
+        {
+            // The current range ends at or exceeds the start of the next address range.
+            // Compute the max end address between the two and use that to make the new
+            // length.
+            const dw_addr_t max_end_addr = std::max(m_arange_descriptors[i].end_address(), m_arange_descriptors[i+1].end_address());
+            m_arange_descriptors[i].length = max_end_addr - m_arange_descriptors[i].address;
+            // Now remove the next entry as it was just combined with the previous one.
+            m_arange_descriptors.erase(m_arange_descriptors.begin()+i+1);
+        }
+        else
+        {
+            // Discontiguous address range, just proceed to the next one.
+            ++i;
+        }
+    }
+}
+//----------------------------------------------------------------------
+// Compare function DWARFDebugArangeSet::Descriptor structures
+//----------------------------------------------------------------------
+static bool DescriptorLessThan (const DWARFDebugArangeSet::Descriptor& range1, const DWARFDebugArangeSet::Descriptor& range2)
+{
+    return range1.address < range2.address;
+}
+
+//----------------------------------------------------------------------
+// Add a range descriptor and keep things sorted so we can easily
+// compact the ranges before being saved or used.
+//----------------------------------------------------------------------
+void
+DWARFDebugArangeSet::AddDescriptor(const DWARFDebugArangeSet::Descriptor& range)
+{
+    if (m_arange_descriptors.empty())
+    {
+        m_arange_descriptors.push_back(range);
+        return;
+    }
+
+    DescriptorIter end = m_arange_descriptors.end();
+    DescriptorIter pos = lower_bound(m_arange_descriptors.begin(), end, range, DescriptorLessThan);
+    const dw_addr_t range_end_addr = range.end_address();
+    if (pos != end)
+    {
+        const dw_addr_t found_end_addr = pos->end_address();
+        if (range.address < pos->address)
+        {
+            if (range_end_addr < pos->address)
+            {
+                // Non-contiguous entries, add this one before the found entry
+                m_arange_descriptors.insert(pos, range);
+            }
+            else if (range_end_addr == pos->address)
+            {
+                // The top end of 'range' is the lower end of the entry
+                // pointed to by 'pos'. We can combine range with the
+                // entry we found by setting the starting address and
+                // increasing the length since they don't overlap.
+                pos->address = range.address;
+                pos->length += range.length;
+            }
+            else
+            {
+                // We can combine these two and make sure the largest end
+                // address is used to make end address.
+                pos->address = range.address;
+                pos->length = std::max(found_end_addr, range_end_addr) - pos->address;
+            }
+        }
+        else if (range.address == pos->address)
+        {
+            pos->length = std::max(pos->length, range.length);
+        }
+    }
+    else
+    {
+        // NOTE: 'pos' points to entry past the end which is ok for insert,
+        // don't use otherwise!!!
+        const dw_addr_t max_addr = m_arange_descriptors.back().end_address();
+        if (max_addr < range.address)
+        {
+            // Non-contiguous entries, add this one before the found entry
+            m_arange_descriptors.insert(pos, range);
+        }
+        else if (max_addr == range.address)
+        {
+            m_arange_descriptors.back().length += range.length;
+        }
+        else
+        {
+            m_arange_descriptors.back().length = std::max(max_addr, range_end_addr) - m_arange_descriptors.back().address;
+        }
+    }
+}
+
+bool
+DWARFDebugArangeSet::Extract(const DataExtractor &data, uint32_t* offset_ptr)
+{
+    if (data.ValidOffset(*offset_ptr))
+    {
+        m_arange_descriptors.clear();
+        m_offset = *offset_ptr;
+
+        // 7.20 Address Range Table
+        //
+        // Each set of entries in the table of address ranges contained in
+        // the .debug_aranges section begins with a header consisting of: a
+        // 4-byte length containing the length of the set of entries for this
+        // compilation unit, not including the length field itself; a 2-byte
+        // version identifier containing the value 2 for DWARF Version 2; a
+        // 4-byte offset into the.debug_infosection; a 1-byte unsigned integer
+        // containing the size in bytes of an address (or the offset portion of
+        // an address for segmented addressing) on the target system; and a
+        // 1-byte unsigned integer containing the size in bytes of a segment
+        // descriptor on the target system. This header is followed by a series
+        // of tuples. Each tuple consists of an address and a length, each in
+        // the size appropriate for an address on the target architecture.
+        m_header.length     = data.GetU32(offset_ptr);
+        m_header.version    = data.GetU16(offset_ptr);
+        m_header.cu_offset  = data.GetU32(offset_ptr);
+        m_header.addr_size  = data.GetU8(offset_ptr);
+        m_header.seg_size   = data.GetU8(offset_ptr);
+
+
+        // The first tuple following the header in each set begins at an offset
+        // that is a multiple of the size of a single tuple (that is, twice the
+        // size of an address). The header is padded, if necessary, to the
+        // appropriate boundary.
+        const uint32_t header_size = *offset_ptr - m_offset;
+        const uint32_t tuple_size = m_header.addr_size << 1;
+        uint32_t first_tuple_offset = 0;
+        while (first_tuple_offset < header_size)
+            first_tuple_offset += tuple_size;
+
+        *offset_ptr = m_offset + first_tuple_offset;
+
+        Descriptor arangeDescriptor;
+
+        assert(sizeof(arangeDescriptor.address) == sizeof(arangeDescriptor.length));
+        assert(sizeof(arangeDescriptor.address) >= m_header.addr_size);
+
+        while (data.ValidOffset(*offset_ptr))
+        {
+            arangeDescriptor.address    = data.GetMaxU64(offset_ptr, m_header.addr_size);
+            arangeDescriptor.length     = data.GetMaxU64(offset_ptr, m_header.addr_size);
+
+            // Each set of tuples is terminated by a 0 for the address and 0
+            // for the length.
+            if (arangeDescriptor.address || arangeDescriptor.length)
+                m_arange_descriptors.push_back(arangeDescriptor);
+            else
+                break;  // We are done if we get a zero address and length
+        }
+
+        return !m_arange_descriptors.empty();
+    }
+    return false;
+}
+
+
+dw_offset_t
+DWARFDebugArangeSet::GetOffsetOfNextEntry() const
+{
+    return m_offset + m_header.length + 4;
+}
+
+
+void
+DWARFDebugArangeSet::Dump(Stream *s) const
+{
+    s->Printf("Address Range Header: length = 0x%8.8x, version = 0x%4.4x, cu_offset = 0x%8.8x, addr_size = 0x%2.2x, seg_size = 0x%2.2x\n",
+        m_header.length ,m_header.version, m_header.cu_offset, m_header.addr_size, m_header.seg_size);
+
+    const uint32_t hex_width = m_header.addr_size * 2;
+    DescriptorConstIter pos;
+    DescriptorConstIter end = m_arange_descriptors.end();
+    for (pos = m_arange_descriptors.begin(); pos != end; ++pos)
+        s->Printf("[0x%*.*llx - 0x%*.*llx)\n",
+            hex_width, hex_width, pos->address,
+            hex_width, hex_width, pos->end_address());
+}
+
+
+class DescriptorContainsAddress
+{
+public:
+    DescriptorContainsAddress (dw_addr_t address) : m_address(address) {}
+    bool operator() (const DWARFDebugArangeSet::Descriptor& desc) const
+    {
+        return (m_address >= desc.address) && (m_address < (desc.address + desc.length));
+    }
+ private:
+   const dw_addr_t m_address;
+};
+
+dw_offset_t
+DWARFDebugArangeSet::FindAddress(dw_addr_t address) const
+{
+    DescriptorConstIter end = m_arange_descriptors.end();
+    DescriptorConstIter pos = std::find_if( m_arange_descriptors.begin(), end,  // Range
+                                            DescriptorContainsAddress(address));// Predicate
+    if (pos != end)
+        return m_header.cu_offset;
+
+    return DW_INVALID_OFFSET;
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h
new file mode 100644
index 0000000..fc1e391
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h
@@ -0,0 +1,70 @@
+//===-- DWARFDebugArangeSet.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_DWARFDebugArangeSet_h_
+#define SymbolFileDWARF_DWARFDebugArangeSet_h_
+
+#include "SymbolFileDWARF.h"
+#include <vector>
+
+class SymbolFileDWARF;
+
+class DWARFDebugArangeSet
+{
+public:
+    typedef struct HeaderTag
+    {
+        uint32_t    length;     // The total length of the entries for that set, not including the length field itself.
+        uint16_t    version;    // The DWARF version number
+        uint32_t    cu_offset;  // The offset from the beginning of the .debug_info section of the compilation unit entry referenced by the table.
+        uint8_t     addr_size;  // The size in bytes of an address on the target architecture. For segmented addressing, this is the size of the offset portion of the address
+        uint8_t     seg_size;   // The size in bytes of a segment descriptor on the target architecture. If the target system uses a flat address space, this value is 0.
+    } Header;
+
+    typedef struct DescriptorTag
+    {
+        dw_addr_t   address;
+        dw_addr_t   length;
+        dw_addr_t end_address() const { return address + length; }
+    } Descriptor;
+
+
+                    DWARFDebugArangeSet();
+        void        Clear();
+        void        SetOffset(uint32_t offset) { m_offset = offset; }
+        void        SetHeader(uint16_t version, uint32_t cu_offset, uint8_t addr_size, uint8_t seg_size);
+        void        AddDescriptor(const DWARFDebugArangeSet::Descriptor& range);
+        void        Compact();
+        bool        Extract(const lldb_private::DataExtractor &data, uint32_t* offset_ptr);
+        void        Dump(lldb_private::Stream *s) const;
+        dw_offset_t GetCompileUnitDIEOffset() const { return m_header.cu_offset; }
+        dw_offset_t GetOffsetOfNextEntry() const;
+        dw_offset_t FindAddress(dw_addr_t address) const;
+        uint32_t    NumDescriptors() const { return m_arange_descriptors.size(); }
+        const Header&       GetHeader() const { return m_header; }
+        const Descriptor*   GetDescriptor(uint32_t i) const
+        {
+            if (i < m_arange_descriptors.size())
+                return &m_arange_descriptors[i];
+            return NULL;
+        }
+
+
+protected:
+    typedef std::vector<Descriptor>         DescriptorColl;
+    typedef DescriptorColl::iterator        DescriptorIter;
+    typedef DescriptorColl::const_iterator  DescriptorConstIter;
+
+
+    uint32_t        m_offset;
+    Header          m_header;
+    DescriptorColl  m_arange_descriptors;
+};
+
+#endif  // SymbolFileDWARF_DWARFDebugArangeSet_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
new file mode 100644
index 0000000..a3213e0
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
@@ -0,0 +1,343 @@
+//===-- DWARFDebugAranges.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugAranges.h"
+
+#include <assert.h>
+
+#include <algorithm>
+
+#include "lldb/Core/Stream.h"
+
+#include "SymbolFileDWARF.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFCompileUnit.h"
+
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Constructor
+//----------------------------------------------------------------------
+DWARFDebugAranges::DWARFDebugAranges() :
+    m_aranges()
+{
+}
+
+
+//----------------------------------------------------------------------
+// Compare function DWARFDebugAranges::Range structures
+//----------------------------------------------------------------------
+static bool RangeLessThan (const DWARFDebugAranges::Range& range1, const DWARFDebugAranges::Range& range2)
+{
+//  printf("RangeLessThan -- 0x%8.8x < 0x%8.8x ? %d\n", range1.lo_pc, range1.lo_pc, range1.lo_pc < range2.lo_pc);
+    return range1.lo_pc < range2.lo_pc;
+}
+
+//----------------------------------------------------------------------
+// CountArangeDescriptors
+//----------------------------------------------------------------------
+class CountArangeDescriptors
+{
+public:
+    CountArangeDescriptors (uint32_t& count_ref) : count(count_ref)
+    {
+//      printf("constructor CountArangeDescriptors()\n");
+    }
+    void operator() (const DWARFDebugArangeSet& set)
+    {
+        count += set.NumDescriptors();
+    }
+    uint32_t& count;
+};
+
+//----------------------------------------------------------------------
+// AddArangeDescriptors
+//----------------------------------------------------------------------
+class AddArangeDescriptors
+{
+public:
+    AddArangeDescriptors (DWARFDebugAranges::RangeColl& ranges) : range_collection(ranges) {}
+    void operator() (const DWARFDebugArangeSet& set)
+    {
+        const DWARFDebugArangeSet::Descriptor* arange_desc_ptr;
+        DWARFDebugAranges::Range range;
+        range.offset = set.GetCompileUnitDIEOffset();
+
+        for (uint32_t i=0; arange_desc_ptr = set.GetDescriptor(i); ++i)
+        {
+            range.lo_pc = arange_desc_ptr->address;
+            range.hi_pc = arange_desc_ptr->address + arange_desc_ptr->length;
+
+            // Insert each item in increasing address order so binary searching
+            // can later be done!
+            DWARFDebugAranges::RangeColl::iterator insert_pos = lower_bound(range_collection.begin(), range_collection.end(), range, RangeLessThan);
+            range_collection.insert(insert_pos, range);
+        }
+    }
+    DWARFDebugAranges::RangeColl& range_collection;
+};
+
+//----------------------------------------------------------------------
+// PrintRange
+//----------------------------------------------------------------------
+static void PrintRange(const DWARFDebugAranges::Range& range)
+{
+    // Cast the address values in case the address type is compiled as 32 bit
+    printf("0x%8.8x: [0x%8.8llx - 0x%8.8llx)\n", range.offset, (uint64_t)range.lo_pc, (uint64_t)range.hi_pc);
+}
+
+//----------------------------------------------------------------------
+// Extract
+//----------------------------------------------------------------------
+bool
+DWARFDebugAranges::Extract(const DataExtractor &debug_aranges_data)
+{
+    if (debug_aranges_data.ValidOffset(0))
+    {
+        uint32_t offset = 0;
+
+        typedef std::vector<DWARFDebugArangeSet>    SetCollection;
+        typedef SetCollection::const_iterator       SetCollectionIter;
+        SetCollection sets;
+
+        DWARFDebugArangeSet set;
+        Range range;
+        while (set.Extract(debug_aranges_data, &offset))
+            sets.push_back(set);
+
+        uint32_t count = 0;
+
+        for_each(sets.begin(), sets.end(), CountArangeDescriptors(count));
+
+        if (count > 0)
+        {
+            m_aranges.reserve(count);
+            AddArangeDescriptors range_adder(m_aranges);
+            for_each(sets.begin(), sets.end(), range_adder);
+        }
+
+    //  puts("\n\nDWARFDebugAranges list is:\n");
+    //  for_each(m_aranges.begin(), m_aranges.end(), PrintRange);
+    }
+    return false;
+}
+
+//----------------------------------------------------------------------
+// Generate
+//----------------------------------------------------------------------
+bool
+DWARFDebugAranges::Generate(SymbolFileDWARF* dwarf2Data)
+{
+    Clear();
+    DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
+    if (debug_info)
+    {
+        uint32_t cu_idx = 0;
+        const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
+        for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
+        {
+            DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
+            if (cu)
+                cu->DIE()->BuildAddressRangeTable(dwarf2Data, cu, this);
+        }
+    }
+    return !IsEmpty();
+}
+
+
+void
+DWARFDebugAranges::Print() const
+{
+    puts("\n\nDWARFDebugAranges address range list is:\n");
+    for_each(m_aranges.begin(), m_aranges.end(), PrintRange);
+}
+
+
+void
+DWARFDebugAranges::Range::Dump(Stream *s) const
+{
+    s->Printf("{0x%8.8x}: [0x%8.8llx - 0x%8.8llx)\n", offset, lo_pc, hi_pc);
+}
+
+//----------------------------------------------------------------------
+// Dump
+//----------------------------------------------------------------------
+void
+DWARFDebugAranges::Dump(SymbolFileDWARF* dwarf2Data, Stream *s)
+{
+    const DataExtractor &debug_aranges_data = dwarf2Data->get_debug_aranges_data();
+    if (debug_aranges_data.ValidOffset(0))
+    {
+        uint32_t offset = 0;
+
+        DWARFDebugArangeSet set;
+        while (set.Extract(debug_aranges_data, &offset))
+            set.Dump(s);
+    }
+    else
+        s->PutCString("< EMPTY >\n");
+}
+
+
+//----------------------------------------------------------------------
+// AppendDebugRanges
+//----------------------------------------------------------------------
+//void
+//DWARFDebugAranges::AppendDebugRanges(BinaryStreamBuf& debug_ranges, dw_addr_t cu_base_addr, uint32_t addr_size) const
+//{
+//  if (!m_aranges.empty())
+//  {
+//      RangeCollIterator end = m_aranges.end();
+//      RangeCollIterator pos;
+//      RangeCollIterator lo_pos = end;
+//      for (pos = m_aranges.begin(); pos != end; ++pos)
+//      {
+//          if (lo_pos == end)
+//              lo_pos = pos;
+//
+//          RangeCollIterator next = pos + 1;
+//          if (next != end)
+//          {
+//              // Check to see if we can combine two consecutive ranges?
+//              if (pos->hi_pc == next->lo_pc)
+//                  continue;   // We can combine them!
+//          }
+//
+//          if (cu_base_addr == 0 || cu_base_addr == DW_INVALID_ADDRESS)
+//          {
+//              debug_ranges.AppendMax64(lo_pos->lo_pc, addr_size);
+//              debug_ranges.AppendMax64(pos->hi_pc, addr_size);
+//          }
+//          else
+//          {
+//              assert(lo_pos->lo_pc >= cu_base_addr);
+//              assert(pos->hi_pc >= cu_base_addr);
+//              debug_ranges.AppendMax64(lo_pos->lo_pc - cu_base_addr, addr_size);
+//              debug_ranges.AppendMax64(pos->hi_pc - cu_base_addr, addr_size);
+//          }
+//
+//          // Reset the low part of the next address range
+//          lo_pos = end;
+//      }
+//  }
+//  // Terminate the .debug_ranges with two zero addresses
+//  debug_ranges.AppendMax64(0, addr_size);
+//  debug_ranges.AppendMax64(0, addr_size);
+//
+//}
+//
+//----------------------------------------------------------------------
+// ArangeSetContainsAddress
+//----------------------------------------------------------------------
+class ArangeSetContainsAddress
+{
+public:
+    ArangeSetContainsAddress (dw_addr_t the_address) : address(the_address), offset(DW_INVALID_OFFSET) {}
+    bool operator() (const DWARFDebugArangeSet& set)
+    {
+        offset = set.FindAddress(address);
+        return (offset != DW_INVALID_OFFSET);
+    }
+    const dw_addr_t address;
+    dw_offset_t offset;
+};
+
+
+//----------------------------------------------------------------------
+// InsertRange
+//----------------------------------------------------------------------
+void
+DWARFDebugAranges::InsertRange(dw_offset_t offset, dw_addr_t low_pc, dw_addr_t high_pc)
+{
+    // Insert each item in increasing address order so binary searching
+    // can later be done!
+    DWARFDebugAranges::Range range(low_pc, high_pc, offset);
+    InsertRange(range);
+}
+
+//----------------------------------------------------------------------
+// InsertRange
+//----------------------------------------------------------------------
+void
+DWARFDebugAranges::InsertRange(const DWARFDebugAranges::Range& range)
+{
+    // Insert each item in increasing address order so binary searching
+    // can later be done!
+    RangeColl::iterator insert_pos = lower_bound(m_aranges.begin(), m_aranges.end(), range, RangeLessThan);
+    m_aranges.insert(insert_pos, range);
+}
+
+
+//----------------------------------------------------------------------
+// FindAddress
+//----------------------------------------------------------------------
+dw_offset_t
+DWARFDebugAranges::FindAddress(dw_addr_t address) const
+{
+    if ( !m_aranges.empty() )
+    {
+        DWARFDebugAranges::Range range(address);
+        DWARFDebugAranges::RangeCollIterator begin = m_aranges.begin();
+        DWARFDebugAranges::RangeCollIterator end = m_aranges.end();
+        DWARFDebugAranges::RangeCollIterator pos = lower_bound(begin, end, range, RangeLessThan);
+
+        if ((pos != end) && (pos->lo_pc <= address && address < pos->hi_pc))
+        {
+        //  printf("FindAddress(1) found 0x%8.8x in compile unit: 0x%8.8x\n", address, pos->offset);
+            return pos->offset;
+        }
+        else if (pos != begin)
+        {
+            --pos;
+            if ((pos->lo_pc <= address) && (address < pos->hi_pc))
+            {
+            //  printf("FindAddress(2) found 0x%8.8x in compile unit: 0x%8.8x\n", address, pos->offset);
+                return (*pos).offset;
+            }
+        }
+    }
+    return DW_INVALID_OFFSET;
+}
+
+//----------------------------------------------------------------------
+// AllRangesAreContiguous
+//----------------------------------------------------------------------
+bool
+DWARFDebugAranges::AllRangesAreContiguous(dw_addr_t& lo_pc, dw_addr_t& hi_pc) const
+{
+    if (m_aranges.empty())
+        return false;
+
+    DWARFDebugAranges::RangeCollIterator begin = m_aranges.begin();
+    DWARFDebugAranges::RangeCollIterator end = m_aranges.end();
+    DWARFDebugAranges::RangeCollIterator pos;
+    dw_addr_t next_addr = 0;
+
+    for (pos = begin; pos != end; ++pos)
+    {
+        if ((pos != begin) && (pos->lo_pc != next_addr))
+            return false;
+        next_addr = pos->hi_pc;
+    }
+    lo_pc = m_aranges.front().lo_pc;    // We checked for empty at the start of function so front() will be valid
+    hi_pc = m_aranges.back().hi_pc;     // We checked for empty at the start of function so back() will be valid
+    return true;
+}
+
+bool
+DWARFDebugAranges::GetMaxRange(dw_addr_t& lo_pc, dw_addr_t& hi_pc) const
+{
+    if (m_aranges.empty())
+        return false;
+
+    lo_pc = m_aranges.front().lo_pc;    // We checked for empty at the start of function so front() will be valid
+    hi_pc = m_aranges.back().hi_pc;     // We checked for empty at the start of function so back() will be valid
+    return true;
+}
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
new file mode 100644
index 0000000..f3db949
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
@@ -0,0 +1,98 @@
+//===-- DWARFDebugAranges.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_DWARFDebugAranges_h_
+#define SymbolFileDWARF_DWARFDebugAranges_h_
+
+#include "DWARFDebugArangeSet.h"
+#include <list>
+
+class SymbolFileDWARF;
+
+class DWARFDebugAranges
+{
+public:
+    struct Range
+    {
+        Range(
+            dw_addr_t   _lo_pc = DW_INVALID_ADDRESS,
+            dw_addr_t   _hi_pc = DW_INVALID_ADDRESS,
+            dw_offset_t _offset = DW_INVALID_OFFSET) :
+                lo_pc(_lo_pc),
+                hi_pc(_hi_pc),
+                offset(_offset)
+        {
+        }
+
+        void Clear()
+        {
+            lo_pc = hi_pc = DW_INVALID_ADDRESS;
+            offset = DW_INVALID_OFFSET;
+        }
+
+        bool ValidRange() const
+        {
+            return hi_pc > lo_pc;
+        }
+
+        bool Contains(const Range& range) const
+        {
+            return lo_pc <= range.lo_pc && range.hi_pc <= hi_pc;
+        }
+
+        void Dump(lldb_private::Stream *s) const;
+        dw_addr_t   lo_pc;      // Start of address range
+        dw_addr_t   hi_pc;      // End of address range (not including this address)
+        dw_offset_t offset;     // Offset of the compile unit or die
+    };
+
+                DWARFDebugAranges();
+
+    void        Clear() { m_aranges.clear(); }
+    bool        AllRangesAreContiguous(dw_addr_t& lo_pc, dw_addr_t& hi_pc) const;
+    bool        GetMaxRange(dw_addr_t& lo_pc, dw_addr_t& hi_pc) const;
+    bool        Extract(const lldb_private::DataExtractor &debug_aranges_data);
+    bool        Generate(SymbolFileDWARF* dwarf2Data);
+    void        InsertRange(dw_offset_t cu_offset, dw_addr_t low_pc, dw_addr_t high_pc);
+    void        InsertRange(const DWARFDebugAranges::Range& range);
+    const Range* RangeAtIndex(uint32_t idx) const
+                {
+                    if (idx < m_aranges.size())
+                        return &m_aranges[idx];
+                    return NULL;
+                }
+    void        Print() const;
+    dw_offset_t FindAddress(dw_addr_t address) const;
+    bool        IsEmpty() const { return m_aranges.empty(); }
+    void        Dump(lldb_private::Stream *s);
+    uint32_t    NumRanges() const
+                {
+                    return m_aranges.size();
+                }
+
+    dw_offset_t OffsetAtIndex(uint32_t idx) const
+                {
+                    if (idx < m_aranges.size())
+                        return m_aranges[idx].offset;
+                    return DW_INVALID_OFFSET;
+                }
+//  void    AppendDebugRanges(BinaryStreamBuf& debug_ranges, dw_addr_t cu_base_addr, uint32_t addr_size) const;
+
+    static void Dump(SymbolFileDWARF* dwarf2Data, lldb_private::Stream *s);
+
+    typedef std::vector<Range>              RangeColl;
+    typedef RangeColl::const_iterator       RangeCollIterator;
+
+protected:
+
+    RangeColl m_aranges;
+};
+
+
+#endif  // SymbolFileDWARF_DWARFDebugAranges_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
new file mode 100644
index 0000000..fcb0ccf
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
@@ -0,0 +1,1206 @@
+//===-- DWARFDebugInfo.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolFileDWARF.h"
+
+#include <algorithm>
+#include <set>
+
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/Stream.h"
+
+#include "DWARFDebugInfo.h"
+#include "DWARFCompileUnit.h"
+#include "DWARFDebugAranges.h"
+#include "DWARFDebugInfoEntry.h"
+#include "DWARFFormValue.h"
+
+using namespace lldb_private;
+using namespace std;
+
+//----------------------------------------------------------------------
+// Constructor
+//----------------------------------------------------------------------
+DWARFDebugInfo::DWARFDebugInfo() :
+    m_dwarf2Data(NULL),
+    m_compile_units()
+{
+}
+
+//----------------------------------------------------------------------
+// SetDwarfData
+//----------------------------------------------------------------------
+void
+DWARFDebugInfo::SetDwarfData(SymbolFileDWARF* dwarf2Data)
+{
+    m_dwarf2Data = dwarf2Data;
+    m_compile_units.clear();
+}
+
+//----------------------------------------------------------------------
+// BuildDIEAddressRangeTable
+//----------------------------------------------------------------------
+bool
+DWARFDebugInfo::BuildFunctionAddressRangeTable(DWARFDebugAranges* debug_aranges)
+{
+    const uint32_t num_compile_units = GetNumCompileUnits();
+    uint32_t idx;
+    for (idx = 0; idx < num_compile_units; ++idx)
+    {
+        DWARFCompileUnit* cu = GetCompileUnitAtIndex (idx);
+        if (cu)
+        {
+            cu->DIE()->BuildFunctionAddressRangeTable(m_dwarf2Data, cu, debug_aranges);
+        }
+    }
+    return !debug_aranges->IsEmpty();
+}
+
+//----------------------------------------------------------------------
+// LookupAddress
+//----------------------------------------------------------------------
+bool
+DWARFDebugInfo::LookupAddress
+(
+    const dw_addr_t address,
+    const dw_offset_t hint_die_offset,
+    DWARFCompileUnitSP& cu_sp,
+    DWARFDebugInfoEntry** function_die,
+    DWARFDebugInfoEntry** block_die
+)
+{
+
+    if (hint_die_offset != DW_INVALID_OFFSET)
+        cu_sp = GetCompileUnit(hint_die_offset);
+    else
+    {
+        // Get a non const version of the address ranges
+        DWARFDebugAranges* debug_aranges = ((SymbolFileDWARF*)m_dwarf2Data)->DebugAranges();
+
+        if (debug_aranges != NULL)
+        {
+            // If we have an empty address ranges section, lets build a sorted
+            // table ourselves by going through all of the debug information so we
+            // can do quick subsequent searches.
+
+            if (debug_aranges->IsEmpty())
+            {
+                const uint32_t num_compile_units = GetNumCompileUnits();
+                uint32_t idx;
+                for (idx = 0; idx < num_compile_units; ++idx)
+                {
+                    DWARFCompileUnit* cu = GetCompileUnitAtIndex(idx);
+                    if (cu)
+                        cu->DIE()->BuildAddressRangeTable(m_dwarf2Data, cu, debug_aranges);
+                }
+            }
+            cu_sp = GetCompileUnit(debug_aranges->FindAddress(address));
+        }
+    }
+
+    if (cu_sp.get())
+    {
+        if (cu_sp->LookupAddress(address, function_die, block_die))
+            return true;
+        cu_sp.reset();
+    }
+    else
+    {
+        // The hint_die_offset may have been a pointer to the actual item that
+        // we are looking for
+        DWARFDebugInfoEntry* die_ptr = GetDIEPtr(hint_die_offset, &cu_sp);
+        if (die_ptr)
+        {
+            if (cu_sp.get())
+            {
+                if (function_die || block_die)
+                    return die_ptr->LookupAddress(address, m_dwarf2Data, cu_sp.get(), function_die, block_die);
+
+                // We only wanted the compile unit that contained this address
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+
+void
+DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded()
+{
+    if (m_compile_units.empty())
+    {
+        if (m_dwarf2Data != NULL)
+        {
+            uint32_t offset = 0;
+            const DataExtractor &debug_info_data = m_dwarf2Data->get_debug_info_data();
+            while (debug_info_data.ValidOffset(offset))
+            {
+                DWARFCompileUnitSP cu_sp(new DWARFCompileUnit(m_dwarf2Data));
+                // Out of memory?
+                if (cu_sp.get() == NULL)
+                    break;
+
+                if (cu_sp->Extract(debug_info_data, &offset) == false)
+                    break;
+
+                m_compile_units.push_back(cu_sp);
+
+                offset = cu_sp->GetNextCompileUnitOffset();
+            }
+        }
+    }
+}
+
+uint32_t
+DWARFDebugInfo::GetNumCompileUnits()
+{
+    ParseCompileUnitHeadersIfNeeded();
+    return m_compile_units.size();
+}
+
+DWARFCompileUnit*
+DWARFDebugInfo::GetCompileUnitAtIndex(uint32_t idx)
+{
+    DWARFCompileUnit* cu = NULL;
+    if (idx < GetNumCompileUnits())
+        cu = m_compile_units[idx].get();
+    return cu;
+}
+
+static bool CompileUnitOffsetLessThan (const DWARFCompileUnitSP& a, const DWARFCompileUnitSP& b)
+{
+    return a->GetOffset() < b->GetOffset();
+}
+
+
+static int
+CompareDWARFCompileUnitSPOffset (const void *key, const void *arrmem)
+{
+    const dw_offset_t key_cu_offset = *(dw_offset_t*) key;
+    const dw_offset_t cu_offset = ((DWARFCompileUnitSP *)arrmem)->get()->GetOffset();
+    if (key_cu_offset < cu_offset)
+        return -1;
+    if (key_cu_offset > cu_offset)
+        return 1;
+    return 0;
+}
+
+DWARFCompileUnitSP
+DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr)
+{
+    DWARFCompileUnitSP cu_sp;
+    uint32_t cu_idx = DW_INVALID_INDEX;
+    if (cu_offset != DW_INVALID_OFFSET)
+    {
+        ParseCompileUnitHeadersIfNeeded();
+
+        DWARFCompileUnitSP* match = (DWARFCompileUnitSP*)bsearch(&cu_offset, &m_compile_units[0], m_compile_units.size(), sizeof(DWARFCompileUnitSP), CompareDWARFCompileUnitSPOffset);
+        if (match)
+        {
+            cu_sp = *match;
+            cu_idx = match - &m_compile_units[0];
+        }
+    }
+    if (idx_ptr)
+        *idx_ptr = cu_idx;
+    return cu_sp;
+}
+
+DWARFCompileUnitSP
+DWARFDebugInfo::GetCompileUnitContainingDIE(dw_offset_t die_offset)
+{
+    DWARFCompileUnitSP cu_sp;
+    if (die_offset != DW_INVALID_OFFSET)
+    {
+        ParseCompileUnitHeadersIfNeeded();
+
+        CompileUnitColl::const_iterator end_pos = m_compile_units.end();
+        CompileUnitColl::const_iterator pos;
+
+        for (pos = m_compile_units.begin(); pos != end_pos; ++pos)
+        {
+            dw_offset_t cu_start_offset = (*pos)->GetOffset();
+            dw_offset_t cu_end_offset = (*pos)->GetNextCompileUnitOffset();
+            if (cu_start_offset <= die_offset && die_offset < cu_end_offset)
+            {
+                cu_sp = *pos;
+                break;
+            }
+        }
+    }
+    return cu_sp;
+}
+
+//----------------------------------------------------------------------
+// Compare function DWARFDebugAranges::Range structures
+//----------------------------------------------------------------------
+static bool CompareDIEOffset (const DWARFDebugInfoEntry& die1, const DWARFDebugInfoEntry& die2)
+{
+    return die1.GetOffset() < die2.GetOffset();
+}
+
+
+//----------------------------------------------------------------------
+// GetDIE()
+//
+// Get the DIE (Debug Information Entry) with the specified offset.
+//----------------------------------------------------------------------
+DWARFDebugInfoEntry*
+DWARFDebugInfo::GetDIEPtr(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr)
+{
+    DWARFCompileUnitSP cu_sp(GetCompileUnitContainingDIE(die_offset));
+    if (cu_sp_ptr)
+        *cu_sp_ptr = cu_sp;
+    if (cu_sp.get())
+        return cu_sp->GetDIEPtr(die_offset);
+    return NULL;    // Not found in any compile units
+}
+
+const DWARFDebugInfoEntry*
+DWARFDebugInfo::GetDIEPtrContainingOffset(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr)
+{
+    DWARFCompileUnitSP cu_sp(GetCompileUnitContainingDIE(die_offset));
+    if (cu_sp_ptr)
+        *cu_sp_ptr = cu_sp;
+    if (cu_sp.get())
+        return cu_sp->GetDIEPtrContainingOffset(die_offset);
+
+    return NULL;    // Not found in any compile units
+
+}
+
+//----------------------------------------------------------------------
+// DWARFDebugInfo_ParseCallback
+//
+// A callback function for the static DWARFDebugInfo::Parse() function
+// that gets parses all compile units and DIE's into an internate
+// representation for further modification.
+//----------------------------------------------------------------------
+
+static dw_offset_t
+DWARFDebugInfo_ParseCallback
+(
+    SymbolFileDWARF* dwarf2Data,
+    DWARFCompileUnitSP& cu_sp,
+    DWARFDebugInfoEntry* die,
+    const dw_offset_t next_offset,
+    const uint32_t curr_depth,
+    void* userData
+)
+{
+    DWARFDebugInfo* debug_info = (DWARFDebugInfo*)userData;
+    DWARFCompileUnit* cu = cu_sp.get();
+    if (die)
+    {
+        cu->AddDIE(*die);
+    }
+    else if (cu)
+    {
+        debug_info->AddCompileUnit(cu_sp);
+    }
+
+    // Just return the current offset to parse the next CU or DIE entry
+    return next_offset;
+}
+
+//----------------------------------------------------------------------
+// AddCompileUnit
+//----------------------------------------------------------------------
+void
+DWARFDebugInfo::AddCompileUnit(DWARFCompileUnitSP& cu)
+{
+    m_compile_units.push_back(cu);
+}
+
+/*
+void
+DWARFDebugInfo::AddDIE(DWARFDebugInfoEntry& die)
+{
+    m_die_array.push_back(die);
+}
+*/
+
+
+
+
+//----------------------------------------------------------------------
+// Parse
+//
+// Parses the .debug_info section and uses the .debug_abbrev section
+// and various other sections in the SymbolFileDWARF class and calls the
+// supplied callback function each time a compile unit header, or debug
+// information entry is successfully parsed. This function can be used
+// for different tasks such as parsing the file contents into a
+// structured data, dumping, verifying and much more.
+//----------------------------------------------------------------------
+void
+DWARFDebugInfo::Parse(SymbolFileDWARF* dwarf2Data, Callback callback, void* userData)
+{
+    if (dwarf2Data)
+    {
+        uint32_t offset = 0;
+        uint32_t depth = 0;
+        DWARFCompileUnitSP cu(new DWARFCompileUnit(dwarf2Data));
+        if (cu.get() == NULL)
+            return;
+        DWARFDebugInfoEntry die;
+
+        while (cu->Extract(dwarf2Data->get_debug_info_data(), &offset))
+        {
+            const dw_offset_t next_cu_offset = cu->GetNextCompileUnitOffset();
+
+            depth = 0;
+            // Call the callback funtion with no DIE pointer for the compile unit
+            // and get the offset that we are to continue to parse from
+            offset = callback(dwarf2Data, cu, NULL, offset, depth, userData);
+
+            // Make sure we are within our compile unit
+            if (offset < next_cu_offset)
+            {
+                // We are in our compile unit, parse starting at the offset
+                // we were told to parse
+                bool done = false;
+                while (!done && die.Extract(dwarf2Data, cu.get(), &offset))
+                {
+                    // Call the callback funtion with DIE pointer that falls within the compile unit
+                    offset = callback(dwarf2Data, cu, &die, offset, depth, userData);
+
+                    if (die.IsNULL())
+                    {
+                        if (depth)
+                            --depth;
+                        else
+                            done = true;    // We are done with this compile unit!
+                    }
+                    else if (die.HasChildren())
+                        ++depth;
+                }
+            }
+
+            // Make sure the offset returned is valid, and if not stop parsing.
+            // Returning DW_INVALID_OFFSET from this callback is a good way to end
+            // all parsing
+            if (!dwarf2Data->get_debug_info_data().ValidOffset(offset))
+                break;
+
+            // See if during the callback anyone retained a copy of the compile
+            // unit other than ourselves and if so, let whomever did own the object
+            // and create a new one for our own use!
+            if (!cu.unique())
+                cu.reset(new DWARFCompileUnit(dwarf2Data));
+
+
+            // Make sure we start on a propper
+            offset = next_cu_offset;
+        }
+    }
+}
+
+/*
+typedef struct AddressRangeTag
+{
+    dw_addr_t   lo_pc;
+    dw_addr_t   hi_pc;
+    dw_offset_t die_offset;
+} AddressRange;
+*/
+struct DIERange
+{
+    DIERange() :
+        range(),
+        lo_die_offset(),
+        hi_die_offset()
+    {
+    }
+
+    DWARFDebugAranges::Range range;
+    dw_offset_t lo_die_offset;
+    dw_offset_t hi_die_offset;
+};
+
+typedef struct DwarfStat
+{
+    DwarfStat() : count(0), byte_size(0) {}
+    uint32_t count;
+    uint32_t byte_size;
+} DwarfStat;
+
+typedef map<dw_attr_t, DwarfStat> DwarfAttrStatMap;
+
+typedef struct DIEStat
+{
+    DIEStat() : count(0), byte_size(0), attr_stats() {}
+    uint32_t count;
+    uint32_t byte_size;
+    DwarfAttrStatMap attr_stats;
+} DIEStat;
+
+typedef map<dw_tag_t, DIEStat> DIEStatMap;
+struct VerifyInfo
+{
+    VerifyInfo(Stream* the_strm) :
+        strm(the_strm),
+        die_ranges(),
+        addr_range_errors(0),
+        sibling_errors(0),
+        die_stats()
+    {
+    }
+
+    Stream* strm;
+    vector<DIERange> die_ranges;
+    uint32_t addr_range_errors;
+    uint32_t sibling_errors;
+    DIEStatMap die_stats;
+
+    DISALLOW_COPY_AND_ASSIGN(VerifyInfo);
+
+};
+
+
+//----------------------------------------------------------------------
+// VerifyCallback
+//
+// A callback function for the static DWARFDebugInfo::Parse() function
+// that gets called each time a compile unit header or debug information
+// entry is successfully parsed.
+//
+// This function will verify the DWARF information is well formed by
+// making sure that any DW_TAG_compile_unit tags that have valid address
+// ranges (DW_AT_low_pc and DW_AT_high_pc) have no gaps in the address
+// ranges of it contained DW_TAG_subprogram tags. Also the sibling chain
+// and relationships are verified to make sure nothing gets hosed up
+// when dead stripping occurs.
+//----------------------------------------------------------------------
+
+static dw_offset_t
+VerifyCallback
+(
+    SymbolFileDWARF* dwarf2Data,
+    DWARFCompileUnitSP& cu_sp,
+    DWARFDebugInfoEntry* die,
+    const dw_offset_t next_offset,
+    const uint32_t curr_depth,
+    void* userData
+)
+{
+    VerifyInfo* verifyInfo = (VerifyInfo*)userData;
+
+    const DWARFCompileUnit* cu = cu_sp.get();
+    Stream *s = verifyInfo->strm;
+    bool verbose = s->GetVerbose();
+    if (die)
+    {
+    //  die->Dump(dwarf2Data, cu, f);
+        const DWARFAbbreviationDeclaration* abbrevDecl = die->GetAbbreviationDeclarationPtr();
+        // We have a DIE entry
+        if (abbrevDecl)
+        {
+            const dw_offset_t die_offset = die->GetOffset();
+            const dw_offset_t sibling = die->GetAttributeValueAsReference(dwarf2Data, cu, DW_AT_sibling, DW_INVALID_OFFSET);
+
+            if (sibling != DW_INVALID_OFFSET)
+            {
+                if (sibling <= next_offset)
+                {
+                    if (verifyInfo->sibling_errors++ == 0)
+                        s->Printf("ERROR\n");
+                    s->Printf("    0x%8.8x: sibling attribyte (0x%8.8x) in this die is not valid: it is less than this DIE or some of its contents.\n", die->GetOffset(), sibling);
+                }
+                else if (sibling > verifyInfo->die_ranges.back().hi_die_offset)
+                {
+                    if (verifyInfo->sibling_errors++ == 0)
+                        s->Printf("ERROR\n");
+                    s->Printf("    0x%8.8x: sibling attribute (0x%8.8x) in this DIE is not valid: it is greater than the end of the parent scope.\n", die->GetOffset(), sibling);
+                }
+            }
+
+            if ((die_offset < verifyInfo->die_ranges.back().lo_die_offset) || (die_offset >= verifyInfo->die_ranges.back().hi_die_offset))
+            {
+                if (verifyInfo->sibling_errors++ == 0)
+                    s->Printf("ERROR\n");
+                s->Printf("    0x%8.8x: DIE offset is not within the parent DIE range {0x%8.8x}: (0x%8.8x - 0x%8.8x)\n",
+                        die->GetOffset(),
+                        verifyInfo->die_ranges.back().range.offset,
+                        verifyInfo->die_ranges.back().lo_die_offset,
+                        verifyInfo->die_ranges.back().hi_die_offset);
+
+            }
+
+            dw_tag_t tag = abbrevDecl->Tag();
+
+            // Keep some stats on this DWARF file
+            verifyInfo->die_stats[tag].count++;
+            verifyInfo->die_stats[tag].byte_size += (next_offset - die->GetOffset());
+
+            if (verbose)
+            {
+                DIEStat& tag_stat = verifyInfo->die_stats[tag];
+
+                const DataExtractor& debug_info = dwarf2Data->get_debug_info_data();
+
+                dw_offset_t offset = die->GetOffset();
+                // Skip the abbreviation code so we are at the data for the attributes
+                debug_info.Skip_LEB128(&offset);
+
+                const uint32_t numAttributes = abbrevDecl->NumAttributes();
+                dw_attr_t attr;
+                dw_form_t form;
+                for (uint32_t idx = 0; idx < numAttributes; ++idx)
+                {
+                    dw_offset_t start_offset = offset;
+                    abbrevDecl->GetAttrAndFormByIndexUnchecked(idx, attr, form);
+                    DWARFFormValue::SkipValue(form, debug_info, &offset, cu);
+
+                    if (tag_stat.attr_stats.find(attr) == tag_stat.attr_stats.end())
+                    {
+                        tag_stat.attr_stats[attr].count = 0;
+                        tag_stat.attr_stats[attr].byte_size = 0;
+                    }
+
+                    tag_stat.attr_stats[attr].count++;
+                    tag_stat.attr_stats[attr].byte_size += offset - start_offset;
+                }
+            }
+
+            DWARFDebugAranges::Range range;
+            range.offset = die->GetOffset();
+
+            switch (tag)
+            {
+            case DW_TAG_compile_unit:
+                // Check for previous subroutines that were within a previous
+                //
+            //  VerifyAddressRangesForCU(verifyInfo);
+                // Remember which compile unit we are dealing with so we can verify
+                // the address ranges within it (if any) are contiguous. The DWARF
+                // spec states that if a compile unit TAG has high and low PC
+                // attributes, there must be no gaps in the address ranges of it's
+                // contained subtroutines. If there are gaps, the high and low PC
+                // must not be in the DW_TAG_compile_unit's attributes. Errors like
+                // this can crop up when optimized code is dead stripped and the debug
+                // information isn't properly fixed up for output.
+                range.lo_pc = die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, DW_INVALID_ADDRESS);
+                if (range.lo_pc != DW_INVALID_ADDRESS)
+                {
+                    range.hi_pc = die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_high_pc, DW_INVALID_ADDRESS);
+                    if (s->GetVerbose())
+                    {
+                        s->Printf("\n    CU ");
+                        range.Dump(s);
+                    }
+                }
+                else
+                {
+                    range.lo_pc = die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_entry_pc, DW_INVALID_ADDRESS);
+                }
+                break;
+
+            case DW_TAG_subprogram:
+                // If the DW_TAG_compile_unit that contained this function had a
+                // valid address range, add all of the valid subroutine address
+                // ranges to a collection of addresses which will be sorted
+                // and verified right before the next DW_TAG_compile_unit is
+                // processed to make sure that there are no gaps in the address
+                // range.
+                range.lo_pc = die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, DW_INVALID_ADDRESS);
+                if (range.lo_pc != DW_INVALID_ADDRESS)
+                {
+                    range.hi_pc = die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_high_pc, DW_INVALID_ADDRESS);
+                    if (range.hi_pc != DW_INVALID_ADDRESS)
+                    {
+                        range.offset = die->GetOffset();
+                        bool valid = range.ValidRange();
+                        if (!valid || s->GetVerbose())
+                        {
+                            s->Printf("\n  FUNC ");
+                            range.Dump(s);
+                            if (!valid)
+                            {
+                                ++verifyInfo->addr_range_errors;
+                                s->Printf(" ERROR: Invalid address range for function.");
+                            }
+                        }
+
+                        // Only add to our subroutine ranges if our compile unit has a valid address range
+                    //  if (valid && verifyInfo->die_ranges.size() >= 2 && verifyInfo->die_ranges[1].range.ValidRange())
+                    //      verifyInfo->subroutine_ranges.InsertRange(range);
+                    }
+                }
+                break;
+
+            case DW_TAG_lexical_block:
+            case DW_TAG_inlined_subroutine:
+                {
+                    range.lo_pc = die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, DW_INVALID_ADDRESS);
+                    if (range.lo_pc != DW_INVALID_ADDRESS)
+                    {
+                        range.hi_pc = die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_high_pc, DW_INVALID_ADDRESS);
+                        if (range.hi_pc != DW_INVALID_ADDRESS)
+                        {
+                            range.offset = die->GetOffset();
+                            bool valid = range.ValidRange();
+                            if (!valid || s->GetVerbose())
+                            {
+                                s->Printf("\n  BLCK ");
+                                range.Dump(s);
+                                if (!valid)
+                                {
+                                    ++verifyInfo->addr_range_errors;
+                                    s->Printf(" ERROR: Invalid address range for block or inlined subroutine.");
+                                }
+                            }
+                        }
+                    }
+                }
+                break;
+            }
+
+            if (range.ValidRange() && verifyInfo->die_ranges.back().range.ValidRange())
+            {
+                if (!verifyInfo->die_ranges.back().range.Contains(range))
+                {
+                    ++verifyInfo->addr_range_errors;
+                    s->Printf("\n       ");
+                    range.Dump(s);
+                    s->Printf(" ERROR: Range is not in parent");
+                    verifyInfo->die_ranges.back().range.Dump(s);
+                }
+            }
+
+            if (die->HasChildren())
+            {
+                // Keep tabs on the valid address ranges for the current item to make
+                // sure that it all fits (make sure the sibling offsets got fixed up
+                // correctly if any functions were dead stripped).
+                DIERange die_range;
+                die_range.range = range;
+                die_range.lo_die_offset = next_offset;
+                die_range.hi_die_offset = sibling;
+                if (die_range.hi_die_offset == DW_INVALID_OFFSET)
+                    die_range.hi_die_offset = verifyInfo->die_ranges.back().hi_die_offset;
+                verifyInfo->die_ranges.push_back(die_range);
+            }
+        }
+        else
+        {
+            // NULL entry
+            verifyInfo->die_ranges.pop_back();
+        }
+    }
+    else
+    {
+    //  cu->Dump(ostrm_ptr); // Dump the compile unit for the DIE
+        // We have a new comile unit header
+        verifyInfo->die_ranges.clear();
+        DIERange die_range;
+        die_range.range.offset  = cu->GetOffset();
+        die_range.lo_die_offset = next_offset;
+        die_range.hi_die_offset = cu->GetNextCompileUnitOffset();
+        verifyInfo->die_ranges.push_back(die_range);
+    }
+
+    // Just return the current offset to parse the next CU or DIE entry
+    return next_offset;
+}
+
+
+class CompareDIEStatSizes
+{
+public:
+    bool operator() (const DIEStatMap::const_iterator& pos1, const DIEStatMap::const_iterator& pos2) const
+    {
+        return pos1->second.byte_size <= pos2->second.byte_size;
+    }
+};
+
+class CompareAttrDIEStatSizes
+{
+public:
+    bool operator() (const DwarfAttrStatMap::const_iterator& pos1, const DwarfAttrStatMap::const_iterator& pos2) const
+    {
+        return pos1->second.byte_size <= pos2->second.byte_size;
+    }
+};
+
+//----------------------------------------------------------------------
+// Verify
+//
+// Verifies the DWARF information is valid.
+//----------------------------------------------------------------------
+void
+DWARFDebugInfo::Verify(Stream *s, SymbolFileDWARF* dwarf2Data)
+{
+    s->Printf("Verifying Compile Unit Header chain.....");
+    VerifyInfo verifyInfo(s);
+    verifyInfo.addr_range_errors = 0;
+    verifyInfo.sibling_errors = 0;
+
+    bool verbose = s->GetVerbose();
+
+    uint32_t offset = 0;
+    if (verbose)
+        s->EOL();
+//  vector<dw_offset_t> valid_cu_offsets;
+    DWARFCompileUnit cu (dwarf2Data);
+    bool success = true;
+    while ( success && dwarf2Data->get_debug_info_data().ValidOffset(offset+cu.Size()) )
+    {
+        success = cu.Extract (dwarf2Data->get_debug_info_data(), &offset);
+        if (!success)
+            s->Printf("ERROR\n");
+    //  else
+    //      valid_cu_offsets.push_back(cu.GetOffset());
+
+        cu.Verify(verifyInfo.strm);
+        offset = cu.GetNextCompileUnitOffset();
+    }
+
+    if (success)
+        s->Printf("OK\n");
+
+    s->Printf("Verifying address ranges and siblings...");
+    if (verbose)
+        s->EOL();
+    DWARFDebugInfo::Parse(dwarf2Data, VerifyCallback, &verifyInfo);
+
+//  VerifyAddressRangesForCU(&verifyInfo);
+
+    if (verifyInfo.addr_range_errors > 0)
+        s->Printf("\nERRORS - %u error(s) were found.\n", verifyInfo.addr_range_errors);
+    else
+        s->Printf("OK\n");
+
+    uint32_t total_category_sizes[kNumTagCategories] = {0};
+    uint32_t total_category_count[kNumTagCategories] = {0};
+    uint32_t total_die_count = 0;
+    uint32_t total_die_size = 0;
+
+    typedef set<DIEStatMap::const_iterator, CompareDIEStatSizes> DIEStatBySizeMap;
+
+    s->PutCString(  "\n"
+                "DWARF Statistics\n"
+                "Count    Size     Size %   Tag\n"
+                "-------- -------- -------- -------------------------------------------\n");
+    DIEStatBySizeMap statBySizeMap;
+    DIEStatMap::const_iterator pos;
+    DIEStatMap::const_iterator end_pos = verifyInfo.die_stats.end();
+    for (pos = verifyInfo.die_stats.begin(); pos != end_pos; ++pos)
+    {
+        const uint32_t die_count = pos->second.count;
+        const uint32_t die_size = pos->second.byte_size;
+
+        statBySizeMap.insert(pos);
+        total_die_count += die_count;
+        total_die_size += die_size;
+        DW_TAG_CategoryEnum category = get_tag_category(pos->first);
+        total_category_sizes[category] += die_size;
+        total_category_count[category] += die_count;
+    }
+
+    float total_die_size_float = total_die_size;
+
+    DIEStatBySizeMap::const_reverse_iterator size_pos;
+    DIEStatBySizeMap::const_reverse_iterator size_pos_end = statBySizeMap.rend();
+    float percentage;
+    for (size_pos = statBySizeMap.rbegin(); size_pos != size_pos_end; ++size_pos)
+    {
+        pos = *size_pos;
+
+        const DIEStat& tag_stat = pos->second;
+
+        const uint32_t die_count = tag_stat.count;
+        const uint32_t die_size = tag_stat.byte_size;
+        percentage = ((float)die_size/total_die_size_float)*100.0;
+        s->Printf("%7u %8u %2.2f%%     %s\n", die_count, die_size, percentage, DW_TAG_value_to_name(pos->first));
+
+        const DwarfAttrStatMap& attr_stats = tag_stat.attr_stats;
+        if (!attr_stats.empty())
+        {
+            typedef set<DwarfAttrStatMap::const_iterator, CompareAttrDIEStatSizes> DwarfAttrStatBySizeMap;
+            DwarfAttrStatBySizeMap attrStatBySizeMap;
+            DwarfAttrStatMap::const_iterator attr_stat_pos;
+            DwarfAttrStatMap::const_iterator attr_stat_pos_end = attr_stats.end();
+            for (attr_stat_pos = attr_stats.begin(); attr_stat_pos != attr_stat_pos_end; ++attr_stat_pos)
+            {
+                attrStatBySizeMap.insert(attr_stat_pos);
+            }
+
+            DwarfAttrStatBySizeMap::const_reverse_iterator attr_size_pos;
+            DwarfAttrStatBySizeMap::const_reverse_iterator attr_size_pos_end = attrStatBySizeMap.rend();
+            for (attr_size_pos = attrStatBySizeMap.rbegin(); attr_size_pos != attr_size_pos_end; ++attr_size_pos)
+            {
+                attr_stat_pos = *attr_size_pos;
+                percentage = ((float)attr_stat_pos->second.byte_size/die_size)*100.0;
+                s->Printf("%7u %8u %2.2f%%    %s\n", attr_stat_pos->second.count, attr_stat_pos->second.byte_size, percentage, DW_AT_value_to_name(attr_stat_pos->first));
+            }
+            s->EOL();
+        }
+    }
+
+    s->Printf("-------- -------- -------- -------------------------------------------\n");
+    s->Printf("%7u %8u 100.00% Total for all DIEs\n", total_die_count, total_die_size);
+
+    float total_category_percentages[kNumTagCategories] =
+    {
+        ((float)total_category_sizes[TagCategoryVariable]/total_die_size_float)*100.0,
+        ((float)total_category_sizes[TagCategoryType]/total_die_size_float)*100.0,
+        ((float)total_category_sizes[TagCategoryProgram]/total_die_size_float)*100.0
+    };
+
+    s->EOL();
+    s->Printf("%7u %8u %2.2f%%    %s\n", total_category_count[TagCategoryVariable], total_category_sizes[TagCategoryVariable],  total_category_percentages[TagCategoryVariable],    "Total for variable related DIEs");
+    s->Printf("%7u %8u %2.2f%%    %s\n", total_category_count[TagCategoryType],     total_category_sizes[TagCategoryType],      total_category_percentages[TagCategoryType],        "Total for type related DIEs");
+    s->Printf("%7u %8u %2.2f%%    %s\n", total_category_count[TagCategoryProgram],      total_category_sizes[TagCategoryProgram],   total_category_percentages[TagCategoryProgram],     "Total for program related DIEs");
+    s->Printf("\n\n");
+}
+
+typedef struct DumpInfo
+{
+    DumpInfo(Stream* init_strm, uint32_t off, uint32_t depth) :
+        strm(init_strm),
+        die_offset(off),
+        recurse_depth(depth),
+        found_depth(UINT_MAX),
+        found_die(false),
+        ancestors()
+    {
+    }
+    Stream* strm;
+    const uint32_t die_offset;
+    const uint32_t recurse_depth;
+    uint32_t found_depth;
+    bool found_die;
+    std::vector<DWARFDebugInfoEntry> ancestors;
+
+    DISALLOW_COPY_AND_ASSIGN(DumpInfo);
+} DumpInfo;
+
+//----------------------------------------------------------------------
+// DumpCallback
+//
+// A callback function for the static DWARFDebugInfo::Parse() function
+// that gets called each time a compile unit header or debug information
+// entry is successfully parsed.
+//
+// This function dump DWARF information and obey recurse depth and
+// wether a single DIE is to be dumped (or all of the data).
+//----------------------------------------------------------------------
+static dw_offset_t DumpCallback
+(
+    SymbolFileDWARF* dwarf2Data,
+    DWARFCompileUnitSP& cu_sp,
+    DWARFDebugInfoEntry* die,
+    const dw_offset_t next_offset,
+    const uint32_t curr_depth,
+    void* userData
+)
+{
+    DumpInfo* dumpInfo = (DumpInfo*)userData;
+
+    const DWARFCompileUnit* cu = cu_sp.get();
+
+    Stream *s = dumpInfo->strm;
+    bool show_parents = s->GetFlags().IsSet(DWARFDebugInfo::eDumpFlag_ShowAncestors);
+
+    if (die)
+    {
+        // Are we dumping everything?
+        if (dumpInfo->die_offset == DW_INVALID_OFFSET)
+        {
+            // Yes we are dumping everything. Obey our recurse level though
+            if (curr_depth < dumpInfo->recurse_depth)
+                die->Dump(dwarf2Data, cu, s, 0);
+        }
+        else
+        {
+            // We are dumping a specific DIE entry by offset
+            if (dumpInfo->die_offset == die->GetOffset())
+            {
+                // We found the DIE we were looking for, dump it!
+                if (show_parents)
+                {
+                    s->SetIndentLevel(0);
+                    const uint32_t num_ancestors = dumpInfo->ancestors.size();
+                    if (num_ancestors > 0)
+                    {
+                        for (uint32_t i=0; i<num_ancestors-1; ++i)
+                        {
+                            dumpInfo->ancestors[i].Dump(dwarf2Data, cu, s, 0);
+                            s->IndentMore();
+                        }
+                    }
+                }
+
+                dumpInfo->found_depth = curr_depth;
+
+                die->Dump(dwarf2Data, cu, s, 0);
+
+                // Note that we found the DIE we were looking for
+                dumpInfo->found_die = true;
+
+                // Since we are dumping a single DIE, if there are no children we are done!
+                if (!die->HasChildren() || dumpInfo->recurse_depth == 0)
+                    return DW_INVALID_OFFSET;   // Return an invalid address to end parsing
+            }
+            else if (dumpInfo->found_die)
+            {
+                // Are we done with all the children?
+                if (curr_depth <= dumpInfo->found_depth)
+                    return DW_INVALID_OFFSET;
+
+                // We have already found our DIE and are printing it's children. Obey
+                // our recurse depth and return an invalid offset if we get done
+                // dumping all the the children
+                if (dumpInfo->recurse_depth == UINT_MAX || curr_depth <= dumpInfo->found_depth + dumpInfo->recurse_depth)
+                    die->Dump(dwarf2Data, cu, s, 0);
+            }
+            else if (dumpInfo->die_offset > die->GetOffset())
+            {
+                if (show_parents)
+                    dumpInfo->ancestors.back() = *die;
+            }
+        }
+
+        // Keep up with our indent level
+        if (die->IsNULL())
+        {
+            if (show_parents)
+                dumpInfo->ancestors.pop_back();
+
+            if (curr_depth <= 1)
+                return cu->GetNextCompileUnitOffset();
+            else
+                s->IndentLess();
+        }
+        else if (die->HasChildren())
+        {
+            if (show_parents)
+            {
+                DWARFDebugInfoEntry null_die;
+                dumpInfo->ancestors.push_back(null_die);
+            }
+            s->IndentMore();
+        }
+    }
+    else
+    {
+        if (cu == NULL)
+            s->PutCString("NULL - cu");
+        // We have a compile unit, reset our indent level to zero just in case
+        s->SetIndentLevel(0);
+
+        // See if we are dumping everything?
+        if (dumpInfo->die_offset == DW_INVALID_OFFSET)
+        {
+            // We are dumping everything
+            cu->Dump(s);
+            return cu->GetFirstDIEOffset(); // Return true to parse all DIEs in this Compile Unit
+        }
+        else
+        {
+            if (show_parents)
+            {
+                dumpInfo->ancestors.clear();
+                dumpInfo->ancestors.resize(1);
+            }
+
+            // We are dumping only a single DIE possibly with it's children and
+            // we must find it's compile unit before we can dump it properly
+            if (dumpInfo->die_offset < cu->GetFirstDIEOffset())
+            {
+                // Not found, maybe the DIE offset provided wasn't correct?
+            //  *ostrm_ptr << "DIE at offset " << HEX32 << dumpInfo->die_offset << " was not found." << endl;
+                return DW_INVALID_OFFSET;
+            }
+            else
+            {
+                // See if the DIE is in this compile unit?
+                if (dumpInfo->die_offset < cu->GetNextCompileUnitOffset())
+                {
+                    // This DIE is in this compile unit!
+                    if (s->GetVerbose())
+                        cu->Dump(s); // Dump the compile unit for the DIE in verbose mode
+
+                    return next_offset;
+                //  // We found our compile unit that contains our DIE, just skip to dumping the requested DIE...
+                //  return dumpInfo->die_offset;
+                }
+                else
+                {
+                    // Skip to the next compile unit as the DIE isn't in the current one!
+                    return cu->GetNextCompileUnitOffset();
+                }
+            }
+        }
+    }
+
+    // Just return the current offset to parse the next CU or DIE entry
+    return next_offset;
+}
+
+//----------------------------------------------------------------------
+// Dump
+//
+// Dump the information in the .debug_info section to the specified
+// ostream. If die_offset is valid, a single DIE will be dumped. If the
+// die_offset is invalid, all the DWARF information will be dumped. Both
+// cases will obey a "recurse_depth" or how deep to traverse into the
+// children of each DIE entry. A recurse_depth of zero will dump all
+// compile unit headers. A recurse_depth of 1 will dump all compile unit
+// headers and the DW_TAG_compile unit tags. A depth of 2 will also
+// dump all types and functions.
+//----------------------------------------------------------------------
+void
+DWARFDebugInfo::Dump
+(
+    Stream *s,
+    SymbolFileDWARF* dwarf2Data,
+    const uint32_t die_offset,
+    const uint32_t recurse_depth
+)
+{
+    DumpInfo dumpInfo(s, die_offset, recurse_depth);
+    s->PutCString(".debug_info contents");
+    if (dwarf2Data->get_debug_info_data().GetByteSize() > 0)
+    {
+        if (die_offset == DW_INVALID_OFFSET)
+            s->PutCString(":\n");
+        else
+        {
+            s->Printf(" for DIE entry at .debug_info[0x%8.8x]", die_offset);
+            if (recurse_depth != UINT_MAX)
+                s->Printf(" recursing %u levels deep.", recurse_depth);
+            s->EOL();
+        }
+    }
+    else
+    {
+        s->PutCString(": < EMPTY >\n");
+        return;
+    }
+    DWARFDebugInfo::Parse(dwarf2Data, DumpCallback, &dumpInfo);
+}
+
+
+//----------------------------------------------------------------------
+// Dump
+//
+// Dump the contents of this DWARFDebugInfo object as has been parsed
+// and/or modified after it has been parsed.
+//----------------------------------------------------------------------
+void
+DWARFDebugInfo::Dump (Stream *s, const uint32_t die_offset, const uint32_t recurse_depth)
+{
+    DumpInfo dumpInfo(s, die_offset, recurse_depth);
+
+    s->PutCString("Dumping .debug_info section from internal representation\n");
+
+    CompileUnitColl::const_iterator pos;
+    uint32_t curr_depth = 0;
+    ParseCompileUnitHeadersIfNeeded();
+    for (pos = m_compile_units.begin(); pos != m_compile_units.end(); ++pos)
+    {
+        const DWARFCompileUnitSP& cu_sp = *pos;
+        DumpCallback(m_dwarf2Data, (DWARFCompileUnitSP&)cu_sp, NULL, 0, curr_depth, &dumpInfo);
+        cu_sp->DIE()->Dump(m_dwarf2Data, cu_sp.get(), s, recurse_depth);
+    }
+}
+
+
+//----------------------------------------------------------------------
+// FindCallbackString
+//
+// A callback function for the static DWARFDebugInfo::Parse() function
+// that gets called each time a compile unit header or debug information
+// entry is successfully parsed.
+//
+// This function will find the die_offset of any items whose DW_AT_name
+// matches the given string
+//----------------------------------------------------------------------
+typedef struct FindCallbackStringInfoTag
+{
+    const char* name;
+    bool ignore_case;
+    RegularExpression* regex;
+    vector<dw_offset_t>& die_offsets;
+} FindCallbackStringInfo;
+
+static dw_offset_t FindCallbackString
+(
+    SymbolFileDWARF* dwarf2Data,
+    DWARFCompileUnitSP& cu_sp,
+    DWARFDebugInfoEntry* die,
+    const dw_offset_t next_offset,
+    const uint32_t curr_depth,
+    void* userData
+)
+{
+    FindCallbackStringInfo* info = (FindCallbackStringInfo*)userData;
+    const DWARFCompileUnit* cu = cu_sp.get();
+
+    if (die)
+    {
+        const char* die_name = die->GetName(dwarf2Data, cu);
+        if (die_name)
+        {
+            if (info->regex)
+            {
+                if (info->regex->Execute(die_name))
+                    info->die_offsets.push_back(die->GetOffset());
+            }
+            else
+            {
+                if ((info->ignore_case ? strcasecmp(die_name, info->name) : strcmp(die_name, info->name)) == 0)
+                    info->die_offsets.push_back(die->GetOffset());
+            }
+        }
+    }
+
+    // Just return the current offset to parse the next CU or DIE entry
+    return next_offset;
+}
+
+//----------------------------------------------------------------------
+// Find
+//
+// Finds all DIE that have a specific DW_AT_name attribute by manually
+// searching through the debug information (not using the
+// .debug_pubnames section). The string must match the entire name
+// and case sensitive searches are an option.
+//----------------------------------------------------------------------
+bool
+DWARFDebugInfo::Find(const char* name, bool ignore_case, vector<dw_offset_t>& die_offsets) const
+{
+    die_offsets.clear();
+    if (name && name[0])
+    {
+        FindCallbackStringInfo info = { name, ignore_case, NULL, die_offsets };
+        DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info);
+    }
+    return !die_offsets.empty();
+}
+
+//----------------------------------------------------------------------
+// Find
+//
+// Finds all DIE that have a specific DW_AT_name attribute by manually
+// searching through the debug information (not using the
+// .debug_pubnames section). The string must match the supplied regular
+// expression.
+//----------------------------------------------------------------------
+bool
+DWARFDebugInfo::Find(RegularExpression& re, vector<dw_offset_t>& die_offsets) const
+{
+    die_offsets.clear();
+    FindCallbackStringInfo info = { NULL, false, &re, die_offsets };
+    DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info);
+    return !die_offsets.empty();
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
new file mode 100644
index 0000000..f506a3d
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
@@ -0,0 +1,86 @@
+//===-- DWARFDebugInfo.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_DWARFDebugInfo_h_
+#define SymbolFileDWARF_DWARFDebugInfo_h_
+
+#include <vector>
+#include <map>
+
+#include "lldb/lldb-private.h"
+#include "lldb/lldb-private.h"
+#include "SymbolFileDWARF.h"
+
+typedef std::multimap<const char*, dw_offset_t, CStringCompareFunctionObject> CStringToDIEMap;
+typedef CStringToDIEMap::iterator CStringToDIEMapIter;
+typedef CStringToDIEMap::const_iterator CStringToDIEMapConstIter;
+
+typedef lldb::SharedPtr<DWARFCompileUnit>::Type DWARFCompileUnitSP;
+
+class DWARFDebugInfo
+{
+public:
+    typedef dw_offset_t (*Callback)(
+        SymbolFileDWARF* dwarf2Data,
+        DWARFCompileUnitSP& cu_shared_ptr,
+        DWARFDebugInfoEntry* die,
+        const dw_offset_t next_offset,
+        const uint32_t depth,
+        void* userData);
+
+    DWARFDebugInfo();
+    void SetDwarfData(SymbolFileDWARF* dwarf2Data);
+    bool BuildFunctionAddressRangeTable(DWARFDebugAranges* debug_aranges);
+
+    bool LookupAddress(
+            const dw_addr_t address,
+            const dw_offset_t cu_offset,    // Can be valid (find in .debug_aranges), or DW_INVALID_OFFSET if we need to search manually
+            DWARFCompileUnitSP& cu_shared_ptr,
+            DWARFDebugInfoEntry** function_die,
+            DWARFDebugInfoEntry** block_die);
+
+    void AddCompileUnit(DWARFCompileUnitSP& cu);
+    uint32_t GetNumCompileUnits();
+    DWARFCompileUnit* GetCompileUnitAtIndex(uint32_t idx);
+    DWARFCompileUnitSP GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr = NULL);
+    DWARFCompileUnitSP GetCompileUnitContainingDIE(dw_offset_t die_offset);
+
+    DWARFDebugInfoEntry* GetDIEPtr(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr);
+    const DWARFDebugInfoEntry* GetDIEPtrContainingOffset(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr);
+
+    void Dump(lldb_private::Stream *s, const uint32_t die_offset, const uint32_t recurse_depth);
+    static void Parse(SymbolFileDWARF* parser, Callback callback, void* userData);
+    static void Verify(lldb_private::Stream *s, SymbolFileDWARF* dwarf2Data);
+    static void Dump(lldb_private::Stream *s, SymbolFileDWARF* dwarf2Data, const uint32_t die_offset, const uint32_t recurse_depth);
+    bool Find(const char* name, bool ignore_case, std::vector<dw_offset_t>& die_offsets) const;
+    bool Find(lldb_private::RegularExpression& re, std::vector<dw_offset_t>& die_offsets) const;
+
+    enum
+    {
+        eDumpFlag_Verbose               = (1<<0),   // Verbose dumping
+        eDumpFlag_ShowForm              = (1<<1),   // Show the DW_form type
+        eDumpFlag_EnglishyNames         = (1<<2),   // Show the DW_TAG, DW_AT and DW_FORM types in more englishy names instead of as DWARF definitions values
+        eDumpFlag_ShowAncestors         = (1<<3)    // Show all parent DIEs when dumping single DIEs
+    };
+
+
+protected:
+    SymbolFileDWARF* m_dwarf2Data;
+    typedef std::vector<DWARFCompileUnitSP>     CompileUnitColl;
+
+    CompileUnitColl m_compile_units;
+
+private:
+    // All parsing needs to be done partially any managed by this class as accessors are called.
+    void ParseCompileUnitHeadersIfNeeded();
+
+    DISALLOW_COPY_AND_ASSIGN (DWARFDebugInfo);
+};
+
+#endif  // SymbolFileDWARF_DWARFDebugInfo_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
new file mode 100644
index 0000000..19eef06
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -0,0 +1,1929 @@
+//===-- DWARFDebugInfoEntry.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugInfoEntry.h"
+
+#include <assert.h>
+
+#include <algorithm>
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Symbol/ObjectFile.h"
+
+#include "DWARFCompileUnit.h"
+#include "SymbolFileDWARF.h"
+#include "DWARFDebugAbbrev.h"
+#include "DWARFDebugAranges.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFDIECollection.h"
+#include "DWARFFormValue.h"
+#include "DWARFLocationDescription.h"
+#include "DWARFLocationList.h"
+#include "DWARFDebugRanges.h"
+
+using namespace lldb_private;
+using namespace std;
+extern int g_verbose;
+
+
+
+DWARFDebugInfoEntry::Attributes::Attributes() :
+    m_infos()
+{
+    m_infos.reserve(20);
+}
+
+DWARFDebugInfoEntry::Attributes::~Attributes()
+{
+}
+
+
+uint32_t
+DWARFDebugInfoEntry::Attributes::FindAttributeIndex(dw_attr_t attr) const
+{
+    std::vector<Info>::const_iterator end = m_infos.end();
+    std::vector<Info>::const_iterator beg = m_infos.begin();
+    std::vector<Info>::const_iterator pos;
+    for (pos = beg; pos != end; ++pos)
+    {
+        if (pos->attr == attr)
+            return std::distance(beg, pos);
+    }
+    return UINT_MAX;
+}
+
+void
+DWARFDebugInfoEntry::Attributes::Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr, dw_form_t form)
+{
+    Info info = { cu, attr_die_offset, attr, form };
+    m_infos.push_back(info);
+}
+
+bool
+DWARFDebugInfoEntry::Attributes::ContainsAttribute(dw_attr_t attr) const
+{
+    return FindAttributeIndex(attr) != UINT_MAX;
+}
+
+bool
+DWARFDebugInfoEntry::Attributes::RemoveAttribute(dw_attr_t attr)
+{
+    uint32_t attr_index = FindAttributeIndex(attr);
+    if (attr_index != UINT_MAX)
+    {
+        m_infos.erase(m_infos.begin() + attr_index);
+        return true;
+    }
+    return false;
+}
+
+bool
+DWARFDebugInfoEntry::Attributes::ExtractFormValueAtIndex (SymbolFileDWARF* dwarf2Data, uint32_t i, DWARFFormValue &form_value) const
+{
+    form_value.SetForm(FormAtIndex(i));
+    dw_offset_t offset = DIEOffsetAtIndex(i);
+    return form_value.ExtractValue(dwarf2Data->get_debug_info_data(), &offset, CompileUnitAtIndex(i));
+}
+
+uint64_t
+DWARFDebugInfoEntry::Attributes::FormValueAsUnsignedAtIndex(SymbolFileDWARF* dwarf2Data, uint32_t i, uint64_t fail_value) const
+{
+    DWARFFormValue form_value;
+    if (ExtractFormValueAtIndex(dwarf2Data, i, form_value))
+        return form_value.Reference(CompileUnitAtIndex(i));
+    return fail_value;
+}
+
+
+//----------------------------------------------------------------------
+// Extract
+//
+// Extract a debug info entry for a given compile unit from the
+// .debug_info and .debug_abbrev data within the SymbolFileDWARF class
+// starting at the given offset
+//----------------------------------------------------------------------
+bool
+DWARFDebugInfoEntry::Extract
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    uint32_t* offset_ptr
+)
+{
+    const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
+//    const DataExtractor& debug_str_data = dwarf2Data->get_debug_str_data();
+    const uint32_t cu_end_offset = cu->GetNextCompileUnitOffset();
+    const uint8_t cu_addr_size = cu->GetAddressByteSize();
+    uint32_t offset = *offset_ptr;
+//  if (offset >= cu_end_offset)
+//      Log::Error("DIE at offset 0x%8.8x is beyond the end of the current compile unit (0x%8.8x)", m_offset, cu_end_offset);
+    if ((offset < cu_end_offset) && debug_info_data.ValidOffset(offset))
+    {
+        m_offset = offset;
+
+        dw_uleb128_t abbrCode = debug_info_data.GetULEB128(&offset);
+
+        if (abbrCode)
+        {
+            m_abbrevDecl = cu->GetAbbreviations()->GetAbbreviationDeclaration(abbrCode);
+
+            if (m_abbrevDecl)
+            {
+                dw_tag_t tag = m_abbrevDecl->Tag();
+
+                bool isCompileUnitTag = tag == DW_TAG_compile_unit;
+                if (cu && isCompileUnitTag)
+                    ((DWARFCompileUnit*)cu)->SetBaseAddress(0);
+
+                // Skip all data in the .debug_info for the attributes
+                const uint32_t numAttributes = m_abbrevDecl->NumAttributes();
+                uint32_t i;
+                dw_attr_t attr;
+                dw_form_t form;
+                for (i=0; i<numAttributes; ++i)
+                {
+                    m_abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form);
+
+                    if (isCompileUnitTag && ((attr == DW_AT_entry_pc) || (attr == DW_AT_low_pc)))
+                    {
+                        DWARFFormValue form_value(form);
+                        if (form_value.ExtractValue(debug_info_data, &offset, cu))
+                        {
+                            if (attr == DW_AT_low_pc || attr == DW_AT_entry_pc)
+                                ((DWARFCompileUnit*)cu)->SetBaseAddress(form_value.Unsigned());
+                        }
+                    }
+                    else
+                    {
+die_extract_indirect_form:
+                        register uint32_t form_size = 0;
+                        switch (form)
+                        {
+                        // Blocks if inlined data that have a length field and the data bytes
+                        // inlined in the .debug_info
+                        case DW_FORM_block      : form_size = debug_info_data.GetULEB128(&offset);  break;
+                        case DW_FORM_block1     : form_size = debug_info_data.GetU8(&offset);       break;
+                        case DW_FORM_block2     : form_size = debug_info_data.GetU16(&offset);      break;
+                        case DW_FORM_block4     : form_size = debug_info_data.GetU32(&offset);      break;
+
+                        // Inlined NULL terminated C-strings
+                        case DW_FORM_string     :
+                            {
+//                                const char *s = 
+                                debug_info_data.GetCStr(&offset);
+//                                switch (attr)
+//                                {
+//                                case DW_AT_name: m_name = s; break;
+//                                case DW_AT_MIPS_linkage_name: m_linkage_name = s; break;
+//                                default: break;
+//                                }
+                            }
+                            break;
+
+                        // Compile unit address sized values
+                        case DW_FORM_addr       :
+                        case DW_FORM_ref_addr   :
+                            form_size = cu_addr_size;
+                            break;
+
+                        // 1 byte values
+                        case DW_FORM_data1      :
+                        case DW_FORM_flag       :
+                        case DW_FORM_ref1       :
+                            form_size = 1;
+                            break;
+
+                        // 2 byte values
+                        case DW_FORM_data2      :
+                        case DW_FORM_ref2       :
+                            form_size = 2;
+                            break;
+
+                        // 4 byte values
+                        case DW_FORM_strp       :
+//                            switch (attr)
+//                            {
+//                            case DW_AT_name:
+//                                m_name = debug_str_data.PeekCStr(debug_info_data.GetU32(&offset));
+//                                break;
+//                            case DW_AT_MIPS_linkage_name:
+//                                m_linkage_name = debug_str_data.PeekCStr(debug_info_data.GetU32(&offset));
+//                                break;
+//
+//                            default:
+                                form_size = 4;
+//                                break;
+//                            }
+                            break;
+
+                        case DW_FORM_data4      :
+                        case DW_FORM_ref4       :
+                            form_size = 4;
+                            break;
+
+                        // 8 byte values
+                        case DW_FORM_data8      :
+                        case DW_FORM_ref8       :
+                            form_size = 8;
+                            break;
+
+                        // signed or unsigned LEB 128 values
+                    //  case DW_FORM_APPLE_db_str:
+                        case DW_FORM_sdata      :
+                        case DW_FORM_udata      :
+                        case DW_FORM_ref_udata  :
+                            debug_info_data.Skip_LEB128(&offset);
+                            break;
+
+                        case DW_FORM_indirect   :
+                            form = debug_info_data.GetULEB128(&offset);
+                            goto die_extract_indirect_form;
+
+                        default:
+                            *offset_ptr = offset;
+                            return false;
+                        }
+
+                        offset += form_size;
+                    }
+                }
+                *offset_ptr = offset;
+                return true;
+            }
+        }
+        else
+        {
+            m_abbrevDecl = NULL;
+            *offset_ptr = offset;
+            return true;    // NULL debug tag entry
+        }
+    }
+
+    return false;
+}
+
+//----------------------------------------------------------------------
+// AppendDependentDIES()
+//----------------------------------------------------------------------
+bool
+DWARFDebugInfoEntry::AppendDependentDIES
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const bool add_children,
+    DWARFDIECollection& dependent_dies
+) const
+{
+    // Add this object's DIE offset
+    // The line below is the only place that should add a die to the
+    // dependent_dies collection as we have to be careful of recursion!
+    if ( !dependent_dies.Insert(this) )
+        return false;   // This DIE already exists in the collection, nothing to do!
+
+    //DEBUG_PRINTF("    dependent_dies.Insert(0x%8.8x)\n", GetOffset());///
+
+    if (m_abbrevDecl)
+    {
+        // Keep adding parent DIE offsets as long as the offsets do not
+        // already exist in the collection
+        const DWARFDebugInfoEntry* die = GetParent();
+        while ( die && die->AppendDependentDIES(dwarf2Data, cu, false, dependent_dies) )
+            die = die->GetParent();
+
+        bool add_non_subprogram_children = false;
+        bool add_children_override = false;
+
+        if (!add_children)
+        {
+            switch (m_abbrevDecl->Tag())
+            {
+            case DW_TAG_array_type:                                             break;
+            case DW_TAG_class_type:         add_non_subprogram_children = true; break;
+            case DW_TAG_entry_point:                                            break;
+            case DW_TAG_enumeration_type:                                       break;
+            case DW_TAG_formal_parameter:                                       break;
+            case DW_TAG_imported_declaration:                                   break;
+            case DW_TAG_label:                                                  break;
+            case DW_TAG_lexical_block:      add_children_override = true;       break;
+            case DW_TAG_member:                                                 break;
+            case DW_TAG_pointer_type:                                           break;
+            case DW_TAG_reference_type:                                         break;
+            case DW_TAG_compile_unit:                                           break;
+            case DW_TAG_string_type:                                            break;
+            case DW_TAG_structure_type:     add_non_subprogram_children = true; break;
+            case DW_TAG_subroutine_type:    add_children_override = true;       break;
+            case DW_TAG_typedef:                                                break;
+            case DW_TAG_union_type:         add_non_subprogram_children = true; break;
+            case DW_TAG_unspecified_parameters:                                 break;
+            case DW_TAG_variant:                                                break;
+            case DW_TAG_common_block:                                           break;
+            case DW_TAG_common_inclusion:                                       break;
+            case DW_TAG_inheritance:                                            break;
+            case DW_TAG_inlined_subroutine:                                     break;
+            case DW_TAG_module:                                                 break;
+            case DW_TAG_ptr_to_member_type:                                     break;
+            case DW_TAG_set_type:                                               break;
+            case DW_TAG_subrange_type:                                          break;
+            case DW_TAG_with_stmt:                                              break;
+            case DW_TAG_access_declaration:                                     break;
+            case DW_TAG_base_type:                                              break;
+            case DW_TAG_catch_block:                                            break;
+            case DW_TAG_const_type:                                             break;
+            case DW_TAG_constant:                                               break;
+            case DW_TAG_enumerator:                                             break;
+            case DW_TAG_file_type:                                              break;
+            case DW_TAG_friend:                                                 break;
+            case DW_TAG_namelist:                                               break;
+            case DW_TAG_namelist_item:                                          break;
+            case DW_TAG_packed_type:                                            break;
+            case DW_TAG_subprogram:             add_children_override = true;   break;
+            case DW_TAG_template_type_parameter:                                break;
+            case DW_TAG_template_value_parameter:                               break;
+            case DW_TAG_thrown_type:                                            break;
+            case DW_TAG_try_block:                                              break;
+            case DW_TAG_variant_part:                                           break;
+            case DW_TAG_variable:                                               break;
+            case DW_TAG_volatile_type:                                          break;
+            case DW_TAG_dwarf_procedure:                                        break;
+            case DW_TAG_restrict_type:                                          break;
+            case DW_TAG_interface_type:                                         break;
+            case DW_TAG_namespace:                                              break;
+            case DW_TAG_imported_module:                                        break;
+            case DW_TAG_unspecified_type:                                       break;
+            case DW_TAG_partial_unit:                                           break;
+            case DW_TAG_imported_unit:                                          break;
+            case DW_TAG_shared_type:                                            break;
+            }
+        }
+        const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
+
+        // Dump all data in the .debug_info for the attributes
+        const uint32_t numAttributes = m_abbrevDecl->NumAttributes();
+        uint32_t i;
+        dw_offset_t offset = GetOffset();
+        debug_info_data.Skip_LEB128(&offset);   // Skip abbreviation code
+
+        dw_attr_t attr;
+        dw_form_t form;
+        for (i=0; i<numAttributes; ++i)
+        {
+            m_abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form);
+            DWARFFormValue form_value(form);
+
+            switch (attr)
+            {
+            // All cases that use refer to another DIE should use this case
+            // without
+            // having to check the FORM of the attribute to tell if it refers to another
+            // DIE
+            case DW_AT_abstract_origin:
+            case DW_AT_import:
+            case DW_AT_discr:
+            case DW_AT_containing_type:
+            case DW_AT_base_types:
+            case DW_AT_friend:
+            case DW_AT_specification:
+            case DW_AT_type:
+            case DW_AT_common_reference:
+            case DW_AT_default_value:
+                {
+                    form_value.ExtractValue(debug_info_data, &offset, cu);
+                    DWARFCompileUnitSP cu_sp_ptr;
+                    const DWARFDebugInfoEntry* ref_die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(cu), &cu_sp_ptr);
+                    if (ref_die)
+                        ref_die->AppendDependentDIES(dwarf2Data, cu_sp_ptr.get(), true, dependent_dies);
+                }
+                break;
+
+            default:
+                if (attr != DW_AT_sibling)
+                {
+                    switch (form_value.Form())
+                    {
+                    case DW_FORM_ref_addr:
+                    case DW_FORM_ref1:
+                    case DW_FORM_ref2:
+                    case DW_FORM_ref4:
+                    case DW_FORM_ref8:
+                    case DW_FORM_ref_udata:
+//                      Log::WarningVerbose("DWARFDebugInfoEntry::AppendDependentDIES() -- check on this item %s: attr = %s  form = %s",
+//                          DW_TAG_value_to_name(m_abbrevDecl->Tag()),
+//                          DW_AT_value_to_name(attr),
+//                          DW_FORM_value_to_name(form));
+                        break;
+                    }
+                }
+                form_value.SkipValue(debug_info_data, &offset, cu);
+                break;
+            }
+        }
+
+        if (m_abbrevDecl->HasChildren())
+        {
+            const DWARFDebugInfoEntry* child;
+            for (child = GetFirstChild(); child != NULL; child = child->GetSibling())
+            {
+                bool add = add_children || add_children_override;
+
+                if (!add)
+                {
+                    if (add_non_subprogram_children)
+                    {
+                        // add_non_subprogram_children is used for classes and structs
+                        // that may contain children that are the member variables that
+                        // may have functions as children and whom may add the class or
+                        // struct by adding their parent. We don't want to add any
+                        // functions though since they may have been optimized out. But
+                        // we do need to watch for declarations and keep them.
+                        if (child->Tag() == DW_TAG_subprogram)
+                        {
+                            // Check if this subprogram TAG had a DW_AT_declaration attribute set to 1.
+                            // If so we need to include this DIE so that we always have a complete view
+                            // of a class definition so debuggers can track down any weak symbols that
+                            // may not have had weak definition entries.
+                            if (child->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_declaration, 0) == 1)
+                                add = true;
+                        }
+                        else
+                        {
+                            // Add all other items inside a class/struct
+                            add = true;
+                        }
+                    }
+                    else
+                    {
+                        // We don't need to add this child, only add it if it's a NULL tag
+                        add = child->IsNULL();
+                    }
+                }
+
+                if (add)
+                    child->AppendDependentDIES(dwarf2Data, cu, true, dependent_dies);
+            }
+        }
+    }
+    return true;
+}
+
+//----------------------------------------------------------------------
+// DumpAncestry
+//
+// Dumps all of a debug information entries parents up until oldest and
+// all of it's attributes to the specified stream.
+//----------------------------------------------------------------------
+void
+DWARFDebugInfoEntry::DumpAncestry
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const DWARFDebugInfoEntry* oldest,
+    Stream *s,
+    uint32_t recurse_depth
+) const
+{
+    const DWARFDebugInfoEntry* parent = GetParent();
+    if (parent && parent != oldest)
+        parent->DumpAncestry(dwarf2Data, cu, oldest, s, 0);
+    Dump(dwarf2Data, cu, s, recurse_depth);
+}
+
+//----------------------------------------------------------------------
+// Compare two DIE by comparing all their attributes values, and
+// following all DW_FORM_ref attributes and comparing their contents as
+// well (except for DW_AT_sibling attributes.
+//
+//  DWARFDebugInfoEntry::CompareState compare_state;
+//  int result = DWARFDebugInfoEntry::Compare(this, 0x00017ccb, 0x0001eb2b, compare_state, false, true);
+//----------------------------------------------------------------------
+int
+DWARFDebugInfoEntry::Compare
+(
+    SymbolFileDWARF* dwarf2Data,
+    dw_offset_t a_die_offset,
+    dw_offset_t b_die_offset,
+    CompareState &compare_state,
+    bool compare_siblings,
+    bool compare_children
+)
+{
+    if (a_die_offset == b_die_offset)
+        return 0;
+
+    DWARFCompileUnitSP a_cu_sp;
+    DWARFCompileUnitSP b_cu_sp;
+    const DWARFDebugInfoEntry* a_die = dwarf2Data->DebugInfo()->GetDIEPtr(a_die_offset, &a_cu_sp);
+    const DWARFDebugInfoEntry* b_die = dwarf2Data->DebugInfo()->GetDIEPtr(b_die_offset, &b_cu_sp);
+
+    return Compare(dwarf2Data, a_cu_sp.get(), a_die, b_cu_sp.get(), b_die, compare_state, compare_siblings, compare_children);
+}
+
+int
+DWARFDebugInfoEntry::Compare
+(
+    SymbolFileDWARF* dwarf2Data,
+    DWARFCompileUnit* a_cu, const DWARFDebugInfoEntry* a_die,
+    DWARFCompileUnit* b_cu, const DWARFDebugInfoEntry* b_die,
+    CompareState &compare_state,
+    bool compare_siblings,
+    bool compare_children
+)
+{
+    if (a_die == b_die)
+        return 0;
+
+    if (!compare_state.AddTypePair(a_die->GetOffset(), b_die->GetOffset()))
+    {
+        // We are already comparing both of these types, so let
+        // compares complete for the real result
+        return 0;
+    }
+
+    //printf("DWARFDebugInfoEntry::Compare(0x%8.8x, 0x%8.8x)\n", a_die->GetOffset(), b_die->GetOffset());
+
+    // Do we have two valid DIEs?
+    if (a_die && b_die)
+    {
+        // Both DIE are valid
+        int result = 0;
+
+        const dw_tag_t a_tag = a_die->Tag();
+        const dw_tag_t b_tag = b_die->Tag();
+        if (a_tag == 0 && b_tag == 0)
+            return 0;
+
+        //printf("    comparing tags: %s and %s\n", DW_TAG_value_to_name(a_tag), DW_TAG_value_to_name(b_tag));
+
+        if (a_tag < b_tag)
+            return -1;
+        else if (a_tag > b_tag)
+            return 1;
+
+        DWARFDebugInfoEntry::Attributes a_attrs;
+        DWARFDebugInfoEntry::Attributes b_attrs;
+        size_t a_attr_count = a_die->GetAttributes(dwarf2Data, a_cu, a_attrs);
+        size_t b_attr_count = b_die->GetAttributes(dwarf2Data, b_cu, b_attrs);
+        if (a_attr_count != b_attr_count)
+        {
+            a_attrs.RemoveAttribute(DW_AT_sibling);
+            b_attrs.RemoveAttribute(DW_AT_sibling);
+        }
+
+        a_attr_count = a_attrs.Size();
+        b_attr_count = b_attrs.Size();
+
+        DWARFFormValue a_form_value;
+        DWARFFormValue b_form_value;
+
+        if (a_attr_count != b_attr_count)
+        {
+            uint32_t is_decl_index = a_attrs.FindAttributeIndex(DW_AT_declaration);
+            uint32_t a_name_index = UINT_MAX;
+            uint32_t b_name_index = UINT_MAX;
+            if (is_decl_index != UINT_MAX)
+            {
+                if (a_attr_count == 2)
+                {
+                    a_name_index = a_attrs.FindAttributeIndex(DW_AT_name);
+                    b_name_index = b_attrs.FindAttributeIndex(DW_AT_name);
+                }
+            }
+            else
+            {
+                is_decl_index = b_attrs.FindAttributeIndex(DW_AT_declaration);
+                if (is_decl_index != UINT_MAX && a_attr_count == 2)
+                {
+                    a_name_index = a_attrs.FindAttributeIndex(DW_AT_name);
+                    b_name_index = b_attrs.FindAttributeIndex(DW_AT_name);
+                }
+            }
+            if (a_name_index != UINT_MAX && b_name_index != UINT_MAX)
+            {
+                if (a_attrs.ExtractFormValueAtIndex(dwarf2Data, a_name_index, a_form_value) &&
+                    b_attrs.ExtractFormValueAtIndex(dwarf2Data, b_name_index, b_form_value))
+                {
+                    result = DWARFFormValue::Compare (a_form_value, b_form_value, a_cu, b_cu, &dwarf2Data->get_debug_str_data());
+                    if (result == 0)
+                    {
+                        a_attr_count = b_attr_count = 0;
+                        compare_children = false;
+                    }
+                }
+            }
+        }
+
+        if (a_attr_count < b_attr_count)
+            return -1;
+        if (a_attr_count > b_attr_count)
+            return 1;
+
+
+        // The number of attributes are the same...
+        if (a_attr_count > 0)
+        {
+            const DataExtractor* debug_str_data_ptr = &dwarf2Data->get_debug_str_data();
+
+            uint32_t i;
+            for (i=0; i<a_attr_count; ++i)
+            {
+                const dw_attr_t a_attr = a_attrs.AttributeAtIndex(i);
+                const dw_attr_t b_attr = b_attrs.AttributeAtIndex(i);
+                //printf("    comparing attributes\n\t\t0x%8.8x: %s %s\t\t0x%8.8x: %s %s\n",
+                //                a_attrs.DIEOffsetAtIndex(i), DW_FORM_value_to_name(a_attrs.FormAtIndex(i)), DW_AT_value_to_name(a_attr),
+                //                b_attrs.DIEOffsetAtIndex(i), DW_FORM_value_to_name(b_attrs.FormAtIndex(i)), DW_AT_value_to_name(b_attr));
+
+                if (a_attr < b_attr)
+                    return -1;
+                else if (a_attr > b_attr)
+                    return 1;
+
+                switch (a_attr)
+                {
+                // Since we call a form of GetAttributes which inlines the
+                // attributes from DW_AT_abstract_origin and DW_AT_specification
+                // we don't care if their values mismatch...
+                case DW_AT_abstract_origin:
+                case DW_AT_specification:
+                case DW_AT_sibling:
+                case DW_AT_containing_type:
+                    //printf("        action = IGNORE\n");
+                    result = 0;
+                    break;  // ignore
+
+                default:
+                    if (a_attrs.ExtractFormValueAtIndex(dwarf2Data, i, a_form_value) &&
+                        b_attrs.ExtractFormValueAtIndex(dwarf2Data, i, b_form_value))
+                        result = DWARFFormValue::Compare (a_form_value, b_form_value, a_cu, b_cu, debug_str_data_ptr);
+                    break;
+                }
+
+                //printf("\t  result = %i\n", result);
+
+                if (result != 0)
+                {
+                    // Attributes weren't equal, lets see if we care?
+                    switch (a_attr)
+                    {
+                    case DW_AT_decl_file:
+                        // TODO: add the ability to compare files in two different compile units
+                        if (a_cu == b_cu)
+                        {
+                            //printf("        action = RETURN RESULT\n");
+                            return result;  // Only return the compare results when the compile units are the same and the decl_file attributes can be compared
+                        }
+                        else
+                        {
+                            result = 0;
+                            //printf("        action = IGNORE\n");
+                        }
+                        break;
+
+                    default:
+                        switch (a_attrs.FormAtIndex(i))
+                        {
+                        case DW_FORM_ref1:
+                        case DW_FORM_ref2:
+                        case DW_FORM_ref4:
+                        case DW_FORM_ref8:
+                        case DW_FORM_ref_udata:
+                        case DW_FORM_ref_addr:
+                            //printf("    action = COMPARE DIEs 0x%8.8x 0x%8.8x\n", (dw_offset_t)a_form_value.Reference(a_cu), (dw_offset_t)b_form_value.Reference(b_cu));
+                            // These attribute values refer to other DIEs, so lets compare those instead of their DIE offsets...
+                            result = Compare(dwarf2Data, a_form_value.Reference(a_cu), b_form_value.Reference(b_cu), compare_state, false, true);
+                            if (result != 0)
+                                return result;
+                            break;
+
+                        default:
+                            // We do care that they were different, return this result...
+                            //printf("        action = RETURN RESULT\n");
+                            return result;
+                        }
+                    }
+                }
+            }
+        }
+        //printf("    SUCCESS\n\t\t0x%8.8x: %s\n\t\t0x%8.8x: %s\n", a_die->GetOffset(), DW_TAG_value_to_name(a_tag), b_die->GetOffset(), DW_TAG_value_to_name(b_tag));
+
+        if (compare_children)
+        {
+            bool a_has_children = a_die->HasChildren();
+            bool b_has_children = b_die->HasChildren();
+            if (a_has_children == b_has_children)
+            {
+                // Both either have kids or don't
+                if (a_has_children)
+                    result = Compare(   dwarf2Data,
+                                        a_cu, a_die->GetFirstChild(),
+                                        b_cu, b_die->GetFirstChild(),
+                                        compare_state, true, compare_children);
+                else
+                    result = 0;
+            }
+            else if (!a_has_children)
+                result = -1;    // A doesn't have kids, but B does
+            else
+                result = 1; // A has kids, but B doesn't
+        }
+
+        if (compare_siblings)
+        {
+            result = Compare(   dwarf2Data,
+                                a_cu, a_die->GetSibling(),
+                                b_cu, b_die->GetSibling(),
+                                compare_state, true, compare_children);
+        }
+
+        return result;
+    }
+
+    if (a_die == NULL)
+        return -1;  // a_die is NULL, yet b_die is non-NULL
+    else
+        return 1;   // a_die is non-NULL, yet b_die is NULL
+
+}
+
+//
+//int
+//DWARFDebugInfoEntry::Compare
+//(
+//  SymbolFileDWARF* dwarf2Data,
+//  const DWARFCompileUnit* cu_a,
+//  const DWARFDebugInfoEntry* die_a,
+//  const DWARFCompileUnit* cu_a,
+//  const DWARFDebugInfoEntry* die_b,
+//  CompareState &compare_state
+//)
+//{
+//}
+
+//----------------------------------------------------------------------
+// GetDIENamesAndRanges
+//
+// Gets the valid address ranges for a given DIE by looking for a
+// DW_AT_low_pc/DW_AT_high_pc pair, DW_AT_entry_pc, or DW_AT_ranges
+// attributes.
+//----------------------------------------------------------------------
+bool
+DWARFDebugInfoEntry::GetDIENamesAndRanges
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const char * &name,
+    const char * &mangled,
+    DWARFDebugRanges::RangeList& ranges,
+    int& decl_file,
+    int& decl_line,
+    int& decl_column,
+    int& call_file,
+    int& call_line,
+    int& call_column,
+    DWARFExpression *frame_base
+) const
+{
+    if (dwarf2Data == NULL)
+        return false;
+
+    dw_addr_t lo_pc = DW_INVALID_ADDRESS;
+    dw_addr_t hi_pc = DW_INVALID_ADDRESS;
+    std::vector<dw_offset_t> die_offsets;
+    if (m_abbrevDecl)
+    {
+        const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
+        uint32_t offset = m_offset;
+
+        if (!debug_info_data.ValidOffset(offset))
+            return false;
+
+        // Skip the abbreviation code
+        debug_info_data.Skip_LEB128(&offset);
+
+        const uint32_t numAttributes = m_abbrevDecl->NumAttributes();
+        uint32_t i;
+        dw_attr_t attr;
+        dw_form_t form;
+        for (i=0; i<numAttributes; ++i)
+        {
+            m_abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form);
+            DWARFFormValue form_value(form);
+            if (form_value.ExtractValue(debug_info_data, &offset, cu))
+            {
+                switch (attr)
+                {
+                case DW_AT_low_pc:
+                case DW_AT_entry_pc:
+                    lo_pc = form_value.Unsigned();
+                    break;
+
+                case DW_AT_high_pc:
+                    hi_pc = form_value.Unsigned();
+                    break;
+
+                case DW_AT_ranges:
+                    {
+                        const DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges();
+                        debug_ranges->FindRanges(form_value.Unsigned(), ranges);
+                        // All DW_AT_ranges are relative to the base address of the
+                        // compile unit. We add the compile unit base address to make
+                        // sure all the addresses are properly fixed up.
+                        ranges.AddOffset(cu->GetBaseAddress());
+                    }
+                    break;
+
+                case DW_AT_name:
+                    if (name == NULL)
+                        name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+                    break;
+
+                case DW_AT_MIPS_linkage_name:
+                    if (mangled == NULL)
+                        mangled = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+                    break;
+
+                case DW_AT_abstract_origin:
+                    die_offsets.push_back(form_value.Reference(cu));
+                    break;
+
+                case DW_AT_specification:
+                    die_offsets.push_back(form_value.Reference(cu));
+                    break;
+
+                case DW_AT_decl_file:
+                    if (decl_file == 0)
+                        decl_file = form_value.Unsigned();
+                    break;
+
+                case DW_AT_decl_line:
+                    if (decl_line == 0)
+                        decl_line = form_value.Unsigned();
+                    break;
+
+                case DW_AT_decl_column:
+                    if (decl_column == 0)
+                        decl_column = form_value.Unsigned();
+                    break;
+
+                case DW_AT_call_file:
+                    if (call_file == 0)
+                        call_file = form_value.Unsigned();
+                    break;
+
+                case DW_AT_call_line:
+                    if (call_line == 0)
+                        call_line = form_value.Unsigned();
+                    break;
+
+                case DW_AT_call_column:
+                    if (call_column == 0)
+                        call_column = form_value.Unsigned();
+                    break;
+
+                case DW_AT_frame_base:
+                    if (frame_base)
+                    {
+                        if (form_value.BlockData())
+                        {
+                            uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
+                            uint32_t block_length = form_value.Unsigned();
+                            frame_base->SetOpcodeData(debug_info_data, block_offset, block_length, NULL);
+                        }
+                        else
+                        {
+                            const DataExtractor&    debug_loc_data = dwarf2Data->get_debug_loc_data();
+                            const dw_offset_t debug_loc_offset = form_value.Unsigned();
+
+                            size_t loc_list_length = DWARFLocationList::Size(debug_loc_data, debug_loc_offset);
+                            if (loc_list_length > 0)
+                            {
+                                Address base_address(cu->GetBaseAddress(), dwarf2Data->GetObjectFile()->GetSectionList());
+                                frame_base->SetOpcodeData(debug_loc_data, debug_loc_offset, loc_list_length, &base_address);
+                            }
+                        }
+                    }
+                    break;
+
+                default:
+                    break;
+                }
+            }
+        }
+    }
+
+    size_t numRanges = ranges.Size();
+
+    if (numRanges == 0)
+    {
+        if (lo_pc != DW_INVALID_ADDRESS)
+        {
+            if (hi_pc != DW_INVALID_ADDRESS)
+                ranges.AddRange(lo_pc, hi_pc);
+            else
+                ranges.AddRange(lo_pc, lo_pc);
+        }
+    }
+
+    if (ranges.Size() == 0 || (name == NULL) || (mangled == NULL))
+    {
+        std::vector<dw_offset_t>::const_iterator pos;
+        std::vector<dw_offset_t>::const_iterator end = die_offsets.end();
+        for (pos = die_offsets.begin(); pos != end; ++pos)
+        {
+            DWARFCompileUnitSP cu_sp_ptr;
+            const DWARFDebugInfoEntry* die = NULL;
+            dw_offset_t die_offset = *pos;
+            if (die_offset != DW_INVALID_OFFSET)
+            {
+                die = dwarf2Data->DebugInfo()->GetDIEPtr(die_offset, &cu_sp_ptr);
+                if (die)
+                    die->GetDIENamesAndRanges(dwarf2Data, cu_sp_ptr.get(), name, mangled, ranges, decl_file, decl_line, decl_column, call_file, call_line, call_column);
+            }
+        }
+    }
+    return ranges.Size() > 0;
+}
+
+//----------------------------------------------------------------------
+// Dump
+//
+// Dumps a debug information entry and all of it's attributes to the
+// specified stream.
+//----------------------------------------------------------------------
+void
+DWARFDebugInfoEntry::Dump
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    Stream *s,
+    uint32_t recurse_depth
+) const
+{
+    const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
+    uint32_t offset = m_offset;
+    bool english    = s->GetFlags().IsSet (DWARFDebugInfo::eDumpFlag_EnglishyNames);
+
+    if (debug_info_data.ValidOffset(offset))
+    {
+        dw_uleb128_t abbrCode = debug_info_data.GetULEB128(&offset);
+
+        s->Printf("\n0x%8.8x: ", m_offset);
+        s->Indent();
+        if (abbrCode)
+        {
+            if (m_abbrevDecl)
+            {
+                if (english)
+                    s->PutCString(DW_TAG_value_to_englishy_name(m_abbrevDecl->Tag()));
+                else
+                    s->PutCString(DW_TAG_value_to_name(m_abbrevDecl->Tag()));
+                s->Printf( " [%u] %c\n", abbrCode, m_abbrevDecl->HasChildren() ? '*':' ');
+
+                // Dump all data in the .debug_info for the attributes
+                const uint32_t numAttributes = m_abbrevDecl->NumAttributes();
+                uint32_t i;
+                dw_attr_t attr;
+                dw_form_t form;
+                for (i=0; i<numAttributes; ++i)
+                {
+                    m_abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form);
+
+                    DumpAttribute(dwarf2Data, cu, debug_info_data, &offset, s, attr, form);
+                }
+
+                const DWARFDebugInfoEntry* child = GetFirstChild();
+                if (recurse_depth > 0 && child)
+                {
+                    s->IndentMore();
+
+                    while (child)
+                    {
+                        child->Dump(dwarf2Data, cu, s, recurse_depth-1);
+                        child = child->GetSibling();
+                    }
+                    s->IndentLess();
+                }
+            }
+            else
+                s->Printf( "Abbreviation code note found in 'debug_abbrev' class for code: %u\n", abbrCode);
+        }
+        else
+        {
+            s->Printf( "NULL\n");
+        }
+    }
+}
+
+//----------------------------------------------------------------------
+// DumpAttribute
+//
+// Dumps a debug information entry attribute along with it's form. Any
+// special display of attributes is done (disassemble location lists,
+// show enumeration values for attributes, etc).
+//----------------------------------------------------------------------
+void
+DWARFDebugInfoEntry::DumpAttribute
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const DataExtractor& debug_info_data,
+    uint32_t* offset_ptr,
+    Stream *s,
+    dw_attr_t attr,
+    dw_form_t form
+)
+{
+    bool verbose    = s->GetVerbose();
+    bool show_form  = s->GetFlags().IsSet(DWARFDebugInfo::eDumpFlag_ShowForm);
+    bool english    = s->GetFlags().IsSet(DWARFDebugInfo::eDumpFlag_EnglishyNames);
+    const DataExtractor* debug_str_data = dwarf2Data ? &dwarf2Data->get_debug_str_data() : NULL;
+    if (verbose)
+        s->Offset(*offset_ptr);
+    else
+        s->Printf( "            ");
+    s->Indent();
+
+    if (english)
+        s->PutCString(DW_AT_value_to_englishy_name(attr));
+    else
+        s->PutCString(DW_AT_value_to_name(attr));
+
+    if (show_form)
+    {
+        s->Printf( "[%s", english ? DW_FORM_value_to_englishy_name(form) : DW_FORM_value_to_name(form));
+    }
+
+    DWARFFormValue form_value(form);
+
+    if (!form_value.ExtractValue(debug_info_data, offset_ptr, cu))
+        return;
+
+    if (show_form)
+    {
+        if (form == DW_FORM_indirect)
+        {
+            s->Printf( " [%s]", english ? DW_FORM_value_to_englishy_name(form_value.Form()) : DW_FORM_value_to_name(form_value.Form()));
+        }
+
+        s->PutCString("] ");
+    }
+
+    s->PutCString("( ");
+
+    // Always dump form value if verbose is enabled
+    if (verbose)
+    {
+        form_value.Dump(s, debug_str_data, cu);
+    }
+
+
+    // Check to see if we have any special attribute formatters
+    switch (attr)
+    {
+    case DW_AT_stmt_list:
+        if ( verbose ) s->PutCString(" ( ");
+        s->Printf( "0x%8.8x", form_value.Unsigned());
+        if ( verbose ) s->PutCString(" )");
+        break;
+
+    case DW_AT_language:
+        if ( verbose ) s->PutCString(" ( ");
+        s->PutCString(DW_LANG_value_to_name(form_value.Unsigned()));
+        if ( verbose ) s->PutCString(" )");
+        break;
+
+    case DW_AT_encoding:
+        if ( verbose ) s->PutCString(" ( ");
+        s->PutCString(DW_ATE_value_to_name(form_value.Unsigned()));
+        if ( verbose ) s->PutCString(" )");
+        break;
+
+    case DW_AT_frame_base:
+    case DW_AT_location:
+    case DW_AT_data_member_location:
+        {
+            const uint8_t* blockData = form_value.BlockData();
+            if (blockData)
+            {
+                if (!verbose)
+                    form_value.Dump(s, debug_str_data, cu);
+
+                // Location description is inlined in data in the form value
+                DataExtractor locationData(debug_info_data, (*offset_ptr) - form_value.Unsigned(), form_value.Unsigned());
+                if ( verbose ) s->PutCString(" ( ");
+                print_dwarf_expression (s, locationData, DWARFCompileUnit::GetAddressByteSize(cu), 4, false);
+                if ( verbose ) s->PutCString(" )");
+            }
+            else
+            {
+                // We have a location list offset as the value that is
+                // the offset into the .debug_loc section that describes
+                // the value over it's lifetime
+                uint64_t debug_loc_offset = form_value.Unsigned();
+                if (dwarf2Data)
+                {
+                    if ( !verbose )
+                        form_value.Dump(s, debug_str_data, cu);
+                    DWARFLocationList::Dump(s, cu, dwarf2Data->get_debug_loc_data(), debug_loc_offset);
+                }
+                else
+                {
+                    if ( !verbose )
+                        form_value.Dump(s, NULL, cu);
+                }
+            }
+        }
+        break;
+
+    case DW_AT_abstract_origin:
+    case DW_AT_specification:
+        {
+            uint64_t abstract_die_offset = form_value.Reference(cu);
+            form_value.Dump(s, debug_str_data, cu);
+        //  *ostrm_ptr << HEX32 << abstract_die_offset << " ( ";
+            if ( verbose ) s->PutCString(" ( ");
+            GetName(dwarf2Data, cu, abstract_die_offset, s);
+            if ( verbose ) s->PutCString(" )");
+        }
+        break;
+
+    case DW_AT_type:
+        {
+            uint64_t type_die_offset = form_value.Reference(cu);
+            if (!verbose)
+                form_value.Dump(s, debug_str_data, cu);
+            s->PutCString(" ( ");
+            AppendTypeName(dwarf2Data, cu, type_die_offset, s);
+            s->PutCString(" )");
+        }
+        break;
+
+    case DW_AT_ranges:
+        {
+            if ( !verbose )
+                form_value.Dump(s, debug_str_data, cu);
+            uint32_t ranges_offset = form_value.Unsigned();
+            dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0;
+            DWARFDebugRanges::Dump(s, dwarf2Data->get_debug_ranges_data(), &ranges_offset, base_addr);
+        }
+        break;
+
+    default:
+        if ( !verbose )
+            form_value.Dump(s, debug_str_data, cu);
+        break;
+    }
+
+    s->PutCString(" )\n");
+}
+
+//----------------------------------------------------------------------
+// Get all attribute values for a given DIE, including following any
+// specification or abstract origin attributes and including those in
+// the results. Any duplicate attributes will have the first instance
+// take precedence (this can happen for declaration attributes).
+//----------------------------------------------------------------------
+size_t
+DWARFDebugInfoEntry::GetAttributes
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    DWARFDebugInfoEntry::Attributes& attributes
+) const
+{
+    if (m_abbrevDecl)
+    {
+        uint32_t offset = GetOffset();
+        const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
+
+        // Skip the abbreviation code so we are at the data for the attributes
+        debug_info_data.Skip_LEB128(&offset);
+
+        const uint32_t num_attributes = m_abbrevDecl->NumAttributes();
+        uint32_t i;
+        dw_attr_t attr;
+        dw_form_t form;
+        DWARFFormValue form_value;
+        for (i=0; i<num_attributes; ++i)
+        {
+            m_abbrevDecl->GetAttrAndFormByIndexUnchecked (i, attr, form);
+            attributes.Append(cu, offset, attr, form);
+            if ((attr == DW_AT_specification) || (attr == DW_AT_abstract_origin))
+            {
+                form_value.SetForm(form);
+                if (form_value.ExtractValue(debug_info_data, &offset, cu))
+                {
+                    const DWARFDebugInfoEntry* die = NULL;
+                    dw_offset_t die_offset = form_value.Reference(cu);
+                    if (cu->ContainsDIEOffset(die_offset))
+                    {
+                        die = const_cast<DWARFCompileUnit*>(cu)->GetDIEPtr(die_offset);
+                        if (die)
+                            die->GetAttributes(dwarf2Data, cu, attributes);
+                    }
+                    else
+                    {
+                        DWARFCompileUnitSP cu_sp_ptr;
+                        die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(die_offset, &cu_sp_ptr);
+                        if (die)
+                            die->GetAttributes(dwarf2Data, cu_sp_ptr.get(), attributes);
+                    }
+                }
+            }
+            else
+            {
+                assert(DWARFFormValue::SkipValue(form, debug_info_data, &offset, cu));
+            }
+        }
+    }
+    else
+    {
+        attributes.Clear();
+    }
+    return attributes.Size();
+
+}
+
+//----------------------------------------------------------------------
+// GetAttributeValue
+//
+// Get the value of an attribute and return the .debug_info offset of the
+// attribute if it was properly extracted into form_value, or zero
+// if we fail since an offset of zero is invalid for an attribute (it
+// would be a compile unit header).
+//----------------------------------------------------------------------
+dw_offset_t
+DWARFDebugInfoEntry::GetAttributeValue
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const dw_attr_t attr,
+    DWARFFormValue& form_value,
+    dw_offset_t* end_attr_offset_ptr
+) const
+{
+    if (m_abbrevDecl)
+    {
+        uint32_t attr_idx = m_abbrevDecl->FindAttributeIndex(attr);
+
+        if (attr_idx != DW_INVALID_INDEX)
+        {
+            uint32_t offset = GetOffset();
+
+            const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
+
+            // Skip the abbreviation code so we are at the data for the attributes
+            debug_info_data.Skip_LEB128(&offset);
+
+            uint32_t idx=0;
+            while (idx<attr_idx)
+                DWARFFormValue::SkipValue(m_abbrevDecl->GetFormByIndex(idx++), debug_info_data, &offset, cu);
+
+            const dw_offset_t attr_offset = offset;
+            form_value.SetForm(m_abbrevDecl->GetFormByIndex(idx));
+            if (form_value.ExtractValue(debug_info_data, &offset, cu))
+            {
+                if (end_attr_offset_ptr)
+                    *end_attr_offset_ptr = offset;
+                return attr_offset;
+            }
+        }
+    }
+
+    return 0;
+}
+
+//----------------------------------------------------------------------
+// GetAttributeValueAsString
+//
+// Get the value of an attribute as a string return it. The resulting
+// pointer to the string data exists within the supplied SymbolFileDWARF
+// and will only be available as long as the SymbolFileDWARF is still around
+// and it's content doesn't change.
+//----------------------------------------------------------------------
+const char*
+DWARFDebugInfoEntry::GetAttributeValueAsString
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const dw_attr_t attr,
+    const char* fail_value) const
+{
+    DWARFFormValue form_value;
+    if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
+        return form_value.AsCString(&dwarf2Data->get_debug_str_data());
+    return fail_value;
+}
+
+//----------------------------------------------------------------------
+// GetAttributeValueAsUnsigned
+//
+// Get the value of an attribute as unsigned and return it.
+//----------------------------------------------------------------------
+uint64_t
+DWARFDebugInfoEntry::GetAttributeValueAsUnsigned
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const dw_attr_t attr,
+    uint64_t fail_value
+) const
+{
+    DWARFFormValue form_value;
+    if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
+        return form_value.Unsigned();
+    return fail_value;
+}
+
+//----------------------------------------------------------------------
+// GetAttributeValueAsSigned
+//
+// Get the value of an attribute a signed value and return it.
+//----------------------------------------------------------------------
+int64_t
+DWARFDebugInfoEntry::GetAttributeValueAsSigned
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const dw_attr_t attr,
+    int64_t fail_value
+) const
+{
+    DWARFFormValue form_value;
+    if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
+        return form_value.Signed();
+    return fail_value;
+}
+
+//----------------------------------------------------------------------
+// GetAttributeValueAsReference
+//
+// Get the value of an attribute as reference and fix up and compile
+// unit relative offsets as needed.
+//----------------------------------------------------------------------
+uint64_t
+DWARFDebugInfoEntry::GetAttributeValueAsReference
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const dw_attr_t attr,
+    uint64_t fail_value
+) const
+{
+    DWARFFormValue form_value;
+    if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
+        return form_value.Reference(cu);
+    return fail_value;
+}
+
+//----------------------------------------------------------------------
+// GetAttributeValueAsLocation
+//
+// Get the value of an attribute as reference and fix up and compile
+// unit relative offsets as needed.
+//----------------------------------------------------------------------
+dw_offset_t
+DWARFDebugInfoEntry::GetAttributeValueAsLocation
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const dw_attr_t attr,
+    DataExtractor& location_data,
+    uint32_t &block_size
+) const
+{
+    block_size = 0;
+    DWARFFormValue form_value;
+
+    // Empty out data in case we don't find anything
+    location_data.Clear();
+    dw_offset_t end_addr_offset = DW_INVALID_OFFSET;
+    const dw_offset_t attr_offset = GetAttributeValue(dwarf2Data, cu, attr, form_value, &end_addr_offset);
+    if (attr_offset)
+    {
+        const uint8_t* blockData = form_value.BlockData();
+        if (blockData)
+        {
+            // We have an inlined location list in the .debug_info section
+            const DataExtractor& debug_info = dwarf2Data->get_debug_info_data();
+            dw_offset_t block_offset = blockData - debug_info.GetDataStart();
+            block_size = (end_addr_offset - attr_offset) - form_value.Unsigned();
+            location_data.SetData(debug_info, block_offset, block_size);
+        }
+        else
+        {
+            // We have a location list offset as the value that is
+            // the offset into the .debug_loc section that describes
+            // the value over it's lifetime
+            dw_offset_t debug_loc_offset = form_value.Unsigned();
+            if (dwarf2Data)
+            {
+                assert(dwarf2Data->get_debug_loc_data().GetAddressByteSize() == cu->GetAddressByteSize());
+                return DWARFLocationList::Extract(dwarf2Data->get_debug_loc_data(), &debug_loc_offset, location_data);
+            }
+        }
+    }
+    return attr_offset;
+}
+
+//----------------------------------------------------------------------
+// GetName
+//
+// Get value of the DW_AT_name attribute and return it if one exists,
+// else return NULL.
+//----------------------------------------------------------------------
+const char*
+DWARFDebugInfoEntry::GetName
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu
+) const
+{
+    DWARFFormValue form_value;
+    if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
+        return form_value.AsCString(&dwarf2Data->get_debug_str_data());
+    return NULL;
+}
+
+
+//----------------------------------------------------------------------
+// GetMangledName
+//
+// Get value of the DW_AT_MIPS_linkage_name attribute and return it if
+// one exists, else return the value of the DW_AT_name attribute
+//----------------------------------------------------------------------
+const char*
+DWARFDebugInfoEntry::GetMangledName
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    bool substitute_name_allowed
+) const
+{
+    const char* name = NULL;
+    DWARFFormValue form_value;
+
+    if (GetAttributeValue(dwarf2Data, cu, DW_AT_MIPS_linkage_name, form_value))
+        name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+
+    if (substitute_name_allowed && name == NULL)
+    {
+        if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
+            name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+    }
+    return name;
+}
+
+
+//----------------------------------------------------------------------
+// GetPubname
+//
+// Get value the name for a DIE as it should appear for a
+// .debug_pubnames or .debug_pubtypes section.
+//----------------------------------------------------------------------
+const char*
+DWARFDebugInfoEntry::GetPubname
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu
+) const
+{
+    const char* name = NULL;
+    DWARFFormValue form_value;
+
+    if (GetAttributeValue(dwarf2Data, cu, DW_AT_MIPS_linkage_name, form_value))
+        name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+    else if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
+        name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+    else if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value))
+    {
+        // The specification DIE may be in another compile unit so we need
+        // to get a die and its compile unit.
+        DWARFCompileUnitSP cu_sp_ptr;
+        const DWARFDebugInfoEntry* die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(cu), &cu_sp_ptr);
+        if (die)
+            return die->GetPubname(dwarf2Data, cu_sp_ptr.get());
+    }
+    return name;
+}
+
+
+//----------------------------------------------------------------------
+// GetName
+//
+// Get value of the DW_AT_name attribute for a debug information entry
+// that exists at offset "die_offset" and place that value into the
+// supplied stream object. If the DIE is a NULL object "NULL" is placed
+// into the stream, and if no DW_AT_name attribute exists for the DIE
+// then nothing is printed.
+//----------------------------------------------------------------------
+bool
+DWARFDebugInfoEntry::GetName
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const uint32_t die_offset,
+    Stream *s
+)
+{
+    DWARFDebugInfoEntry die;
+    uint32_t offset = die_offset;
+    if (die.Extract(dwarf2Data, cu, &offset))
+    {
+        if (die.IsNULL())
+        {
+            s->PutCString("NULL");
+            return true;
+        }
+        else
+        {
+            DWARFFormValue form_value;
+            if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
+            {
+                const char* name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+                if (name)
+                {
+                    s->PutCString(name);
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+//----------------------------------------------------------------------
+// AppendTypeName
+//
+// Follows the type name definition down through all needed tags to
+// end up with a fully qualified type name and dump the results to
+// the supplied stream. This is used to show the name of types given
+// a type identifier.
+//----------------------------------------------------------------------
+bool
+DWARFDebugInfoEntry::AppendTypeName
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const uint32_t die_offset,
+    Stream *s
+)
+{
+    DWARFDebugInfoEntry die;
+    uint32_t offset = die_offset;
+    if (die.Extract(dwarf2Data, cu, &offset))
+    {
+        if (die.IsNULL())
+        {
+            s->PutCString("NULL");
+            return true;
+        }
+        else
+        {
+            const char* name = die.GetPubname(dwarf2Data, cu);
+        //  if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
+        //      name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+            if (name)
+                s->PutCString(name);
+            else
+            {
+                bool result = true;
+                const DWARFAbbreviationDeclaration* abbrevDecl = die.GetAbbreviationDeclarationPtr();
+
+                switch (abbrevDecl->Tag())
+                {
+                case DW_TAG_array_type:         break;  // print out a "[]" after printing the full type of the element below
+                case DW_TAG_base_type:          s->PutCString("base ");         break;
+                case DW_TAG_class_type:         s->PutCString("class ");            break;
+                case DW_TAG_const_type:         s->PutCString("const ");            break;
+                case DW_TAG_enumeration_type:   s->PutCString("enum ");         break;
+                case DW_TAG_file_type:          s->PutCString("file ");         break;
+                case DW_TAG_interface_type:     s->PutCString("interface ");        break;
+                case DW_TAG_packed_type:        s->PutCString("packed ");       break;
+                case DW_TAG_pointer_type:       break;  // print out a '*' after printing the full type below
+                case DW_TAG_ptr_to_member_type: break;  // print out a '*' after printing the full type below
+                case DW_TAG_reference_type:     break;  // print out a '&' after printing the full type below
+                case DW_TAG_restrict_type:      s->PutCString("restrict ");     break;
+                case DW_TAG_set_type:           s->PutCString("set ");          break;
+                case DW_TAG_shared_type:        s->PutCString("shared ");       break;
+                case DW_TAG_string_type:        s->PutCString("string ");       break;
+                case DW_TAG_structure_type:     s->PutCString("struct ");       break;
+                case DW_TAG_subrange_type:      s->PutCString("subrange ");     break;
+                case DW_TAG_subroutine_type:    s->PutCString("function ");     break;
+                case DW_TAG_thrown_type:        s->PutCString("thrown ");       break;
+                case DW_TAG_union_type:         s->PutCString("union ");            break;
+                case DW_TAG_unspecified_type:   s->PutCString("unspecified ");  break;
+                case DW_TAG_volatile_type:      s->PutCString("volatile ");     break;
+                default:
+                    return false;
+                }
+
+                // Follow the DW_AT_type if possible
+                DWARFFormValue form_value;
+                if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_type, form_value))
+                {
+                    uint64_t next_die_offset = form_value.Reference(cu);
+                    result = AppendTypeName(dwarf2Data, cu, next_die_offset, s);
+                }
+
+                switch (abbrevDecl->Tag())
+                {
+                case DW_TAG_array_type:         s->PutCString("[]");    break;
+                case DW_TAG_pointer_type:       s->PutChar('*');    break;
+                case DW_TAG_ptr_to_member_type: s->PutChar('*');    break;
+                case DW_TAG_reference_type:     s->PutChar('&');    break;
+                default:
+                    break;
+                }
+                return result;
+            }
+        }
+    }
+    return false;
+}
+
+//----------------------------------------------------------------------
+// BuildAddressRangeTable
+//----------------------------------------------------------------------
+void
+DWARFDebugInfoEntry::BuildAddressRangeTable
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    DWARFDebugAranges* debug_aranges
+) const
+{
+    if (m_abbrevDecl)
+    {
+        dw_tag_t tag = m_abbrevDecl->Tag();
+        if (tag == DW_TAG_subprogram)
+        {
+            dw_addr_t hi_pc = DW_INVALID_ADDRESS;
+            dw_addr_t lo_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, DW_INVALID_ADDRESS);
+            if (lo_pc != DW_INVALID_ADDRESS)
+                hi_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_high_pc, DW_INVALID_ADDRESS);
+            if (hi_pc != DW_INVALID_ADDRESS)
+            {
+            /// printf("BuildAddressRangeTable() 0x%8.8x: %30s: [0x%8.8x - 0x%8.8x)\n", m_offset, DW_TAG_value_to_name(tag), lo_pc, hi_pc);
+                debug_aranges->InsertRange(cu->GetOffset(), lo_pc, hi_pc);
+            }
+        }
+
+
+        const DWARFDebugInfoEntry* child = GetFirstChild();
+        while (child)
+        {
+            child->BuildAddressRangeTable(dwarf2Data, cu, debug_aranges);
+            child = child->GetSibling();
+        }
+    }
+}
+
+//----------------------------------------------------------------------
+// BuildFunctionAddressRangeTable
+//
+// This function is very similar to the BuildAddressRangeTable function
+// except that the actual DIE offset for the function is placed in the
+// table instead of the compile unit offset (which is the way the
+// standard .debug_aranges section does it).
+//----------------------------------------------------------------------
+void
+DWARFDebugInfoEntry::BuildFunctionAddressRangeTable
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    DWARFDebugAranges* debug_aranges
+) const
+{
+    if (m_abbrevDecl)
+    {
+        dw_tag_t tag = m_abbrevDecl->Tag();
+        if (tag == DW_TAG_subprogram)
+        {
+            dw_addr_t hi_pc = DW_INVALID_ADDRESS;
+            dw_addr_t lo_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, DW_INVALID_ADDRESS);
+            if (lo_pc != DW_INVALID_ADDRESS)
+                hi_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_high_pc, DW_INVALID_ADDRESS);
+            if (hi_pc != DW_INVALID_ADDRESS)
+            {
+            //  printf("BuildAddressRangeTable() 0x%8.8x: [0x%16.16llx - 0x%16.16llx)\n", m_offset, lo_pc, hi_pc); // DEBUG ONLY
+                debug_aranges->InsertRange(GetOffset(), lo_pc, hi_pc);
+            }
+        }
+
+        const DWARFDebugInfoEntry* child = GetFirstChild();
+        while (child)
+        {
+            child->BuildFunctionAddressRangeTable(dwarf2Data, cu, debug_aranges);
+            child = child->GetSibling();
+        }
+    }
+}
+
+
+//----------------------------------------------------------------------
+// LookupAddress
+//----------------------------------------------------------------------
+bool
+DWARFDebugInfoEntry::LookupAddress
+(
+    const dw_addr_t address,
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    DWARFDebugInfoEntry** function_die,
+    DWARFDebugInfoEntry** block_die
+)
+{
+    bool found_address = false;
+    if (m_abbrevDecl)
+    {
+        bool check_children = false;
+        bool match_addr_range = false;
+        dw_tag_t tag = m_abbrevDecl->Tag();
+    //  printf("0x%8.8x: %30s: address = 0x%8.8x - ", m_offset, DW_TAG_value_to_name(tag), address);
+        switch (tag)
+        {
+        case DW_TAG_array_type                 : break;
+        case DW_TAG_class_type                 : check_children = true; break;
+        case DW_TAG_entry_point                : break;
+        case DW_TAG_enumeration_type           : break;
+        case DW_TAG_formal_parameter           : break;
+        case DW_TAG_imported_declaration       : break;
+        case DW_TAG_label                      : break;
+        case DW_TAG_lexical_block              : check_children = true; match_addr_range = true; break;
+        case DW_TAG_member                     : break;
+        case DW_TAG_pointer_type               : break;
+        case DW_TAG_reference_type             : break;
+        case DW_TAG_compile_unit               : match_addr_range = true; break;
+        case DW_TAG_string_type                : break;
+        case DW_TAG_structure_type             : check_children = true; break;
+        case DW_TAG_subroutine_type            : break;
+        case DW_TAG_typedef                    : break;
+        case DW_TAG_union_type                 : break;
+        case DW_TAG_unspecified_parameters     : break;
+        case DW_TAG_variant                    : break;
+        case DW_TAG_common_block               : check_children = true; break;
+        case DW_TAG_common_inclusion           : break;
+        case DW_TAG_inheritance                : break;
+        case DW_TAG_inlined_subroutine         : check_children = true; match_addr_range = true; break;
+        case DW_TAG_module                     : match_addr_range = true; break;
+        case DW_TAG_ptr_to_member_type         : break;
+        case DW_TAG_set_type                   : break;
+        case DW_TAG_subrange_type              : break;
+        case DW_TAG_with_stmt                  : break;
+        case DW_TAG_access_declaration         : break;
+        case DW_TAG_base_type                  : break;
+        case DW_TAG_catch_block                : match_addr_range = true; break;
+        case DW_TAG_const_type                 : break;
+        case DW_TAG_constant                   : break;
+        case DW_TAG_enumerator                 : break;
+        case DW_TAG_file_type                  : break;
+        case DW_TAG_friend                     : break;
+        case DW_TAG_namelist                   : break;
+        case DW_TAG_namelist_item              : break;
+        case DW_TAG_packed_type                : break;
+        case DW_TAG_subprogram                 : match_addr_range = true; break;
+        case DW_TAG_template_type_parameter    : break;
+        case DW_TAG_template_value_parameter   : break;
+        case DW_TAG_thrown_type                : break;
+        case DW_TAG_try_block                  : match_addr_range = true; break;
+        case DW_TAG_variant_part               : break;
+        case DW_TAG_variable                   : break;
+        case DW_TAG_volatile_type              : break;
+        case DW_TAG_dwarf_procedure            : break;
+        case DW_TAG_restrict_type              : break;
+        case DW_TAG_interface_type             : break;
+        case DW_TAG_namespace                  : check_children = true; break;
+        case DW_TAG_imported_module            : break;
+        case DW_TAG_unspecified_type           : break;
+        case DW_TAG_partial_unit               : break;
+        case DW_TAG_imported_unit              : break;
+        case DW_TAG_shared_type                : break;
+        default: break;
+        }
+
+        if (match_addr_range)
+        {
+            dw_addr_t lo_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, DW_INVALID_ADDRESS);
+            if (lo_pc != DW_INVALID_ADDRESS)
+            {
+                dw_addr_t hi_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_high_pc, DW_INVALID_ADDRESS);
+                if (hi_pc != DW_INVALID_ADDRESS)
+                {
+                    //  printf("\n0x%8.8x: %30s: address = 0x%8.8x  [0x%8.8x - 0x%8.8x) ", m_offset, DW_TAG_value_to_name(tag), address, lo_pc, hi_pc);
+                    if ((lo_pc <= address) && (address < hi_pc))
+                    {
+                        found_address = true;
+                    //  puts("***MATCH***");
+                        switch (tag)
+                        {
+                        case DW_TAG_compile_unit:       // File
+                            check_children = ((function_die != NULL) || (block_die != NULL));
+                            break;
+
+                        case DW_TAG_subprogram:         // Function
+                            if (function_die)
+                                *function_die = this;
+                            check_children = (block_die != NULL);
+                            break;
+
+                        case DW_TAG_inlined_subroutine: // Inlined Function
+                        case DW_TAG_lexical_block:      // Block { } in code
+                            if (block_die)
+                            {
+                                *block_die = this;
+                                check_children = true;
+                            }
+                            break;
+
+                        default:
+                            check_children = true;
+                            break;
+                        }
+                    }
+                }
+                else
+                {   // compile units may not have a valid high/low pc when there
+                    // are address gaps in subtroutines so we must always search
+                    // if there is no valid high and low PC
+                    check_children = (tag == DW_TAG_compile_unit) && ((function_die != NULL) || (block_die != NULL));
+                }
+            }
+            else
+            {
+                dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET);
+                if (debug_ranges_offset != DW_INVALID_OFFSET)
+                {
+                    DWARFDebugRanges::RangeList ranges;
+                    DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges();
+                    debug_ranges->FindRanges(debug_ranges_offset, ranges);
+                    // All DW_AT_ranges are relative to the base address of the
+                    // compile unit. We add the compile unit base address to make
+                    // sure all the addresses are properly fixed up.
+                    ranges.AddOffset(cu->GetBaseAddress());
+                    if (ranges.Lookup(address))
+                    {
+                        found_address = true;
+                    //  puts("***MATCH***");
+                        switch (tag)
+                        {
+                        case DW_TAG_compile_unit:       // File
+                            check_children = ((function_die != NULL) || (block_die != NULL));
+                            break;
+
+                        case DW_TAG_subprogram:         // Function
+                            if (function_die)
+                                *function_die = this;
+                            check_children = (block_die != NULL);
+                            break;
+
+                        case DW_TAG_inlined_subroutine: // Inlined Function
+                        case DW_TAG_lexical_block:      // Block { } in code
+                            if (block_die)
+                            {
+                                *block_die = this;
+                                check_children = true;
+                            }
+                            break;
+
+                        default:
+                            check_children = true;
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        check_children = false;
+                    }
+                }
+            }
+        }
+
+
+        if (check_children)
+        {
+        //  printf("checking children\n");
+            DWARFDebugInfoEntry* child = GetFirstChild();
+            while (child)
+            {
+                if (child->LookupAddress(address, dwarf2Data, cu, function_die, block_die))
+                    return true;
+                child = child->GetSibling();
+            }
+        }
+    }
+    return found_address;
+}
+
+
+bool
+DWARFDebugInfoEntry::OffsetLessThan (const DWARFDebugInfoEntry& a, const DWARFDebugInfoEntry& b)
+{
+    return a.GetOffset() < b.GetOffset();
+}
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
new file mode 100644
index 0000000..8340acc
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
@@ -0,0 +1,320 @@
+//===-- DWARFDebugInfoEntry.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_DWARFDebugInfoEntry_h_
+#define liblldb_DWARFDebugInfoEntry_h_
+
+#include "SymbolFileDWARF.h"
+#include "DWARFAbbreviationDeclaration.h"
+#include "DWARFDebugRanges.h"
+#include <vector>
+#include <map>
+#include <set>
+
+typedef std::map<const DWARFDebugInfoEntry*, dw_addr_t>     DIEToAddressMap;
+typedef DIEToAddressMap::iterator                           DIEToAddressMapIter;
+typedef DIEToAddressMap::const_iterator                     DIEToAddressMapConstIter;
+
+typedef std::map<dw_addr_t, const DWARFDebugInfoEntry*>     AddressToDIEMap;
+typedef AddressToDIEMap::iterator                           AddressToDIEMapIter;
+typedef AddressToDIEMap::const_iterator                     AddressToDIEMapConstIter;
+
+
+typedef std::map<dw_offset_t, dw_offset_t>                  DIEToDIEMap;
+typedef DIEToDIEMap::iterator                               DIEToDIEMapIter;
+typedef DIEToDIEMap::const_iterator                         DIEToDIEMapConstIter;
+
+typedef std::map<uint32_t, const DWARFDebugInfoEntry*>      UInt32ToDIEMap;
+typedef UInt32ToDIEMap::iterator                            UInt32ToDIEMapIter;
+typedef UInt32ToDIEMap::const_iterator                      UInt32ToDIEMapConstIter;
+
+typedef std::multimap<uint32_t, const DWARFDebugInfoEntry*> UInt32ToDIEMMap;
+typedef UInt32ToDIEMMap::iterator                           UInt32ToDIEMMapIter;
+typedef UInt32ToDIEMMap::const_iterator                     UInt32ToDIEMMapConstIter;
+
+class DWARFDebugInfoEntry
+{
+public:
+    typedef std::vector<DWARFDebugInfoEntry>    collection;
+    typedef collection::iterator                iterator;
+    typedef collection::const_iterator          const_iterator;
+
+    typedef std::vector<dw_offset_t>            offset_collection;
+    typedef offset_collection::iterator         offset_collection_iterator;
+    typedef offset_collection::const_iterator   offset_collection_const_iterator;
+
+    class Attributes
+    {
+    public:
+        Attributes();
+        ~Attributes();
+
+        void Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr, dw_form_t form);
+        const DWARFCompileUnit * CompileUnitAtIndex(uint32_t i) const { return m_infos[i].cu; }
+        dw_offset_t DIEOffsetAtIndex(uint32_t i) const { return m_infos[i].die_offset; }
+        dw_attr_t AttributeAtIndex(uint32_t i) const { return m_infos[i].attr; }
+        dw_attr_t FormAtIndex(uint32_t i) const { return m_infos[i].form; }
+        bool ExtractFormValueAtIndex (SymbolFileDWARF* dwarf2Data, uint32_t i, DWARFFormValue &form_value) const;
+        uint64_t FormValueAsUnsignedAtIndex (SymbolFileDWARF* dwarf2Data, uint32_t i, uint64_t fail_value) const;
+        uint32_t FindAttributeIndex(dw_attr_t attr) const;
+        bool ContainsAttribute(dw_attr_t attr) const;
+        bool RemoveAttribute(dw_attr_t attr);
+        void Clear() { m_infos.clear(); }
+        uint32_t Size() const { return m_infos.size(); }
+
+    protected:
+        struct Info
+        {
+            const DWARFCompileUnit *cu; // Keep the compile unit with each attribute in case we have DW_FORM_ref_addr values
+            dw_offset_t die_offset;
+            dw_attr_t attr;
+            dw_form_t form;
+        };
+        std::vector<Info> m_infos;
+    };
+
+    struct CompareState
+    {
+        CompareState() :
+            die_offset_pairs()
+        {
+            assert(sizeof(dw_offset_t)*2 == sizeof(uint64_t));
+        }
+
+        bool AddTypePair(dw_offset_t a, dw_offset_t b)
+        {
+            uint64_t a_b_offsets = (uint64_t)a << 32 | (uint64_t)b;
+            // Return true if this type was inserted, false otherwise
+            return die_offset_pairs.insert(a_b_offsets).second;
+        }
+        std::set< uint64_t > die_offset_pairs;
+    };
+
+                DWARFDebugInfoEntry():
+                    m_offset        (DW_INVALID_OFFSET),
+                    m_parent_idx    (0),
+                    m_sibling_idx   (0),
+                    m_abbrevDecl    (NULL),
+                    m_user_data     (NULL)
+                {
+                }
+
+
+    void        BuildAddressRangeTable(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    DWARFDebugAranges* debug_aranges) const;
+
+    void        BuildFunctionAddressRangeTable(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    DWARFDebugAranges* debug_aranges) const;
+
+    bool        Extract(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    dw_offset_t* offset_ptr);
+
+    bool        LookupAddress(
+                    const dw_addr_t address,
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    DWARFDebugInfoEntry** function_die,
+                    DWARFDebugInfoEntry** block_die);
+
+    size_t      GetAttributes(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    DWARFDebugInfoEntry::Attributes& attrs) const;
+
+    dw_offset_t GetAttributeValue(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const dw_attr_t attr,
+                    DWARFFormValue& formValue,
+                    dw_offset_t* end_attr_offset_ptr = NULL) const;
+
+    const char* GetAttributeValueAsString(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const dw_attr_t attr,
+                    const char* fail_value) const;
+
+    uint64_t    GetAttributeValueAsUnsigned(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const dw_attr_t attr,
+                    uint64_t fail_value) const;
+
+    uint64_t    GetAttributeValueAsReference(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const dw_attr_t attr,
+                    uint64_t fail_value) const;
+
+    int64_t     GetAttributeValueAsSigned(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const dw_attr_t attr,
+                    int64_t fail_value) const;
+
+    dw_offset_t GetAttributeValueAsLocation(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const dw_attr_t attr,
+                    lldb_private::DataExtractor& data,
+                    uint32_t &block_size) const;
+
+    const char* GetName(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu) const;
+
+    const char* GetMangledName(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    bool substitute_name_allowed = true) const;
+
+    const char* GetPubname(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu) const;
+
+    static bool GetName(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const dw_offset_t die_offset,
+                    lldb_private::Stream *s);
+
+    static bool AppendTypeName(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const dw_offset_t die_offset,
+                    lldb_private::Stream *s);
+
+    static int  Compare(
+                    SymbolFileDWARF* dwarf2Data,
+                    dw_offset_t a_die_offset,
+                    dw_offset_t b_die_offset,
+                    CompareState &compare_state,
+                    bool compare_siblings,
+                    bool compare_children);
+
+    static int Compare(
+                    SymbolFileDWARF* dwarf2Data,
+                    DWARFCompileUnit* a_cu, const DWARFDebugInfoEntry* a_die,
+                    DWARFCompileUnit* b_cu, const DWARFDebugInfoEntry* b_die,
+                    CompareState &compare_state,
+                    bool compare_siblings,
+                    bool compare_children);
+
+    static bool OffsetLessThan (
+                    const DWARFDebugInfoEntry& a,
+                    const DWARFDebugInfoEntry& b);
+
+    bool        AppendDependentDIES(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const bool add_children,
+                    DWARFDIECollection& die_offsets) const;
+
+    void        Dump(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    lldb_private::Stream *s,
+                    uint32_t recurse_depth) const;
+
+    void        DumpAncestry(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const DWARFDebugInfoEntry* oldest,
+                    lldb_private::Stream *s,
+                    uint32_t recurse_depth) const;
+
+    static void DumpAttribute(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const lldb_private::DataExtractor& debug_info_data,
+                    uint32_t* offset_ptr,
+                    lldb_private::Stream *s,
+                    dw_attr_t attr,
+                    dw_form_t form);
+
+    bool        GetDIENamesAndRanges(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const char * &name,
+                    const char * &mangled,
+                    DWARFDebugRanges::RangeList& rangeList,
+                    int& decl_file,
+                    int& decl_line,
+                    int& decl_column,
+                    int& call_file,
+                    int& call_line,
+                    int& call_column,
+                    lldb_private::DWARFExpression *frame_base = NULL) const;
+
+
+    dw_tag_t    Tag()           const { return m_abbrevDecl ? m_abbrevDecl->Tag() : 0; }
+    bool        IsNULL()        const { return m_abbrevDecl == NULL; }
+    dw_offset_t GetOffset()     const { return m_offset; }
+    void        SetOffset(dw_offset_t offset) { m_offset = offset; }
+    uint32_t    NumAttributes() const { return m_abbrevDecl ? m_abbrevDecl->NumAttributes() : 0; }
+    bool        HasChildren()   const { return m_abbrevDecl != NULL && m_abbrevDecl->HasChildren(); }
+
+            // We know we are kept in a vector of contiguous entries, so we know
+            // our parent will be some index behind "this".
+            DWARFDebugInfoEntry*    GetParent()             { return m_parent_idx > 0 ? this - m_parent_idx : NULL;  }
+    const   DWARFDebugInfoEntry*    GetParent()     const   { return m_parent_idx > 0 ? this - m_parent_idx : NULL;  }
+            // We know we are kept in a vector of contiguous entries, so we know
+            // our sibling will be some index after "this".
+            DWARFDebugInfoEntry*    GetSibling()            { return m_sibling_idx > 0 ? this + m_sibling_idx : NULL;  }
+    const   DWARFDebugInfoEntry*    GetSibling()    const   { return m_sibling_idx > 0 ? this + m_sibling_idx : NULL;  }
+            // We know we are kept in a vector of contiguous entries, so we know
+            // we don't need to store our child pointer, if we have a child it will
+            // be the next entry in the list...
+            DWARFDebugInfoEntry*    GetFirstChild()         { return HasChildren() ? this + 1 : NULL; }
+    const   DWARFDebugInfoEntry*    GetFirstChild() const   { return HasChildren() ? this + 1 : NULL; }
+
+    void        
+    SetParent (DWARFDebugInfoEntry* parent)     
+    {
+        if (parent)
+        {
+            // We know we are kept in a vector of contiguous entries, so we know
+            // our parent will be some index behind "this".
+            m_parent_idx = this - parent;
+        }
+        else        
+            m_parent_idx = 0;
+    }
+    void
+    SetSibling (DWARFDebugInfoEntry* sibling)
+    {
+        if (sibling)
+        {
+            // We know we are kept in a vector of contiguous entries, so we know
+            // our sibling will be some index after "this".
+            m_sibling_idx = sibling - this;
+            sibling->SetParent(GetParent()); 
+        }
+        else        
+            m_sibling_idx = 0;
+    }
+    const DWARFAbbreviationDeclaration* GetAbbreviationDeclarationPtr() const { return m_abbrevDecl; }
+
+    void *      GetUserData() const { return m_user_data; }
+    void        SetUserData(void *d) const { m_user_data = d; }
+protected:
+    dw_offset_t                         m_offset;       // Offset within the .debug_info of the start of this entry
+    uint32_t                            m_parent_idx;   // How many to subtract from "this" to get the parent. If zero this die has no parent
+    uint32_t                            m_sibling_idx;  // How many to add to "this" to get the sibling.
+    const DWARFAbbreviationDeclaration* m_abbrevDecl;
+    mutable void *                      m_user_data;    // Flags for use by the parsers
+};
+
+#endif  // liblldb_DWARFDebugInfoEntry_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
new file mode 100644
index 0000000..2b3f39b
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
@@ -0,0 +1,1410 @@
+//===-- DWARFDebugLine.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugLine.h"
+
+//#define ENABLE_DEBUG_PRINTF   // DO NOT LEAVE THIS DEFINED: DEBUG ONLY!!!
+#include <assert.h>
+
+#include "lldb/Core/FileSpecList.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Timer.h"
+
+#include "SymbolFileDWARF.h"
+#include "LogChannelDWARF.h"
+
+using namespace lldb_private;
+using namespace std;
+
+//----------------------------------------------------------------------
+// Parse
+//
+// Parse all information in the debug_line_data into an internal
+// representation.
+//----------------------------------------------------------------------
+void
+DWARFDebugLine::Parse(const DataExtractor& debug_line_data)
+{
+    m_lineTableMap.clear();
+    dw_offset_t offset = 0;
+    LineTable::shared_ptr line_table_sp(new LineTable);
+    while (debug_line_data.ValidOffset(offset))
+    {
+        const uint32_t debug_line_offset = offset;
+
+        if (line_table_sp.get() == NULL)
+            break;
+
+        if (ParseStatementTable(debug_line_data, &offset, line_table_sp.get()))
+        {
+            // Make sure we don't don't loop infinitely
+            if (offset <= debug_line_offset)
+                break;
+            //DEBUG_PRINTF("m_lineTableMap[0x%8.8x] = line_table_sp\n", debug_line_offset);
+            m_lineTableMap[debug_line_offset] = line_table_sp;
+            line_table_sp.reset(new LineTable);
+        }
+        else
+            ++offset;   // Try next byte in line table
+    }
+}
+
+void
+DWARFDebugLine::ParseIfNeeded(const DataExtractor& debug_line_data)
+{
+    if (m_lineTableMap.empty())
+        Parse(debug_line_data);
+}
+
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::GetLineTable
+//----------------------------------------------------------------------
+DWARFDebugLine::LineTable::shared_ptr
+DWARFDebugLine::GetLineTable(const dw_offset_t offset) const
+{
+    DWARFDebugLine::LineTable::shared_ptr line_table_shared_ptr;
+    LineTableConstIter pos = m_lineTableMap.find(offset);
+    if (pos != m_lineTableMap.end())
+        line_table_shared_ptr = pos->second;
+    return line_table_shared_ptr;
+}
+
+
+//----------------------------------------------------------------------
+// DumpStateToFile
+//----------------------------------------------------------------------
+static void
+DumpStateToFile (dw_offset_t offset, const DWARFDebugLine::State& state, void* userData)
+{
+    Log *log = (Log *)userData;
+    if (state.row == DWARFDebugLine::State::StartParsingLineTable)
+    {
+        // If the row is zero we are being called with the prologue only
+        state.prologue->Dump (log);
+        log->PutCString ("Address            Line   Column File");
+        log->PutCString ("------------------ ------ ------ ------");
+    }
+    else if (state.row == DWARFDebugLine::State::DoneParsingLineTable)
+    {
+        // Done parsing line table
+    }
+    else
+    {
+        log->Printf( "0x%16.16llx %6u %6u %6u%s\n", state.address, state.line, state.column, state.file, state.end_sequence ? " END" : "");
+    }
+}
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::DumpLineTableRows
+//----------------------------------------------------------------------
+bool
+DWARFDebugLine::DumpLineTableRows(Log *log, SymbolFileDWARF* dwarf2Data, dw_offset_t debug_line_offset)
+{
+    const DataExtractor& debug_line_data = dwarf2Data->get_debug_line_data();
+
+    if (debug_line_offset == DW_INVALID_OFFSET)
+    {
+        // Dump line table to a single file only
+        debug_line_offset = 0;
+        while (debug_line_data.ValidOffset(debug_line_offset))
+            debug_line_offset = DumpStatementTable (log, debug_line_data, debug_line_offset);
+    }
+    else
+    {
+        // Dump line table to a single file only
+        DumpStatementTable (log, debug_line_data, debug_line_offset);
+    }
+    return false;
+}
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::DumpStatementTable
+//----------------------------------------------------------------------
+dw_offset_t
+DWARFDebugLine::DumpStatementTable(Log *log, const DataExtractor& debug_line_data, const dw_offset_t debug_line_offset)
+{
+    if (debug_line_data.ValidOffset(debug_line_offset))
+    {
+        uint32_t offset = debug_line_offset;
+        log->Printf(  "----------------------------------------------------------------------\n"
+                    "debug_line[0x%8.8x]\n"
+                    "----------------------------------------------------------------------\n", debug_line_offset);
+
+        if (ParseStatementTable(debug_line_data, &offset, DumpStateToFile, log))
+            return offset;
+        else
+            return debug_line_offset + 1;   // Skip to next byte in .debug_line section
+    }
+
+    return DW_INVALID_OFFSET;
+}
+
+
+//----------------------------------------------------------------------
+// DumpOpcodes
+//----------------------------------------------------------------------
+bool
+DWARFDebugLine::DumpOpcodes(Log *log, SymbolFileDWARF* dwarf2Data, dw_offset_t debug_line_offset, uint32_t dump_flags)
+{
+    const DataExtractor& debug_line_data = dwarf2Data->get_debug_line_data();
+
+    if (debug_line_data.GetByteSize() == 0)
+    {
+        log->Printf( "< EMPTY >\n");
+        return false;
+    }
+
+    if (debug_line_offset == DW_INVALID_OFFSET)
+    {
+        // Dump line table to a single file only
+        debug_line_offset = 0;
+        while (debug_line_data.ValidOffset(debug_line_offset))
+            debug_line_offset = DumpStatementOpcodes (log, debug_line_data, debug_line_offset, dump_flags);
+    }
+    else
+    {
+        // Dump line table to a single file only
+        DumpStatementOpcodes (log, debug_line_data, debug_line_offset, dump_flags);
+    }
+    return false;
+}
+
+//----------------------------------------------------------------------
+// DumpStatementOpcodes
+//----------------------------------------------------------------------
+dw_offset_t
+DWARFDebugLine::DumpStatementOpcodes(Log *log, const DataExtractor& debug_line_data, const dw_offset_t debug_line_offset, uint32_t flags)
+{
+    uint32_t offset = debug_line_offset;
+    if (debug_line_data.ValidOffset(offset))
+    {
+        Prologue prologue;
+
+        if (ParsePrologue(debug_line_data, &offset, &prologue))
+        {
+            log->PutCString ("----------------------------------------------------------------------");
+            log->Printf     ("debug_line[0x%8.8x]", debug_line_offset);
+            log->PutCString ("----------------------------------------------------------------------\n");
+            prologue.Dump (log);
+        }
+        else
+        {
+            offset = debug_line_offset;
+            log->Printf( "0x%8.8x: skipping pad byte %2.2x", offset, debug_line_data.GetU8(&offset));
+            return offset;
+        }
+
+        Row row(prologue.default_is_stmt);
+        const dw_offset_t end_offset = debug_line_offset + prologue.total_length + sizeof(prologue.total_length);
+
+        assert(debug_line_data.ValidOffset(end_offset-1));
+
+        while (offset < end_offset)
+        {
+            const uint32_t op_offset = offset;
+            uint8_t opcode = debug_line_data.GetU8(&offset);
+            switch (opcode)
+            {
+            case 0: // Extended Opcodes always start with a zero opcode followed by
+                {   // a uleb128 length so you can skip ones you don't know about
+
+                    dw_offset_t ext_offset = offset;
+                    dw_uleb128_t len = debug_line_data.GetULEB128(&offset);
+                    dw_offset_t arg_size = len - (offset - ext_offset);
+                    uint8_t sub_opcode = debug_line_data.GetU8(&offset);
+//                    if (verbose)
+//                        log->Printf( "Extended: <%u> %2.2x ", len, sub_opcode);
+
+                    switch (sub_opcode)
+                    {
+                    case DW_LNE_end_sequence    :
+                        log->Printf( "0x%8.8x: DW_LNE_end_sequence", op_offset);
+                        row.Dump(log);
+                        row.Reset(prologue.default_is_stmt);
+                        break;
+
+                    case DW_LNE_set_address     :
+                        {
+                            row.address = debug_line_data.GetMaxU64(&offset, arg_size);
+                            log->Printf( "0x%8.8x: DW_LNE_set_address (0x%llx)", op_offset, row.address);
+                        }
+                        break;
+
+                    case DW_LNE_define_file:
+                        {
+                            FileNameEntry fileEntry;
+                            fileEntry.name      = debug_line_data.GetCStr(&offset);
+                            fileEntry.dir_idx   = debug_line_data.GetULEB128(&offset);
+                            fileEntry.mod_time  = debug_line_data.GetULEB128(&offset);
+                            fileEntry.length    = debug_line_data.GetULEB128(&offset);
+                            log->Printf( "0x%8.8x: DW_LNE_define_file('%s', dir=%i, mod_time=0x%8.8x, length=%i )",
+                                    op_offset,
+                                    fileEntry.name.c_str(),
+                                    fileEntry.dir_idx,
+                                    fileEntry.mod_time,
+                                    fileEntry.length);
+                            prologue.file_names.push_back(fileEntry);
+                        }
+                        break;
+
+                    default:
+                        log->Printf( "0x%8.8x: DW_LNE_??? (%2.2x) - Skipping unknown upcode", op_offset, opcode);
+                        // Length doesn't include the zero opcode byte or the length itself, but
+                        // it does include the sub_opcode, so we have to adjust for that below
+                        offset += arg_size;
+                        break;
+                    }
+                }
+                break;
+
+            // Standard Opcodes
+            case DW_LNS_copy:
+                log->Printf( "0x%8.8x: DW_LNS_copy", op_offset);
+                row.Dump (log);
+                break;
+
+            case DW_LNS_advance_pc:
+                {
+                    dw_uleb128_t addr_offset_n = debug_line_data.GetULEB128(&offset);
+                    dw_uleb128_t addr_offset = addr_offset_n * prologue.min_inst_length;
+                    log->Printf( "0x%8.8x: DW_LNS_advance_pc (0x%llx)", op_offset, addr_offset);
+                    row.address += addr_offset;
+                }
+                break;
+
+            case DW_LNS_advance_line:
+                {
+                    dw_sleb128_t line_offset = debug_line_data.GetSLEB128(&offset);
+                    log->Printf( "0x%8.8x: DW_LNS_advance_line (%i)", op_offset, line_offset);
+                    row.line += line_offset;
+                }
+                break;
+
+            case DW_LNS_set_file:
+                row.file = debug_line_data.GetULEB128(&offset);
+                log->Printf( "0x%8.8x: DW_LNS_set_file (%u)", op_offset, row.file);
+                break;
+
+            case DW_LNS_set_column:
+                row.column = debug_line_data.GetULEB128(&offset);
+                log->Printf( "0x%8.8x: DW_LNS_set_column (%u)", op_offset, row.column);
+                break;
+
+            case DW_LNS_negate_stmt:
+                row.is_stmt = !row.is_stmt;
+                log->Printf( "0x%8.8x: DW_LNS_negate_stmt", op_offset);
+                break;
+
+            case DW_LNS_set_basic_block:
+                row.basic_block = true;
+                log->Printf( "0x%8.8x: DW_LNS_set_basic_block", op_offset);
+                break;
+
+            case DW_LNS_const_add_pc:
+                {
+                    uint8_t adjust_opcode = 255 - prologue.opcode_base;
+                    dw_addr_t addr_offset = (adjust_opcode / prologue.line_range) * prologue.min_inst_length;
+                    log->Printf( "0x%8.8x: DW_LNS_const_add_pc (0x%8.8llx)", op_offset, addr_offset);
+                    row.address += addr_offset;
+                }
+                break;
+
+            case DW_LNS_fixed_advance_pc:
+                {
+                    uint16_t pc_offset = debug_line_data.GetU16(&offset);
+                    log->Printf( "0x%8.8x: DW_LNS_fixed_advance_pc (0x%4.4x)", op_offset, pc_offset);
+                    row.address += pc_offset;
+                }
+                break;
+
+            case DW_LNS_set_prologue_end:
+                row.prologue_end = true;
+                log->Printf( "0x%8.8x: DW_LNS_set_prologue_end", op_offset);
+                break;
+
+            case DW_LNS_set_epilogue_begin:
+                row.epilogue_begin = true;
+                log->Printf( "0x%8.8x: DW_LNS_set_epilogue_begin", op_offset);
+                break;
+
+            case DW_LNS_set_isa:
+                row.isa = debug_line_data.GetULEB128(&offset);
+                log->Printf( "0x%8.8x: DW_LNS_set_isa (%u)", op_offset, row.isa);
+                break;
+
+            // Special Opcodes
+            default:
+                if (opcode < prologue.opcode_base)
+                {
+                    // We have an opcode that this parser doesn't know about, skip
+                    // the number of ULEB128 numbers that is says to skip in the
+                    // prologue's standard_opcode_lengths array
+                    uint8_t n = prologue.standard_opcode_lengths[opcode-1];
+                    log->Printf( "0x%8.8x: Special : Unknown skipping %u ULEB128 values.", op_offset, n);
+                    while (n > 0)
+                    {
+                        debug_line_data.GetULEB128(&offset);
+                        --n;
+                    }
+                }
+                else
+                {
+                    uint8_t adjust_opcode = opcode - prologue.opcode_base;
+                    dw_addr_t addr_offset = (adjust_opcode / prologue.line_range) * prologue.min_inst_length;
+                    int32_t line_offset = prologue.line_base + (adjust_opcode % prologue.line_range);
+                    log->Printf("0x%8.8x: address += 0x%llx,  line += %i\n", op_offset, (uint64_t)addr_offset, line_offset);
+                    row.address += addr_offset;
+                    row.line += line_offset;
+                    row.Dump (log);
+                }
+                break;
+            }
+        }
+        return end_offset;
+    }
+    return DW_INVALID_OFFSET;
+}
+
+
+
+
+//----------------------------------------------------------------------
+// Parse
+//
+// Parse the entire line table contents calling callback each time a
+// new prologue is parsed and every time a new row is to be added to
+// the line table.
+//----------------------------------------------------------------------
+void
+DWARFDebugLine::Parse(const DataExtractor& debug_line_data, DWARFDebugLine::State::Callback callback, void* userData)
+{
+    uint32_t offset = 0;
+    if (debug_line_data.ValidOffset(offset))
+    {
+        if (!ParseStatementTable(debug_line_data, &offset, callback, userData))
+            ++offset;   // Skip to next byte in .debug_line section
+    }
+}
+
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::ParsePrologue
+//----------------------------------------------------------------------
+bool
+DWARFDebugLine::ParsePrologue(const DataExtractor& debug_line_data, dw_offset_t* offset_ptr, Prologue* prologue)
+{
+//  const uint32_t prologue_offset = *offset_ptr;
+
+    //DEBUG_PRINTF("0x%8.8x: ParsePrologue()\n", *offset_ptr);
+
+    prologue->Clear();
+    uint32_t i;
+    const char * s;
+    prologue->total_length      = debug_line_data.GetU32(offset_ptr);
+    prologue->version           = debug_line_data.GetU16(offset_ptr);
+    if (prologue->version != 2)
+      return false;
+
+    prologue->prologue_length   = debug_line_data.GetU32(offset_ptr);
+    const dw_offset_t end_prologue_offset = prologue->prologue_length + *offset_ptr;
+    prologue->min_inst_length   = debug_line_data.GetU8(offset_ptr);
+    prologue->default_is_stmt   = debug_line_data.GetU8(offset_ptr);
+    prologue->line_base         = debug_line_data.GetU8(offset_ptr);
+    prologue->line_range        = debug_line_data.GetU8(offset_ptr);
+    prologue->opcode_base       = debug_line_data.GetU8(offset_ptr);
+
+    prologue->standard_opcode_lengths.reserve(prologue->opcode_base-1);
+
+    for (i=1; i<prologue->opcode_base; ++i)
+    {
+        uint8_t op_len = debug_line_data.GetU8(offset_ptr);
+        prologue->standard_opcode_lengths.push_back(op_len);
+    }
+
+    while (*offset_ptr < end_prologue_offset)
+    {
+        s = debug_line_data.GetCStr(offset_ptr);
+        if (s && s[0])
+            prologue->include_directories.push_back(s);
+        else
+            break;
+    }
+
+    while (*offset_ptr < end_prologue_offset)
+    {
+        const char* name = debug_line_data.GetCStr( offset_ptr );
+        if (name && name[0])
+        {
+            FileNameEntry fileEntry;
+            fileEntry.name      = name;
+            fileEntry.dir_idx   = debug_line_data.GetULEB128( offset_ptr );
+            fileEntry.mod_time  = debug_line_data.GetULEB128( offset_ptr );
+            fileEntry.length    = debug_line_data.GetULEB128( offset_ptr );
+            prologue->file_names.push_back(fileEntry);
+        }
+        else
+            break;
+    }
+
+    assert(*offset_ptr == end_prologue_offset);
+    return end_prologue_offset;
+}
+
+bool
+DWARFDebugLine::ParseSupportFiles(const DataExtractor& debug_line_data, const char *cu_comp_dir, dw_offset_t stmt_list, FileSpecList &support_files)
+{
+    uint32_t offset = stmt_list + 4;    // Skip the total length
+    const char * s;
+    uint32_t version = debug_line_data.GetU16(&offset);
+    if (version != 2)
+      return false;
+
+    const dw_offset_t end_prologue_offset = debug_line_data.GetU32(&offset) + offset;
+    // Skip instruction length, default is stmt, line base, line range and
+    // opcode base, and all opcode lengths
+    offset += 4;
+    const uint8_t opcode_base = debug_line_data.GetU8(&offset);
+    offset += opcode_base - 1;
+    std::vector<std::string> include_directories;
+    include_directories.push_back("");  // Directory at index zero doesn't exist
+    while (offset < end_prologue_offset)
+    {
+        s = debug_line_data.GetCStr(&offset);
+        if (s && s[0])
+            include_directories.push_back(s);
+        else
+            break;
+    }
+    std::string fullpath;
+    while (offset < end_prologue_offset)
+    {
+        const char* path = debug_line_data.GetCStr( &offset );
+        if (path && path[0])
+        {
+            uint32_t dir_idx    = debug_line_data.GetULEB128( &offset );
+            debug_line_data.Skip_LEB128(&offset); // Skip mod_time
+            debug_line_data.Skip_LEB128(&offset); // Skip length
+
+            if (path[0] == '/')
+            {
+                // The path starts with a directory delimiter, so we are done.
+                fullpath = path;
+            }
+            else
+            {
+                if (dir_idx > 0 && dir_idx < include_directories.size())
+                {
+                    if (cu_comp_dir && include_directories[dir_idx][0] != '/')
+                    {
+                        fullpath = cu_comp_dir;
+
+                        if (*fullpath.rbegin() != '/')
+                            fullpath += '/';
+                        fullpath += include_directories[dir_idx];
+
+                    }
+                    else
+                        fullpath = include_directories[dir_idx];
+                }
+                else if (cu_comp_dir && cu_comp_dir[0])
+                {
+                    fullpath = cu_comp_dir;
+                }
+
+                if (!fullpath.empty())
+                {
+                   if (*fullpath.rbegin() != '/')
+                        fullpath += '/';
+                }
+                fullpath += path;
+            }
+            FileSpec file_spec(fullpath.c_str());
+            support_files.Append(file_spec);
+        }
+    }
+
+    assert(offset == end_prologue_offset);
+    return end_prologue_offset;
+}
+
+//----------------------------------------------------------------------
+// ParseStatementTable
+//
+// Parse a single line table (prologue and all rows) and call the
+// callback function once for the prologue (row in state will be zero)
+// and each time a row is to be added to the line table.
+//----------------------------------------------------------------------
+bool
+DWARFDebugLine::ParseStatementTable
+(
+    const DataExtractor& debug_line_data,
+    dw_offset_t* offset_ptr,
+    DWARFDebugLine::State::Callback callback,
+    void* userData
+)
+{
+    Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_LINE);
+    Prologue::shared_ptr prologue(new Prologue());
+
+
+    const dw_offset_t debug_line_offset = *offset_ptr;
+
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "DWARFDebugLine::ParseStatementTable (.debug_line[0x%8.8x])",
+                        debug_line_offset);
+
+    if (!ParsePrologue(debug_line_data, offset_ptr, prologue.get()))
+    {
+        if (log)
+            log->Error ("failed to parse DWARF line table prologue");
+        // Restore our offset and return false to indicate failure!
+        *offset_ptr = debug_line_offset;
+        return false;
+    }
+
+    if (log)
+        prologue->Dump (log);
+
+    const dw_offset_t end_offset = debug_line_offset + prologue->total_length + sizeof(prologue->total_length);
+
+    assert(debug_line_data.ValidOffset(end_offset-1));
+
+    State state(prologue, log, callback, userData);
+
+    while (*offset_ptr < end_offset)
+    {
+        //DEBUG_PRINTF("0x%8.8x: ", *offset_ptr);
+        uint8_t opcode = debug_line_data.GetU8(offset_ptr);
+
+        if (opcode == 0)
+        {
+            // Extended Opcodes always start with a zero opcode followed by
+            // a uleb128 length so you can skip ones you don't know about
+            dw_offset_t ext_offset = *offset_ptr;
+            dw_uleb128_t len = debug_line_data.GetULEB128(offset_ptr);
+            dw_offset_t arg_size = len - (*offset_ptr - ext_offset);
+
+            //DEBUG_PRINTF("Extended: <%2u> ", len);
+            uint8_t sub_opcode = debug_line_data.GetU8(offset_ptr);
+            switch (sub_opcode)
+            {
+            case DW_LNE_end_sequence:
+                // Set the end_sequence register of the state machine to true and
+                // append a row to the matrix using the current values of the
+                // state-machine registers. Then reset the registers to the initial
+                // values specified above. Every statement program sequence must end
+                // with a DW_LNE_end_sequence instruction which creates a row whose
+                // address is that of the byte after the last target machine instruction
+                // of the sequence.
+                state.end_sequence = true;
+                state.AppendRowToMatrix(*offset_ptr);
+                state.Reset();
+                break;
+
+            case DW_LNE_set_address:
+                // Takes a single relocatable address as an operand. The size of the
+                // operand is the size appropriate to hold an address on the target
+                // machine. Set the address register to the value given by the
+                // relocatable address. All of the other statement program opcodes
+                // that affect the address register add a delta to it. This instruction
+                // stores a relocatable value into it instead.
+                state.address = debug_line_data.GetAddress(offset_ptr);
+                break;
+
+            case DW_LNE_define_file:
+                // Takes 4 arguments. The first is a null terminated string containing
+                // a source file name. The second is an unsigned LEB128 number representing
+                // the directory index of the directory in which the file was found. The
+                // third is an unsigned LEB128 number representing the time of last
+                // modification of the file. The fourth is an unsigned LEB128 number
+                // representing the length in bytes of the file. The time and length
+                // fields may contain LEB128(0) if the information is not available.
+                //
+                // The directory index represents an entry in the include_directories
+                // section of the statement program prologue. The index is LEB128(0)
+                // if the file was found in the current directory of the compilation,
+                // LEB128(1) if it was found in the first directory in the
+                // include_directories section, and so on. The directory index is
+                // ignored for file names that represent full path names.
+                //
+                // The files are numbered, starting at 1, in the order in which they
+                // appear; the names in the prologue come before names defined by
+                // the DW_LNE_define_file instruction. These numbers are used in the
+                // the file register of the state machine.
+                {
+                    FileNameEntry fileEntry;
+                    fileEntry.name      = debug_line_data.GetCStr(offset_ptr);
+                    fileEntry.dir_idx   = debug_line_data.GetULEB128(offset_ptr);
+                    fileEntry.mod_time  = debug_line_data.GetULEB128(offset_ptr);
+                    fileEntry.length    = debug_line_data.GetULEB128(offset_ptr);
+                    state.prologue->file_names.push_back(fileEntry);
+                }
+                break;
+
+            default:
+                // Length doesn't include the zero opcode byte or the length itself, but
+                // it does include the sub_opcode, so we have to adjust for that below
+                (*offset_ptr) += arg_size;
+                break;
+            }
+        }
+        else if (opcode < prologue->opcode_base)
+        {
+            switch (opcode)
+            {
+            // Standard Opcodes
+            case DW_LNS_copy:
+                // Takes no arguments. Append a row to the matrix using the
+                // current values of the state-machine registers. Then set
+                // the basic_block register to false.
+                state.AppendRowToMatrix(*offset_ptr);
+                break;
+
+            case DW_LNS_advance_pc:
+                // Takes a single unsigned LEB128 operand, multiplies it by the
+                // min_inst_length field of the prologue, and adds the
+                // result to the address register of the state machine.
+                state.address += debug_line_data.GetULEB128(offset_ptr) * prologue->min_inst_length;
+                break;
+
+            case DW_LNS_advance_line:
+                // Takes a single signed LEB128 operand and adds that value to
+                // the line register of the state machine.
+                state.line += debug_line_data.GetSLEB128(offset_ptr);
+                break;
+
+            case DW_LNS_set_file:
+                // Takes a single unsigned LEB128 operand and stores it in the file
+                // register of the state machine.
+                state.file = debug_line_data.GetULEB128(offset_ptr);
+                break;
+
+            case DW_LNS_set_column:
+                // Takes a single unsigned LEB128 operand and stores it in the
+                // column register of the state machine.
+                state.column = debug_line_data.GetULEB128(offset_ptr);
+                break;
+
+            case DW_LNS_negate_stmt:
+                // Takes no arguments. Set the is_stmt register of the state
+                // machine to the logical negation of its current value.
+                state.is_stmt = !state.is_stmt;
+                break;
+
+            case DW_LNS_set_basic_block:
+                // Takes no arguments. Set the basic_block register of the
+                // state machine to true
+                state.basic_block = true;
+                break;
+
+            case DW_LNS_const_add_pc:
+                // Takes no arguments. Add to the address register of the state
+                // machine the address increment value corresponding to special
+                // opcode 255. The motivation for DW_LNS_const_add_pc is this:
+                // when the statement program needs to advance the address by a
+                // small amount, it can use a single special opcode, which occupies
+                // a single byte. When it needs to advance the address by up to
+                // twice the range of the last special opcode, it can use
+                // DW_LNS_const_add_pc followed by a special opcode, for a total
+                // of two bytes. Only if it needs to advance the address by more
+                // than twice that range will it need to use both DW_LNS_advance_pc
+                // and a special opcode, requiring three or more bytes.
+                {
+                    uint8_t adjust_opcode = 255 - prologue->opcode_base;
+                    dw_addr_t addr_offset = (adjust_opcode / prologue->line_range) * prologue->min_inst_length;
+                    state.address += addr_offset;
+                }
+                break;
+
+            case DW_LNS_fixed_advance_pc:
+                // Takes a single uhalf operand. Add to the address register of
+                // the state machine the value of the (unencoded) operand. This
+                // is the only extended opcode that takes an argument that is not
+                // a variable length number. The motivation for DW_LNS_fixed_advance_pc
+                // is this: existing assemblers cannot emit DW_LNS_advance_pc or
+                // special opcodes because they cannot encode LEB128 numbers or
+                // judge when the computation of a special opcode overflows and
+                // requires the use of DW_LNS_advance_pc. Such assemblers, however,
+                // can use DW_LNS_fixed_advance_pc instead, sacrificing compression.
+                state.address += debug_line_data.GetU16(offset_ptr);
+                break;
+
+            case DW_LNS_set_prologue_end:
+                // Takes no arguments. Set the prologue_end register of the
+                // state machine to true
+                state.prologue_end = true;
+                break;
+
+            case DW_LNS_set_epilogue_begin:
+                // Takes no arguments. Set the basic_block register of the
+                // state machine to true
+                state.epilogue_begin = true;
+                break;
+
+            case DW_LNS_set_isa:
+                // Takes a single unsigned LEB128 operand and stores it in the
+                // column register of the state machine.
+                state.isa = debug_line_data.GetULEB128(offset_ptr);
+                break;
+
+            default:
+                // Handle any unknown standard opcodes here. We know the lengths
+                // of such opcodes because they are specified in the prologue
+                // as a multiple of LEB128 operands for each opcode.
+                {
+                    uint8_t i;
+                    assert (opcode - 1 < prologue->standard_opcode_lengths.size());
+                    const uint8_t opcode_length = prologue->standard_opcode_lengths[opcode - 1];
+                    for (i=0; i<opcode_length; ++i)
+                        debug_line_data.Skip_LEB128(offset_ptr);
+                }
+                break;
+            }
+        }
+        else
+        {
+            // Special Opcodes
+
+            // A special opcode value is chosen based on the amount that needs
+            // to be added to the line and address registers. The maximum line
+            // increment for a special opcode is the value of the line_base
+            // field in the header, plus the value of the line_range field,
+            // minus 1 (line base + line range - 1). If the desired line
+            // increment is greater than the maximum line increment, a standard
+            // opcode must be used instead of a special opcode. The “address
+            // advance” is calculated by dividing the desired address increment
+            // by the minimum_instruction_length field from the header. The
+            // special opcode is then calculated using the following formula:
+            //
+            //  opcode = (desired line increment - line_base) + (line_range * address advance) + opcode_base
+            //
+            // If the resulting opcode is greater than 255, a standard opcode
+            // must be used instead.
+            //
+            // To decode a special opcode, subtract the opcode_base from the
+            // opcode itself to give the adjusted opcode. The amount to
+            // increment the address register is the result of the adjusted
+            // opcode divided by the line_range multiplied by the
+            // minimum_instruction_length field from the header. That is:
+            //
+            //  address increment = (adjusted opcode / line_range) * minimim_instruction_length
+            //
+            // The amount to increment the line register is the line_base plus
+            // the result of the adjusted opcode modulo the line_range. That is:
+            //
+            // line increment = line_base + (adjusted opcode % line_range)
+
+            uint8_t adjust_opcode = opcode - prologue->opcode_base;
+            dw_addr_t addr_offset = (adjust_opcode / prologue->line_range) * prologue->min_inst_length;
+            int32_t line_offset = prologue->line_base + (adjust_opcode % prologue->line_range);
+            state.line += line_offset;
+            state.address += addr_offset;
+            state.AppendRowToMatrix(*offset_ptr);
+        }
+    }
+
+    state.Finalize( *offset_ptr );
+
+    return end_offset;
+}
+
+
+//----------------------------------------------------------------------
+// ParseStatementTableCallback
+//----------------------------------------------------------------------
+static void
+ParseStatementTableCallback(dw_offset_t offset, const DWARFDebugLine::State& state, void* userData)
+{
+    DWARFDebugLine::LineTable* line_table = (DWARFDebugLine::LineTable*)userData;
+    if (state.row == DWARFDebugLine::State::StartParsingLineTable)
+    {
+        // Just started parsing the line table, so lets keep a reference to
+        // the prologue using the supplied shared pointer
+        line_table->prologue = state.prologue;
+    }
+    else if (state.row == DWARFDebugLine::State::DoneParsingLineTable)
+    {
+        // Done parsing line table, nothing to do for the cleanup
+    }
+    else
+    {
+        // We have a new row, lets append it
+        line_table->AppendRow(state);
+    }
+}
+
+//----------------------------------------------------------------------
+// ParseStatementTable
+//
+// Parse a line table at offset and populate the LineTable class with
+// the prologue and all rows.
+//----------------------------------------------------------------------
+bool
+DWARFDebugLine::ParseStatementTable(const DataExtractor& debug_line_data, uint32_t* offset_ptr, LineTable* line_table)
+{
+    return ParseStatementTable(debug_line_data, offset_ptr, ParseStatementTableCallback, line_table);
+}
+
+
+inline bool
+DWARFDebugLine::Prologue::IsValid() const
+{
+    return SymbolFileDWARF::SupportedVersion(version);
+}
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::Prologue::Dump
+//----------------------------------------------------------------------
+void
+DWARFDebugLine::Prologue::Dump(Log *log)
+{
+    uint32_t i;
+
+    log->Printf( "Line table prologue:");
+    log->Printf( "   total_length: 0x%8.8x", total_length);
+    log->Printf( "        version: %u", version);
+    log->Printf( "prologue_length: 0x%8.8x", prologue_length);
+    log->Printf( "min_inst_length: %u", min_inst_length);
+    log->Printf( "default_is_stmt: %u", default_is_stmt);
+    log->Printf( "      line_base: %i", line_base);
+    log->Printf( "     line_range: %u", line_range);
+    log->Printf( "    opcode_base: %u", opcode_base);
+
+    for (i=0; i<standard_opcode_lengths.size(); ++i)
+    {
+        log->Printf( "standard_opcode_lengths[%s] = %u", DW_LNS_value_to_name(i+1), standard_opcode_lengths[i]);
+    }
+
+    if (!include_directories.empty())
+    {
+        for (i=0; i<include_directories.size(); ++i)
+        {
+            log->Printf( "include_directories[%3u] = '%s'", i+1, include_directories[i].c_str());
+        }
+    }
+
+    if (!file_names.empty())
+    {
+        log->PutCString ("                Dir  Mod Time   File Len   File Name");
+        log->PutCString ("                ---- ---------- ---------- ---------------------------");
+        for (i=0; i<file_names.size(); ++i)
+        {
+            const FileNameEntry& fileEntry = file_names[i];
+            log->Printf ("file_names[%3u] %4u 0x%8.8x 0x%8.8x %s",
+                i+1,
+                fileEntry.dir_idx,
+                fileEntry.mod_time,
+                fileEntry.length,
+                fileEntry.name.c_str());
+        }
+    }
+}
+
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::ParsePrologue::Append
+//
+// Append the contents of the prologue to the binary stream buffer
+//----------------------------------------------------------------------
+//void
+//DWARFDebugLine::Prologue::Append(BinaryStreamBuf& buff) const
+//{
+//  uint32_t i;
+//
+//  buff.Append32(total_length);
+//  buff.Append16(version);
+//  buff.Append32(prologue_length);
+//  buff.Append8(min_inst_length);
+//  buff.Append8(default_is_stmt);
+//  buff.Append8(line_base);
+//  buff.Append8(line_range);
+//  buff.Append8(opcode_base);
+//
+//  for (i=0; i<standard_opcode_lengths.size(); ++i)
+//      buff.Append8(standard_opcode_lengths[i]);
+//
+//  for (i=0; i<include_directories.size(); ++i)
+//      buff.AppendCStr(include_directories[i].c_str());
+//  buff.Append8(0);    // Terminate the include directory section with empty string
+//
+//  for (i=0; i<file_names.size(); ++i)
+//  {
+//      buff.AppendCStr(file_names[i].name.c_str());
+//      buff.Append32_as_ULEB128(file_names[i].dir_idx);
+//      buff.Append32_as_ULEB128(file_names[i].mod_time);
+//      buff.Append32_as_ULEB128(file_names[i].length);
+//  }
+//  buff.Append8(0);    // Terminate the file names section with empty string
+//}
+
+
+bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx, std::string& path, std::string& directory) const
+{
+    uint32_t idx = file_idx - 1;    // File indexes are 1 based...
+    if (idx < file_names.size())
+    {
+        path = file_names[idx].name;
+        uint32_t dir_idx = file_names[idx].dir_idx - 1;
+        if (dir_idx < include_directories.size())
+            directory = include_directories[dir_idx];
+        else
+            directory.clear();
+        return true;
+    }
+    return false;
+}
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::LineTable::Dump
+//----------------------------------------------------------------------
+void
+DWARFDebugLine::LineTable::Dump(Log *log) const
+{
+    if (prologue.get())
+        prologue->Dump (log);
+
+    if (!rows.empty())
+    {
+        log->PutCString ("Address            Line   Column File   ISA Flags");
+        log->PutCString ("------------------ ------ ------ ------ --- -------------");
+        Row::const_iterator pos = rows.begin();
+        Row::const_iterator end = rows.end();
+        while (pos != end)
+        {
+            (*pos).Dump (log);
+            ++pos;
+        }
+    }
+}
+
+
+void
+DWARFDebugLine::LineTable::AppendRow(const DWARFDebugLine::Row& state)
+{
+    rows.push_back(state);
+}
+
+
+
+//----------------------------------------------------------------------
+// Compare function for the binary search in DWARFDebugLine::LineTable::LookupAddress()
+//----------------------------------------------------------------------
+static bool FindMatchingAddress (const DWARFDebugLine::Row& row1, const DWARFDebugLine::Row& row2)
+{
+    return row1.address < row2.address;
+}
+
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::LineTable::LookupAddress
+//----------------------------------------------------------------------
+uint32_t
+DWARFDebugLine::LineTable::LookupAddress(dw_addr_t address, dw_addr_t cu_high_pc) const
+{
+    uint32_t index = UINT_MAX;
+    if (!rows.empty())
+    {
+        // Use the lower_bound algorithm to perform a binary search since we know
+        // that our line table data is ordered by address.
+        DWARFDebugLine::Row row;
+        row.address = address;
+        Row::const_iterator begin_pos = rows.begin();
+        Row::const_iterator end_pos = rows.end();
+        Row::const_iterator pos = lower_bound(begin_pos, end_pos, row, FindMatchingAddress);
+        if (pos == end_pos)
+        {
+            if (address < cu_high_pc)
+                return rows.size()-1;
+        }
+        else
+        {
+            // Rely on fact that we are using a std::vector and we can do
+            // pointer arithmetic to find the row index (which will be one less
+            // that what we found since it will find the first position after
+            // the current address) since std::vector iterators are just
+            // pointers to the container type.
+            index = pos - begin_pos;
+            if (pos->address > address)
+            {
+                if (index > 0)
+                    --index;
+                else
+                    index = UINT_MAX;
+            }
+        }
+    }
+    return index;   // Failed to find address
+}
+
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::Row::Row
+//----------------------------------------------------------------------
+DWARFDebugLine::Row::Row(bool default_is_stmt) :
+    address(0),
+    line(1),
+    column(0),
+    file(1),
+    is_stmt(default_is_stmt),
+    basic_block(false),
+    end_sequence(false),
+    prologue_end(false),
+    epilogue_begin(false),
+    isa(0)
+{
+}
+
+//----------------------------------------------------------------------
+// Called after a row is appended to the matrix
+//----------------------------------------------------------------------
+void
+DWARFDebugLine::Row::PostAppend()
+{
+    basic_block = false;
+    prologue_end = false;
+    epilogue_begin = false;
+}
+
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::Row::Reset
+//----------------------------------------------------------------------
+void
+DWARFDebugLine::Row::Reset(bool default_is_stmt)
+{
+    address = 0;
+    line = 1;
+    column = 0;
+    file = 1;
+    is_stmt = default_is_stmt;
+    basic_block = false;
+    end_sequence = false;
+    prologue_end = false;
+    epilogue_begin = false;
+    isa = 0;
+}
+//----------------------------------------------------------------------
+// DWARFDebugLine::Row::Dump
+//----------------------------------------------------------------------
+void
+DWARFDebugLine::Row::Dump(Log *log) const
+{
+    log->Printf( "0x%16.16llx %6u %6u %6u %3u %s%s%s%s%s",
+                address,
+                line,
+                column,
+                file,
+                isa,
+                is_stmt ? " is_stmt" : "",
+                basic_block ? " basic_block" : "",
+                prologue_end ? " prologue_end" : "",
+                epilogue_begin ? " epilogue_begin" : "",
+                end_sequence ? " end_sequence" : "");
+}
+
+//----------------------------------------------------------------------
+// Compare function LineTable structures
+//----------------------------------------------------------------------
+static bool AddressLessThan (const DWARFDebugLine::Row& a, const DWARFDebugLine::Row& b)
+{
+    return a.address < b.address;
+}
+
+
+
+// Insert a row at the correct address if the addresses can be out of
+// order which can only happen when we are linking a line table that
+// may have had it's contents rearranged.
+void
+DWARFDebugLine::Row::Insert(Row::collection& state_coll, const Row& state)
+{
+    // If we don't have anything yet, or if the address of the last state in our
+    // line table is less than the current one, just append the current state
+    if (state_coll.empty() || AddressLessThan(state_coll.back(), state))
+    {
+        state_coll.push_back(state);
+    }
+    else
+    {
+        // Do a binary search for the correct entry
+        pair<Row::iterator, Row::iterator> range(equal_range(state_coll.begin(), state_coll.end(), state, AddressLessThan));
+
+        // If the addresses are equal, we can safely replace the previous entry
+        // with the current one if the one it is replacing is an end_sequence entry.
+        // We currently always place an extra end sequence when ever we exit a valid
+        // address range for a function in case the functions get rearranged by
+        // optmimizations or by order specifications. These extra end sequences will
+        // disappear by getting replaced with valid consecutive entries within a
+        // compile unit if there are no gaps.
+        if (range.first == range.second)
+        {
+            state_coll.insert(range.first, state);
+        }
+        else
+        {
+            if ((distance(range.first, range.second) == 1) && range.first->end_sequence == true)
+            {
+                *range.first = state;
+            }
+            else
+            {
+                state_coll.insert(range.second, state);
+            }
+        }
+    }
+}
+
+void
+DWARFDebugLine::Row::Dump(Log *log, const Row::collection& state_coll)
+{
+    std::for_each (state_coll.begin(), state_coll.end(), bind2nd(std::mem_fun_ref(&Row::Dump),log));
+}
+
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::State::State
+//----------------------------------------------------------------------
+DWARFDebugLine::State::State(Prologue::shared_ptr& p, Log *l, DWARFDebugLine::State::Callback cb, void* userData) :
+    Row (p->default_is_stmt),
+    prologue (p),
+    log (l),
+    callback (cb),
+    callbackUserData (userData),
+    row (StartParsingLineTable)
+{
+    // Call the callback with the initial row state of zero for the prologue
+    if (callback)
+        callback(0, *this, callbackUserData);
+}
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::State::Reset
+//----------------------------------------------------------------------
+void
+DWARFDebugLine::State::Reset()
+{
+    Row::Reset(prologue->default_is_stmt);
+}
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::State::AppendRowToMatrix
+//----------------------------------------------------------------------
+void
+DWARFDebugLine::State::AppendRowToMatrix(dw_offset_t offset)
+{
+    // Each time we are to add an entry into the line table matrix
+    // call the callback funtion so that someone can do something with
+    // the current state of the state machine (like build a line table
+    // or dump the line table!)
+    if (log)
+    {
+        if (row == 0)
+        {
+            log->PutCString ("Address            Line   Column File   ISA Flags");
+            log->PutCString ("------------------ ------ ------ ------ --- -------------");
+        }
+        Dump (log);
+    }
+
+    ++row;  // Increase the row number before we call our callback for a real row
+    if (callback)
+        callback(offset, *this, callbackUserData);
+    PostAppend();
+}
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::State::Finalize
+//----------------------------------------------------------------------
+void
+DWARFDebugLine::State::Finalize(dw_offset_t offset)
+{
+    // Call the callback with a special row state when we are done parsing a
+    // line table
+    row = DoneParsingLineTable;
+    if (callback)
+        callback(offset, *this, callbackUserData);
+}
+
+//void
+//DWARFDebugLine::AppendLineTableData
+//(
+//  const DWARFDebugLine::Prologue* prologue,
+//  const DWARFDebugLine::Row::collection& state_coll,
+//  const uint32_t addr_size,
+//  BinaryStreamBuf &debug_line_data
+//)
+//{
+//  if (state_coll.empty())
+//  {
+//      // We have no entries, just make an empty line table
+//      debug_line_data.Append8(0);
+//      debug_line_data.Append8(1);
+//      debug_line_data.Append8(DW_LNE_end_sequence);
+//  }
+//  else
+//  {
+//      DWARFDebugLine::Row::const_iterator pos;
+//      Row::const_iterator end = state_coll.end();
+//      bool default_is_stmt = prologue->default_is_stmt;
+//      const DWARFDebugLine::Row reset_state(default_is_stmt);
+//      const DWARFDebugLine::Row* prev_state = &reset_state;
+//      const int32_t max_line_increment_for_special_opcode = prologue->MaxLineIncrementForSpecialOpcode();
+//      for (pos = state_coll.begin(); pos != end; ++pos)
+//      {
+//          const DWARFDebugLine::Row& curr_state = *pos;
+//          int32_t line_increment  = 0;
+//          dw_addr_t addr_offset   = curr_state.address - prev_state->address;
+//          dw_addr_t addr_advance  = (addr_offset) / prologue->min_inst_length;
+//          line_increment = (int32_t)(curr_state.line - prev_state->line);
+//
+//          // If our previous state was the reset state, then let's emit the
+//          // address to keep GDB's DWARF parser happy. If we don't start each
+//          // sequence with a DW_LNE_set_address opcode, the line table won't
+//          // get slid properly in GDB.
+//
+//          if (prev_state == &reset_state)
+//          {
+//              debug_line_data.Append8(0); // Extended opcode
+//              debug_line_data.Append32_as_ULEB128(addr_size + 1); // Length of opcode bytes
+//              debug_line_data.Append8(DW_LNE_set_address);
+//              debug_line_data.AppendMax64(curr_state.address, addr_size);
+//              addr_advance = 0;
+//          }
+//
+//          if (prev_state->file != curr_state.file)
+//          {
+//              debug_line_data.Append8(DW_LNS_set_file);
+//              debug_line_data.Append32_as_ULEB128(curr_state.file);
+//          }
+//
+//          if (prev_state->column != curr_state.column)
+//          {
+//              debug_line_data.Append8(DW_LNS_set_column);
+//              debug_line_data.Append32_as_ULEB128(curr_state.column);
+//          }
+//
+//          // Don't do anything fancy if we are at the end of a sequence
+//          // as we don't want to push any extra rows since the DW_LNE_end_sequence
+//          // will push a row itself!
+//          if (curr_state.end_sequence)
+//          {
+//              if (line_increment != 0)
+//              {
+//                  debug_line_data.Append8(DW_LNS_advance_line);
+//                  debug_line_data.Append32_as_SLEB128(line_increment);
+//              }
+//
+//              if (addr_advance > 0)
+//              {
+//                  debug_line_data.Append8(DW_LNS_advance_pc);
+//                  debug_line_data.Append32_as_ULEB128(addr_advance);
+//              }
+//
+//              // Now push the end sequence on!
+//              debug_line_data.Append8(0);
+//              debug_line_data.Append8(1);
+//              debug_line_data.Append8(DW_LNE_end_sequence);
+//
+//              prev_state = &reset_state;
+//          }
+//          else
+//          {
+//              if (line_increment || addr_advance)
+//              {
+//                  if (line_increment > max_line_increment_for_special_opcode)
+//                  {
+//                      debug_line_data.Append8(DW_LNS_advance_line);
+//                      debug_line_data.Append32_as_SLEB128(line_increment);
+//                      line_increment = 0;
+//                  }
+//
+//                  uint32_t special_opcode = (line_increment >= prologue->line_base) ? ((line_increment - prologue->line_base) + (prologue->line_range * addr_advance) + prologue->opcode_base) : 256;
+//                  if (special_opcode > 255)
+//                  {
+//                      // Both the address and line won't fit in one special opcode
+//                      // check to see if just the line advance will?
+//                      uint32_t special_opcode_line = ((line_increment >= prologue->line_base) && (line_increment != 0)) ?
+//                              ((line_increment - prologue->line_base) + prologue->opcode_base) : 256;
+//
+//
+//                      if (special_opcode_line > 255)
+//                      {
+//                          // Nope, the line advance won't fit by itself, check the address increment by itself
+//                          uint32_t special_opcode_addr = addr_advance ?
+//                              ((0 - prologue->line_base) + (prologue->line_range * addr_advance) + prologue->opcode_base) : 256;
+//
+//                          if (special_opcode_addr > 255)
+//                          {
+//                              // Neither the address nor the line will fit in a
+//                              // special opcode, we must manually enter both then
+//                              // do a DW_LNS_copy to push a row (special opcode
+//                              // automatically imply a new row is pushed)
+//                              if (line_increment != 0)
+//                              {
+//                                  debug_line_data.Append8(DW_LNS_advance_line);
+//                                  debug_line_data.Append32_as_SLEB128(line_increment);
+//                              }
+//
+//                              if (addr_advance > 0)
+//                              {
+//                                  debug_line_data.Append8(DW_LNS_advance_pc);
+//                                  debug_line_data.Append32_as_ULEB128(addr_advance);
+//                              }
+//
+//                              // Now push a row onto the line table manually
+//                              debug_line_data.Append8(DW_LNS_copy);
+//
+//                          }
+//                          else
+//                          {
+//                              // The address increment alone will fit into a special opcode
+//                              // so modify our line change, then issue a special opcode
+//                              // for the address increment and it will push a row into the
+//                              // line table
+//                              if (line_increment != 0)
+//                              {
+//                                  debug_line_data.Append8(DW_LNS_advance_line);
+//                                  debug_line_data.Append32_as_SLEB128(line_increment);
+//                              }
+//
+//                              // Advance of line and address will fit into a single byte special opcode
+//                              // and this will also push a row onto the line table
+//                              debug_line_data.Append8(special_opcode_addr);
+//                          }
+//                      }
+//                      else
+//                      {
+//                          // The line change alone will fit into a special opcode
+//                          // so modify our address increment first, then issue a
+//                          // special opcode for the line change and it will push
+//                          // a row into the line table
+//                          if (addr_advance > 0)
+//                          {
+//                              debug_line_data.Append8(DW_LNS_advance_pc);
+//                              debug_line_data.Append32_as_ULEB128(addr_advance);
+//                          }
+//
+//                          // Advance of line and address will fit into a single byte special opcode
+//                          // and this will also push a row onto the line table
+//                          debug_line_data.Append8(special_opcode_line);
+//                      }
+//                  }
+//                  else
+//                  {
+//                      // Advance of line and address will fit into a single byte special opcode
+//                      // and this will also push a row onto the line table
+//                      debug_line_data.Append8(special_opcode);
+//                  }
+//              }
+//              prev_state = &curr_state;
+//          }
+//      }
+//  }
+//}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
new file mode 100644
index 0000000..57b2f15
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
@@ -0,0 +1,225 @@
+//===-- DWARFDebugLine.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_DWARFDebugLine_h_
+#define liblldb_DWARFDebugLine_h_
+
+#include <map>
+#include <vector>
+#include <string>
+
+#include "lldb/lldb-private.h"
+
+#include "DWARFDefines.h"
+
+class SymbolFileDWARF;
+class DWARFDebugInfoEntry;
+
+//----------------------------------------------------------------------
+// DWARFDebugLine
+//----------------------------------------------------------------------
+class DWARFDebugLine
+{
+public:
+    //------------------------------------------------------------------
+    // FileNameEntry
+    //------------------------------------------------------------------
+    struct FileNameEntry
+    {
+        FileNameEntry() :
+            name(),
+            dir_idx(0),
+            mod_time(0),
+            length(0)
+        {
+        }
+
+        std::string     name;
+        dw_sleb128_t    dir_idx;
+        dw_sleb128_t    mod_time;
+        dw_sleb128_t    length;
+
+    };
+
+    //------------------------------------------------------------------
+    // Prologue
+    //------------------------------------------------------------------
+    struct Prologue
+    {
+
+        Prologue() :
+            total_length(0),
+            version(0),
+            prologue_length(0),
+            min_inst_length(0),
+            default_is_stmt(0),
+            line_base(0),
+            line_range(0),
+            opcode_base(0),
+            standard_opcode_lengths(),
+            include_directories(),
+            file_names()
+        {
+        }
+
+        typedef lldb::SharedPtr<Prologue>::Type shared_ptr;
+
+        uint32_t    total_length;   // The size in bytes of the statement information for this compilation unit (not including the total_length field itself).
+        uint16_t    version;        // Version identifier for the statement information format.
+        uint32_t    prologue_length;// The number of bytes following the prologue_length field to the beginning of the first byte of the statement program itself.
+        uint8_t     min_inst_length;// The size in bytes of the smallest target machine instruction. Statement program opcodes that alter the address register first multiply their operands by this value.
+        uint8_t     default_is_stmt;// The initial value of theis_stmtregister.
+        int8_t      line_base;      // This parameter affects the meaning of the special opcodes. See below.
+        uint8_t     line_range;     // This parameter affects the meaning of the special opcodes. See below.
+        uint8_t     opcode_base;    // The number assigned to the first special opcode.
+        std::vector<uint8_t>            standard_opcode_lengths;
+        std::vector<std::string>        include_directories;
+        std::vector<FileNameEntry>      file_names;
+
+        // Length of the prologue in bytes
+        uint32_t Length() const { return prologue_length + sizeof(total_length) + sizeof(version) + sizeof(prologue_length); }
+        // Length of the line table data in bytes (not including the prologue)
+        uint32_t StatementTableLength() const { return total_length + sizeof(total_length) - Length(); }
+        int32_t MaxLineIncrementForSpecialOpcode() const { return line_base + (int8_t)line_range - 1; };
+        bool IsValid() const;
+//      void Append(BinaryStreamBuf& buff) const;
+        void Dump (lldb_private::Log *log);
+        void Clear()
+        {
+            total_length = version = prologue_length = min_inst_length = line_base = line_range = opcode_base = 0;
+            line_base = 0;
+            standard_opcode_lengths.clear();
+            include_directories.clear();
+            file_names.clear();
+        }
+        bool GetFile(uint32_t file_idx, std::string& file, std::string& dir) const;
+
+    };
+
+    // Standard .debug_line state machine structure
+    struct Row
+    {
+        typedef std::vector<Row>            collection;
+        typedef collection::iterator        iterator;
+        typedef collection::const_iterator  const_iterator;
+
+        Row(bool default_is_stmt = false);
+        virtual ~Row() {}
+        void PostAppend ();
+        void Reset(bool default_is_stmt);
+        void Dump(lldb_private::Log *log) const;
+        static void Insert(Row::collection& state_coll, const Row& state);
+        static void Dump(lldb_private::Log *log, const Row::collection& state_coll);
+
+        dw_addr_t   address;        // The program-counter value corresponding to a machine instruction generated by the compiler.
+        uint32_t    line;           // An unsigned integer indicating a source line number. Lines are numbered beginning at 1. The compiler may emit the value 0 in cases where an instruction cannot be attributed to any source line.
+        uint16_t    column;         // An unsigned integer indicating a column number within a source line. Columns are numbered beginning at 1. The value 0 is reserved to indicate that a statement begins at the ‘‘left edge’’ of the line.
+        uint16_t    file;           // An unsigned integer indicating the identity of the source file corresponding to a machine instruction.
+        uint8_t     is_stmt:1,      // A boolean indicating that the current instruction is the beginning of a statement.
+                    basic_block:1,  // A boolean indicating that the current instruction is the beginning of a basic block.
+                    end_sequence:1, // A boolean indicating that the current address is that of the first byte after the end of a sequence of target machine instructions.
+                    prologue_end:1, // A boolean indicating that the current address is one (of possibly many) where execution should be suspended for an entry breakpoint of a function.
+                    epilogue_begin:1;// A boolean indicating that the current address is one (of possibly many) where execution should be suspended for an exit breakpoint of a function.
+        uint32_t    isa;            // An unsigned integer whose value encodes the applicable instruction set architecture for the current instruction.
+    };
+
+
+    //------------------------------------------------------------------
+    // LineTable
+    //------------------------------------------------------------------
+    struct LineTable
+    {
+        typedef lldb::SharedPtr<LineTable>::Type shared_ptr;
+
+        LineTable() :
+            prologue(),
+            rows()
+        {
+        }
+
+        void AppendRow(const DWARFDebugLine::Row& state);
+        void Clear()
+        {
+            prologue.reset();
+            rows.clear();
+        }
+
+        uint32_t LookupAddress(dw_addr_t address, dw_addr_t cu_high_pc) const;
+        void Dump(lldb_private::Log *log) const;
+
+        Prologue::shared_ptr prologue;
+        Row::collection rows;
+    };
+
+    //------------------------------------------------------------------
+    // State
+    //------------------------------------------------------------------
+    struct State : public Row
+    {
+        typedef void (*Callback)(dw_offset_t offset, const State& state, void* userData);
+
+        // Special row codes used when calling the callback
+        enum
+        {
+            StartParsingLineTable = 0,
+            DoneParsingLineTable = -1
+        };
+
+        State (Prologue::shared_ptr& prologue_sp,
+               lldb_private::Log *log,
+               Callback callback,
+               void* userData);
+
+        void
+        AppendRowToMatrix (dw_offset_t offset);
+
+        void
+        Finalize (dw_offset_t offset);
+
+        void
+        Reset ();
+
+        Prologue::shared_ptr prologue;
+        lldb_private::Log *log;
+        Callback callback; // Callback funcation that gets called each time an entry it to be added to the matrix
+        void* callbackUserData;
+        int row; // The row number that starts at zero for the prologue, and increases for each row added to the matrix
+    private:
+        DISALLOW_COPY_AND_ASSIGN (State);
+    };
+
+    static bool DumpOpcodes(lldb_private::Log *log, SymbolFileDWARF* dwarf2Data, dw_offset_t line_offset = DW_INVALID_OFFSET, uint32_t dump_flags = 0);   // If line_offset is invalid, dump everything
+    static bool DumpLineTableRows(lldb_private::Log *log, SymbolFileDWARF* dwarf2Data, dw_offset_t line_offset = DW_INVALID_OFFSET);  // If line_offset is invalid, dump everything
+    static bool ParseSupportFiles(const lldb_private::DataExtractor& debug_line_data, const char *cu_comp_dir, dw_offset_t stmt_list, lldb_private::FileSpecList &support_files);
+    static bool ParsePrologue(const lldb_private::DataExtractor& debug_line_data, dw_offset_t* offset_ptr, Prologue* prologue);
+    static bool ParseStatementTable(const lldb_private::DataExtractor& debug_line_data, dw_offset_t* offset_ptr, State::Callback callback, void* userData);
+    static dw_offset_t DumpStatementTable(lldb_private::Log *log, const lldb_private::DataExtractor& debug_line_data, const dw_offset_t line_offset);
+    static dw_offset_t DumpStatementOpcodes(lldb_private::Log *log, const lldb_private::DataExtractor& debug_line_data, const dw_offset_t line_offset, uint32_t flags);
+    static bool ParseStatementTable(const lldb_private::DataExtractor& debug_line_data, uint32_t* offset_ptr, LineTable* line_table);
+    static void Parse(const lldb_private::DataExtractor& debug_line_data, DWARFDebugLine::State::Callback callback, void* userData);
+//  static void AppendLineTableData(const DWARFDebugLine::Prologue* prologue, const DWARFDebugLine::Row::collection& state_coll, const uint32_t addr_size, BinaryStreamBuf &debug_line_data);
+
+    DWARFDebugLine() :
+        m_lineTableMap()
+    {
+    }
+
+    void Parse(const lldb_private::DataExtractor& debug_line_data);
+    void ParseIfNeeded(const lldb_private::DataExtractor& debug_line_data);
+    LineTable::shared_ptr GetLineTable(const dw_offset_t offset) const;
+
+protected:
+    typedef std::map<dw_offset_t, LineTable::shared_ptr> LineTableMap;
+    typedef LineTableMap::iterator LineTableIter;
+    typedef LineTableMap::const_iterator LineTableConstIter;
+
+    LineTableMap m_lineTableMap;
+};
+
+#endif  // liblldb_DWARFDebugLine_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.cpp
new file mode 100644
index 0000000..0501da8
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.cpp
@@ -0,0 +1,48 @@
+//===-- DWARFDebugMacinfo.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugMacinfo.h"
+
+#include "DWARFDebugMacinfoEntry.h"
+#include "SymbolFileDWARF.h"
+
+#include "lldb/Core/Stream.h"
+
+using namespace lldb_private;
+using namespace std;
+
+DWARFDebugMacinfo::DWARFDebugMacinfo()
+{
+}
+
+DWARFDebugMacinfo::~DWARFDebugMacinfo()
+{
+}
+
+void
+DWARFDebugMacinfo::Dump(Stream *s, const DataExtractor& macinfo_data, dw_offset_t offset)
+{
+    DWARFDebugMacinfoEntry maninfo_entry;
+    if (macinfo_data.GetByteSize() == 0)
+    {
+        s->PutCString("< EMPTY >\n");
+        return;
+    }
+    if (offset == DW_INVALID_OFFSET)
+    {
+        offset = 0;
+        while (maninfo_entry.Extract(macinfo_data, &offset))
+            maninfo_entry.Dump(s);
+    }
+    else
+    {
+        if (maninfo_entry.Extract(macinfo_data, &offset))
+            maninfo_entry.Dump(s);
+    }
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.h
new file mode 100644
index 0000000..e420a5b
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.h
@@ -0,0 +1,29 @@
+//===-- DWARFDebugMacinfo.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_DWARFDebugLine_h_
+#define SymbolFileDWARF_DWARFDebugLine_h_
+
+#include "SymbolFileDWARF.h"
+
+class DWARFDebugMacinfo
+{
+public:
+    DWARFDebugMacinfo();
+
+    ~DWARFDebugMacinfo();
+
+    static void
+    Dump (lldb_private::Stream *s,
+          const lldb_private::DataExtractor& macinfo_data,
+          dw_offset_t offset = DW_INVALID_OFFSET);
+};
+
+
+#endif  // SymbolFileDWARF_DWARFDebugLine_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.cpp
new file mode 100644
index 0000000..c07cec4
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.cpp
@@ -0,0 +1,132 @@
+//===-- DWARFDebugMacinfoEntry.cpp ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugMacinfoEntry.h"
+
+#include "lldb/Core/Stream.h"
+
+using namespace lldb_private;
+using namespace std;
+
+DWARFDebugMacinfoEntry::DWARFDebugMacinfoEntry() :
+    m_type_code(0),
+    m_line(0),
+    m_op2()
+{
+    m_op2.cstr = NULL;
+}
+
+DWARFDebugMacinfoEntry::~DWARFDebugMacinfoEntry()
+{
+}
+
+const char*
+DWARFDebugMacinfoEntry::GetCString() const
+{
+    switch (m_type_code)
+    {
+    case 0:
+    case DW_MACINFO_start_file:
+    case DW_MACINFO_end_file:
+        return NULL;
+    default:
+        break;
+    }
+    return m_op2.cstr;
+}
+
+
+
+void
+DWARFDebugMacinfoEntry::Dump(Stream *s) const
+{
+    if (m_type_code)
+    {
+        s->PutCString(DW_MACINFO_value_to_name(m_type_code));
+
+        switch (m_type_code)
+        {
+        case DW_MACINFO_define:
+            s->Printf(" line:%u  #define %s\n", (uint32_t)m_line, m_op2.cstr);
+            break;
+
+        case DW_MACINFO_undef:
+            s->Printf(" line:%u  #undef %s\n", (uint32_t)m_line, m_op2.cstr);
+            break;
+
+        default:
+            s->Printf(" line:%u  str: '%s'\n", (uint32_t)m_line, m_op2.cstr);
+            break;
+
+        case DW_MACINFO_start_file:
+            s->Printf(" line:%u  file index: '%s'\n", (uint32_t)m_line, (uint32_t)m_op2.file_idx);
+            break;
+
+        case DW_MACINFO_end_file:
+            break;
+        }
+    }
+    else
+    {
+        s->PutCString(" END\n");
+    }
+}
+
+
+bool
+DWARFDebugMacinfoEntry::Extract(const DataExtractor& mac_info_data, dw_offset_t* offset_ptr)
+{
+    if (mac_info_data.ValidOffset(*offset_ptr))
+    {
+        m_type_code = mac_info_data.GetU8(offset_ptr);
+
+        switch (m_type_code)
+        {
+
+        case DW_MACINFO_define:
+        case DW_MACINFO_undef:
+            // 2 operands:
+            // Arg 1: operand encodes the line number of the source line on which
+            //      the relevant defining or undefining pre-processor directives
+            //      appeared.
+            m_line  = mac_info_data.GetULEB128(offset_ptr);
+            // Arg 2: define string
+            m_op2.cstr  = mac_info_data.GetCStr(offset_ptr);
+            break;
+
+        case DW_MACINFO_start_file:
+            // 2 operands:
+            // Op 1: line number of the source line on which the inclusion
+            //      pre-processor directive occurred.
+            m_line  = mac_info_data.GetULEB128(offset_ptr);
+            // Op 2: a source file name index to a file number in the statement
+            //      information table for the relevant compilation unit.
+            m_op2.file_idx  = mac_info_data.GetULEB128(offset_ptr);
+            break;
+
+        case 0: // End of list
+        case DW_MACINFO_end_file:
+            // No operands
+            m_line = DW_INVALID_OFFSET;
+            m_op2.cstr = NULL;
+            break;
+        default:
+            // Vendor specific entries always have a ULEB128 and a string
+            m_line      = mac_info_data.GetULEB128(offset_ptr);
+            m_op2.cstr  = mac_info_data.GetCStr(offset_ptr);
+            break;
+        }
+        return true;
+    }
+    else
+        m_type_code = 0;
+
+    return false;
+}
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.h
new file mode 100644
index 0000000..85dd625
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.h
@@ -0,0 +1,57 @@
+//===-- DWARFDebugMacinfoEntry.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_DWARFDebugMacinfoEntry_h_
+#define SymbolFileDWARF_DWARFDebugMacinfoEntry_h_
+
+#include "SymbolFileDWARF.h"
+
+class DWARFDebugMacinfoEntry
+{
+public:
+    DWARFDebugMacinfoEntry();
+
+    ~DWARFDebugMacinfoEntry();
+
+    uint8_t
+    TypeCode() const
+    {
+        return m_type_code;
+    }
+
+    uint8_t
+    GetLineNumber() const
+    {
+        return m_line;
+    }
+
+    void
+    Dump(lldb_private::Stream *s) const;
+
+    const char*
+    GetCString() const;
+
+    bool
+    Extract(const lldb_private::DataExtractor& mac_info_data,
+            dw_offset_t* offset_ptr);
+
+protected:
+
+private:
+    uint8_t m_type_code;
+    dw_uleb128_t m_line;
+    union
+    {
+        dw_uleb128_t file_idx;
+        const char* cstr;
+    } m_op2;
+};
+
+
+#endif  // SymbolFileDWARF_DWARFDebugMacinfoEntry_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
new file mode 100644
index 0000000..93ecaed
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
@@ -0,0 +1,297 @@
+//===-- DWARFDebugPubnames.cpp ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugPubnames.h"
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/Timer.h"
+
+#include "DWARFDebugInfo.h"
+#include "DWARFDIECollection.h"
+#include "DWARFFormValue.h"
+#include "DWARFCompileUnit.h"
+#include "LogChannelDWARF.h"
+#include "SymbolFileDWARF.h"
+
+
+using namespace lldb_private;
+
+DWARFDebugPubnames::DWARFDebugPubnames() :
+    m_sets()
+{
+}
+
+bool
+DWARFDebugPubnames::Extract(const DataExtractor& data)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "DWARFDebugPubnames::Extract (byte_size = %zu)",
+                        data.GetByteSize());
+    Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES);
+    if (log)
+        log->Printf("DWARFDebugPubnames::Extract (byte_size = %zu)", data.GetByteSize());
+
+    if (data.ValidOffset(0))
+    {
+        uint32_t offset = 0;
+
+        DWARFDebugPubnamesSet set;
+        while (data.ValidOffset(offset))
+        {
+            if (set.Extract(data, &offset))
+            {
+                m_sets.push_back(set);
+                offset = set.GetOffsetOfNextEntry();
+            }
+            else
+                break;
+        }
+        if (log)
+            Dump (log);
+        return true;
+    }
+    return false;
+}
+
+
+bool
+DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "DWARFDebugPubnames::GeneratePubnames (data = %p)",
+                        dwarf2Data);
+
+    Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES);
+    if (log)
+        log->Printf("DWARFDebugPubnames::GeneratePubnames (data = %p)", dwarf2Data);
+
+    m_sets.clear();
+    DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
+    if (debug_info)
+    {
+
+        const DataExtractor* debug_str = &dwarf2Data->get_debug_str_data();
+
+        uint32_t cu_idx = 0;
+        const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
+        for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
+        {
+
+            DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
+
+            bool clear_dies = cu->ExtractDIEsIfNeeded (false) > 1;
+
+            DWARFDIECollection dies;
+            const size_t die_count = cu->AppendDIEsWithTag (DW_TAG_subprogram, dies) +
+                                     cu->AppendDIEsWithTag (DW_TAG_variable, dies);
+
+            dw_offset_t cu_offset = cu->GetOffset();
+            DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset, cu->GetNextCompileUnitOffset() - cu_offset);
+
+            size_t die_idx;
+            for (die_idx = 0; die_idx < die_count; ++die_idx)
+            {
+                const DWARFDebugInfoEntry *die = dies.GetDIEPtrAtIndex(die_idx);
+                DWARFDebugInfoEntry::Attributes attributes;
+                const char *name = NULL;
+                const char *mangled = NULL;
+                bool add_die = false;
+                bool is_variable = false;
+                const size_t num_attributes = die->GetAttributes(dwarf2Data, cu, attributes);
+                if (num_attributes > 0)
+                {
+                    uint32_t i;
+
+                    dw_tag_t tag = die->Tag();
+                    
+                    is_variable = tag == DW_TAG_variable;
+
+                    for (i=0; i<num_attributes; ++i)
+                    {
+                        dw_attr_t attr = attributes.AttributeAtIndex(i);
+                        DWARFFormValue form_value;
+                        switch (attr)
+                        {
+                        case DW_AT_name:
+                            if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
+                                name = form_value.AsCString(debug_str);
+                            break;
+
+                        case DW_AT_MIPS_linkage_name:
+                            if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
+                                mangled = form_value.AsCString(debug_str);
+                            break;
+
+                        case DW_AT_low_pc:
+                        case DW_AT_ranges:
+                        case DW_AT_entry_pc:
+                            if (tag == DW_TAG_subprogram)
+                                add_die = true;
+                            break;
+
+                        case DW_AT_location:
+                            if (tag == DW_TAG_variable)
+                            {
+                                const DWARFDebugInfoEntry* parent_die = die->GetParent();
+                                while ( parent_die != NULL )
+                                {
+                                    switch (parent_die->Tag())
+                                    {
+                                    case DW_TAG_subprogram:
+                                    case DW_TAG_lexical_block:
+                                    case DW_TAG_inlined_subroutine:
+                                        // Even if this is a function level static, we don't add it. We could theoretically
+                                        // add these if we wanted to by introspecting into the DW_AT_location and seeing
+                                        // if the location describes a hard coded address, but we dont want the performance
+                                        // penalty of that right now.
+                                        add_die = false;
+//                                      if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
+//                                      {
+//                                          // If we have valid block data, then we have location expression bytes
+//                                          // that are fixed (not a location list).
+//                                          const uint8_t *block_data = form_value.BlockData();
+//                                          if (block_data)
+//                                          {
+//                                              uint32_t block_length = form_value.Unsigned();
+//                                              if (block_length == 1 + attributes.CompileUnitAtIndex(i)->GetAddressByteSize())
+//                                              {
+//                                                  if (block_data[0] == DW_OP_addr)
+//                                                      add_die = true;
+//                                              }
+//                                          }
+//                                      }
+                                        parent_die = NULL;  // Terminate the while loop.
+                                        break;
+
+                                    case DW_TAG_compile_unit:
+                                        add_die = true;
+                                        parent_die = NULL;  // Terminate the while loop.
+                                        break;
+
+                                    default:
+                                        parent_die = parent_die->GetParent();   // Keep going in the while loop.
+                                        break;
+                                    }
+                                }
+                            }
+                            break;
+                        }
+                    }
+                }
+
+                if (add_die && (name || mangled))
+                {
+                    if (is_variable)
+                        cu->AddGlobal(die);
+                    pubnames_set.AddDescriptor(die->GetOffset() - cu_offset, mangled ? mangled : name);
+                }
+            }
+
+            if (pubnames_set.NumDescriptors() > 0)
+            {
+                m_sets.push_back(pubnames_set);
+            }
+            
+            // Keep memory down by clearing DIEs if this generate function
+            // caused them to be parsed
+            if (clear_dies)
+                cu->ClearDIEs (true);
+        }
+    }
+    if (m_sets.empty())
+        return false;
+    if (log)
+        Dump (log);
+    return true;
+}
+
+bool
+DWARFDebugPubnames::GeneratePubBaseTypes(SymbolFileDWARF* dwarf2Data)
+{
+    m_sets.clear();
+    DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
+    if (debug_info)
+    {
+        uint32_t cu_idx = 0;
+        const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
+        for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
+        {
+            DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
+            DWARFDIECollection dies;
+            const size_t die_count = cu->AppendDIEsWithTag (DW_TAG_base_type, dies);
+            dw_offset_t cu_offset = cu->GetOffset();
+            DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset, cu->GetNextCompileUnitOffset() - cu_offset);
+
+            size_t die_idx;
+            for (die_idx = 0; die_idx < die_count; ++die_idx)
+            {
+                const DWARFDebugInfoEntry *die = dies.GetDIEPtrAtIndex(die_idx);
+                const char *name = die->GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, NULL);
+
+                if (name)
+                {
+                    pubnames_set.AddDescriptor(die->GetOffset() - cu_offset, name);
+                }
+            }
+
+            if (pubnames_set.NumDescriptors() > 0)
+            {
+                m_sets.push_back(pubnames_set);
+            }
+        }
+    }
+    return !m_sets.empty();
+}
+
+void
+DWARFDebugPubnames::Dump(Log *s) const
+{
+    if (m_sets.empty())
+        s->PutCString("< EMPTY >\n");
+    else
+    {
+        const_iterator pos;
+        const_iterator end = m_sets.end();
+
+        for (pos = m_sets.begin(); pos != end; ++pos)
+            (*pos).Dump(s);
+    }
+}
+
+bool
+DWARFDebugPubnames::Find(const char* name, bool ignore_case, std::vector<dw_offset_t>& die_offsets) const
+{
+    const_iterator pos;
+    const_iterator end = m_sets.end();
+
+    die_offsets.clear();
+
+    for (pos = m_sets.begin(); pos != end; ++pos)
+    {
+        (*pos).Find(name, ignore_case, die_offsets);
+    }
+
+    return !die_offsets.empty();
+}
+
+bool
+DWARFDebugPubnames::Find(const RegularExpression& regex, std::vector<dw_offset_t>& die_offsets) const
+{
+    const_iterator pos;
+    const_iterator end = m_sets.end();
+
+    die_offsets.clear();
+
+    for (pos = m_sets.begin(); pos != end; ++pos)
+    {
+        (*pos).Find(regex, die_offsets);
+    }
+
+    return !die_offsets.empty();
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.h
new file mode 100644
index 0000000..7d09bf3
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.h
@@ -0,0 +1,38 @@
+//===-- DWARFDebugPubnames.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_DWARFDebugPubnames_h_
+#define SymbolFileDWARF_DWARFDebugPubnames_h_
+
+#include "SymbolFileDWARF.h"
+
+#include <list>
+
+#include "DWARFDebugPubnamesSet.h"
+
+class DWARFDebugPubnames
+{
+public:
+            DWARFDebugPubnames();
+    bool    Extract(const lldb_private::DataExtractor& data);
+    bool    GeneratePubnames(SymbolFileDWARF* dwarf2Data);
+    bool    GeneratePubBaseTypes(SymbolFileDWARF* dwarf2Data);
+
+    void    Dump(lldb_private::Log *s) const;
+    bool    Find(const char* name, bool ignore_case, std::vector<dw_offset_t>& die_offset_coll) const;
+    bool    Find(const lldb_private::RegularExpression& regex, std::vector<dw_offset_t>& die_offsets) const;
+protected:
+    typedef std::list<DWARFDebugPubnamesSet>    collection;
+    typedef collection::iterator                iterator;
+    typedef collection::const_iterator          const_iterator;
+
+    collection m_sets;
+};
+
+#endif  // SymbolFileDWARF_DWARFDebugPubnames_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.cpp
new file mode 100644
index 0000000..0421ced
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.cpp
@@ -0,0 +1,166 @@
+//===-- DWARFDebugPubnamesSet.cpp -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugPubnamesSet.h"
+
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/Log.h"
+
+#include "SymbolFileDWARF.h"
+
+using namespace lldb_private;
+
+DWARFDebugPubnamesSet::DWARFDebugPubnamesSet() :
+    m_offset(DW_INVALID_OFFSET),
+    m_header(),
+    m_descriptors(),
+    m_name_to_descriptor_index()
+{
+}
+
+DWARFDebugPubnamesSet::DWARFDebugPubnamesSet(dw_offset_t debug_aranges_offset, dw_offset_t cu_die_offset, dw_offset_t cu_die_length) :
+    m_offset(debug_aranges_offset),
+    m_header(),
+    m_descriptors(),
+    m_name_to_descriptor_index()
+{
+    m_header.length = 10;               // set the length to only include the header right for now
+    m_header.version = 2;               // The DWARF version number
+    m_header.die_offset = cu_die_offset;// compile unit .debug_info offset
+    m_header.die_length = cu_die_length;// compile unit .debug_info length
+}
+
+void
+DWARFDebugPubnamesSet::AddDescriptor(dw_offset_t cu_rel_offset, const char* name)
+{
+    if (name && name[0])
+    {
+        // Adjust our header length
+        m_header.length += strlen(name) + 1 + sizeof(dw_offset_t);
+        Descriptor pubnameDesc(cu_rel_offset, name);
+        m_descriptors.push_back(pubnameDesc);
+    }
+}
+
+void
+DWARFDebugPubnamesSet::Clear()
+{
+    m_offset = DW_INVALID_OFFSET;
+    m_header.length = 10;
+    m_header.version = 2;
+    m_header.die_offset = DW_INVALID_OFFSET;
+    m_header.die_length = 0;
+    m_descriptors.clear();
+}
+
+
+//----------------------------------------------------------------------
+// InitNameIndexes
+//----------------------------------------------------------------------
+void
+DWARFDebugPubnamesSet::InitNameIndexes() const
+{
+    // Create the name index vector to be able to quickly search by name
+    const size_t count = m_descriptors.size();
+    for (uint32_t idx = 0; idx < count; ++idx)
+    {
+        const char* name = m_descriptors[idx].name.c_str();
+        if (name && name[0])
+            m_name_to_descriptor_index.insert(cstr_to_index_mmap::value_type(name, idx));
+    }
+}
+
+
+bool
+DWARFDebugPubnamesSet::Extract(const DataExtractor& data, uint32_t* offset_ptr)
+{
+    if (data.ValidOffset(*offset_ptr))
+    {
+        m_descriptors.clear();
+        m_offset = *offset_ptr;
+        m_header.length     = data.GetU32(offset_ptr);
+        m_header.version    = data.GetU16(offset_ptr);
+        m_header.die_offset = data.GetU32(offset_ptr);
+        m_header.die_length = data.GetU32(offset_ptr);
+
+        Descriptor pubnameDesc;
+        while (data.ValidOffset(*offset_ptr))
+        {
+            pubnameDesc.offset  = data.GetU32(offset_ptr);
+
+            if (pubnameDesc.offset)
+            {
+                const char* name = data.GetCStr(offset_ptr);
+                if (name && name[0])
+                {
+                    pubnameDesc.name = name;
+                    m_descriptors.push_back(pubnameDesc);
+                }
+            }
+            else
+                break;  // We are done if we get a zero 4 byte offset
+        }
+
+        return !m_descriptors.empty();
+    }
+    return false;
+}
+
+dw_offset_t
+DWARFDebugPubnamesSet::GetOffsetOfNextEntry() const
+{
+    return m_offset + m_header.length + 4;
+}
+
+void
+DWARFDebugPubnamesSet::Dump(Log *log) const
+{
+    log->Printf("Pubnames Header: length = 0x%8.8x, version = 0x%4.4x, die_offset = 0x%8.8x, die_length = 0x%8.8x",
+        m_header.length,
+        m_header.version,
+        m_header.die_offset,
+        m_header.die_length);
+
+    bool verbose = log->GetVerbose();
+
+    DescriptorConstIter pos;
+    DescriptorConstIter end = m_descriptors.end();
+    for (pos = m_descriptors.begin(); pos != end; ++pos)
+    {
+        if (verbose)
+            log->Printf("0x%8.8x + 0x%8.8x = 0x%8.8x: %s", pos->offset, m_header.die_offset, pos->offset + m_header.die_offset, pos->name.c_str());
+        else
+            log->Printf("0x%8.8x: %s", pos->offset + m_header.die_offset, pos->name.c_str());
+    }
+}
+
+
+void
+DWARFDebugPubnamesSet::Find(const char* name, bool ignore_case, std::vector<dw_offset_t>& die_offset_coll) const
+{
+    if (!m_descriptors.empty() && m_name_to_descriptor_index.empty())
+        InitNameIndexes();
+
+    std::pair<cstr_to_index_mmap::const_iterator, cstr_to_index_mmap::const_iterator> range(m_name_to_descriptor_index.equal_range(name));
+    for (cstr_to_index_mmap::const_iterator pos = range.first; pos != range.second; ++pos)
+        die_offset_coll.push_back(m_header.die_offset + m_descriptors[(*pos).second].offset);
+}
+
+void
+DWARFDebugPubnamesSet::Find(const RegularExpression& regex, std::vector<dw_offset_t>& die_offset_coll) const
+{
+    DescriptorConstIter pos;
+    DescriptorConstIter end = m_descriptors.end();
+    for (pos = m_descriptors.begin(); pos != end; ++pos)
+    {
+        if ( regex.Execute(pos->name.c_str()) )
+            die_offset_coll.push_back(m_header.die_offset + pos->offset);
+    }
+}
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.h
new file mode 100644
index 0000000..0597e36
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.h
@@ -0,0 +1,91 @@
+//===-- DWARFDebugPubnamesSet.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_DWARFDebugPubnamesSet_h_
+#define SymbolFileDWARF_DWARFDebugPubnamesSet_h_
+
+#include "SymbolFileDWARF.h"
+#include <string>
+#include <vector>
+#include <ext/hash_map>
+
+class DWARFDebugPubnamesSet
+{
+public:
+    struct Header
+    {
+        uint32_t    length;     // length of the set of entries for this compilation unit, not including the length field itself
+        uint16_t    version;    // The DWARF version number
+        uint32_t    die_offset; // compile unit .debug_info offset
+        uint32_t    die_length; // compile unit .debug_info length
+        Header() :
+            length(10),
+            version(2),
+            die_offset(DW_INVALID_OFFSET),
+            die_length(0)
+        {
+        }
+    };
+
+    struct Descriptor
+    {
+        Descriptor() :
+            offset(),
+            name()
+        {
+        }
+
+        Descriptor(dw_offset_t the_offset, const char *the_name) :
+            offset(the_offset),
+            name(the_name ? the_name : "")
+        {
+        }
+
+        dw_offset_t offset;
+        std::string name;
+    };
+
+                DWARFDebugPubnamesSet();
+                DWARFDebugPubnamesSet(dw_offset_t debug_aranges_offset, dw_offset_t cu_die_offset, dw_offset_t die_length);
+    dw_offset_t GetOffset() const { return m_offset; }
+    void        SetOffset(dw_offset_t offset) { m_offset = offset; }
+    DWARFDebugPubnamesSet::Header& GetHeader() { return m_header; }
+    const DWARFDebugPubnamesSet::Header& GetHeader() const { return m_header; }
+    const DWARFDebugPubnamesSet::Descriptor* GetDescriptor(uint32_t i) const
+        {
+            if (i < m_descriptors.size())
+                return &m_descriptors[i];
+            return NULL;
+        }
+    uint32_t    NumDescriptors() const { return m_descriptors.size(); }
+    void        AddDescriptor(dw_offset_t cu_rel_offset, const char* name);
+    void        Clear();
+    bool        Extract(const lldb_private::DataExtractor& debug_pubnames_data, uint32_t* offset_ptr);
+    void        Dump(lldb_private::Log *s) const;
+    void        InitNameIndexes() const;
+    void        Find(const char* name, bool ignore_case, std::vector<dw_offset_t>& die_offset_coll) const;
+    void        Find(const lldb_private::RegularExpression& regex, std::vector<dw_offset_t>& die_offsets) const;
+    dw_offset_t GetOffsetOfNextEntry() const;
+
+
+
+protected:
+    typedef std::vector<Descriptor>         DescriptorColl;
+    typedef DescriptorColl::iterator        DescriptorIter;
+    typedef DescriptorColl::const_iterator  DescriptorConstIter;
+
+
+    dw_offset_t     m_offset;
+    Header          m_header;
+    typedef __gnu_cxx::hash_multimap<const char*, uint32_t, __gnu_cxx::hash<const char*>, CStringEqualBinaryPredicate> cstr_to_index_mmap;
+    DescriptorColl  m_descriptors;
+    mutable cstr_to_index_mmap m_name_to_descriptor_index;
+};
+
+#endif  // SymbolFileDWARF_DWARFDebugPubnamesSet_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
new file mode 100644
index 0000000..62da228
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
@@ -0,0 +1,275 @@
+//===-- DWARFDebugRanges.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugRanges.h"
+#include "SymbolFileDWARF.h"
+#include "lldb/Core/Stream.h"
+#include <assert.h>
+
+using namespace lldb_private;
+using namespace std;
+
+DWARFDebugRanges::DWARFDebugRanges() :
+    m_range_map()
+{
+}
+
+DWARFDebugRanges::~DWARFDebugRanges()
+{
+}
+
+void
+DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data)
+{
+    RangeList range_list;
+    dw_offset_t offset = 0;
+    dw_offset_t debug_ranges_offset = offset;
+    while (range_list.Extract(dwarf2Data, &offset))
+    {
+        m_range_map[debug_ranges_offset] = range_list;
+        debug_ranges_offset = offset;
+    }
+}
+
+bool
+DWARFDebugRanges::RangeList::AddRange(dw_addr_t lo_addr, dw_addr_t hi_addr)
+{
+    if (lo_addr <= hi_addr)
+    {
+        Range range(lo_addr, hi_addr);
+        ranges.push_back(range);
+        return true;
+    }
+    return false;
+}
+
+const DWARFDebugRanges::Range*
+DWARFDebugRanges::RangeList::Lookup(dw_addr_t offset) const
+{
+    Range::const_iterator pos = ranges.begin();
+    Range::const_iterator end_pos = ranges.end();
+    for (pos = ranges.begin(); pos != end_pos; ++pos)
+    {
+        if (pos->begin_offset <= offset && offset < pos->end_offset)
+        {
+            return &(*pos);
+        }
+    }
+    return NULL;
+}
+
+size_t
+DWARFDebugRanges::RangeList::Size() const
+{
+    return ranges.size();
+}
+
+void
+DWARFDebugRanges::RangeList::AddOffset(dw_addr_t offset)
+{
+    if (!ranges.empty())
+    {
+        Range::iterator pos = ranges.begin();
+        Range::iterator end_pos = ranges.end();
+        for (pos = ranges.begin(); pos != end_pos; ++pos)
+        {
+            // assert for unsigned overflows
+            assert (~pos->begin_offset >= offset);
+            assert (~pos->end_offset >= offset);
+            pos->begin_offset += offset;
+            pos->end_offset += offset;
+        }
+    }
+}
+
+void
+DWARFDebugRanges::RangeList::SubtractOffset(dw_addr_t offset)
+{
+    if (!ranges.empty())
+    {
+        Range::iterator pos = ranges.begin();
+        Range::iterator end_pos = ranges.end();
+        for (pos = ranges.begin(); pos != end_pos; ++pos)
+        {
+            assert (pos->begin_offset >= offset);
+            assert (pos->end_offset >= offset);
+            pos->begin_offset -= offset;
+            pos->end_offset -= offset;
+        }
+    }
+}
+
+
+const DWARFDebugRanges::Range*
+DWARFDebugRanges::RangeList::RangeAtIndex(size_t i) const
+{
+    if (i < ranges.size())
+        return &ranges[i];
+    return NULL;
+}
+
+bool
+DWARFDebugRanges::RangeList::Extract(SymbolFileDWARF* dwarf2Data, uint32_t* offset_ptr)
+{
+    Clear();
+    uint32_t range_offset = *offset_ptr;
+    const DataExtractor& debug_ranges_data = dwarf2Data->get_debug_ranges_data();
+    uint32_t addr_size = debug_ranges_data.GetAddressByteSize();
+
+    while (debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size))
+    {
+        dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
+        dw_addr_t end   = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
+        if (!begin && !end)
+        {
+            // End of range list
+            break;
+        }
+        // Extend 4 byte addresses that consits of 32 bits of 1's to be 64 bits
+        // of ones
+        switch (addr_size)
+        {
+        case 2:
+            if (begin == 0xFFFFull)
+                begin = DW_INVALID_ADDRESS;
+            break;
+
+        case 4:
+            if (begin == 0xFFFFFFFFull)
+                begin = DW_INVALID_ADDRESS;
+            break;
+
+        case 8:
+            break;
+
+        default:
+            assert(!"DWARFDebugRanges::RangeList::Extract() unsupported address size.");
+            break;
+        }
+
+        // Filter out empty ranges
+        if (begin != end)
+            ranges.push_back(Range(begin, end));
+    }
+
+    // Make sure we consumed at least something
+    return range_offset != *offset_ptr;
+}
+
+
+dw_addr_t
+DWARFDebugRanges::RangeList::LowestAddress(const dw_addr_t cu_base_addr) const
+{
+    dw_addr_t addr = DW_INVALID_ADDRESS;
+    dw_addr_t curr_base_addr = cu_base_addr;
+    if (!ranges.empty())
+    {
+        Range::const_iterator pos = ranges.begin();
+        Range::const_iterator end_pos = ranges.end();
+        for (pos = ranges.begin(); pos != end_pos; ++pos)
+        {
+            if (pos->begin_offset == DW_INVALID_ADDRESS)
+                curr_base_addr = pos->end_offset;
+            else if (curr_base_addr != DW_INVALID_ADDRESS)
+            {
+                dw_addr_t curr_addr = curr_base_addr + pos->begin_offset;
+                if (addr > curr_addr)
+                    addr = curr_addr;
+            }
+        }
+    }
+    return addr;
+}
+
+dw_addr_t
+DWARFDebugRanges::RangeList::HighestAddress(const dw_addr_t cu_base_addr) const
+{
+    dw_addr_t addr = 0;
+    dw_addr_t curr_base_addr = cu_base_addr;
+    if (!ranges.empty())
+    {
+        Range::const_iterator pos = ranges.begin();
+        Range::const_iterator end_pos = ranges.end();
+        for (pos = ranges.begin(); pos != end_pos; ++pos)
+        {
+            if (pos->begin_offset == DW_INVALID_ADDRESS)
+                curr_base_addr = pos->end_offset;
+            else if (curr_base_addr != DW_INVALID_ADDRESS)
+            {
+                dw_addr_t curr_addr = curr_base_addr + pos->end_offset;
+                if (addr < curr_addr)
+                    addr = curr_addr;
+            }
+        }
+    }
+    if (addr != 0)
+        return addr;
+    return DW_INVALID_ADDRESS;
+}
+
+
+void
+DWARFDebugRanges::Dump(Stream *s, const DataExtractor& debug_ranges_data, uint32_t* offset_ptr, dw_addr_t cu_base_addr)
+{
+    uint32_t addr_size = s->GetAddressByteSize();
+    bool verbose = s->GetVerbose();
+
+    dw_addr_t base_addr = cu_base_addr;
+    while (debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size))
+    {
+        dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
+        dw_addr_t end   = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
+        // Extend 4 byte addresses that consits of 32 bits of 1's to be 64 bits
+        // of ones
+        if (begin == 0xFFFFFFFFull && addr_size == 4)
+            begin = DW_INVALID_ADDRESS;
+
+        s->Indent();
+        if (verbose)
+        {
+            s->AddressRange(begin, end, sizeof (dw_addr_t), " offsets = ");
+        }
+
+
+        if (begin == 0 && end == 0)
+        {
+            s->PutCString(" End");
+            break;
+        }
+        else if (begin == DW_INVALID_ADDRESS)
+        {
+            // A base address selection entry
+            base_addr = end;
+            s->Address(base_addr, sizeof (dw_addr_t), " Base address = ");
+        }
+        else
+        {
+            // Convert from offset to an address
+            dw_addr_t begin_addr = begin + base_addr;
+            dw_addr_t end_addr = end + base_addr;
+
+            s->AddressRange(begin_addr, end_addr, sizeof (dw_addr_t), verbose ? " ==> addrs = " : NULL);
+        }
+    }
+}
+
+bool
+DWARFDebugRanges::FindRanges(dw_offset_t debug_ranges_offset, RangeList& range_list) const
+{
+    range_map_const_iterator pos = m_range_map.find(debug_ranges_offset);
+    if (pos != m_range_map.end())
+    {
+        range_list = pos->second;
+        return true;
+    }
+    return false;
+}
+
+
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
new file mode 100644
index 0000000..607c3c2
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
@@ -0,0 +1,89 @@
+//===-- DWARFDebugRanges.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_DWARFDebugRanges_h_
+#define liblldb_DWARFDebugRanges_h_
+
+#include "SymbolFileDWARF.h"
+#include <map>
+#include <vector>
+
+
+class DWARFDebugRanges
+{
+public:
+
+    //------------------------------------------------------------------
+    // Address range
+    //------------------------------------------------------------------
+    struct Range
+    {
+        Range(dw_addr_t begin = DW_INVALID_ADDRESS, dw_addr_t end = DW_INVALID_ADDRESS) :
+            begin_offset(begin),
+            end_offset(end)
+        {
+        }
+
+        void Clear()
+        {
+            begin_offset = DW_INVALID_ADDRESS;
+            end_offset = DW_INVALID_ADDRESS;
+        }
+
+        dw_addr_t   begin_offset;
+        dw_addr_t   end_offset;
+
+        typedef std::vector<Range>          collection;
+        typedef collection::iterator        iterator;
+        typedef collection::const_iterator  const_iterator;
+
+    };
+
+    //------------------------------------------------------------------
+    // Collection of ranges
+    //------------------------------------------------------------------
+    struct RangeList
+    {
+            RangeList() :
+                ranges()
+            {
+            }
+
+        bool Extract(SymbolFileDWARF* dwarf2Data, uint32_t* offset_ptr);
+        bool AddRange(dw_addr_t lo_addr, dw_addr_t hi_addr);
+        void Clear()
+            {
+                ranges.clear();
+            }
+
+        dw_addr_t LowestAddress(const dw_addr_t base_addr) const;
+        dw_addr_t HighestAddress(const dw_addr_t base_addr) const;
+        void AddOffset(dw_addr_t offset);
+        void SubtractOffset(dw_addr_t offset);
+        size_t Size() const;
+        const Range* RangeAtIndex(size_t i) const;
+        const Range* Lookup(dw_addr_t offset) const;
+        Range::collection   ranges;
+    };
+
+    DWARFDebugRanges();
+    ~DWARFDebugRanges();
+    void Extract(SymbolFileDWARF* dwarf2Data);
+    static void Dump(lldb_private::Stream *s, const lldb_private::DataExtractor& debug_ranges_data, uint32_t* offset_ptr, dw_addr_t cu_base_addr);
+    bool FindRanges(dw_offset_t debug_ranges_offset, DWARFDebugRanges::RangeList& range_list) const;
+
+protected:
+    typedef std::map<dw_offset_t, RangeList>    range_map;
+    typedef range_map::iterator                 range_map_iterator;
+    typedef range_map::const_iterator           range_map_const_iterator;
+    range_map m_range_map;
+};
+
+
+#endif  // liblldb_DWARFDebugRanges_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDefines.c b/source/Plugins/SymbolFile/DWARF/DWARFDefines.c
new file mode 100644
index 0000000..fe487f9
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDefines.c
@@ -0,0 +1,2224 @@
+//===-- DWARFDefines.c ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDefines.h"
+#include <stdio.h>
+
+#define DW_TAG_PREFIX   "TAG_"
+#define DW_AT_PREFIX    " AT_"
+#define DW_FORM_PREFIX  "FORM_"
+
+/* [7.5.4] Figure 16 "Tag Encodings" (pp. 125-127) in DWARFv3 draft 8 */
+
+const char *
+DW_TAG_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x0000: return DW_TAG_PREFIX "NULL";
+    case 0x0001: return DW_TAG_PREFIX "array_type";
+    case 0x0002: return DW_TAG_PREFIX "class_type";
+    case 0x0003: return DW_TAG_PREFIX "entry_point";
+    case 0x0004: return DW_TAG_PREFIX "enumeration_type";
+    case 0x0005: return DW_TAG_PREFIX "formal_parameter";
+    case 0x0008: return DW_TAG_PREFIX "imported_declaration";
+    case 0x000a: return DW_TAG_PREFIX "label";
+    case 0x000b: return DW_TAG_PREFIX "lexical_block";
+    case 0x000d: return DW_TAG_PREFIX "member";
+    case 0x000f: return DW_TAG_PREFIX "pointer_type";
+    case 0x0010: return DW_TAG_PREFIX "reference_type";
+    case 0x0011: return DW_TAG_PREFIX "compile_unit";
+    case 0x0012: return DW_TAG_PREFIX "string_type";
+    case 0x0013: return DW_TAG_PREFIX "structure_type";
+    case 0x0015: return DW_TAG_PREFIX "subroutine_type";
+    case 0x0016: return DW_TAG_PREFIX "typedef";
+    case 0x0017: return DW_TAG_PREFIX "union_type";
+    case 0x0018: return DW_TAG_PREFIX "unspecified_parameters";
+    case 0x0019: return DW_TAG_PREFIX "variant";
+    case 0x001a: return DW_TAG_PREFIX "common_block";
+    case 0x001b: return DW_TAG_PREFIX "common_inclusion";
+    case 0x001c: return DW_TAG_PREFIX "inheritance";
+    case 0x001d: return DW_TAG_PREFIX "inlined_subroutine";
+    case 0x001e: return DW_TAG_PREFIX "module";
+    case 0x001f: return DW_TAG_PREFIX "ptr_to_member_type";
+    case 0x0020: return DW_TAG_PREFIX "set_type";
+    case 0x0021: return DW_TAG_PREFIX "subrange_type";
+    case 0x0022: return DW_TAG_PREFIX "with_stmt";
+    case 0x0023: return DW_TAG_PREFIX "access_declaration";
+    case 0x0024: return DW_TAG_PREFIX "base_type";
+    case 0x0025: return DW_TAG_PREFIX "catch_block";
+    case 0x0026: return DW_TAG_PREFIX "const_type";
+    case 0x0027: return DW_TAG_PREFIX "constant";
+    case 0x0028: return DW_TAG_PREFIX "enumerator";
+    case 0x0029: return DW_TAG_PREFIX "file_type";
+    case 0x002a: return DW_TAG_PREFIX "friend";
+    case 0x002b: return DW_TAG_PREFIX "namelist";
+    case 0x002c: return DW_TAG_PREFIX "namelist_item";
+    case 0x002d: return DW_TAG_PREFIX "packed_type";
+    case 0x002e: return DW_TAG_PREFIX "subprogram";
+    case 0x002f: return DW_TAG_PREFIX "template_type_parameter";
+    case 0x0030: return DW_TAG_PREFIX "template_value_parameter";
+    case 0x0031: return DW_TAG_PREFIX "thrown_type";
+    case 0x0032: return DW_TAG_PREFIX "try_block";
+    case 0x0033: return DW_TAG_PREFIX "variant_part";
+    case 0x0034: return DW_TAG_PREFIX "variable";
+    case 0x0035: return DW_TAG_PREFIX "volatile_type";
+    case 0x0036: return DW_TAG_PREFIX "dwarf_procedure";
+    case 0x0037: return DW_TAG_PREFIX "restrict_type";
+    case 0x0038: return DW_TAG_PREFIX "interface_type";
+    case 0x0039: return DW_TAG_PREFIX "namespace";
+    case 0x003a: return DW_TAG_PREFIX "imported_module";
+    case 0x003b: return DW_TAG_PREFIX "unspecified_type";
+    case 0x003c: return DW_TAG_PREFIX "partial_unit";
+    case 0x003d: return DW_TAG_PREFIX "imported_unit";
+//  case 0x003d: return DW_TAG_PREFIX "condition";
+    case 0x0040: return DW_TAG_PREFIX "shared_type";
+    case 0x4080: return DW_TAG_PREFIX "lo_user";
+    case 0xffff: return DW_TAG_PREFIX "hi_user";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_TAG constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+const char *
+DW_TAG_value_to_englishy_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x0001: return "array type";
+    case 0x0002: return "class type";
+    case 0x0003: return "entry point";
+    case 0x0004: return "enumeration type";
+    case 0x0005: return "formal parameter";
+    case 0x0008: return "imported declaration";
+    case 0x000a: return "label";
+    case 0x000b: return "lexical block";
+    case 0x000d: return "member";
+    case 0x000f: return "pointer type";
+    case 0x0010: return "reference type";
+    case 0x0011: return "file";
+    case 0x0012: return "string type";
+    case 0x0013: return "structure type";
+    case 0x0015: return "subroutine type";
+    case 0x0016: return "typedef";
+    case 0x0017: return "union type";
+    case 0x0018: return "unspecified parameters";
+    case 0x0019: return "variant";
+    case 0x001a: return "common block";
+    case 0x001b: return "common inclusion";
+    case 0x001c: return "inheritance";
+    case 0x001d: return "inlined subroutine";
+    case 0x001e: return "module";
+    case 0x001f: return "ptr to member type";
+    case 0x0020: return "set type";
+    case 0x0021: return "subrange type";
+    case 0x0022: return "with stmt";
+    case 0x0023: return "access declaration";
+    case 0x0024: return "base type";
+    case 0x0025: return "catch block";
+    case 0x0026: return "const type";
+    case 0x0027: return "constant";
+    case 0x0028: return "enumerator";
+    case 0x0029: return "file type";
+    case 0x002a: return "friend";
+    case 0x002b: return "namelist";
+    case 0x002c: return "namelist item";
+    case 0x002d: return "packed type";
+    case 0x002e: return "function";
+    case 0x002f: return "template type parameter";
+    case 0x0030: return "template value parameter";
+    case 0x0031: return "thrown type";
+    case 0x0032: return "try block";
+    case 0x0033: return "variant part";
+    case 0x0034: return "variable";
+    case 0x0035: return "volatile type";
+    case 0x0036: return "dwarf procedure";
+    case 0x0037: return "restrict type";
+    case 0x0038: return "interface type";
+    case 0x0039: return "namespace";
+    case 0x003a: return "imported module";
+    case 0x003b: return "unspecified type";
+    case 0x003c: return "partial unit";
+    case 0x003d: return "imported unit";
+//  case 0x003d: return "condition";
+    case 0x0040: return "shared type";
+    case 0x4080: return "lo user";
+    case 0xffff: return "hi user";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_TAG constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+DRC_class
+DW_TAG_value_to_class (uint32_t val)
+{
+  switch (val) {
+    case 0x0001: return 0;
+    case 0x0002: return 0;
+    case 0x0003: return 0;
+    case 0x0004: return 0;
+    case 0x0005: return 0;
+    case 0x0008: return 0;
+    case 0x000a: return 0;
+    case 0x000b: return 0;
+    case 0x000d: return 0;
+    case 0x000f: return 0;
+    case 0x0010: return 0;
+    case 0x0011: return 0;
+    case 0x0012: return 0;
+    case 0x0013: return 0;
+    case 0x0015: return 0;
+    case 0x0016: return 0;
+    case 0x0017: return 0;
+    case 0x0018: return 0;
+    case 0x0019: return 0;
+    case 0x001a: return 0;
+    case 0x001b: return 0;
+    case 0x001c: return 0;
+    case 0x001d: return 0;
+    case 0x001e: return 0;
+    case 0x001f: return 0;
+    case 0x0020: return 0;
+    case 0x0021: return 0;
+    case 0x0022: return 0;
+    case 0x0023: return 0;
+    case 0x0024: return 0;
+    case 0x0025: return 0;
+    case 0x0026: return 0;
+    case 0x0027: return 0;
+    case 0x0028: return 0;
+    case 0x0029: return 0;
+    case 0x002a: return 0;
+    case 0x002b: return 0;
+    case 0x002c: return 0;
+    case 0x002d: return 0;
+    case 0x002e: return 0;
+    case 0x002f: return 0;
+    case 0x0030: return 0;
+    case 0x0031: return 0;
+    case 0x0032: return 0;
+    case 0x0033: return 0;
+    case 0x0034: return 0;
+    case 0x0035: return 0;
+    case 0x0036: return DRC_DWARFv3;
+    case 0x0037: return DRC_DWARFv3;
+    case 0x0038: return DRC_DWARFv3;
+    case 0x0039: return DRC_DWARFv3;
+    case 0x003a: return DRC_DWARFv3;
+    case 0x003b: return DRC_DWARFv3;
+    case 0x003c: return DRC_DWARFv3;
+    case 0x003d: return DRC_DWARFv3;
+//  case 0x003d: return DRC_DWARFv3;
+    case 0x0040: return DRC_DWARFv3;
+    case 0x4080: return 0;
+    case 0xffff: return 0;
+    default: return 0;
+  }
+}
+
+/* [7.5.4] Figure 17 "Child determination encodings" (p. 128) in DWARFv3 draft 8 */
+
+const char *
+DW_CHILDREN_value_to_name (uint8_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x0: return "DW_CHILDREN_no";
+    case 0x1: return "DW_CHILDREN_yes";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_CHILDREN constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+const char *
+DW_CHILDREN_value_to_englishy_name (uint8_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x0: return "no";
+    case 0x1: return "yes";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_CHILDREN constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+DRC_class
+DW_CHILDREN_value_to_class (uint32_t val)
+{
+  switch (val) {
+    case 0x0: return 0;
+    case 0x1: return 0;
+    default: return 0;
+  }
+}
+
+/* [7.5.4] Figure 18 "Attribute encodings" (pp. 129-132) in DWARFv3 draft 8 */
+
+const char *
+DW_AT_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x0001: return DW_AT_PREFIX "sibling";
+    case 0x0002: return DW_AT_PREFIX "location";
+    case 0x0003: return DW_AT_PREFIX "name";
+    case 0x0009: return DW_AT_PREFIX "ordering";
+    case 0x000b: return DW_AT_PREFIX "byte_size";
+    case 0x000c: return DW_AT_PREFIX "bit_offset";
+    case 0x000d: return DW_AT_PREFIX "bit_size";
+    case 0x0010: return DW_AT_PREFIX "stmt_list";
+    case 0x0011: return DW_AT_PREFIX "low_pc";
+    case 0x0012: return DW_AT_PREFIX "high_pc";
+    case 0x0013: return DW_AT_PREFIX "language";
+    case 0x0015: return DW_AT_PREFIX "discr";
+    case 0x0016: return DW_AT_PREFIX "discr_value";
+    case 0x0017: return DW_AT_PREFIX "visibility";
+    case 0x0018: return DW_AT_PREFIX "import";
+    case 0x0019: return DW_AT_PREFIX "string_length";
+    case 0x001a: return DW_AT_PREFIX "common_reference";
+    case 0x001b: return DW_AT_PREFIX "comp_dir";
+    case 0x001c: return DW_AT_PREFIX "const_value";
+    case 0x001d: return DW_AT_PREFIX "containing_type";
+    case 0x001e: return DW_AT_PREFIX "default_value";
+    case 0x0020: return DW_AT_PREFIX "inline";
+    case 0x0021: return DW_AT_PREFIX "is_optional";
+    case 0x0022: return DW_AT_PREFIX "lower_bound";
+    case 0x0025: return DW_AT_PREFIX "producer";
+    case 0x0027: return DW_AT_PREFIX "prototyped";
+    case 0x002a: return DW_AT_PREFIX "return_addr";
+    case 0x002c: return DW_AT_PREFIX "start_scope";
+    case 0x002e: return DW_AT_PREFIX "bit_stride";
+    case 0x002f: return DW_AT_PREFIX "upper_bound";
+    case 0x0031: return DW_AT_PREFIX "abstract_origin";
+    case 0x0032: return DW_AT_PREFIX "accessibility";
+    case 0x0033: return DW_AT_PREFIX "address_class";
+    case 0x0034: return DW_AT_PREFIX "artificial";
+    case 0x0035: return DW_AT_PREFIX "base_types";
+    case 0x0036: return DW_AT_PREFIX "calling_convention";
+    case 0x0037: return DW_AT_PREFIX "count";
+    case 0x0038: return DW_AT_PREFIX "data_member_location";
+    case 0x0039: return DW_AT_PREFIX "decl_column";
+    case 0x003a: return DW_AT_PREFIX "decl_file";
+    case 0x003b: return DW_AT_PREFIX "decl_line";
+    case 0x003c: return DW_AT_PREFIX "declaration";
+    case 0x003d: return DW_AT_PREFIX "discr_list";
+    case 0x003e: return DW_AT_PREFIX "encoding";
+    case 0x003f: return DW_AT_PREFIX "external";
+    case 0x0040: return DW_AT_PREFIX "frame_base";
+    case 0x0041: return DW_AT_PREFIX "friend";
+    case 0x0042: return DW_AT_PREFIX "identifier_case";
+    case 0x0043: return DW_AT_PREFIX "macro_info";
+    case 0x0044: return DW_AT_PREFIX "namelist_item";
+    case 0x0045: return DW_AT_PREFIX "priority";
+    case 0x0046: return DW_AT_PREFIX "segment";
+    case 0x0047: return DW_AT_PREFIX "specification";
+    case 0x0048: return DW_AT_PREFIX "static_link";
+    case 0x0049: return DW_AT_PREFIX "type";
+    case 0x004a: return DW_AT_PREFIX "use_location";
+    case 0x004b: return DW_AT_PREFIX "variable_parameter";
+    case 0x004c: return DW_AT_PREFIX "virtuality";
+    case 0x004d: return DW_AT_PREFIX "vtable_elem_location";
+    case 0x004e: return DW_AT_PREFIX "allocated";
+    case 0x004f: return DW_AT_PREFIX "associated";
+    case 0x0050: return DW_AT_PREFIX "data_location";
+    case 0x0051: return DW_AT_PREFIX "byte_stride";
+    case 0x0052: return DW_AT_PREFIX "entry_pc";
+    case 0x0053: return DW_AT_PREFIX "use_UTF8";
+    case 0x0054: return DW_AT_PREFIX "extension";
+    case 0x0055: return DW_AT_PREFIX "ranges";
+    case 0x0056: return DW_AT_PREFIX "trampoline";
+    case 0x0057: return DW_AT_PREFIX "call_column";
+    case 0x0058: return DW_AT_PREFIX "call_file";
+    case 0x0059: return DW_AT_PREFIX "call_line";
+    case 0x005a: return DW_AT_PREFIX "description";
+    case 0x005b: return DW_AT_PREFIX "binary_scale";
+    case 0x005c: return DW_AT_PREFIX "decimal_scale";
+    case 0x005d: return DW_AT_PREFIX "small";
+    case 0x005e: return DW_AT_PREFIX "decimal_sign";
+    case 0x005f: return DW_AT_PREFIX "digit_count";
+    case 0x0060: return DW_AT_PREFIX "picture_string";
+    case 0x0061: return DW_AT_PREFIX "mutable";
+    case 0x0062: return DW_AT_PREFIX "threads_scaled";
+    case 0x0063: return DW_AT_PREFIX "explicit";
+    case 0x0064: return DW_AT_PREFIX "object_pointer";
+    case 0x0065: return DW_AT_PREFIX "endianity";
+    case 0x0066: return DW_AT_PREFIX "elemental";
+    case 0x0067: return DW_AT_PREFIX "pure";
+    case 0x0068: return DW_AT_PREFIX "recursive";
+    case 0x2000: return DW_AT_PREFIX "lo_user";
+    case 0x3fff: return DW_AT_PREFIX "hi_user";
+    case 0x2001: return DW_AT_PREFIX "MIPS_fde";
+    case 0x2002: return DW_AT_PREFIX "MIPS_loop_begin";
+    case 0x2003: return DW_AT_PREFIX "MIPS_tail_loop_begin";
+    case 0x2004: return DW_AT_PREFIX "MIPS_epilog_begin";
+    case 0x2005: return DW_AT_PREFIX "MIPS_loop_unroll_factor";
+    case 0x2006: return DW_AT_PREFIX "MIPS_software_pipeline_depth";
+    case 0x2007: return DW_AT_PREFIX "MIPS_linkage_name";
+    case 0x2008: return DW_AT_PREFIX "MIPS_stride";
+    case 0x2009: return DW_AT_PREFIX "MIPS_abstract_name";
+    case 0x200a: return DW_AT_PREFIX "MIPS_clone_origin";
+    case 0x200b: return DW_AT_PREFIX "MIPS_has_inlines";
+    case 0x2101: return DW_AT_PREFIX "sf_names";
+    case 0x2102: return DW_AT_PREFIX "src_info";
+    case 0x2103: return DW_AT_PREFIX "mac_info";
+    case 0x2104: return DW_AT_PREFIX "src_coords";
+    case 0x2105: return DW_AT_PREFIX "body_begin";
+    case 0x2106: return DW_AT_PREFIX "body_end";
+    case 0x2107: return DW_AT_PREFIX "GNU_vector";
+    case 0x2501: return DW_AT_PREFIX "APPLE_repository_file";
+    case 0x2502: return DW_AT_PREFIX "APPLE_repository_type";
+    case 0x2503: return DW_AT_PREFIX "APPLE_repository_name";
+    case 0x2504: return DW_AT_PREFIX "APPLE_repository_specification";
+    case 0x2505: return DW_AT_PREFIX "APPLE_repository_import";
+    case 0x2506: return DW_AT_PREFIX "APPLE_repository_abstract_origin";
+    case DW_AT_APPLE_flags: return DW_AT_PREFIX "APPLE_flags";
+    case DW_AT_APPLE_optimized: return DW_AT_PREFIX "APPLE_optimized";
+    case DW_AT_APPLE_isa: return DW_AT_PREFIX "APPLE_isa";
+    case DW_AT_APPLE_block: return DW_AT_PREFIX "APPLE_block";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_AT constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+const char *
+DW_AT_value_to_englishy_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x0001: return "sibling";
+    case 0x0002: return "location";
+    case 0x0003: return "name";
+    case 0x0009: return "ordering";
+    case 0x000b: return "byte size";
+    case 0x000c: return "bit offset";
+    case 0x000d: return "bit size";
+    case 0x0010: return "stmt list";
+    case 0x0011: return "low pc";
+    case 0x0012: return "high pc";
+    case 0x0013: return "language";
+    case 0x0015: return "discr";
+    case 0x0016: return "discr value";
+    case 0x0017: return "visibility";
+    case 0x0018: return "import";
+    case 0x0019: return "string length";
+    case 0x001a: return "common reference";
+    case 0x001b: return "comp dir";
+    case 0x001c: return "const value";
+    case 0x001d: return "containing type";
+    case 0x001e: return "default value";
+    case 0x0020: return "inline";
+    case 0x0021: return "is optional";
+    case 0x0022: return "lower bound";
+    case 0x0025: return "producer";
+    case 0x0027: return "prototyped";
+    case 0x002a: return "return addr";
+    case 0x002c: return "start scope";
+    case 0x002e: return "bit stride";
+    case 0x002f: return "upper bound";
+    case 0x0031: return "abstract origin";
+    case 0x0032: return "accessibility";
+    case 0x0033: return "address class";
+    case 0x0034: return "artificial";
+    case 0x0035: return "base types";
+    case 0x0036: return "calling convention";
+    case 0x0037: return "count";
+    case 0x0038: return "data member location";
+    case 0x0039: return "decl column";
+    case 0x003a: return "decl file";
+    case 0x003b: return "decl line";
+    case 0x003c: return "declaration";
+    case 0x003d: return "discr list";
+    case 0x003e: return "encoding";
+    case 0x003f: return "external";
+    case 0x0040: return "frame base";
+    case 0x0041: return "friend";
+    case 0x0042: return "identifier case";
+    case 0x0043: return "macro info";
+    case 0x0044: return "namelist item";
+    case 0x0045: return "priority";
+    case 0x0046: return "segment";
+    case 0x0047: return "specification";
+    case 0x0048: return "static link";
+    case 0x0049: return "type";
+    case 0x004a: return "use location";
+    case 0x004b: return "variable parameter";
+    case 0x004c: return "virtuality";
+    case 0x004d: return "vtable elem location";
+    case 0x004e: return "allocated";
+    case 0x004f: return "associated";
+    case 0x0050: return "data location";
+    case 0x0051: return "byte stride";
+    case 0x0052: return "entry pc";
+    case 0x0053: return "use UTF8";
+    case 0x0054: return "extension";
+    case 0x0055: return "ranges";
+    case 0x0056: return "trampoline";
+    case 0x0057: return "call column";
+    case 0x0058: return "call file";
+    case 0x0059: return "call line";
+    case 0x005a: return "description";
+    case 0x005b: return "binary scale";
+    case 0x005c: return "decimal scale";
+    case 0x005d: return "small";
+    case 0x005e: return "decimal sign";
+    case 0x005f: return "digit count";
+    case 0x0060: return "picture string";
+    case 0x0061: return "mutable";
+    case 0x0062: return "threads scaled";
+    case 0x0063: return "explicit";
+    case 0x0064: return "object pointer";
+    case 0x0065: return "endianity";
+    case 0x0066: return "elemental";
+    case 0x0067: return "pure";
+    case 0x0068: return "recursive";
+    case 0x2000: return "lo user";
+    case 0x3fff: return "hi user";
+    case 0x2001: return "MIPS fde";
+    case 0x2002: return "MIPS loop begin";
+    case 0x2003: return "MIPS tail loop begin";
+    case 0x2004: return "MIPS epilog begin";
+    case 0x2005: return "MIPS loop unroll factor";
+    case 0x2006: return "MIPS software pipeline depth";
+    case 0x2007: return "MIPS linkage name";
+    case 0x2008: return "MIPS stride";
+    case 0x2009: return "MIPS abstract name";
+    case 0x200a: return "MIPS clone origin";
+    case 0x200b: return "MIPS has inlines";
+    case 0x2101: return "source file names";
+    case 0x2102: return "source info";
+    case 0x2103: return "macro info";
+    case 0x2104: return "source coordinates";
+    case 0x2105: return "body begin";
+    case 0x2106: return "body end";
+    case 0x2107: return "GNU vector";
+    case 0x2501: return "repository file";
+    case 0x2502: return "repository type";
+    case 0x2503: return "repository name";
+    case 0x2504: return "repository specification";
+    case 0x2505: return "repository import";
+    case 0x2506: return "repository abstract origin";
+    case DW_AT_APPLE_flags: return "Apple gcc compiler flags";
+    case DW_AT_APPLE_optimized: return "APPLE optimized";
+    case DW_AT_APPLE_isa: return "APPLE instruction set architecture";
+    case DW_AT_APPLE_block: return "APPLE block";
+   default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_AT constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+DRC_class
+DW_AT_value_to_class (uint32_t val)
+{
+  switch (val) {
+    case 0x0001: return DRC_REFERENCE;
+    case 0x0002: return DRC_BLOCK | DRC_LOCEXPR | DRC_LOCLISTPTR;
+    case 0x0003: return DRC_STRING;
+    case 0x0009: return DRC_CONSTANT;
+    case 0x000b: return DRC_BLOCK | DRC_CONSTANT | DRC_REFERENCE;
+    case 0x000c: return DRC_BLOCK | DRC_CONSTANT | DRC_REFERENCE;
+    case 0x000d: return DRC_BLOCK | DRC_CONSTANT | DRC_REFERENCE;
+    case 0x0010: return DRC_LINEPTR;
+    case 0x0011: return DRC_ADDRESS;
+    case 0x0012: return DRC_ADDRESS;
+    case 0x0013: return DRC_CONSTANT;
+    case 0x0015: return DRC_REFERENCE;
+    case 0x0016: return DRC_CONSTANT;
+    case 0x0017: return DRC_CONSTANT;
+    case 0x0018: return DRC_REFERENCE;
+    case 0x0019: return DRC_BLOCK | DRC_LOCEXPR | DRC_LOCLISTPTR;
+    case 0x001a: return DRC_REFERENCE;
+    case 0x001b: return DRC_STRING;
+    case 0x001c: return DRC_BLOCK | DRC_CONSTANT | DRC_STRING;
+    case 0x001d: return DRC_REFERENCE;
+    case 0x001e: return DRC_REFERENCE;
+    case 0x0020: return DRC_CONSTANT;
+    case 0x0021: return DRC_FLAG;
+    case 0x0022: return DRC_BLOCK | DRC_CONSTANT | DRC_REFERENCE;
+    case 0x0025: return DRC_STRING;
+    case 0x0027: return DRC_FLAG;
+    case 0x002a: return DRC_BLOCK | DRC_LOCEXPR | DRC_LOCLISTPTR;
+    case 0x002c: return DRC_CONSTANT;
+    case 0x002e: return DRC_CONSTANT;
+    case 0x002f: return DRC_BLOCK | DRC_CONSTANT | DRC_REFERENCE;
+    case 0x0031: return DRC_REFERENCE;
+    case 0x0032: return DRC_CONSTANT;
+    case 0x0033: return DRC_CONSTANT;
+    case 0x0034: return DRC_FLAG;
+    case 0x0035: return DRC_REFERENCE;
+    case 0x0036: return DRC_CONSTANT;
+    case 0x0037: return DRC_BLOCK | DRC_CONSTANT | DRC_REFERENCE;
+    case 0x0038: return DRC_BLOCK | DRC_CONSTANT | DRC_LOCEXPR | DRC_LOCLISTPTR;
+    case 0x0039: return DRC_CONSTANT;
+    case 0x003a: return DRC_CONSTANT;
+    case 0x003b: return DRC_CONSTANT;
+    case 0x003c: return DRC_FLAG;
+    case 0x003d: return DRC_BLOCK;
+    case 0x003e: return DRC_CONSTANT;
+    case 0x003f: return DRC_FLAG;
+    case 0x0040: return DRC_BLOCK | DRC_LOCEXPR | DRC_LOCLISTPTR;
+    case 0x0041: return DRC_REFERENCE;
+    case 0x0042: return DRC_CONSTANT;
+    case 0x0043: return DRC_MACPTR;
+    case 0x0044: return DRC_BLOCK;
+    case 0x0045: return DRC_REFERENCE;
+    case 0x0046: return DRC_BLOCK | DRC_CONSTANT;
+    case 0x0047: return DRC_REFERENCE;
+    case 0x0048: return DRC_BLOCK | DRC_LOCEXPR | DRC_LOCLISTPTR;
+    case 0x0049: return DRC_REFERENCE;
+    case 0x004a: return DRC_BLOCK | DRC_LOCEXPR | DRC_LOCLISTPTR;
+    case 0x004b: return DRC_FLAG;
+    case 0x004c: return DRC_CONSTANT;
+    case 0x004d: return DRC_BLOCK | DRC_LOCEXPR | DRC_LOCLISTPTR;
+    case 0x004e: return DRC_BLOCK | DRC_CONSTANT | DRC_DWARFv3 | DRC_REFERENCE;
+    case 0x004f: return DRC_BLOCK | DRC_CONSTANT | DRC_DWARFv3 | DRC_REFERENCE;
+    case 0x0050: return DRC_BLOCK | DRC_DWARFv3;
+    case 0x0051: return DRC_BLOCK | DRC_CONSTANT | DRC_DWARFv3 | DRC_REFERENCE;
+    case 0x0052: return DRC_ADDRESS | DRC_DWARFv3;
+    case 0x0053: return DRC_DWARFv3 | DRC_FLAG;
+    case 0x0054: return DRC_DWARFv3 | DRC_REFERENCE;
+    case 0x0055: return DRC_DWARFv3 | DRC_RANGELISTPTR;
+    case 0x0056: return DRC_ADDRESS | DRC_DWARFv3 | DRC_FLAG | DRC_REFERENCE | DRC_STRING;
+    case 0x0057: return DRC_CONSTANT | DRC_DWARFv3;
+    case 0x0058: return DRC_CONSTANT | DRC_DWARFv3;
+    case 0x0059: return DRC_CONSTANT | DRC_DWARFv3;
+    case 0x005a: return DRC_DWARFv3 | DRC_STRING;
+    case 0x005b: return DRC_CONSTANT | DRC_DWARFv3;
+    case 0x005c: return DRC_CONSTANT | DRC_DWARFv3;
+    case 0x005d: return DRC_DWARFv3 | DRC_REFERENCE;
+    case 0x005e: return DRC_CONSTANT | DRC_DWARFv3;
+    case 0x005f: return DRC_CONSTANT | DRC_DWARFv3;
+    case 0x0060: return DRC_DWARFv3 | DRC_STRING;
+    case 0x0061: return DRC_DWARFv3 | DRC_FLAG;
+    case 0x0062: return DRC_DWARFv3 | DRC_FLAG;
+    case 0x0063: return DRC_DWARFv3 | DRC_FLAG;
+    case 0x0064: return DRC_DWARFv3 | DRC_REFERENCE;
+    case 0x0065: return DRC_0x65 | DRC_CONSTANT | DRC_DWARFv3;
+    case 0x0066: return DRC_DWARFv3 | DRC_FLAG;
+    case 0x0067: return DRC_DWARFv3 | DRC_FLAG;
+    case 0x0068: return DRC_DWARFv3 | DRC_FLAG;
+    case 0x2000: return 0;
+    case 0x3fff: return 0;
+    case 0x2001: return DRC_VENDOR_MIPS;
+    case 0x2002: return DRC_VENDOR_MIPS;
+    case 0x2003: return DRC_VENDOR_MIPS;
+    case 0x2004: return DRC_VENDOR_MIPS;
+    case 0x2005: return DRC_VENDOR_MIPS;
+    case 0x2006: return DRC_VENDOR_MIPS;
+    case 0x2007: return DRC_STRING | DRC_VENDOR_MIPS;
+    case 0x2008: return DRC_VENDOR_MIPS;
+    case 0x2009: return DRC_VENDOR_MIPS;
+    case 0x200a: return DRC_VENDOR_MIPS;
+    case 0x200b: return DRC_VENDOR_MIPS;
+    default: return 0;
+  }
+}
+
+/* [7.5.4] Figure 19 "Attribute form encodings" (pp. 133-134) in DWARFv3 draft 8 */
+
+const char *
+DW_FORM_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x01: return DW_FORM_PREFIX "addr";
+    case 0x03: return DW_FORM_PREFIX "block2";
+    case 0x04: return DW_FORM_PREFIX "block4";
+    case 0x05: return DW_FORM_PREFIX "data2";
+    case 0x06: return DW_FORM_PREFIX "data4";
+    case 0x07: return DW_FORM_PREFIX "data8";
+    case 0x08: return DW_FORM_PREFIX "string";
+    case 0x09: return DW_FORM_PREFIX "block";
+    case 0x0a: return DW_FORM_PREFIX "block1";
+    case 0x0b: return DW_FORM_PREFIX "data1";
+    case 0x0c: return DW_FORM_PREFIX "flag";
+    case 0x0d: return DW_FORM_PREFIX "sdata";
+    case 0x0e: return DW_FORM_PREFIX "strp";
+    case 0x0f: return DW_FORM_PREFIX "udata";
+    case 0x10: return DW_FORM_PREFIX "ref_addr";
+    case 0x11: return DW_FORM_PREFIX "ref1";
+    case 0x12: return DW_FORM_PREFIX "ref2";
+    case 0x13: return DW_FORM_PREFIX "ref4";
+    case 0x14: return DW_FORM_PREFIX "ref8";
+    case 0x15: return DW_FORM_PREFIX "ref_udata";
+    case 0x16: return DW_FORM_PREFIX "indirect";
+//  case DW_FORM_APPLE_db_str: return DW_FORM_PREFIX "APPLE_db_str";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_FORM constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+const char *
+DW_FORM_value_to_englishy_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x01: return "addr";
+    case 0x03: return "block2";
+    case 0x04: return "block4";
+    case 0x05: return "data2";
+    case 0x06: return "data4";
+    case 0x07: return "data8";
+    case 0x08: return "string";
+    case 0x09: return "block";
+    case 0x0a: return "block1";
+    case 0x0b: return "data1";
+    case 0x0c: return "flag";
+    case 0x0d: return "sdata";
+    case 0x0e: return "strp";
+    case 0x0f: return "udata";
+    case 0x10: return "ref addr";
+    case 0x11: return "ref1";
+    case 0x12: return "ref2";
+    case 0x13: return "ref4";
+    case 0x14: return "ref8";
+    case 0x15: return "ref udata";
+    case 0x16: return "indirect";
+//  case DW_FORM_APPLE_db_str: return "repository str";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_FORM constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+DRC_class
+DW_FORM_value_to_class (uint32_t val)
+{
+  switch (val) {
+    case 0x01: return DRC_ADDRESS;
+    case 0x03: return DRC_BLOCK | DRC_LOCEXPR;
+    case 0x04: return DRC_BLOCK | DRC_LOCEXPR;
+    case 0x05: return DRC_CONSTANT;
+    case 0x06: return DRC_CONSTANT | DRC_LINEPTR | DRC_LOCLISTPTR | DRC_MACPTR | DRC_RANGELISTPTR;
+    case 0x07: return DRC_CONSTANT | DRC_LINEPTR | DRC_LOCLISTPTR | DRC_MACPTR | DRC_RANGELISTPTR;
+    case 0x08: return DRC_STRING;
+    case 0x09: return DRC_BLOCK | DRC_LOCEXPR;
+    case 0x0a: return DRC_BLOCK | DRC_LOCEXPR;
+    case 0x0b: return DRC_CONSTANT;
+    case 0x0c: return DRC_FLAG;
+    case 0x0d: return DRC_CONSTANT;
+    case 0x0e: return DRC_STRING;
+    case 0x0f: return DRC_CONSTANT;
+    case 0x10: return DRC_REFERENCE;
+    case 0x11: return DRC_REFERENCE;
+    case 0x12: return DRC_REFERENCE;
+    case 0x13: return DRC_REFERENCE;
+    case 0x14: return DRC_REFERENCE;
+    case 0x15: return DRC_REFERENCE;
+    case 0x16: return DRC_INDIRECT_SPECIAL;
+    default: return 0;
+  }
+}
+
+/* [7.7.1] Figure 22 "DWARF operation encodings" (pp. 136-139) in DWARFv3 draft 8 */
+
+const char *
+DW_OP_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x03: return "DW_OP_addr";
+    case 0x06: return "DW_OP_deref";
+    case 0x08: return "DW_OP_const1u";
+    case 0x09: return "DW_OP_const1s";
+    case 0x0a: return "DW_OP_const2u";
+    case 0x0b: return "DW_OP_const2s";
+    case 0x0c: return "DW_OP_const4u";
+    case 0x0d: return "DW_OP_const4s";
+    case 0x0e: return "DW_OP_const8u";
+    case 0x0f: return "DW_OP_const8s";
+    case 0x10: return "DW_OP_constu";
+    case 0x11: return "DW_OP_consts";
+    case 0x12: return "DW_OP_dup";
+    case 0x13: return "DW_OP_drop";
+    case 0x14: return "DW_OP_over";
+    case 0x15: return "DW_OP_pick";
+    case 0x16: return "DW_OP_swap";
+    case 0x17: return "DW_OP_rot";
+    case 0x18: return "DW_OP_xderef";
+    case 0x19: return "DW_OP_abs";
+    case 0x1a: return "DW_OP_and";
+    case 0x1b: return "DW_OP_div";
+    case 0x1c: return "DW_OP_minus";
+    case 0x1d: return "DW_OP_mod";
+    case 0x1e: return "DW_OP_mul";
+    case 0x1f: return "DW_OP_neg";
+    case 0x20: return "DW_OP_not";
+    case 0x21: return "DW_OP_or";
+    case 0x22: return "DW_OP_plus";
+    case 0x23: return "DW_OP_plus_uconst";
+    case 0x24: return "DW_OP_shl";
+    case 0x25: return "DW_OP_shr";
+    case 0x26: return "DW_OP_shra";
+    case 0x27: return "DW_OP_xor";
+    case 0x2f: return "DW_OP_skip";
+    case 0x28: return "DW_OP_bra";
+    case 0x29: return "DW_OP_eq";
+    case 0x2a: return "DW_OP_ge";
+    case 0x2b: return "DW_OP_gt";
+    case 0x2c: return "DW_OP_le";
+    case 0x2d: return "DW_OP_lt";
+    case 0x2e: return "DW_OP_ne";
+    case 0x30: return "DW_OP_lit0";
+    case 0x31: return "DW_OP_lit1";
+    case 0x32: return "DW_OP_lit2";
+    case 0x33: return "DW_OP_lit3";
+    case 0x34: return "DW_OP_lit4";
+    case 0x35: return "DW_OP_lit5";
+    case 0x36: return "DW_OP_lit6";
+    case 0x37: return "DW_OP_lit7";
+    case 0x38: return "DW_OP_lit8";
+    case 0x39: return "DW_OP_lit9";
+    case 0x3a: return "DW_OP_lit10";
+    case 0x3b: return "DW_OP_lit11";
+    case 0x3c: return "DW_OP_lit12";
+    case 0x3d: return "DW_OP_lit13";
+    case 0x3e: return "DW_OP_lit14";
+    case 0x3f: return "DW_OP_lit15";
+    case 0x40: return "DW_OP_lit16";
+    case 0x41: return "DW_OP_lit17";
+    case 0x42: return "DW_OP_lit18";
+    case 0x43: return "DW_OP_lit19";
+    case 0x44: return "DW_OP_lit20";
+    case 0x45: return "DW_OP_lit21";
+    case 0x46: return "DW_OP_lit22";
+    case 0x47: return "DW_OP_lit23";
+    case 0x48: return "DW_OP_lit24";
+    case 0x49: return "DW_OP_lit25";
+    case 0x4a: return "DW_OP_lit26";
+    case 0x4b: return "DW_OP_lit27";
+    case 0x4c: return "DW_OP_lit28";
+    case 0x4d: return "DW_OP_lit29";
+    case 0x4e: return "DW_OP_lit30";
+    case 0x4f: return "DW_OP_lit31";
+    case 0x50: return "DW_OP_reg0";
+    case 0x51: return "DW_OP_reg1";
+    case 0x52: return "DW_OP_reg2";
+    case 0x53: return "DW_OP_reg3";
+    case 0x54: return "DW_OP_reg4";
+    case 0x55: return "DW_OP_reg5";
+    case 0x56: return "DW_OP_reg6";
+    case 0x57: return "DW_OP_reg7";
+    case 0x58: return "DW_OP_reg8";
+    case 0x59: return "DW_OP_reg9";
+    case 0x5a: return "DW_OP_reg10";
+    case 0x5b: return "DW_OP_reg11";
+    case 0x5c: return "DW_OP_reg12";
+    case 0x5d: return "DW_OP_reg13";
+    case 0x5e: return "DW_OP_reg14";
+    case 0x5f: return "DW_OP_reg15";
+    case 0x60: return "DW_OP_reg16";
+    case 0x61: return "DW_OP_reg17";
+    case 0x62: return "DW_OP_reg18";
+    case 0x63: return "DW_OP_reg19";
+    case 0x64: return "DW_OP_reg20";
+    case 0x65: return "DW_OP_reg21";
+    case 0x66: return "DW_OP_reg22";
+    case 0x67: return "DW_OP_reg23";
+    case 0x68: return "DW_OP_reg24";
+    case 0x69: return "DW_OP_reg25";
+    case 0x6a: return "DW_OP_reg26";
+    case 0x6b: return "DW_OP_reg27";
+    case 0x6c: return "DW_OP_reg28";
+    case 0x6d: return "DW_OP_reg29";
+    case 0x6e: return "DW_OP_reg30";
+    case 0x6f: return "DW_OP_reg31";
+    case 0x70: return "DW_OP_breg0";
+    case 0x71: return "DW_OP_breg1";
+    case 0x72: return "DW_OP_breg2";
+    case 0x73: return "DW_OP_breg3";
+    case 0x74: return "DW_OP_breg4";
+    case 0x75: return "DW_OP_breg5";
+    case 0x76: return "DW_OP_breg6";
+    case 0x77: return "DW_OP_breg7";
+    case 0x78: return "DW_OP_breg8";
+    case 0x79: return "DW_OP_breg9";
+    case 0x7a: return "DW_OP_breg10";
+    case 0x7b: return "DW_OP_breg11";
+    case 0x7c: return "DW_OP_breg12";
+    case 0x7d: return "DW_OP_breg13";
+    case 0x7e: return "DW_OP_breg14";
+    case 0x7f: return "DW_OP_breg15";
+    case 0x80: return "DW_OP_breg16";
+    case 0x81: return "DW_OP_breg17";
+    case 0x82: return "DW_OP_breg18";
+    case 0x83: return "DW_OP_breg19";
+    case 0x84: return "DW_OP_breg20";
+    case 0x85: return "DW_OP_breg21";
+    case 0x86: return "DW_OP_breg22";
+    case 0x87: return "DW_OP_breg23";
+    case 0x88: return "DW_OP_breg24";
+    case 0x89: return "DW_OP_breg25";
+    case 0x8a: return "DW_OP_breg26";
+    case 0x8b: return "DW_OP_breg27";
+    case 0x8c: return "DW_OP_breg28";
+    case 0x8d: return "DW_OP_breg29";
+    case 0x8e: return "DW_OP_breg30";
+    case 0x8f: return "DW_OP_breg31";
+    case 0x90: return "DW_OP_regx";
+    case 0x91: return "DW_OP_fbreg";
+    case 0x92: return "DW_OP_bregx";
+    case 0x93: return "DW_OP_piece";
+    case 0x94: return "DW_OP_deref_size";
+    case 0x95: return "DW_OP_xderef_size";
+    case 0x96: return "DW_OP_nop";
+    case 0x97: return "DW_OP_push_object_address";
+    case 0x98: return "DW_OP_call2";
+    case 0x99: return "DW_OP_call4";
+    case 0x9a: return "DW_OP_call_ref";
+    case 0xf0: return "DW_OP_APPLE_uninit";
+    case 0xe0: return "DW_OP_lo_user";
+    case 0xff: return "DW_OP_hi_user";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_OP constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+const char *
+DW_OP_value_to_englishy_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x03: return "addr";
+    case 0x06: return "deref";
+    case 0x08: return "const1u";
+    case 0x09: return "const1s";
+    case 0x0a: return "const2u";
+    case 0x0b: return "const2s";
+    case 0x0c: return "const4u";
+    case 0x0d: return "const4s";
+    case 0x0e: return "const8u";
+    case 0x0f: return "const8s";
+    case 0x10: return "constu";
+    case 0x11: return "consts";
+    case 0x12: return "dup";
+    case 0x13: return "drop";
+    case 0x14: return "over";
+    case 0x15: return "pick";
+    case 0x16: return "swap";
+    case 0x17: return "rot";
+    case 0x18: return "xderef";
+    case 0x19: return "abs";
+    case 0x1a: return "and";
+    case 0x1b: return "div";
+    case 0x1c: return "minus";
+    case 0x1d: return "mod";
+    case 0x1e: return "mul";
+    case 0x1f: return "neg";
+    case 0x20: return "not";
+    case 0x21: return "or";
+    case 0x22: return "plus";
+    case 0x23: return "plus uconst";
+    case 0x24: return "shl";
+    case 0x25: return "shr";
+    case 0x26: return "shra";
+    case 0x27: return "xor";
+    case 0x2f: return "skip";
+    case 0x28: return "bra";
+    case 0x29: return "eq";
+    case 0x2a: return "ge";
+    case 0x2b: return "gt";
+    case 0x2c: return "le";
+    case 0x2d: return "lt";
+    case 0x2e: return "ne";
+    case 0x30: return "lit0";
+    case 0x31: return "lit1";
+    case 0x32: return "lit2";
+    case 0x33: return "lit3";
+    case 0x34: return "lit4";
+    case 0x35: return "lit5";
+    case 0x36: return "lit6";
+    case 0x37: return "lit7";
+    case 0x38: return "lit8";
+    case 0x39: return "lit9";
+    case 0x3a: return "lit10";
+    case 0x3b: return "lit11";
+    case 0x3c: return "lit12";
+    case 0x3d: return "lit13";
+    case 0x3e: return "lit14";
+    case 0x3f: return "lit15";
+    case 0x40: return "lit16";
+    case 0x41: return "lit17";
+    case 0x42: return "lit18";
+    case 0x43: return "lit19";
+    case 0x44: return "lit20";
+    case 0x45: return "lit21";
+    case 0x46: return "lit22";
+    case 0x47: return "lit23";
+    case 0x48: return "lit24";
+    case 0x49: return "lit25";
+    case 0x4a: return "lit26";
+    case 0x4b: return "lit27";
+    case 0x4c: return "lit28";
+    case 0x4d: return "lit29";
+    case 0x4e: return "lit30";
+    case 0x4f: return "lit31";
+    case 0x50: return "reg0";
+    case 0x51: return "reg1";
+    case 0x52: return "reg2";
+    case 0x53: return "reg3";
+    case 0x54: return "reg4";
+    case 0x55: return "reg5";
+    case 0x56: return "reg6";
+    case 0x57: return "reg7";
+    case 0x58: return "reg8";
+    case 0x59: return "reg9";
+    case 0x5a: return "reg10";
+    case 0x5b: return "reg11";
+    case 0x5c: return "reg12";
+    case 0x5d: return "reg13";
+    case 0x5e: return "reg14";
+    case 0x5f: return "reg15";
+    case 0x60: return "reg16";
+    case 0x61: return "reg17";
+    case 0x62: return "reg18";
+    case 0x63: return "reg19";
+    case 0x64: return "reg20";
+    case 0x65: return "reg21";
+    case 0x66: return "reg22";
+    case 0x67: return "reg23";
+    case 0x68: return "reg24";
+    case 0x69: return "reg25";
+    case 0x6a: return "reg26";
+    case 0x6b: return "reg27";
+    case 0x6c: return "reg28";
+    case 0x6d: return "reg29";
+    case 0x6e: return "reg30";
+    case 0x6f: return "reg31";
+    case 0x70: return "breg0";
+    case 0x71: return "breg1";
+    case 0x72: return "breg2";
+    case 0x73: return "breg3";
+    case 0x74: return "breg4";
+    case 0x75: return "breg5";
+    case 0x76: return "breg6";
+    case 0x77: return "breg7";
+    case 0x78: return "breg8";
+    case 0x79: return "breg9";
+    case 0x7a: return "breg10";
+    case 0x7b: return "breg11";
+    case 0x7c: return "breg12";
+    case 0x7d: return "breg13";
+    case 0x7e: return "breg14";
+    case 0x7f: return "breg15";
+    case 0x80: return "breg16";
+    case 0x81: return "breg17";
+    case 0x82: return "breg18";
+    case 0x83: return "breg19";
+    case 0x84: return "breg20";
+    case 0x85: return "breg21";
+    case 0x86: return "breg22";
+    case 0x87: return "breg23";
+    case 0x88: return "breg24";
+    case 0x89: return "breg25";
+    case 0x8a: return "breg26";
+    case 0x8b: return "breg27";
+    case 0x8c: return "breg28";
+    case 0x8d: return "breg29";
+    case 0x8e: return "breg30";
+    case 0x8f: return "breg31";
+    case 0x90: return "regx";
+    case 0x91: return "fbreg";
+    case 0x92: return "bregx";
+    case 0x93: return "piece";
+    case 0x94: return "deref size";
+    case 0x95: return "xderef size";
+    case 0x96: return "nop";
+    case 0x97: return "push object address";
+    case 0x98: return "call2";
+    case 0x99: return "call4";
+    case 0x9a: return "call ref";
+    case 0xf0: return "uninitialized";
+    case 0xe0: return "lo user";
+    case 0xff: return "hi user";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_OP constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+DRC_class
+DW_OP_value_to_class (uint32_t val)
+{
+  switch (val) {
+    case 0x03: return DRC_ONEOPERAND;
+    case 0x06: return DRC_ZEROOPERANDS;
+    case 0x08: return DRC_ONEOPERAND;
+    case 0x09: return DRC_ONEOPERAND;
+    case 0x0a: return DRC_ONEOPERAND;
+    case 0x0b: return DRC_ONEOPERAND;
+    case 0x0c: return DRC_ONEOPERAND;
+    case 0x0d: return DRC_ONEOPERAND;
+    case 0x0e: return DRC_ONEOPERAND;
+    case 0x0f: return DRC_ONEOPERAND;
+    case 0x10: return DRC_ONEOPERAND;
+    case 0x11: return DRC_ONEOPERAND;
+    case 0x12: return DRC_ZEROOPERANDS;
+    case 0x13: return DRC_ZEROOPERANDS;
+    case 0x14: return DRC_ZEROOPERANDS;
+    case 0x15: return DRC_ONEOPERAND;
+    case 0x16: return DRC_ZEROOPERANDS;
+    case 0x17: return DRC_ZEROOPERANDS;
+    case 0x18: return DRC_ZEROOPERANDS;
+    case 0x19: return DRC_ZEROOPERANDS;
+    case 0x1a: return DRC_ZEROOPERANDS;
+    case 0x1b: return DRC_ZEROOPERANDS;
+    case 0x1c: return DRC_ZEROOPERANDS;
+    case 0x1d: return DRC_ZEROOPERANDS;
+    case 0x1e: return DRC_ZEROOPERANDS;
+    case 0x1f: return DRC_ZEROOPERANDS;
+    case 0x20: return DRC_ZEROOPERANDS;
+    case 0x21: return DRC_ZEROOPERANDS;
+    case 0x22: return DRC_ZEROOPERANDS;
+    case 0x23: return DRC_ONEOPERAND;
+    case 0x24: return DRC_ZEROOPERANDS;
+    case 0x25: return DRC_ZEROOPERANDS;
+    case 0x26: return DRC_ZEROOPERANDS;
+    case 0x27: return DRC_ZEROOPERANDS;
+    case 0x2f: return DRC_ONEOPERAND;
+    case 0x28: return DRC_ONEOPERAND;
+    case 0x29: return DRC_ZEROOPERANDS;
+    case 0x2a: return DRC_ZEROOPERANDS;
+    case 0x2b: return DRC_ZEROOPERANDS;
+    case 0x2c: return DRC_ZEROOPERANDS;
+    case 0x2d: return DRC_ZEROOPERANDS;
+    case 0x2e: return DRC_ZEROOPERANDS;
+    case 0x30: return DRC_ZEROOPERANDS;
+    case 0x31: return DRC_ZEROOPERANDS;
+    case 0x32: return DRC_ZEROOPERANDS;
+    case 0x33: return DRC_ZEROOPERANDS;
+    case 0x34: return DRC_ZEROOPERANDS;
+    case 0x35: return DRC_ZEROOPERANDS;
+    case 0x36: return DRC_ZEROOPERANDS;
+    case 0x37: return DRC_ZEROOPERANDS;
+    case 0x38: return DRC_ZEROOPERANDS;
+    case 0x39: return DRC_ZEROOPERANDS;
+    case 0x3a: return DRC_ZEROOPERANDS;
+    case 0x3b: return DRC_ZEROOPERANDS;
+    case 0x3c: return DRC_ZEROOPERANDS;
+    case 0x3d: return DRC_ZEROOPERANDS;
+    case 0x3e: return DRC_ZEROOPERANDS;
+    case 0x3f: return DRC_ZEROOPERANDS;
+    case 0x40: return DRC_ZEROOPERANDS;
+    case 0x41: return DRC_ZEROOPERANDS;
+    case 0x42: return DRC_ZEROOPERANDS;
+    case 0x43: return DRC_ZEROOPERANDS;
+    case 0x44: return DRC_ZEROOPERANDS;
+    case 0x45: return DRC_ZEROOPERANDS;
+    case 0x46: return DRC_ZEROOPERANDS;
+    case 0x47: return DRC_ZEROOPERANDS;
+    case 0x48: return DRC_ZEROOPERANDS;
+    case 0x49: return DRC_ZEROOPERANDS;
+    case 0x4a: return DRC_ZEROOPERANDS;
+    case 0x4b: return DRC_ZEROOPERANDS;
+    case 0x4c: return DRC_ZEROOPERANDS;
+    case 0x4d: return DRC_ZEROOPERANDS;
+    case 0x4e: return DRC_ZEROOPERANDS;
+    case 0x4f: return DRC_ZEROOPERANDS;
+    case 0x50: return DRC_ZEROOPERANDS;
+    case 0x51: return DRC_ZEROOPERANDS;
+    case 0x52: return DRC_ZEROOPERANDS;
+    case 0x53: return DRC_ZEROOPERANDS;
+    case 0x54: return DRC_ZEROOPERANDS;
+    case 0x55: return DRC_ZEROOPERANDS;
+    case 0x56: return DRC_ZEROOPERANDS;
+    case 0x57: return DRC_ZEROOPERANDS;
+    case 0x58: return DRC_ZEROOPERANDS;
+    case 0x59: return DRC_ZEROOPERANDS;
+    case 0x5a: return DRC_ZEROOPERANDS;
+    case 0x5b: return DRC_ZEROOPERANDS;
+    case 0x5c: return DRC_ZEROOPERANDS;
+    case 0x5d: return DRC_ZEROOPERANDS;
+    case 0x5e: return DRC_ZEROOPERANDS;
+    case 0x5f: return DRC_ZEROOPERANDS;
+    case 0x60: return DRC_ZEROOPERANDS;
+    case 0x61: return DRC_ZEROOPERANDS;
+    case 0x62: return DRC_ZEROOPERANDS;
+    case 0x63: return DRC_ZEROOPERANDS;
+    case 0x64: return DRC_ZEROOPERANDS;
+    case 0x65: return DRC_ZEROOPERANDS;
+    case 0x66: return DRC_ZEROOPERANDS;
+    case 0x67: return DRC_ZEROOPERANDS;
+    case 0x68: return DRC_ZEROOPERANDS;
+    case 0x69: return DRC_ZEROOPERANDS;
+    case 0x6a: return DRC_ZEROOPERANDS;
+    case 0x6b: return DRC_ZEROOPERANDS;
+    case 0x6c: return DRC_ZEROOPERANDS;
+    case 0x6d: return DRC_ZEROOPERANDS;
+    case 0x6e: return DRC_ZEROOPERANDS;
+    case 0x6f: return DRC_ZEROOPERANDS;
+    case 0x70: return DRC_ONEOPERAND;
+    case 0x71: return DRC_ONEOPERAND;
+    case 0x72: return DRC_ONEOPERAND;
+    case 0x73: return DRC_ONEOPERAND;
+    case 0x74: return DRC_ONEOPERAND;
+    case 0x75: return DRC_ONEOPERAND;
+    case 0x76: return DRC_ONEOPERAND;
+    case 0x77: return DRC_ONEOPERAND;
+    case 0x78: return DRC_ONEOPERAND;
+    case 0x79: return DRC_ONEOPERAND;
+    case 0x7a: return DRC_ONEOPERAND;
+    case 0x7b: return DRC_ONEOPERAND;
+    case 0x7c: return DRC_ONEOPERAND;
+    case 0x7d: return DRC_ONEOPERAND;
+    case 0x7e: return DRC_ONEOPERAND;
+    case 0x7f: return DRC_ONEOPERAND;
+    case 0x80: return DRC_ONEOPERAND;
+    case 0x81: return DRC_ONEOPERAND;
+    case 0x82: return DRC_ONEOPERAND;
+    case 0x83: return DRC_ONEOPERAND;
+    case 0x84: return DRC_ONEOPERAND;
+    case 0x85: return DRC_ONEOPERAND;
+    case 0x86: return DRC_ONEOPERAND;
+    case 0x87: return DRC_ONEOPERAND;
+    case 0x88: return DRC_ONEOPERAND;
+    case 0x89: return DRC_ONEOPERAND;
+    case 0x8a: return DRC_ONEOPERAND;
+    case 0x8b: return DRC_ONEOPERAND;
+    case 0x8c: return DRC_ONEOPERAND;
+    case 0x8d: return DRC_ONEOPERAND;
+    case 0x8e: return DRC_ONEOPERAND;
+    case 0x8f: return DRC_ONEOPERAND;
+    case 0x90: return DRC_ONEOPERAND;
+    case 0x91: return DRC_ONEOPERAND;
+    case 0x92: return DRC_TWOOPERANDS;
+    case 0x93: return DRC_ONEOPERAND;
+    case 0x94: return DRC_ONEOPERAND;
+    case 0x95: return DRC_ONEOPERAND;
+    case 0x96: return DRC_ZEROOPERANDS;
+    case 0x97: return DRC_DWARFv3 | DRC_ZEROOPERANDS;
+    case 0x98: return DRC_DWARFv3 | DRC_ONEOPERAND;
+    case 0x99: return DRC_DWARFv3 | DRC_ONEOPERAND;
+    case 0x9a: return DRC_DWARFv3 | DRC_ONEOPERAND;
+    case 0xf0: return DRC_ZEROOPERANDS; /* DW_OP_APPLE_uninit */
+    case 0xe0: return 0;
+    case 0xff: return 0;
+    default: return 0;
+  }
+}
+
+/* [7.8] Figure 23 "Base type encoding values" (pp. 140-141) in DWARFv3 draft 8 */
+
+const char *
+DW_ATE_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x01: return "DW_ATE_address";
+    case 0x02: return "DW_ATE_boolean";
+    case 0x03: return "DW_ATE_complex_float";
+    case 0x04: return "DW_ATE_float";
+    case 0x05: return "DW_ATE_signed";
+    case 0x06: return "DW_ATE_signed_char";
+    case 0x07: return "DW_ATE_unsigned";
+    case 0x08: return "DW_ATE_unsigned_char";
+    case 0x09: return "DW_ATE_imaginary_float";
+    case 0x80: return "DW_ATE_lo_user";
+    case 0xff: return "DW_ATE_hi_user";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_ATE constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+const char *
+DW_ATE_value_to_englishy_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x01: return "address";
+    case 0x02: return "boolean";
+    case 0x03: return "complex float";
+    case 0x04: return "float";
+    case 0x05: return "signed";
+    case 0x06: return "signed char";
+    case 0x07: return "unsigned";
+    case 0x08: return "unsigned char";
+    case 0x09: return "imaginary float";
+    case 0x80: return "lo user";
+    case 0xff: return "hi user";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_ATE constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+DRC_class
+DW_ATE_value_to_class (uint32_t val)
+{
+  switch (val) {
+    case 0x01: return 0;
+    case 0x02: return 0;
+    case 0x03: return 0;
+    case 0x04: return 0;
+    case 0x05: return 0;
+    case 0x06: return 0;
+    case 0x07: return 0;
+    case 0x08: return 0;
+    case 0x09: return DRC_DWARFv3;
+    case 0x80: return 0;
+    case 0xff: return 0;
+    default: return 0;
+  }
+}
+
+/* [7.9] Figure 24 "Accessibility encodings" (p. 141) in DWARFv3 draft 8 */
+
+const char *
+DW_ACCESS_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x1: return "DW_ACCESS_public";
+    case 0x2: return "DW_ACCESS_protected";
+    case 0x3: return "DW_ACCESS_private";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_ACCESS constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+const char *
+DW_ACCESS_value_to_englishy_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x1: return "public";
+    case 0x2: return "protected";
+    case 0x3: return "private";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_ACCESS constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+DRC_class
+DW_ACCESS_value_to_class (uint32_t val)
+{
+  switch (val) {
+    case 0x1: return 0;
+    case 0x2: return 0;
+    case 0x3: return 0;
+    default: return 0;
+  }
+}
+
+/* [7.10] Figure 25 "Visibility encodings" (p. 142) in DWARFv3 draft 8 */
+
+const char *
+DW_VIS_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x1: return "DW_VIS_local";
+    case 0x2: return "DW_VIS_exported";
+    case 0x3: return "DW_VIS_qualified";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_VIS constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+const char *
+DW_VIS_value_to_englishy_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x1: return "local";
+    case 0x2: return "exported";
+    case 0x3: return "qualified";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_VIS constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+DRC_class
+DW_VIS_value_to_class (uint32_t val)
+{
+  switch (val) {
+    case 0x1: return 0;
+    case 0x2: return 0;
+    case 0x3: return 0;
+    default: return 0;
+  }
+}
+
+/* [7.11] Figure 26 "Virtuality encodings" (p. 142) in DWARFv3 draft 8 */
+
+const char *
+DW_VIRTUALITY_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x0: return "DW_VIRTUALITY_none";
+    case 0x1: return "DW_VIRTUALITY_virtual";
+    case 0x2: return "DW_VIRTUALITY_pure_virtual";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_VIRTUALITY constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+const char *
+DW_VIRTUALITY_value_to_englishy_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x0: return "none";
+    case 0x1: return "virtual";
+    case 0x2: return "pure virtual";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_VIRTUALITY constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+DRC_class
+DW_VIRTUALITY_value_to_class (uint32_t val)
+{
+  switch (val) {
+    case 0x0: return 0;
+    case 0x1: return 0;
+    case 0x2: return 0;
+    default: return 0;
+  }
+}
+
+/* [7.12] Figure 27 "Language encodings" (p. 143) in DWARFv3 draft 8 */
+
+const char *
+DW_LANG_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x0001: return "DW_LANG_C89";
+    case 0x0002: return "DW_LANG_C";
+    case 0x0003: return "DW_LANG_Ada83";
+    case 0x0004: return "DW_LANG_C_plus_plus";
+    case 0x0005: return "DW_LANG_Cobol74";
+    case 0x0006: return "DW_LANG_Cobol85";
+    case 0x0007: return "DW_LANG_Fortran77";
+    case 0x0008: return "DW_LANG_Fortran90";
+    case 0x0009: return "DW_LANG_Pascal83";
+    case 0x000a: return "DW_LANG_Modula2";
+    case 0x000b: return "DW_LANG_Java";
+    case 0x000c: return "DW_LANG_C99";
+    case 0x000d: return "DW_LANG_Ada95";
+    case 0x000e: return "DW_LANG_Fortran95";
+    case 0x000f: return "DW_LANG_PLI";
+    case 0x0010: return "DW_LANG_ObjC";
+    case 0x0011: return "DW_LANG_ObjC_plus_plus";
+    case 0x0012: return "DW_LANG_UPC";
+    case 0x0013: return "DW_LANG_D";
+    case 0x8000: return "DW_LANG_lo_user";
+    case 0x8001: return "DW_LANG_Mips_Assembler";
+    case 0x8765: return "DW_LANG_Upc";
+    case 0xffff: return "DW_LANG_hi_user";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_LANG constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+const char *
+DW_LANG_value_to_englishy_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x0001: return "C89";
+    case 0x0002: return "C";
+    case 0x0003: return "Ada83";
+    case 0x0004: return "C++";
+    case 0x0005: return "Cobol74";
+    case 0x0006: return "Cobol85";
+    case 0x0007: return "Fortran77";
+    case 0x0008: return "Fortran90";
+    case 0x0009: return "Pascal83";
+    case 0x000a: return "Modula2";
+    case 0x000b: return "Java";
+    case 0x000c: return "C99";
+    case 0x000d: return "Ada95";
+    case 0x000e: return "Fortran95";
+    case 0x000f: return "PLI";
+    case 0x0010: return "Objective C";
+    case 0x0011: return "Objective C++";
+    case 0x0012: return "UPC";
+    case 0x0013: return "D";
+    case 0x8000: return "lo user";
+    case 0x8001: return "MIPS Assembler";
+    case 0x8765: return "UPC";
+    case 0xffff: return "hi user";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_LANG constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+DRC_class
+DW_LANG_value_to_class (uint32_t val)
+{
+  switch (val) {
+    case 0x0001: return 0;
+    case 0x0002: return 0;
+    case 0x0003: return 0;
+    case 0x0004: return 0;
+    case 0x0005: return 0;
+    case 0x0006: return 0;
+    case 0x0007: return 0;
+    case 0x0008: return 0;
+    case 0x0009: return 0;
+    case 0x000a: return 0;
+    case 0x000b: return DRC_DWARFv3;
+    case 0x000c: return DRC_DWARFv3;
+    case 0x000d: return DRC_DWARFv3;
+    case 0x000e: return DRC_DWARFv3;
+    case 0x000f: return DRC_DWARFv3;
+    case 0x0010: return DRC_DWARFv3;
+    case 0x0011: return DRC_DWARFv3;
+    case 0x0012: return DRC_DWARFv3;
+    case 0x0013: return DRC_DWARFv3;
+    case 0x8000: return 0;
+    case 0x8001: return 0;
+    case 0x8765: return 0;
+    case 0xffff: return 0;
+    default: return 0;
+  }
+}
+
+/* [7.13], "Address Class Encodings" (p. 144) in DWARFv3 draft 8 */
+
+const char *
+DW_ADDR_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x0: return "DW_ADDR_none";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_ADDR constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+const char *
+DW_ADDR_value_to_englishy_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x0: return "none";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_ADDR constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+DRC_class
+DW_ADDR_value_to_class (uint32_t val)
+{
+  switch (val) {
+    case 0x0: return 0;
+    default: return 0;
+  }
+}
+
+/* [7.14] Figure 28 "Identifier case encodings" (p. 144) in DWARFv3 draft 8 */
+
+const char *
+DW_ID_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x0: return "DW_ID_case_sensitive";
+    case 0x1: return "DW_ID_up_case";
+    case 0x2: return "DW_ID_down_case";
+    case 0x3: return "DW_ID_case_insensitive";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_ID constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+const char *
+DW_ID_value_to_englishy_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x0: return "case sensitive";
+    case 0x1: return "up case";
+    case 0x2: return "down case";
+    case 0x3: return "case insensitive";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_ID constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+DRC_class
+DW_ID_value_to_class (uint32_t val)
+{
+  switch (val) {
+    case 0x0: return 0;
+    case 0x1: return 0;
+    case 0x2: return 0;
+    case 0x3: return 0;
+    default: return 0;
+  }
+}
+
+/* [7.15] Figure 29 "Calling convention encodings" (p. 144) in DWARFv3 draft 8 */
+
+const char *
+DW_CC_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x01: return "DW_CC_normal";
+    case 0x02: return "DW_CC_program";
+    case 0x03: return "DW_CC_nocall";
+    case 0x40: return "DW_CC_lo_user";
+    case 0xff: return "DW_CC_hi_user";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_CC constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+const char *
+DW_CC_value_to_englishy_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x01: return "normal";
+    case 0x02: return "program";
+    case 0x03: return "nocall";
+    case 0x40: return "lo user";
+    case 0xff: return "hi user";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_CC constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+DRC_class
+DW_CC_value_to_class (uint32_t val)
+{
+  switch (val) {
+    case 0x01: return 0;
+    case 0x02: return 0;
+    case 0x03: return 0;
+    case 0x40: return 0;
+    case 0xff: return 0;
+    default: return 0;
+  }
+}
+
+/* [7.16] Figure 30 "Inline encodings" (p. 145) in DWARFv3 draft 8 */
+
+const char *
+DW_INL_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x0: return "DW_INL_not_inlined";
+    case 0x1: return "DW_INL_inlined";
+    case 0x2: return "DW_INL_declared_not_inlined";
+    case 0x3: return "DW_INL_declared_inlined";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_INL constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+const char *
+DW_INL_value_to_englishy_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x0: return "not inlined";
+    case 0x1: return "inlined";
+    case 0x2: return "declared not inlined";
+    case 0x3: return "declared inlined";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_INL constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+DRC_class
+DW_INL_value_to_class (uint32_t val)
+{
+  switch (val) {
+    case 0x0: return 0;
+    case 0x1: return 0;
+    case 0x2: return 0;
+    case 0x3: return 0;
+    default: return 0;
+  }
+}
+
+/* [7.17] Figure 31 "Ordering encodings" (p. 145) in DWARFv3 draft 8 */
+
+const char *
+DW_ORD_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x0: return "DW_ORD_row_major";
+    case 0x1: return "DW_ORD_col_major";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_ORD constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+const char *
+DW_ORD_value_to_englishy_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x0: return "row major";
+    case 0x1: return "col major";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_ORD constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+DRC_class
+DW_ORD_value_to_class (uint32_t val)
+{
+  switch (val) {
+    case 0x0: return 0;
+    case 0x1: return 0;
+    default: return 0;
+  }
+}
+
+/* [7.18] Figure 32 "Discriminant descriptor encodings" (p. 146) in DWARFv3 draft 8 */
+
+const char *
+DW_DSC_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x0: return "DW_DSC_label";
+    case 0x1: return "DW_DSC_range";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_DSC constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+const char *
+DW_DSC_value_to_englishy_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x0: return "label";
+    case 0x1: return "range";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_DSC constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+DRC_class
+DW_DSC_value_to_class (uint32_t val)
+{
+  switch (val) {
+    case 0x0: return 0;
+    case 0x1: return 0;
+    default: return 0;
+  }
+}
+
+/* [7.21] Figure 33 "Line Number Standard Opcode Encodings" (pp. 148-149) in DWARFv3 draft 8 */
+
+const char *
+DW_LNS_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x1: return "DW_LNS_copy";
+    case 0x2: return "DW_LNS_advance_pc";
+    case 0x3: return "DW_LNS_advance_line";
+    case 0x4: return "DW_LNS_set_file";
+    case 0x5: return "DW_LNS_set_column";
+    case 0x6: return "DW_LNS_negate_stmt";
+    case 0x7: return "DW_LNS_set_basic_block";
+    case 0x8: return "DW_LNS_const_add_pc";
+    case 0x9: return "DW_LNS_fixed_advance_pc";
+    case 0xa: return "DW_LNS_set_prologue_end";
+    case 0xb: return "DW_LNS_set_epilogue_begin";
+    case 0xc: return "DW_LNS_set_isa";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_LNS constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+const char *
+DW_LNS_value_to_englishy_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x1: return "copy";
+    case 0x2: return "advance pc";
+    case 0x3: return "advance line";
+    case 0x4: return "set file";
+    case 0x5: return "set column";
+    case 0x6: return "negate stmt";
+    case 0x7: return "set basic block";
+    case 0x8: return "const add pc";
+    case 0x9: return "fixed advance pc";
+    case 0xa: return "set prologue end";
+    case 0xb: return "set epilogue begin";
+    case 0xc: return "set isa";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_LNS constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+DRC_class
+DW_LNS_value_to_class (uint32_t val)
+{
+  switch (val) {
+    case 0x1: return 0;
+    case 0x2: return 0;
+    case 0x3: return 0;
+    case 0x4: return 0;
+    case 0x5: return 0;
+    case 0x6: return 0;
+    case 0x7: return 0;
+    case 0x8: return 0;
+    case 0x9: return 0;
+    case 0xa: return DRC_DWARFv3;
+    case 0xb: return DRC_DWARFv3;
+    case 0xc: return DRC_DWARFv3;
+    default: return 0;
+  }
+}
+
+/* [7.21] Figure 34 "Line Number Extended Opcode Encodings" (p. 149) in DWARFv3 draft 8 */
+
+const char *
+DW_LNE_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x01: return "DW_LNE_end_sequence";
+    case 0x02: return "DW_LNE_set_address";
+    case 0x03: return "DW_LNE_define_file";
+    case 0x80: return "DW_LNE_lo_user";
+    case 0xff: return "DW_LNE_hi_user";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_LNE constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+const char *
+DW_LNE_value_to_englishy_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x01: return "end sequence";
+    case 0x02: return "set address";
+    case 0x03: return "define file";
+    case 0x80: return "lo user";
+    case 0xff: return "hi user";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_LNE constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+DRC_class
+DW_LNE_value_to_class (uint32_t val)
+{
+  switch (val) {
+    case 0x01: return 0;
+    case 0x02: return 0;
+    case 0x03: return 0;
+    case 0x80: return DRC_DWARFv3;
+    case 0xff: return DRC_DWARFv3;
+    default: return 0;
+  }
+}
+
+/* [7.22] Figure 35 "Macinfo Type Encodings" (p. 150) in DWARFv3 draft 8 */
+
+const char *
+DW_MACINFO_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x01: return "DW_MACINFO_define";
+    case 0x02: return "DW_MACINFO_undef";
+    case 0x03: return "DW_MACINFO_start_file";
+    case 0x04: return "DW_MACINFO_end_file";
+    case 0xff: return "DW_MACINFO_vendor_ext";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_MACINFO constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+const char *
+DW_MACINFO_value_to_englishy_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x01: return "define";
+    case 0x02: return "undef";
+    case 0x03: return "start file";
+    case 0x04: return "end file";
+    case 0xff: return "vendor ext";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_MACINFO constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+DRC_class
+DW_MACINFO_value_to_class (uint32_t val)
+{
+  switch (val) {
+    case 0x01: return 0;
+    case 0x02: return 0;
+    case 0x03: return 0;
+    case 0x04: return 0;
+    case 0xff: return 0;
+    default: return 0;
+  }
+}
+
+/* [7.23] Figure 36 "Call frame instruction encodings" (pp. 151-152) in DWARFv3 draft 8 */
+
+const char *
+DW_CFA_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x40: return "DW_CFA_advance_loc";
+    case 0x80: return "DW_CFA_offset";
+    case 0xc0: return "DW_CFA_restore";
+    case 0x00: return "DW_CFA_nop";
+    case 0x01: return "DW_CFA_set_loc";
+    case 0x02: return "DW_CFA_advance_loc1";
+    case 0x03: return "DW_CFA_advance_loc2";
+    case 0x04: return "DW_CFA_advance_loc4";
+    case 0x05: return "DW_CFA_offset_extended";
+    case 0x06: return "DW_CFA_restore_extended";
+    case 0x07: return "DW_CFA_undefined";
+    case 0x08: return "DW_CFA_same_value";
+    case 0x09: return "DW_CFA_register";
+    case 0x0a: return "DW_CFA_remember_state";
+    case 0x0b: return "DW_CFA_restore_state";
+    case 0x0c: return "DW_CFA_def_cfa";
+    case 0x0d: return "DW_CFA_def_cfa_register";
+    case 0x0e: return "DW_CFA_def_cfa_offset";
+    case 0x0f: return "DW_CFA_def_cfa_expression";
+    case 0x10: return "DW_CFA_expression";
+    case 0x11: return "DW_CFA_offset_extended_sf";
+    case 0x12: return "DW_CFA_def_cfa_sf";
+    case 0x13: return "DW_CFA_def_cfa_offset_sf";
+    case 0x1c: return "DW_CFA_lo_user";
+    case 0x3f: return "DW_CFA_hi_user";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_CFA constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+const char *
+DW_CFA_value_to_englishy_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x40: return "advance loc";
+    case 0x80: return "offset";
+    case 0xc0: return "restore";
+    case 0x00: return "nop";
+    case 0x01: return "set loc";
+    case 0x02: return "advance loc1";
+    case 0x03: return "advance loc2";
+    case 0x04: return "advance loc4";
+    case 0x05: return "offset extended";
+    case 0x06: return "restore extended";
+    case 0x07: return "undefined";
+    case 0x08: return "same value";
+    case 0x09: return "register";
+    case 0x0a: return "remember state";
+    case 0x0b: return "restore state";
+    case 0x0c: return "def cfa";
+    case 0x0d: return "def cfa register";
+    case 0x0e: return "def cfa offset";
+    case 0x0f: return "def cfa expression";
+    case 0x10: return "expression";
+    case 0x11: return "offset extended sf";
+    case 0x12: return "def cfa sf";
+    case 0x13: return "def cfa offset sf";
+    case 0x1c: return "lo user";
+    case 0x3f: return "hi user";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_CFA constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+DRC_class
+DW_CFA_value_to_class (uint32_t val)
+{
+  switch (val) {
+    case 0x40: return DRC_ZEROOPERANDS;
+    case 0x80: return DRC_ONEOPERAND | DRC_OPERANDONE_ULEB128_OFFSET;
+    case 0xc0: return DRC_ZEROOPERANDS;
+    case 0x00: return DRC_ZEROOPERANDS;
+    case 0x01: return DRC_ONEOPERAND | DRC_OPERANDONE_ADDRESS;
+    case 0x02: return DRC_ONEOPERAND | DRC_OPERANDONE_1BYTE_DELTA;
+    case 0x03: return DRC_ONEOPERAND | DRC_OPERANDONE_2BYTE_DELTA;
+    case 0x04: return DRC_ONEOPERAND | DRC_OPERANDONE_4BYTE_DELTA;
+    case 0x05: return DRC_OPERANDTWO_ULEB128_OFFSET | DRC_OPERNADONE_ULEB128_REGISTER | DRC_TWOOPERANDS;
+    case 0x06: return DRC_ONEOPERAND | DRC_OPERANDONE_ULEB128_REGISTER;
+    case 0x07: return DRC_ONEOPERAND | DRC_OPERANDONE_ULEB128_REGISTER;
+    case 0x08: return DRC_ONEOPERAND | DRC_OPERANDONE_ULEB128_REGISTER;
+    case 0x09: return DRC_OPERANDONE_ULEB128_REGISTER | DRC_OPERANDTWO_ULEB128_REGISTER | DRC_TWOOPERANDS;
+    case 0x0a: return DRC_ZEROOPERANDS;
+    case 0x0b: return DRC_ZEROOPERANDS;
+    case 0x0c: return DRC_OPERANDONE_ULEB128_REGISTER | DRC_OPERANDTWO_ULEB128_OFFSET | DRC_TWOOPERANDS;
+    case 0x0d: return DRC_ONEOPERAND | DRC_OPERANDONE_ULEB128_REGISTER;
+    case 0x0e: return DRC_ONEOPERAND | DRC_OPERANDONE_ULEB128_OFFSET;
+    case 0x0f: return DRC_DWARFv3 | DRC_ONEOPERAND | DRC_OPERANDONE_BLOCK;
+    case 0x10: return DRC_DWARFv3 | DRC_OPERANDONE_ULEB128_REGISTER | DRC_OPERANDTWO_BLOCK | DRC_TWOOPERANDS;
+    case 0x11: return DRC_DWARFv3 | DRC_OPERANDONE_ULEB128_REGISTER | DRC_OPERANDTWO_SLEB128_OFFSET | DRC_TWOOPERANDS;
+    case 0x12: return DRC_DWARFv3 | DRC_OPERANDONE_ULEB128_REGISTER | DRC_OPERANDTWO_SLEB128_OFFSET | DRC_TWOOPERANDS;
+    case 0x13: return DRC_DWARFv3 | DRC_ONEOPERAND | DRC_OPERANDONE_SLEB128_OFFSET;
+    case 0x1c: return 0;
+    case 0x3f: return 0;
+    default: return 0;
+  }
+}
+
+/* FSF exception handling Pointer-Encoding constants (CFI augmentation) -- "DW_EH_PE_..." in the FSF sources */
+
+const char *
+DW_GNU_EH_PE_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x00: return "DW_GNU_EH_PE_absptr";
+    case 0x01: return "DW_GNU_EH_PE_uleb128";
+    case 0x02: return "DW_GNU_EH_PE_udata2";
+    case 0x03: return "DW_GNU_EH_PE_udata4";
+    case 0x04: return "DW_GNU_EH_PE_udata8";
+    case 0x09: return "DW_GNU_EH_PE_sleb128";
+    case 0x0a: return "DW_GNU_EH_PE_sdata2";
+    case 0x0b: return "DW_GNU_EH_PE_sdata4";
+    case 0x0c: return "DW_GNU_EH_PE_sdata8";
+    case 0x08: return "DW_GNU_EH_PE_signed";
+    case 0x10: return "DW_GNU_EH_PE_pcrel";
+    case 0x20: return "DW_GNU_EH_PE_textrel";
+    case 0x30: return "DW_GNU_EH_PE_datarel";
+    case 0x40: return "DW_GNU_EH_PE_funcrel";
+    case 0x50: return "DW_GNU_EH_PE_aligned";
+    case 0x80: return "DW_GNU_EH_PE_indirect";
+    case 0xff: return "DW_GNU_EH_PE_omit";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_GNU_EH_PE constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+const char *
+DW_GNU_EH_PE_value_to_englishy_name (uint32_t val)
+{
+  static char invalid[100];
+  switch (val) {
+    case 0x00: return "absptr";
+    case 0x01: return "uleb128";
+    case 0x02: return "udata2";
+    case 0x03: return "udata4";
+    case 0x04: return "udata8";
+    case 0x09: return "sleb128";
+    case 0x0a: return "sdata2";
+    case 0x0b: return "sdata4";
+    case 0x0c: return "sdata8";
+    case 0x08: return "signed";
+    case 0x10: return "pcrel";
+    case 0x20: return "textrel";
+    case 0x30: return "datarel";
+    case 0x40: return "funcrel";
+    case 0x50: return "aligned";
+    case 0x80: return "indirect";
+    case 0xff: return "omit";
+    default:
+       snprintf (invalid, sizeof(invalid), "Unknown DW_GNU_EH_PE constant: 0x%x", val);
+       return invalid;
+  }
+}
+
+DRC_class
+DW_GNU_EH_PE_value_to_class (uint32_t val)
+{
+  switch (val) {
+    case 0x00: return DRC_VENDOR_GNU;
+    case 0x01: return DRC_VENDOR_GNU;
+    case 0x02: return DRC_VENDOR_GNU;
+    case 0x03: return DRC_VENDOR_GNU;
+    case 0x04: return DRC_VENDOR_GNU;
+    case 0x09: return DRC_VENDOR_GNU;
+    case 0x0a: return DRC_VENDOR_GNU;
+    case 0x0b: return DRC_VENDOR_GNU;
+    case 0x0c: return DRC_VENDOR_GNU;
+    case 0x08: return DRC_VENDOR_GNU;
+    case 0x10: return DRC_VENDOR_GNU;
+    case 0x20: return DRC_VENDOR_GNU;
+    case 0x30: return DRC_VENDOR_GNU;
+    case 0x40: return DRC_VENDOR_GNU;
+    case 0x50: return DRC_VENDOR_GNU;
+    case 0x80: return DRC_VENDOR_GNU;
+    case 0xff: return DRC_VENDOR_GNU;
+    default: return 0;
+  }
+}
+
+bool
+is_type_tag (uint16_t tag)
+{
+  switch (tag)
+    {
+      case DW_TAG_array_type:
+      case DW_TAG_base_type:
+      case DW_TAG_class_type:
+      case DW_TAG_const_type:
+      case DW_TAG_enumeration_type:
+      case DW_TAG_file_type:
+      case DW_TAG_interface_type:
+      case DW_TAG_packed_type:
+      case DW_TAG_pointer_type:
+      case DW_TAG_ptr_to_member_type:
+      case DW_TAG_reference_type:
+      case DW_TAG_restrict_type:
+      case DW_TAG_set_type:
+      case DW_TAG_shared_type:
+      case DW_TAG_string_type:
+      case DW_TAG_structure_type:
+      case DW_TAG_subrange_type:
+      case DW_TAG_subroutine_type:
+      case DW_TAG_thrown_type:
+      case DW_TAG_union_type:
+      case DW_TAG_unspecified_type:
+      case DW_TAG_volatile_type:
+        return true;
+      default:
+        return false;
+    }
+}
+
+bool
+is_pubtype_tag (uint16_t tag)
+{
+  switch (tag)
+    {
+      case DW_TAG_array_type:
+      case DW_TAG_class_type:
+      case DW_TAG_enumeration_type:
+      case DW_TAG_file_type:
+      case DW_TAG_interface_type:
+      case DW_TAG_set_type:
+      case DW_TAG_string_type:
+      case DW_TAG_structure_type:
+      case DW_TAG_subrange_type:
+      case DW_TAG_subroutine_type:
+      case DW_TAG_thrown_type:
+      case DW_TAG_typedef:
+      case DW_TAG_union_type:
+      case DW_TAG_unspecified_type:
+        return true;
+      default:
+        break;
+    }
+  return false;
+}
+
+DW_TAG_CategoryEnum
+get_tag_category (uint16_t tag)
+{
+  switch (tag)
+    {
+      case DW_TAG_array_type                 : return TagCategoryType;
+      case DW_TAG_class_type                 : return TagCategoryType;
+      case DW_TAG_entry_point                : return TagCategoryProgram;
+      case DW_TAG_enumeration_type           : return TagCategoryType;
+      case DW_TAG_formal_parameter           : return TagCategoryVariable;
+      case DW_TAG_imported_declaration       : return TagCategoryProgram;
+      case DW_TAG_label                      : return TagCategoryProgram;
+      case DW_TAG_lexical_block              : return TagCategoryProgram;
+      case DW_TAG_member                     : return TagCategoryType;
+      case DW_TAG_pointer_type               : return TagCategoryType;
+      case DW_TAG_reference_type             : return TagCategoryType;
+      case DW_TAG_compile_unit               : return TagCategoryProgram;
+      case DW_TAG_string_type                : return TagCategoryType;
+      case DW_TAG_structure_type             : return TagCategoryType;
+      case DW_TAG_subroutine_type            : return TagCategoryType;
+      case DW_TAG_typedef                    : return TagCategoryType;
+      case DW_TAG_union_type                 : return TagCategoryType;
+      case DW_TAG_unspecified_parameters     : return TagCategoryVariable;
+      case DW_TAG_variant                    : return TagCategoryType;
+      case DW_TAG_common_block               : return TagCategoryProgram;
+      case DW_TAG_common_inclusion           : return TagCategoryProgram;
+      case DW_TAG_inheritance                : return TagCategoryType;
+      case DW_TAG_inlined_subroutine         : return TagCategoryProgram;
+      case DW_TAG_module                     : return TagCategoryProgram;
+      case DW_TAG_ptr_to_member_type         : return TagCategoryType;
+      case DW_TAG_set_type                   : return TagCategoryType;
+      case DW_TAG_subrange_type              : return TagCategoryType;
+      case DW_TAG_with_stmt                  : return TagCategoryProgram;
+      case DW_TAG_access_declaration         : return TagCategoryProgram;
+      case DW_TAG_base_type                  : return TagCategoryType;
+      case DW_TAG_catch_block                : return TagCategoryProgram;
+      case DW_TAG_const_type                 : return TagCategoryType;
+      case DW_TAG_constant                   : return TagCategoryVariable;
+      case DW_TAG_enumerator                 : return TagCategoryType;
+      case DW_TAG_file_type                  : return TagCategoryType;
+      case DW_TAG_friend                     : return TagCategoryType;
+      case DW_TAG_namelist                   : return TagCategoryVariable;
+      case DW_TAG_namelist_item              : return TagCategoryVariable;
+      case DW_TAG_packed_type                : return TagCategoryType;
+      case DW_TAG_subprogram                 : return TagCategoryProgram;
+      case DW_TAG_template_type_parameter    : return TagCategoryType;
+      case DW_TAG_template_value_parameter   : return TagCategoryType;
+      case DW_TAG_thrown_type                : return TagCategoryType;
+      case DW_TAG_try_block                  : return TagCategoryProgram;
+      case DW_TAG_variant_part               : return TagCategoryType;
+      case DW_TAG_variable                   : return TagCategoryVariable;
+      case DW_TAG_volatile_type              : return TagCategoryType;
+      case DW_TAG_dwarf_procedure            : return TagCategoryProgram;
+      case DW_TAG_restrict_type              : return TagCategoryType;
+      case DW_TAG_interface_type             : return TagCategoryType;
+      case DW_TAG_namespace                  : return TagCategoryProgram;
+      case DW_TAG_imported_module            : return TagCategoryProgram;
+      case DW_TAG_unspecified_type           : return TagCategoryType;
+      case DW_TAG_partial_unit               : return TagCategoryProgram;
+      case DW_TAG_imported_unit              : return TagCategoryProgram;
+      case DW_TAG_shared_type                : return TagCategoryType;
+      default: break;
+    }
+    return TagCategoryProgram;
+}
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDefines.h b/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
new file mode 100644
index 0000000..dafe8a7
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
@@ -0,0 +1,252 @@
+//===-- DWARFDefines.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_DWARFDefines_h_
+#define liblldb_DWARFDefines_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "lldb/Core/dwarf.h"
+
+/* DWARF constants generated on Wed Sep  7 16:41:50 2005 */
+
+typedef uint32_t DRC_class;          // Holds DRC_* class bitfields
+
+/* [7.5.4] Figure 16 "Tag Encodings" (pp. 125-127) in DWARFv3 draft 8 */
+
+
+enum DW_TAG_Category
+{
+    TagCategoryVariable,
+    TagCategoryType,
+    TagCategoryProgram,
+    kNumTagCategories
+};
+
+typedef enum DW_TAG_Category DW_TAG_CategoryEnum;
+const char *DW_TAG_value_to_name (uint32_t val);
+const char *DW_TAG_value_to_englishy_name (uint32_t val);
+DRC_class DW_TAG_value_to_class (uint32_t val);
+DW_TAG_CategoryEnum get_tag_category (uint16_t tag);
+#define DW_TAG_MAX_NAME_LENGTH 31
+
+
+/* [7.5.4] Figure 17 "Child determination encodings" (p. 128) in DWARFv3 draft 8 */
+
+const char *DW_CHILDREN_value_to_name (uint8_t val);
+const char *DW_CHILDREN_value_to_englishy_name (uint8_t val);
+DRC_class DW_CHILDREN_value_to_class (uint32_t val);
+#define DW_CHILDREN_MAX_NAME_LENGTH 15
+
+
+/* [7.5.4] Figure 18 "Attribute encodings" (pp. 129-132) in DWARFv3 draft 8 */
+
+
+const char *DW_AT_value_to_name (uint32_t val);
+const char *DW_AT_value_to_englishy_name (uint32_t val);
+DRC_class DW_AT_value_to_class (uint32_t val);
+#define DW_AT_MAX_NAME_LENGTH 34
+
+
+/* [7.5.4] Figure 19 "Attribute form encodings" (pp. 133-134) in DWARFv3 draft 8 */
+
+const char *DW_FORM_value_to_name (uint32_t val);
+const char *DW_FORM_value_to_englishy_name (uint32_t val);
+DRC_class DW_FORM_value_to_class (uint32_t val);
+#define DW_FORM_MAX_NAME_LENGTH 17
+
+
+/* [7.7.1] Figure 22 "DWARF operation encodings" (pp. 136-139) in DWARFv3 draft 8 */
+
+const char *DW_OP_value_to_name (uint32_t val);
+const char *DW_OP_value_to_englishy_name (uint32_t val);
+DRC_class DW_OP_value_to_class (uint32_t val);
+#define DW_OP_MAX_NAME_LENGTH 25
+
+
+/* [7.8] Figure 23 "Base type encoding values" (pp. 140-141) in DWARFv3 draft 8 */
+
+const char *DW_ATE_value_to_name (uint32_t val);
+const char *DW_ATE_value_to_englishy_name (uint32_t val);
+DRC_class DW_ATE_value_to_class (uint32_t val);
+#define DW_ATE_MAX_NAME_LENGTH 22
+
+
+/* [7.9] Figure 24 "Accessibility encodings" (p. 141) in DWARFv3 draft 8 */
+
+const char *DW_ACCESS_value_to_name (uint32_t val);
+const char *DW_ACCESS_value_to_englishy_name (uint32_t val);
+DRC_class DW_ACCESS_value_to_class (uint32_t val);
+#define DW_ACCESS_MAX_NAME_LENGTH 19
+
+
+/* [7.10] Figure 25 "Visibility encodings" (p. 142) in DWARFv3 draft 8 */
+
+const char *DW_VIS_value_to_name (uint32_t val);
+const char *DW_VIS_value_to_englishy_name (uint32_t val);
+DRC_class DW_VIS_value_to_class (uint32_t val);
+#define DW_VIS_MAX_NAME_LENGTH 16
+
+
+/* [7.11] Figure 26 "Virtuality encodings" (p. 142) in DWARFv3 draft 8 */
+
+const char *DW_VIRTUALITY_value_to_name (uint32_t val);
+const char *DW_VIRTUALITY_value_to_englishy_name (uint32_t val);
+DRC_class DW_VIRTUALITY_value_to_class (uint32_t val);
+#define DW_VIRTUALITY_MAX_NAME_LENGTH 26
+
+
+/* [7.12] Figure 27 "Language encodings" (p. 143) in DWARFv3 draft 8 */
+
+const char *DW_LANG_value_to_name (uint32_t val);
+const char *DW_LANG_value_to_englishy_name (uint32_t val);
+DRC_class DW_LANG_value_to_class (uint32_t val);
+#define DW_LANG_MAX_NAME_LENGTH 19
+
+
+/* [7.13], "Address Class Encodings" (p. 144) in DWARFv3 draft 8 */
+
+const char *DW_ADDR_value_to_name (uint32_t val);
+const char *DW_ADDR_value_to_englishy_name (uint32_t val);
+DRC_class DW_ADDR_value_to_class (uint32_t val);
+#define DW_ADDR_MAX_NAME_LENGTH 12
+
+
+/* [7.14] Figure 28 "Identifier case encodings" (p. 144) in DWARFv3 draft 8 */
+
+const char *DW_ID_value_to_name (uint32_t val);
+const char *DW_ID_value_to_englishy_name (uint32_t val);
+DRC_class DW_ID_value_to_class (uint32_t val);
+#define DW_ID_MAX_NAME_LENGTH 22
+
+
+/* [7.15] Figure 29 "Calling convention encodings" (p. 144) in DWARFv3 draft 8 */
+
+const char *DW_CC_value_to_name (uint32_t val);
+const char *DW_CC_value_to_englishy_name (uint32_t val);
+DRC_class DW_CC_value_to_class (uint32_t val);
+#define DW_CC_MAX_NAME_LENGTH 13
+
+
+/* [7.16] Figure 30 "Inline encodings" (p. 145) in DWARFv3 draft 8 */
+
+const char *DW_INL_value_to_name (uint32_t val);
+const char *DW_INL_value_to_englishy_name (uint32_t val);
+DRC_class DW_INL_value_to_class (uint32_t val);
+#define DW_INL_MAX_NAME_LENGTH 27
+
+
+/* [7.17] Figure 31 "Ordering encodings" (p. 145) in DWARFv3 draft 8 */
+
+const char *DW_ORD_value_to_name (uint32_t val);
+const char *DW_ORD_value_to_englishy_name (uint32_t val);
+DRC_class DW_ORD_value_to_class (uint32_t val);
+#define DW_ORD_MAX_NAME_LENGTH 16
+
+
+/* [7.18] Figure 32 "Discriminant descriptor encodings" (p. 146) in DWARFv3 draft 8 */
+
+const char *DW_DSC_value_to_name (uint32_t val);
+const char *DW_DSC_value_to_englishy_name (uint32_t val);
+DRC_class DW_DSC_value_to_class (uint32_t val);
+#define DW_DSC_MAX_NAME_LENGTH 12
+
+
+/* [7.21] Figure 33 "Line Number Standard Opcode Encodings" (pp. 148-149) in DWARFv3 draft 8 */
+
+const char *DW_LNS_value_to_name (uint32_t val);
+const char *DW_LNS_value_to_englishy_name (uint32_t val);
+DRC_class DW_LNS_value_to_class (uint32_t val);
+#define DW_LNS_MAX_NAME_LENGTH 25
+
+
+/* [7.21] Figure 34 "Line Number Extended Opcode Encodings" (p. 149) in DWARFv3 draft 8 */
+
+const char *DW_LNE_value_to_name (uint32_t val);
+const char *DW_LNE_value_to_englishy_name (uint32_t val);
+DRC_class DW_LNE_value_to_class (uint32_t val);
+#define DW_LNE_MAX_NAME_LENGTH 19
+
+
+/* [7.22] Figure 35 "Macinfo Type Encodings" (p. 150) in DWARFv3 draft 8 */
+
+const char *DW_MACINFO_value_to_name (uint32_t val);
+const char *DW_MACINFO_value_to_englishy_name (uint32_t val);
+DRC_class DW_MACINFO_value_to_class (uint32_t val);
+#define DW_MACINFO_MAX_NAME_LENGTH 21
+
+
+/* [7.23] Figure 36 "Call frame instruction encodings" (pp. 151-152) in DWARFv3 draft 8 */
+
+const char *DW_CFA_value_to_name (uint32_t val);
+const char *DW_CFA_value_to_englishy_name (uint32_t val);
+DRC_class DW_CFA_value_to_class (uint32_t val);
+#define DW_CFA_MAX_NAME_LENGTH 25
+
+
+/* FSF exception handling Pointer-Encoding constants (CFI augmentation) -- "DW_EH_PE_..." in the FSF sources */
+
+const char *DW_GNU_EH_PE_value_to_name (uint32_t val);
+const char *DW_GNU_EH_PE_value_to_englishy_name (uint32_t val);
+DRC_class DW_GNU_EH_PE_value_to_class (uint32_t val);
+#define DW_GNU_EH_PE_MAX_NAME_LENGTH 21
+
+
+/* These DRC are entirely our own construction,
+    although they are derived from various comments in the DWARF standard.
+    Most of these are not useful to the parser, but the DW_AT and DW_FORM
+    classes should prove to be usable in some fashion.  */
+
+#define DRC_0x65                               0x1
+#define DRC_ADDRESS                            0x2
+#define DRC_BLOCK                              0x4
+#define DRC_CONSTANT                           0x8
+#define DRC_DWARFv3                           0x10
+#define DRC_FLAG                              0x20
+#define DRC_INDIRECT_SPECIAL                  0x40
+#define DRC_LINEPTR                           0x80
+#define DRC_LOCEXPR                          0x100
+#define DRC_LOCLISTPTR                       0x200
+#define DRC_MACPTR                           0x400
+#define DRC_ONEOPERAND                       0x800
+#define DRC_OPERANDONE_1BYTE_DELTA          0x1000
+#define DRC_OPERANDONE_2BYTE_DELTA          0x2000
+#define DRC_OPERANDONE_4BYTE_DELTA          0x4000
+#define DRC_OPERANDONE_ADDRESS              0x8000
+#define DRC_OPERANDONE_BLOCK               0x10000
+#define DRC_OPERANDONE_SLEB128_OFFSET      0x20000
+#define DRC_OPERANDONE_ULEB128_OFFSET      0x40000
+#define DRC_OPERANDONE_ULEB128_REGISTER    0x80000
+#define DRC_OPERANDTWO_BLOCK              0x100000
+#define DRC_OPERANDTWO_SLEB128_OFFSET     0x200000
+#define DRC_OPERANDTWO_ULEB128_OFFSET     0x400000
+#define DRC_OPERANDTWO_ULEB128_REGISTER   0x800000
+#define DRC_OPERNADONE_ULEB128_REGISTER  0x1000000
+#define DRC_RANGELISTPTR                 0x2000000
+#define DRC_REFERENCE                    0x4000000
+#define DRC_STRING                       0x8000000
+#define DRC_TWOOPERANDS                 0x10000000
+#define DRC_VENDOR_GNU                  0x20000000
+#define DRC_VENDOR_MIPS                 0x40000000
+#define DRC_ZEROOPERANDS                0x80000000
+
+bool is_type_tag (uint16_t tag);
+bool is_pubtype_tag (uint16_t tag);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif  // liblldb_DWARFDefines_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
new file mode 100644
index 0000000..d2c137b
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -0,0 +1,571 @@
+//===-- DWARFFormValue.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <assert.h>
+
+#include "lldb/Core/dwarf.h"
+#include "lldb/Core/Stream.h"
+
+#include "DWARFFormValue.h"
+#include "DWARFCompileUnit.h"
+
+class DWARFCompileUnit;
+
+using namespace lldb_private;
+
+DWARFFormValue::DWARFFormValue(dw_form_t form) :
+    m_form(form),
+    m_value()
+{
+}
+
+bool
+DWARFFormValue::ExtractValue(const DataExtractor& data, uint32_t* offset_ptr, const DWARFCompileUnit* cu)
+{
+    bool indirect = false;
+    bool is_block = false;
+    m_value.data = NULL;
+    // Read the value for the form into value and follow and DW_FORM_indirect instances we run into
+    do
+    {
+        indirect = false;
+        switch (m_form)
+        {
+        case DW_FORM_addr:      m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::GetAddressByteSize(cu));  break;
+        case DW_FORM_block2:    m_value.value.uval = data.GetU16(offset_ptr); is_block = true;          break;
+        case DW_FORM_block4:    m_value.value.uval = data.GetU32(offset_ptr); is_block = true;          break;
+        case DW_FORM_data2:     m_value.value.uval = data.GetU16(offset_ptr);                           break;
+        case DW_FORM_data4:     m_value.value.uval = data.GetU32(offset_ptr);                           break;
+        case DW_FORM_data8:     m_value.value.uval = data.GetU64(offset_ptr);                           break;
+        case DW_FORM_string:    m_value.value.cstr = data.GetCStr(offset_ptr);
+                                // Set the string value to also be the data for inlined cstr form values only
+                                // so we can tell the differnence between DW_FORM_string and DW_FORM_strp form
+                                // values;
+                                m_value.data = (uint8_t*)m_value.value.cstr;                            break;
+        case DW_FORM_block:     m_value.value.uval = data.GetULEB128(offset_ptr); is_block = true;      break;
+        case DW_FORM_block1:    m_value.value.uval = data.GetU8(offset_ptr); is_block = true;           break;
+        case DW_FORM_data1:     m_value.value.uval = data.GetU8(offset_ptr);                            break;
+        case DW_FORM_flag:      m_value.value.uval = data.GetU8(offset_ptr);                            break;
+        case DW_FORM_sdata:     m_value.value.sval = data.GetSLEB128(offset_ptr);                       break;
+        case DW_FORM_strp:      m_value.value.uval = data.GetU32(offset_ptr);                           break;
+    //  case DW_FORM_APPLE_db_str:
+        case DW_FORM_udata:     m_value.value.uval = data.GetULEB128(offset_ptr);                       break;
+        case DW_FORM_ref_addr:  m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::GetAddressByteSize(cu));  break;
+        case DW_FORM_ref1:      m_value.value.uval = data.GetU8(offset_ptr);                            break;
+        case DW_FORM_ref2:      m_value.value.uval = data.GetU16(offset_ptr);                           break;
+        case DW_FORM_ref4:      m_value.value.uval = data.GetU32(offset_ptr);                           break;
+        case DW_FORM_ref8:      m_value.value.uval = data.GetU64(offset_ptr);                           break;
+        case DW_FORM_ref_udata: m_value.value.uval = data.GetULEB128(offset_ptr);                       break;
+        case DW_FORM_indirect:
+            m_form = data.GetULEB128(offset_ptr);
+            indirect = true;
+            break;
+
+        default:
+            return false;
+            break;
+        }
+    } while (indirect);
+
+    if (is_block)
+    {
+        m_value.data = data.PeekData(*offset_ptr, m_value.value.uval);
+        if (m_value.data != NULL)
+        {
+            *offset_ptr += m_value.value.uval;
+        }
+    }
+
+    return true;
+}
+
+bool
+DWARFFormValue::SkipValue(const DataExtractor& debug_info_data, uint32_t* offset_ptr, const DWARFCompileUnit* cu) const
+{
+    return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, cu);
+}
+
+bool
+DWARFFormValue::SkipValue(dw_form_t form, const DataExtractor& debug_info_data, uint32_t* offset_ptr, const DWARFCompileUnit* cu)
+{
+    bool indirect = false;
+    do
+    {
+        indirect = false;
+        switch (form)
+        {
+        // Blocks if inlined data that have a length field and the data bytes
+        // inlined in the .debug_info
+        case DW_FORM_block      : { dw_uleb128_t size = debug_info_data.GetULEB128(offset_ptr); *offset_ptr += size; } return true;
+        case DW_FORM_block1     : { dw_uleb128_t size = debug_info_data.GetU8(offset_ptr);          *offset_ptr += size; } return true;
+        case DW_FORM_block2     : { dw_uleb128_t size = debug_info_data.GetU16(offset_ptr);         *offset_ptr += size; } return true;
+        case DW_FORM_block4     : { dw_uleb128_t size = debug_info_data.GetU32(offset_ptr);         *offset_ptr += size; } return true;
+
+        // Inlined NULL terminated C-strings
+        case DW_FORM_string     :
+            debug_info_data.GetCStr(offset_ptr);
+            return true;
+
+        // Compile unit address sized values
+        case DW_FORM_addr       :
+        case DW_FORM_ref_addr   :
+            *offset_ptr += DWARFCompileUnit::GetAddressByteSize(cu);
+            return true;
+
+        // 1 byte values
+        case DW_FORM_data1      :
+        case DW_FORM_flag       :
+        case DW_FORM_ref1       :
+            *offset_ptr += 1;
+            return true;
+
+        // 2 byte values
+        case DW_FORM_data2      :
+        case DW_FORM_ref2       :
+            *offset_ptr += 2;
+            return true;
+
+        // 4 byte values
+        case DW_FORM_strp       :
+        case DW_FORM_data4      :
+        case DW_FORM_ref4       :
+            *offset_ptr += 4;
+            return true;
+
+        // 8 byte values
+        case DW_FORM_data8      :
+        case DW_FORM_ref8       :
+            *offset_ptr += 8;
+            return true;
+
+        // signed or unsigned LEB 128 values
+    //  case DW_FORM_APPLE_db_str:
+        case DW_FORM_sdata      :
+        case DW_FORM_udata      :
+        case DW_FORM_ref_udata  :
+            debug_info_data.Skip_LEB128(offset_ptr);
+            return true;
+
+        case DW_FORM_indirect   :
+            indirect = true;
+            form = debug_info_data.GetULEB128(offset_ptr);
+            break;
+        default:
+            return false;
+        }
+    } while (indirect);
+    return true;
+}
+
+//bool
+//DWARFFormValue::PutUnsigned(dw_form_t form, dw_offset_t offset, uint64_t value, BinaryStreamBuf& out_buff, const DWARFCompileUnit* cu, bool fixup_cu_relative_refs)
+//{
+//  assert(offset != DW_INVALID_OFFSET);
+////    printf("PutUnsigned(%s, 0x%8.8x, 0x%16.16llx, %d)\n", DW_FORM_value_to_name(form), offset, value, fixup_cu_relative_refs);
+//  // Read the value for the form into value and follow and DW_FORM_indirect instances we run into
+//  switch (form)
+//  {
+//  case DW_FORM_addr:      offset = out_buff.PutMax64(offset, value, DWARFCompileUnit::GetAddressByteSize(cu));    break;
+//
+//  case DW_FORM_flag:
+//  case DW_FORM_data1:     offset = out_buff.Put8(offset, value);                  break;
+//  case DW_FORM_data2:     offset = out_buff.Put16(offset, value);                 break;
+//  case DW_FORM_data4:     offset = out_buff.Put32(offset, value);                 break;
+//  case DW_FORM_data8:     offset = out_buff.Put64(offset, value);                 break;
+////    case DW_FORM_udata:     offset = out_buff.Put32_as_ULEB128(offset, value);      break;
+////    case DW_FORM_sdata:     offset = out_buff.Put32_as_SLEB128(offset, value);      break;
+//  case DW_FORM_strp:      offset = out_buff.Put32(offset, value);                 break;
+////    case DW_FORM_APPLE_db_str:
+////                            offset = out_buff.Put32_as_ULEB128(offset, value);      break;
+//
+//  case DW_FORM_ref1:
+//      if (fixup_cu_relative_refs) value -= cu->GetOffset();
+//      offset = out_buff.Put8(offset, value);
+//      break;
+//  case DW_FORM_ref2:
+//      if (fixup_cu_relative_refs) value -= cu->GetOffset();
+//      offset = out_buff.Put16(offset, value);
+//      break;
+//  case DW_FORM_ref4:
+//      if (fixup_cu_relative_refs) value -= cu->GetOffset();
+//      offset = out_buff.Put32(offset, value);
+//      break;
+//  case DW_FORM_ref8:
+//      if (fixup_cu_relative_refs) value -= cu->GetOffset();
+//      offset = out_buff.Put64(offset, value);
+//      break;
+////    case DW_FORM_ref_udata:
+////        if (fixup_cu_relative_refs) value -= cu->GetOffset();
+////        offset = out_buff.Put32_as_ULEB128(offset, value);
+////        break;
+//  case DW_FORM_ref_addr:
+//      // TODO: Add support for DWARF3 if we ever start emitting DWARF3. The DW_FORM_ref_addr
+//      // is always the same size as an address prior to DWARF3, and with DWARF3 or later it
+//      // is 4 hard coded to bytes.
+//      offset = out_buff.PutMax64(offset, value, DWARFCompileUnit::GetAddressByteSize(cu));
+//      break;
+//
+//  default:
+//      return false;
+//  }
+//
+//  return true;
+//}
+
+//bool
+//DWARFFormValue::TransferValue(dw_form_t form, const DataExtractor& data, uint32_t* offset_ptr, const DWARFCompileUnit* cu, BinaryStreamBuf& out_buff)
+//{
+//  DWARFFormValue formValue(form);
+//  if (formValue.ExtractValue(data, offset_ptr,cu))
+//      return TransferValue(formValue, cu, out_buff);
+//  return false;
+//}
+
+//bool
+//DWARFFormValue::TransferValue(const DWARFFormValue& formValue, const DWARFCompileUnit* cu, BinaryStreamBuf& out_buff)
+//{
+//  // Read the value for the form into value and follow and DW_FORM_indirect instances we run into
+//  dw_form_t form = formValue.Form();
+//  switch (form)
+//  {
+//  case DW_FORM_addr:
+//  case DW_FORM_ref_addr:
+//      {
+//          uint8_t addr_size = DWARFCompileUnit::GetAddressByteSize(cu);
+//          out_buff.AppendMax64(formValue.Unsigned(), addr_size);
+//      }
+//      break;
+//
+//  case DW_FORM_block:     out_buff.Append32_as_ULEB128(formValue.Unsigned()); break;
+//  case DW_FORM_block1:    out_buff.Append8(formValue.Unsigned());             break;
+//  case DW_FORM_block2:    out_buff.Append16(formValue.Unsigned());            break;
+//  case DW_FORM_block4:    out_buff.Append32(formValue.Unsigned());            break;
+//
+//  case DW_FORM_flag:
+//  case DW_FORM_data1:     out_buff.Append8(formValue.Unsigned());             break;
+//  case DW_FORM_data2:     out_buff.Append16(formValue.Unsigned());            break;
+//  case DW_FORM_data4:     out_buff.Append32(formValue.Unsigned());            break;
+//  case DW_FORM_data8:     out_buff.Append64(formValue.Unsigned());            break;
+//  case DW_FORM_udata:     out_buff.Append32_as_ULEB128(formValue.Unsigned()); break;
+//  case DW_FORM_sdata:     out_buff.Append32_as_SLEB128(formValue.Signed());   break;
+//
+//  case DW_FORM_string:    out_buff.AppendCStr(formValue.m_value.value.cstr);      break;
+//  case DW_FORM_strp:      out_buff.Append32(formValue.Unsigned());            break;
+////    case DW_FORM_APPLE_db_str:
+////                            out_buff.Append32_as_ULEB128(formValue.Unsigned()); break;
+//
+//  case DW_FORM_ref1:      out_buff.Append8(formValue.Unsigned());             break;
+//  case DW_FORM_ref2:      out_buff.Append16(formValue.Unsigned());            break;
+//  case DW_FORM_ref4:      out_buff.Append32(formValue.Unsigned());            break;
+//  case DW_FORM_ref8:      out_buff.Append64(formValue.Unsigned());            break;
+//  case DW_FORM_ref_udata: out_buff.Append32_as_ULEB128(formValue.Unsigned()); break;
+//
+//  case DW_FORM_indirect:
+//      assert(!"DW_FORM_indirect found in DWARFFormValue::TransferValue() for an extracted form...");
+//      break;
+//
+//  default:
+//      Log::Error("DWARFFormValue::TransferValue() Unrecognized form: 0x%4.4x", form);
+//      return false;
+//      break;
+//  }
+//
+//  const uint8_t* block_data = formValue.BlockData();
+//  if (block_data)
+//      out_buff.AppendData(block_data, formValue.Unsigned());
+//  return true;
+//}
+
+void
+DWARFFormValue::Dump(Stream *s, const DataExtractor* debug_str_data, const DWARFCompileUnit* cu) const
+{
+    uint64_t uvalue = Unsigned();
+    bool cu_relative_offset = false;
+
+    bool verbose = s->GetVerbose();
+
+    switch (m_form)
+    {
+    case DW_FORM_addr:      s->Address(uvalue, sizeof (uint64_t)); break;
+    case DW_FORM_flag:
+    case DW_FORM_data1:     s->PutHex8(uvalue);     break;
+    case DW_FORM_data2:     s->PutHex16(uvalue);        break;
+    case DW_FORM_data4:     s->PutHex32(uvalue);        break;
+    case DW_FORM_data8:     s->PutHex64(uvalue);        break;
+    case DW_FORM_string:    s->QuotedCString(AsCString(NULL));          break;
+    case DW_FORM_block:
+    case DW_FORM_block1:
+    case DW_FORM_block2:
+    case DW_FORM_block4:
+        if (uvalue > 0)
+        {
+            switch (m_form)
+            {
+            case DW_FORM_block:  s->Printf("<0x%llx> ", uvalue);                break;
+            case DW_FORM_block1: s->Printf("<0x%2.2x> ", (uint8_t)uvalue);      break;
+            case DW_FORM_block2: s->Printf("<0x%4.4x> ", (uint16_t)uvalue);     break;
+            case DW_FORM_block4: s->Printf("<0x%8.8x> ", (uint32_t)uvalue);     break;
+            default:                                                            break;
+            }
+
+            const uint8_t* data_ptr = m_value.data;
+            if (data_ptr)
+            {
+                const uint8_t* end_data_ptr = data_ptr + uvalue;    // uvalue contains size of block
+                while (data_ptr < end_data_ptr)
+                {
+                    s->Printf("%2.2x ", *data_ptr);
+                    ++data_ptr;
+                }
+            }
+            else
+                s->PutCString("NULL");
+        }
+        break;
+
+    case DW_FORM_sdata:     s->PutSLEB128(uvalue); break;
+    case DW_FORM_udata:     s->PutULEB128(uvalue); break;
+    case DW_FORM_strp:
+        if (debug_str_data)
+        {
+            if (verbose)
+                s->Printf(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
+
+            const char* dbg_str = AsCString(debug_str_data);
+            if (dbg_str)
+                s->QuotedCString(dbg_str);
+        }
+        else
+        {
+            s->PutHex32(uvalue);
+        }
+        break;
+
+    case DW_FORM_ref_addr:
+    {
+        s->Address(uvalue, sizeof (uint64_t) * 2);
+        break;
+    }
+    case DW_FORM_ref1:      cu_relative_offset = true;  if (verbose) s->Printf("cu + 0x%2.2x", (uint8_t)uvalue); break;
+    case DW_FORM_ref2:      cu_relative_offset = true;  if (verbose) s->Printf("cu + 0x%4.4x", (uint16_t)uvalue); break;
+    case DW_FORM_ref4:      cu_relative_offset = true;  if (verbose) s->Printf("cu + 0x%4.4x", (uint32_t)uvalue); break;
+    case DW_FORM_ref8:      cu_relative_offset = true;  if (verbose) s->Printf("cu + 0x%8.8llx", uvalue); break;
+    case DW_FORM_ref_udata: cu_relative_offset = true;  if (verbose) s->Printf("cu + 0x%llx", uvalue); break;
+
+    // All DW_FORM_indirect attributes should be resolved prior to calling this function
+    case DW_FORM_indirect:  s->PutCString("DW_FORM_indirect"); break;
+    default:
+        s->Printf("DW_FORM(0x%4.4x)", m_form);
+        break;
+    }
+
+    if (cu_relative_offset)
+    {
+        if (verbose)
+            s->PutCString(" => ");
+
+        s->Printf("{0x%8.8x}", (uvalue + (cu ? cu->GetOffset() : 0)));
+    }
+}
+
+const char*
+DWARFFormValue::AsCString(const DataExtractor* debug_str_data_ptr) const
+{
+    if (IsInlinedCStr())
+        return m_value.value.cstr;
+    else if (debug_str_data_ptr)
+        return debug_str_data_ptr->PeekCStr(m_value.value.uval);
+    return NULL;
+}
+
+uint64_t
+DWARFFormValue::Reference(const DWARFCompileUnit* cu) const
+{
+    uint64_t die_offset = m_value.value.uval;
+    switch (m_form)
+    {
+    case DW_FORM_ref1:
+    case DW_FORM_ref2:
+    case DW_FORM_ref4:
+    case DW_FORM_ref8:
+    case DW_FORM_ref_udata:
+        die_offset += (cu ? cu->GetOffset() : 0);
+        break;
+
+    default:
+        break;
+    }
+
+    return die_offset;
+}
+
+//----------------------------------------------------------------------
+// Resolve any compile unit specific references so that we don't need
+// the compile unit at a later time in order to work with the form
+// value.
+//----------------------------------------------------------------------
+bool
+DWARFFormValue::ResolveCompileUnitReferences(const DWARFCompileUnit* cu)
+{
+    switch (m_form)
+    {
+    case DW_FORM_ref1:
+    case DW_FORM_ref2:
+    case DW_FORM_ref4:
+    case DW_FORM_ref8:
+    case DW_FORM_ref_udata:
+        m_value.value.uval += cu->GetOffset();
+        m_form = DW_FORM_ref_addr;
+        return true;
+        break;
+
+    default:
+        break;
+    }
+
+    return false;
+}
+
+const uint8_t*
+DWARFFormValue::BlockData() const
+{
+    if (!IsInlinedCStr())
+        return m_value.data;
+    return NULL;
+}
+
+
+bool
+DWARFFormValue::IsBlockForm(const dw_form_t form)
+{
+    switch (form)
+    {
+    case DW_FORM_block:
+    case DW_FORM_block1:
+    case DW_FORM_block2:
+    case DW_FORM_block4:
+        return true;
+    }
+    return false;
+}
+
+bool
+DWARFFormValue::IsDataForm(const dw_form_t form)
+{
+    switch (form)
+    {
+    case DW_FORM_sdata:
+    case DW_FORM_udata:
+    case DW_FORM_data1:
+    case DW_FORM_data2:
+    case DW_FORM_data4:
+    case DW_FORM_data8:
+        return true;
+    }
+    return false;
+}
+
+int
+DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_value, const DWARFCompileUnit* a_cu, const DWARFCompileUnit* b_cu, const DataExtractor* debug_str_data_ptr)
+{
+    dw_form_t a_form = a_value.Form();
+    dw_form_t b_form = b_value.Form();
+    if (a_form < b_form)
+        return -1;
+    if (a_form > b_form)
+        return 1;
+    switch (a_form)
+    {
+    case DW_FORM_addr:
+    case DW_FORM_flag:
+    case DW_FORM_data1:
+    case DW_FORM_data2:
+    case DW_FORM_data4:
+    case DW_FORM_data8:
+    case DW_FORM_udata:
+    case DW_FORM_ref_addr:
+        {
+            uint64_t a = a_value.Unsigned();
+            uint64_t b = b_value.Unsigned();
+            if (a < b)
+                return -1;
+            if (a > b)
+                return 1;
+            return 0;
+        }
+
+    case DW_FORM_sdata:
+        {
+            int64_t a = a_value.Signed();
+            int64_t b = b_value.Signed();
+            if (a < b)
+                return -1;
+            if (a > b)
+                return 1;
+            return 0;
+        }
+
+    case DW_FORM_string:
+    case DW_FORM_strp:
+        {
+            const char *a_string = a_value.AsCString(debug_str_data_ptr);
+            const char *b_string = b_value.AsCString(debug_str_data_ptr);
+            if (a_string == b_string)
+                return 0;
+            else if (a_string && b_string)
+                return strcmp(a_string, b_string);
+            else if (a_string == NULL)
+                return -1;  // A string is NULL, and B is valid
+            else
+                return 1;   // A string valid, and B is NULL
+        }
+
+
+    case DW_FORM_block:
+    case DW_FORM_block1:
+    case DW_FORM_block2:
+    case DW_FORM_block4:
+        {
+            uint64_t a_len = a_value.Unsigned();
+            uint64_t b_len = b_value.Unsigned();
+            if (a_len < b_len)
+                return -1;
+            if (a_len > b_len)
+                return 1;
+            // The block lengths are the same
+            return memcmp(a_value.BlockData(), b_value.BlockData(), a_value.Unsigned());
+        }
+        break;
+
+    case DW_FORM_ref1:
+    case DW_FORM_ref2:
+    case DW_FORM_ref4:
+    case DW_FORM_ref8:
+    case DW_FORM_ref_udata:
+        {
+            uint64_t a = a_value.Reference(a_cu);
+            uint64_t b = b_value.Reference(b_cu);
+            if (a < b)
+                return -1;
+            if (a > b)
+                return 1;
+            return 0;
+        }
+
+    case DW_FORM_indirect:
+        assert(!"This shouldn't happen after the form has been extracted...");
+        break;
+
+    default:
+        assert(!"Unhandled DW_FORM");
+        break;
+    }
+    return -1;
+}
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
new file mode 100644
index 0000000..3db6366
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
@@ -0,0 +1,81 @@
+//===-- DWARFFormValue.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_DWARFFormValue_h_
+ #define SymbolFileDWARF_DWARFFormValue_h_
+
+#include "SymbolFileDWARF.h"
+#include <stddef.h> // for NULL
+
+class DWARFFormValue
+{
+public:
+    typedef struct ValueTypeTag
+    {
+        ValueTypeTag() :
+            data(NULL),
+            value()
+        {
+            value.uval = 0;
+        }
+
+        union
+        {
+            uint64_t uval;
+            int64_t sval;
+            const char* cstr;
+        } value;
+        const uint8_t* data;
+    } ValueType;
+
+    enum
+    {
+        eValueTypeInvalid = 0,
+        eValueTypeUnsigned,
+        eValueTypeSigned,
+        eValueTypeCStr,
+        eValueTypeBlock
+    };
+
+    DWARFFormValue(dw_form_t form = 0);
+    dw_form_t           Form()  const { return m_form; }
+    void                SetForm(dw_form_t form) { m_form = form; }
+    const ValueType&    Value() const { return m_value; }
+    void                Dump(lldb_private::Stream *s, const lldb_private::DataExtractor* debug_str_data, const DWARFCompileUnit* cu) const;
+    bool                ExtractValue(const lldb_private::DataExtractor& data, uint32_t* offset_ptr, const DWARFCompileUnit* cu);
+    bool                IsInlinedCStr() const { return (m_value.data != NULL) && m_value.data == (uint8_t*)m_value.value.cstr; }
+    const uint8_t*      BlockData() const;
+    uint64_t            Reference(const DWARFCompileUnit* cu) const;
+    bool                ResolveCompileUnitReferences(const DWARFCompileUnit* cu);
+    uint64_t            Unsigned() const { return m_value.value.uval; }
+    void                SetUnsigned(uint64_t uval) { m_value.value.uval = uval; }
+    int64_t             Signed() const { return m_value.value.sval; }
+    void                SetSigned(int64_t sval) { m_value.value.sval = sval; }
+    const char*         AsCString(const lldb_private::DataExtractor* debug_str_data_ptr) const;
+    bool                SkipValue(const lldb_private::DataExtractor& debug_info_data, uint32_t* offset_ptr, const DWARFCompileUnit* cu) const;
+    static bool         SkipValue(const dw_form_t form, const lldb_private::DataExtractor& debug_info_data, uint32_t* offset_ptr, const DWARFCompileUnit* cu);
+//  static bool         TransferValue(dw_form_t form, const lldb_private::DataExtractor& debug_info_data, uint32_t* offset_ptr, const DWARFCompileUnit* cu, BinaryStreamBuf& out_buff);
+//  static bool         TransferValue(const DWARFFormValue& formValue, const DWARFCompileUnit* cu, BinaryStreamBuf& out_buff);
+//  static bool         PutUnsigned(dw_form_t form, dw_offset_t offset, uint64_t value, BinaryStreamBuf& out_buff, const DWARFCompileUnit* cu, bool fixup_cu_relative_refs);
+    static bool         IsBlockForm(const dw_form_t form);
+    static bool         IsDataForm(const dw_form_t form);
+
+    static int          Compare (const DWARFFormValue& a, const DWARFFormValue& b, const DWARFCompileUnit* a_cu, const DWARFCompileUnit* b_cu, const lldb_private::DataExtractor* debug_str_data_ptr);
+protected:
+    dw_form_t   m_form;     // Form for this value
+    ValueType   m_value;    // Contains all data for the form
+};
+
+
+#endif  // SymbolFileDWARF_DWARFFormValue_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp b/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp
new file mode 100644
index 0000000..9229c2a
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp
@@ -0,0 +1,172 @@
+//===-- DWARFLocationDescription.cpp ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFLocationDescription.h"
+#include "DWARFDefines.h"
+#include "lldb/lldb-private.h"
+#include "lldb/Core/Stream.h"
+
+
+using namespace lldb_private;
+
+static int print_dwarf_exp_op (Stream *s, const DataExtractor& data, uint32_t* offset_ptr, int address_size, int dwarf_ref_size);
+
+int
+print_dwarf_expression (Stream *s,
+                        const DataExtractor& data,
+                        int address_size,
+                        int dwarf_ref_size,
+                        bool location_expression)
+{
+    int op_count = 0;
+    uint32_t offset = 0;
+    while (data.ValidOffset(offset))
+    {
+        if (location_expression && op_count > 0)
+        {
+            //  err (baton, "Dwarf location expressions may only have one operand!");
+            return 1;
+        }
+        if (op_count > 0)
+        {
+            s->PutCString(", ");
+        }
+        if (print_dwarf_exp_op (s, data, &offset, address_size, dwarf_ref_size) == 1)
+            return 1;
+        op_count++;
+    }
+
+    return 0;
+}
+
+static int
+print_dwarf_exp_op (Stream *s,
+                    const DataExtractor& data,
+                    uint32_t* offset_ptr,
+                    int address_size,
+                    int dwarf_ref_size)
+{
+    uint8_t opcode = data.GetU8(offset_ptr);
+    DRC_class opcode_class;
+    uint64_t  uint;
+    int64_t   sint;
+
+    int size;
+
+    opcode_class = DW_OP_value_to_class (opcode) & (~DRC_DWARFv3);
+
+    s->Printf("%s ", DW_OP_value_to_englishy_name (opcode));
+
+    /* Does this take zero parameters?  If so we can shortcut this function.  */
+    if (opcode_class == DRC_ZEROOPERANDS)
+        return 0;
+
+    if (opcode_class == DRC_TWOOPERANDS && opcode == DW_OP_bregx)
+    {
+        uint = data.GetULEB128(offset_ptr);
+        sint = data.GetSLEB128(offset_ptr);
+        s->Printf("%llu %lli", uint, sint);
+        return 0;
+    }
+    if (opcode_class != DRC_ONEOPERAND)
+    {
+        s->Printf("UNKNOWN OP %u", opcode);
+        return 1;
+    }
+
+    switch (opcode)
+    {
+        case DW_OP_addr:    size = address_size;    break;
+        case DW_OP_const1u: size = 1;               break;
+        case DW_OP_const1s: size = -1;              break;
+        case DW_OP_const2u: size = 2;               break;
+        case DW_OP_const2s: size = -2;              break;
+        case DW_OP_const4u: size = 4;               break;
+        case DW_OP_const4s: size = -4;              break;
+        case DW_OP_const8u: size = 8;               break;
+        case DW_OP_const8s: size = -8;              break;
+        case DW_OP_constu:  size = 128;             break;
+        case DW_OP_consts:  size = -128;            break;
+        case DW_OP_fbreg:   size = -128;            break;
+        case DW_OP_breg0:
+        case DW_OP_breg1:
+        case DW_OP_breg2:
+        case DW_OP_breg3:
+        case DW_OP_breg4:
+        case DW_OP_breg5:
+        case DW_OP_breg6:
+        case DW_OP_breg7:
+        case DW_OP_breg8:
+        case DW_OP_breg9:
+        case DW_OP_breg10:
+        case DW_OP_breg11:
+        case DW_OP_breg12:
+        case DW_OP_breg13:
+        case DW_OP_breg14:
+        case DW_OP_breg15:
+        case DW_OP_breg16:
+        case DW_OP_breg17:
+        case DW_OP_breg18:
+        case DW_OP_breg19:
+        case DW_OP_breg20:
+        case DW_OP_breg21:
+        case DW_OP_breg22:
+        case DW_OP_breg23:
+        case DW_OP_breg24:
+        case DW_OP_breg25:
+        case DW_OP_breg26:
+        case DW_OP_breg27:
+        case DW_OP_breg28:
+        case DW_OP_breg29:
+        case DW_OP_breg30:
+        case DW_OP_breg31:
+            size = -128; break;
+        case DW_OP_pick:
+            size = 1;       break;
+        case DW_OP_deref_size:
+            size = 1;       break;
+        case DW_OP_xderef_size:
+            size = 1;       break;
+        case DW_OP_plus_uconst:
+            size = 128;     break;
+        case DW_OP_skip:
+            size = -2;      break;
+        case DW_OP_bra:
+            size = -2;      break;
+        case DW_OP_call2:
+            size = 2;       break;
+        case DW_OP_call4:
+            size = 4;       break;
+        case DW_OP_call_ref:
+            size = dwarf_ref_size;  break;
+        case DW_OP_piece:
+            size = 128; break;
+        case DW_OP_regx:
+            size = 128; break;
+        default:
+            s->Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode);
+            return 1;
+    }
+
+    switch (size)
+    {
+    case -1:    sint = (int8_t)     data.GetU8(offset_ptr);     s->Printf("%+lli", sint); break;
+    case -2:    sint = (int16_t)    data.GetU16(offset_ptr);    s->Printf("%+lli", sint); break;
+    case -4:    sint = (int32_t)    data.GetU32(offset_ptr);    s->Printf("%+lli", sint); break;
+    case -8:    sint = (int64_t)    data.GetU64(offset_ptr);    s->Printf("%+lli", sint); break;
+    case -128:  sint = data.GetSLEB128(offset_ptr);         s->Printf("%+lli", sint); break;
+    case 1:     uint = data.GetU8(offset_ptr);                  s->Printf("0x%2.2llx", uint); break;
+    case 2:     uint = data.GetU16(offset_ptr);                 s->Printf("0x%4.4llx", uint); break;
+    case 4:     uint = data.GetU32(offset_ptr);                 s->Printf("0x%8.8llx", uint); break;
+    case 8:     uint = data.GetU64(offset_ptr);                 s->Printf("0x%16.16llx", uint); break;
+    case 128:   uint = data.GetULEB128(offset_ptr);         s->Printf("0x%llx", uint); break;
+    }
+
+    return 0;
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h b/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h
new file mode 100644
index 0000000..413a95c
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h
@@ -0,0 +1,24 @@
+//===-- DWARFLocationDescription.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_DWARFLocationDescription_h_
+#define SymbolFileDWARF_DWARFLocationDescription_h_
+
+#include "SymbolFileDWARF.h"
+
+int
+print_dwarf_expression (lldb_private::Stream *s,
+                        const lldb_private::DataExtractor& data,
+                        int address_size,
+                        int dwarf_ref_size,
+                        bool location_expression);
+
+
+
+#endif  // SymbolFileDWARF_DWARFLocationDescription_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp b/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp
new file mode 100644
index 0000000..6a8359d
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp
@@ -0,0 +1,89 @@
+//===-- DWARFLocationList.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFLocationList.h"
+
+#include "lldb/Core/Stream.h"
+
+#include "DWARFCompileUnit.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFLocationDescription.h"
+
+using namespace lldb_private;
+
+dw_offset_t
+DWARFLocationList::Dump(Stream *s, const DWARFCompileUnit* cu, const DataExtractor& debug_loc_data, dw_offset_t offset)
+{
+    uint64_t start_addr, end_addr;
+    uint32_t addr_size = DWARFCompileUnit::GetAddressByteSize(cu);
+    s->SetAddressByteSize(DWARFCompileUnit::GetAddressByteSize(cu));
+    dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0;
+    while (debug_loc_data.ValidOffset(offset))
+    {
+        start_addr = debug_loc_data.GetMaxU64(&offset,addr_size);
+        end_addr = debug_loc_data.GetMaxU64(&offset,addr_size);
+
+        if (start_addr == 0 && end_addr == 0)
+            break;
+
+        s->PutCString("\n            ");
+        s->Indent();
+        s->AddressRange(start_addr + base_addr, end_addr + base_addr, NULL, ": ");
+        uint32_t loc_length = debug_loc_data.GetU16(&offset);
+
+        DataExtractor locationData(debug_loc_data, offset, loc_length);
+    //  if ( dump_flags & DWARFDebugInfo::eDumpFlag_Verbose ) *ostrm_ptr << " ( ";
+        print_dwarf_expression (s, locationData, addr_size, 4, false);
+        offset += loc_length;
+    }
+
+    return offset;
+}
+
+bool
+DWARFLocationList::Extract(const DataExtractor& debug_loc_data, dw_offset_t* offset_ptr, DataExtractor& location_list_data)
+{
+    // Initialize with no data just in case we don't find anything
+    location_list_data.Clear();
+
+    size_t loc_list_length = Size(debug_loc_data, *offset_ptr);
+    if (loc_list_length > 0)
+    {
+        location_list_data.SetData(debug_loc_data, *offset_ptr, loc_list_length);
+        *offset_ptr += loc_list_length;
+        return true;
+    }
+
+    return false;
+}
+
+size_t
+DWARFLocationList::Size(const DataExtractor& debug_loc_data, dw_offset_t offset)
+{
+    const dw_offset_t debug_loc_offset = offset;
+
+    while (debug_loc_data.ValidOffset(offset))
+    {
+        dw_addr_t start_addr = debug_loc_data.GetAddress(&offset);
+        dw_addr_t end_addr = debug_loc_data.GetAddress(&offset);
+
+        if (start_addr == 0 && end_addr == 0)
+            break;
+
+        uint16_t loc_length = debug_loc_data.GetU16(&offset);
+        offset += loc_length;
+    }
+
+    if (offset > debug_loc_offset)
+        return offset - debug_loc_offset;
+    return 0;
+}
+
+
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h b/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h
new file mode 100644
index 0000000..3efd5c4
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h
@@ -0,0 +1,34 @@
+//===-- DWARFLocationList.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_DWARFLocationList_h_
+#define SymbolFileDWARF_DWARFLocationList_h_
+
+#include "SymbolFileDWARF.h"
+
+class DWARFLocationList
+{
+public:
+    static dw_offset_t
+    Dump (lldb_private::Stream *s,
+          const DWARFCompileUnit* cu,
+          const lldb_private::DataExtractor& debug_loc_data,
+          dw_offset_t offset);
+
+    static bool
+    Extract (const lldb_private::DataExtractor& debug_loc_data,
+             dw_offset_t* offset_ptr,
+             lldb_private::DataExtractor& location_list_data);
+
+    static size_t
+    Size (const lldb_private::DataExtractor& debug_loc_data,
+          dw_offset_t offset);
+
+};
+#endif  // SymbolFileDWARF_DWARFLocationList_h_
diff --git a/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp b/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp
new file mode 100644
index 0000000..571271b
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp
@@ -0,0 +1,207 @@
+//===-- LogChannelDWARF.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LogChannelDWARF.h"
+
+#include "lldb/Core/Args.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamFile.h"
+#include "SymbolFileDWARF.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+// when the one and only logging channel is abled, then this will be non NULL.
+static LogChannelDWARF* g_log_channel = NULL;
+
+LogChannelDWARF::LogChannelDWARF () :
+    LogChannel ()
+{
+}
+
+LogChannelDWARF::~LogChannelDWARF ()
+{
+}
+
+
+void
+LogChannelDWARF::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   LogChannelDWARF::CreateInstance);
+}
+
+void
+LogChannelDWARF::Terminate()
+{
+    PluginManager::UnregisterPlugin (LogChannelDWARF::CreateInstance);
+}
+
+LogChannel*
+LogChannelDWARF::CreateInstance ()
+{
+    return new LogChannelDWARF ();
+}
+
+const char *
+LogChannelDWARF::GetPluginNameStatic()
+{
+    static std::string g_plugin_name;
+    if (g_plugin_name.empty())
+    {
+        g_plugin_name = SymbolFileDWARF::GetPluginNameStatic();
+        g_plugin_name += LogChannel::GetPluginSuffix ();
+    }
+    return g_plugin_name.c_str();
+}
+
+
+const char *
+LogChannelDWARF::GetPluginDescriptionStatic()
+{
+    return "DWARF log channel for debugging plug-in issues.";
+}
+
+const char *
+LogChannelDWARF::GetPluginName()
+{
+    return GetPluginDescriptionStatic();
+}
+
+const char *
+LogChannelDWARF::GetShortPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+LogChannelDWARF::GetPluginVersion()
+{
+    return 1;
+}
+
+
+void
+LogChannelDWARF::GetPluginCommandHelp (const char *command, Stream *strm)
+{
+}
+
+
+Error
+LogChannelDWARF::ExecutePluginCommand (Args &command, Stream *strm)
+{
+    Error error;
+    error.SetErrorStringWithFormat("No commands are supported.\n");
+    return error;
+}
+
+
+Log *
+LogChannelDWARF::EnablePluginLogging (Stream *strm, Args &command)
+{
+    return NULL;
+}
+
+
+void
+LogChannelDWARF::Disable ()
+{
+    g_log_channel = NULL;
+    m_log_sp.reset();
+}
+
+bool
+LogChannelDWARF::Enable
+(
+    StreamSP &log_stream_sp,
+    uint32_t log_options,
+    Stream *feedback_strm,  // Feedback stream for argument errors etc
+    const Args &categories  // The categories to enable within this logging stream, if empty, enable default set
+)
+{
+    Disable ();
+
+    m_log_sp.reset(new Log (log_stream_sp));
+    g_log_channel = this;
+    uint32_t flag_bits = 0;
+    bool got_unknown_category = false;
+    const size_t argc = categories.GetArgumentCount();
+    for (size_t i=0; i<argc; ++i)
+    {
+        const char *arg = categories.GetArgumentAtIndex(i);
+
+        if      (::strcasecmp (arg, "all")        == 0   ) flag_bits |= DWARF_LOG_ALL;
+        else if (::strcasecmp (arg, "info")       == 0   ) flag_bits |= DWARF_LOG_DEBUG_INFO;
+        else if (::strcasecmp (arg, "line")       == 0   ) flag_bits |= DWARF_LOG_DEBUG_LINE;
+        else if (::strcasecmp (arg, "pubnames")   == 0   ) flag_bits |= DWARF_LOG_DEBUG_PUBNAMES;
+        else if (::strcasecmp (arg, "pubtypes")   == 0   ) flag_bits |= DWARF_LOG_DEBUG_PUBTYPES;
+        else if (::strcasecmp (arg, "default")    == 0   ) flag_bits |= DWARF_LOG_DEFAULT;
+        else
+        {
+            feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
+            if (got_unknown_category == false)
+            {
+                got_unknown_category = true;
+                ListCategories (feedback_strm);
+            }
+        }
+    }
+    if (flag_bits == 0)
+        flag_bits = DWARF_LOG_DEFAULT;
+    m_log_sp->GetMask().SetAllFlagBits(flag_bits);
+    m_log_sp->GetOptions().SetAllFlagBits(log_options);
+    return m_log_sp.get() != NULL;
+}
+
+void
+LogChannelDWARF::ListCategories (Stream *strm)
+{
+    strm->Printf("Logging categories for '%s':\n"
+        "   all - turn on all available logging categories\n"
+        "   info - log the parsing if .debug_info\n"
+        "   line - log the parsing if .debug_line\n"
+        "   pubnames - log the parsing if .debug_pubnames\n"
+        "   pubtypes - log the parsing if .debug_pubtypes\n\n",
+        SymbolFileDWARF::GetPluginNameStatic());
+}
+
+Log *
+LogChannelDWARF::GetLog ()
+{
+    if (g_log_channel)
+        return g_log_channel->m_log_sp.get();
+    else
+        return NULL;
+}
+
+Log *
+LogChannelDWARF::GetLogIfAll (uint32_t mask)
+{
+    Log *log = GetLog();
+    if (log)
+        if (log->GetMask().IsSet(mask))
+            return log;
+    return NULL;
+}
+
+
+void
+LogChannelDWARF::LogIf (uint32_t mask, const char *format, ...)
+{
+    if (g_log_channel)
+    {
+        LogSP log_sp(g_log_channel->m_log_sp);
+        va_list args;
+        va_start (args, format);
+        log_sp->VAPrintf (format, args);
+        va_end (args);
+    }
+}
diff --git a/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h b/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h
new file mode 100644
index 0000000..943d1da
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h
@@ -0,0 +1,91 @@
+//===-- LogChannelDWARF.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_LogChannelDWARF_h_
+#define liblldb_LogChannelDWARF_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+
+// Project includes
+#include "lldb/Core/Log.h"
+
+#define DWARF_LOG_VERBOSE           (1u << 0)
+#define DWARF_LOG_DEBUG_INFO        (1u << 1)
+#define DWARF_LOG_DEBUG_LINE        (1u << 2)
+#define DWARF_LOG_DEBUG_PUBNAMES    (1u << 3)
+#define DWARF_LOG_DEBUG_PUBTYPES    (1u << 4)
+#define DWARF_LOG_ALL               (UINT32_MAX)
+#define DWARF_LOG_DEFAULT           (DWARF_LOG_DEBUG_INFO)
+
+class LogChannelDWARF : public lldb_private::LogChannel
+{
+public:
+    LogChannelDWARF ();
+
+    virtual
+    ~LogChannelDWARF ();
+
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static const char *
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb_private::LogChannel *
+    CreateInstance ();
+
+    virtual const char *
+    GetPluginName();
+
+    virtual const char *
+    GetShortPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+    virtual void
+    GetPluginCommandHelp (const char *command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Error
+    ExecutePluginCommand (lldb_private::Args &command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Log *
+    EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
+
+    virtual void
+    Disable ();
+
+    virtual bool
+    Enable (lldb::StreamSP &log_stream_sp,
+            uint32_t log_options,
+            lldb_private::Stream *feedback_strm,      // Feedback stream for argument errors etc
+            const lldb_private::Args &categories);    // The categories to enable within this logging stream, if empty, enable default set
+
+    virtual void
+    ListCategories (lldb_private::Stream *strm);
+
+    static lldb_private::Log *
+    GetLog ();
+
+    static lldb_private::Log *
+    GetLogIfAll (uint32_t mask);
+
+    static void
+    LogIf (uint32_t mask, const char *format, ...);
+};
+
+#endif  // liblldb_LogChannelDWARF_h_
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
new file mode 100644
index 0000000..ffee695
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -0,0 +1,3615 @@
+//===-- SymbolFileDWARF.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolFileDWARF.h"
+
+// Other libraries and framework includes
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Specifiers.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Core/Value.h"
+
+#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/LineTable.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/VariableList.h"
+
+#include "DWARFCompileUnit.h"
+#include "DWARFDebugAbbrev.h"
+#include "DWARFDebugAranges.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFDebugInfoEntry.h"
+#include "DWARFDebugLine.h"
+#include "DWARFDebugPubnames.h"
+#include "DWARFDebugRanges.h"
+#include "DWARFDIECollection.h"
+#include "DWARFFormValue.h"
+#include "DWARFLocationList.h"
+#include "LogChannelDWARF.h"
+
+#include <map>
+
+#define DIE_IS_BEING_PARSED ((void*)1)
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+static const ConstString&
+GetSectionNameDebugInfo()
+{
+    static const ConstString g_sect_name("__debug_info");
+    return g_sect_name;
+}
+
+static const ConstString&
+GetSectionNameDebugAbbrev()
+{
+    static const ConstString g_sect_name ("__debug_abbrev");
+    return g_sect_name;
+}
+
+static const ConstString&
+GetSectionNameDebugAranges()
+{
+    static const ConstString g_sect_name ("__debug_aranges");
+    return g_sect_name;
+}
+
+static const ConstString&
+GetSectionNameDebugFrame()
+{
+    static const ConstString g_sect_name ("__debug_frame");
+    return g_sect_name;
+}
+
+static const ConstString&
+GetSectionNameDebugLine()
+{
+    static const ConstString g_sect_name ("__debug_line");
+    return g_sect_name;
+}
+
+static const ConstString&
+GetSectionNameDebugLoc()
+{
+    static const ConstString g_sect_name ("__debug_loc");
+    return g_sect_name;
+}
+
+static const ConstString&
+GetSectionNameDebugMacInfo()
+{
+    static const ConstString g_sect_name ("__debug_macinfo");
+    return g_sect_name;
+}
+
+static const ConstString&
+GetSectionNameDebugPubNames()
+{
+    static const ConstString g_sect_name ("__debug_pubnames");
+    return g_sect_name;
+}
+
+static const ConstString&
+GetSectionNameDebugPubTypes()
+{
+    static const ConstString g_sect_name ("__debug_pubtypes");
+    return g_sect_name;
+}
+
+static const ConstString&
+GetSectionNameDebugRanges()
+{
+    static const ConstString g_sect_name ("__debug_ranges");
+    return g_sect_name;
+}
+
+static const ConstString&
+GetSectionNameDebugStr()
+{
+    static const ConstString g_sect_name ("__debug_str");
+    return g_sect_name;
+}
+
+static uint32_t
+DwarfToClangAccessibility (uint32_t dwarf_accessibility)
+{
+    switch (dwarf_accessibility)
+    {
+        case DW_ACCESS_public:
+            return clang::AS_public;
+        case DW_ACCESS_private:
+            return clang::AS_private;
+        case DW_ACCESS_protected:
+            return clang::AS_protected;
+        default:
+            return clang::AS_none;
+    }
+}
+
+void
+SymbolFileDWARF::Initialize()
+{
+    LogChannelDWARF::Initialize();
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance);
+}
+
+void
+SymbolFileDWARF::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+    LogChannelDWARF::Initialize();
+}
+
+
+const char *
+SymbolFileDWARF::GetPluginNameStatic()
+{
+    return "symbol-file.dwarf2";
+}
+
+const char *
+SymbolFileDWARF::GetPluginDescriptionStatic()
+{
+    return "DWARF and DWARF3 debug symbol file reader.";
+}
+
+
+SymbolFile*
+SymbolFileDWARF::CreateInstance (ObjectFile* obj_file)
+{
+    return new SymbolFileDWARF(obj_file);
+}
+
+//----------------------------------------------------------------------
+// Gets the first parent that is a lexical block, function or inlined
+// subroutine, or compile unit.
+//----------------------------------------------------------------------
+static const DWARFDebugInfoEntry *
+GetParentSymbolContextDIE(const DWARFDebugInfoEntry *child_die)
+{
+    const DWARFDebugInfoEntry *die;
+    for (die = child_die->GetParent(); die != NULL; die = die->GetParent())
+    {
+        dw_tag_t tag = die->Tag();
+
+        switch (tag)
+        {
+        case DW_TAG_compile_unit:
+        case DW_TAG_subprogram:
+        case DW_TAG_inlined_subroutine:
+        case DW_TAG_lexical_block:
+            return die;
+        }
+    }
+    return NULL;
+}
+
+
+SymbolFileDWARF::SymbolFileDWARF(ObjectFile* ofile) :
+    SymbolFile(ofile),
+    m_flags(),
+    m_data_debug_abbrev(),
+    m_data_debug_aranges(),
+    m_data_debug_frame(),
+    m_data_debug_info(),
+    m_data_debug_line(),
+    m_data_debug_loc(),
+    m_data_debug_macinfo(),
+    m_data_debug_pubnames(),
+    m_data_debug_pubtypes(),
+    m_data_debug_ranges(),
+    m_data_debug_str(),
+    m_abbr(),
+    m_aranges(),
+    m_info(),
+    m_line(),
+    m_name_to_function_die(),
+    m_name_to_inlined_die(),
+    m_name_to_global_die(),
+    m_name_to_type_die(),
+    m_indexed(false),
+//    m_pubnames(),
+//    m_pubtypes(),
+//    m_pubbasetypes(),
+    m_ranges()//,
+//  m_type_fixups(),
+//  m_indirect_fixups()
+{
+}
+
+SymbolFileDWARF::~SymbolFileDWARF()
+{
+}
+
+bool
+SymbolFileDWARF::SupportedVersion(uint16_t version)
+{
+    return version == 2 || version == 3;
+}
+
+uint32_t
+SymbolFileDWARF::GetAbilities ()
+{
+    uint32_t abilities = 0;
+    if (m_obj_file != NULL)
+    {
+        const Section* section = NULL;
+        const SectionList *section_list = m_obj_file->GetSectionList();
+        if (section_list == NULL)
+            return 0;
+
+        uint64_t debug_abbrev_file_size = 0;
+        uint64_t debug_aranges_file_size = 0;
+        uint64_t debug_frame_file_size = 0;
+        uint64_t debug_info_file_size = 0;
+        uint64_t debug_line_file_size = 0;
+        uint64_t debug_loc_file_size = 0;
+        uint64_t debug_macinfo_file_size = 0;
+        uint64_t debug_pubnames_file_size = 0;
+        uint64_t debug_pubtypes_file_size = 0;
+        uint64_t debug_ranges_file_size = 0;
+        uint64_t debug_str_file_size = 0;
+
+        static ConstString g_dwarf_section_name ("__DWARF");
+
+        section = section_list->FindSectionByName(g_dwarf_section_name).get();
+        
+        if (section)
+            section->MemoryMapSectionDataFromObjectFile(m_obj_file, m_dwarf_data);
+        
+        section = section_list->FindSectionByName (GetSectionNameDebugInfo()).get();
+        if (section != NULL)
+        {
+            debug_info_file_size = section->GetByteSize();
+
+            section = section_list->FindSectionByName (GetSectionNameDebugAbbrev()).get();
+            if (section)
+                debug_abbrev_file_size = section->GetByteSize();
+            else
+                m_flags.Set (flagsGotDebugAbbrevData);
+
+            section = section_list->FindSectionByName (GetSectionNameDebugAranges()).get();
+            if (section)
+                debug_aranges_file_size = section->GetByteSize();
+            else
+                m_flags.Set (flagsGotDebugArangesData);
+
+            section = section_list->FindSectionByName (GetSectionNameDebugFrame()).get();
+            if (section)
+                debug_frame_file_size = section->GetByteSize();
+            else
+                m_flags.Set (flagsGotDebugFrameData);
+
+            section = section_list->FindSectionByName (GetSectionNameDebugLine()).get();
+            if (section)
+                debug_line_file_size = section->GetByteSize();
+            else
+                m_flags.Set (flagsGotDebugLineData);
+
+            section = section_list->FindSectionByName (GetSectionNameDebugLoc()).get();
+            if (section)
+                debug_loc_file_size = section->GetByteSize();
+            else
+                m_flags.Set (flagsGotDebugLocData);
+
+            section = section_list->FindSectionByName (GetSectionNameDebugMacInfo()).get();
+            if (section)
+                debug_macinfo_file_size = section->GetByteSize();
+            else
+                m_flags.Set (flagsGotDebugMacInfoData);
+
+            section = section_list->FindSectionByName (GetSectionNameDebugPubNames()).get();
+            if (section)
+                debug_pubnames_file_size = section->GetByteSize();
+            else
+                m_flags.Set (flagsGotDebugPubNamesData);
+
+            section = section_list->FindSectionByName (GetSectionNameDebugPubTypes()).get();
+            if (section)
+                debug_pubtypes_file_size = section->GetByteSize();
+            else
+                m_flags.Set (flagsGotDebugPubTypesData);
+
+            section = section_list->FindSectionByName (GetSectionNameDebugRanges()).get();
+            if (section)
+                debug_ranges_file_size = section->GetByteSize();
+            else
+                m_flags.Set (flagsGotDebugRangesData);
+
+            section = section_list->FindSectionByName (GetSectionNameDebugStr()).get();
+            if (section)
+                debug_str_file_size = section->GetByteSize();
+            else
+                m_flags.Set (flagsGotDebugStrData);
+        }
+
+        if (debug_abbrev_file_size > 0 && debug_info_file_size > 0)
+            abilities |= CompileUnits | Functions | Blocks | GlobalVariables | LocalVariables | VariableTypes;
+
+        if (debug_line_file_size > 0)
+            abilities |= LineTables;
+
+        if (debug_aranges_file_size > 0)
+            abilities |= AddressAcceleratorTable;
+
+        if (debug_pubnames_file_size > 0)
+            abilities |= FunctionAcceleratorTable;
+
+        if (debug_pubtypes_file_size > 0)
+            abilities |= TypeAcceleratorTable;
+
+        if (debug_macinfo_file_size > 0)
+            abilities |= MacroInformation;
+
+        if (debug_frame_file_size > 0)
+            abilities |= CallFrameInformation;
+    }
+    return abilities;
+}
+
+const DataExtractor&
+SymbolFileDWARF::GetCachedSectionData (uint32_t got_flag, const ConstString &section_name, DataExtractor &data)
+{
+    if (m_flags.IsClear (got_flag))
+    {
+        m_flags.Set (got_flag);
+        const SectionList *section_list = m_obj_file->GetSectionList();
+        if (section_list)
+        {
+            Section *section = section_list->FindSectionByName (section_name).get();
+            if (section )
+            {
+                // See if we memory mapped the DWARF segment?
+                if (m_dwarf_data.GetByteSize())
+                {
+                    data.SetData(m_dwarf_data, section->GetOffset (), section->GetByteSize());
+                }
+                else
+                {
+                    if (section->ReadSectionDataFromObjectFile(m_obj_file, data) == 0)
+                        data.Clear();
+                }
+            }
+        }
+    }
+    return data;
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_debug_abbrev_data()
+{
+    return GetCachedSectionData (flagsGotDebugAbbrevData, GetSectionNameDebugAbbrev(), m_data_debug_abbrev);
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_debug_aranges_data()
+{
+    return GetCachedSectionData (flagsGotDebugArangesData, GetSectionNameDebugAranges(), m_data_debug_aranges);
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_debug_frame_data()
+{
+    return GetCachedSectionData (flagsGotDebugFrameData, GetSectionNameDebugFrame(), m_data_debug_frame);
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_debug_info_data()
+{
+    return GetCachedSectionData (flagsGotDebugInfoData, GetSectionNameDebugInfo(), m_data_debug_info);
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_debug_line_data()
+{
+    return GetCachedSectionData (flagsGotDebugLineData, GetSectionNameDebugLine(), m_data_debug_line);
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_debug_loc_data()
+{
+    return GetCachedSectionData (flagsGotDebugLocData, GetSectionNameDebugLoc(), m_data_debug_loc);
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_debug_macinfo_data()
+{
+    return GetCachedSectionData (flagsGotDebugMacInfoData, GetSectionNameDebugMacInfo(), m_data_debug_macinfo);
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_debug_pubnames_data()
+{
+    return GetCachedSectionData (flagsGotDebugPubNamesData, GetSectionNameDebugPubNames(), m_data_debug_pubnames);
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_debug_pubtypes_data()
+{
+    return GetCachedSectionData (flagsGotDebugPubTypesData, GetSectionNameDebugPubTypes(), m_data_debug_pubtypes);
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_debug_ranges_data()
+{
+    return GetCachedSectionData (flagsGotDebugRangesData, GetSectionNameDebugRanges(), m_data_debug_ranges);
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_debug_str_data()
+{
+    return GetCachedSectionData (flagsGotDebugStrData, GetSectionNameDebugStr(), m_data_debug_str);
+}
+
+
+DWARFDebugAbbrev*
+SymbolFileDWARF::DebugAbbrev()
+{
+    if (m_abbr.get() == NULL)
+    {
+        const DataExtractor &debug_abbrev_data = get_debug_abbrev_data();
+        if (debug_abbrev_data.GetByteSize() > 0)
+        {
+            m_abbr.reset(new DWARFDebugAbbrev());
+            if (m_abbr.get())
+                m_abbr->Parse(debug_abbrev_data);
+        }
+    }
+    return m_abbr.get();
+}
+
+const DWARFDebugAbbrev*
+SymbolFileDWARF::DebugAbbrev() const
+{
+    return m_abbr.get();
+}
+
+DWARFDebugAranges*
+SymbolFileDWARF::DebugAranges()
+{
+    if (m_aranges.get() == NULL)
+    {
+        Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", __PRETTY_FUNCTION__, this);
+        m_aranges.reset(new DWARFDebugAranges());
+        if (m_aranges.get())
+        {
+            const DataExtractor &debug_aranges_data = get_debug_aranges_data();
+            if (debug_aranges_data.GetByteSize() > 0)
+                m_aranges->Extract(debug_aranges_data);
+            else
+                m_aranges->Generate(this);
+        }
+    }
+    return m_aranges.get();
+}
+
+const DWARFDebugAranges*
+SymbolFileDWARF::DebugAranges() const
+{
+    return m_aranges.get();
+}
+
+
+DWARFDebugInfo*
+SymbolFileDWARF::DebugInfo()
+{
+    if (m_info.get() == NULL)
+    {
+        Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", __PRETTY_FUNCTION__, this);
+        if (get_debug_info_data().GetByteSize() > 0)
+        {
+            m_info.reset(new DWARFDebugInfo());
+            if (m_info.get())
+            {
+                m_info->SetDwarfData(this);
+            }
+        }
+    }
+    return m_info.get();
+}
+
+const DWARFDebugInfo*
+SymbolFileDWARF::DebugInfo() const
+{
+    return m_info.get();
+}
+
+//DWARFDebugLine*
+//SymbolFileDWARF::DebugLine()
+//{
+//  if (m_line.get() == NULL)
+//  {
+//      Timer scoped_timer(__PRETTY_FUNCTION__);
+//      const DataExtractor &debug_line_data = debug_line();
+//      if (debug_line_data.GetByteSize() > 0)
+//      {
+//          m_line.reset(new DWARFDebugLine());
+//          if (m_line.get())
+//              m_line->Parse(debug_line_data);
+//      }
+//  }
+//  return m_line.get();
+//}
+//
+//const DWARFDebugLine*
+//SymbolFileDWARF::DebugLine() const
+//{
+//  return m_line.get();
+//}
+
+
+DWARFCompileUnit*
+SymbolFileDWARF::GetDWARFCompileUnitForUID(lldb::user_id_t cu_uid)
+{
+    DWARFDebugInfo* info = DebugInfo();
+    if (info)
+        return info->GetCompileUnit(cu_uid).get();
+    return NULL;
+}
+
+//DWARFCompileUnit*
+//SymbolFileDWARF::GetNextUnparsedDWARFCompileUnit(DWARFCompileUnit* prev_cu)
+//{
+//  DWARFCompileUnit* cu = NULL;
+//  DWARFDebugInfo* info = DebugInfo();
+//  if (info)
+//  {
+//      uint32_t cu_idx = 0;
+//      if (prev_cu != NULL)
+//      {
+//          // Find the index of the previus DWARF compile unit if one was provided
+//          while ((cu = info->GetCompileUnitAtIndex(cu_idx)) != NULL)
+//          {
+//              ++cu_idx;
+//              if (cu == prev_cu)
+//                  break;
+//          }
+//      }
+//
+//      // Now find the next unparsed DWARF compile unit. We do this by checking the
+//      // user data in the DWARFCompileUnit class that starts as NULL, and eventually
+//      // holds a pointer to the CompileUnit that was created for it after it has
+//      // been parsed.
+//      while ((cu = info->GetCompileUnitAtIndex(cu_idx)) != NULL)
+//      {
+//          if (cu->GetUserData() == NULL)
+//              break;
+//      }
+//  }
+//  return cu;
+//}
+
+DWARFDebugRanges*
+SymbolFileDWARF::DebugRanges()
+{
+    if (m_ranges.get() == NULL)
+    {
+        Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", __PRETTY_FUNCTION__, this);
+        if (get_debug_ranges_data().GetByteSize() > 0)
+        {
+            m_ranges.reset(new DWARFDebugRanges());
+            if (m_ranges.get())
+                m_ranges->Extract(this);
+        }
+    }
+    return m_ranges.get();
+}
+
+const DWARFDebugRanges*
+SymbolFileDWARF::DebugRanges() const
+{
+    return m_ranges.get();
+}
+//
+//DWARFDebugPubnames*
+//SymbolFileDWARF::DebugPubnames()
+//{
+//    if (m_pubnames.get() == NULL)
+//    {
+//        Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", __PRETTY_FUNCTION__, this);
+//        const DataExtractor &debug_pubnames_data = get_debug_pubnames_data();
+//        if (debug_pubnames_data.GetByteSize() > 0)
+//        {
+//            // Pass false to indicate this is a pubnames section
+//            m_pubnames.reset(new DWARFDebugPubnames());
+//            if (m_pubnames.get())
+//            {
+//                // "m_pubnames->GeneratePubnames" is costly, but needed for global variables
+//                m_pubnames->GeneratePubnames(this);
+//
+//#if 0
+//                StreamFile s(stdout);
+//                s.Printf (".debug_pubnames for %s/%s:\n",
+//                          m_obj_file->GetModule()->GetFileSpec().GetDirectory().AsCString(),
+//                          m_obj_file->GetModule()->GetFileSpec().GetFilename().AsCString());
+//                m_pubnames->Dump (&s);
+//#endif
+//                // "m_pubnames->Extract" is quicker, but the pubnames don't always contain what we need.
+//                //m_pubnames->Extract(debug_pubnames_data);
+//            }
+//        }
+//    }
+//    return m_pubnames.get();
+//}
+//
+//const DWARFDebugPubnames*
+//SymbolFileDWARF::DebugPubnames() const
+//{
+//    return m_pubnames.get();
+//}
+
+//DWARFDebugPubnames*
+//SymbolFileDWARF::DebugPubBaseTypes()
+//{
+//    if (m_pubbasetypes.get() == NULL)
+//    {
+//        Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", __PRETTY_FUNCTION__, this);
+//        // Pass false to indicate this is a pubnames section
+//        m_pubbasetypes.reset(new DWARFDebugPubnames());
+//        if (m_pubbasetypes.get())
+//            m_pubbasetypes->GeneratePubBaseTypes(this);
+//    }
+//    return m_pubbasetypes.get();
+//}
+//
+//const DWARFDebugPubnames*
+//SymbolFileDWARF::DebugPubBaseTypes() const
+//{
+//    return m_pubbasetypes.get();
+//}
+//
+//const DWARFDebugPubnames*
+//SymbolFileDWARF::DebugPubtypes() const
+//{
+//    return m_pubtypes.get();
+//}
+//
+//DWARFDebugPubnames*
+//SymbolFileDWARF::DebugPubtypes()
+//{
+//    if (m_pubtypes.get() == NULL)
+//    {
+//        Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", __PRETTY_FUNCTION__, this);
+//        const DataExtractor &debug_pubtypes_data = get_debug_pubtypes_data();
+//        if (debug_pubtypes_data.GetByteSize() > 0)
+//        {
+//            // Pass false to indicate this is a pubnames section
+//            m_pubtypes.reset(new DWARFDebugPubnames());
+//            if (m_pubtypes.get())
+//                m_pubtypes->Extract(debug_pubtypes_data);
+//        }
+//    }
+//    return m_pubtypes.get();
+//}
+//
+
+bool
+SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit* cu, CompUnitSP& compile_unit_sp)
+{
+    if (cu != NULL)
+    {
+        const DWARFDebugInfoEntry * cu_die = cu->GetCompileUnitDIEOnly ();
+        if (cu_die)
+        {
+            const char * cu_die_name = cu_die->GetName(this, cu);
+            const char * cu_comp_dir = cu_die->GetAttributeValueAsString(this, cu, DW_AT_comp_dir, NULL);
+            Language::Type language = (Language::Type)cu_die->GetAttributeValueAsUnsigned(this, cu, DW_AT_language, 0);
+            if (cu_die_name)
+            {
+                if (cu_die_name[0] == '/' || cu_comp_dir == NULL && cu_comp_dir[0])
+                {
+                    compile_unit_sp.reset(new CompileUnit(m_obj_file->GetModule(), cu, cu_die_name, cu->GetOffset(), language));
+                }
+                else
+                {
+                    std::string fullpath(cu_comp_dir);
+                    if (*fullpath.rbegin() != '/')
+                        fullpath += '/';
+                    fullpath += cu_die_name;
+
+                    compile_unit_sp.reset(new CompileUnit(m_obj_file->GetModule(), cu, fullpath.c_str(), cu->GetOffset(), language));
+                }
+
+                if (compile_unit_sp.get())
+                {
+                    cu->SetUserData(compile_unit_sp.get());
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+#if defined LLDB_SYMBOL_FILE_DWARF_SHRINK_TEST
+
+void
+SymbolFileDWARF::ShrinkDSYM(CompileUnit *dc_cu, DWARFCompileUnit *dw_cu, const FileSpec& cu_fspec, const FileSpec& base_types_fspec, FSToDIES& fs_to_dies, const DWARFDebugInfoEntry *die)
+{
+    while (die != NULL)
+    {
+        dw_tag_t tag = die->Tag();
+
+        switch (tag)
+        {
+        case DW_TAG_base_type:
+            // Put all base types into the base type compile unit
+            fs_to_dies[base_types_fspec].Insert(die);
+            break;
+
+        default:
+            {
+                uint32_t decl_file = die->GetAttributeValueAsUnsigned(this, dw_cu, DW_AT_decl_file, 0);
+                if (decl_file)
+                {
+                    fs_to_dies[dc_cu->GetSupportFiles().GetFileSpecAtIndex(decl_file)].Insert(die);
+                }
+                else
+                {
+                    // add this to the current compile unit
+                    fs_to_dies[cu_fspec].Insert(die);
+                }
+            }
+            break;
+        }
+
+        die = die->GetSibling();
+    }
+}
+
+
+
+#endif
+
+uint32_t
+SymbolFileDWARF::GetNumCompileUnits()
+{
+    DWARFDebugInfo* info = DebugInfo();
+    if (info)
+    {
+#if defined LLDB_SYMBOL_FILE_DWARF_SHRINK_TEST
+        uint32_t cu_idx;
+        FSToDIES fs_to_dies;
+
+        FileSpec base_type_fspec("DW_TAG_base_type");
+        const uint32_t num_comp_units = info->GetNumCompileUnits();
+
+        for (cu_idx=0; cu_idx < num_comp_units; ++cu_idx)
+        {
+            DWARFCompileUnit* cu = info->GetCompileUnitAtIndex(cu_idx);
+            if (cu != NULL)
+            {
+                const DWARFDebugInfoEntry *cu_die = cu->DIE();
+                if (cu_die)
+                {
+                    CompUnitSP dc_cu_sp;
+                    ParseCompileUnit(cu, dc_cu_sp);
+                    if (dc_cu_sp.get())
+                    {
+                        FileSpec cu_fspec(*dc_cu_sp.get());
+
+                        ShrinkDSYM(dc_cu_sp.get(), cu, cu_fspec, base_type_fspec, fs_to_dies, cu->DIE()->GetFirstChild());
+                    }
+                }
+            }
+        }
+
+        Stream strm(stdout);
+        FSToDIES::const_iterator pos, end = fs_to_dies.end();
+        for (pos = fs_to_dies.begin(); pos != end; ++pos)
+        {
+            strm << "\n\nMinimal Compile Unit: " << pos->first << ":\n";
+            const DWARFDIECollection& dies = pos->second;
+            dies.Dump(strm, NULL);
+        }
+        return num_comp_units;
+#else
+        return info->GetNumCompileUnits();
+#endif
+    }
+    return 0;
+}
+
+CompUnitSP
+SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx)
+{
+    CompUnitSP comp_unit;
+    DWARFDebugInfo* info = DebugInfo();
+    if (info)
+    {
+        DWARFCompileUnit* cu = info->GetCompileUnitAtIndex(cu_idx);
+        if (cu != NULL)
+        {
+            // Our symbol vendor shouldn't be asking us to add a compile unit that
+            // has already been added to it, which this DWARF plug-in knows as it
+            // stores the lldb compile unit (CompileUnit) pointer in each
+            // DWARFCompileUnit object when it gets added.
+            assert(cu->GetUserData() == NULL);
+            ParseCompileUnit(cu, comp_unit);
+        }
+    }
+    return comp_unit;
+}
+
+static void
+AddRangesToBlock
+(
+    BlockList& blocks,
+    lldb::user_id_t blockID,
+    DWARFDebugRanges::RangeList& ranges,
+    addr_t block_base_addr
+)
+{
+    ranges.SubtractOffset (block_base_addr);
+    size_t range_idx = 0;
+    const DWARFDebugRanges::Range *debug_range;
+    for (range_idx = 0; (debug_range = ranges.RangeAtIndex(range_idx)) != NULL; range_idx++)
+    {
+        blocks.AddRange(blockID, debug_range->begin_offset, debug_range->end_offset);
+    }
+}
+
+
+Function *
+SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, const DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die)
+{
+    DWARFDebugRanges::RangeList func_ranges;
+    const char *name = NULL;
+    const char *mangled = NULL;
+    int decl_file = 0;
+    int decl_line = 0;
+    int decl_column = 0;
+    int call_file = 0;
+    int call_line = 0;
+    int call_column = 0;
+    DWARFExpression frame_base;
+
+    // Parse the function prototype as a type that can then be added to concrete function instance
+    ParseTypes (sc, dwarf_cu, die, false, false);
+    //FixupTypes();
+
+    if (die->GetDIENamesAndRanges(this, dwarf_cu, name, mangled, func_ranges, decl_file, decl_line, decl_column, call_file, call_line, call_column, &frame_base))
+    {
+        // Union of all ranges in the function DIE (if the function is discontiguous)
+        AddressRange func_range;
+        lldb::addr_t lowest_func_addr = func_ranges.LowestAddress(0);
+        lldb::addr_t highest_func_addr = func_ranges.HighestAddress(0);
+        if (lowest_func_addr != LLDB_INVALID_ADDRESS && lowest_func_addr <= highest_func_addr)
+        {
+            func_range.GetBaseAddress().ResolveAddressUsingFileSections (lowest_func_addr, m_obj_file->GetSectionList());
+            if (func_range.GetBaseAddress().IsValid())
+                func_range.SetByteSize(highest_func_addr - lowest_func_addr);
+        }
+
+        if (func_range.GetBaseAddress().IsValid())
+        {
+            Mangled func_name;
+            if (mangled)
+                func_name.SetValue(mangled, true);
+            else if (name)
+                func_name.SetValue(name, false);
+
+            FunctionSP func_sp;
+            std::auto_ptr<Declaration> decl_ap;
+            if (decl_file != 0 || decl_line != 0 || decl_column != 0)
+                decl_ap.reset(new Declaration(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file), decl_line, decl_column));
+
+            Type *func_type = NULL;
+
+            if (die->GetUserData() != DIE_IS_BEING_PARSED)
+                func_type = (Type*)die->GetUserData();
+
+            assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED);
+
+            func_range.GetBaseAddress().ResolveLinkedAddress();
+
+            func_sp.reset(new Function (sc.comp_unit,
+                                        die->GetOffset(),       // UserID is the DIE offset
+                                        die->GetOffset(),
+                                        func_name,
+                                        func_type,
+                                        func_range));           // first address range
+
+            if (func_sp.get() != NULL)
+            {
+                func_sp->GetFrameBaseExpression() = frame_base;
+                sc.comp_unit->AddFunction(func_sp);
+                return func_sp.get();
+            }
+        }
+    }
+    return NULL;
+}
+
+size_t
+SymbolFileDWARF::ParseCompileUnitFunctions(const SymbolContext &sc)
+{
+    assert (sc.comp_unit);
+    size_t functions_added = 0;
+    const DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnitForUID(sc.comp_unit->GetID());
+    if (dwarf_cu)
+    {
+        DWARFDIECollection function_dies;
+        const size_t num_funtions = dwarf_cu->AppendDIEsWithTag (DW_TAG_subprogram, function_dies);
+        size_t func_idx;
+        for (func_idx = 0; func_idx < num_funtions; ++func_idx)
+        {
+            const DWARFDebugInfoEntry *die = function_dies.GetDIEPtrAtIndex(func_idx);
+            if (sc.comp_unit->FindFunctionByUID (die->GetOffset()).get() == NULL)
+            {
+                if (ParseCompileUnitFunction(sc, dwarf_cu, die))
+                    ++functions_added;
+            }
+        }
+        //FixupTypes();
+    }
+    return functions_added;
+}
+
+bool
+SymbolFileDWARF::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList& support_files)
+{
+    assert (sc.comp_unit);
+    DWARFCompileUnit* cu = GetDWARFCompileUnitForUID(sc.comp_unit->GetID());
+    assert (cu);
+    const DWARFDebugInfoEntry * cu_die = cu->GetCompileUnitDIEOnly();
+
+    if (cu_die)
+    {
+        const char * cu_comp_dir = cu_die->GetAttributeValueAsString(this, cu, DW_AT_comp_dir, NULL);
+        dw_offset_t stmt_list = cu_die->GetAttributeValueAsUnsigned(this, cu, DW_AT_stmt_list, DW_INVALID_OFFSET);
+
+        // All file indexes in DWARF are one based and a file of index zero is
+        // supposed to be the compile unit itself.
+        support_files.Append (*sc.comp_unit);
+
+        return DWARFDebugLine::ParseSupportFiles(get_debug_line_data(), cu_comp_dir, stmt_list, support_files);
+    }
+    return false;
+}
+
+struct ParseDWARFLineTableCallbackInfo
+{
+    LineTable* line_table;
+    const SectionList *section_list;
+    lldb::addr_t prev_sect_file_base_addr;
+    lldb::addr_t curr_sect_file_base_addr;
+    bool is_oso_for_debug_map;
+    bool prev_in_final_executable;
+    DWARFDebugLine::Row prev_row;
+    SectionSP prev_section_sp;
+    SectionSP curr_section_sp;
+};
+
+//----------------------------------------------------------------------
+// ParseStatementTableCallback
+//----------------------------------------------------------------------
+static void
+ParseDWARFLineTableCallback(dw_offset_t offset, const DWARFDebugLine::State& state, void* userData)
+{
+    LineTable* line_table = ((ParseDWARFLineTableCallbackInfo*)userData)->line_table;
+    if (state.row == DWARFDebugLine::State::StartParsingLineTable)
+    {
+        // Just started parsing the line table
+    }
+    else if (state.row == DWARFDebugLine::State::DoneParsingLineTable)
+    {
+        // Done parsing line table, nothing to do for the cleanup
+    }
+    else
+    {
+        ParseDWARFLineTableCallbackInfo* info = (ParseDWARFLineTableCallbackInfo*)userData;
+        // We have a new row, lets append it
+
+        if (info->curr_section_sp.get() == NULL || info->curr_section_sp->ContainsFileAddress(state.address) == false)
+        {
+            info->prev_section_sp = info->curr_section_sp;
+            info->prev_sect_file_base_addr = info->curr_sect_file_base_addr;
+            // If this is an end sequence entry, then we subtract one from the
+            // address to make sure we get an address that is not the end of
+            // a section.
+            if (state.end_sequence && state.address != 0)
+                info->curr_section_sp = info->section_list->FindSectionContainingFileAddress (state.address - 1);
+            else
+                info->curr_section_sp = info->section_list->FindSectionContainingFileAddress (state.address);
+
+            if (info->curr_section_sp.get())
+                info->curr_sect_file_base_addr = info->curr_section_sp->GetFileAddress ();
+            else
+                info->curr_sect_file_base_addr = 0;
+        }
+        if (info->curr_section_sp.get())
+        {
+            lldb::addr_t curr_line_section_offset = state.address - info->curr_sect_file_base_addr;
+            // Check for the fancy section magic to determine if we
+
+            if (info->is_oso_for_debug_map)
+            {
+                // When this is a debug map object file that contains DWARF
+                // (referenced from an N_OSO debug map nlist entry) we will have
+                // a file address in the file range for our section from the
+                // original .o file, and a load address in the executable that
+                // contains the debug map.
+                //
+                // If the sections for the file range and load range are
+                // different, we have a remapped section for the function and
+                // this address is resolved. If they are the same, then the
+                // function for this address didn't make it into the final
+                // executable.
+                bool curr_in_final_executable = info->curr_section_sp->GetLinkedSection () != NULL;
+
+                // If we are doing DWARF with debug map, then we need to carefully
+                // add each line table entry as there may be gaps as functions
+                // get moved around or removed.
+                if (!info->prev_row.end_sequence && info->prev_section_sp.get())
+                {
+                    if (info->prev_in_final_executable)
+                    {
+                        bool terminate_previous_entry = false;
+                        if (!curr_in_final_executable)
+                        {
+                            // Check for the case where the previous line entry
+                            // in a function made it into the final executable,
+                            // yet the current line entry falls in a function
+                            // that didn't. The line table used to be contiguous
+                            // through this address range but now it isn't. We
+                            // need to terminate the previous line entry so
+                            // that we can reconstruct the line range correctly
+                            // for it and to keep the line table correct.
+                            terminate_previous_entry = true;
+                        }
+                        else if (info->curr_section_sp.get() != info->prev_section_sp.get())
+                        {
+                            // Check for cases where the line entries used to be
+                            // contiguous address ranges, but now they aren't.
+                            // This can happen when order files specify the
+                            // ordering of the functions.
+                            lldb::addr_t prev_line_section_offset = info->prev_row.address - info->prev_sect_file_base_addr;
+                            Section *curr_sect = info->curr_section_sp.get();
+                            Section *prev_sect = info->prev_section_sp.get();
+                            assert (curr_sect->GetLinkedSection());
+                            assert (prev_sect->GetLinkedSection());
+                            lldb::addr_t object_file_addr_delta = state.address - info->prev_row.address;
+                            lldb::addr_t curr_linked_file_addr = curr_sect->GetLinkedFileAddress() + curr_line_section_offset;
+                            lldb::addr_t prev_linked_file_addr = prev_sect->GetLinkedFileAddress() + prev_line_section_offset;
+                            lldb::addr_t linked_file_addr_delta = curr_linked_file_addr - prev_linked_file_addr;
+                            if (object_file_addr_delta != linked_file_addr_delta)
+                                terminate_previous_entry = true;
+                        }
+
+                        if (terminate_previous_entry)
+                        {
+                            line_table->InsertLineEntry (info->prev_section_sp,
+                                                         state.address - info->prev_sect_file_base_addr,
+                                                         info->prev_row.line,
+                                                         info->prev_row.column,
+                                                         info->prev_row.file,
+                                                         false,                 // is_stmt
+                                                         false,                 // basic_block
+                                                         false,                 // state.prologue_end
+                                                         false,                 // state.epilogue_begin
+                                                         true);                 // end_sequence);
+                        }
+                    }
+                }
+
+                if (curr_in_final_executable)
+                {
+                    line_table->InsertLineEntry (info->curr_section_sp,
+                                                 curr_line_section_offset,
+                                                 state.line,
+                                                 state.column,
+                                                 state.file,
+                                                 state.is_stmt,
+                                                 state.basic_block,
+                                                 state.prologue_end,
+                                                 state.epilogue_begin,
+                                                 state.end_sequence);
+                    info->prev_section_sp = info->curr_section_sp;
+                }
+                else
+                {
+                    // If the current address didn't make it into the final
+                    // executable, the current section will be the __text
+                    // segment in the .o file, so we need to clear this so
+                    // we can catch the next function that did make it into
+                    // the final executable.
+                    info->prev_section_sp.reset();
+                    info->curr_section_sp.reset();
+                }
+
+                info->prev_in_final_executable = curr_in_final_executable;
+            }
+            else
+            {
+                // We are not in an object file that contains DWARF for an
+                // N_OSO, this is just a normal DWARF file. The DWARF spec
+                // guarantees that the addresses will be in increasing order
+                // so, since we store line tables in file address order, we
+                // can always just append the line entry without needing to
+                // search for the correct insertion point (we don't need to
+                // use LineEntry::InsertLineEntry()).
+                line_table->AppendLineEntry (info->curr_section_sp,
+                                             curr_line_section_offset,
+                                             state.line,
+                                             state.column,
+                                             state.file,
+                                             state.is_stmt,
+                                             state.basic_block,
+                                             state.prologue_end,
+                                             state.epilogue_begin,
+                                             state.end_sequence);
+            }
+        }
+
+        info->prev_row = state;
+    }
+}
+
+bool
+SymbolFileDWARF::ParseCompileUnitLineTable (const SymbolContext &sc)
+{
+    assert (sc.comp_unit);
+    if (sc.comp_unit->GetLineTable() != NULL)
+        return true;
+
+    DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnitForUID(sc.comp_unit->GetID());
+    if (dwarf_cu)
+    {
+        const DWARFDebugInfoEntry *dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly();
+        const dw_offset_t cu_line_offset = dwarf_cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_stmt_list, DW_INVALID_OFFSET);
+        if (cu_line_offset != DW_INVALID_OFFSET)
+        {
+            std::auto_ptr<LineTable> line_table_ap(new LineTable(sc.comp_unit));
+            if (line_table_ap.get())
+            {
+                ParseDWARFLineTableCallbackInfo info = { line_table_ap.get(), m_obj_file->GetSectionList(), 0, 0, m_flags.IsSet (flagsDWARFIsOSOForDebugMap), false};
+                uint32_t offset = cu_line_offset;
+                DWARFDebugLine::ParseStatementTable(get_debug_line_data(), &offset, ParseDWARFLineTableCallback, &info);
+                sc.comp_unit->SetLineTable(line_table_ap.release());
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+size_t
+SymbolFileDWARF::ParseFunctionBlocks
+(
+    const SymbolContext& sc,
+    lldb::user_id_t parentBlockID,
+    const DWARFCompileUnit* dwarf_cu,
+    const DWARFDebugInfoEntry *die,
+    addr_t subprogram_low_pc,
+    bool parse_siblings,
+    bool parse_children
+)
+{
+    size_t blocks_added = 0;
+    while (die != NULL)
+    {
+        dw_tag_t tag = die->Tag();
+
+        switch (tag)
+        {
+        case DW_TAG_subprogram:
+        case DW_TAG_inlined_subroutine:
+        case DW_TAG_lexical_block:
+            {
+                DWARFDebugRanges::RangeList ranges;
+                const char *name = NULL;
+                const char *mangled_name = NULL;
+                BlockList& blocks = sc.function->GetBlocks(false);
+
+                lldb::user_id_t blockID = blocks.AddChild(parentBlockID, die->GetOffset());
+                int decl_file = 0;
+                int decl_line = 0;
+                int decl_column = 0;
+                int call_file = 0;
+                int call_line = 0;
+                int call_column = 0;
+                if (die->GetDIENamesAndRanges(this, dwarf_cu, name, mangled_name, ranges, decl_file, decl_line, decl_column, call_file, call_line, call_column))
+                {
+                    if (tag == DW_TAG_subprogram)
+                    {
+                        assert (subprogram_low_pc == LLDB_INVALID_ADDRESS);
+                        subprogram_low_pc = ranges.LowestAddress(0);
+                    }
+
+                    AddRangesToBlock (blocks, blockID, ranges, subprogram_low_pc);
+
+                    if (tag != DW_TAG_subprogram && (name != NULL || mangled_name != NULL))
+                    {
+                        std::auto_ptr<Declaration> decl_ap;
+                        if (decl_file != 0 || decl_line != 0 || decl_column != 0)
+                            decl_ap.reset(new Declaration(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file), decl_line, decl_column));
+
+                        std::auto_ptr<Declaration> call_ap;
+                        if (call_file != 0 || call_line != 0 || call_column != 0)
+                            call_ap.reset(new Declaration(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(call_file), call_line, call_column));
+
+                        blocks.SetInlinedFunctionInfo(blockID, name, mangled_name, decl_ap.get(), call_ap.get());
+                    }
+
+                    ++blocks_added;
+
+                    if (parse_children && die->HasChildren())
+                    {
+                        blocks_added += ParseFunctionBlocks(sc, blockID, dwarf_cu, die->GetFirstChild(), subprogram_low_pc, true, true);
+                    }
+                }
+            }
+            break;
+        default:
+            break;
+        }
+
+        if (parse_siblings)
+            die = die->GetSibling();
+        else
+            die = NULL;
+    }
+    return blocks_added;
+}
+
+size_t
+SymbolFileDWARF::ParseChildMembers
+(
+    const SymbolContext& sc,
+    TypeSP& type_sp,
+    const DWARFCompileUnit* dwarf_cu,
+    const DWARFDebugInfoEntry *parent_die,
+    std::vector<clang::CXXBaseSpecifier *>& base_classes,
+    std::vector<int>& member_accessibilities,
+    int& default_accessibility,
+    bool &is_a_class
+)
+{
+    if (parent_die == NULL)
+        return 0;
+
+    TypeList* type_list = m_obj_file->GetModule()->GetTypeList();
+
+    size_t count = 0;
+    const DWARFDebugInfoEntry *die;
+    for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
+    {
+        dw_tag_t tag = die->Tag();
+
+        switch (tag)
+        {
+        case DW_TAG_member:
+            {
+                DWARFDebugInfoEntry::Attributes attributes;
+                const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes);
+                if (num_attributes > 0)
+                {
+                    Declaration decl;
+                    DWARFExpression location;
+                    const char *name = NULL;
+                    lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
+                    uint32_t accessibility = clang::AS_none;
+                    off_t member_offset = 0;
+                    size_t byte_size = 0;
+                    size_t bit_offset = 0;
+                    size_t bit_size = 0;
+                    uint32_t i;
+                    for (i=0; i<num_attributes; ++i)
+                    {
+                        const dw_attr_t attr = attributes.AttributeAtIndex(i);
+                        DWARFFormValue form_value;
+                        if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                        {
+                            switch (attr)
+                            {
+                            case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+                            case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break;
+                            case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+                            case DW_AT_name:        name = form_value.AsCString(&get_debug_str_data()); break;
+                            case DW_AT_type:        encoding_uid = form_value.Reference(dwarf_cu); break;
+                            case DW_AT_bit_offset:  bit_offset = form_value.Unsigned(); break;
+                            case DW_AT_bit_size:    bit_size = form_value.Unsigned(); break;
+                            case DW_AT_byte_size:   byte_size = form_value.Unsigned(); break;
+                            case DW_AT_data_member_location:
+                                if (form_value.BlockData())
+                                {
+                                    Value initialValue(0);
+                                    Value memberOffset(0);
+                                    const DataExtractor& debug_info_data = get_debug_info_data();
+                                    uint32_t block_length = form_value.Unsigned();
+                                    uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
+                                    if (DWARFExpression::Evaluate(NULL, NULL, debug_info_data, NULL, NULL, block_offset, block_length, eRegisterKindDWARF, &initialValue, memberOffset, NULL))
+                                    {
+                                        member_offset = memberOffset.ResolveValue(NULL, NULL).UInt();
+                                    }
+                                }
+                                break;
+
+                            case DW_AT_accessibility: accessibility = DwarfToClangAccessibility (form_value.Unsigned()); break;
+                            case DW_AT_declaration:
+                            case DW_AT_description:
+                            case DW_AT_mutable:
+                            case DW_AT_visibility:
+                            default:
+                            case DW_AT_sibling:
+                                break;
+                            }
+                        }
+                    }
+
+                    Type *member_type = ResolveTypeUID(encoding_uid);
+                    assert(member_type);
+                    if (accessibility == clang::AS_none)
+                        accessibility = default_accessibility;
+                    member_accessibilities.push_back(accessibility);
+
+                    type_list->GetClangASTContext().AddFieldToRecordType (type_sp->GetOpaqueClangQualType(), name, member_type->GetOpaqueClangQualType(), accessibility, bit_size);
+                }
+            }
+            break;
+
+        case DW_TAG_subprogram:
+            {
+                is_a_class = true;
+                if (default_accessibility == clang::AS_none)
+                    default_accessibility = clang::AS_private;
+                // TODO: implement DW_TAG_subprogram type parsing
+//              UserDefTypeChildInfo method_info(die->GetOffset());
+//
+//              FunctionSP func_sp (sc.comp_unit->FindFunctionByUID (die->GetOffset()));
+//              if (func_sp.get() == NULL)
+//                  ParseCompileUnitFunction(sc, dwarf_cu, die);
+//
+//              method_info.SetEncodingTypeUID(die->GetOffset());
+//              struct_udt->AddMethod(method_info);
+            }
+            break;
+
+        case DW_TAG_inheritance:
+            {
+                is_a_class = true;
+                if (default_accessibility == clang::AS_none)
+                    default_accessibility = clang::AS_private;
+                // TODO: implement DW_TAG_inheritance type parsing
+                DWARFDebugInfoEntry::Attributes attributes;
+                const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes);
+                if (num_attributes > 0)
+                {
+                    Declaration decl;
+                    DWARFExpression location;
+                    lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
+                    uint32_t accessibility = default_accessibility;
+                    bool is_virtual = false;
+                    bool is_base_of_class = true;
+                    off_t member_offset = 0;
+                    uint32_t i;
+                    for (i=0; i<num_attributes; ++i)
+                    {
+                        const dw_attr_t attr = attributes.AttributeAtIndex(i);
+                        DWARFFormValue form_value;
+                        if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                        {
+                            switch (attr)
+                            {
+                            case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+                            case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break;
+                            case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+                            case DW_AT_type:        encoding_uid = form_value.Reference(dwarf_cu); break;
+                            case DW_AT_data_member_location:
+                                if (form_value.BlockData())
+                                {
+                                    Value initialValue(0);
+                                    Value memberOffset(0);
+                                    const DataExtractor& debug_info_data = get_debug_info_data();
+                                    uint32_t block_length = form_value.Unsigned();
+                                    uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
+                                    if (DWARFExpression::Evaluate(NULL, NULL, debug_info_data, NULL, NULL, block_offset, block_length, eRegisterKindDWARF, &initialValue, memberOffset, NULL))
+                                    {
+                                        member_offset = memberOffset.ResolveValue(NULL, NULL).UInt();
+                                    }
+                                }
+                                break;
+
+                            case DW_AT_accessibility:
+                                accessibility = DwarfToClangAccessibility(form_value.Unsigned());
+                                break;
+
+                            case DW_AT_virtuality: is_virtual = form_value.Unsigned() != 0; break;
+                            default:
+                            case DW_AT_sibling:
+                                break;
+                            }
+                        }
+                    }
+
+                    Type *base_class_dctype = ResolveTypeUID(encoding_uid);
+                    assert(base_class_dctype);
+                    base_classes.push_back (type_list->GetClangASTContext().CreateBaseClassSpecifier (base_class_dctype->GetOpaqueClangQualType(), accessibility, is_virtual, is_base_of_class));
+                    assert(base_classes.back());
+                }
+            }
+            break;
+
+        default:
+            break;
+        }
+    }
+    return count;
+}
+
+
+clang::DeclContext*
+SymbolFileDWARF::GetClangDeclContextForTypeUID (lldb::user_id_t type_uid)
+{
+    DWARFDebugInfo* debug_info = DebugInfo();
+    if (debug_info)
+    {
+        DWARFCompileUnitSP cu_sp;
+        const DWARFDebugInfoEntry* die = debug_info->GetDIEPtr(type_uid, &cu_sp);
+        if (die)
+            return GetClangDeclContextForDIE (cu_sp.get(), die);
+    }
+    return NULL;
+}
+
+Type*
+SymbolFileDWARF::ResolveTypeUID(lldb::user_id_t type_uid)
+{
+    DWARFDebugInfo* debug_info = DebugInfo();
+    if (debug_info)
+    {
+        const DWARFDebugInfoEntry* type_die = debug_info->GetDIEPtr(type_uid, NULL);
+        if (type_die != NULL)
+        {
+            void *type = type_die->GetUserData();
+            if (type == NULL)
+            {
+                DWARFCompileUnitSP cu_sp;
+                const DWARFDebugInfoEntry* die = debug_info->GetDIEPtr(type_uid, &cu_sp);
+                if (die != NULL)
+                {
+                    TypeSP owning_type_sp;
+                    TypeSP type_sp(GetTypeForDIE(cu_sp.get(), die, owning_type_sp, 0, 0));
+                }
+                type = type_die->GetUserData();
+            }
+            if (type != DIE_IS_BEING_PARSED)
+                return (Type *)type;
+        }
+    }
+    return NULL;
+}
+
+CompileUnit*
+SymbolFileDWARF::GetCompUnitForDWARFCompUnit(DWARFCompileUnit* cu, uint32_t cu_idx)
+{
+    // Check if the symbol vendor already knows about this compile unit?
+    if (cu->GetUserData() == NULL)
+    {
+        // The symbol vendor doesn't know about this compile unit, we
+        // need to parse and add it to the symbol vendor object.
+        CompUnitSP dc_cu;
+        ParseCompileUnit(cu, dc_cu);
+        if (dc_cu.get())
+        {
+            // Figure out the compile unit index if we weren't given one
+            if (cu_idx == UINT_MAX)
+                DebugInfo()->GetCompileUnit(cu->GetOffset(), &cu_idx);
+
+            m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex(dc_cu, cu_idx);
+        }
+    }
+    return (CompileUnit*)cu->GetUserData();
+}
+
+bool
+SymbolFileDWARF::GetFunction (DWARFCompileUnit* cu, const DWARFDebugInfoEntry* func_die, SymbolContext& sc)
+{
+    sc.Clear();
+    // Check if the symbol vendor already knows about this compile unit?
+    sc.module_sp = m_obj_file->GetModule()->GetSP();
+    sc.comp_unit = GetCompUnitForDWARFCompUnit(cu, UINT_MAX);
+
+    sc.function = sc.comp_unit->FindFunctionByUID (func_die->GetOffset()).get();
+    if (sc.function == NULL)
+        sc.function = ParseCompileUnitFunction(sc, cu, func_die);
+
+    return sc.function != NULL;
+}
+
+uint32_t
+SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
+{
+    Timer scoped_timer(__PRETTY_FUNCTION__,
+                       "SymbolFileDWARF::ResolveSymbolContext (so_addr = { section = %p, offset = 0x%llx }, resolve_scope = 0x%8.8x)",
+                       so_addr.GetSection(),
+                       so_addr.GetOffset(),
+                       resolve_scope);
+    uint32_t resolved = 0;
+    if (resolve_scope & (   eSymbolContextCompUnit |
+                            eSymbolContextFunction |
+                            eSymbolContextBlock |
+                            eSymbolContextLineEntry))
+    {
+        lldb::addr_t file_vm_addr = so_addr.GetFileAddress();
+
+        DWARFDebugAranges* debug_aranges = DebugAranges();
+        DWARFDebugInfo* debug_info = DebugInfo();
+        if (debug_aranges)
+        {
+            dw_offset_t cu_offset = debug_aranges->FindAddress(file_vm_addr);
+            if (cu_offset != DW_INVALID_OFFSET)
+            {
+                uint32_t cu_idx;
+                DWARFCompileUnit* cu = debug_info->GetCompileUnit(cu_offset, &cu_idx).get();
+                if (cu)
+                {
+                    sc.comp_unit = GetCompUnitForDWARFCompUnit(cu, cu_idx);
+                    assert(sc.comp_unit != NULL);
+                    resolved |= eSymbolContextCompUnit;
+
+                    if (resolve_scope & eSymbolContextLineEntry)
+                    {
+                        LineTable *line_table = sc.comp_unit->GetLineTable();
+                        if (line_table == NULL)
+                        {
+                            if (ParseCompileUnitLineTable(sc))
+                                line_table = sc.comp_unit->GetLineTable();
+                        }
+                        if (line_table != NULL)
+                        {
+                            if (so_addr.IsLinkedAddress())
+                            {
+                                Address linked_addr (so_addr);
+                                linked_addr.ResolveLinkedAddress();
+                                if (line_table->FindLineEntryByAddress (linked_addr, sc.line_entry))
+                                {
+                                    resolved |= eSymbolContextLineEntry;
+                                }
+                            }
+                            else if (line_table->FindLineEntryByAddress (so_addr, sc.line_entry))
+                            {
+                                resolved |= eSymbolContextLineEntry;
+                            }
+                        }
+                    }
+
+                    if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock))
+                    {
+                        DWARFDebugInfoEntry *function_die = NULL;
+                        DWARFDebugInfoEntry *block_die = NULL;
+                        if (resolve_scope & eSymbolContextBlock)
+                        {
+                            cu->LookupAddress(file_vm_addr, &function_die, &block_die);
+                        }
+                        else
+                        {
+                            cu->LookupAddress(file_vm_addr, &function_die, NULL);
+                        }
+
+                        if (function_die != NULL)
+                        {
+                            sc.function = sc.comp_unit->FindFunctionByUID (function_die->GetOffset()).get();
+                            if (sc.function == NULL)
+                                sc.function = ParseCompileUnitFunction(sc, cu, function_die);
+                        }
+
+                        if (sc.function != NULL)
+                        {
+                            resolved |= eSymbolContextFunction;
+
+                            if (resolve_scope & eSymbolContextBlock)
+                            {
+                                BlockList& blocks = sc.function->GetBlocks(true);
+
+                                if (block_die != NULL)
+                                    sc.block = blocks.GetBlockByID(block_die->GetOffset());
+                                else
+                                    sc.block = blocks.GetBlockByID(function_die->GetOffset());
+                                if (sc.block)
+                                    resolved |= eSymbolContextBlock;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return resolved;
+}
+
+
+
+uint32_t
+SymbolFileDWARF::ResolveSymbolContext(const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
+{
+    const uint32_t prev_size = sc_list.GetSize();
+    if (resolve_scope & eSymbolContextCompUnit)
+    {
+        DWARFDebugInfo* debug_info = DebugInfo();
+        if (debug_info)
+        {
+            uint32_t cu_idx;
+            DWARFCompileUnit* cu = NULL;
+
+            for (cu_idx = 0; (cu = debug_info->GetCompileUnitAtIndex(cu_idx)) != NULL; ++cu_idx)
+            {
+                CompileUnit *dc_cu = GetCompUnitForDWARFCompUnit(cu, cu_idx);
+                bool file_spec_matches_cu_file_spec = dc_cu != NULL && FileSpec::Compare(file_spec, *dc_cu, false) == 0;
+                if (check_inlines || file_spec_matches_cu_file_spec)
+                {
+                    SymbolContext sc (m_obj_file->GetModule());
+                    sc.comp_unit = GetCompUnitForDWARFCompUnit(cu, cu_idx);
+                    assert(sc.comp_unit != NULL);
+
+                    uint32_t file_idx = UINT32_MAX;
+
+                    // If we are looking for inline functions only and we don't
+                    // find it in the support files, we are done.
+                    if (check_inlines)
+                    {
+                        file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec);
+                        if (file_idx == UINT32_MAX)
+                            continue;
+                    }
+
+                    if (line != 0)
+                    {
+                        LineTable *line_table = sc.comp_unit->GetLineTable();
+
+                        if (line_table != NULL && line != 0)
+                        {
+                            // We will have already looked up the file index if
+                            // we are searching for inline entries.
+                            if (!check_inlines)
+                                file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec);
+
+                            if (file_idx != UINT32_MAX)
+                            {
+                                uint32_t found_line;
+                                uint32_t line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_idx, line, false, &sc.line_entry);
+                                found_line = sc.line_entry.line;
+
+                                while (line_idx != UINT_MAX)
+                                {
+                                    sc.function = NULL;
+                                    sc.block = NULL;
+                                    if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock))
+                                    {
+                                        const lldb::addr_t file_vm_addr = sc.line_entry.range.GetBaseAddress().GetFileAddress();
+                                        if (file_vm_addr != LLDB_INVALID_ADDRESS)
+                                        {
+                                            DWARFDebugInfoEntry *function_die = NULL;
+                                            DWARFDebugInfoEntry *block_die = NULL;
+                                            cu->LookupAddress(file_vm_addr, &function_die, resolve_scope & eSymbolContextBlock ? &block_die : NULL);
+
+                                            if (function_die != NULL)
+                                            {
+                                                sc.function = sc.comp_unit->FindFunctionByUID (function_die->GetOffset()).get();
+                                                if (sc.function == NULL)
+                                                    sc.function = ParseCompileUnitFunction(sc, cu, function_die);
+                                            }
+
+                                            if (sc.function != NULL)
+                                            {
+                                                BlockList& blocks = sc.function->GetBlocks(true);
+
+                                                if (block_die != NULL)
+                                                    sc.block = blocks.GetBlockByID(block_die->GetOffset());
+                                                else
+                                                    sc.block = blocks.GetBlockByID(function_die->GetOffset());
+                                            }
+                                        }
+                                    }
+
+                                    sc_list.Append(sc);
+                                    line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_idx, found_line, true, &sc.line_entry);
+                                }
+                            }
+                        }
+                        else if (file_spec_matches_cu_file_spec && !check_inlines)
+                        {
+                            // only append the context if we aren't looking for inline call sites
+                            // by file and line and if the file spec matches that of the compile unit
+                            sc_list.Append(sc);
+                        }
+                    }
+                    else if (file_spec_matches_cu_file_spec && !check_inlines)
+                    {
+                        // only append the context if we aren't looking for inline call sites
+                        // by file and line and if the file spec matches that of the compile unit
+                        sc_list.Append(sc);
+                    }
+
+                    if (!check_inlines)
+                        break;
+                }
+            }
+        }
+    }
+    return sc_list.GetSize() - prev_size;
+}
+
+void
+SymbolFileDWARF::Index ()
+{
+    if (m_indexed)
+        return;
+    m_indexed = true;
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "SymbolFileDWARF::Index (%s)",
+                        GetObjectFile()->GetFileSpec().GetFilename().AsCString());
+
+    DWARFDebugInfo* debug_info = DebugInfo();
+    if (debug_info)
+    {
+        uint32_t cu_idx = 0;
+        const uint32_t num_compile_units = GetNumCompileUnits();
+        for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
+        {
+            DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
+
+            bool clear_dies = cu->ExtractDIEsIfNeeded (false) > 1;
+
+            cu->Index (m_name_to_function_die,
+                       m_name_to_inlined_die,
+                       m_name_to_global_die, 
+                       m_name_to_type_die);  
+            
+            // Keep memory down by clearing DIEs if this generate function
+            // caused them to be parsed
+            if (clear_dies)
+                cu->ClearDIEs (true);
+        }
+        
+        m_name_to_function_die.Sort();
+        m_name_to_inlined_die.Sort();
+        m_name_to_global_die.Sort(); 
+        m_name_to_type_die.Sort();
+    }
+}
+
+uint32_t
+SymbolFileDWARF::FindGlobalVariables (const ConstString &name, bool append, uint32_t max_matches, VariableList& variables)
+{
+    std::vector<dw_offset_t> die_offsets;
+
+    // If we aren't appending the results to this list, then clear the list
+    if (!append)
+        variables.Clear();
+
+    // Remember how many variables are in the list before we search in case
+    // we are appending the results to a variable list.
+    const uint32_t original_size = variables.GetSize();
+
+    // Index the DWARF if we haven't already
+    if (!m_indexed)
+        Index ();
+
+    const UniqueCStringMap<dw_offset_t>::Entry *entry;
+    
+    for (entry = m_name_to_global_die.FindFirstValueForName (name.AsCString());
+         entry != NULL;
+         entry = m_name_to_global_die.FindNextValueForName (name.AsCString(), entry))
+    {
+        DWARFCompileUnitSP cu_sp;
+        const DWARFDebugInfoEntry* die = DebugInfo()->GetDIEPtr (entry->value, &cu_sp);
+        DWARFCompileUnit* cu = cu_sp.get();
+        if (die)
+        {
+            SymbolContext sc;
+            sc.module_sp = m_obj_file->GetModule()->GetSP();
+            assert (sc.module_sp);
+
+            sc.comp_unit = GetCompUnitForDWARFCompUnit(cu, UINT_MAX);
+            assert(sc.comp_unit != NULL);
+
+            ParseVariables(sc, cu_sp.get(), die, false, false, &variables);
+
+            if (variables.GetSize() - original_size >= max_matches)
+                break;
+        }
+    }
+
+    // Return the number of variable that were appended to the list
+    return variables.GetSize() - original_size;
+}
+
+uint32_t
+SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables)
+{
+    std::vector<dw_offset_t> die_offsets;
+
+    // If we aren't appending the results to this list, then clear the list
+    if (!append)
+        variables.Clear();
+
+    // Remember how many variables are in the list before we search in case
+    // we are appending the results to a variable list.
+    const uint32_t original_size = variables.GetSize();
+
+    // Index the DWARF if we haven't already
+    if (!m_indexed)
+        Index ();
+
+    // Create the pubnames information so we can quickly lookup external symbols by name
+    const size_t num_entries = m_name_to_global_die.GetSize();
+    for (size_t i=0; i<num_entries; i++)
+    {
+        if (!regex.Execute(m_name_to_global_die.GetCStringAtIndex (i)))
+            continue;
+
+        const dw_offset_t die_offset = *m_name_to_global_die.GetValueAtIndex (i);
+
+        DWARFCompileUnitSP cu_sp;
+        const DWARFDebugInfoEntry* die = DebugInfo()->GetDIEPtr (die_offset, &cu_sp);
+        DWARFCompileUnit* cu = cu_sp.get();
+        if (die)
+        {
+            SymbolContext sc;
+            sc.module_sp = m_obj_file->GetModule()->GetSP();
+            assert (sc.module_sp);
+
+
+            sc.comp_unit = GetCompUnitForDWARFCompUnit(cu, UINT_MAX);
+            assert(sc.comp_unit != NULL);
+
+            ParseVariables(sc, cu_sp.get(), die, false, false, &variables);
+
+            if (variables.GetSize() - original_size >= max_matches)
+                break;
+        }
+    }
+
+    // Return the number of variable that were appended to the list
+    return variables.GetSize() - original_size;
+}
+
+
+uint32_t
+SymbolFileDWARF::FindFunctions(const ConstString &name, bool append, SymbolContextList& sc_list)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "SymbolFileDWARF::FindFunctions (name = '%s')",
+                        name.AsCString());
+
+    std::vector<dw_offset_t> die_offsets;
+
+    // If we aren't appending the results to this list, then clear the list
+    if (!append)
+        sc_list.Clear();
+
+    // Remember how many sc_list are in the list before we search in case
+    // we are appending the results to a variable list.
+    uint32_t original_size = sc_list.GetSize();
+
+    // Index the DWARF if we haven't already
+    if (!m_indexed)
+        Index ();
+
+    const UniqueCStringMap<dw_offset_t>::Entry *entry;
+    
+    SymbolContext sc;
+    for (entry = m_name_to_function_die.FindFirstValueForName (name.AsCString());
+         entry != NULL;
+         entry = m_name_to_function_die.FindNextValueForName (name.AsCString(), entry))
+    {
+        DWARFCompileUnitSP cu_sp;
+        const DWARFDebugInfoEntry* die = DebugInfo()->GetDIEPtr (entry->value, &cu_sp);
+        if (die)
+        {
+            if (GetFunction (cu_sp.get(), die, sc))
+            {
+                // We found the function, so we should find the line table
+                // and line table entry as well
+                LineTable *line_table = sc.comp_unit->GetLineTable();
+                if (line_table == NULL)
+                {
+                    if (ParseCompileUnitLineTable(sc))
+                        line_table = sc.comp_unit->GetLineTable();
+                }
+                if (line_table != NULL)
+                    line_table->FindLineEntryByAddress (sc.function->GetAddressRange().GetBaseAddress(), sc.line_entry);
+
+                sc_list.Append(sc);
+            }
+        }
+    }
+
+    // Return the number of variable that were appended to the list
+    return sc_list.GetSize() - original_size;
+}
+
+
+uint32_t
+SymbolFileDWARF::FindFunctions(const RegularExpression& regex, bool append, SymbolContextList& sc_list)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "SymbolFileDWARF::FindFunctions (regex = '%s')",
+                        regex.GetText());
+
+    std::vector<dw_offset_t> die_offsets;
+
+    // If we aren't appending the results to this list, then clear the list
+    if (!append)
+        sc_list.Clear();
+
+    // Remember how many sc_list are in the list before we search in case
+    // we are appending the results to a variable list.
+    uint32_t original_size = sc_list.GetSize();
+
+    // Index the DWARF if we haven't already
+    if (!m_indexed)
+        Index ();
+
+    // Create the pubnames information so we can quickly lookup external symbols by name
+    // Create the pubnames information so we can quickly lookup external symbols by name
+    const size_t num_entries = m_name_to_function_die.GetSize();
+    SymbolContext sc;
+    for (size_t i=0; i<num_entries; i++)
+    {
+        if (!regex.Execute(m_name_to_function_die.GetCStringAtIndex (i)))
+            continue;
+
+        const dw_offset_t die_offset = *m_name_to_function_die.GetValueAtIndex (i);
+
+        DWARFCompileUnitSP cu_sp;
+        const DWARFDebugInfoEntry* die = DebugInfo()->GetDIEPtr (die_offset, &cu_sp);
+        if (die)
+        {
+            if (GetFunction (cu_sp.get(), die, sc))
+            {
+                // We found the function, so we should find the line table
+                // and line table entry as well
+                LineTable *line_table = sc.comp_unit->GetLineTable();
+                if (line_table == NULL)
+                {
+                    if (ParseCompileUnitLineTable(sc))
+                        line_table = sc.comp_unit->GetLineTable();
+                }
+                if (line_table != NULL)
+                    line_table->FindLineEntryByAddress (sc.function->GetAddressRange().GetBaseAddress(), sc.line_entry);
+
+
+                sc_list.Append(sc);
+            }
+        }
+    }
+
+    // Return the number of variable that were appended to the list
+    return sc_list.GetSize() - original_size;
+}
+
+#if 0
+uint32_t
+SymbolFileDWARF::FindTypes(const SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, Type::Encoding encoding, lldb::user_id_t udt_uid, TypeList& types)
+{
+    // If we aren't appending the results to this list, then clear the list
+    if (!append)
+        types.Clear();
+
+    // Create the pubnames information so we can quickly lookup external symbols by name
+    DWARFDebugPubnames* pubtypes = DebugPubtypes();
+    if (pubtypes)
+    {
+        std::vector<dw_offset_t> die_offsets;
+        if (!pubtypes->Find(name.AsCString(), false, die_offsets))
+        {
+            DWARFDebugPubnames* pub_base_types = DebugPubBaseTypes();
+            if (pub_base_types && !pub_base_types->Find(name.AsCString(), false, die_offsets))
+                return 0;
+        }
+        return FindTypes(die_offsets, max_matches, encoding, udt_uid, types);
+    }
+    return 0;
+}
+
+
+uint32_t
+SymbolFileDWARF::FindTypes(const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, Type::Encoding encoding, lldb::user_id_t udt_uid, TypeList& types)
+{
+    // If we aren't appending the results to this list, then clear the list
+    if (!append)
+        types.Clear();
+
+    // Create the pubnames information so we can quickly lookup external symbols by name
+    DWARFDebugPubnames* pubtypes = DebugPubtypes();
+    if (pubtypes)
+    {
+        std::vector<dw_offset_t> die_offsets;
+        if (!pubtypes->Find(regex, die_offsets))
+        {
+            DWARFDebugPubnames* pub_base_types = DebugPubBaseTypes();
+            if (pub_base_types && !pub_base_types->Find(regex, die_offsets))
+                return 0;
+        }
+
+        return FindTypes(die_offsets, max_matches, encoding, udt_uid, types);
+    }
+
+    return 0;
+}
+
+
+
+uint32_t
+SymbolFileDWARF::FindTypes(std::vector<dw_offset_t> die_offsets, uint32_t max_matches, Type::Encoding encoding, lldb::user_id_t udt_uid, TypeList& types)
+{
+    // Remember how many sc_list are in the list before we search in case
+    // we are appending the results to a variable list.
+    uint32_t original_size = types.Size();
+
+    const uint32_t num_die_offsets = die_offsets.size();
+    // Parse all of the types we found from the pubtypes matches
+    uint32_t i;
+    uint32_t num_matches = 0;
+    for (i = 0; i < num_die_offsets; ++i)
+    {
+        dw_offset_t die_offset = die_offsets[i];
+        DWARFCompileUnitSP cu_sp;
+        const DWARFDebugInfoEntry* die = DebugInfo()->GetDIEPtr(die_offset, &cu_sp);
+
+        assert(die != NULL);
+
+        bool get_type_for_die = true;
+        if (encoding)
+        {
+            // Check if this type has already been uniqued and registers with the module?
+            Type* type = (Type*)die->GetUserData();
+            if (type != NULL && type != DIE_IS_BEING_PARSED)
+            {
+                get_type_for_die = type->GetEncoding() == encoding;
+            }
+            else
+            {
+                dw_tag_t tag = die->Tag();
+                switch (encoding)
+                {
+                case Type::address:
+                case Type::boolean:
+                case Type::complex_float:
+                case Type::float_type:
+                case Type::signed_int:
+                case Type::signed_char:
+                case Type::unsigned_int:
+                case Type::unsigned_char:
+                case Type::imaginary_float:
+                case Type::packed_decimal:
+                case Type::numeric_string:
+                case Type::edited_string:
+                case Type::signed_fixed:
+                case Type::unsigned_fixed:
+                case Type::decimal_float:
+                    if (tag != DW_TAG_base_type)
+                        get_type_for_die = false;
+                    else
+                    {
+                        if (die->GetAttributeValueAsUnsigned(this, cu_sp.get(), DW_AT_encoding, Type::invalid) != encoding)
+                            get_type_for_die = false;
+                    }
+                    break;
+
+                case Type::indirect_const:      get_type_for_die = tag == DW_TAG_const_type; break;
+                case Type::indirect_restrict:       get_type_for_die = tag == DW_TAG_restrict_type; break;
+                case Type::indirect_volatile:       get_type_for_die = tag == DW_TAG_volatile_type; break;
+                case Type::indirect_typedef:        get_type_for_die = tag == DW_TAG_typedef; break;
+                case Type::indirect_pointer:        get_type_for_die = tag == DW_TAG_pointer_type; break;
+                case Type::indirect_reference:  get_type_for_die = tag == DW_TAG_reference_type; break;
+
+                case Type::user_defined_type:
+                    switch (tag)
+                    {
+                    case DW_TAG_array_type:
+                        get_type_for_die = UserDefTypeArray::OwnsUserDefTypeUID(udt_uid);
+                        break;
+
+                    case DW_TAG_structure_type:
+                    case DW_TAG_union_type:
+                    case DW_TAG_class_type:
+                        get_type_for_die = UserDefTypeStruct::OwnsUserDefTypeUID(udt_uid);
+                        break;
+
+                    case DW_TAG_enumeration_type:
+                        get_type_for_die = UserDefTypeEnum::OwnsUserDefTypeUID(udt_uid);
+                        break;
+
+                    case DW_TAG_subprogram:
+                    case DW_TAG_subroutine_type:
+                        get_type_for_die = UserDefTypeFunction::OwnsUserDefTypeUID(udt_uid);
+                        break;
+                    }
+                }
+            }
+        }
+
+        if (get_type_for_die)
+        {
+            TypeSP owning_type_sp;
+            TypeSP type_sp(GetTypeForDIE(cu_sp.get(), die, owning_type_sp, NULL, 0, 0));
+
+            if (type_sp.get())
+            {
+                // See if we are filtering results based on encoding?
+                bool add_type = (encoding == Type::invalid);
+                if (!add_type)
+                {
+                    // We are filtering base on encoding, so lets check the resulting type encoding
+                    add_type = (encoding == type_sp->GetEncoding());
+                    if (add_type)
+                    {
+                        // The type encoding matches, if this is a user defined type, lets
+                        // make sure the exact user define type uid matches if one was provided
+                        if (encoding == Type::user_defined_type && udt_uid != LLDB_INVALID_UID)
+                        {
+                            UserDefType* udt = type_sp->GetUserDefinedType().get();
+                            if (udt)
+                                add_type = udt->UserDefinedTypeUID() == udt_uid;
+                        }
+                    }
+                }
+                // Add the type to our list as long as everything matched
+                if (add_type)
+                {
+                    types.InsertUnique(type_sp);
+                    if (++num_matches >= max_matches)
+                        break;
+                }
+            }
+        }
+    }
+
+    // Return the number of variable that were appended to the list
+    return types.Size() - original_size;
+}
+
+#endif
+
+
+size_t
+SymbolFileDWARF::ParseChildParameters
+(
+    const SymbolContext& sc,
+    TypeSP& type_sp,
+    const DWARFCompileUnit* dwarf_cu,
+    const DWARFDebugInfoEntry *parent_die,
+    TypeList* type_list,
+    std::vector<void *>& function_param_types,
+    std::vector<clang::ParmVarDecl*>& function_param_decls
+)
+{
+    if (parent_die == NULL)
+        return 0;
+
+    size_t count = 0;
+    const DWARFDebugInfoEntry *die;
+    for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
+    {
+        dw_tag_t tag = die->Tag();
+        switch (tag)
+        {
+        case DW_TAG_formal_parameter:
+            {
+                DWARFDebugInfoEntry::Attributes attributes;
+                const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes);
+                if (num_attributes > 0)
+                {
+                    const char *name = NULL;
+                    Declaration decl;
+                    dw_offset_t param_type_die_offset = DW_INVALID_OFFSET;
+                    // one of None, Auto, Register, Extern, Static, PrivateExtern
+
+                    clang::VarDecl::StorageClass storage = clang::VarDecl::None;
+                    uint32_t i;
+                    for (i=0; i<num_attributes; ++i)
+                    {
+                        const dw_attr_t attr = attributes.AttributeAtIndex(i);
+                        DWARFFormValue form_value;
+                        if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                        {
+                            switch (attr)
+                            {
+                            case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+                            case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break;
+                            case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+                            case DW_AT_name:        name = form_value.AsCString(&get_debug_str_data()); break;
+                            case DW_AT_type:        param_type_die_offset = form_value.Reference(dwarf_cu); break;
+                            case DW_AT_location:
+    //                          if (form_value.BlockData())
+    //                          {
+    //                              const DataExtractor& debug_info_data = debug_info();
+    //                              uint32_t block_length = form_value.Unsigned();
+    //                              DataExtractor location(debug_info_data, form_value.BlockData() - debug_info_data.GetDataStart(), block_length);
+    //                          }
+    //                          else
+    //                          {
+    //                          }
+    //                          break;
+                            case DW_AT_artificial:
+                            case DW_AT_const_value:
+                            case DW_AT_default_value:
+                            case DW_AT_description:
+                            case DW_AT_endianity:
+                            case DW_AT_is_optional:
+                            case DW_AT_segment:
+                            case DW_AT_variable_parameter:
+                            default:
+                            case DW_AT_abstract_origin:
+                            case DW_AT_sibling:
+                                break;
+                            }
+                        }
+                    }
+                    Type *dc_type = ResolveTypeUID(param_type_die_offset);
+                    if (dc_type)
+                    {
+                        function_param_types.push_back (dc_type->GetOpaqueClangQualType());
+
+                        clang::ParmVarDecl *param_var_decl = type_list->GetClangASTContext().CreateParmeterDeclaration (name, dc_type->GetOpaqueClangQualType(), storage);
+                        assert(param_var_decl);
+                        function_param_decls.push_back(param_var_decl);
+                    }
+                }
+            }
+            break;
+
+        default:
+            break;
+        }
+    }
+    return count;
+}
+
+size_t
+SymbolFileDWARF::ParseChildEnumerators
+(
+    const SymbolContext& sc,
+    TypeSP& type_sp,
+    void * enumerator_qual_type,
+    uint32_t enumerator_byte_size,
+    const DWARFCompileUnit* dwarf_cu,
+    const DWARFDebugInfoEntry *parent_die
+)
+{
+    if (parent_die == NULL)
+        return 0;
+
+    size_t enumerators_added = 0;
+    const DWARFDebugInfoEntry *die;
+    for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
+    {
+        const dw_tag_t tag = die->Tag();
+        if (tag == DW_TAG_enumerator)
+        {
+            DWARFDebugInfoEntry::Attributes attributes;
+            const size_t num_child_attributes = die->GetAttributes(this, dwarf_cu, attributes);
+            if (num_child_attributes > 0)
+            {
+                const char *name = NULL;
+                bool got_value = false;
+                int64_t enum_value = 0;
+                Declaration decl;
+
+                uint32_t i;
+                for (i=0; i<num_child_attributes; ++i)
+                {
+                    const dw_attr_t attr = attributes.AttributeAtIndex(i);
+                    DWARFFormValue form_value;
+                    if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                    {
+                        switch (attr)
+                        {
+                        case DW_AT_const_value:
+                            got_value = true;
+                            enum_value = form_value.Unsigned();
+                            break;
+
+                        case DW_AT_name:
+                            name = form_value.AsCString(&get_debug_str_data());
+                            break;
+
+                        case DW_AT_description:
+                        default:
+                        case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+                        case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break;
+                        case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+                        case DW_AT_sibling:
+                            break;
+                        }
+                    }
+                }
+
+                if (name && name[0] && got_value)
+                {
+                    TypeList* type_list = m_obj_file->GetModule()->GetTypeList();
+                    type_list->GetClangASTContext().AddEnumerationValueToEnumerationType (type_sp->GetOpaqueClangQualType(), enumerator_qual_type, decl, name, enum_value, enumerator_byte_size * 8);
+                    ++enumerators_added;
+                }
+            }
+        }
+    }
+    return enumerators_added;
+}
+
+void
+SymbolFileDWARF::ParseChildArrayInfo
+(
+    const SymbolContext& sc,
+    const DWARFCompileUnit* dwarf_cu,
+    const DWARFDebugInfoEntry *parent_die,
+    int64_t& first_index,
+    std::vector<uint64_t>& element_orders,
+    uint32_t& byte_stride,
+    uint32_t& bit_stride
+)
+{
+    if (parent_die == NULL)
+        return;
+
+    const DWARFDebugInfoEntry *die;
+    for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
+    {
+        const dw_tag_t tag = die->Tag();
+        switch (tag)
+        {
+        case DW_TAG_enumerator:
+            {
+                DWARFDebugInfoEntry::Attributes attributes;
+                const size_t num_child_attributes = die->GetAttributes(this, dwarf_cu, attributes);
+                if (num_child_attributes > 0)
+                {
+                    const char *name = NULL;
+                    bool got_value = false;
+                    int64_t enum_value = 0;
+
+                    uint32_t i;
+                    for (i=0; i<num_child_attributes; ++i)
+                    {
+                        const dw_attr_t attr = attributes.AttributeAtIndex(i);
+                        DWARFFormValue form_value;
+                        if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                        {
+                            switch (attr)
+                            {
+                            case DW_AT_const_value:
+                                got_value = true;
+                                enum_value = form_value.Unsigned();
+                                break;
+
+                            case DW_AT_name:
+                                name = form_value.AsCString(&get_debug_str_data());
+                                break;
+
+                            case DW_AT_description:
+                            default:
+                            case DW_AT_decl_file:
+                            case DW_AT_decl_line:
+                            case DW_AT_decl_column:
+                            case DW_AT_sibling:
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+            break;
+
+        case DW_TAG_subrange_type:
+            {
+                DWARFDebugInfoEntry::Attributes attributes;
+                const size_t num_child_attributes = die->GetAttributes(this, dwarf_cu, attributes);
+                if (num_child_attributes > 0)
+                {
+                    const char *name = NULL;
+                    bool got_value = false;
+                    uint64_t byte_size = 0;
+                    int64_t enum_value = 0;
+                    uint64_t num_elements = 0;
+                    uint64_t lower_bound = 0;
+                    uint64_t upper_bound = 0;
+                    uint32_t i;
+                    for (i=0; i<num_child_attributes; ++i)
+                    {
+                        const dw_attr_t attr = attributes.AttributeAtIndex(i);
+                        DWARFFormValue form_value;
+                        if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                        {
+                            switch (attr)
+                            {
+                            case DW_AT_const_value:
+                                got_value = true;
+                                enum_value = form_value.Unsigned();
+                                break;
+
+                            case DW_AT_name:
+                                name = form_value.AsCString(&get_debug_str_data());
+                                break;
+
+                            case DW_AT_count:
+                                num_elements = form_value.Unsigned();
+                                break;
+
+                            case DW_AT_bit_stride:
+                                bit_stride = form_value.Unsigned();
+                                break;
+
+                            case DW_AT_byte_stride:
+                                byte_stride = form_value.Unsigned();
+                                break;
+
+                            case DW_AT_byte_size:
+                                byte_size = form_value.Unsigned();
+                                break;
+
+                            case DW_AT_lower_bound:
+                                lower_bound = form_value.Unsigned();
+                                break;
+
+                            case DW_AT_upper_bound:
+                                upper_bound = form_value.Unsigned();
+                                break;
+
+                            default:
+                                //printf("0x%8.8x: %-30s skipping attribute at 0x%8.8x: %s\n", die->GetOffset(), DW_TAG_value_to_name(tag), attributes.die_offsets[i], DW_AT_value_to_name(attr));  // remove this, debug only
+
+                            case DW_AT_abstract_origin:
+                            case DW_AT_accessibility:
+                            case DW_AT_allocated:
+                            case DW_AT_associated:
+                            case DW_AT_data_location:
+                            case DW_AT_declaration:
+                            case DW_AT_description:
+                            case DW_AT_sibling:
+                            case DW_AT_threads_scaled:
+                            case DW_AT_type:
+                            case DW_AT_visibility:
+                                break;
+                            }
+                        }
+                    }
+
+                    if (upper_bound > lower_bound)
+                        num_elements = upper_bound - lower_bound + 1;
+
+                    if (num_elements > 0)
+                        element_orders.push_back (num_elements);
+                }
+            }
+            break;
+        }
+    }
+}
+
+Type*
+SymbolFileDWARF::GetUniquedTypeForDIEOffset(dw_offset_t type_die_offset, TypeSP& owning_type_sp, int32_t child_type, uint32_t idx, bool safe)
+{
+    if (type_die_offset != DW_INVALID_OFFSET)
+    {
+        DWARFCompileUnitSP cu_sp;
+        const DWARFDebugInfoEntry* type_die = DebugInfo()->GetDIEPtr(type_die_offset, &cu_sp);
+        assert(type_die != NULL);
+        GetTypeForDIE(cu_sp.get(), type_die, owning_type_sp, child_type, idx);
+        // Return the uniqued type if there is one
+        Type* type = (Type*)type_die->GetUserData();
+        if (type == DIE_IS_BEING_PARSED && safe)
+            return NULL;
+        return type;
+    }
+    return NULL;
+}
+
+TypeSP
+SymbolFileDWARF::GetTypeForDIE(DWARFCompileUnit *cu, const DWARFDebugInfoEntry* die, TypeSP& owning_type_sp, int32_t child_type, uint32_t idx)
+{
+    TypeSP type_sp;
+    if (die != NULL)
+    {
+        assert(cu != NULL);
+        Type *type_ptr = (Type *)die->GetUserData();
+        if (type_ptr == NULL)
+        {
+            SymbolContext sc(GetCompUnitForDWARFCompUnit(cu));
+            bool type_is_new = false;
+            type_sp = ParseType(sc, cu, die, type_is_new);
+            type_ptr = (Type *)die->GetUserData();
+            if (owning_type_sp.get() == NULL)
+                owning_type_sp = type_sp;
+        }
+        else if (type_ptr != DIE_IS_BEING_PARSED)
+        {
+            // Grab the existing type from the master types lists
+            type_sp = m_obj_file->GetModule()->GetTypeList()->FindType(type_ptr->GetID());
+        }
+
+    }
+    return type_sp;
+}
+
+clang::DeclContext *
+SymbolFileDWARF::GetClangDeclContextForDIEOffset (dw_offset_t die_offset)
+{
+    if (die_offset != DW_INVALID_OFFSET)
+    {
+        DWARFCompileUnitSP cu_sp;
+        const DWARFDebugInfoEntry* die = DebugInfo()->GetDIEPtr(die_offset, &cu_sp);
+        return GetClangDeclContextForDIE (cu_sp.get(), die);
+    }
+    return NULL;
+}
+
+
+
+clang::DeclContext *
+SymbolFileDWARF::GetClangDeclContextForDIE (const DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
+{
+    DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find(die);
+    if (pos != m_die_to_decl_ctx.end())
+        return pos->second;
+
+    while (die != NULL)
+    {
+        switch (die->Tag())
+        {
+        case DW_TAG_namespace:
+            {
+                const char *namespace_name = die->GetAttributeValueAsString(this, cu, DW_AT_name, NULL);
+                if (namespace_name)
+                {
+                    TypeList* type_list = m_obj_file->GetModule()->GetTypeList();
+                    assert(type_list);
+                    Declaration decl;   // TODO: fill in the decl object
+                    clang::NamespaceDecl *namespace_decl = type_list->GetClangASTContext().GetUniqueNamespaceDeclaration (namespace_name, decl, GetClangDeclContextForDIE (cu, die->GetParent()));
+                    if (namespace_decl)
+                        m_die_to_decl_ctx[die] = (clang::DeclContext*)namespace_decl;
+                    return namespace_decl;
+                }
+            }
+            break;
+
+        default:
+            break;
+        }
+        clang::DeclContext *decl_ctx;
+        decl_ctx = GetClangDeclContextForDIEOffset (die->GetAttributeValueAsUnsigned(this, cu, DW_AT_specification, DW_INVALID_OFFSET));
+        if (decl_ctx)
+            return decl_ctx;
+
+        decl_ctx = GetClangDeclContextForDIEOffset (die->GetAttributeValueAsUnsigned(this, cu, DW_AT_abstract_origin, DW_INVALID_OFFSET));
+        if (decl_ctx)
+            return decl_ctx;
+
+        die = die->GetParent();
+    }
+    return NULL;
+}
+
+TypeSP
+SymbolFileDWARF::ParseType(const SymbolContext& sc, const DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool &type_is_new)
+{
+    TypeSP type_sp;
+
+    uint32_t accessibility = clang::AS_none;
+    if (die != NULL)
+    {
+        dw_tag_t tag = die->Tag();
+        if (die->GetUserData() == NULL)
+        {
+            type_is_new = true;
+
+            bool is_forward_declaration = false;
+            DWARFDebugInfoEntry::Attributes attributes;
+            const char *type_name_cstr = NULL;
+            ConstString type_name_dbstr;
+            Type::EncodingUIDType encoding_uid_type = Type::eIsTypeWithUID;
+            void *clang_type = NULL;
+
+            TypeList* type_list = m_obj_file->GetModule()->GetTypeList();
+            dw_attr_t attr;
+
+            switch (tag)
+            {
+            case DW_TAG_base_type:
+            case DW_TAG_pointer_type:
+            case DW_TAG_reference_type:
+            case DW_TAG_typedef:
+            case DW_TAG_const_type:
+            case DW_TAG_restrict_type:
+            case DW_TAG_volatile_type:
+                {
+                    //printf("0x%8.8x: %s (ParesTypes)\n", die->GetOffset(), DW_TAG_value_to_name(tag));
+                    // Set a bit that lets us know that we are currently parsing this
+                    const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(DIE_IS_BEING_PARSED);
+
+                    const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes);
+                    Declaration decl;
+                    uint32_t encoding = 0;
+                    size_t byte_size = 0;
+                    lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
+
+                    if (num_attributes > 0)
+                    {
+                        uint32_t i;
+                        for (i=0; i<num_attributes; ++i)
+                        {
+                            attr = attributes.AttributeAtIndex(i);
+                            DWARFFormValue form_value;
+                            if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                            {
+                                switch (attr)
+                                {
+                                case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+                                case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break;
+                                case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+                                case DW_AT_name:
+                                    type_name_cstr = form_value.AsCString(&get_debug_str_data());
+                                    type_name_dbstr.SetCString(type_name_cstr);
+                                    break;
+                                case DW_AT_byte_size:   byte_size = form_value.Unsigned();  break;
+                                case DW_AT_encoding:    encoding = form_value.Unsigned(); break;
+                                case DW_AT_type:        encoding_uid = form_value.Reference(dwarf_cu); break;
+                                default:
+                                case DW_AT_sibling:
+                                    break;
+                                }
+                            }
+                        }
+                    }
+
+                    switch (tag)
+                    {
+                    default:
+                    case DW_TAG_base_type:
+                        clang_type = type_list->GetClangASTContext().GetBuiltinTypeForDWARFEncodingAndBitSize (type_name_cstr, encoding, byte_size * 8);
+                        break;
+
+                    case DW_TAG_pointer_type:
+                        // The encoding_uid will be embedded into the
+                        // Type object and will be looked up when the Type::GetOpaqueClangQualType()
+                        encoding_uid_type = Type::ePointerToTypeWithUID;
+                        break;
+
+                    case DW_TAG_reference_type:
+                        // The encoding_uid will be embedded into the
+                        // Type object and will be looked up when the Type::GetOpaqueClangQualType()
+                        encoding_uid_type = Type::eLValueReferenceToTypeWithUID;
+                        break;
+
+                    case DW_TAG_typedef:
+                        // The encoding_uid will be embedded into the
+                        // Type object and will be looked up when the Type::GetOpaqueClangQualType()
+                        encoding_uid_type = Type::eTypedefToTypeWithUID;
+                        break;
+
+                    case DW_TAG_const_type:
+                        // The encoding_uid will be embedded into the
+                        // Type object and will be looked up when the Type::GetOpaqueClangQualType()
+                        encoding_uid_type = Type::eIsConstTypeWithUID; //ClangASTContext::AddConstModifier (clang_type);
+                        break;
+
+                    case DW_TAG_restrict_type:
+                        // The encoding_uid will be embedded into the
+                        // Type object and will be looked up when the Type::GetOpaqueClangQualType()
+                        encoding_uid_type = Type::eIsRestrictTypeWithUID; //ClangASTContext::AddRestrictModifier (clang_type);
+                        break;
+
+                    case DW_TAG_volatile_type:
+                        // The encoding_uid will be embedded into the
+                        // Type object and will be looked up when the Type::GetOpaqueClangQualType()
+                        encoding_uid_type = Type::eIsVolatileTypeWithUID; //ClangASTContext::AddVolatileModifier (clang_type);
+                        break;
+                    }
+
+                    type_sp.reset( new Type(die->GetOffset(), this, type_name_dbstr, byte_size, NULL, encoding_uid, encoding_uid_type, &decl, clang_type));
+
+                    const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(type_sp.get());
+
+
+//                  Type* encoding_type = GetUniquedTypeForDIEOffset(encoding_uid, type_sp, NULL, 0, 0, false);
+//                  if (encoding_type != NULL)
+//                  {
+//                      if (encoding_type != DIE_IS_BEING_PARSED)
+//                          type_sp->SetEncodingType(encoding_type);
+//                      else
+//                          m_indirect_fixups.push_back(type_sp.get());
+//                  }
+                }
+                break;
+
+            case DW_TAG_structure_type:
+            case DW_TAG_union_type:
+            case DW_TAG_class_type:
+                {
+                    //printf("0x%8.8x: %s (ParesTypes)\n", die->GetOffset(), DW_TAG_value_to_name(tag));
+                    // Set a bit that lets us know that we are currently parsing this
+                    const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(DIE_IS_BEING_PARSED);
+
+                    size_t byte_size = 0;
+                    //bool struct_is_class = false;
+                    Declaration decl;
+                    const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes);
+                    if (num_attributes > 0)
+                    {
+                        uint32_t i;
+                        for (i=0; i<num_attributes; ++i)
+                        {
+                            attr = attributes.AttributeAtIndex(i);
+                            DWARFFormValue form_value;
+                            if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                            {
+                                switch (attr)
+                                {
+                                case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+                                case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break;
+                                case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+                                case DW_AT_name:
+                                    type_name_cstr = form_value.AsCString(&get_debug_str_data());
+                                    type_name_dbstr.SetCString(type_name_cstr);
+                                    break;
+                                case DW_AT_byte_size:   byte_size = form_value.Unsigned(); break;
+                                case DW_AT_accessibility: accessibility = DwarfToClangAccessibility(form_value.Unsigned()); break; break;
+                                case DW_AT_declaration: is_forward_declaration = form_value.Unsigned() != 0; break;
+                                case DW_AT_allocated:
+                                case DW_AT_associated:
+                                case DW_AT_data_location:
+                                case DW_AT_description:
+                                case DW_AT_start_scope:
+                                case DW_AT_visibility:
+                                default:
+                                case DW_AT_sibling:
+                                    break;
+                                }
+                            }
+                        }
+                    }
+
+                    int tag_decl_kind = -1;
+                    int default_accessibility = clang::AS_none;
+                    if (tag == DW_TAG_structure_type)
+                    {
+                        tag_decl_kind = clang::TTK_Struct;
+                        default_accessibility = clang::AS_public;
+                    }
+                    else if (tag == DW_TAG_union_type)
+                    {
+                        tag_decl_kind = clang::TTK_Union;
+                        default_accessibility = clang::AS_public;
+                    }
+                    else if (tag == DW_TAG_class_type)
+                    {
+                        tag_decl_kind = clang::TTK_Class;
+                        default_accessibility = clang::AS_private;
+                    }
+
+                    assert (tag_decl_kind != -1);
+                    clang_type = type_list->GetClangASTContext().CreateRecordType (type_name_cstr, tag_decl_kind, GetClangDeclContextForDIE (dwarf_cu, die));
+
+                    m_die_to_decl_ctx[die] = ClangASTContext::GetDeclContextForType (clang_type);
+                    type_sp.reset( new Type(die->GetOffset(), this, type_name_dbstr, byte_size, NULL, LLDB_INVALID_UID, Type::eIsTypeWithUID, &decl, clang_type));
+
+                    const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(type_sp.get());
+
+//                  assert(type_sp.get());
+//                  if (accessibility)
+//                      type_sp->SetAccess(accessibility);
+//
+                    type_list->GetClangASTContext().StartTagDeclarationDefinition (clang_type);
+                    if (die->HasChildren())
+                    {
+                        std::vector<clang::CXXBaseSpecifier *> base_classes;
+                        std::vector<int> member_accessibilities;
+                        bool is_a_class = false;
+                        ParseChildMembers(sc, type_sp, dwarf_cu, die, base_classes, member_accessibilities, default_accessibility, is_a_class);
+                        // If we have a DW_TAG_structure_type instead of a DW_TAG_class_type we
+                        // need to tell the clang type it is actually a class.
+                        if (is_a_class && tag_decl_kind != clang::TTK_Class)
+                            type_list->GetClangASTContext().SetTagTypeKind (clang_type, clang::TTK_Class);
+
+                        // Since DW_TAG_structure_type gets used for both classes
+                        // and structures, we may need to set any DW_TAG_member
+                        // fields to have a "private" access if none was specified.
+                        // When we parsed the child members we tracked that actual
+                        // accessibility value for each DW_TAG_member in the
+                        // "member_accessibilities" array. If the value for the
+                        // member is zero, then it was set to the "default_accessibility"
+                        // which for structs was "public". Below we correct this
+                        // by setting any fields to "private" that weren't correctly
+                        // set.
+                        if (is_a_class && !member_accessibilities.empty())
+                        {
+                            // This is a class and all members that didn't have
+                            // their access specified are private.
+                            type_list->GetClangASTContext().SetDefaultAccessForRecordFields (clang_type, clang::AS_private, member_accessibilities.data(), member_accessibilities.size());
+                        }
+
+                        if (!base_classes.empty())
+                        {
+                            type_list->GetClangASTContext().SetBaseClassesForClassType (clang_type, base_classes.data(), base_classes.size());
+                        }
+                    }
+                    type_list->GetClangASTContext().CompleteTagDeclarationDefinition (clang_type);
+                }
+                break;
+
+            case DW_TAG_enumeration_type:
+                {
+                    //printf("0x%8.8x: %s (ParesTypes)\n", die->GetOffset(), DW_TAG_value_to_name(tag));
+                    // Set a bit that lets us know that we are currently parsing this
+                    const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(DIE_IS_BEING_PARSED);
+
+                    size_t byte_size = 0;
+                    lldb::user_id_t encoding_uid = DW_INVALID_OFFSET;
+                    Declaration decl;
+
+                    const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes);
+                    if (num_attributes > 0)
+                    {
+                        uint32_t i;
+
+                        for (i=0; i<num_attributes; ++i)
+                        {
+                            attr = attributes.AttributeAtIndex(i);
+                            DWARFFormValue form_value;
+                            if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                            {
+                                switch (attr)
+                                {
+                                case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+                                case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break;
+                                case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+                                case DW_AT_name:
+                                    type_name_cstr = form_value.AsCString(&get_debug_str_data());
+                                    type_name_dbstr.SetCString(type_name_cstr);
+                                    break;
+                                case DW_AT_type:        encoding_uid = form_value.Reference(dwarf_cu); break;
+                                case DW_AT_byte_size:   byte_size = form_value.Unsigned(); break;
+                                case DW_AT_accessibility: accessibility = DwarfToClangAccessibility(form_value.Unsigned()); break;
+                                case DW_AT_declaration: is_forward_declaration = form_value.Unsigned() != 0; break;
+                                case DW_AT_allocated:
+                                case DW_AT_associated:
+                                case DW_AT_bit_stride:
+                                case DW_AT_byte_stride:
+                                case DW_AT_data_location:
+                                case DW_AT_description:
+                                case DW_AT_start_scope:
+                                case DW_AT_visibility:
+                                case DW_AT_specification:
+                                case DW_AT_abstract_origin:
+                                case DW_AT_sibling:
+                                    break;
+                                }
+                            }
+                        }
+
+                        clang_type = type_list->GetClangASTContext().CreateEnumerationType(decl, type_name_cstr);
+                        m_die_to_decl_ctx[die] = ClangASTContext::GetDeclContextForType (clang_type);
+                        type_sp.reset( new Type(die->GetOffset(), this, type_name_dbstr, byte_size, NULL, encoding_uid, Type::eIsTypeWithUID, &decl, clang_type));
+
+                        const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(type_sp.get());
+
+                        if (die->HasChildren())
+                        {
+                            type_list->GetClangASTContext().StartTagDeclarationDefinition (clang_type);
+                            void *enumerator_qual_type = type_list->GetClangASTContext().GetBuiltinTypeForDWARFEncodingAndBitSize (NULL, DW_ATE_signed, byte_size * 8);
+                            ParseChildEnumerators(sc, type_sp, enumerator_qual_type, byte_size, dwarf_cu, die);
+                            type_list->GetClangASTContext().CompleteTagDeclarationDefinition (clang_type);
+                        }
+                    }
+                }
+                break;
+
+            case DW_TAG_subprogram:
+            case DW_TAG_subroutine_type:
+                {
+                    //printf("0x%8.8x: %s (ParesTypes)\n", die->GetOffset(), DW_TAG_value_to_name(tag));
+                    // Set a bit that lets us know that we are currently parsing this
+                    const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(DIE_IS_BEING_PARSED);
+
+                    const char *mangled = NULL;
+                    dw_offset_t type_die_offset = DW_INVALID_OFFSET;
+                    Declaration decl;
+                    bool isVariadic = false;
+                    bool is_inline = false;
+                    unsigned type_quals = 0;
+                    clang::FunctionDecl::StorageClass storage = clang::FunctionDecl::None;//, Extern, Static, PrivateExtern
+
+
+                    const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes);
+                    if (num_attributes > 0)
+                    {
+                        uint32_t i;
+                        for (i=0; i<num_attributes; ++i)
+                        {
+                            attr = attributes.AttributeAtIndex(i);
+                            DWARFFormValue form_value;
+                            if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                            {
+                                switch (attr)
+                                {
+                                case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+                                case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break;
+                                case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+                                case DW_AT_name:
+                                    type_name_cstr = form_value.AsCString(&get_debug_str_data());
+                                    type_name_dbstr.SetCString(type_name_cstr);
+                                    break;
+
+                                case DW_AT_MIPS_linkage_name:   mangled = form_value.AsCString(&get_debug_str_data()); break;
+                                case DW_AT_type:                type_die_offset = form_value.Reference(dwarf_cu); break;
+                                case DW_AT_accessibility:       accessibility = DwarfToClangAccessibility(form_value.Unsigned()); break;
+                                case DW_AT_declaration:         is_forward_declaration = form_value.Unsigned() != 0; break;
+                                case DW_AT_external:
+                                    if (form_value.Unsigned())
+                                    {
+                                        if (storage == clang::FunctionDecl::None)
+                                            storage = clang::FunctionDecl::Extern;
+                                        else
+                                            storage = clang::FunctionDecl::PrivateExtern;
+                                    }
+                                    break;
+                                case DW_AT_inline:
+                                    is_inline = form_value.Unsigned() != 0;
+                                    break;
+
+                                case DW_AT_allocated:
+                                case DW_AT_associated:
+                                case DW_AT_address_class:
+                                case DW_AT_artificial:
+                                case DW_AT_calling_convention:
+                                case DW_AT_data_location:
+                                case DW_AT_elemental:
+                                case DW_AT_entry_pc:
+                                case DW_AT_explicit:
+                                case DW_AT_frame_base:
+                                case DW_AT_high_pc:
+                                case DW_AT_low_pc:
+                                case DW_AT_object_pointer:
+                                case DW_AT_prototyped:
+                                case DW_AT_pure:
+                                case DW_AT_ranges:
+                                case DW_AT_recursive:
+                                case DW_AT_return_addr:
+                                case DW_AT_segment:
+                                case DW_AT_specification:
+                                case DW_AT_start_scope:
+                                case DW_AT_static_link:
+                                case DW_AT_trampoline:
+                                case DW_AT_visibility:
+                                case DW_AT_virtuality:
+                                case DW_AT_vtable_elem_location:
+                                case DW_AT_abstract_origin:
+                                case DW_AT_description:
+                                case DW_AT_sibling:
+                                    break;
+                                }
+                            }
+                        }
+
+                        void *return_clang_type = NULL;
+                        Type *func_type = ResolveTypeUID(type_die_offset);
+                        if (func_type)
+                            return_clang_type = func_type->GetOpaqueClangQualType();
+                        else
+                            return_clang_type = type_list->GetClangASTContext().GetVoidBuiltInType();
+
+                        std::vector<void *> function_param_types;
+                        std::vector<clang::ParmVarDecl*> function_param_decls;
+
+                        // Parse the function children for the parameters
+                        ParseChildParameters(sc, type_sp, dwarf_cu, die, type_list, function_param_types, function_param_decls);
+
+                        clang_type = type_list->GetClangASTContext().CreateFunctionType (return_clang_type, &function_param_types[0], function_param_types.size(), isVariadic, type_quals);
+                        if (type_name_cstr)
+                        {
+                            clang::FunctionDecl *function_decl = type_list->GetClangASTContext().CreateFunctionDeclaration (type_name_cstr, clang_type, storage, is_inline);
+                            // Add the decl to our DIE to decl context map
+                            assert (function_decl);
+                            m_die_to_decl_ctx[die] = function_decl;
+                            if (!function_param_decls.empty())
+                                type_list->GetClangASTContext().SetFunctionParameters (function_decl, function_param_decls.data(), function_param_decls.size());
+                        }
+                        type_sp.reset( new Type(die->GetOffset(), this, type_name_dbstr, 0, NULL, LLDB_INVALID_UID, Type::eIsTypeWithUID, &decl, clang_type));
+
+                        const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(type_sp.get());
+                        assert(type_sp.get());
+                    }
+                }
+                break;
+
+            case DW_TAG_array_type:
+                {
+                    //printf("0x%8.8x: %s (ParesTypes)\n", die->GetOffset(), DW_TAG_value_to_name(tag));
+                    // Set a bit that lets us know that we are currently parsing this
+                    const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(DIE_IS_BEING_PARSED);
+
+                    size_t byte_size = 0;
+                    lldb::user_id_t type_die_offset = DW_INVALID_OFFSET;
+                    Declaration decl;
+                    int64_t first_index = 0;
+                    uint32_t byte_stride = 0;
+                    uint32_t bit_stride = 0;
+                    const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes);
+
+                    if (num_attributes > 0)
+                    {
+                        uint32_t i;
+                        for (i=0; i<num_attributes; ++i)
+                        {
+                            attr = attributes.AttributeAtIndex(i);
+                            DWARFFormValue form_value;
+                            if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                            {
+                                switch (attr)
+                                {
+                                case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+                                case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break;
+                                case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+                                case DW_AT_name:
+                                    type_name_cstr = form_value.AsCString(&get_debug_str_data());
+                                    type_name_dbstr.SetCString(type_name_cstr);
+                                    break;
+
+                                case DW_AT_type:            type_die_offset = form_value.Reference(dwarf_cu); break;
+                                case DW_AT_byte_size:       byte_size = form_value.Unsigned(); break;
+                                case DW_AT_byte_stride:     byte_stride = form_value.Unsigned(); break;
+                                case DW_AT_bit_stride:      bit_stride = form_value.Unsigned(); break;
+                                case DW_AT_accessibility:   accessibility = DwarfToClangAccessibility(form_value.Unsigned()); break;
+                                case DW_AT_declaration:     is_forward_declaration = form_value.Unsigned() != 0; break;
+                                case DW_AT_allocated:
+                                case DW_AT_associated:
+                                case DW_AT_data_location:
+                                case DW_AT_description:
+                                case DW_AT_ordering:
+                                case DW_AT_start_scope:
+                                case DW_AT_visibility:
+                                case DW_AT_specification:
+                                case DW_AT_abstract_origin:
+                                case DW_AT_sibling:
+                                    break;
+                                }
+                            }
+                        }
+
+                        Type *element_type = ResolveTypeUID(type_die_offset);
+
+                        if (element_type)
+                        {
+                            std::vector<uint64_t> element_orders;
+                            ParseChildArrayInfo(sc, dwarf_cu, die, first_index, element_orders, byte_stride, bit_stride);
+                            if (byte_stride == 0 && bit_stride == 0)
+                                byte_stride = element_type->GetByteSize();
+                            void *array_element_type = element_type->GetOpaqueClangQualType();
+                            uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride;
+                            uint64_t num_elements = 0;
+                            std::vector<uint64_t>::const_reverse_iterator pos;
+                            std::vector<uint64_t>::const_reverse_iterator end = element_orders.rend();
+                            for (pos = element_orders.rbegin(); pos != end; ++pos)
+                            {
+                                num_elements = *pos;
+                                clang_type = type_list->GetClangASTContext().CreateArrayType (array_element_type, num_elements, num_elements * array_element_bit_stride);
+                                array_element_type = clang_type;
+                                array_element_bit_stride = array_element_bit_stride * num_elements;
+                            }
+                            ConstString empty_name;
+                            type_sp.reset( new Type(die->GetOffset(), this, empty_name, array_element_bit_stride / 8, NULL, LLDB_INVALID_UID, Type::eIsTypeWithUID, &decl, clang_type));
+                            const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(type_sp.get());
+                        }
+                    }
+                }
+                break;
+
+            default:
+                break;
+            }
+
+            if (type_sp.get())
+            {
+                const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(die);
+                dw_tag_t sc_parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0;
+
+                SymbolContextScope * symbol_context_scope = NULL;
+                if (sc_parent_tag == DW_TAG_compile_unit)
+                {
+                    symbol_context_scope = sc.comp_unit;
+                }
+                else if (sc.function != NULL)
+                {
+                    symbol_context_scope = sc.function->GetBlocks(true).GetBlockByID(sc_parent_die->GetOffset());
+                    if (symbol_context_scope == NULL)
+                        symbol_context_scope = sc.function;
+                }
+
+                if (symbol_context_scope != NULL)
+                {
+                    type_sp->SetSymbolContextScope(symbol_context_scope);
+                }
+
+//              if (udt_sp.get())
+//              {
+//                  if (is_forward_declaration)
+//                      udt_sp->GetFlags().Set(UserDefType::flagIsForwardDefinition);
+//                  type_sp->SetUserDefinedType(udt_sp);
+//              }
+
+                if (type_sp.unique())
+                {
+                    // We are ready to put this type into the uniqued list up at the module level
+                    TypeSP uniqued_type_sp(m_obj_file->GetModule()->GetTypeList()->InsertUnique(type_sp));
+
+                    const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(uniqued_type_sp.get());
+
+                    type_sp = uniqued_type_sp;
+                }
+            }
+        }
+        else
+        {
+            switch (tag)
+            {
+            case DW_TAG_base_type:
+            case DW_TAG_pointer_type:
+            case DW_TAG_reference_type:
+            case DW_TAG_typedef:
+            case DW_TAG_const_type:
+            case DW_TAG_restrict_type:
+            case DW_TAG_volatile_type:
+            case DW_TAG_structure_type:
+            case DW_TAG_union_type:
+            case DW_TAG_class_type:
+            case DW_TAG_enumeration_type:
+            case DW_TAG_subprogram:
+            case DW_TAG_subroutine_type:
+            case DW_TAG_array_type:
+                {
+                    Type *existing_type = (Type*)die->GetUserData();
+                    if (existing_type != DIE_IS_BEING_PARSED)
+                    {
+                        type_sp = m_obj_file->GetModule()->GetTypeList()->FindType(existing_type->GetID());
+                    }
+                }
+                break;
+            default:
+                //assert(!"invalid type tag...");
+                break;
+            }
+        }
+    }
+    return type_sp;
+}
+
+size_t
+SymbolFileDWARF::ParseTypes (const SymbolContext& sc, const DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool parse_siblings, bool parse_children)
+{
+    size_t types_added = 0;
+    while (die != NULL)
+    {
+        bool type_is_new = false;
+        if (ParseType(sc, dwarf_cu, die, type_is_new).get())
+        {
+            if (type_is_new)
+                ++types_added;
+        }
+
+        if (parse_children && die->HasChildren())
+        {
+            if (die->Tag() == DW_TAG_subprogram)
+            {
+                SymbolContext child_sc(sc);
+                child_sc.function = sc.comp_unit->FindFunctionByUID(die->GetOffset()).get();
+                types_added += ParseTypes(child_sc, dwarf_cu, die->GetFirstChild(), true, true);
+            }
+            else
+                types_added += ParseTypes(sc, dwarf_cu, die->GetFirstChild(), true, true);
+        }
+
+        if (parse_siblings)
+            die = die->GetSibling();
+        else
+            die = NULL;
+    }
+    return types_added;
+}
+
+
+size_t
+SymbolFileDWARF::ParseFunctionBlocks (const SymbolContext &sc)
+{
+    assert(sc.comp_unit && sc.function);
+    size_t functions_added = 0;
+    DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnitForUID(sc.comp_unit->GetID());
+    if (dwarf_cu)
+    {
+        dw_offset_t function_die_offset = sc.function->GetID();
+        const DWARFDebugInfoEntry *function_die = dwarf_cu->GetDIEPtr(function_die_offset);
+        if (function_die)
+        {
+            ParseFunctionBlocks(sc, Block::RootID, dwarf_cu, function_die, LLDB_INVALID_ADDRESS, false, true);
+        }
+    }
+
+    return functions_added;
+}
+
+
+size_t
+SymbolFileDWARF::ParseTypes (const SymbolContext &sc)
+{
+    // At least a compile unit must be valid
+    assert(sc.comp_unit);
+    size_t types_added = 0;
+    DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnitForUID(sc.comp_unit->GetID());
+    if (dwarf_cu)
+    {
+        if (sc.function)
+        {
+            dw_offset_t function_die_offset = sc.function->GetID();
+            const DWARFDebugInfoEntry *func_die = dwarf_cu->GetDIEPtr(function_die_offset);
+            if (func_die && func_die->HasChildren())
+            {
+                types_added = ParseTypes(sc, dwarf_cu, func_die->GetFirstChild(), true, true);
+            }
+        }
+        else
+        {
+            const DWARFDebugInfoEntry *dwarf_cu_die = dwarf_cu->DIE();
+            if (dwarf_cu_die && dwarf_cu_die->HasChildren())
+            {
+                types_added = ParseTypes(sc, dwarf_cu, dwarf_cu_die->GetFirstChild(), true, true);
+            }
+        }
+    }
+
+    return types_added;
+}
+
+size_t
+SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)
+{
+    if (sc.comp_unit != NULL)
+    {
+        DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnitForUID(sc.comp_unit->GetID());
+
+        if (dwarf_cu == NULL)
+            return 0;
+
+        if (sc.function)
+        {
+            const DWARFDebugInfoEntry *function_die = dwarf_cu->GetDIEPtr(sc.function->GetID());
+            return ParseVariables(sc, dwarf_cu, function_die->GetFirstChild(), true, true);
+        }
+        else if (sc.comp_unit)
+        {
+            uint32_t vars_added = 0;
+            VariableListSP variables (sc.comp_unit->GetVariableList(false));
+            
+            if (variables.get() == NULL)
+            {
+                variables.reset(new VariableList());
+                sc.comp_unit->SetVariableList(variables);
+
+                // Index if we already haven't to make sure the compile units
+                // get indexed and make their global DIE index list
+                if (!m_indexed)
+                    Index ();
+
+                const size_t num_globals = dwarf_cu->GetNumGlobals();
+                for (size_t idx=0; idx<num_globals; ++idx)
+                {
+                    VariableSP var_sp (ParseVariableDIE(sc, dwarf_cu, dwarf_cu->GetGlobalDIEAtIndex (idx)));
+                    if (var_sp)
+                    {
+                        variables->AddVariable(var_sp);
+                        ++vars_added;
+                    }
+                }
+            }
+            return vars_added;
+        }
+    }
+    return 0;
+}
+
+
+VariableSP
+SymbolFileDWARF::ParseVariableDIE
+(
+    const SymbolContext& sc,
+    const DWARFCompileUnit* dwarf_cu,
+    const DWARFDebugInfoEntry *die
+)
+{
+
+    VariableSP var_sp;
+    
+    const dw_tag_t tag = die->Tag();
+    DWARFDebugInfoEntry::Attributes attributes;
+    const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes);
+    if (num_attributes > 0)
+    {
+        const char *name = NULL;
+        Declaration decl;
+        uint32_t i;
+        TypeSP type_sp;
+        Type *var_type = NULL;
+        DWARFExpression location;
+        bool is_external = false;
+        bool is_artificial = false;
+        uint32_t accessibility = clang::AS_none;
+
+        for (i=0; i<num_attributes; ++i)
+        {
+            dw_attr_t attr = attributes.AttributeAtIndex(i);
+            DWARFFormValue form_value;
+            if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+            {
+                switch (attr)
+                {
+                case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+                case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break;
+                case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+                case DW_AT_name:        name = form_value.AsCString(&get_debug_str_data()); break;
+                case DW_AT_type:        var_type = GetUniquedTypeForDIEOffset(form_value.Reference(dwarf_cu), type_sp, 0, 0, false); break;
+                case DW_AT_external:    is_external = form_value.Unsigned() != 0; break;
+                case DW_AT_location:
+                    {
+                        if (form_value.BlockData())
+                        {
+                            const DataExtractor& debug_info_data = get_debug_info_data();
+
+                            uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
+                            uint32_t block_length = form_value.Unsigned();
+                            location.SetOpcodeData(get_debug_info_data(), block_offset, block_length, NULL);
+                        }
+                        else
+                        {
+                            const DataExtractor&    debug_loc_data = get_debug_loc_data();
+                            const dw_offset_t debug_loc_offset = form_value.Unsigned();
+
+                            size_t loc_list_length = DWARFLocationList::Size(debug_loc_data, debug_loc_offset);
+                            if (loc_list_length > 0)
+                            {
+                                Address base_address(dwarf_cu->GetBaseAddress(), m_obj_file->GetSectionList());
+                                location.SetOpcodeData(debug_loc_data, debug_loc_offset, loc_list_length, &base_address);
+                            }
+                        }
+                    }
+                    break;
+
+                case DW_AT_artificial:      is_artificial = form_value.Unsigned() != 0; break;
+                case DW_AT_accessibility:   accessibility = DwarfToClangAccessibility(form_value.Unsigned()); break;
+                case DW_AT_const_value:
+                case DW_AT_declaration:
+                case DW_AT_description:
+                case DW_AT_endianity:
+                case DW_AT_segment:
+                case DW_AT_start_scope:
+                case DW_AT_visibility:
+                default:
+                case DW_AT_abstract_origin:
+                case DW_AT_sibling:
+                case DW_AT_specification:
+                    break;
+                }
+            }
+        }
+
+        if (location.IsValid())
+        {
+            assert(var_type != DIE_IS_BEING_PARSED);
+
+            ConstString var_name(name);
+
+            ValueType scope = eValueTypeInvalid;
+
+            const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(die);
+            dw_tag_t parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0;
+
+            if (tag == DW_TAG_formal_parameter)
+                scope = eValueTypeVariableArgument;
+            else if (is_external || parent_tag == DW_TAG_compile_unit)
+                scope = eValueTypeVariableGlobal;
+            else
+                scope = eValueTypeVariableLocal;
+
+            SymbolContextScope * symbol_context_scope = NULL;
+            if (parent_tag == DW_TAG_compile_unit)
+            {
+                symbol_context_scope = sc.comp_unit;
+            }
+            else if (sc.function != NULL)
+            {
+                symbol_context_scope = sc.function->GetBlocks(true).GetBlockByID(sc_parent_die->GetOffset());
+                if (symbol_context_scope == NULL)
+                    symbol_context_scope = sc.function;
+            }
+
+            assert(symbol_context_scope != NULL);
+            var_sp.reset (new Variable(die->GetOffset(), 
+                                       var_name, 
+                                       var_type, 
+                                       scope, 
+                                       symbol_context_scope, 
+                                       &decl, 
+                                       location, 
+                                       is_external, 
+                                       is_artificial));
+            const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(var_sp.get());
+        }
+    }
+    return var_sp;
+}
+
+size_t
+SymbolFileDWARF::ParseVariables
+(
+    const SymbolContext& sc,
+    const DWARFCompileUnit* dwarf_cu,
+    const DWARFDebugInfoEntry *orig_die,
+    bool parse_siblings,
+    bool parse_children,
+    VariableList* cc_variable_list
+)
+{
+    if (orig_die == NULL)
+        return 0;
+
+    size_t vars_added = 0;
+    const DWARFDebugInfoEntry *die = orig_die;
+    const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(orig_die);
+    dw_tag_t parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0;
+    VariableListSP variables;
+    switch (parent_tag)
+    {
+    case DW_TAG_compile_unit:
+        if (sc.comp_unit != NULL)
+        {
+            variables = sc.comp_unit->GetVariableList(false);
+            if (variables.get() == NULL)
+            {
+                variables.reset(new VariableList());
+                sc.comp_unit->SetVariableList(variables);
+            }
+        }
+        else
+        {
+            assert(!"Parent DIE was a compile unit, yet we don't have a valid compile unit in the symbol context...");
+            vars_added = 0;
+        }
+        break;
+
+    case DW_TAG_subprogram:
+    case DW_TAG_inlined_subroutine:
+    case DW_TAG_lexical_block:
+        if (sc.function != NULL)
+        {
+            // Check to see if we already have parsed the variables for the given scope
+            variables = sc.function->GetBlocks(true).GetVariableList(sc_parent_die->GetOffset(), false, false);
+            if (variables.get() == NULL)
+            {
+                variables.reset(new VariableList());
+                sc.function->GetBlocks(true).SetVariableList(sc_parent_die->GetOffset(), variables);
+            }
+        }
+        else
+        {
+            assert(!"Parent DIE was a function or block, yet we don't have a function in the symbol context...");
+            vars_added = 0;
+        }
+        break;
+
+    default:
+        assert(!"Didn't find appropriate parent DIE for variable list...");
+        break;
+    }
+
+    // We need to have a variable list at this point that we can add variables to
+    assert(variables.get());
+
+    while (die != NULL)
+    {
+        dw_tag_t tag = die->Tag();
+
+        // Check to see if we have already parsed this variable or constant?
+        if (die->GetUserData() == NULL)
+        {
+            // We haven't already parsed it, lets do that now.
+            if ((tag == DW_TAG_variable) ||
+                (tag == DW_TAG_constant) ||
+                (tag == DW_TAG_formal_parameter && sc.function))
+            {
+                VariableSP var_sp (ParseVariableDIE(sc, dwarf_cu, die));
+                if (var_sp)
+                {
+                    variables->AddVariable(var_sp);
+                    ++vars_added;
+                }
+            }
+        }
+
+        bool skip_children = (sc.function == NULL && tag == DW_TAG_subprogram);
+
+        if (!skip_children && parse_children && die->HasChildren())
+        {
+            vars_added += ParseVariables(sc, dwarf_cu, die->GetFirstChild(), true, true);
+            //vars_added += ParseVariables(sc, dwarf_cu, die->GetFirstChild(), parse_siblings, parse_children);
+        }
+
+        if (parse_siblings)
+            die = die->GetSibling();
+        else
+            die = NULL;
+    }
+
+    if (cc_variable_list)
+    {
+        cc_variable_list->AddVariables(variables.get());
+    }
+
+    return vars_added;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+const char *
+SymbolFileDWARF::GetPluginName()
+{
+    return "SymbolFileDWARF";
+}
+
+const char *
+SymbolFileDWARF::GetShortPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+SymbolFileDWARF::GetPluginVersion()
+{
+    return 1;
+}
+
+void
+SymbolFileDWARF::GetPluginCommandHelp (const char *command, Stream *strm)
+{
+}
+
+Error
+SymbolFileDWARF::ExecutePluginCommand (Args &command, Stream *strm)
+{
+    Error error;
+    error.SetErrorString("No plug-in command are currently supported.");
+    return error;
+}
+
+Log *
+SymbolFileDWARF::EnablePluginLogging (Stream *strm, Args &command)
+{
+    return NULL;
+}
+
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
new file mode 100644
index 0000000..95545a4
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -0,0 +1,331 @@
+//===-- SymbolFileDWARF.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_SymbolFileDWARF_h_
+#define liblldb_SymbolFileDWARF_h_
+
+// C Includes
+// C++ Includes
+#include <list>
+#include <memory>
+#include <map>
+#include <vector>
+
+// Other libraries and framework includes
+#include "llvm/ADT/DenseMap.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Flags.h"
+#include "lldb/Core/UniqueCStringMap.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/SymbolContext.h"
+
+// Project includes
+#include "DWARFDefines.h"
+
+
+//----------------------------------------------------------------------
+// Forward Declarations for this DWARF plugin
+//----------------------------------------------------------------------
+class DWARFAbbreviationDeclaration;
+class DWARFAbbreviationDeclarationSet;
+class DWARFCompileUnit;
+class DWARFDebugAbbrev;
+class DWARFDebugAranges;
+class DWARFDebugInfo;
+class DWARFDebugInfoEntry;
+class DWARFDebugLine;
+class DWARFDebugPubnames;
+class DWARFDebugRanges;
+class DWARFDIECollection;
+class DWARFFormValue;
+
+class SymbolFileDWARF : public lldb_private::SymbolFile
+{
+public:
+    friend class SymbolFileDWARFDebugMap;
+
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static const char *
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb_private::SymbolFile*
+    CreateInstance (lldb_private::ObjectFile* obj_file);
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+                            SymbolFileDWARF(lldb_private::ObjectFile* ofile);
+    virtual                 ~SymbolFileDWARF();
+
+    virtual uint32_t        GetAbilities ();
+
+    //------------------------------------------------------------------
+    // Compile Unit function calls
+    //------------------------------------------------------------------
+    virtual uint32_t        GetNumCompileUnits();
+    virtual lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index);
+
+    virtual size_t          ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc);
+    virtual bool            ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc);
+    virtual bool            ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList& support_files);
+    virtual size_t          ParseFunctionBlocks (const lldb_private::SymbolContext& sc);
+    virtual size_t          ParseTypes (const lldb_private::SymbolContext& sc);
+    virtual size_t          ParseVariablesForContext (const lldb_private::SymbolContext& sc);
+
+    virtual lldb_private::Type*     ResolveTypeUID(lldb::user_id_t type_uid);
+    virtual clang::DeclContext* GetClangDeclContextForTypeUID (lldb::user_id_t type_uid);
+
+    virtual uint32_t        ResolveSymbolContext (const lldb_private::Address& so_addr, uint32_t resolve_scope, lldb_private::SymbolContext& sc);
+    virtual uint32_t        ResolveSymbolContext (const lldb_private::FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, lldb_private::SymbolContextList& sc_list);
+    virtual uint32_t        FindGlobalVariables(const lldb_private::ConstString &name, bool append, uint32_t max_matches, lldb_private::VariableList& variables);
+    virtual uint32_t        FindGlobalVariables(const lldb_private::RegularExpression& regex, bool append, uint32_t max_matches, lldb_private::VariableList& variables);
+    virtual uint32_t        FindFunctions(const lldb_private::ConstString &name, bool append, lldb_private::SymbolContextList& sc_list);
+    virtual uint32_t        FindFunctions(const lldb_private::RegularExpression& regex, bool append, lldb_private::SymbolContextList& sc_list);
+//  virtual uint32_t        FindTypes(const lldb_private::SymbolContext& sc, const lldb_private::ConstString &name, bool append, uint32_t max_matches, lldb::Type::Encoding encoding, lldb::user_id_t udt_uid, lldb_private::TypeList& types);
+//  virtual uint32_t        FindTypes(const lldb_private::SymbolContext& sc, const lldb_private::RegularExpression& regex, bool append, uint32_t max_matches, lldb::Type::Encoding encoding, lldb::user_id_t udt_uid, lldb_private::TypeList& types);
+
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual const char *
+    GetPluginName();
+
+    virtual const char *
+    GetShortPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+    virtual void
+    GetPluginCommandHelp (const char *command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Error
+    ExecutePluginCommand (lldb_private::Args &command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Log *
+    EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
+
+    // Approach 2 - count + accessor
+    // Index compile units would scan the initial compile units and register
+    // them with the module. This would only be done on demand if and only if
+    // the compile units were needed.
+    //virtual size_t        GetCompUnitCount() = 0;
+    //virtual CompUnitSP    GetCompUnitAtIndex(size_t cu_idx) = 0;
+
+    const lldb_private::DataExtractor&      get_debug_abbrev_data();
+    const lldb_private::DataExtractor&      get_debug_aranges_data();
+    const lldb_private::DataExtractor&      get_debug_frame_data();
+    const lldb_private::DataExtractor&      get_debug_info_data();
+    const lldb_private::DataExtractor&      get_debug_line_data();
+    const lldb_private::DataExtractor&      get_debug_loc_data();
+    const lldb_private::DataExtractor&      get_debug_macinfo_data();
+    const lldb_private::DataExtractor&      get_debug_pubnames_data();
+    const lldb_private::DataExtractor&      get_debug_pubtypes_data();
+    const lldb_private::DataExtractor&      get_debug_ranges_data();
+    const lldb_private::DataExtractor&      get_debug_str_data();
+
+    DWARFDebugAbbrev*       DebugAbbrev();
+    const DWARFDebugAbbrev* DebugAbbrev() const;
+
+    DWARFDebugAranges*      DebugAranges();
+    const DWARFDebugAranges*DebugAranges() const;
+
+    DWARFDebugInfo*         DebugInfo();
+    const DWARFDebugInfo*   DebugInfo() const;
+
+//  These shouldn't be used unless we want to dump the DWARF line tables.
+//  DWARFDebugLine*         DebugLine();
+//  const DWARFDebugLine*   DebugLine() const;
+
+//    DWARFDebugPubnames*     DebugPubnames();
+//    const DWARFDebugPubnames* DebugPubnames() const;
+//
+//    DWARFDebugPubnames*     DebugPubBaseTypes();
+//    const DWARFDebugPubnames* DebugPubBaseTypes() const;
+//
+//    DWARFDebugPubnames*     DebugPubtypes();
+//    const DWARFDebugPubnames* DebugPubtypes() const;
+
+    DWARFDebugRanges*       DebugRanges();
+    const DWARFDebugRanges* DebugRanges() const;
+
+    const lldb_private::DataExtractor&
+    GetCachedSectionData (uint32_t got_flag, const lldb_private::ConstString &section_name, lldb_private::DataExtractor &data);
+
+    static bool             SupportedVersion(uint16_t version);
+
+    clang::DeclContext *
+    GetClangDeclContextForDIE (const DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die);
+
+    clang::DeclContext *
+    GetClangDeclContextForDIEOffset (dw_offset_t die_offset);
+
+    lldb_private::Flags&
+    GetFlags ()
+    {
+        return m_flags;
+    }
+
+    const lldb_private::Flags&
+    GetFlags () const
+    {
+        return m_flags;
+    }
+
+protected:
+
+    enum
+    {
+        flagsGotDebugAbbrevData     = (1 << 0),
+        flagsGotDebugArangesData    = (1 << 1),
+        flagsGotDebugFrameData      = (1 << 2),
+        flagsGotDebugInfoData       = (1 << 3),
+        flagsGotDebugLineData       = (1 << 4),
+        flagsGotDebugLocData        = (1 << 5),
+        flagsGotDebugMacInfoData    = (1 << 6),
+        flagsGotDebugPubNamesData   = (1 << 7),
+        flagsGotDebugPubTypesData   = (1 << 8),
+        flagsGotDebugRangesData     = (1 << 9),
+        flagsGotDebugStrData        = (1 << 10),
+        // True if this is a .o file used when resolving a N_OSO entry with
+        // debug maps.
+        flagsDWARFIsOSOForDebugMap  = (1 << 16)
+    };
+
+    DISALLOW_COPY_AND_ASSIGN (SymbolFileDWARF);
+    bool                    ParseCompileUnit(DWARFCompileUnit* cu, lldb::CompUnitSP& compile_unit_sp);
+    DWARFCompileUnit*       GetDWARFCompileUnitForUID(lldb::user_id_t cu_uid);
+    DWARFCompileUnit*       GetNextUnparsedDWARFCompileUnit(DWARFCompileUnit* prev_cu);
+    lldb_private::CompileUnit*      GetCompUnitForDWARFCompUnit(DWARFCompileUnit* cu, uint32_t cu_idx = UINT_MAX);
+    bool                    GetFunction (DWARFCompileUnit* cu, const DWARFDebugInfoEntry* func_die, lldb_private::SymbolContext& sc);
+    lldb_private::Function *        ParseCompileUnitFunction (const lldb_private::SymbolContext& sc, const DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die);
+    size_t                  ParseFunctionBlocks (const lldb_private::SymbolContext& sc,
+                                                 lldb::user_id_t parentBlockID,
+                                                 const DWARFCompileUnit* dwarf_cu,
+                                                 const DWARFDebugInfoEntry *die,
+                                                 lldb::addr_t subprogram_low_pc,
+                                                 bool parse_siblings,
+                                                 bool parse_children);
+    size_t                  ParseTypes (const lldb_private::SymbolContext& sc, const DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool parse_siblings, bool parse_children);
+    lldb::TypeSP            ParseType (const lldb_private::SymbolContext& sc, const DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool &type_is_new);
+
+    lldb::VariableSP        ParseVariableDIE(
+                                const lldb_private::SymbolContext& sc,
+                                const DWARFCompileUnit* dwarf_cu,
+                                const DWARFDebugInfoEntry *die);
+
+    size_t                  ParseVariables(
+                                const lldb_private::SymbolContext& sc,
+                                const DWARFCompileUnit* dwarf_cu,
+                                const DWARFDebugInfoEntry *die,
+                                bool parse_siblings,
+                                bool parse_children,
+                                lldb_private::VariableList* cc_variable_list = NULL);
+
+    size_t                  ParseChildMembers(
+                                const lldb_private::SymbolContext& sc,
+                                lldb::TypeSP& type_sp,
+                                const DWARFCompileUnit* dwarf_cu,
+                                const DWARFDebugInfoEntry *die,
+                                std::vector<clang::CXXBaseSpecifier *>& base_classes,
+                                std::vector<int>& member_accessibilities,
+                                int &default_accessibility,
+                                bool &is_a_class);
+
+    size_t                  ParseChildParameters(
+                                const lldb_private::SymbolContext& sc,
+                                lldb::TypeSP& type_sp,
+                                const DWARFCompileUnit* dwarf_cu,
+                                const DWARFDebugInfoEntry *parent_die,
+                                lldb_private::TypeList* type_list,
+                                std::vector<void *>& function_args,
+                                std::vector<clang::ParmVarDecl*>& function_param_decls);
+
+    size_t                  ParseChildEnumerators(
+                                const lldb_private::SymbolContext& sc,
+                                lldb::TypeSP& type_sp,
+                                void *enumerator_qual_type,
+                                uint32_t enumerator_byte_size,
+                                const DWARFCompileUnit* dwarf_cu,
+                                const DWARFDebugInfoEntry *enum_die);
+
+    void                    ParseChildArrayInfo(
+                                const lldb_private::SymbolContext& sc,
+                                const DWARFCompileUnit* dwarf_cu,
+                                const DWARFDebugInfoEntry *parent_die,
+                                int64_t& first_index,
+                                std::vector<uint64_t>& element_orders,
+                                uint32_t& byte_stride,
+                                uint32_t& bit_stride);
+
+    lldb_private::Type*     GetUniquedTypeForDIEOffset(dw_offset_t type_die_offset, lldb::TypeSP& owning_type_sp, int32_t child_type, uint32_t idx, bool safe);
+    lldb::TypeSP            GetTypeForDIE(DWARFCompileUnit *cu, const DWARFDebugInfoEntry* die, lldb::TypeSP& owning_type_sp, int32_t child_type, uint32_t idx);
+//  uint32_t                FindTypes(std::vector<dw_offset_t> die_offsets, uint32_t max_matches, Type::Encoding encoding, lldb::user_id_t udt_uid, TypeList& types);
+
+    void                    Index();
+
+    lldb_private::Flags             m_flags;
+    lldb_private::DataExtractor     m_dwarf_data; 
+    lldb_private::DataExtractor     m_data_debug_abbrev;
+    lldb_private::DataExtractor     m_data_debug_aranges;
+    lldb_private::DataExtractor     m_data_debug_frame;
+    lldb_private::DataExtractor     m_data_debug_info;
+    lldb_private::DataExtractor     m_data_debug_line;
+    lldb_private::DataExtractor     m_data_debug_loc;
+    lldb_private::DataExtractor     m_data_debug_macinfo;
+    lldb_private::DataExtractor     m_data_debug_pubnames;
+    lldb_private::DataExtractor     m_data_debug_pubtypes;
+    lldb_private::DataExtractor     m_data_debug_ranges;
+    lldb_private::DataExtractor     m_data_debug_str;
+
+    // The auto_ptr items below are generated on demand if and when someone accesses
+    // them through a non const version of this class.
+    std::auto_ptr<DWARFDebugAbbrev>     m_abbr;
+    std::auto_ptr<DWARFDebugAranges>    m_aranges;
+    std::auto_ptr<DWARFDebugInfo>       m_info;
+    std::auto_ptr<DWARFDebugLine>       m_line;
+    lldb_private::UniqueCStringMap<dw_offset_t> m_name_to_function_die; // All concrete functions
+    lldb_private::UniqueCStringMap<dw_offset_t> m_name_to_inlined_die;  // All inlined functions
+    lldb_private::UniqueCStringMap<dw_offset_t> m_name_to_global_die;   // Global and static variables
+    lldb_private::UniqueCStringMap<dw_offset_t> m_name_to_type_die;     // All type DIE offsets
+    bool m_indexed;
+
+//    std::auto_ptr<DWARFDebugPubnames>   m_pubnames;
+//    std::auto_ptr<DWARFDebugPubnames>   m_pubbasetypes; // Just like m_pubtypes, but for DW_TAG_base_type DIEs
+//    std::auto_ptr<DWARFDebugPubnames>   m_pubtypes;
+    std::auto_ptr<DWARFDebugRanges>     m_ranges;
+
+    typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> DIEToDeclContextMap;
+    DIEToDeclContextMap m_die_to_decl_ctx;
+    
+//  TypeFixupColl   m_type_fixups;
+//  std::vector<Type*> m_indirect_fixups;
+
+//#define LLDB_SYMBOL_FILE_DWARF_SHRINK_TEST 1
+#if defined(LLDB_SYMBOL_FILE_DWARF_SHRINK_TEST)
+
+    typedef std::map<FileSpec, DWARFDIECollection> FSToDIES;
+    void ShrinkDSYM(CompileUnit *dc_cu, DWARFCompileUnit *dw_cu, const FileSpec& cu_fspec, const FileSpec& base_types_cu_fspec, FSToDIES& fs_to_dies, const DWARFDebugInfoEntry *die);
+#endif
+};
+
+#endif  // liblldb_SymbolFileDWARF_h_
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
new file mode 100644
index 0000000..7bf968d
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -0,0 +1,873 @@
+//===-- SymbolFileDWARFDebugMap.cpp ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolFileDWARFDebugMap.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/VariableList.h"
+
+#include "SymbolFileDWARF.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+SymbolFileDWARFDebugMap::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance);
+}
+
+void
+SymbolFileDWARFDebugMap::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+const char *
+SymbolFileDWARFDebugMap::GetPluginNameStatic()
+{
+    return "symbol-file.dwarf2-debugmap";
+}
+
+const char *
+SymbolFileDWARFDebugMap::GetPluginDescriptionStatic()
+{
+    return "DWARF and DWARF3 debug symbol file reader (debug map).";
+}
+
+SymbolFile*
+SymbolFileDWARFDebugMap::CreateInstance (ObjectFile* obj_file)
+{
+    return new SymbolFileDWARFDebugMap (obj_file);
+}
+
+
+SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap (ObjectFile* ofile) :
+    SymbolFile(ofile),
+    m_flags(),
+    m_compile_unit_infos(),
+    m_func_indexes(),
+    m_glob_indexes()
+{
+}
+
+
+SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap()
+{
+}
+
+void
+SymbolFileDWARFDebugMap::InitOSO ()
+{
+    if (m_flags.test(kHaveInitializedOSOs))
+        return;
+
+    m_flags.set(kHaveInitializedOSOs);
+    // In order to get the abilities of this plug-in, we look at the list of
+    // N_OSO entries (object files) from the symbol table and make sure that
+    // these files exist and also contain valid DWARF. If we get any of that
+    // then we return the abilities of the first N_OSO's DWARF.
+
+    Symtab* symtab = m_obj_file->GetSymtab();
+    if (symtab)
+    {
+        //StreamFile s(0, 4, eByteOrderHost, stdout);
+        std::vector<uint32_t> oso_indexes;
+        const uint32_t oso_index_count = symtab->AppendSymbolIndexesWithType(eSymbolTypeObjectFile, oso_indexes);
+
+        symtab->AppendSymbolIndexesWithType(eSymbolTypeFunction, m_func_indexes);
+        symtab->AppendSymbolIndexesWithType(eSymbolTypeGlobal, m_glob_indexes);
+
+        symtab->SortSymbolIndexesByValue(m_func_indexes, true);
+        symtab->SortSymbolIndexesByValue(m_glob_indexes, true);
+
+        if (oso_index_count > 0)
+        {
+            m_compile_unit_infos.resize(oso_index_count);
+//          s.Printf("%s N_OSO symbols:\n", __PRETTY_FUNCTION__);
+//          symtab->Dump(&s, oso_indexes);
+
+            for (uint32_t i=0; i<oso_index_count; ++i)
+            {
+                m_compile_unit_infos[i].so_symbol = symtab->SymbolAtIndex(oso_indexes[i] - 1);
+                if (m_compile_unit_infos[i].so_symbol->GetSiblingIndex() == 0)
+                    m_compile_unit_infos[i].so_symbol = symtab->SymbolAtIndex(oso_indexes[i] - 2);
+                m_compile_unit_infos[i].oso_symbol = symtab->SymbolAtIndex(oso_indexes[i]);
+            }
+        }
+    }
+}
+
+Module *
+SymbolFileDWARFDebugMap::GetModuleByOSOIndex (uint32_t oso_idx)
+{
+    const uint32_t cu_count = GetNumCompileUnits();
+    if (oso_idx < cu_count)
+        return GetModuleByCompUnitInfo (&m_compile_unit_infos[oso_idx]);
+    return NULL;
+}
+
+Module *
+SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo (CompileUnitInfo *comp_unit_info)
+{
+    if (comp_unit_info->oso_module_sp.get() == NULL)
+    {
+        Symbol *oso_symbol = comp_unit_info->oso_symbol;
+        if (oso_symbol)
+        {
+            FileSpec oso_file_spec(oso_symbol->GetMangled().GetName().AsCString());
+
+            ModuleList::GetSharedModule (oso_file_spec,
+                                         m_obj_file->GetModule()->GetArchitecture(),
+                                         NULL,  // UUID pointer
+                                         NULL,  // object name
+                                         0,     // object offset
+                                         comp_unit_info->oso_module_sp,
+                                         NULL,
+                                         NULL);
+            //comp_unit_info->oso_module_sp.reset(new Module (oso_file_spec, m_obj_file->GetModule()->GetArchitecture()));
+        }
+    }
+    return comp_unit_info->oso_module_sp.get();
+}
+
+
+bool
+SymbolFileDWARFDebugMap::GetFileSpecForSO (uint32_t oso_idx, FileSpec &file_spec)
+{
+    if (oso_idx < m_compile_unit_infos.size())
+    {
+        if (!m_compile_unit_infos[oso_idx].so_file)
+        {
+
+            if (m_compile_unit_infos[oso_idx].so_symbol == NULL)
+                return false;
+
+            std::string so_path (m_compile_unit_infos[oso_idx].so_symbol->GetMangled().GetName().AsCString());
+            if (m_compile_unit_infos[oso_idx].so_symbol[1].GetType() == eSymbolTypeSourceFile)
+                so_path += m_compile_unit_infos[oso_idx].so_symbol[1].GetMangled().GetName().AsCString();
+            m_compile_unit_infos[oso_idx].so_file.SetFile(so_path.c_str());
+        }
+        file_spec = m_compile_unit_infos[oso_idx].so_file;
+        return true;
+    }
+    return false;
+}
+
+
+
+ObjectFile *
+SymbolFileDWARFDebugMap::GetObjectFileByOSOIndex (uint32_t oso_idx)
+{
+    Module *oso_module = GetModuleByOSOIndex (oso_idx);
+    if (oso_module)
+        return oso_module->GetObjectFile();
+    return NULL;
+}
+
+SymbolFileDWARF *
+SymbolFileDWARFDebugMap::GetSymbolFile (const SymbolContext& sc)
+{
+    CompileUnitInfo *comp_unit_info = GetCompUnitInfo (sc);
+    if (comp_unit_info)
+        return GetSymbolFileByCompUnitInfo (comp_unit_info);
+    return NULL;
+}
+
+ObjectFile *
+SymbolFileDWARFDebugMap::GetObjectFileByCompUnitInfo (CompileUnitInfo *comp_unit_info)
+{
+    Module *oso_module = GetModuleByCompUnitInfo (comp_unit_info);
+    if (oso_module)
+        return oso_module->GetObjectFile();
+    return NULL;
+}
+
+SymbolFileDWARF *
+SymbolFileDWARFDebugMap::GetSymbolFileByOSOIndex (uint32_t oso_idx)
+{
+    if (oso_idx < m_compile_unit_infos.size())
+        return GetSymbolFileByCompUnitInfo (&m_compile_unit_infos[oso_idx]);
+    return NULL;
+}
+
+SymbolFileDWARF *
+SymbolFileDWARFDebugMap::GetSymbolFileByCompUnitInfo (CompileUnitInfo *comp_unit_info)
+{
+    if (comp_unit_info->oso_symbol_vendor == NULL)
+    {
+        ObjectFile *oso_objfile = GetObjectFileByCompUnitInfo (comp_unit_info);
+
+        if (oso_objfile)
+        {
+            comp_unit_info->oso_symbol_vendor = oso_objfile->GetModule()->GetSymbolVendor();
+//          SymbolFileDWARF *oso_dwarf = new SymbolFileDWARF(oso_objfile);
+//          comp_unit_info->oso_dwarf_sp.reset (oso_dwarf);
+            if (comp_unit_info->oso_symbol_vendor)
+            {
+                // Set a bit that lets this DWARF file know that it is being
+                // used along with a debug map and that it will have the
+                // remapped sections that we do below.
+                ((SymbolFileDWARF *)comp_unit_info->oso_symbol_vendor->GetSymbolFile())->GetFlags().Set(SymbolFileDWARF::flagsDWARFIsOSOForDebugMap);
+                comp_unit_info->debug_map_sections_sp.reset(new SectionList);
+
+                Symtab *exe_symtab = m_obj_file->GetSymtab();
+                Module *oso_module = oso_objfile->GetModule();
+                Symtab *oso_symtab = oso_objfile->GetSymtab();
+//#define DEBUG_OSO_DMAP    // Do not check in with this defined...
+#if defined(DEBUG_OSO_DMAP)
+                StreamFile s(stdout);
+                s << "OSO symtab:\n";
+                oso_symtab->Dump(&s, NULL);
+                s << "OSO sections before:\n";
+                oso_objfile->GetSectionList()->Dump(&s, NULL, true);
+#endif
+
+                ///const uint32_t fun_resolve_flags = SymbolContext::Module | eSymbolContextCompUnit | eSymbolContextFunction;
+                //SectionList *oso_sections = oso_objfile->Sections();
+                // Now we need to make sections that map from zero based object
+                // file addresses to where things eneded up in the main executable.
+                uint32_t oso_start_idx = comp_unit_info->oso_symbol->GetID() + 1;
+                const uint32_t oso_end_idx = comp_unit_info->so_symbol->GetSiblingIndex();
+                uint32_t sect_id = 0x10000;
+                for (uint32_t idx = oso_start_idx; idx < oso_end_idx; ++idx)
+                {
+                    Symbol *exe_symbol = exe_symtab->SymbolAtIndex(idx);
+                    if (exe_symbol)
+                    {
+                        switch (exe_symbol->GetType())
+                        {
+                        case eSymbolTypeFunction:
+                            {
+                                // For each N_FUN, or function that we run into in the debug map
+                                // we make a new section that we add to the sections found in the
+                                // .o file. This new section has the file address set to what the
+                                // addresses are in the .o file, and the load address is adjusted
+                                // to match where it ended up in the final executable! We do this
+                                // before we parse any dwarf info so that when it goes get parsed
+                                // all section/offset addresses that get registered will resolve
+                                // correctly to the new addresses in the main executable.
+
+                                // First we find the original symbol in the .o file's symbol table
+                                Symbol *oso_fun_symbol = oso_symtab->FindFirstSymbolWithNameAndType(exe_symbol->GetMangled().GetName(), eSymbolTypeCode);
+                                if (oso_fun_symbol)
+                                {
+                                    // If we found the symbol, then we
+                                    Section* exe_fun_section = const_cast<Section *>(exe_symbol->GetAddressRangePtr()->GetBaseAddress().GetSection());
+                                    Section* oso_fun_section = const_cast<Section *>(oso_fun_symbol->GetAddressRangePtr()->GetBaseAddress().GetSection());
+                                    if (oso_fun_section)
+                                    {
+                                        // Now we create a section that we will add as a child of the
+                                        // section in which the .o symbol (the N_FUN) exists.
+
+                                        // We use the exe_symbol size because the one in the .o file
+                                        // will just be a symbol with no size, and the exe_symbol
+                                        // size will reflect any size changes (ppc has been known to
+                                        // shrink function sizes when it gets rid of jump islands that
+                                        // aren't needed anymore).
+                                        SectionSP oso_fun_section_sp (new Section (const_cast<Section *>(oso_fun_symbol->GetAddressRangePtr()->GetBaseAddress().GetSection()),
+                                                                                   oso_module,                         // Module (the .o file)
+                                                                                   sect_id++,                          // Section ID starts at 0x10000 and increments so the section IDs don't overlap with the standard mach IDs
+                                                                                   exe_symbol->GetMangled().GetName(), // Name the section the same as the symbol for which is was generated!
+                                                                                   eSectionTypeDebug,
+                                                                                   oso_fun_symbol->GetAddressRangePtr()->GetBaseAddress().GetOffset(),  // File VM address offset in the current section
+                                                                                   exe_symbol->GetByteSize(),          // File size (we need the size from the executable)
+                                                                                   0, 0, 0));
+
+                                        oso_fun_section_sp->SetLinkedLocation (exe_fun_section,
+                                                                               exe_symbol->GetValue().GetFileAddress() - exe_fun_section->GetFileAddress());
+                                        oso_fun_section->GetChildren().AddSection(oso_fun_section_sp);
+                                        comp_unit_info->debug_map_sections_sp->AddSection(oso_fun_section_sp);
+                                    }
+                                }
+                            }
+                            break;
+
+                        case eSymbolTypeGlobal:
+                        case eSymbolTypeStatic:
+                            {
+                                // For each N_GSYM we remap the address for the global by making
+                                // a new section that we add to the sections found in the .o file.
+                                // This new section has the file address set to what the
+                                // addresses are in the .o file, and the load address is adjusted
+                                // to match where it ended up in the final executable! We do this
+                                // before we parse any dwarf info so that when it goes get parsed
+                                // all section/offset addresses that get registered will resolve
+                                // correctly to the new addresses in the main executable. We
+                                // initially set the section size to be 1 byte, but will need to
+                                // fix up these addresses further after all globals have been
+                                // parsed to span the gaps, or we can find the global variable
+                                // sizes from the DWARF info as we are parsing.
+
+#if 0
+                                // First we find the non-stab entry that corresponds to the N_GSYM in the executable
+                                Symbol *exe_gsym_symbol = exe_symtab->FindFirstSymbolWithNameAndType(exe_symbol->GetMangled().GetName(), eSymbolTypeData);
+#else
+                                // The mach-o object file parser already matches up the N_GSYM with with the non-stab
+                                // entry, so we shouldn't have to do that. If this ever changes, enable the code above
+                                // in the "#if 0" block. STSYM's always match the symbol as found below.
+                                Symbol *exe_gsym_symbol = exe_symbol;
+#endif
+                                // Next we find the non-stab entry that corresponds to the N_GSYM in the .o file
+                                Symbol *oso_gsym_symbol = oso_symtab->FindFirstSymbolWithNameAndType(exe_symbol->GetMangled().GetName(), eSymbolTypeData);
+                                if (exe_gsym_symbol && oso_gsym_symbol)
+                                {
+                                    // If we found the symbol, then we
+                                    Section* exe_gsym_section = const_cast<Section *>(exe_gsym_symbol->GetAddressRangePtr()->GetBaseAddress().GetSection());
+                                    Section* oso_gsym_section = const_cast<Section *>(oso_gsym_symbol->GetAddressRangePtr()->GetBaseAddress().GetSection());
+                                    if (oso_gsym_section)
+                                    {
+                                        SectionSP oso_gsym_section_sp (new Section (const_cast<Section *>(oso_gsym_symbol->GetAddressRangePtr()->GetBaseAddress().GetSection()),
+                                                                                   oso_module,                         // Module (the .o file)
+                                                                                   sect_id++,                          // Section ID starts at 0x10000 and increments so the section IDs don't overlap with the standard mach IDs
+                                                                                   exe_symbol->GetMangled().GetName(), // Name the section the same as the symbol for which is was generated!
+                                                                                   eSectionTypeDebug,
+                                                                                   oso_gsym_symbol->GetAddressRangePtr()->GetBaseAddress().GetOffset(),  // File VM address offset in the current section
+                                                                                   1,                                   // We don't know the size of the global, just do the main address for now.
+                                                                                   0, 0, 0));
+
+                                        oso_gsym_section_sp->SetLinkedLocation (exe_gsym_section,
+                                                                               exe_gsym_symbol->GetValue().GetFileAddress() - exe_gsym_section->GetFileAddress());
+                                        oso_gsym_section->GetChildren().AddSection(oso_gsym_section_sp);
+                                        comp_unit_info->debug_map_sections_sp->AddSection(oso_gsym_section_sp);
+                                    }
+                                }
+                            }
+                            break;
+
+//                        case eSymbolTypeStatic:
+//                            {
+//                                // For each N_STSYM we remap the address for the global by making
+//                                // a new section that we add to the sections found in the .o file.
+//                                // This new section has the file address set to what the
+//                                // addresses are in the .o file, and the load address is adjusted
+//                                // to match where it ended up in the final executable! We do this
+//                                // before we parse any dwarf info so that when it goes get parsed
+//                                // all section/offset addresses that get registered will resolve
+//                                // correctly to the new addresses in the main executable. We
+//                                // initially set the section size to be 1 byte, but will need to
+//                                // fix up these addresses further after all globals have been
+//                                // parsed to span the gaps, or we can find the global variable
+//                                // sizes from the DWARF info as we are parsing.
+//
+//
+//                                Symbol *exe_stsym_symbol = exe_symbol;
+//                                // First we find the non-stab entry that corresponds to the N_STSYM in the .o file
+//                                Symbol *oso_stsym_symbol = oso_symtab->FindFirstSymbolWithNameAndType(exe_symbol->GetMangled().GetName(), eSymbolTypeData);
+//                                if (exe_stsym_symbol && oso_stsym_symbol)
+//                                {
+//                                    // If we found the symbol, then we
+//                                    Section* exe_stsym_section = const_cast<Section *>(exe_stsym_symbol->GetAddressRangePtr()->GetBaseAddress().GetSection());
+//                                    Section* oso_stsym_section = const_cast<Section *>(oso_stsym_symbol->GetAddressRangePtr()->GetBaseAddress().GetSection());
+//                                    if (oso_stsym_section)
+//                                    {
+//                                        // The load address of the symbol will use the section in the
+//                                        // executable that contains the debug map that corresponds to
+//                                        // the N_FUN symbol. We set the offset to reflect the offset
+//                                        // into that section since we are creating a new section.
+//                                        AddressRange stsym_load_range(exe_stsym_section, exe_stsym_symbol->GetValue().GetFileAddress() - exe_stsym_section->GetFileAddress(), 1);
+//                                        // We need the symbol's section offset address from the .o file, but
+//                                        // we need a non-zero size.
+//                                        AddressRange stsym_file_range(exe_stsym_symbol->GetAddressRangePtr()->GetBaseAddress().GetSection(), exe_stsym_symbol->GetAddressRangePtr()->GetBaseAddress().GetOffset(), 1);
+//
+//                                        // Now we create a section that we will add as a child of the
+//                                        // section in which the .o symbol (the N_FUN) exists.
+//
+//// TODO: mimic what I did for N_FUN if that works...
+////                                        // We use the 1 byte for the size because we don't know the
+////                                        // size of the global symbol without seeing the DWARF.
+////                                        SectionSP oso_fun_section_sp (new Section ( NULL, oso_module,                     // Module (the .o file)
+////                                                                                        sect_id++,                      // Section ID starts at 0x10000 and increments so the section IDs don't overlap with the standard mach IDs
+////                                                                                        exe_symbol->GetMangled().GetName(),// Name the section the same as the symbol for which is was generated!
+////                                                                                       // &stsym_load_range,              // Load offset is the offset into the executable section for the N_FUN from the debug map
+////                                                                                        &stsym_file_range,              // File section/offset is just the same os the symbol on the .o file
+////                                                                                        0, 0, 0));
+////
+////                                        // Now we add the new section to the .o file's sections as a child
+////                                        // of the section in which the N_SECT symbol exists.
+////                                        oso_stsym_section->GetChildren().AddSection(oso_fun_section_sp);
+////                                        comp_unit_info->debug_map_sections_sp->AddSection(oso_fun_section_sp);
+//                                    }
+//                                }
+//                            }
+//                            break;
+                        }
+                    }
+                }
+#if defined(DEBUG_OSO_DMAP)
+                s << "OSO sections after:\n";
+                oso_objfile->GetSectionList()->Dump(&s, NULL, true);
+#endif
+            }
+        }
+    }
+    if (comp_unit_info->oso_symbol_vendor)
+        return (SymbolFileDWARF *)comp_unit_info->oso_symbol_vendor->GetSymbolFile();
+    return NULL;
+}
+
+uint32_t
+SymbolFileDWARFDebugMap::GetAbilities ()
+{
+    // In order to get the abilities of this plug-in, we look at the list of
+    // N_OSO entries (object files) from the symbol table and make sure that
+    // these files exist and also contain valid DWARF. If we get any of that
+    // then we return the abilities of the first N_OSO's DWARF.
+
+    const uint32_t oso_index_count = GetNumCompileUnits();
+    if (oso_index_count > 0)
+    {
+        const uint32_t dwarf_abilities = SymbolFile::CompileUnits |
+                                         SymbolFile::Functions |
+                                         SymbolFile::Blocks |
+                                         SymbolFile::GlobalVariables |
+                                         SymbolFile::LocalVariables |
+                                         SymbolFile::VariableTypes |
+                                         SymbolFile::LineTables;
+
+        for (uint32_t oso_idx=0; oso_idx<oso_index_count; ++oso_idx)
+        {
+            SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx);
+            if (oso_dwarf)
+            {
+                uint32_t oso_abilities = oso_dwarf->GetAbilities();
+                if ((oso_abilities & dwarf_abilities) == dwarf_abilities)
+                    return oso_abilities;
+            }
+        }
+    }
+    return 0;
+}
+
+uint32_t
+SymbolFileDWARFDebugMap::GetNumCompileUnits()
+{
+    InitOSO ();
+    return m_compile_unit_infos.size();
+}
+
+
+CompUnitSP
+SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx)
+{
+    CompUnitSP comp_unit_sp;
+    const uint32_t cu_count = GetNumCompileUnits();
+
+    if (cu_idx < cu_count)
+    {
+        if (m_compile_unit_infos[cu_idx].oso_compile_unit_sp.get() == NULL)
+        {
+            SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (cu_idx);
+            if (oso_dwarf)
+            {
+                // There is only one compile unit for N_OSO entry right now, so
+                // it will always exist at index zero.
+                m_compile_unit_infos[cu_idx].oso_compile_unit_sp = m_compile_unit_infos[cu_idx].oso_symbol_vendor->GetCompileUnitAtIndex (0);
+            }
+
+            if (m_compile_unit_infos[cu_idx].oso_compile_unit_sp.get() == NULL)
+            {
+                // We weren't able to get the DWARF for this N_OSO entry (the
+                // .o file may be missing or not at the specified path), make
+                // one up as best we can from the debug map. We set the uid
+                // of the compile unit to the symbol index with the MSBit set
+                // so that it doesn't collide with any uid values from the DWARF
+                Symbol *so_symbol = m_compile_unit_infos[cu_idx].so_symbol;
+                if (so_symbol)
+                {
+                    m_compile_unit_infos[cu_idx].oso_compile_unit_sp.reset(new CompileUnit (m_obj_file->GetModule(),
+                                                                                            NULL,
+                                                                                            so_symbol->GetMangled().GetName().AsCString(),
+                                                                                            cu_idx,
+                                                                                            Language::Unknown));
+                }
+            }
+        }
+        comp_unit_sp = m_compile_unit_infos[cu_idx].oso_compile_unit_sp;
+    }
+
+    return comp_unit_sp;
+}
+
+SymbolFileDWARFDebugMap::CompileUnitInfo *
+SymbolFileDWARFDebugMap::GetCompUnitInfo (const SymbolContext& sc)
+{
+    const uint32_t cu_count = GetNumCompileUnits();
+    for (uint32_t i=0; i<cu_count; ++i)
+    {
+        if (sc.comp_unit == m_compile_unit_infos[i].oso_compile_unit_sp.get())
+            return &m_compile_unit_infos[i];
+    }
+    return NULL;
+}
+
+size_t
+SymbolFileDWARFDebugMap::ParseCompileUnitFunctions (const SymbolContext& sc)
+{
+    SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc);
+    if (oso_dwarf)
+        return oso_dwarf->ParseCompileUnitFunctions (sc);
+    return 0;
+}
+
+bool
+SymbolFileDWARFDebugMap::ParseCompileUnitLineTable (const SymbolContext& sc)
+{
+    SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc);
+    if (oso_dwarf)
+        return oso_dwarf->ParseCompileUnitLineTable (sc);
+    return false;
+}
+
+bool
+SymbolFileDWARFDebugMap::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList &support_files)
+{
+    SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc);
+    if (oso_dwarf)
+        return oso_dwarf->ParseCompileUnitSupportFiles (sc, support_files);
+    return false;
+}
+
+
+size_t
+SymbolFileDWARFDebugMap::ParseFunctionBlocks (const SymbolContext& sc)
+{
+    SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc);
+    if (oso_dwarf)
+        return oso_dwarf->ParseFunctionBlocks (sc);
+    return 0;
+}
+
+
+size_t
+SymbolFileDWARFDebugMap::ParseTypes (const SymbolContext& sc)
+{
+    SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc);
+    if (oso_dwarf)
+        return oso_dwarf->ParseTypes (sc);
+    return 0;
+}
+
+
+size_t
+SymbolFileDWARFDebugMap::ParseVariablesForContext (const SymbolContext& sc)
+{
+    SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc);
+    if (oso_dwarf)
+        return oso_dwarf->ParseTypes (sc);
+    return 0;
+}
+
+
+
+Type*
+SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid)
+{
+    return NULL;
+}
+
+
+uint32_t
+SymbolFileDWARFDebugMap::ResolveSymbolContext (const Address& exe_so_addr, uint32_t resolve_scope, SymbolContext& sc)
+{
+    uint32_t resolved_flags = 0;
+    Symtab* symtab = m_obj_file->GetSymtab();
+    if (symtab)
+    {
+        const addr_t exe_file_addr = exe_so_addr.GetFileAddress();
+        sc.symbol = symtab->FindSymbolContainingFileAddress (exe_file_addr, &m_func_indexes[0], m_func_indexes.size());
+
+        if (sc.symbol != NULL)
+        {
+            resolved_flags |= eSymbolContextSymbol;
+
+            uint32_t oso_idx = 0;
+            CompileUnitInfo* comp_unit_info = GetCompileUnitInfoForSymbolWithIndex (sc.symbol->GetID(), &oso_idx);
+            if (comp_unit_info)
+            {
+                SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx);
+                ObjectFile *oso_objfile = GetObjectFileByOSOIndex (oso_idx);
+                if (oso_dwarf && oso_objfile)
+                {
+                    SectionList *oso_section_list = oso_objfile->GetSectionList();
+
+
+                    SectionSP oso_section_sp(oso_section_list->FindSectionByName(exe_so_addr.GetSection()->GetName()));
+                    if (oso_section_sp)
+                    {
+                        SectionSP oso_symbol_section_sp (oso_section_sp->GetChildren().FindSectionContainingLinkedFileAddress (exe_file_addr));
+
+                        if (oso_symbol_section_sp)
+                        {
+                            const addr_t linked_file_addr = oso_symbol_section_sp->GetLinkedFileAddress();
+                            Address oso_so_addr (oso_symbol_section_sp.get(), exe_file_addr - linked_file_addr);
+                            if (oso_so_addr.IsSectionOffset())
+                                resolved_flags |= oso_dwarf->ResolveSymbolContext (oso_so_addr, resolve_scope, sc);
+                        }
+                    }
+                    // Map the load address from in the executable back to a
+                    // section/offset address in the .o file so we can do
+                    // lookups in the .o DWARF.
+//                    Address oso_so_addr (exe_load_addr, false, comp_unit_info->debug_map_sections_sp.get());
+//
+//                    // Make sure we were able to resolve this back to a .o
+//                    // section offset address, and if so, resolve the context
+//                    // for everything that was asked for.
+//                    if (oso_so_addr.IsSectionOffset())
+//                        resolved_flags |= oso_dwarf->ResolveSymbolContext (oso_so_addr, resolve_scope, sc);
+                }
+            }
+        }
+    }
+    return resolved_flags;
+}
+
+
+uint32_t
+SymbolFileDWARFDebugMap::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
+{
+    uint32_t initial = sc_list.GetSize();
+    const uint32_t cu_count = GetNumCompileUnits();
+
+    FileSpec so_file_spec;
+    for (uint32_t i=0; i<cu_count; ++i)
+    {
+        if (GetFileSpecForSO (i, so_file_spec))
+        {
+            // By passing false to the comparison we will be able to match
+            // and files given a filename only. If both file_spec and
+            // so_file_spec have directories, we will still do a full match.
+            if (FileSpec::Compare (file_spec, so_file_spec, false) == 0)
+            {
+                SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (i);
+
+                oso_dwarf->ResolveSymbolContext(file_spec, line, check_inlines, resolve_scope, sc_list);
+            }
+        }
+    }
+    return sc_list.GetSize() - initial;
+}
+
+uint32_t
+SymbolFileDWARFDebugMap::PrivateFindGlobalVariables
+(
+    const ConstString &name,
+    const std::vector<uint32_t> &indexes,   // Indexes into the symbol table that match "name"
+    uint32_t max_matches,
+    VariableList& variables
+)
+{
+    const uint32_t original_size = variables.GetSize();
+    const size_t match_count = indexes.size();
+    for (size_t i=0; i<match_count; ++i)
+    {
+        uint32_t oso_idx;
+        CompileUnitInfo* comp_unit_info = GetCompileUnitInfoForSymbolWithIndex (indexes[i], &oso_idx);
+        if (comp_unit_info)
+        {
+            SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx);
+            if (oso_dwarf)
+            {
+                if (oso_dwarf->FindGlobalVariables(name, true, max_matches, variables))
+                    if (variables.GetSize() > max_matches)
+                        break;
+            }
+        }
+    }
+    return variables.GetSize() - original_size;
+}
+
+uint32_t
+SymbolFileDWARFDebugMap::FindGlobalVariables (const ConstString &name, bool append, uint32_t max_matches, VariableList& variables)
+{
+
+    // If we aren't appending the results to this list, then clear the list
+    if (!append)
+        variables.Clear();
+
+    // Remember how many variables are in the list before we search in case
+    // we are appending the results to a variable list.
+    const uint32_t original_size = variables.GetSize();
+
+    Symtab* symtab = m_obj_file->GetSymtab();
+    if (symtab)
+    {
+        std::vector<uint32_t> indexes;
+        const size_t match_count = m_obj_file->GetSymtab()->FindAllSymbolsWithNameAndType (name, eSymbolTypeGlobal, indexes);
+        if (match_count)
+        {
+            PrivateFindGlobalVariables (name, indexes, max_matches, variables);
+        }
+    }
+    // Return the number of variable that were appended to the list
+    return variables.GetSize() - original_size;
+}
+
+
+uint32_t
+SymbolFileDWARFDebugMap::FindGlobalVariables (const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables)
+{
+    return 0;
+}
+
+
+int
+SymbolFileDWARFDebugMap::SymbolContainsSymbolIndex (uint32_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info)
+{
+    const uint32_t symbol_idx = *symbol_idx_ptr;
+
+    if (symbol_idx < comp_unit_info->so_symbol->GetID())
+        return -1;
+
+    if (symbol_idx < comp_unit_info->so_symbol->GetSiblingIndex())
+        return 0;
+
+    return 1;
+}
+
+
+SymbolFileDWARFDebugMap::CompileUnitInfo*
+SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithIndex (uint32_t symbol_idx, uint32_t *oso_idx_ptr)
+{
+    const uint32_t oso_index_count = m_compile_unit_infos.size();
+    CompileUnitInfo *comp_unit_info = NULL;
+    if (oso_index_count)
+    {
+        comp_unit_info = (CompileUnitInfo*)bsearch(&symbol_idx, &m_compile_unit_infos[0], m_compile_unit_infos.size(), sizeof(CompileUnitInfo), (comparison_function)SymbolContainsSymbolIndex);
+    }
+
+    if (oso_idx_ptr)
+    {
+        if (comp_unit_info != NULL)
+            *oso_idx_ptr = comp_unit_info - &m_compile_unit_infos[0];
+        else
+            *oso_idx_ptr = UINT32_MAX;
+    }
+    return comp_unit_info;
+}
+
+uint32_t
+SymbolFileDWARFDebugMap::FindFunctions(const ConstString &name, bool append, SymbolContextList& sc_list)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "SymbolFileDWARFDebugMap::FindFunctions (name = %s)",
+                        name.GetCString());
+
+
+    std::vector<uint32_t> indexes;
+    uint32_t initial_size = 0;
+    if (append)
+        initial_size = sc_list.GetSize();
+    else
+        sc_list.Clear();
+
+    const size_t match_count = m_obj_file->GetSymtab()->FindAllSymbolsWithNameAndType (name, eSymbolTypeFunction, indexes);
+    if (match_count > 0)
+    {
+        for (size_t i=0; i<match_count; ++i)
+        {
+            uint32_t oso_idx;
+            CompileUnitInfo* comp_unit_info = GetCompileUnitInfoForSymbolWithIndex (indexes[i], &oso_idx);
+            if (comp_unit_info)
+            {
+                SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx);
+                if (oso_dwarf)
+                    oso_dwarf->FindFunctions(name, true, sc_list);
+            }
+        }
+//      Stream s(stdout);
+//      sc_list.Dump(&s);
+    }
+
+    return sc_list.GetSize() - initial_size;
+}
+
+
+uint32_t
+SymbolFileDWARFDebugMap::FindFunctions (const RegularExpression& regex, bool append, SymbolContextList& sc_list)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "SymbolFileDWARFDebugMap::FindFunctions (regex = '%s')",
+                        regex.GetText());
+
+
+    return 0;
+}
+
+//
+//uint32_t
+//SymbolFileDWARFDebugMap::FindTypes (const SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, Type::Encoding encoding, lldb::user_id_t udt_uid, TypeList& types)
+//{
+//  SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc);
+//  if (oso_dwarf)
+//      return oso_dwarf->FindTypes (sc, name, append, max_matches, encoding, udt_uid, types);
+//  return 0;
+//}
+//
+//
+//uint32_t
+//SymbolFileDWARFDebugMap::FindTypes (const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, Type::Encoding encoding, lldb::user_id_t udt_uid, TypeList& types)
+//{
+//  SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc);
+//  if (oso_dwarf)
+//      return oso_dwarf->FindTypes (sc, regex, append, max_matches, encoding, udt_uid, types);
+//  return 0;
+//}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+const char *
+SymbolFileDWARFDebugMap::GetPluginName()
+{
+    return "SymbolFileDWARFDebugMap";
+}
+
+const char *
+SymbolFileDWARFDebugMap::GetShortPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+SymbolFileDWARFDebugMap::GetPluginVersion()
+{
+    return 1;
+}
+
+void
+SymbolFileDWARFDebugMap::GetPluginCommandHelp (const char *command, Stream *strm)
+{
+}
+
+Error
+SymbolFileDWARFDebugMap::ExecutePluginCommand (Args &command, Stream *strm)
+{
+    Error error;
+    error.SetErrorString("No plug-in command are currently supported.");
+    return error;
+}
+
+Log *
+SymbolFileDWARFDebugMap::EnablePluginLogging (Stream *strm, Args &command)
+{
+    return NULL;
+}
+
+
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
new file mode 100644
index 0000000..0a312ab
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -0,0 +1,186 @@
+//===-- SymbolFileDWARFDebugMap.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_SymbolFileDWARFDebugMap_h_
+#define liblldb_SymbolFileDWARFDebugMap_h_
+
+
+#include <vector>
+#include <bitset>
+#include "lldb/Symbol/SymbolFile.h"
+
+class SymbolFileDWARF;
+
+class SymbolFileDWARFDebugMap : public lldb_private::SymbolFile
+{
+public:
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static const char *
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb_private::SymbolFile *
+    CreateInstance (lldb_private::ObjectFile* obj_file);
+
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+                            SymbolFileDWARFDebugMap (lldb_private::ObjectFile* ofile);
+    virtual               ~ SymbolFileDWARFDebugMap ();
+
+    virtual uint32_t        GetAbilities ();
+
+    //------------------------------------------------------------------
+    // Compile Unit function calls
+    //------------------------------------------------------------------
+    virtual uint32_t        GetNumCompileUnits ();
+    virtual lldb::CompUnitSP ParseCompileUnitAtIndex (uint32_t index);
+
+    virtual size_t          ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc);
+    virtual bool            ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc);
+    virtual bool            ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList &support_files);
+    virtual size_t          ParseFunctionBlocks (const lldb_private::SymbolContext& sc);
+    virtual size_t          ParseTypes (const lldb_private::SymbolContext& sc);
+    virtual size_t          ParseVariablesForContext (const lldb_private::SymbolContext& sc);
+
+    virtual lldb_private::Type*     ResolveTypeUID (lldb::user_id_t type_uid);
+    virtual uint32_t        ResolveSymbolContext (const lldb_private::Address& so_addr, uint32_t resolve_scope, lldb_private::SymbolContext& sc);
+    virtual uint32_t        ResolveSymbolContext (const lldb_private::FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, lldb_private::SymbolContextList& sc_list);
+    virtual uint32_t        FindGlobalVariables (const lldb_private::ConstString &name, bool append, uint32_t max_matches, lldb_private::VariableList& variables);
+    virtual uint32_t        FindGlobalVariables (const lldb_private::RegularExpression& regex, bool append, uint32_t max_matches, lldb_private::VariableList& variables);
+    virtual uint32_t        FindFunctions (const lldb_private::ConstString &name, bool append, lldb_private::SymbolContextList& sc_list);
+    virtual uint32_t        FindFunctions (const lldb_private::RegularExpression& regex, bool append, lldb_private::SymbolContextList& sc_list);
+//  virtual uint32_t        FindTypes (const lldb_private::SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, Type::Encoding encoding, lldb::user_id_t udt_uid, TypeList& types);
+//  virtual uint32_t        FindTypes (const lldb_private::SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, Type::Encoding encoding, lldb::user_id_t udt_uid, TypeList& types);
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual const char *
+    GetPluginName();
+
+    virtual const char *
+    GetShortPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+    virtual void
+    GetPluginCommandHelp (const char *command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Error
+    ExecutePluginCommand (lldb_private::Args &command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Log *
+    EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
+
+protected:
+    enum
+    {
+        kHaveInitializedOSOs = (1 << 0),
+        kNumFlags
+    };
+
+    //------------------------------------------------------------------
+    // Class specific types
+    //------------------------------------------------------------------
+    struct CompileUnitInfo
+    {
+        lldb_private::FileSpec so_file;
+        lldb_private::Symbol *so_symbol;
+        lldb_private::Symbol *oso_symbol;
+        lldb::ModuleSP oso_module_sp;
+        lldb::CompUnitSP oso_compile_unit_sp;
+        lldb_private::SymbolVendor *oso_symbol_vendor;
+//      lldb_private::shared_ptr<SymbolFileDWARF> oso_dwarf_sp;
+//      lldb_private::shared_ptr<SymbolVendor> oso_dwarf_sp;
+        std::vector<uint32_t> function_indexes;
+        std::vector<uint32_t> static_indexes;
+        lldb::SharedPtr<lldb_private::SectionList>::Type debug_map_sections_sp;
+
+        CompileUnitInfo() :
+            so_file(),
+            so_symbol(NULL),
+            oso_symbol(NULL),
+            oso_module_sp(),
+            oso_compile_unit_sp(),
+            oso_symbol_vendor(NULL),
+//          oso_dwarf_sp(),
+            function_indexes(),
+            static_indexes(),
+            debug_map_sections_sp()
+        {
+        }
+    };
+
+    //------------------------------------------------------------------
+    // Protected Member Functions
+    //------------------------------------------------------------------
+    void
+    InitOSO ();
+
+    bool
+    GetFileSpecForSO (uint32_t oso_idx, lldb_private::FileSpec &file_spec);
+
+    CompileUnitInfo *
+    GetCompUnitInfo (const lldb_private::SymbolContext& sc);
+
+    lldb_private::Module *
+    GetModuleByCompUnitInfo (CompileUnitInfo *comp_unit_info);
+
+    lldb_private::Module *
+    GetModuleByOSOIndex (uint32_t oso_idx);
+
+    lldb_private::ObjectFile *
+    GetObjectFileByCompUnitInfo (CompileUnitInfo *comp_unit_info);
+
+    lldb_private::ObjectFile *
+    GetObjectFileByOSOIndex (uint32_t oso_idx);
+
+    SymbolFileDWARF *
+    GetSymbolFile (const lldb_private::SymbolContext& sc);
+
+    SymbolFileDWARF *
+    GetSymbolFileByCompUnitInfo (CompileUnitInfo *comp_unit_info);
+
+    SymbolFileDWARF *
+    GetSymbolFileByOSOIndex (uint32_t oso_idx);
+
+    CompileUnitInfo*
+    GetCompileUnitInfoForSymbolWithIndex (uint32_t symbol_idx, uint32_t *oso_idx_ptr);
+
+    static int
+    SymbolContainsSymbolIndex (uint32_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info);
+
+    uint32_t
+    PrivateFindGlobalVariables (const lldb_private::ConstString &name,
+                                const std::vector<uint32_t> &name_symbol_indexes,
+                                uint32_t max_matches,
+                                lldb_private::VariableList& variables);
+
+    //------------------------------------------------------------------
+    // Member Variables
+    //------------------------------------------------------------------
+    std::bitset<kNumFlags> m_flags;
+    std::vector<CompileUnitInfo> m_compile_unit_infos;
+    std::vector<uint32_t> m_func_indexes;   // Sorted by address
+    std::vector<uint32_t> m_glob_indexes;
+};
+
+#endif // #ifndef liblldb_SymbolFileDWARFDebugMap_h_
diff --git a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
new file mode 100644
index 0000000..d7da356
--- /dev/null
+++ b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
@@ -0,0 +1,401 @@
+//===-- SymbolFileSymtab.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolFileSymtab.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/Symtab.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/Function.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+SymbolFileSymtab::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance);
+}
+
+void
+SymbolFileSymtab::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+const char *
+SymbolFileSymtab::GetPluginNameStatic()
+{
+    return "symbol-file.symtab";
+}
+
+const char *
+SymbolFileSymtab::GetPluginDescriptionStatic()
+{
+    return "Reads debug symbols from an object file's symbol table.";
+}
+
+
+SymbolFile*
+SymbolFileSymtab::CreateInstance (ObjectFile* obj_file)
+{
+    return new SymbolFileSymtab(obj_file);
+}
+
+SymbolFileSymtab::SymbolFileSymtab(ObjectFile* obj_file) :
+    SymbolFile(obj_file),
+    m_source_indexes(),
+    m_func_indexes(),
+    m_code_indexes(),
+    m_data_indexes(),
+    m_addr_indexes()
+{
+}
+
+SymbolFileSymtab::~SymbolFileSymtab()
+{
+}
+
+
+uint32_t
+SymbolFileSymtab::GetAbilities ()
+{
+    uint32_t abilities = 0;
+    const Symtab *symtab = m_obj_file->GetSymtab();
+    if (symtab)
+    {
+
+        //----------------------------------------------------------------------
+        // The snippet of code below will get the indexes the module symbol
+        // table entries that are code, data, or function related (debug info),
+        // sort them by value (address) and dump the sorted symbols.
+        //----------------------------------------------------------------------
+        symtab->AppendSymbolIndexesWithType(eSymbolTypeSourceFile, m_source_indexes);
+        if (!m_source_indexes.empty())
+        {
+            abilities |= CompileUnits;
+        }
+        symtab->AppendSymbolIndexesWithType(eSymbolTypeFunction, m_func_indexes);
+        if (!m_func_indexes.empty())
+        {
+            symtab->SortSymbolIndexesByValue(m_func_indexes, true);
+            abilities |= Functions;
+        }
+
+        symtab->AppendSymbolIndexesWithType(eSymbolTypeCode, m_code_indexes);
+        if (!m_code_indexes.empty())
+        {
+            symtab->SortSymbolIndexesByValue(m_code_indexes, true);
+            abilities |= Labels;
+        }
+
+        symtab->AppendSymbolIndexesWithType(eSymbolTypeData, m_data_indexes);
+
+        if (!m_data_indexes.empty())
+        {
+            symtab->SortSymbolIndexesByValue(m_data_indexes, true);
+            abilities |= GlobalVariables;
+        }
+    }
+
+    return abilities;
+}
+
+uint32_t
+SymbolFileSymtab::GetNumCompileUnits()
+{
+    // If we don't have any source file symbols we will just have one compile unit for
+    // the entire object file
+    if (m_source_indexes.empty())
+        return 1;
+
+    // If we have any source file symbols we will logically orgnize the object symbols
+    // using these.
+    return m_source_indexes.size();
+}
+
+CompUnitSP
+SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx)
+{
+    CompUnitSP cu_sp;
+
+    // If we don't have any source file symbols we will just have one compile unit for
+    // the entire object file
+    if (m_source_indexes.empty())
+    {
+        const FileSpec &obj_file_spec = m_obj_file->GetFileSpec();
+        if (obj_file_spec)
+            cu_sp.reset(new CompileUnit(m_obj_file->GetModule(), NULL, obj_file_spec, 0, Language::Unknown));
+
+    }
+    else if (idx < m_source_indexes.size())
+    {
+        const Symbol *cu_symbol = m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]);
+        if (cu_symbol)
+            cu_sp.reset(new CompileUnit(m_obj_file->GetModule(), NULL, cu_symbol->GetMangled().GetName().AsCString(), 0, Language::Unknown));
+    }
+    return cu_sp;
+}
+
+size_t
+SymbolFileSymtab::ParseCompileUnitFunctions (const SymbolContext &sc)
+{
+    size_t num_added = 0;
+    // We must at least have a valid compile unit
+    assert (sc.comp_unit != NULL);
+    const Symtab *symtab = m_obj_file->GetSymtab();
+    const Symbol *curr_symbol = NULL;
+    const Symbol *next_symbol = NULL;
+//  const char *prefix = m_obj_file->SymbolPrefix();
+//  if (prefix == NULL)
+//      prefix == "";
+//
+//  const uint32_t prefix_len = strlen(prefix);
+
+    // If we don't have any source file symbols we will just have one compile unit for
+    // the entire object file
+    if (m_source_indexes.empty())
+    {
+        // The only time we will have a user ID of zero is when we don't have
+        // and source file symbols and we declare one compile unit for the
+        // entire object file
+        if (!m_func_indexes.empty())
+        {
+
+        }
+
+        if (!m_code_indexes.empty())
+        {
+//          StreamFile s(stdout);
+//          symtab->Dump(&s, m_code_indexes);
+
+            uint32_t idx = 0;   // Index into the indexes
+            const uint32_t num_indexes = m_code_indexes.size();
+            for (idx = 0; idx < num_indexes; ++idx)
+            {
+                uint32_t symbol_idx = m_code_indexes[idx];
+                curr_symbol = symtab->SymbolAtIndex(symbol_idx);
+                if (curr_symbol)
+                {
+                    // Union of all ranges in the function DIE (if the function is discontiguous)
+                    AddressRange func_range(curr_symbol->GetValue(), 0);
+                    if (func_range.GetBaseAddress().IsSectionOffset())
+                    {
+                        uint32_t symbol_size = curr_symbol->GetByteSize();
+                        if (symbol_size != 0 && !curr_symbol->GetSizeIsSibling())
+                            func_range.SetByteSize(symbol_size);
+                        else if (idx + 1 < num_indexes)
+                        {
+                            next_symbol = symtab->SymbolAtIndex(m_code_indexes[idx + 1]);
+                            if (next_symbol)
+                            {
+                                func_range.SetByteSize(next_symbol->GetValue().GetOffset() - curr_symbol->GetValue().GetOffset());
+                            }
+                        }
+
+                        FunctionSP func_sp(new Function(sc.comp_unit,
+                                                            symbol_idx,                 // UserID is the DIE offset
+                                                            LLDB_INVALID_UID,           // We don't have any type info for this function
+                                                            curr_symbol->GetMangled(),  // Linker/mangled name
+                                                            NULL,                       // no return type for a code symbol...
+                                                            func_range));               // first address range
+
+                        if (func_sp.get() != NULL)
+                        {
+                            sc.comp_unit->AddFunction(func_sp);
+                            ++num_added;
+                        }
+                    }
+                }
+            }
+
+        }
+    }
+    else
+    {
+        // We assume we
+    }
+    return num_added;
+}
+
+bool
+SymbolFileSymtab::ParseCompileUnitLineTable (const SymbolContext &sc)
+{
+    return false;
+}
+
+bool
+SymbolFileSymtab::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList &support_files)
+{
+    return false;
+}
+
+size_t
+SymbolFileSymtab::ParseFunctionBlocks (const SymbolContext &sc)
+{
+    return 0;
+}
+
+
+size_t
+SymbolFileSymtab::ParseTypes (const SymbolContext &sc)
+{
+    return 0;
+}
+
+
+size_t
+SymbolFileSymtab::ParseVariablesForContext (const SymbolContext& sc)
+{
+    return 0;
+}
+
+Type*
+SymbolFileSymtab::ResolveTypeUID(lldb::user_id_t type_uid)
+{
+    return NULL;
+}
+
+
+
+uint32_t
+SymbolFileSymtab::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
+{
+    if (m_obj_file->GetSymtab() == NULL)
+        return 0;
+
+    uint32_t resolved_flags = 0;
+    if (resolve_scope & eSymbolContextSymbol)
+    {
+        sc.symbol = m_obj_file->GetSymtab()->FindSymbolContainingFileAddress(so_addr.GetFileAddress());
+        if (sc.symbol)
+            resolved_flags |= eSymbolContextSymbol;
+    }
+    return resolved_flags;
+}
+
+uint32_t
+SymbolFileSymtab::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
+{
+    return 0;
+}
+
+uint32_t
+SymbolFileSymtab::FindGlobalVariables(const ConstString &name, bool append, uint32_t max_matches, VariableList& variables)
+{
+    return 0;
+}
+
+uint32_t
+SymbolFileSymtab::FindGlobalVariables(const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables)
+{
+    return 0;
+}
+
+uint32_t
+SymbolFileSymtab::FindFunctions(const ConstString &name, bool append, SymbolContextList& sc_list)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "SymbolFileSymtab::FindFunctions (name = '%s')",
+                        name.GetCString());
+
+    Symtab *symtab = m_obj_file->GetSymtab();
+    if (symtab)
+    {
+        const uint32_t start_size = sc_list.GetSize();
+        std::vector<uint32_t> symbol_indexes;
+        symtab->FindAllSymbolsWithNameAndType (name, eSymbolTypeFunction, symbol_indexes);
+        symtab->FindAllSymbolsWithNameAndType (name, eSymbolTypeCode, symbol_indexes);
+        const uint32_t num_matches = symbol_indexes.size();
+        if (num_matches)
+        {
+            SymbolContext sc(m_obj_file->GetModule());
+            for (uint32_t i=0; i<num_matches; i++)
+            {
+                sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]);
+                sc_list.Append(sc);
+            }
+        }
+        return sc_list.GetSize() - start_size;
+    }
+    return 0;
+}
+
+uint32_t
+SymbolFileSymtab::FindFunctions(const RegularExpression& regex, bool append, SymbolContextList& sc_list)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "SymbolFileSymtab::FindFunctions (regex = '%s')",
+                        regex.GetText());
+
+    return 0;
+}
+
+//uint32_t
+//SymbolFileSymtab::FindTypes(const SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, Type::Encoding encoding, lldb::user_id_t udt_uid, TypeList& types)
+//{
+//  return 0;
+//}
+//
+//uint32_t
+//SymbolFileSymtab::FindTypes(const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, Type::Encoding encoding, lldb::user_id_t udt_uid, TypeList& types)
+//{
+//  return 0;
+//}
+
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+const char *
+SymbolFileSymtab::GetPluginName()
+{
+    return "SymbolFileSymtab";
+}
+
+const char *
+SymbolFileSymtab::GetShortPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+SymbolFileSymtab::GetPluginVersion()
+{
+    return 1;
+}
+
+void
+SymbolFileSymtab::GetPluginCommandHelp (const char *command, Stream *strm)
+{
+}
+
+Error
+SymbolFileSymtab::ExecutePluginCommand (Args &command, Stream *strm)
+{
+    Error error;
+    error.SetErrorString("No plug-in command are currently supported.");
+    return error;
+}
+
+Log *
+SymbolFileSymtab::EnablePluginLogging (Stream *strm, Args &command)
+{
+    return NULL;
+}
+
diff --git a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
new file mode 100644
index 0000000..ac73f29
--- /dev/null
+++ b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
@@ -0,0 +1,136 @@
+//===-- SymbolFileSymtab.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_SymbolFileSymtab_h_
+#define liblldb_SymbolFileSymtab_h_
+
+#include "lldb/Symbol/SymbolFile.h"
+#include <vector>
+
+class SymbolFileSymtab : public lldb_private::SymbolFile
+{
+public:
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static const char *
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb_private::SymbolFile*
+    CreateInstance (lldb_private::ObjectFile* obj_file);
+
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    SymbolFileSymtab(lldb_private::ObjectFile* obj_file);
+
+    virtual
+    ~SymbolFileSymtab();
+
+    virtual uint32_t        GetAbilities ();
+
+    //------------------------------------------------------------------
+    // Compile Unit function calls
+    //------------------------------------------------------------------
+    virtual uint32_t
+    GetNumCompileUnits();
+
+    virtual lldb::CompUnitSP
+    ParseCompileUnitAtIndex(uint32_t index);
+
+    virtual size_t
+    ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc);
+
+    virtual bool
+    ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc);
+
+    virtual bool
+    ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList &support_files);
+
+    virtual size_t
+    ParseFunctionBlocks (const lldb_private::SymbolContext& sc);
+
+    virtual size_t
+    ParseTypes (const lldb_private::SymbolContext& sc);
+
+    virtual size_t
+    ParseVariablesForContext (const lldb_private::SymbolContext& sc);
+
+    virtual lldb_private::Type*
+    ResolveTypeUID(lldb::user_id_t type_uid);
+
+    virtual uint32_t
+    ResolveSymbolContext (const lldb_private::Address& so_addr, uint32_t resolve_scope, lldb_private::SymbolContext& sc);
+
+    virtual uint32_t
+    ResolveSymbolContext (const lldb_private::FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, lldb_private::SymbolContextList& sc_list);
+
+    virtual uint32_t
+    FindGlobalVariables(const lldb_private::ConstString &name, bool append, uint32_t max_matches, lldb_private::VariableList& variables);
+
+    virtual uint32_t
+    FindGlobalVariables(const lldb_private::RegularExpression& regex, bool append, uint32_t max_matches, lldb_private::VariableList& variables);
+
+    virtual uint32_t
+    FindFunctions(const lldb_private::ConstString &name, bool append, lldb_private::SymbolContextList& sc_list);
+
+    virtual uint32_t
+    FindFunctions(const lldb_private::RegularExpression& regex, bool append, lldb_private::SymbolContextList& sc_list);
+
+//  virtual uint32_t
+//  FindTypes(const lldb_private::SymbolContext& sc, const lldb_private::ConstString &name, bool append, uint32_t max_matches, lldb_private::Type::Encoding encoding, lldb::user_id_t udt_uid, lldb_private::TypeList& types);
+
+//  virtual uint32_t
+//  FindTypes(const lldb_private::SymbolContext& sc, const lldb_private::RegularExpression& regex, bool append, uint32_t max_matches, lldb_private::Type::Encoding encoding, lldb::user_id_t udt_uid, lldb_private::TypeList& types);
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual const char *
+    GetPluginName();
+
+    virtual const char *
+    GetShortPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+    virtual void
+    GetPluginCommandHelp (const char *command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Error
+    ExecutePluginCommand (lldb_private::Args &command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Log *
+    EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
+
+
+
+protected:
+    std::vector<uint32_t>   m_source_indexes;
+    std::vector<uint32_t>   m_func_indexes;
+    std::vector<uint32_t>   m_code_indexes;
+    std::vector<uint32_t>   m_data_indexes;
+    std::vector<uint32_t>   m_addr_indexes; // Anything that needs to go into an search by address
+
+private:
+    DISALLOW_COPY_AND_ASSIGN (SymbolFileSymtab);
+};
+
+
+#endif  // liblldb_SymbolFileSymtab_h_
diff --git a/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp b/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
new file mode 100644
index 0000000..270d7ed
--- /dev/null
+++ b/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
@@ -0,0 +1,339 @@
+//===-- SymbolVendorMacOSX.cpp ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolVendorMacOSX.h"
+
+#include <mach/machine.h>   // DebugSymbols needs this on Leopard...
+
+#include <AvailabilityMacros.h>
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Host/Symbols.h"
+#include "lldb/Symbol/ObjectFile.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// SymbolVendorMacOSX constructor
+//----------------------------------------------------------------------
+SymbolVendorMacOSX::SymbolVendorMacOSX(Module *module) :
+    SymbolVendor(module)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+SymbolVendorMacOSX::~SymbolVendorMacOSX()
+{
+}
+
+
+static bool
+UUIDsMatch(Module *module, ObjectFile *ofile)
+{
+    if (module && ofile)
+    {
+        // Make sure the UUIDs match
+        UUID dsym_uuid;
+        if (ofile->GetUUID(&dsym_uuid))
+            return dsym_uuid == module->GetUUID();
+    }
+    return false;
+}
+
+
+//ObjectFile *
+//LocateDSYMMachFileInDSYMBundle (Module* module, FileSpec& dsym_fspec)
+//{
+//    ObjectFile *dsym_objfile = NULL;
+//
+//    char path[PATH_MAX];
+//
+//    if (dsym_fspec.GetPath(path, sizeof(path)))
+//    {
+//        size_t path_len = strlen(path);
+//        const char *bundle_subpath = "/Contents/Resources/DWARF/";
+//        if (path_len > 0)
+//        {
+//            if (path[path_len-1] == '/')
+//                ::strncat (path, bundle_subpath + 1, sizeof(path));
+//            else
+//                ::strncat (path, bundle_subpath, sizeof(path));
+//            ::strncat (path, dsym_fspec.GetFilename().AsCString(), sizeof(path));
+//
+//            path_len = strlen(path);
+//
+//            if (::strcasecmp (&path[path_len - strlen(".dSYM")], ".dSYM") == 0)
+//            {
+//                path[path_len - ::strlen(".dSYM")] = '\0';
+//                dsym_fspec.SetFile(path);
+//                dsym_objfile = ObjectFile::FindPlugin(module, &dsym_fspec, 0);
+//            }
+//        }
+//    }
+//    return dsym_objfile;
+//}
+//
+//CFURLRef DBGCopyFullDSYMURLForUUID (CFUUIDRef uuid, CFURLRef exec_url) __attribute__((weak_import));
+
+
+//ObjectFile *
+//FindDSYMUsingDebugSymbols (Module* module, FileSpec& dsym_fspec)
+//{
+//    Timer scoped_locate("FindDSYMUsingDebugSymbols");
+//    dsym_fspec.Clear();
+//    ObjectFile *dsym_objfile = NULL;
+//    if (module->GetUUID().IsValid())
+//    {
+//        // Try and locate the dSYM file using DebugSymbols first
+//        const UInt8 *module_uuid = (const UInt8 *)module->GetUUID().GetBytes();
+//        if (module_uuid != NULL)
+//        {
+//            CFUUIDRef module_uuid_ref;
+//            module_uuid_ref = ::CFUUIDCreateWithBytes ( NULL,
+//                                                        module_uuid[0],
+//                                                        module_uuid[1],
+//                                                        module_uuid[2],
+//                                                        module_uuid[3],
+//                                                        module_uuid[4],
+//                                                        module_uuid[5],
+//                                                        module_uuid[6],
+//                                                        module_uuid[7],
+//                                                        module_uuid[8],
+//                                                        module_uuid[9],
+//                                                        module_uuid[10],
+//                                                        module_uuid[11],
+//                                                        module_uuid[12],
+//                                                        module_uuid[13],
+//                                                        module_uuid[14],
+//                                                        module_uuid[15]);
+//
+//            if (module_uuid_ref)
+//            {
+//                CFURLRef dsym_url = NULL;
+//                CFURLRef exec_url = NULL;
+//
+//            //  if (DBGCopyFullDSYMURLForUUID)
+//                {
+//                    char exec_path[PATH_MAX];
+//                    if (module->GetFileSpec().GetPath(exec_path, sizeof(exec_path)))
+//                    {
+//                        exec_url = CFURLCreateFromFileSystemRepresentation ( NULL,
+//                                                                             (const UInt8 *)exec_path,
+//                                                                             strlen(exec_path),
+//                                                                             FALSE);
+//                    }
+//
+//                    dsym_url = DBGCopyFullDSYMURLForUUID(module_uuid_ref, exec_url);
+//                }
+//    //          else
+//    //          {
+//    //              dsym_url = DBGCopyDSYMURLForUUID(module_uuid_ref);
+//    //          }
+//
+//                if (exec_url)
+//                {
+//                    ::CFRelease (exec_url);
+//                    exec_url = NULL;
+//                }
+//
+//                ::CFRelease(module_uuid_ref);
+//                module_uuid_ref = NULL;
+//
+//                if (dsym_url)
+//                {
+//                    char dsym_path[PATH_MAX];
+//                    Boolean success = CFURLGetFileSystemRepresentation (dsym_url, true, (UInt8*)dsym_path, sizeof(dsym_path)-1);
+//
+//                    ::CFRelease(dsym_url), dsym_url = NULL;
+//
+//                    if (success)
+//                    {
+//                        dsym_fspec.SetFile(dsym_path);
+//
+//                        // Some newer versions of DebugSymbols will return a full path into a dSYM bundle
+//                        // that points to the correct mach file within the dSYM bundle (MH_DSYM mach file
+//                        // type).
+//                        dsym_objfile = ObjectFile::FindPlugin(module, &dsym_fspec, 0);
+//
+//                        // Olders versions of DebugSymbols will return a path to a dSYM bundle.
+//                        if (dsym_objfile == NULL)
+//                            dsym_objfile = LocateDSYMMachFileInDSYMBundle (module, dsym_fspec);
+//                    }
+//                }
+//            }
+//        }
+//    }
+//    return dsym_objfile;
+//}
+
+static void
+ReplaceDSYMSectionsWithExecutableSections (ObjectFile *exec_objfile, ObjectFile *dsym_objfile)
+{
+    // We need both the executable and the dSYM to live off of the
+    // same section lists. So we take all of the sections from the
+    // executable, and replace them in the dSYM. This allows section
+    // offset addresses that come from the dSYM to automatically
+    // get updated as images (shared libraries) get loaded and
+    // unloaded.
+    SectionList *exec_section_list = exec_objfile->GetSectionList();
+    SectionList *dsym_section_list = dsym_objfile->GetSectionList();
+    if (exec_section_list && dsym_section_list)
+    {
+        const uint32_t num_exec_sections = dsym_section_list->GetSize();
+        uint32_t exec_sect_idx;
+        for (exec_sect_idx = 0; exec_sect_idx < num_exec_sections; ++exec_sect_idx)
+        {
+            SectionSP exec_sect_sp(exec_section_list->GetSectionAtIndex(exec_sect_idx));
+            if (exec_sect_sp.get())
+            {
+                // Try and replace any sections that exist in both the executable
+                // and in the dSYM with those from the executable. If we fail to
+                // replace the one in the dSYM, then add the executable section to
+                // the dSYM.
+                if (dsym_section_list->ReplaceSection(exec_sect_sp->GetID(), exec_sect_sp, 0) == false)
+                    dsym_section_list->AddSection(exec_sect_sp);
+            }
+        }
+    }
+}
+
+void
+SymbolVendorMacOSX::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance);
+}
+
+void
+SymbolVendorMacOSX::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+const char *
+SymbolVendorMacOSX::GetPluginNameStatic()
+{
+    return "symbol-vendor.macosx";
+}
+
+const char *
+SymbolVendorMacOSX::GetPluginDescriptionStatic()
+{
+    return "Symbol vendor for MacOSX that looks for dSYM files that match executables.";
+}
+
+
+
+//----------------------------------------------------------------------
+// CreateInstance
+//
+// Platforms can register a callback to use when creating symbol
+// vendors to allow for complex debug information file setups, and to
+// also allow for finding separate debug information files.
+//----------------------------------------------------------------------
+SymbolVendor*
+SymbolVendorMacOSX::CreateInstance(Module* module)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "SymbolVendorMacOSX::CreateInstance (module = %s/%s)",
+                        module->GetFileSpec().GetDirectory().AsCString(),
+                        module->GetFileSpec().GetFilename().AsCString());
+    SymbolVendorMacOSX* symbol_vendor = new SymbolVendorMacOSX(module);
+    if (symbol_vendor)
+    {
+        char path[PATH_MAX];
+        path[0] = '\0';
+
+        // Try and locate the dSYM file on Mac OS X
+        ObjectFile * obj_file = module->GetObjectFile();
+        if (obj_file)
+        {
+            Timer scoped_timer2 ("SymbolVendorMacOSX::CreateInstance () locate dSYM",
+                                 "SymbolVendorMacOSX::CreateInstance (module = %s/%s) locate dSYM",
+                                 module->GetFileSpec().GetDirectory().AsCString(),
+                                 module->GetFileSpec().GetFilename().AsCString());
+
+            FileSpec dsym_fspec;
+            std::auto_ptr<ObjectFile> dsym_objfile_ap;
+            const FileSpec &file_spec = obj_file->GetFileSpec();
+            if (file_spec)
+            {
+                dsym_fspec = Symbols::LocateExecutableSymbolFile (&file_spec, &module->GetArchitecture(), &module->GetUUID());
+
+                if (dsym_fspec)
+                {
+                    dsym_objfile_ap.reset(ObjectFile::FindPlugin(module, &dsym_fspec, 0, dsym_fspec.GetByteSize()));
+                    if (UUIDsMatch(module, dsym_objfile_ap.get()))
+                    {
+                        ReplaceDSYMSectionsWithExecutableSections (obj_file, dsym_objfile_ap.get());
+                        symbol_vendor->AddSymbolFileRepresendation(dsym_objfile_ap.release());
+                        return symbol_vendor;
+                    }
+                }
+            }
+
+            // Just create our symbol vendor using the current objfile as this is either
+            // an executable with no dSYM (that we could locate), and executable with
+            // a dSYM that has a UUID that doesn't match, or it is a dSYM file itself.
+            symbol_vendor->AddSymbolFileRepresendation(obj_file);
+        }
+    }
+    return symbol_vendor;
+}
+
+
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+const char *
+SymbolVendorMacOSX::GetPluginName()
+{
+    return "SymbolVendorMacOSX";
+}
+
+const char *
+SymbolVendorMacOSX::GetShortPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+SymbolVendorMacOSX::GetPluginVersion()
+{
+    return 1;
+}
+
+void
+SymbolVendorMacOSX::GetPluginCommandHelp (const char *command, Stream *strm)
+{
+}
+
+Error
+SymbolVendorMacOSX::ExecutePluginCommand (Args &command, Stream *strm)
+{
+    Error error;
+    error.SetErrorString("No plug-in command are currently supported.");
+    return error;
+}
+
+Log *
+SymbolVendorMacOSX::EnablePluginLogging (Stream *strm, Args &command)
+{
+    return NULL;
+}
+
diff --git a/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.h b/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.h
new file mode 100644
index 0000000..adbf648
--- /dev/null
+++ b/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.h
@@ -0,0 +1,71 @@
+//===-- SymbolVendorMacOSX.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_SymbolVendorMacOSX_h_
+#define liblldb_SymbolVendorMacOSX_h_
+
+#include "lldb/lldb-private.h"
+#include "lldb/Symbol/SymbolVendor.h"
+
+class SymbolVendorMacOSX : public lldb_private::SymbolVendor
+{
+public:
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static const char *
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb_private::SymbolVendor*
+    CreateInstance (lldb_private::Module *module);
+
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    SymbolVendorMacOSX (lldb_private::Module *module);
+
+    virtual
+    ~SymbolVendorMacOSX();
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual const char *
+    GetPluginName();
+
+    virtual const char *
+    GetShortPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+    virtual void
+    GetPluginCommandHelp (const char *command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Error
+    ExecutePluginCommand (lldb_private::Args &command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Log *
+    EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
+
+
+private:
+    DISALLOW_COPY_AND_ASSIGN (SymbolVendorMacOSX);
+};
+
+#endif  // liblldb_SymbolVendorMacOSX_h_
diff --git a/source/Symbol/Block.cpp b/source/Symbol/Block.cpp
new file mode 100644
index 0000000..3214119
--- /dev/null
+++ b/source/Symbol/Block.cpp
@@ -0,0 +1,641 @@
+//===-- Block.cpp -----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/VariableList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+Block::Block(user_id_t uid, uint32_t depth, BlockList* blocks) :
+    UserID(uid),
+    m_block_list(blocks),
+    m_depth(depth),
+    m_ranges(),
+    m_inlineInfoSP(),
+    m_variables()
+{
+}
+
+Block::Block(const Block& rhs) :
+    UserID(rhs),
+    m_block_list(rhs.m_block_list),
+    m_depth(rhs.m_depth),
+    m_ranges(rhs.m_ranges),
+    m_inlineInfoSP(rhs.m_inlineInfoSP),
+    m_variables(rhs.m_variables)
+{
+}
+
+const Block&
+Block::operator= (const Block& rhs)
+{
+    if (this != &rhs)
+    {
+        UserID::operator= (rhs);
+        m_block_list = rhs.m_block_list;
+        m_depth = rhs.m_depth;
+        m_ranges = rhs.m_ranges;
+        m_inlineInfoSP = rhs.m_inlineInfoSP;
+        m_variables = rhs.m_variables;
+    }
+    return *this;
+}
+
+Block::~Block ()
+{
+}
+
+void
+Block::Dump(Stream *s, addr_t base_addr, int32_t depth, bool show_context) const
+{
+    if (depth < 0)
+    {
+        // We have a depth that is less than zero, print our parent blocks
+        // first
+        m_block_list->Dump(s, GetParentUID(), depth + 1, show_context);
+    }
+
+    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+    s->Indent();
+    *s << "Block" << ((const UserID&)*this);
+    user_id_t parentID = GetParentUID();
+    const Block* parent_block = NULL;
+    if (parentID != Block::InvalidID)
+    {
+        parent_block = m_block_list->GetBlockByID(parentID);
+        s->Printf(", parent = {0x%8.8x}", parentID);
+    }
+    if (m_inlineInfoSP.get() != NULL)
+        m_inlineInfoSP->Dump(s);
+
+    if (!m_ranges.empty())
+    {
+        *s << ", ranges =";
+        std::vector<VMRange>::const_iterator pos;
+        std::vector<VMRange>::const_iterator end = m_ranges.end();
+        for (pos = m_ranges.begin(); pos != end; ++pos)
+        {
+            if (parent_block != NULL && parent_block->Contains(*pos) == false)
+                *s << '!';
+            else
+                *s << ' ';
+            pos->Dump(s, base_addr);
+        }
+    }
+    s->EOL();
+
+    if (depth > 0)
+    {
+        s->IndentMore();
+
+        if (m_variables.get())
+        {
+            m_variables->Dump(s, show_context);
+        }
+
+        uint32_t blockID = m_block_list->GetFirstChild(GetID());
+        while (blockID != Block::InvalidID)
+        {
+            m_block_list->Dump(s, blockID, depth - 1, show_context);
+
+            blockID = m_block_list->GetSibling(blockID);
+        }
+
+        s->IndentLess();
+    }
+
+}
+
+
+void
+Block::CalculateSymbolContext(SymbolContext* sc)
+{
+    sc->block = this;
+    m_block_list->GetFunction()->CalculateSymbolContext(sc);
+}
+
+void
+Block::DumpStopContext (Stream *s, const SymbolContext *sc)
+{
+    user_id_t parentID = GetParentUID();
+    Block* parent_block = NULL;
+    if (parentID != Block::InvalidID)
+        parent_block = m_block_list->GetBlockByID(parentID);
+
+    InlineFunctionInfo* inline_info = InlinedFunctionInfo ();
+    if (inline_info)
+    {
+        const Declaration &call_site = inline_info->GetCallSite();
+        if (sc)
+        {
+            // First frame, dump the first inline call site
+//            if (call_site.IsValid())
+//            {
+//                s->PutCString(" at ");
+//                call_site.DumpStopContext (s);
+//            }
+            s->PutCString (" [inlined]");
+        }
+        s->EOL();
+        inline_info->DumpStopContext (s);
+        if (sc == NULL)
+        {
+            if (call_site.IsValid())
+            {
+                s->PutCString(" at ");
+                call_site.DumpStopContext (s);
+            }
+        }
+    }
+
+    if (sc)
+    {
+        // If we have any inlined functions, this will be the deepest most
+        // inlined location
+        if (sc->line_entry.IsValid())
+        {
+            s->PutCString(" at ");
+            sc->line_entry.DumpStopContext (s);
+        }
+    }
+    if (parent_block)
+        parent_block->Block::DumpStopContext (s, NULL);
+}
+
+
+void
+Block::DumpSymbolContext(Stream *s)
+{
+    m_block_list->GetFunction()->DumpSymbolContext(s);
+    s->Printf(", Block{0x%8.8x}", GetID());
+}
+
+bool
+Block::Contains (addr_t range_offset) const
+{
+    return VMRange::ContainsValue(m_ranges, range_offset);
+}
+
+bool
+Block::Contains (const VMRange& range) const
+{
+    return VMRange::ContainsRange(m_ranges, range);
+}
+
+
+
+bool
+BlockList::BlockContainsBlockWithID (const user_id_t block_id, const user_id_t find_block_id) const
+{
+    if (block_id == Block::InvalidID)
+        return false;
+
+    if (block_id == find_block_id)
+        return true;
+    else
+    {
+        user_id_t child_block_id = GetFirstChild(block_id);
+        while (child_block_id != Block::InvalidID)
+        {
+            if (BlockContainsBlockWithID (child_block_id, find_block_id))
+                return true;
+            child_block_id = GetSibling(child_block_id);
+        }
+    }
+
+    return false;
+}
+
+bool
+Block::ContainsBlockWithID (user_id_t block_id) const
+{
+    return m_block_list->BlockContainsBlockWithID (GetID(), block_id);
+}
+
+
+void
+Block::AddRange(addr_t start_offset, addr_t end_offset)
+{
+    m_ranges.resize(m_ranges.size()+1);
+    m_ranges.back().Reset(start_offset, end_offset);
+}
+
+InlineFunctionInfo*
+Block::InlinedFunctionInfo ()
+{
+    return m_inlineInfoSP.get();
+}
+
+const InlineFunctionInfo*
+Block::InlinedFunctionInfo () const
+{
+    return m_inlineInfoSP.get();
+}
+
+// Return the current number of bytes that this object occupies in memory
+size_t
+Block::MemorySize() const
+{
+    size_t mem_size = sizeof(Block) + m_ranges.size() * sizeof(VMRange);
+    if (m_inlineInfoSP.get())
+        mem_size += m_inlineInfoSP->MemorySize();
+    if (m_variables.get())
+        mem_size += m_variables->MemorySize();
+    return mem_size;
+
+}
+
+user_id_t
+Block::GetParentUID() const
+{
+    return m_block_list->GetParent(GetID());
+}
+
+user_id_t
+Block::GetSiblingUID() const
+{
+    return m_block_list->GetSibling(GetID());
+}
+
+user_id_t
+Block::GetFirstChildUID() const
+{
+    return m_block_list->GetFirstChild(GetID());
+}
+
+user_id_t
+Block::AddChild(user_id_t userID)
+{
+    return m_block_list->AddChild(GetID(), userID);
+}
+
+void
+Block::SetInlinedFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr)
+{
+    m_inlineInfoSP.reset(new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr));
+}
+
+BlockList::BlockList(Function *function, const AddressRange& range) :
+    m_function(function),
+    m_range(range),
+    m_blocks()
+{
+}
+
+BlockList::~BlockList()
+{
+}
+
+AddressRange &
+BlockList::GetAddressRange()
+{
+    return m_range;
+}
+
+const AddressRange &
+BlockList::GetAddressRange() const
+{
+    return m_range;
+}
+
+void
+BlockList::Dump(Stream *s, user_id_t blockID, uint32_t depth, bool show_context) const
+{
+    const Block* block = GetBlockByID(blockID);
+    if (block)
+        block->Dump(s, m_range.GetBaseAddress().GetFileAddress(), depth, show_context);
+}
+
+Function *
+BlockList::GetFunction()
+{
+    return m_function;
+}
+
+
+const Function *
+BlockList::GetFunction() const
+{
+    return m_function;
+}
+
+user_id_t
+BlockList::GetParent(user_id_t blockID) const
+{
+    collection::const_iterator end = m_blocks.end();
+    collection::const_iterator begin = m_blocks.begin();
+    collection::const_iterator pos = std::find_if(begin, end, UserID::IDMatches(blockID));
+
+    if (pos != end && pos != begin && pos->Depth() > 0)
+    {
+        const uint32_t parent_depth = pos->Depth() - 1;
+
+        while (--pos >= begin)
+        {
+            if (pos->Depth() == parent_depth)
+                return pos->GetID();
+        }
+    }
+    return Block::InvalidID;
+}
+
+user_id_t
+BlockList::GetSibling(user_id_t blockID) const
+{
+    collection::const_iterator end = m_blocks.end();
+    collection::const_iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID));
+
+    if (pos != end)
+    {
+        const uint32_t sibling_depth = pos->Depth();
+        while (++pos != end)
+        {
+            uint32_t depth = pos->Depth();
+            if (depth == sibling_depth)
+                return pos->GetID();
+            if (depth < sibling_depth)
+                break;
+        }
+    }
+    return Block::InvalidID;
+}
+
+user_id_t
+BlockList::GetFirstChild(user_id_t blockID) const
+{
+    if (!m_blocks.empty())
+    {
+        if (blockID == Block::RootID)
+        {
+            return m_blocks.front().GetID();
+        }
+        else
+        {
+            collection::const_iterator end = m_blocks.end();
+            collection::const_iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID));
+
+            if (pos != end)
+            {
+                collection::const_iterator child_pos = pos + 1;
+                if (child_pos != end)
+                {
+                    if (child_pos->Depth() == pos->Depth() + 1)
+                        return child_pos->GetID();
+                }
+            }
+        }
+    }
+    return Block::InvalidID;
+}
+
+
+// Return the current number of bytes that this object occupies in memory
+size_t
+BlockList::MemorySize() const
+{
+    size_t mem_size = sizeof(BlockList);
+
+    collection::const_iterator pos, end = m_blocks.end();
+    for (pos = m_blocks.begin(); pos != end; ++pos)
+        mem_size += pos->MemorySize();  // Each block can vary in size
+
+    return mem_size;
+
+}
+
+user_id_t
+BlockList::AddChild (user_id_t parentID, user_id_t childID)
+{
+    bool added = false;
+    if (parentID == Block::RootID)
+    {
+        assert(m_blocks.empty());
+        Block block(childID, 0, this);
+        m_blocks.push_back(block);
+        added = true;
+    }
+    else
+    {
+        collection::iterator end = m_blocks.end();
+        collection::iterator parent_pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(parentID));
+        assert(parent_pos != end);
+        if (parent_pos != end)
+        {
+            const uint32_t parent_sibling_depth = parent_pos->Depth();
+
+            collection::iterator insert_pos = parent_pos;
+            collection::iterator prev_sibling = end;
+            while (++insert_pos != end)
+            {
+                if (insert_pos->Depth() <= parent_sibling_depth)
+                    break;
+            }
+
+            Block child_block(childID, parent_pos->Depth() + 1, this);
+            collection::iterator child_pos = m_blocks.insert(insert_pos, child_block);
+            added = true;
+        }
+    }
+    if (added)
+        return childID;
+    return Block::InvalidID;
+}
+
+const Block *
+BlockList::GetBlockByID(user_id_t blockID) const
+{
+    if (m_blocks.empty())
+        return NULL;
+
+    if (blockID == Block::RootID)
+        blockID = m_blocks.front().GetID();
+
+    collection::const_iterator end = m_blocks.end();
+    collection::const_iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID));
+    if (pos != end)
+        return &(*pos);
+    return NULL;
+}
+
+Block *
+BlockList::GetBlockByID(user_id_t blockID)
+{
+    if (m_blocks.empty())
+        return NULL;
+
+    if (blockID == Block::RootID)
+        blockID = m_blocks.front().GetID();
+
+    collection::iterator end = m_blocks.end();
+    collection::iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID));
+    if (pos != end)
+        return &(*pos);
+    return NULL;
+}
+
+bool
+BlockList::AddRange(user_id_t blockID, addr_t start_offset, addr_t end_offset)
+{
+    Block *block = GetBlockByID(blockID);
+
+    if (block)
+    {
+        block->AddRange(start_offset, end_offset);
+        return true;
+    }
+    return false;
+}
+//
+//const Block *
+//BlockList::FindDeepestBlockForAddress (const Address &addr)
+//{
+//    if (m_range.Contains(addr))
+//    {
+//        addr_t block_offset = addr.GetFileAddress() - m_range.GetBaseAddress().GetFileAddress();
+//        collection::const_iterator pos, end = m_blocks.end();
+//        collection::const_iterator deepest_match_pos = end;
+//        for (pos = m_blocks.begin(); pos != end; ++pos)
+//        {
+//            if (pos->Contains (block_offset))
+//            {
+//                if (deepest_match_pos == end || deepest_match_pos->Depth() < pos->Depth())
+//                    deepest_match_pos = pos;
+//            }
+//        }
+//        if (deepest_match_pos != end)
+//            return &(*deepest_match_pos);
+//    }
+//    return NULL;
+//}
+//
+bool
+BlockList::SetInlinedFunctionInfo(user_id_t blockID, const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr)
+{
+    Block *block = GetBlockByID(blockID);
+
+    if (block)
+    {
+        block->SetInlinedFunctionInfo(name, mangled, decl_ptr, call_decl_ptr);
+        return true;
+    }
+    return false;
+}
+
+VariableListSP
+BlockList::GetVariableList(user_id_t blockID, bool get_child_variables, bool can_create)
+{
+    VariableListSP variable_list_sp;
+    Block *block = GetBlockByID(blockID);
+    if (block)
+        variable_list_sp = block->GetVariableList(get_child_variables, can_create);
+    return variable_list_sp;
+}
+
+bool
+BlockList::IsEmpty() const
+{
+    return m_blocks.empty();
+}
+
+
+
+bool
+BlockList::SetVariableList(user_id_t blockID, VariableListSP& variables)
+{
+    Block *block = GetBlockByID(blockID);
+    if (block)
+    {
+        block->SetVariableList(variables);
+        return true;
+    }
+    return false;
+
+}
+
+
+VariableListSP
+Block::GetVariableList (bool get_child_variables, bool can_create)
+{
+    VariableListSP variable_list_sp;
+    if (m_variables.get() == NULL && can_create)
+    {
+        SymbolContext sc;
+        CalculateSymbolContext(&sc);
+        assert(sc.module_sp);
+        sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc);
+    }
+
+    if (m_variables.get())
+    {
+        variable_list_sp.reset(new VariableList());
+        if (variable_list_sp.get())
+            variable_list_sp->AddVariables(m_variables.get());
+
+        if (get_child_variables)
+        {
+            user_id_t block_id = GetFirstChildUID();
+            while (block_id != Block::InvalidID)
+            {
+                Block *child_block = m_block_list->GetBlockByID(block_id);
+                assert(child_block);
+                VariableListSP child_block_variable_list(child_block->GetVariableList(get_child_variables, can_create));
+                if (child_block_variable_list.get())
+                    variable_list_sp->AddVariables(child_block_variable_list.get());
+
+                block_id = child_block->GetSiblingUID();
+            }
+        }
+    }
+
+    return variable_list_sp;
+}
+
+uint32_t
+Block::AppendVariables (bool can_create, bool get_parent_variables, VariableList *variable_list)
+{
+    uint32_t num_variables_added = 0;
+    VariableListSP variable_list_sp(GetVariableList(false, can_create));
+
+    if (variable_list_sp.get())
+    {
+        num_variables_added = variable_list_sp->GetSize();
+        variable_list->AddVariables(variable_list_sp.get());
+    }
+
+    if (get_parent_variables)
+    {
+        user_id_t parentID = GetParentUID();
+        if (parentID != Block::InvalidID)
+        {
+            Block* parent_block = m_block_list->GetBlockByID(parentID);
+            if (parent_block)
+                num_variables_added += parent_block->AppendVariables (can_create, get_parent_variables, variable_list);
+        }
+    }
+    return num_variables_added;
+}
+
+
+void
+Block::SetVariableList(VariableListSP& variables)
+{
+    m_variables = variables;
+}
+
+uint32_t
+Block::Depth () const
+{
+    return m_depth;
+}
+
diff --git a/source/Symbol/ClangASTContext.cpp b/source/Symbol/ClangASTContext.cpp
new file mode 100644
index 0000000..be63de2
--- /dev/null
+++ b/source/Symbol/ClangASTContext.cpp
@@ -0,0 +1,2552 @@
+//===-- ClangASTContext.cpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangASTContext.h"
+
+// C Includes
+// C++ Includes
+#include <string>
+
+// Other libraries and framework includes
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTImporter.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Frontend/FrontendOptions.h"
+#include "clang/Frontend/LangStandard.h"
+
+// Project includes
+#include "lldb/Core/dwarf.h"
+
+using namespace lldb_private;
+using namespace llvm;
+using namespace clang;
+
+
+static void
+ParseLangArgs
+(
+    LangOptions &Opts,
+    FrontendOptions::InputKind IK
+)
+{
+    // FIXME: Cleanup per-file based stuff.
+
+    // Set some properties which depend soley on the input kind; it would be nice
+    // to move these to the language standard, and have the driver resolve the
+    // input kind + language standard.
+    if (IK == FrontendOptions::IK_Asm) {
+        Opts.AsmPreprocessor = 1;
+    } else if (IK == FrontendOptions::IK_ObjC ||
+               IK == FrontendOptions::IK_ObjCXX ||
+               IK == FrontendOptions::IK_PreprocessedObjC ||
+               IK == FrontendOptions::IK_PreprocessedObjCXX) {
+        Opts.ObjC1 = Opts.ObjC2 = 1;
+    }
+
+    LangStandard::Kind LangStd = LangStandard::lang_unspecified;
+
+    if (LangStd == LangStandard::lang_unspecified) {
+        // Based on the base language, pick one.
+        switch (IK) {
+            case FrontendOptions::IK_None:
+            case FrontendOptions::IK_AST:
+                assert(0 && "Invalid input kind!");
+            case FrontendOptions::IK_OpenCL:
+                LangStd = LangStandard::lang_opencl;
+                break;
+            case FrontendOptions::IK_Asm:
+            case FrontendOptions::IK_C:
+            case FrontendOptions::IK_PreprocessedC:
+            case FrontendOptions::IK_ObjC:
+            case FrontendOptions::IK_PreprocessedObjC:
+                LangStd = LangStandard::lang_gnu99;
+                break;
+            case FrontendOptions::IK_CXX:
+            case FrontendOptions::IK_PreprocessedCXX:
+            case FrontendOptions::IK_ObjCXX:
+            case FrontendOptions::IK_PreprocessedObjCXX:
+                LangStd = LangStandard::lang_gnucxx98;
+                break;
+        }
+    }
+
+    const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd);
+    Opts.BCPLComment = Std.hasBCPLComments();
+    Opts.C99 = Std.isC99();
+    Opts.CPlusPlus = Std.isCPlusPlus();
+    Opts.CPlusPlus0x = Std.isCPlusPlus0x();
+    Opts.Digraphs = Std.hasDigraphs();
+    Opts.GNUMode = Std.isGNUMode();
+    Opts.GNUInline = !Std.isC99();
+    Opts.HexFloats = Std.hasHexFloats();
+    Opts.ImplicitInt = Std.hasImplicitInt();
+
+    // OpenCL has some additional defaults.
+    if (LangStd == LangStandard::lang_opencl) {
+        Opts.OpenCL = 1;
+        Opts.AltiVec = 1;
+        Opts.CXXOperatorNames = 1;
+        Opts.LaxVectorConversions = 1;
+    }
+
+    // OpenCL and C++ both have bool, true, false keywords.
+    Opts.Bool = Opts.OpenCL || Opts.CPlusPlus;
+
+//    if (Opts.CPlusPlus)
+//        Opts.CXXOperatorNames = !Args.hasArg(OPT_fno_operator_names);
+//
+//    if (Args.hasArg(OPT_fobjc_gc_only))
+//        Opts.setGCMode(LangOptions::GCOnly);
+//    else if (Args.hasArg(OPT_fobjc_gc))
+//        Opts.setGCMode(LangOptions::HybridGC);
+//
+//    if (Args.hasArg(OPT_print_ivar_layout))
+//        Opts.ObjCGCBitmapPrint = 1;
+//
+//    if (Args.hasArg(OPT_faltivec))
+//        Opts.AltiVec = 1;
+//
+//    if (Args.hasArg(OPT_pthread))
+//        Opts.POSIXThreads = 1;
+//
+//    llvm::StringRef Vis = getLastArgValue(Args, OPT_fvisibility,
+//                                          "default");
+//    if (Vis == "default")
+        Opts.setVisibilityMode(LangOptions::Default);
+//    else if (Vis == "hidden")
+//        Opts.setVisibilityMode(LangOptions::Hidden);
+//    else if (Vis == "protected")
+//        Opts.setVisibilityMode(LangOptions::Protected);
+//    else
+//        Diags.Report(diag::err_drv_invalid_value)
+//        << Args.getLastArg(OPT_fvisibility)->getAsString(Args) << Vis;
+
+//    Opts.OverflowChecking = Args.hasArg(OPT_ftrapv);
+
+    // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs
+    // is specified, or -std is set to a conforming mode.
+    Opts.Trigraphs = !Opts.GNUMode;
+//    if (Args.hasArg(OPT_trigraphs))
+//        Opts.Trigraphs = 1;
+//
+//    Opts.DollarIdents = Args.hasFlag(OPT_fdollars_in_identifiers,
+//                                     OPT_fno_dollars_in_identifiers,
+//                                     !Opts.AsmPreprocessor);
+//    Opts.PascalStrings = Args.hasArg(OPT_fpascal_strings);
+//    Opts.Microsoft = Args.hasArg(OPT_fms_extensions);
+//    Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings);
+//    if (Args.hasArg(OPT_fno_lax_vector_conversions))
+//        Opts.LaxVectorConversions = 0;
+//    Opts.Exceptions = Args.hasArg(OPT_fexceptions);
+//    Opts.RTTI = !Args.hasArg(OPT_fno_rtti);
+//    Opts.Blocks = Args.hasArg(OPT_fblocks);
+//    Opts.CharIsSigned = !Args.hasArg(OPT_fno_signed_char);
+//    Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar);
+//    Opts.Freestanding = Args.hasArg(OPT_ffreestanding);
+//    Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
+//    Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new);
+//    Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions);
+//    Opts.AccessControl = Args.hasArg(OPT_faccess_control);
+//    Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors);
+//    Opts.MathErrno = !Args.hasArg(OPT_fno_math_errno);
+//    Opts.InstantiationDepth = getLastArgIntValue(Args, OPT_ftemplate_depth, 99,
+//                                                 Diags);
+//    Opts.NeXTRuntime = !Args.hasArg(OPT_fgnu_runtime);
+//    Opts.ObjCConstantStringClass = getLastArgValue(Args,
+//                                                   OPT_fconstant_string_class);
+//    Opts.ObjCNonFragileABI = Args.hasArg(OPT_fobjc_nonfragile_abi);
+//    Opts.CatchUndefined = Args.hasArg(OPT_fcatch_undefined_behavior);
+//    Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls);
+//    Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags);
+//    Opts.Static = Args.hasArg(OPT_static_define);
+    Opts.OptimizeSize = 0;
+
+    // FIXME: Eliminate this dependency.
+//    unsigned Opt =
+//    Args.hasArg(OPT_Os) ? 2 : getLastArgIntValue(Args, OPT_O, 0, Diags);
+//    Opts.Optimize = Opt != 0;
+    unsigned Opt = 0;
+
+    // This is the __NO_INLINE__ define, which just depends on things like the
+    // optimization level and -fno-inline, not actually whether the backend has
+    // inlining enabled.
+    //
+    // FIXME: This is affected by other options (-fno-inline).
+    Opts.NoInline = !Opt;
+
+//    unsigned SSP = getLastArgIntValue(Args, OPT_stack_protector, 0, Diags);
+//    switch (SSP) {
+//        default:
+//            Diags.Report(diag::err_drv_invalid_value)
+//            << Args.getLastArg(OPT_stack_protector)->getAsString(Args) << SSP;
+//            break;
+//        case 0: Opts.setStackProtectorMode(LangOptions::SSPOff); break;
+//        case 1: Opts.setStackProtectorMode(LangOptions::SSPOn);  break;
+//        case 2: Opts.setStackProtectorMode(LangOptions::SSPReq); break;
+//    }
+}
+
+//----------------------------------------------------------------------
+// ClangASTContext constructor
+//----------------------------------------------------------------------
+//ClangASTContext::ClangASTContext(Module *module) :
+//  m_target_triple(),
+//  m_ast_context_ap(),
+//  m_language_options_ap(),
+//  m_source_manager_ap(),
+//  m_target_info_ap(),
+//  m_identifier_table_ap(),
+//  m_selector_table_ap(),
+//  m_builtins_ap()
+//{
+//  if (module)
+//  {
+//      ObjectFile * objfile = module->GetObjectFile();
+//      if (objfile)
+//          objfile->GetTargetTriple(m_target_triple);
+//  }
+//}
+
+//ClangASTContext::ClangASTContext(const ConstString& target_triple) :
+//  m_target_triple(target_triple),
+//  m_ast_context_ap(),
+//  m_language_options_ap(),
+//  m_source_manager_ap(),
+//  m_target_info_ap(),
+//  m_identifier_table_ap(),
+//  m_selector_table_ap(),
+//  m_builtins_ap()
+//{
+//}
+ClangASTContext::ClangASTContext(const char *target_triple) :
+    m_target_triple(),
+    m_ast_context_ap(),
+    m_language_options_ap(),
+    m_source_manager_ap(),
+    m_diagnostic_ap(),
+    m_target_options_ap(),
+    m_target_info_ap(),
+    m_identifier_table_ap(),
+    m_selector_table_ap(),
+    m_builtins_ap()
+{
+    if (target_triple && target_triple[0])
+        m_target_triple.assign (target_triple);
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ClangASTContext::~ClangASTContext()
+{
+    m_builtins_ap.reset();
+    m_selector_table_ap.reset();
+    m_identifier_table_ap.reset();
+    m_target_info_ap.reset();
+    m_target_options_ap.reset();
+    m_diagnostic_ap.reset();
+    m_source_manager_ap.reset();
+    m_language_options_ap.reset();
+    m_ast_context_ap.reset();
+}
+
+
+void
+ClangASTContext::Clear()
+{
+    m_ast_context_ap.reset();
+    m_language_options_ap.reset();
+    m_source_manager_ap.reset();
+    m_diagnostic_ap.reset();
+    m_target_options_ap.reset();
+    m_target_info_ap.reset();
+    m_identifier_table_ap.reset();
+    m_selector_table_ap.reset();
+    m_builtins_ap.reset();
+}
+
+const char *
+ClangASTContext::GetTargetTriple ()
+{
+    return m_target_triple.c_str();
+}
+
+void
+ClangASTContext::SetTargetTriple (const char *target_triple)
+{
+    Clear();
+    m_target_triple.assign(target_triple);
+}
+
+
+ASTContext *
+ClangASTContext::getASTContext()
+{
+    if (m_ast_context_ap.get() == NULL)
+    {
+        m_ast_context_ap.reset(
+            new ASTContext(
+                *getLanguageOptions(),
+                *getSourceManager(),
+                *getTargetInfo(),
+                *getIdentifierTable(),
+                *getSelectorTable(),
+                *getBuiltinContext()));
+    }
+    return m_ast_context_ap.get();
+}
+
+Builtin::Context *
+ClangASTContext::getBuiltinContext()
+{
+    if (m_builtins_ap.get() == NULL)
+        m_builtins_ap.reset (new Builtin::Context(*getTargetInfo()));
+    return m_builtins_ap.get();
+}
+
+IdentifierTable *
+ClangASTContext::getIdentifierTable()
+{
+    if (m_identifier_table_ap.get() == NULL)
+        m_identifier_table_ap.reset(new IdentifierTable (*ClangASTContext::getLanguageOptions(), NULL));
+    return m_identifier_table_ap.get();
+}
+
+LangOptions *
+ClangASTContext::getLanguageOptions()
+{
+    if (m_language_options_ap.get() == NULL)
+    {
+        m_language_options_ap.reset(new LangOptions());
+        ParseLangArgs(*m_language_options_ap, FrontendOptions::IK_ObjCXX);
+//        InitializeLangOptions(*m_language_options_ap, FrontendOptions::IK_ObjCXX);
+    }
+    return m_language_options_ap.get();
+}
+
+SelectorTable *
+ClangASTContext::getSelectorTable()
+{
+    if (m_selector_table_ap.get() == NULL)
+        m_selector_table_ap.reset (new SelectorTable());
+    return m_selector_table_ap.get();
+}
+
+SourceManager *
+ClangASTContext::getSourceManager()
+{
+    if (m_source_manager_ap.get() == NULL)
+        m_source_manager_ap.reset(new SourceManager(*getDiagnostic()));
+    return m_source_manager_ap.get();
+}
+
+Diagnostic *
+ClangASTContext::getDiagnostic()
+{
+    if (m_diagnostic_ap.get() == NULL)
+        m_diagnostic_ap.reset(new Diagnostic());
+    return m_diagnostic_ap.get();
+}
+
+TargetOptions *
+ClangASTContext::getTargetOptions()
+{
+    if (m_target_options_ap.get() == NULL && !m_target_triple.empty())
+    {
+        m_target_options_ap.reset (new TargetOptions());
+        if (m_target_options_ap.get())
+            m_target_options_ap->Triple = m_target_triple;
+    }
+    return m_target_options_ap.get();
+}
+
+
+TargetInfo *
+ClangASTContext::getTargetInfo()
+{
+    // target_triple should be something like "x86_64-apple-darwin10"
+    if (m_target_info_ap.get() == NULL && !m_target_triple.empty())
+        m_target_info_ap.reset (TargetInfo::CreateTargetInfo(*getDiagnostic(), *getTargetOptions()));
+    return m_target_info_ap.get();
+}
+
+#pragma mark Basic Types
+
+static inline bool
+QualTypeMatchesBitSize(const uint64_t bit_size, ASTContext *ast_context, QualType qual_type)
+{
+    uint64_t qual_type_bit_size = ast_context->getTypeSize(qual_type);
+    if (qual_type_bit_size == bit_size)
+        return true;
+    return false;
+}
+
+void *
+ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (lldb::Encoding encoding, uint32_t bit_size)
+{
+    ASTContext *ast_context = getASTContext();
+
+    assert (ast_context != NULL);
+
+    return GetBuiltinTypeForEncodingAndBitSize (ast_context, encoding, bit_size);
+}
+
+void *
+ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (clang::ASTContext *ast_context, lldb::Encoding encoding, uint32_t bit_size)
+{
+    if (!ast_context)
+        return NULL;
+    
+    switch (encoding)
+    {
+    case lldb::eEncodingInvalid:
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->VoidPtrTy))
+            return ast_context->VoidPtrTy.getAsOpaquePtr();
+        break;
+        
+    case lldb::eEncodingUint:
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedCharTy))
+            return ast_context->UnsignedCharTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedShortTy))
+            return ast_context->UnsignedShortTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedIntTy))
+            return ast_context->UnsignedIntTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedLongTy))
+            return ast_context->UnsignedLongTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedLongLongTy))
+            return ast_context->UnsignedLongLongTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedInt128Ty))
+            return ast_context->UnsignedInt128Ty.getAsOpaquePtr();
+        break;
+        
+    case lldb::eEncodingSint:
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->CharTy))
+            return ast_context->CharTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->ShortTy))
+            return ast_context->ShortTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->IntTy))
+            return ast_context->IntTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->LongTy))
+            return ast_context->LongTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->LongLongTy))
+            return ast_context->LongLongTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->Int128Ty))
+            return ast_context->Int128Ty.getAsOpaquePtr();
+        break;
+        
+    case lldb::eEncodingIEEE754:
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->FloatTy))
+            return ast_context->FloatTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->DoubleTy))
+            return ast_context->DoubleTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->LongDoubleTy))
+            return ast_context->LongDoubleTy.getAsOpaquePtr();
+        break;
+        
+    case lldb::eEncodingVector:
+    default:
+        break;
+    }
+    
+    return NULL;
+}
+
+void *
+ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize (const char *type_name, uint32_t dw_ate, uint32_t bit_size)
+{
+    ASTContext *ast_context = getASTContext();
+
+    #define streq(a,b) strcmp(a,b) == 0
+    assert (ast_context != NULL);
+    if (ast_context)
+    {
+        switch (dw_ate)
+        {
+        default:
+            break;
+
+        case DW_ATE_address:
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->VoidPtrTy))
+                return ast_context->VoidPtrTy.getAsOpaquePtr();
+            break;
+
+        case DW_ATE_boolean:
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->BoolTy))
+                return ast_context->BoolTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedCharTy))
+                return ast_context->UnsignedCharTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedShortTy))
+                return ast_context->UnsignedShortTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedIntTy))
+                return ast_context->UnsignedIntTy.getAsOpaquePtr();
+            break;
+
+        case DW_ATE_complex_float:
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->FloatComplexTy))
+                return ast_context->FloatComplexTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->DoubleComplexTy))
+                return ast_context->DoubleComplexTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->LongDoubleComplexTy))
+                return ast_context->LongDoubleComplexTy.getAsOpaquePtr();
+            break;
+
+        case DW_ATE_float:
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->FloatTy))
+                return ast_context->FloatTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->DoubleTy))
+                return ast_context->DoubleTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->LongDoubleTy))
+                return ast_context->LongDoubleTy.getAsOpaquePtr();
+            break;
+
+        case DW_ATE_signed:
+            if (type_name)
+            {
+                if (streq(type_name, "int") ||
+                    streq(type_name, "signed int"))
+                {
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->IntTy))
+                        return ast_context->IntTy.getAsOpaquePtr();
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->Int128Ty))
+                        return ast_context->Int128Ty.getAsOpaquePtr();
+                }
+
+                if (streq(type_name, "long int") ||
+                    streq(type_name, "long long int") ||
+                    streq(type_name, "signed long long"))
+                {
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->LongTy))
+                        return ast_context->LongTy.getAsOpaquePtr();
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->LongLongTy))
+                        return ast_context->LongLongTy.getAsOpaquePtr();
+                }
+
+                if (streq(type_name, "short") ||
+                    streq(type_name, "short int") ||
+                    streq(type_name, "signed short") ||
+                    streq(type_name, "short signed int"))
+                {
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->ShortTy))
+                        return ast_context->ShortTy.getAsOpaquePtr();
+                }
+
+                if (streq(type_name, "char") ||
+                    streq(type_name, "signed char"))
+                {
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->CharTy))
+                        return ast_context->CharTy.getAsOpaquePtr();
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->SignedCharTy))
+                        return ast_context->SignedCharTy.getAsOpaquePtr();
+                }
+
+                if (streq(type_name, "wchar_t"))
+                {
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->WCharTy))
+                        return ast_context->WCharTy.getAsOpaquePtr();
+                }
+
+            }
+            // We weren't able to match up a type name, just search by size
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->CharTy))
+                return ast_context->CharTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->ShortTy))
+                return ast_context->ShortTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->IntTy))
+                return ast_context->IntTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->LongTy))
+                return ast_context->LongTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->LongLongTy))
+                return ast_context->LongLongTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->Int128Ty))
+                return ast_context->Int128Ty.getAsOpaquePtr();
+            break;
+
+        case DW_ATE_signed_char:
+            if (type_name)
+            {
+                if (streq(type_name, "signed char"))
+                {
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->SignedCharTy))
+                        return ast_context->SignedCharTy.getAsOpaquePtr();
+                }
+            }
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->CharTy))
+                return ast_context->CharTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->SignedCharTy))
+                return ast_context->SignedCharTy.getAsOpaquePtr();
+            break;
+
+        case DW_ATE_unsigned:
+            if (type_name)
+            {
+                if (streq(type_name, "unsigned int"))
+                {
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedIntTy))
+                        return ast_context->UnsignedIntTy.getAsOpaquePtr();
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedInt128Ty))
+                        return ast_context->UnsignedInt128Ty.getAsOpaquePtr();
+                }
+
+                if (streq(type_name, "unsigned int") ||
+                    streq(type_name, "long unsigned int") ||
+                    streq(type_name, "unsigned long long"))
+                {
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedLongTy))
+                        return ast_context->UnsignedLongTy.getAsOpaquePtr();
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedLongLongTy))
+                        return ast_context->UnsignedLongLongTy.getAsOpaquePtr();
+                }
+
+                if (streq(type_name, "unsigned short") ||
+                    streq(type_name, "short unsigned int"))
+                {
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedShortTy))
+                        return ast_context->UnsignedShortTy.getAsOpaquePtr();
+                }
+                if (streq(type_name, "unsigned char"))
+                {
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedCharTy))
+                        return ast_context->UnsignedCharTy.getAsOpaquePtr();
+                }
+
+            }
+            // We weren't able to match up a type name, just search by size
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedCharTy))
+                return ast_context->UnsignedCharTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedShortTy))
+                return ast_context->UnsignedShortTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedIntTy))
+                return ast_context->UnsignedIntTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedLongTy))
+                return ast_context->UnsignedLongTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedLongLongTy))
+                return ast_context->UnsignedLongLongTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedInt128Ty))
+                return ast_context->UnsignedInt128Ty.getAsOpaquePtr();
+            break;
+
+        case DW_ATE_unsigned_char:
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedCharTy))
+                return ast_context->UnsignedCharTy.getAsOpaquePtr();
+            break;
+
+        case DW_ATE_imaginary_float:
+            break;
+        }
+    }
+    // This assert should fire for anything that we don't catch above so we know
+    // to fix any issues we run into.
+    assert (!"error: ClangASTContext::GetClangTypeForDWARFEncodingAndSize() contains an unhandled encoding. Fix this ASAP!");
+    return NULL;
+}
+
+void *
+ClangASTContext::GetVoidBuiltInType()
+{
+    return getASTContext()->VoidTy.getAsOpaquePtr();
+}
+
+void *
+ClangASTContext::GetCStringType (bool is_const)
+{
+    QualType char_type(getASTContext()->CharTy);
+    
+    if (is_const)
+        char_type.addConst();
+    
+    return getASTContext()->getPointerType(char_type).getAsOpaquePtr();
+}
+
+void *
+ClangASTContext::GetVoidPtrType (bool is_const)
+{
+    return GetVoidPtrType(getASTContext(), is_const);
+}
+
+void *
+ClangASTContext::GetVoidPtrType (clang::ASTContext *ast_context, bool is_const)
+{
+    QualType void_ptr_type(ast_context->VoidPtrTy);
+    
+    if (is_const)
+        void_ptr_type.addConst();
+    
+    return void_ptr_type.getAsOpaquePtr();
+}
+
+void *
+ClangASTContext::CopyType(clang::ASTContext *dest_context, 
+                          clang::ASTContext *source_context,
+                          void * clang_type)
+{
+    Diagnostic diagnostics;
+    FileManager file_manager;
+    ASTImporter importer(diagnostics,
+                         *dest_context, file_manager,
+                         *source_context, file_manager);
+    QualType ret = importer.Import(QualType::getFromOpaquePtr(clang_type));
+    return ret.getAsOpaquePtr();
+}
+
+#pragma mark CVR modifiers
+
+void *
+ClangASTContext::AddConstModifier (void *clang_type)
+{
+    if (clang_type)
+    {
+        QualType result(QualType::getFromOpaquePtr(clang_type));
+        result.addConst();
+        return result.getAsOpaquePtr();
+    }
+    return NULL;
+}
+
+void *
+ClangASTContext::AddRestrictModifier (void *clang_type)
+{
+    if (clang_type)
+    {
+        QualType result(QualType::getFromOpaquePtr(clang_type));
+        result.getQualifiers().setRestrict (true);
+        return result.getAsOpaquePtr();
+    }
+    return NULL;
+}
+
+void *
+ClangASTContext::AddVolatileModifier (void *clang_type)
+{
+    if (clang_type)
+    {
+        QualType result(QualType::getFromOpaquePtr(clang_type));
+        result.getQualifiers().setVolatile (true);
+        return result.getAsOpaquePtr();
+    }
+    return NULL;
+}
+
+#pragma mark Structure, Unions, Classes
+
+void *
+ClangASTContext::CreateRecordType (const char *name, int kind, DeclContext *decl_ctx)
+{
+    ASTContext *ast_context = getASTContext();
+    assert (ast_context != NULL);
+
+    if (decl_ctx == NULL)
+        decl_ctx = ast_context->getTranslationUnitDecl();
+
+    // NOTE: Eventually CXXRecordDecl will be merged back into RecordDecl and
+    // we will need to update this code. I was told to currently always use
+    // the CXXRecordDecl class since we often don't know from debug information
+    // if something is struct or a class, so we default to always use the more
+    // complete definition just in case.
+    CXXRecordDecl *decl = CXXRecordDecl::Create(*ast_context,
+                                                (TagDecl::TagKind)kind,
+                                                decl_ctx,
+                                                SourceLocation(),
+                                                name && name[0] ? &ast_context->Idents.get(name) : NULL);
+
+    return ast_context->getTagDeclType(decl).getAsOpaquePtr();
+}
+
+bool
+ClangASTContext::AddFieldToRecordType (void * record_clang_type, const char *name, void * field_type, int access, uint32_t bitfield_bit_size)
+{
+    if (record_clang_type == NULL || field_type == NULL)
+        return false;
+
+    ASTContext *ast_context = getASTContext();
+    IdentifierTable *identifier_table = getIdentifierTable();
+
+    assert (ast_context != NULL);
+    assert (identifier_table != NULL);
+
+    QualType record_qual_type(QualType::getFromOpaquePtr(record_clang_type));
+
+    Type *clang_type = record_qual_type.getTypePtr();
+    if (clang_type)
+    {
+        const RecordType *record_type = dyn_cast<RecordType>(clang_type);
+
+        if (record_type)
+        {
+            RecordDecl *record_decl = record_type->getDecl();
+
+            CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+            if (cxx_record_decl)
+                cxx_record_decl->setEmpty (false);
+
+            clang::Expr *bit_width = NULL;
+            if (bitfield_bit_size != 0)
+            {
+                APInt bitfield_bit_size_apint(ast_context->getTypeSize(ast_context->IntTy), bitfield_bit_size);
+                bit_width = new (*ast_context)IntegerLiteral (bitfield_bit_size_apint, ast_context->IntTy, SourceLocation());
+            }
+            FieldDecl *field = FieldDecl::Create(*ast_context,
+                                                record_decl,
+                                                SourceLocation(),
+                                                name ? &identifier_table->get(name) : NULL, // Identifier
+                                                QualType::getFromOpaquePtr(field_type), // Field type
+                                                NULL,       // DeclaratorInfo *
+                                                bit_width,  // BitWidth
+                                                false);     // Mutable
+
+            field->setAccess((AccessSpecifier)access);
+
+            if (field)
+            {
+                record_decl->addDecl(field);
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+bool
+ClangASTContext::FieldIsBitfield (FieldDecl* field, uint32_t& bitfield_bit_size)
+{
+    return FieldIsBitfield(getASTContext(), field, bitfield_bit_size);
+}
+
+bool
+ClangASTContext::FieldIsBitfield
+(
+    ASTContext *ast_context,
+    FieldDecl* field,
+    uint32_t& bitfield_bit_size
+)
+{
+    if (ast_context == NULL || field == NULL)
+        return false;
+
+    if (field->isBitField())
+    {
+        Expr* bit_width_expr = field->getBitWidth();
+        if (bit_width_expr)
+        {
+            llvm::APSInt bit_width_apsint;
+            if (bit_width_expr->isIntegerConstantExpr(bit_width_apsint, *ast_context))
+            {
+                bitfield_bit_size = bit_width_apsint.getLimitedValue(UINT32_MAX);
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+bool
+ClangASTContext::RecordHasFields (const RecordDecl *record_decl)
+{
+    if (record_decl == NULL)
+        return false;
+
+    if (!record_decl->field_empty())
+        return true;
+
+    // No fields, lets check this is a CXX record and check the base classes
+    const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+    if (cxx_record_decl)
+    {
+        CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+        for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
+             base_class != base_class_end;
+             ++base_class)
+        {
+            const CXXRecordDecl *base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl());
+            if (RecordHasFields(base_class_decl))
+                return true;
+        }
+    }
+    return false;
+}
+
+void
+ClangASTContext::SetDefaultAccessForRecordFields (void *clang_qual_type, int default_accessibility, int *assigned_accessibilities, size_t num_assigned_accessibilities)
+{
+    if (clang_qual_type)
+    {
+        QualType qual_type(QualType::getFromOpaquePtr(clang_qual_type));
+        Type *clang_type = qual_type.getTypePtr();
+        if (clang_type)
+        {
+            RecordType *record_type = dyn_cast<RecordType>(clang_type);
+            if (record_type)
+            {
+                RecordDecl *record_decl = record_type->getDecl();
+                if (record_decl)
+                {
+                    uint32_t field_idx;
+                    RecordDecl::field_iterator field, field_end;
+                    for (field = record_decl->field_begin(), field_end = record_decl->field_end(), field_idx = 0;
+                         field != field_end;
+                         ++field, ++field_idx)
+                    {
+                        // If no accessibility was assigned, assign the correct one
+                        if (field_idx < num_assigned_accessibilities && assigned_accessibilities[field_idx] == clang::AS_none)
+                            field->setAccess ((AccessSpecifier)default_accessibility);
+                    }
+                }
+            }
+        }
+    }
+}
+
+#pragma mark C++ Base Classes
+
+CXXBaseSpecifier *
+ClangASTContext::CreateBaseClassSpecifier (void *base_class_type, int access, bool is_virtual, bool base_of_class)
+{
+    if (base_class_type)
+        return new CXXBaseSpecifier(SourceRange(), is_virtual, base_of_class, (AccessSpecifier)access, QualType::getFromOpaquePtr(base_class_type));
+    return NULL;
+}
+
+bool
+ClangASTContext::SetBaseClassesForClassType (void *class_clang_type, CXXBaseSpecifier const * const *base_classes, unsigned num_base_classes)
+{
+    if (class_clang_type)
+    {
+        ASTContext *ast_context = getASTContext();
+        IdentifierTable *identifier_table = getIdentifierTable();
+
+        assert (ast_context != NULL);
+        assert (identifier_table != NULL);
+
+        Type *clang_type = QualType::getFromOpaquePtr(class_clang_type).getTypePtr();
+        if (clang_type)
+        {
+            RecordType *record_type = dyn_cast<RecordType>(clang_type);
+            if (record_type)
+            {
+                CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_type->getDecl());
+                if (cxx_record_decl)
+                {
+                    //cxx_record_decl->setEmpty (false);
+                    cxx_record_decl->setBases(base_classes, num_base_classes);
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+
+#pragma mark Aggregate Types
+
+bool
+ClangASTContext::IsAggregateType (void *clang_type)
+{
+    if (clang_type == NULL)
+        return false;
+
+    QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+
+    if (qual_type->isAggregateType ())
+        return true;
+
+    switch (qual_type->getTypeClass())
+    {
+    case Type::IncompleteArray:
+    case Type::VariableArray:
+    case Type::ConstantArray:
+    case Type::ExtVector:
+    case Type::Vector:
+    case Type::Record:
+        return true;
+
+    case Type::Typedef:
+        return ClangASTContext::IsAggregateType (cast<TypedefType>(qual_type)->LookThroughTypedefs().getAsOpaquePtr());
+
+    default:
+        break;
+    }
+    // The clang type does have a value
+    return false;
+}
+
+uint32_t
+ClangASTContext::GetNumChildren (void *clang_qual_type, bool omit_empty_base_classes)
+{
+    if (clang_qual_type == NULL)
+        return 0;
+
+    uint32_t num_children = 0;
+    QualType qual_type(QualType::getFromOpaquePtr(clang_qual_type));
+    switch (qual_type->getTypeClass())
+    {
+    case Type::Record:
+        {
+            const RecordType *record_type = cast<RecordType>(qual_type.getTypePtr());
+            const RecordDecl *record_decl = record_type->getDecl();
+            assert(record_decl);
+            const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+            if (cxx_record_decl)
+            {
+                if (omit_empty_base_classes)
+                {
+                    // Check each base classes to see if it or any of its
+                    // base classes contain any fields. This can help
+                    // limit the noise in variable views by not having to
+                    // show base classes that contain no members.
+                    CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+                    for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
+                         base_class != base_class_end;
+                         ++base_class)
+                    {
+                        const CXXRecordDecl *base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl());
+
+                        // Skip empty base classes
+                        if (RecordHasFields(base_class_decl) == false)
+                            continue;
+
+                        num_children++;
+                    }
+                }
+                else
+                {
+                    // Include all base classes
+                    num_children += cxx_record_decl->getNumBases();
+                }
+
+            }
+            RecordDecl::field_iterator field, field_end;
+            for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field)
+                ++num_children;
+        }
+        break;
+
+    case Type::ConstantArray:
+        num_children = cast<ConstantArrayType>(qual_type.getTypePtr())->getSize().getLimitedValue();
+        break;
+
+    case Type::Pointer:
+        {
+            PointerType *pointer_type = cast<PointerType>(qual_type.getTypePtr());
+            QualType pointee_type = pointer_type->getPointeeType();
+            uint32_t num_pointee_children = ClangASTContext::GetNumChildren (pointee_type.getAsOpaquePtr(), omit_empty_base_classes);
+            // If this type points to a simple type, then it has 1 child
+            if (num_pointee_children == 0)
+                num_children = 1;
+            else
+                num_children = num_pointee_children;
+        }
+        break;
+
+    case Type::Typedef:
+        num_children = ClangASTContext::GetNumChildren (cast<TypedefType>(qual_type)->LookThroughTypedefs().getAsOpaquePtr(), omit_empty_base_classes);
+        break;
+
+    default:
+        break;
+    }
+    return num_children;
+}
+
+
+void *
+ClangASTContext::GetChildClangTypeAtIndex
+(
+    const char *parent_name,
+    void *parent_clang_type,
+    uint32_t idx,
+    bool transparent_pointers,
+    bool omit_empty_base_classes,
+    std::string& child_name,
+    uint32_t &child_byte_size,
+    int32_t &child_byte_offset,
+    uint32_t &child_bitfield_bit_size,
+    uint32_t &child_bitfield_bit_offset
+)
+{
+    if (parent_clang_type)
+
+        return GetChildClangTypeAtIndex (getASTContext(),
+                                         parent_name,
+                                         parent_clang_type,
+                                         idx,
+                                         transparent_pointers,
+                                         omit_empty_base_classes,
+                                         child_name,
+                                         child_byte_size,
+                                         child_byte_offset,
+                                         child_bitfield_bit_size,
+                                         child_bitfield_bit_offset);
+    return NULL;
+}
+
+void *
+ClangASTContext::GetChildClangTypeAtIndex
+(
+    ASTContext *ast_context,
+    const char *parent_name,
+    void *parent_clang_type,
+    uint32_t idx,
+    bool transparent_pointers,
+    bool omit_empty_base_classes,
+    std::string& child_name,
+    uint32_t &child_byte_size,
+    int32_t &child_byte_offset,
+    uint32_t &child_bitfield_bit_size,
+    uint32_t &child_bitfield_bit_offset
+)
+{
+    if (parent_clang_type == NULL)
+        return NULL;
+
+    if (idx < ClangASTContext::GetNumChildren (parent_clang_type, omit_empty_base_classes))
+    {
+        uint32_t bit_offset;
+        child_bitfield_bit_size = 0;
+        child_bitfield_bit_offset = 0;
+        QualType parent_qual_type(QualType::getFromOpaquePtr(parent_clang_type));
+        switch (parent_qual_type->getTypeClass())
+        {
+        case Type::Record:
+            {
+                const RecordType *record_type = cast<RecordType>(parent_qual_type.getTypePtr());
+                const RecordDecl *record_decl = record_type->getDecl();
+                assert(record_decl);
+                const ASTRecordLayout &record_layout = ast_context->getASTRecordLayout(record_decl);
+                uint32_t child_idx = 0;
+
+                const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+                if (cxx_record_decl)
+                {
+                    // We might have base classes to print out first
+                    CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+                    for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
+                         base_class != base_class_end;
+                         ++base_class)
+                    {
+                        const CXXRecordDecl *base_class_decl = NULL;
+
+                        // Skip empty base classes
+                        if (omit_empty_base_classes)
+                        {
+                            base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl());
+                            if (RecordHasFields(base_class_decl) == false)
+                                continue;
+                        }
+
+                        if (idx == child_idx)
+                        {
+                            if (base_class_decl == NULL)
+                                base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl());
+
+
+                            if (base_class->isVirtual())
+                                bit_offset = record_layout.getVBaseClassOffset(base_class_decl);
+                            else
+                                bit_offset = record_layout.getBaseClassOffset(base_class_decl);
+
+                            // Base classes should be a multiple of 8 bits in size
+                            assert (bit_offset % 8 == 0);
+                            child_byte_offset = bit_offset/8;
+                            std::string base_class_type_name(base_class->getType().getAsString());
+
+                            child_name.assign(base_class_type_name.c_str());
+
+                            uint64_t clang_type_info_bit_size = ast_context->getTypeSize(base_class->getType());
+
+                            // Base classes biut sizes should be a multiple of 8 bits in size
+                            assert (clang_type_info_bit_size % 8 == 0);
+                            child_byte_size = clang_type_info_bit_size / 8;
+                            return base_class->getType().getAsOpaquePtr();
+                        }
+                        // We don't increment the child index in the for loop since we might
+                        // be skipping empty base classes
+                        ++child_idx;
+                    }
+                }
+                const unsigned num_fields = record_layout.getFieldCount();
+
+                // Make sure index is in range...
+                uint32_t field_idx = 0;
+                RecordDecl::field_iterator field, field_end;
+                for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx, ++child_idx)
+                {
+                    if (idx == child_idx)
+                    {
+                        // Print the member type if requested
+                        // Print the member name and equal sign
+                        child_name.assign(field->getNameAsString().c_str());
+
+                        // Figure out the type byte size (field_type_info.first) and
+                        // alignment (field_type_info.second) from the AST context.
+                        std::pair<uint64_t, unsigned> field_type_info = ast_context->getTypeInfo(field->getType());
+                        assert(field_idx < num_fields);
+
+                        child_byte_size = field_type_info.first / 8;
+
+                        // Figure out the field offset within the current struct/union/class type
+                        bit_offset = record_layout.getFieldOffset (field_idx);
+                        child_byte_offset = bit_offset / 8;
+                        if (ClangASTContext::FieldIsBitfield (ast_context, *field, child_bitfield_bit_size))
+                            child_bitfield_bit_offset = bit_offset % 8;
+
+                        return field->getType().getAsOpaquePtr();
+                    }
+                }
+            }
+            break;
+
+        case Type::ConstantArray:
+            {
+                const ConstantArrayType *array = cast<ConstantArrayType>(parent_qual_type.getTypePtr());
+                const uint64_t element_count = array->getSize().getLimitedValue();
+
+                if (idx < element_count)
+                {
+                    std::pair<uint64_t, unsigned> field_type_info = ast_context->getTypeInfo(array->getElementType());
+
+                    char element_name[32];
+                    ::snprintf (element_name, sizeof (element_name), "%s[%u]", parent_name ? parent_name : "", idx);
+
+                    child_name.assign(element_name);
+                    assert(field_type_info.first % 8 == 0);
+                    child_byte_size = field_type_info.first / 8;
+                    child_byte_offset = idx * child_byte_size;
+                    return array->getElementType().getAsOpaquePtr();
+                }
+            }
+            break;
+
+        case Type::Pointer:
+            {
+                PointerType *pointer_type = cast<PointerType>(parent_qual_type.getTypePtr());
+                QualType pointee_type = pointer_type->getPointeeType();
+
+                if (transparent_pointers && ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
+                {
+                    return GetChildClangTypeAtIndex (ast_context,
+                                                     parent_name,
+                                                     pointer_type->getPointeeType().getAsOpaquePtr(),
+                                                     idx,
+                                                     transparent_pointers,
+                                                     omit_empty_base_classes,
+                                                     child_name,
+                                                     child_byte_size,
+                                                     child_byte_offset,
+                                                     child_bitfield_bit_size,
+                                                     child_bitfield_bit_offset);
+                }
+                else
+                {
+                    if (parent_name)
+                    {
+                        child_name.assign(1, '*');
+                        child_name += parent_name;
+                    }
+
+                    // We have a pointer to an simple type
+                    if (idx == 0)
+                    {
+                        std::pair<uint64_t, unsigned> clang_type_info = ast_context->getTypeInfo(pointee_type);
+                        assert(clang_type_info.first % 8 == 0);
+                        child_byte_size = clang_type_info.first / 8;
+                        child_byte_offset = 0;
+                        return pointee_type.getAsOpaquePtr();
+                    }
+                }
+            }
+            break;
+
+        case Type::Typedef:
+            return GetChildClangTypeAtIndex (ast_context,
+                                             parent_name,
+                                             cast<TypedefType>(parent_qual_type)->LookThroughTypedefs().getAsOpaquePtr(),
+                                             idx,
+                                             transparent_pointers,
+                                             omit_empty_base_classes,
+                                             child_name,
+                                             child_byte_size,
+                                             child_byte_offset,
+                                             child_bitfield_bit_size,
+                                             child_bitfield_bit_offset);
+            break;
+
+        default:
+            break;
+        }
+    }
+    return false;
+}
+
+static inline bool
+BaseSpecifierIsEmpty (const CXXBaseSpecifier *b)
+{
+    return ClangASTContext::RecordHasFields(cast<CXXRecordDecl>(b->getType()->getAs<RecordType>()->getDecl())) == false;
+}
+
+static uint32_t
+GetNumBaseClasses (const CXXRecordDecl *cxx_record_decl, bool omit_empty_base_classes)
+{
+    uint32_t num_bases = 0;
+    if (cxx_record_decl)
+    {
+        if (omit_empty_base_classes)
+        {
+            CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+            for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
+                 base_class != base_class_end;
+                 ++base_class)
+            {
+                // Skip empty base classes
+                if (omit_empty_base_classes)
+                {
+                    if (BaseSpecifierIsEmpty (base_class))
+                        continue;
+                }
+                ++num_bases;
+            }
+        }
+        else
+            num_bases = cxx_record_decl->getNumBases();
+    }
+    return num_bases;
+}
+
+
+static uint32_t
+GetIndexForRecordBase
+(
+    const RecordDecl *record_decl,
+    const CXXBaseSpecifier *base_spec,
+    bool omit_empty_base_classes
+)
+{
+    uint32_t child_idx = 0;
+
+    const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+
+//    const char *super_name = record_decl->getNameAsCString();
+//    const char *base_name = base_spec->getType()->getAs<RecordType>()->getDecl()->getNameAsCString();
+//    printf ("GetIndexForRecordChild (%s, %s)\n", super_name, base_name);
+//
+    if (cxx_record_decl)
+    {
+        CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+        for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
+             base_class != base_class_end;
+             ++base_class)
+        {
+            if (omit_empty_base_classes)
+            {
+                if (BaseSpecifierIsEmpty (base_class))
+                    continue;
+            }
+
+//            printf ("GetIndexForRecordChild (%s, %s) base[%u] = %s\n", super_name, base_name,
+//                    child_idx,
+//                    base_class->getType()->getAs<RecordType>()->getDecl()->getNameAsCString());
+//
+//
+            if (base_class == base_spec)
+                return child_idx;
+            ++child_idx;
+        }
+    }
+
+    return UINT32_MAX;
+}
+
+
+static uint32_t
+GetIndexForRecordChild
+(
+    const RecordDecl *record_decl,
+    NamedDecl *canonical_decl,
+    bool omit_empty_base_classes
+)
+{
+    uint32_t child_idx = GetNumBaseClasses (dyn_cast<CXXRecordDecl>(record_decl), omit_empty_base_classes);
+
+//    const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+//
+////    printf ("GetIndexForRecordChild (%s, %s)\n", record_decl->getNameAsCString(), canonical_decl->getNameAsCString());
+//    if (cxx_record_decl)
+//    {
+//        CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+//        for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
+//             base_class != base_class_end;
+//             ++base_class)
+//        {
+//            if (omit_empty_base_classes)
+//            {
+//                if (BaseSpecifierIsEmpty (base_class))
+//                    continue;
+//            }
+//
+////            printf ("GetIndexForRecordChild (%s, %s) base[%u] = %s\n",
+////                    record_decl->getNameAsCString(),
+////                    canonical_decl->getNameAsCString(),
+////                    child_idx,
+////                    base_class->getType()->getAs<RecordType>()->getDecl()->getNameAsCString());
+//
+//
+//            CXXRecordDecl *curr_base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl());
+//            if (curr_base_class_decl == canonical_decl)
+//            {
+//                return child_idx;
+//            }
+//            ++child_idx;
+//        }
+//    }
+//
+//    const uint32_t num_bases = child_idx;
+    RecordDecl::field_iterator field, field_end;
+    for (field = record_decl->field_begin(), field_end = record_decl->field_end();
+         field != field_end;
+         ++field, ++child_idx)
+    {
+//            printf ("GetIndexForRecordChild (%s, %s) field[%u] = %s\n",
+//                    record_decl->getNameAsCString(),
+//                    canonical_decl->getNameAsCString(),
+//                    child_idx - num_bases,
+//                    field->getNameAsCString());
+
+        if (field->getCanonicalDecl() == canonical_decl)
+            return child_idx;
+    }
+
+    return UINT32_MAX;
+}
+
+// Look for a child member (doesn't include base classes, but it does include
+// their members) in the type hierarchy. Returns an index path into "clang_type"
+// on how to reach the appropriate member.
+//
+//    class A
+//    {
+//    public:
+//        int m_a;
+//        int m_b;
+//    };
+//
+//    class B
+//    {
+//    };
+//
+//    class C :
+//        public B,
+//        public A
+//    {
+//    };
+//
+// If we have a clang type that describes "class C", and we wanted to looked
+// "m_b" in it:
+//
+// With omit_empty_base_classes == false we would get an integer array back with:
+// { 1,  1 }
+// The first index 1 is the child index for "class A" within class C
+// The second index 1 is the child index for "m_b" within class A
+//
+// With omit_empty_base_classes == true we would get an integer array back with:
+// { 0,  1 }
+// The first index 0 is the child index for "class A" within class C (since class B doesn't have any members it doesn't count)
+// The second index 1 is the child index for "m_b" within class A
+
+size_t
+ClangASTContext::GetIndexOfChildMemberWithName
+(
+    ASTContext *ast_context,
+    void *clang_type,
+    const char *name,
+    bool omit_empty_base_classes,
+    std::vector<uint32_t>& child_indexes
+)
+{
+    if (clang_type && name && name[0])
+    {
+        QualType qual_type(QualType::getFromOpaquePtr(clang_type));
+        switch (qual_type->getTypeClass())
+        {
+        case Type::Record:
+            {
+                const RecordType *record_type = cast<RecordType>(qual_type.getTypePtr());
+                const RecordDecl *record_decl = record_type->getDecl();
+
+                assert(record_decl);
+                uint32_t child_idx = 0;
+
+                const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+
+                // Try and find a field that matches NAME
+                RecordDecl::field_iterator field, field_end;
+                StringRef name_sref(name);
+                for (field = record_decl->field_begin(), field_end = record_decl->field_end();
+                     field != field_end;
+                     ++field, ++child_idx)
+                {
+                    if (field->getName().equals (name_sref))
+                    {
+                        // We have to add on the number of base classes to this index!
+                        child_indexes.push_back (child_idx + GetNumBaseClasses (cxx_record_decl, omit_empty_base_classes));
+                        return child_indexes.size();
+                    }
+                }
+
+                if (cxx_record_decl)
+                {
+                    const RecordDecl *parent_record_decl = cxx_record_decl;
+
+                    //printf ("parent = %s\n", parent_record_decl->getNameAsCString());
+
+                    //const Decl *root_cdecl = cxx_record_decl->getCanonicalDecl();
+                    // Didn't find things easily, lets let clang do its thang...
+                    IdentifierInfo & ident_ref = ast_context->Idents.get(name, name + strlen (name));
+                    DeclarationName decl_name(&ident_ref);
+
+                    CXXBasePaths paths;
+                    if (cxx_record_decl->lookupInBases(CXXRecordDecl::FindOrdinaryMember,
+                                                       decl_name.getAsOpaquePtr(),
+                                                       paths))
+                    {
+                        uint32_t child_idx;
+                        CXXBasePaths::const_paths_iterator path, path_end = paths.end();
+                        for (path = paths.begin(); path != path_end; ++path)
+                        {
+                            const size_t num_path_elements = path->size();
+                            for (size_t e=0; e<num_path_elements; ++e)
+                            {
+                                CXXBasePathElement elem = (*path)[e];
+
+                                child_idx = GetIndexForRecordBase (parent_record_decl, elem.Base, omit_empty_base_classes);
+                                if (child_idx == UINT32_MAX)
+                                {
+                                    child_indexes.clear();
+                                    return 0;
+                                }
+                                else
+                                {
+                                    child_indexes.push_back (child_idx);
+                                    parent_record_decl = cast<RecordDecl>(elem.Base->getType()->getAs<RecordType>()->getDecl());
+                                }
+                            }
+                            DeclContext::lookup_iterator named_decl_pos;
+                            for (named_decl_pos = path->Decls.first;
+                                 named_decl_pos != path->Decls.second && parent_record_decl;
+                                 ++named_decl_pos)
+                            {
+                                //printf ("path[%zu] = %s\n", child_indexes.size(), (*named_decl_pos)->getNameAsCString());
+
+                                child_idx = GetIndexForRecordChild (parent_record_decl, *named_decl_pos, omit_empty_base_classes);
+                                if (child_idx == UINT32_MAX)
+                                {
+                                    child_indexes.clear();
+                                    return 0;
+                                }
+                                else
+                                {
+                                    child_indexes.push_back (child_idx);
+                                }
+                            }
+                        }
+                        return child_indexes.size();
+                    }
+                }
+
+            }
+            break;
+
+        case Type::ConstantArray:
+            {
+//                const ConstantArrayType *array = cast<ConstantArrayType>(parent_qual_type.getTypePtr());
+//                const uint64_t element_count = array->getSize().getLimitedValue();
+//
+//                if (idx < element_count)
+//                {
+//                    std::pair<uint64_t, unsigned> field_type_info = ast_context->getTypeInfo(array->getElementType());
+//
+//                    char element_name[32];
+//                    ::snprintf (element_name, sizeof (element_name), "%s[%u]", parent_name ? parent_name : "", idx);
+//
+//                    child_name.assign(element_name);
+//                    assert(field_type_info.first % 8 == 0);
+//                    child_byte_size = field_type_info.first / 8;
+//                    child_byte_offset = idx * child_byte_size;
+//                    return array->getElementType().getAsOpaquePtr();
+//                }
+            }
+            break;
+
+//        case Type::MemberPointerType:
+//            {
+//                MemberPointerType *mem_ptr_type = cast<MemberPointerType>(qual_type.getTypePtr());
+//                QualType pointee_type = mem_ptr_type->getPointeeType();
+//
+//                if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
+//                {
+//                    return GetIndexOfChildWithName (ast_context,
+//                                                    mem_ptr_type->getPointeeType().getAsOpaquePtr(),
+//                                                    name);
+//                }
+//            }
+//            break;
+//
+        case Type::LValueReference:
+        case Type::RValueReference:
+            {
+                ReferenceType *reference_type = cast<ReferenceType>(qual_type.getTypePtr());
+                QualType pointee_type = reference_type->getPointeeType();
+
+                if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
+                {
+                    return GetIndexOfChildMemberWithName (ast_context,
+                                                          reference_type->getPointeeType().getAsOpaquePtr(),
+                                                          name,
+                                                          omit_empty_base_classes,
+                                                          child_indexes);
+                }
+            }
+            break;
+
+        case Type::Pointer:
+            {
+                PointerType *pointer_type = cast<PointerType>(qual_type.getTypePtr());
+                QualType pointee_type = pointer_type->getPointeeType();
+
+                if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
+                {
+                    return GetIndexOfChildMemberWithName (ast_context,
+                                                          pointer_type->getPointeeType().getAsOpaquePtr(),
+                                                          name,
+                                                          omit_empty_base_classes,
+                                                          child_indexes);
+                }
+                else
+                {
+//                    if (parent_name)
+//                    {
+//                        child_name.assign(1, '*');
+//                        child_name += parent_name;
+//                    }
+//
+//                    // We have a pointer to an simple type
+//                    if (idx == 0)
+//                    {
+//                        std::pair<uint64_t, unsigned> clang_type_info = ast_context->getTypeInfo(pointee_type);
+//                        assert(clang_type_info.first % 8 == 0);
+//                        child_byte_size = clang_type_info.first / 8;
+//                        child_byte_offset = 0;
+//                        return pointee_type.getAsOpaquePtr();
+//                    }
+                }
+            }
+            break;
+
+        case Type::Typedef:
+            return GetIndexOfChildMemberWithName (ast_context,
+                                                  cast<TypedefType>(qual_type)->LookThroughTypedefs().getAsOpaquePtr(),
+                                                  name,
+                                                  omit_empty_base_classes,
+                                                  child_indexes);
+
+        default:
+            break;
+        }
+    }
+    return 0;
+}
+
+
+// Get the index of the child of "clang_type" whose name matches. This function
+// doesn't descend into the children, but only looks one level deep and name
+// matches can include base class names.
+
+uint32_t
+ClangASTContext::GetIndexOfChildWithName
+(
+    ASTContext *ast_context,
+    void *clang_type,
+    const char *name,
+    bool omit_empty_base_classes
+)
+{
+    if (clang_type && name && name[0])
+    {
+        QualType qual_type(QualType::getFromOpaquePtr(clang_type));
+        switch (qual_type->getTypeClass())
+        {
+        case Type::Record:
+            {
+                const RecordType *record_type = cast<RecordType>(qual_type.getTypePtr());
+                const RecordDecl *record_decl = record_type->getDecl();
+
+                assert(record_decl);
+                uint32_t child_idx = 0;
+
+                const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+
+                if (cxx_record_decl)
+                {
+                    CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+                    for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
+                         base_class != base_class_end;
+                         ++base_class)
+                    {
+                        // Skip empty base classes
+                        CXXRecordDecl *base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl());
+                        if (omit_empty_base_classes && RecordHasFields(base_class_decl) == false)
+                            continue;
+
+                        if (base_class->getType().getAsString().compare (name) == 0)
+                            return child_idx;
+                        ++child_idx;
+                    }
+                }
+
+                // Try and find a field that matches NAME
+                RecordDecl::field_iterator field, field_end;
+                StringRef name_sref(name);
+                for (field = record_decl->field_begin(), field_end = record_decl->field_end();
+                     field != field_end;
+                     ++field, ++child_idx)
+                {
+                    if (field->getName().equals (name_sref))
+                        return child_idx;
+                }
+
+            }
+            break;
+
+        case Type::ConstantArray:
+            {
+//                const ConstantArrayType *array = cast<ConstantArrayType>(parent_qual_type.getTypePtr());
+//                const uint64_t element_count = array->getSize().getLimitedValue();
+//
+//                if (idx < element_count)
+//                {
+//                    std::pair<uint64_t, unsigned> field_type_info = ast_context->getTypeInfo(array->getElementType());
+//
+//                    char element_name[32];
+//                    ::snprintf (element_name, sizeof (element_name), "%s[%u]", parent_name ? parent_name : "", idx);
+//
+//                    child_name.assign(element_name);
+//                    assert(field_type_info.first % 8 == 0);
+//                    child_byte_size = field_type_info.first / 8;
+//                    child_byte_offset = idx * child_byte_size;
+//                    return array->getElementType().getAsOpaquePtr();
+//                }
+            }
+            break;
+
+//        case Type::MemberPointerType:
+//            {
+//                MemberPointerType *mem_ptr_type = cast<MemberPointerType>(qual_type.getTypePtr());
+//                QualType pointee_type = mem_ptr_type->getPointeeType();
+//
+//                if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
+//                {
+//                    return GetIndexOfChildWithName (ast_context,
+//                                                    mem_ptr_type->getPointeeType().getAsOpaquePtr(),
+//                                                    name);
+//                }
+//            }
+//            break;
+//
+        case Type::LValueReference:
+        case Type::RValueReference:
+            {
+                ReferenceType *reference_type = cast<ReferenceType>(qual_type.getTypePtr());
+                QualType pointee_type = reference_type->getPointeeType();
+
+                if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
+                {
+                    return GetIndexOfChildWithName (ast_context,
+                                                    reference_type->getPointeeType().getAsOpaquePtr(),
+                                                    name,
+                                                    omit_empty_base_classes);
+                }
+            }
+            break;
+
+        case Type::Pointer:
+            {
+                PointerType *pointer_type = cast<PointerType>(qual_type.getTypePtr());
+                QualType pointee_type = pointer_type->getPointeeType();
+
+                if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
+                {
+                    return GetIndexOfChildWithName (ast_context,
+                                                    pointer_type->getPointeeType().getAsOpaquePtr(),
+                                                    name,
+                                                    omit_empty_base_classes);
+                }
+                else
+                {
+//                    if (parent_name)
+//                    {
+//                        child_name.assign(1, '*');
+//                        child_name += parent_name;
+//                    }
+//
+//                    // We have a pointer to an simple type
+//                    if (idx == 0)
+//                    {
+//                        std::pair<uint64_t, unsigned> clang_type_info = ast_context->getTypeInfo(pointee_type);
+//                        assert(clang_type_info.first % 8 == 0);
+//                        child_byte_size = clang_type_info.first / 8;
+//                        child_byte_offset = 0;
+//                        return pointee_type.getAsOpaquePtr();
+//                    }
+                }
+            }
+            break;
+
+        case Type::Typedef:
+            return GetIndexOfChildWithName (ast_context,
+                                            cast<TypedefType>(qual_type)->LookThroughTypedefs().getAsOpaquePtr(),
+                                            name,
+                                            omit_empty_base_classes);
+
+        default:
+            break;
+        }
+    }
+    return UINT32_MAX;
+}
+
+#pragma mark TagType
+
+bool
+ClangASTContext::SetTagTypeKind (void *tag_clang_type, int kind)
+{
+    if (tag_clang_type)
+    {
+        QualType tag_qual_type(QualType::getFromOpaquePtr(tag_clang_type));
+        Type *clang_type = tag_qual_type.getTypePtr();
+        if (clang_type)
+        {
+            TagType *tag_type = dyn_cast<TagType>(clang_type);
+            if (tag_type)
+            {
+                TagDecl *tag_decl = dyn_cast<TagDecl>(tag_type->getDecl());
+                if (tag_decl)
+                {
+                    tag_decl->setTagKind ((TagDecl::TagKind)kind);
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+
+#pragma mark DeclContext Functions
+
+DeclContext *
+ClangASTContext::GetDeclContextForType (void *clang_type)
+{
+    if (clang_type == NULL)
+        return NULL;
+
+    QualType qual_type(QualType::getFromOpaquePtr(clang_type));
+    switch (qual_type->getTypeClass())
+    {
+    case Type::FunctionNoProto:         break;
+    case Type::FunctionProto:           break;
+    case Type::IncompleteArray:         break;
+    case Type::VariableArray:           break;
+    case Type::ConstantArray:           break;
+    case Type::ExtVector:               break;
+    case Type::Vector:                  break;
+    case Type::Builtin:                 break;
+    case Type::ObjCObjectPointer:       break;
+    case Type::BlockPointer:            break;
+    case Type::Pointer:                 break;
+    case Type::LValueReference:         break;
+    case Type::RValueReference:         break;
+    case Type::MemberPointer:           break;
+    case Type::Complex:                 break;
+    case Type::ObjCInterface:           break;
+    case Type::Record:
+        return cast<RecordType>(qual_type)->getDecl();
+    case Type::Enum:
+        return cast<EnumType>(qual_type)->getDecl();
+    case Type::Typedef:
+        return ClangASTContext::GetDeclContextForType (cast<TypedefType>(qual_type)->LookThroughTypedefs().getAsOpaquePtr());
+
+    case Type::TypeOfExpr:              break;
+    case Type::TypeOf:                  break;
+    case Type::Decltype:                break;
+    //case Type::QualifiedName:           break;
+    case Type::TemplateSpecialization:  break;
+    }
+    // No DeclContext in this type...
+    return NULL;
+}
+
+#pragma mark Namespace Declarations
+
+NamespaceDecl *
+ClangASTContext::GetUniqueNamespaceDeclaration (const char *name, const Declaration &decl, DeclContext *decl_ctx)
+{
+    // TODO: Do something intelligent with the Declaration object passed in
+    // like maybe filling in the SourceLocation with it...
+    if (name)
+    {
+        ASTContext *ast_context = getASTContext();
+        if (decl_ctx == NULL)
+            decl_ctx = ast_context->getTranslationUnitDecl();
+        return NamespaceDecl::Create(*ast_context, decl_ctx, SourceLocation(), &ast_context->Idents.get(name));
+    }
+    return NULL;
+}
+
+
+#pragma mark Function Types
+
+FunctionDecl *
+ClangASTContext::CreateFunctionDeclaration (const char *name, void *function_clang_type, int storage, bool is_inline)
+{
+    if (name)
+    {
+        ASTContext *ast_context = getASTContext();
+        assert (ast_context != NULL);
+
+        if (name && name[0])
+        {
+            return FunctionDecl::Create(*ast_context,
+                                        ast_context->getTranslationUnitDecl(),
+                                        SourceLocation(),
+                                        DeclarationName (&ast_context->Idents.get(name)),
+                                        QualType::getFromOpaquePtr(function_clang_type),
+                                        NULL,
+                                        (FunctionDecl::StorageClass)storage,
+                                        (FunctionDecl::StorageClass)storage,
+                                        is_inline);
+        }
+        else
+        {
+            return FunctionDecl::Create(*ast_context,
+                                        ast_context->getTranslationUnitDecl(),
+                                        SourceLocation(),
+                                        DeclarationName (),
+                                        QualType::getFromOpaquePtr(function_clang_type),
+                                        NULL,
+                                        (FunctionDecl::StorageClass)storage,
+                                        (FunctionDecl::StorageClass)storage,
+                                        is_inline);
+        }
+    }
+    return NULL;
+}
+
+void *
+ClangASTContext::CreateFunctionType (void *result_type, void **args, unsigned num_args, bool isVariadic, unsigned TypeQuals)
+{
+    ASTContext *ast_context = getASTContext();
+    assert (ast_context != NULL);
+    std::vector<QualType> qual_type_args;
+    for (unsigned i=0; i<num_args; ++i)
+        qual_type_args.push_back (QualType::getFromOpaquePtr(args[i]));
+
+    // TODO: Detect calling convention in DWARF?
+    return ast_context->getFunctionType(QualType::getFromOpaquePtr(result_type),
+                                        qual_type_args.data(),
+                                        qual_type_args.size(),
+                                        isVariadic,
+                                        TypeQuals,
+                                        false,  // hasExceptionSpec
+                                        false,  // hasAnyExceptionSpec,
+                                        0,      // NumExs
+                                        0,      // const QualType *ExArray
+                                        FunctionType::ExtInfo ()).getAsOpaquePtr();    // NoReturn);
+}
+
+ParmVarDecl *
+ClangASTContext::CreateParmeterDeclaration (const char *name, void * return_type, int storage)
+{
+    ASTContext *ast_context = getASTContext();
+    assert (ast_context != NULL);
+    return ParmVarDecl::Create(*ast_context,
+                                ast_context->getTranslationUnitDecl(),
+                                SourceLocation(),
+                                name && name[0] ? &ast_context->Idents.get(name) : NULL,
+                                QualType::getFromOpaquePtr(return_type),
+                                NULL,
+                                (VarDecl::StorageClass)storage,
+                                (VarDecl::StorageClass)storage,
+                                0);
+}
+
+void
+ClangASTContext::SetFunctionParameters (FunctionDecl *function_decl, ParmVarDecl **params, unsigned num_params)
+{
+    if (function_decl)
+        function_decl->setParams (params, num_params);
+}
+
+
+#pragma mark Array Types
+
+void *
+ClangASTContext::CreateArrayType (void *element_type, size_t element_count, uint32_t bit_stride)
+{
+    if (element_type)
+    {
+        ASTContext *ast_context = getASTContext();
+        assert (ast_context != NULL);
+        llvm::APInt ap_element_count (64, element_count);
+        return ast_context->getConstantArrayType(QualType::getFromOpaquePtr(element_type),
+                                                 ap_element_count,
+                                                 ArrayType::Normal,
+                                                 0).getAsOpaquePtr(); // ElemQuals
+    }
+    return NULL;
+}
+
+
+#pragma mark TagDecl
+
+bool
+ClangASTContext::StartTagDeclarationDefinition (void *clang_type)
+{
+    if (clang_type)
+    {
+        QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+        Type *t = qual_type.getTypePtr();
+        if (t)
+        {
+            TagType *tag_type = dyn_cast<TagType>(t);
+            if (tag_type)
+            {
+                TagDecl *tag_decl = tag_type->getDecl();
+                if (tag_decl)
+                {
+                    tag_decl->startDefinition();
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+bool
+ClangASTContext::CompleteTagDeclarationDefinition (void *clang_type)
+{
+    if (clang_type)
+    {
+        QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+        Type *t = qual_type.getTypePtr();
+        if (t)
+        {
+            TagType *tag_type = dyn_cast<TagType>(t);
+            if (tag_type)
+            {
+                TagDecl *tag_decl = tag_type->getDecl();
+                if (tag_decl)
+                {
+                    tag_decl->completeDefinition();
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+
+#pragma mark Enumeration Types
+
+void *
+ClangASTContext::CreateEnumerationType (const Declaration &decl, const char *name)
+{
+    // TODO: Do something intelligent with the Declaration object passed in
+    // like maybe filling in the SourceLocation with it...
+    ASTContext *ast_context = getASTContext();
+    assert (ast_context != NULL);
+    EnumDecl *enum_decl = EnumDecl::Create(*ast_context,
+                                           ast_context->getTranslationUnitDecl(),
+                                           SourceLocation(),
+                                           name && name[0] ? &ast_context->Idents.get(name) : NULL,
+                                           SourceLocation(),
+                                           NULL);
+    if (enum_decl)
+        return ast_context->getTagDeclType(enum_decl).getAsOpaquePtr();
+    return NULL;
+}
+
+bool
+ClangASTContext::AddEnumerationValueToEnumerationType
+(
+    void *enum_clang_type,
+    void *enumerator_clang_type,
+    const Declaration &decl,
+    const char *name,
+    int64_t enum_value,
+    uint32_t enum_value_bit_size
+)
+{
+    if (enum_clang_type && enumerator_clang_type && name)
+    {
+        // TODO: Do something intelligent with the Declaration object passed in
+        // like maybe filling in the SourceLocation with it...
+        ASTContext *ast_context = getASTContext();
+        IdentifierTable *identifier_table = getIdentifierTable();
+
+        assert (ast_context != NULL);
+        assert (identifier_table != NULL);
+        QualType enum_qual_type (QualType::getFromOpaquePtr(enum_clang_type));
+
+        Type *clang_type = enum_qual_type.getTypePtr();
+        if (clang_type)
+        {
+            const EnumType *enum_type = dyn_cast<EnumType>(clang_type);
+
+            if (enum_type)
+            {
+                llvm::APSInt enum_llvm_apsint(enum_value_bit_size, false);
+                enum_llvm_apsint = enum_value;
+                EnumConstantDecl *enumerator_decl =
+                    EnumConstantDecl::Create(*ast_context,
+                                             enum_type->getDecl(),
+                                             SourceLocation(),
+                                             name ? &identifier_table->get(name) : NULL,    // Identifier
+                                             QualType::getFromOpaquePtr(enumerator_clang_type),
+                                             NULL,
+                                             enum_llvm_apsint);
+
+                if (enumerator_decl)
+                {
+                    enum_type->getDecl()->addDecl(enumerator_decl);
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+#pragma mark Pointers & References
+
+void *
+ClangASTContext::CreatePointerType (void *clang_type)
+{
+    if (clang_type)
+        return getASTContext()->getPointerType(QualType::getFromOpaquePtr(clang_type)).getAsOpaquePtr();
+    return NULL;
+}
+
+void *
+ClangASTContext::CreateLValueReferenceType (void *clang_type)
+{
+    if (clang_type)
+        return getASTContext()->getLValueReferenceType (QualType::getFromOpaquePtr(clang_type)).getAsOpaquePtr();
+    return NULL;
+}
+
+void *
+ClangASTContext::CreateRValueReferenceType (void *clang_type)
+{
+    if (clang_type)
+        return getASTContext()->getRValueReferenceType (QualType::getFromOpaquePtr(clang_type)).getAsOpaquePtr();
+    return NULL;
+}
+
+size_t
+ClangASTContext::GetPointerBitSize ()
+{
+    ASTContext *ast_context = getASTContext();
+    return ast_context->getTypeSize(ast_context->VoidPtrTy);
+}
+
+bool
+ClangASTContext::IsPointerOrReferenceType (void *clang_type, void **target_type)
+{
+    if (clang_type == NULL)
+        return false;
+
+    QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+    switch (qual_type->getTypeClass())
+    {
+    case Type::ObjCObjectPointer:
+        if (target_type)
+            *target_type = cast<ObjCObjectPointerType>(qual_type)->getPointeeType().getAsOpaquePtr();
+        return true;
+    case Type::BlockPointer:
+        if (target_type)
+            *target_type = cast<BlockPointerType>(qual_type)->getPointeeType().getAsOpaquePtr();
+        return true;
+    case Type::Pointer:
+        if (target_type)
+            *target_type = cast<PointerType>(qual_type)->getPointeeType().getAsOpaquePtr();
+        return true;
+    case Type::MemberPointer:
+        if (target_type)
+            *target_type = cast<MemberPointerType>(qual_type)->getPointeeType().getAsOpaquePtr();
+        return true;
+    case Type::LValueReference:
+        if (target_type)
+            *target_type = cast<LValueReferenceType>(qual_type)->desugar().getAsOpaquePtr();
+        return true;
+    case Type::RValueReference:
+        if (target_type)
+            *target_type = cast<LValueReferenceType>(qual_type)->desugar().getAsOpaquePtr();
+        return true;
+    case Type::Typedef:
+        return ClangASTContext::IsPointerOrReferenceType (cast<TypedefType>(qual_type)->LookThroughTypedefs().getAsOpaquePtr());
+    default:
+        break;
+    }
+    return false;
+}
+
+size_t
+ClangASTContext::GetTypeBitSize (clang::ASTContext *ast_context, void *clang_type)
+{
+    if (clang_type)
+        return ast_context->getTypeSize(QualType::getFromOpaquePtr(clang_type));
+    return 0;
+}
+
+size_t
+ClangASTContext::GetTypeBitAlign (clang::ASTContext *ast_context, void *clang_type)
+{
+    if (clang_type)
+        return ast_context->getTypeAlign(QualType::getFromOpaquePtr(clang_type));
+    return 0;
+}
+
+bool
+ClangASTContext::IsIntegerType (void * clang_type, bool &is_signed)
+{
+    if (!clang_type)
+        return false;
+    
+    QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+    const BuiltinType *builtin_type = dyn_cast<BuiltinType>(qual_type->getCanonicalTypeInternal());
+    
+    if (builtin_type)
+    {
+        if (builtin_type->isInteger())
+            is_signed = builtin_type->isSignedInteger();
+        
+        return true;
+    }
+    
+    return false;
+}
+
+bool
+ClangASTContext::IsPointerType (void *clang_type, void **target_type)
+{
+    if (clang_type)
+    {
+        QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+        switch (qual_type->getTypeClass())
+        {
+        case Type::ObjCObjectPointer:
+            if (target_type)
+                *target_type = cast<ObjCObjectPointerType>(qual_type)->getPointeeType().getAsOpaquePtr();
+            return true;
+        case Type::BlockPointer:
+            if (target_type)
+                *target_type = cast<BlockPointerType>(qual_type)->getPointeeType().getAsOpaquePtr();
+            return true;
+        case Type::Pointer:
+            if (target_type)
+                *target_type = cast<PointerType>(qual_type)->getPointeeType().getAsOpaquePtr();
+            return true;
+        case Type::MemberPointer:
+            if (target_type)
+                *target_type = cast<MemberPointerType>(qual_type)->getPointeeType().getAsOpaquePtr();
+            return true;
+        case Type::Typedef:
+            return ClangASTContext::IsPointerOrReferenceType (cast<TypedefType>(qual_type)->LookThroughTypedefs().getAsOpaquePtr(), target_type);
+        default:
+            break;
+        }
+    }
+    return false;
+}
+
+bool
+ClangASTContext::IsFloatingPointType (void *clang_type, uint32_t &count, bool &is_complex)
+{
+    if (clang_type)
+    {
+        QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+
+        if (const BuiltinType *BT = dyn_cast<BuiltinType>(qual_type->getCanonicalTypeInternal()))
+        {
+            clang::BuiltinType::Kind kind = BT->getKind();
+            if (kind >= BuiltinType::Float && kind <= BuiltinType::LongDouble)
+            {
+                count = 1;
+                is_complex = false;
+                return true;
+            }
+        }
+        else if (const ComplexType *CT = dyn_cast<ComplexType>(qual_type->getCanonicalTypeInternal()))
+        {
+            if (IsFloatingPointType(CT->getElementType().getAsOpaquePtr(), count, is_complex))
+            {
+                count = 2;
+                is_complex = true;
+                return true;
+            }
+        }
+        else if (const VectorType *VT = dyn_cast<VectorType>(qual_type->getCanonicalTypeInternal()))
+        {
+            if (IsFloatingPointType(VT->getElementType().getAsOpaquePtr(), count, is_complex))
+            {
+                count = VT->getNumElements();
+                is_complex = false;
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+
+bool
+ClangASTContext::IsCStringType (void *clang_type, uint32_t &length)
+{
+    if (clang_type)
+    {
+        QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+        switch (qual_type->getTypeClass())
+        {
+        case Type::ConstantArray:
+            {
+                ConstantArrayType *array = cast<ConstantArrayType>(qual_type.getTypePtr());
+                QualType element_qual_type = array->getElementType();
+                Type *canonical_type = element_qual_type->getCanonicalTypeInternal().getTypePtr();
+                if (canonical_type && canonical_type->isCharType())
+                {
+                    // We know the size of the array and it could be a C string
+                    // since it is an array of characters
+                    length = array->getSize().getLimitedValue();
+                    return true;
+                }
+            }
+            break;
+
+        case Type::Pointer:
+            {
+                PointerType *pointer_type = cast<PointerType>(qual_type.getTypePtr());
+                Type *pointee_type_ptr = pointer_type->getPointeeType().getTypePtr();
+                if (pointee_type_ptr)
+                {
+                    Type *canonical_type_ptr = pointee_type_ptr->getCanonicalTypeInternal().getTypePtr();
+                    length = 0; // No length info, read until a NULL terminator is received
+                    if (canonical_type_ptr)
+                        return canonical_type_ptr->isCharType();
+                    else
+                        return pointee_type_ptr->isCharType();
+                }
+            }
+            break;
+
+        case Type::Typedef:
+            return ClangASTContext::IsCStringType (cast<TypedefType>(qual_type)->LookThroughTypedefs().getAsOpaquePtr(), length);
+
+        case Type::LValueReference:
+        case Type::RValueReference:
+            {
+                ReferenceType *reference_type = cast<ReferenceType>(qual_type.getTypePtr());
+                Type *pointee_type_ptr = reference_type->getPointeeType().getTypePtr();
+                if (pointee_type_ptr)
+                {
+                    Type *canonical_type_ptr = pointee_type_ptr->getCanonicalTypeInternal().getTypePtr();
+                    length = 0; // No length info, read until a NULL terminator is received
+                    if (canonical_type_ptr)
+                        return canonical_type_ptr->isCharType();
+                    else
+                        return pointee_type_ptr->isCharType();
+                }
+            }
+            break;
+        }
+    }
+    return false;
+}
+
+bool
+ClangASTContext::IsArrayType (void * clang_type, void **member_type, uint64_t *size)
+{
+    if (!clang_type)
+        return false;
+    
+    QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+    
+    switch (qual_type->getTypeClass())
+    {
+    case Type::ConstantArray:
+        if (member_type)
+            *member_type = cast<ConstantArrayType>(qual_type)->getElementType().getAsOpaquePtr();
+        if (size)
+            *size = cast<ConstantArrayType>(qual_type)->getSize().getLimitedValue(ULONG_LONG_MAX);
+        return true;
+    case Type::IncompleteArray:
+        if (member_type)
+            *member_type = cast<IncompleteArrayType>(qual_type)->getElementType().getAsOpaquePtr();
+        if (size)
+            *size = 0;
+        return true;
+    case Type::VariableArray:
+        if (member_type)
+            *member_type = cast<VariableArrayType>(qual_type)->getElementType().getAsOpaquePtr();
+        if (size)
+            *size = 0;
+    case Type::DependentSizedArray:
+        if (member_type)
+            *member_type = cast<DependentSizedArrayType>(qual_type)->getElementType().getAsOpaquePtr();
+        if (size)
+            *size = 0;
+        return true;
+    }
+    return false;
+}
+
+
+#pragma mark Typedefs
+
+void *
+ClangASTContext::CreateTypedefType (const char *name, void *clang_type, DeclContext *decl_ctx)
+{
+    if (clang_type)
+    {
+        QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+        ASTContext *ast_context = getASTContext();
+        IdentifierTable *identifier_table = getIdentifierTable();
+        assert (ast_context != NULL);
+        assert (identifier_table != NULL);
+        if (decl_ctx == NULL)
+            decl_ctx = ast_context->getTranslationUnitDecl();
+        TypedefDecl *decl = TypedefDecl::Create(*ast_context,
+                                                decl_ctx,
+                                                SourceLocation(),
+                                                name ? &identifier_table->get(name) : NULL, // Identifier
+                                                ast_context->CreateTypeSourceInfo(qual_type));
+
+        // Get a uniqued QualType for the typedef decl type
+        return ast_context->getTypedefType (decl).getAsOpaquePtr();
+    }
+    return NULL;
+}
+
+
+std::string
+ClangASTContext::GetTypeName (void *opaque_qual_type)
+{
+    std::string return_name;
+    
+    clang::QualType qual_type(clang::QualType::getFromOpaquePtr(opaque_qual_type));
+
+    const clang::TypedefType *typedef_type = qual_type->getAs<clang::TypedefType>();
+    if (typedef_type)
+    {
+        const clang::TypedefDecl *typedef_decl = typedef_type->getDecl();
+        return_name = typedef_decl->getQualifiedNameAsString();
+    }
+    else
+    {
+        return_name = qual_type.getAsString();
+    }
+
+    return return_name;
+}
+
+// Disable this for now since I can't seem to get a nicely formatted float
+// out of the APFloat class without just getting the float, double or quad
+// and then using a formatted print on it which defeats the purpose. We ideally
+// would like to get perfect string values for any kind of float semantics
+// so we can support remote targets. The code below also requires a patch to
+// llvm::APInt.
+//bool
+//ClangASTContext::ConvertFloatValueToString (ASTContext *ast_context, void *clang_type, const uint8_t* bytes, size_t byte_size, int apint_byte_order, std::string &float_str)
+//{
+//  uint32_t count = 0;
+//  bool is_complex = false;
+//  if (ClangASTContext::IsFloatingPointType (clang_type, count, is_complex))
+//  {
+//      unsigned num_bytes_per_float = byte_size / count;
+//      unsigned num_bits_per_float = num_bytes_per_float * 8;
+//
+//      float_str.clear();
+//      uint32_t i;
+//      for (i=0; i<count; i++)
+//      {
+//          APInt ap_int(num_bits_per_float, bytes + i * num_bytes_per_float, (APInt::ByteOrder)apint_byte_order);
+//          bool is_ieee = false;
+//          APFloat ap_float(ap_int, is_ieee);
+//          char s[1024];
+//          unsigned int hex_digits = 0;
+//          bool upper_case = false;
+//
+//          if (ap_float.convertToHexString(s, hex_digits, upper_case, APFloat::rmNearestTiesToEven) > 0)
+//          {
+//              if (i > 0)
+//                  float_str.append(", ");
+//              float_str.append(s);
+//              if (i == 1 && is_complex)
+//                  float_str.append(1, 'i');
+//          }
+//      }
+//      return !float_str.empty();
+//  }
+//  return false;
+//}
+
+size_t
+ClangASTContext::ConvertStringToFloatValue (ASTContext *ast_context, void *clang_type, const char *s, uint8_t *dst, size_t dst_size)
+{
+    if (clang_type)
+    {
+        QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+        uint32_t count = 0;
+        bool is_complex = false;
+        if (ClangASTContext::IsFloatingPointType (clang_type, count, is_complex))
+        {
+            // TODO: handle complex and vector types
+            if (count != 1)
+                return false;
+
+            StringRef s_sref(s);
+            APFloat ap_float(ast_context->getFloatTypeSemantics(qual_type), s_sref);
+
+            const uint64_t bit_size = ast_context->getTypeSize (qual_type);
+            const uint64_t byte_size = bit_size / 8;
+            if (dst_size >= byte_size)
+            {
+                if (bit_size == sizeof(float)*8)
+                {
+                    float float32 = ap_float.convertToFloat();
+                    ::memcpy (dst, &float32, byte_size);
+                    return byte_size;
+                }
+                else if (bit_size >= 64)
+                {
+                    llvm::APInt ap_int(ap_float.bitcastToAPInt());
+                    ::memcpy (dst, ap_int.getRawData(), byte_size);
+                    return byte_size;
+                }
+            }
+        }
+    }
+    return 0;
+}
diff --git a/source/Symbol/CompileUnit.cpp b/source/Symbol/CompileUnit.cpp
new file mode 100644
index 0000000..60a893b
--- /dev/null
+++ b/source/Symbol/CompileUnit.cpp
@@ -0,0 +1,366 @@
+//===-- CompileUnit.cpp -----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/LineTable.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/VariableList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+CompileUnit::CompileUnit (Module *module, void *user_data, const char *pathname, const lldb::user_id_t cu_sym_id, Language::Type language) :
+    ModuleChild(module),
+    FileSpec (pathname),
+    UserID(cu_sym_id),
+    Language (language),
+    m_user_data (user_data),
+    m_flags (0),
+    m_functions (),
+    m_support_files (),
+    m_line_table_ap (),
+    m_variables()
+{
+    assert(module != NULL);
+}
+
+CompileUnit::CompileUnit (Module *module, void *user_data, const FileSpec &fspec, const lldb::user_id_t cu_sym_id, Language::Type language) :
+    ModuleChild(module),
+    FileSpec (fspec),
+    UserID(cu_sym_id),
+    Language (language),
+    m_user_data (user_data),
+    m_flags (0),
+    m_functions (),
+    m_support_files (),
+    m_line_table_ap (),
+    m_variables()
+{
+    assert(module != NULL);
+}
+
+CompileUnit::~CompileUnit ()
+{
+}
+
+void
+CompileUnit::CalculateSymbolContext(SymbolContext* sc)
+{
+    sc->comp_unit = this;
+    GetModule()->CalculateSymbolContext(sc);
+}
+
+void
+CompileUnit::DumpSymbolContext(Stream *s)
+{
+    GetModule()->DumpSymbolContext(s);
+    s->Printf(", CompileUnit{0x%8.8x}", GetID());
+}
+
+
+
+//----------------------------------------------------------------------
+// Dump the current contents of this object. No functions that cause on
+// demand parsing of functions, globals, statics are called, so this
+// is a good function to call to get an idea of the current contents of
+// the CompileUnit object.
+//----------------------------------------------------------------------
+void
+CompileUnit::Dump(Stream *s, bool show_context) const
+{
+    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+    s->Indent();
+    *s << "CompileUnit" << (const UserID&)*this
+        << ", language = " << (const Language&)*this
+        << ", file='" << (const FileSpec&)*this << "'\n";
+
+//  m_types.Dump(s);
+
+    if (m_variables.get())
+    {
+        s->IndentMore();
+        m_variables->Dump(s, show_context);
+        s->IndentLess();
+    }
+
+    if (!m_functions.empty())
+    {
+        s->IndentMore();
+        std::vector<FunctionSP>::const_iterator pos;
+        std::vector<FunctionSP>::const_iterator end = m_functions.end();
+        for (pos = m_functions.begin(); pos != end; ++pos)
+        {
+            (*pos)->Dump(s, show_context);
+        }
+
+        s->IndentLess();
+        s->EOL();
+    }
+}
+
+//----------------------------------------------------------------------
+// Add a function to this compile unit
+//----------------------------------------------------------------------
+void
+CompileUnit::AddFunction(FunctionSP& funcSP)
+{
+    // TODO: order these by address
+    m_functions.push_back(funcSP);
+}
+
+FunctionSP
+CompileUnit::GetFunctionAtIndex (size_t idx)
+{
+    FunctionSP funcSP;
+    if (idx < m_functions.size())
+        funcSP = m_functions[idx];
+    return funcSP;
+}
+
+//----------------------------------------------------------------------
+// Find functions using the a Mangled::Tokens token list. This
+// function currently implements an interative approach designed to find
+// all instances of certain functions. It isn't designed to the the
+// quickest way to lookup functions as it will need to iterate through
+// all functions and see if they match, though it does provide a powerful
+// and context sensitive way to search for all functions with a certain
+// name, all functions in a namespace, or all functions of a template
+// type. See Mangled::Tokens::Parse() comments for more information.
+//
+// The function prototype will need to change to return a list of
+// results. It was originally used to help debug the Mangled class
+// and the Mangled::Tokens::MatchesQuery() function and it currently
+// will print out a list of matching results for the functions that
+// are currently in this compile unit.
+//
+// A FindFunctions method should be called prior to this that takes
+// a regular function name (const char * or ConstString as a parameter)
+// before resorting to this slower but more complete function. The
+// other FindFunctions method should be able to take advantage of any
+// accelerator tables available in the debug information (which is
+// parsed by the SymbolFile parser plug-ins and registered with each
+// Module).
+//----------------------------------------------------------------------
+//void
+//CompileUnit::FindFunctions(const Mangled::Tokens& tokens)
+//{
+//  if (!m_functions.empty())
+//  {
+//      Stream s(stdout);
+//      std::vector<FunctionSP>::const_iterator pos;
+//      std::vector<FunctionSP>::const_iterator end = m_functions.end();
+//      for (pos = m_functions.begin(); pos != end; ++pos)
+//      {
+//          const ConstString& demangled = (*pos)->Mangled().Demangled();
+//          if (demangled)
+//          {
+//              const Mangled::Tokens& func_tokens = (*pos)->Mangled().GetTokens();
+//              if (func_tokens.MatchesQuery (tokens))
+//                  s << "demangled MATCH found: " << demangled << "\n";
+//          }
+//      }
+//  }
+//}
+
+FunctionSP
+CompileUnit::FindFunctionByUID (lldb::user_id_t func_uid)
+{
+    FunctionSP funcSP;
+    if (!m_functions.empty())
+    {
+        std::vector<FunctionSP>::const_iterator pos;
+        std::vector<FunctionSP>::const_iterator end = m_functions.end();
+        for (pos = m_functions.begin(); pos != end; ++pos)
+        {
+            if ((*pos)->GetID() == func_uid)
+            {
+                funcSP = *pos;
+                break;
+            }
+        }
+    }
+    return funcSP;
+}
+
+
+LineTable*
+CompileUnit::GetLineTable()
+{
+    if (m_line_table_ap.get() == NULL)
+    {
+        if (m_flags.IsClear(flagsParsedLineTable))
+        {
+            m_flags.Set(flagsParsedLineTable);
+            SymbolVendor* symbol_vendor = GetModule()->GetSymbolVendor();
+            if (symbol_vendor)
+            {
+                SymbolContext sc;
+                CalculateSymbolContext(&sc);
+                symbol_vendor->ParseCompileUnitLineTable(sc);
+            }
+        }
+    }
+    return m_line_table_ap.get();
+}
+
+void
+CompileUnit::SetLineTable(LineTable* line_table)
+{
+    if (line_table == NULL)
+        m_flags.Clear(flagsParsedLineTable);
+    else
+        m_flags.Set(flagsParsedLineTable);
+    m_line_table_ap.reset(line_table);
+}
+
+VariableListSP
+CompileUnit::GetVariableList(bool can_create)
+{
+    if (m_variables.get() == NULL && can_create)
+    {
+        SymbolContext sc;
+        CalculateSymbolContext(&sc);
+        assert(sc.module_sp);
+        sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc);
+    }
+
+    return m_variables;
+}
+
+uint32_t
+CompileUnit::FindLineEntry (uint32_t start_idx, uint32_t line, const FileSpec* file_spec_ptr, LineEntry *line_entry_ptr)
+{
+    uint32_t file_idx = 0;
+
+    if (file_spec_ptr)
+    {
+        file_idx = GetSupportFiles().FindFileIndex (1, *file_spec_ptr);
+        if (file_idx == UINT32_MAX)
+            return UINT32_MAX;
+    }
+    else
+    {
+        // All the line table entries actually point to the version of the Compile
+        // Unit that is in the support files (the one at 0 was artifically added.)
+        // So prefer the one further on in the support files if it exists...
+        FileSpecList &support_files = GetSupportFiles();
+        file_idx = support_files.FindFileIndex (1, support_files.GetFileSpecAtIndex(0));
+        if (file_idx == UINT32_MAX)
+            file_idx = 0;
+    }
+    LineTable *line_table = GetLineTable();
+    if (line_table)
+        return line_table->FindLineEntryIndexByFileIndex (start_idx, file_idx, line, true, line_entry_ptr);
+    return UINT32_MAX;
+}
+
+
+
+
+uint32_t
+CompileUnit::ResolveSymbolContext
+(
+    const FileSpec& file_spec,
+    uint32_t line,
+    bool check_inlines,
+    bool exact,
+    uint32_t resolve_scope,
+    SymbolContextList &sc_list
+)
+{
+    const uint32_t prev_size = sc_list.GetSize();
+    bool file_spec_matches_cu_file_spec = FileSpec::Compare(file_spec, this, !file_spec.GetDirectory().IsEmpty()) == 0;
+    if (check_inlines || file_spec_matches_cu_file_spec)
+    {
+        SymbolContext sc(GetModule());
+        sc.comp_unit = this;
+
+        uint32_t file_idx = UINT32_MAX;
+
+        // If we are looking for inline functions only and we don't
+        // find it in the support files, we are done.
+
+        if (check_inlines)
+        {
+            file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec);
+            if (file_idx == UINT32_MAX)
+                return 0;
+        }
+
+        if (line != 0)
+        {
+            LineTable *line_table = sc.comp_unit->GetLineTable();
+
+            if (line_table != NULL)
+            {
+                // We will have already looked up the file index if
+                // we are searching for inline entries.
+                if (!check_inlines)
+                    file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec);
+
+                if (file_idx != UINT32_MAX)
+                {
+                    uint32_t found_line;
+
+                    uint32_t line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_idx, line, exact, &sc.line_entry);
+                    found_line = sc.line_entry.line;
+
+                    while (line_idx != UINT_MAX)
+                    {
+                        sc_list.Append(sc);
+                        line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_idx, found_line, true, &sc.line_entry);
+                    }
+                }
+            }
+        }
+        else if (file_spec_matches_cu_file_spec && !check_inlines)
+        {
+            // only append the context if we aren't looking for inline call sites
+            // by file and line and if the file spec matches that of the compile unit
+            sc_list.Append(sc);
+        }
+
+    }
+    return sc_list.GetSize() - prev_size;
+}
+
+void
+CompileUnit::SetVariableList(VariableListSP &variables)
+{
+    m_variables = variables;
+}
+
+FileSpecList&
+CompileUnit::GetSupportFiles ()
+{
+    if (m_support_files.GetSize() == 0)
+    {
+        if (m_flags.IsClear(flagsParsedSupportFiles))
+        {
+            m_flags.Set(flagsParsedSupportFiles);
+            SymbolVendor* symbol_vendor = GetModule()->GetSymbolVendor();
+            if (symbol_vendor)
+            {
+                SymbolContext sc;
+                CalculateSymbolContext(&sc);
+                symbol_vendor->ParseCompileUnitSupportFiles(sc, m_support_files);
+            }
+        }
+    }
+    return m_support_files;
+}
+
+void *
+CompileUnit::GetUserData () const
+{
+    return m_user_data;
+}
+
+
diff --git a/source/Symbol/DWARFCallFrameInfo.cpp b/source/Symbol/DWARFCallFrameInfo.cpp
new file mode 100644
index 0000000..febca92
--- /dev/null
+++ b/source/Symbol/DWARFCallFrameInfo.cpp
@@ -0,0 +1,1344 @@
+//===-- DWARFCallFrameInfo.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
+// C++ Includes
+#include <list>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Symbol/DWARFCallFrameInfo.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static void
+DumpRegisterName (Stream *s, Thread *thread, const ArchSpec *arch, uint32_t reg_kind, uint32_t reg_num)
+{
+    const char *reg_name = NULL;
+    RegisterContext *reg_ctx = NULL;
+    if (thread)
+    {
+        reg_ctx = thread->GetRegisterContext();
+        if (reg_ctx)
+            reg_name = reg_ctx->GetRegisterName (reg_ctx->ConvertRegisterKindToRegisterNumber (reg_kind, reg_num));
+    }
+
+    if (reg_name == NULL && arch != NULL)
+    {
+        switch (reg_kind)
+        {
+        case eRegisterKindDWARF: reg_name = arch->GetRegisterName(reg_num, eRegisterKindDWARF); break;
+        case eRegisterKindGCC: reg_name = arch->GetRegisterName(reg_num, eRegisterKindGCC); break;
+        default:
+            break;
+        }
+    }
+
+    if (reg_name)
+        s->PutCString(reg_name);
+    else
+    {
+        const char *reg_kind_name = NULL;
+        switch (reg_kind)
+        {
+        case eRegisterKindDWARF: reg_kind_name = "dwarf-reg"; break;
+        case eRegisterKindGCC: reg_kind_name = "compiler-reg"; break;
+        case eRegisterKindGeneric: reg_kind_name = "generic-reg"; break;
+        default:
+            break;
+        }
+        if (reg_kind_name)
+            s->Printf("%s(%u)", reg_kind_name, reg_num);
+        else
+            s->Printf("reg(%d.%u)", reg_kind, reg_num);
+    }
+}
+
+
+#pragma mark DWARFCallFrameInfo::RegisterLocation
+
+DWARFCallFrameInfo::RegisterLocation::RegisterLocation() :
+    m_type(isSame)
+{
+}
+
+
+bool
+DWARFCallFrameInfo::RegisterLocation::operator == (const DWARFCallFrameInfo::RegisterLocation& rhs) const
+{
+    if (m_type != rhs.m_type)
+        return false;
+    switch (m_type)
+    {
+        case unspecified:
+        case isUndefined:
+        case isSame:
+            return true;
+
+        case atCFAPlusOffset:
+            return m_location.offset == rhs.m_location.offset;
+
+        case isCFAPlusOffset:
+            return m_location.offset == rhs.m_location.offset;
+
+        case inOtherRegister:
+            return m_location.reg_num == rhs.m_location.reg_num;
+
+        default:
+            break;
+    }
+    return false;
+}
+
+void
+DWARFCallFrameInfo::RegisterLocation::SetUnspecified()
+{
+    m_type = unspecified;
+}
+
+void
+DWARFCallFrameInfo::RegisterLocation::SetUndefined()
+{
+    m_type = isUndefined;
+}
+
+void
+DWARFCallFrameInfo::RegisterLocation::SetSame()
+{
+    m_type = isSame;
+}
+
+void
+DWARFCallFrameInfo::RegisterLocation::SetAtCFAPlusOffset(int64_t offset)
+{
+    m_type = atCFAPlusOffset;
+    m_location.offset = offset;
+}
+
+void
+DWARFCallFrameInfo::RegisterLocation::SetIsCFAPlusOffset(int64_t offset)
+{
+    m_type = isCFAPlusOffset;
+    m_location.offset = offset;
+}
+
+void
+DWARFCallFrameInfo::RegisterLocation::SetInRegister (uint32_t reg_num)
+{
+    m_type = inOtherRegister;
+    m_location.reg_num = reg_num;
+}
+
+void
+DWARFCallFrameInfo::RegisterLocation::SetAtDWARFExpression(const uint8_t *opcodes, uint32_t len)
+{
+    m_type = atDWARFExpression;
+    m_location.expr.opcodes = opcodes;
+    m_location.expr.length = len;
+}
+
+void
+DWARFCallFrameInfo::RegisterLocation::SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len)
+{
+    m_type = isDWARFExpression;
+    m_location.expr.opcodes = opcodes;
+    m_location.expr.length = len;
+}
+
+void
+DWARFCallFrameInfo::RegisterLocation::Dump(Stream *s, const DWARFCallFrameInfo &cfi, Thread *thread, const Row *row, uint32_t reg_num) const
+{
+    const ArchSpec *arch = cfi.GetArchitecture();
+    const uint32_t reg_kind = cfi.GetRegisterKind();
+
+    DumpRegisterName (s, thread, arch, reg_kind, reg_num);
+    s->PutChar('=');
+
+    switch (m_type)
+    {
+    case unspecified:
+        s->PutChar('?');
+        break;
+
+    case isUndefined:
+        s->PutCString("undefined");
+        break;
+
+    case isSame:
+        s->PutCString("same");
+        break;
+
+    case atCFAPlusOffset:
+        s->PutChar('[');
+        // Fall through to isCFAPlusOffset...
+    case isCFAPlusOffset:
+        {
+            DumpRegisterName (s, thread, arch, reg_kind, row->GetCFARegister());
+            int32_t offset = row->GetCFAOffset() + m_location.offset;
+            if (offset != 0)
+                s->Printf("%-+d", offset);
+            if (m_type == atCFAPlusOffset)
+                s->PutChar(']');
+        }
+        break;
+
+    case inOtherRegister:
+        DumpRegisterName (s, thread, arch, reg_kind, m_location.reg_num);
+        break;
+
+    case atDWARFExpression:
+        s->PutCString("[EXPR] ");
+        break;
+
+    case isDWARFExpression:
+        s->PutCString("EXPR ");
+        break;
+    }
+}
+
+
+#pragma mark DWARFCallFrameInfo::Row
+
+DWARFCallFrameInfo::Row::Row() :
+    m_offset(0),
+    m_cfa_reg_num(0),
+    m_cfa_offset(0),
+    m_register_locations()
+{
+}
+
+DWARFCallFrameInfo::Row::~Row()
+{
+}
+
+void
+DWARFCallFrameInfo::Row::Clear()
+{
+    m_register_locations.clear();
+}
+bool
+DWARFCallFrameInfo::Row::GetRegisterInfo (uint32_t reg_num, DWARFCallFrameInfo::RegisterLocation& register_location) const
+{
+    collection::const_iterator pos = m_register_locations.find(reg_num);
+    if (pos != m_register_locations.end())
+    {
+        register_location = pos->second;
+        return true;
+    }
+    return false;
+}
+
+void
+DWARFCallFrameInfo::Row::SetRegisterInfo (uint32_t reg_num, const RegisterLocation& register_location)
+{
+    m_register_locations[reg_num] = register_location;
+}
+
+
+void
+DWARFCallFrameInfo::Row::Dump(Stream* s, const DWARFCallFrameInfo &cfi, Thread *thread, lldb::addr_t base_addr) const
+{
+    const ArchSpec *arch = cfi.GetArchitecture();
+    const uint32_t reg_kind = cfi.GetRegisterKind();
+    collection::const_iterator pos, end = m_register_locations.end();
+    s->Indent();
+    s->Printf("0x%16.16llx: CFA=", m_offset + base_addr);
+    DumpRegisterName(s, thread, arch, reg_kind, m_cfa_reg_num);
+    if (m_cfa_offset != 0)
+        s->Printf("%-+lld", m_cfa_offset);
+
+    for (pos = m_register_locations.begin(); pos != end; ++pos)
+    {
+        s->PutChar(' ');
+        pos->second.Dump(s, cfi, thread, this, pos->first);
+    }
+    s->EOL();
+}
+
+
+#pragma mark DWARFCallFrameInfo::FDE
+
+
+DWARFCallFrameInfo::FDE::FDE (dw_offset_t offset, const AddressRange &range) :
+    m_fde_offset (offset),
+    m_range (range),
+    m_row_list ()
+{
+}
+
+DWARFCallFrameInfo::FDE::~FDE()
+{
+}
+
+void
+DWARFCallFrameInfo::FDE::AppendRow (const Row &row)
+{
+    if (m_row_list.empty() || m_row_list.back().GetOffset() != row.GetOffset())
+        m_row_list.push_back(row);
+    else
+        m_row_list.back() = row;
+}
+
+void
+DWARFCallFrameInfo::FDE::Dump (Stream *s, const DWARFCallFrameInfo &cfi, Thread* thread) const
+{
+    s->Indent();
+    s->Printf("FDE{0x%8.8x} ", m_fde_offset);
+    m_range.Dump(s, NULL, Address::DumpStyleFileAddress);
+    lldb::addr_t fde_base_addr = m_range.GetBaseAddress().GetFileAddress();
+    s->EOL();
+    s->IndentMore();
+    collection::const_iterator pos, end = m_row_list.end();
+    for (pos = m_row_list.begin(); pos != end; ++pos)
+    {
+        pos->Dump(s, cfi, thread, fde_base_addr);
+    }
+    s->IndentLess();
+}
+
+const AddressRange &
+DWARFCallFrameInfo::FDE::GetAddressRange() const
+{
+    return m_range;
+}
+
+bool
+DWARFCallFrameInfo::FDE::IsValidRowIndex (uint32_t idx) const
+{
+    return idx < m_row_list.size();
+}
+
+const DWARFCallFrameInfo::Row&
+DWARFCallFrameInfo::FDE::GetRowAtIndex (uint32_t idx)
+{
+    // You must call IsValidRowIndex(idx) first before calling this!!!
+    return m_row_list[idx];
+}
+#pragma mark DWARFCallFrameInfo::FDEInfo
+
+DWARFCallFrameInfo::FDEInfo::FDEInfo () :
+    fde_offset (0),
+    fde_sp()
+{
+}
+
+DWARFCallFrameInfo::FDEInfo::FDEInfo (off_t offset) :
+    fde_offset(offset),
+    fde_sp()
+{
+}
+
+#pragma mark DWARFCallFrameInfo::CIE
+
+DWARFCallFrameInfo::CIE::CIE(dw_offset_t offset) :
+    cie_offset (offset),
+    version (0),
+    augmentation(),
+    code_align (0),
+    data_align (0),
+    return_addr_reg_num (0),
+    inst_offset (0),
+    inst_length (0),
+    ptr_encoding (DW_GNU_EH_PE_absptr)
+{
+}
+
+
+DWARFCallFrameInfo::CIE::~CIE()
+{
+}
+
+void
+DWARFCallFrameInfo::CIE::Dump(Stream *s, Thread* thread, const ArchSpec *arch, uint32_t reg_kind) const
+{
+    s->Indent();
+    s->Printf("CIE{0x%8.8x} version=%u, code_align=%u, data_align=%d, return_addr_reg=", cie_offset, version, code_align, data_align);
+    DumpRegisterName(s, thread, arch, reg_kind, return_addr_reg_num);
+    s->Printf(", instr_offset=0x%8.8x, instr_length=%u, ptr_encoding=0x%02x\n",
+            inst_offset,
+            inst_length,
+            ptr_encoding);
+}
+
+#pragma mark DWARFCallFrameInfo::CIE
+
+DWARFCallFrameInfo::DWARFCallFrameInfo(ObjectFile *objfile, Section *section, uint32_t reg_kind) :
+    m_objfile (objfile),
+    m_section (section),
+    m_reg_kind (reg_kind),  // The flavor of registers that the CFI data uses (One of the defines that starts with "LLDB_REGKIND_")
+    m_cfi_data (),
+    m_cie_map (),
+    m_fde_map ()
+{
+    if (objfile && section)
+    {
+        section->ReadSectionDataFromObjectFile (objfile, m_cfi_data);
+    }
+}
+
+DWARFCallFrameInfo::~DWARFCallFrameInfo()
+{
+}
+
+bool
+DWARFCallFrameInfo::IsEHFrame() const
+{
+    return (m_reg_kind == eRegisterKindGCC);
+}
+
+const ArchSpec *
+DWARFCallFrameInfo::GetArchitecture() const
+{
+    if (m_objfile && m_objfile->GetModule())
+        return &m_objfile->GetModule()->GetArchitecture();
+    return NULL;
+}
+
+uint32_t
+DWARFCallFrameInfo::GetRegisterKind () const
+{
+    return m_reg_kind;
+}
+
+void
+DWARFCallFrameInfo::SetRegisterKind (uint32_t reg_kind)
+{
+    m_reg_kind = reg_kind;
+}
+
+
+
+
+const DWARFCallFrameInfo::CIE*
+DWARFCallFrameInfo::GetCIE(dw_offset_t cie_offset)
+{
+    Index ();
+
+    cie_map_t::iterator pos = m_cie_map.find(cie_offset);
+
+    if (pos != m_cie_map.end())
+    {
+        // Parse and cache the CIE
+        if (pos->second.get() == NULL)
+            pos->second = ParseCIE (cie_offset);
+
+        return pos->second.get();
+    }
+    return NULL;
+}
+
+DWARFCallFrameInfo::CIE::shared_ptr
+DWARFCallFrameInfo::ParseCIE (const dw_offset_t cie_offset)
+{
+    CIE::shared_ptr cie_sp(new CIE(cie_offset));
+    const bool for_eh_frame = IsEHFrame();
+    dw_offset_t offset = cie_offset;
+    const uint32_t length = m_cfi_data.GetU32(&offset);
+    const dw_offset_t cie_id = m_cfi_data.GetU32(&offset);
+    const dw_offset_t end_offset = cie_offset + length + 4;
+    if (length > 0 && (!for_eh_frame && cie_id == 0xfffffffful) || (for_eh_frame && cie_id == 0ul))
+    {
+        size_t i;
+        //    cie.offset = cie_offset;
+        //    cie.length = length;
+        //    cie.cieID = cieID;
+        cie_sp->ptr_encoding = DW_GNU_EH_PE_absptr;
+        cie_sp->version = m_cfi_data.GetU8(&offset);
+
+        for (i=0; i<CFI_AUG_MAX_SIZE; ++i)
+        {
+            cie_sp->augmentation[i] = m_cfi_data.GetU8(&offset);
+            if (cie_sp->augmentation[i] == '\0')
+            {
+                // Zero out remaining bytes in augmentation string
+                for (size_t j = i+1; j<CFI_AUG_MAX_SIZE; ++j)
+                    cie_sp->augmentation[j] = '\0';
+
+                break;
+            }
+        }
+
+        if (i == CFI_AUG_MAX_SIZE && cie_sp->augmentation[CFI_AUG_MAX_SIZE-1] != '\0')
+        {
+            fprintf(stderr, "CIE parse error: CIE augmentation string was too large for the fixed sized buffer of %d bytes.\n", CFI_AUG_MAX_SIZE);
+            return cie_sp;
+        }
+        cie_sp->code_align = (uint32_t)m_cfi_data.GetULEB128(&offset);
+        cie_sp->data_align = (int32_t)m_cfi_data.GetSLEB128(&offset);
+        cie_sp->return_addr_reg_num = m_cfi_data.GetU8(&offset);
+
+        if (cie_sp->augmentation[0])
+        {
+            // Get the length of the eh_frame augmentation data
+            // which starts with a ULEB128 length in bytes
+            const size_t aug_data_len = (size_t)m_cfi_data.GetULEB128(&offset);
+            const size_t aug_data_end = offset + aug_data_len;
+            const size_t aug_str_len = strlen(cie_sp->augmentation);
+            // A 'z' may be present as the first character of the string.
+            // If present, the Augmentation Data field shall be present.
+            // The contents of the Augmentation Data shall be intepreted
+            // according to other characters in the Augmentation String.
+            if (cie_sp->augmentation[0] == 'z')
+            {
+                // Extract the Augmentation Data
+                size_t aug_str_idx = 0;
+                for (aug_str_idx = 1; aug_str_idx < aug_str_len; aug_str_idx++)
+                {
+                    char aug = cie_sp->augmentation[aug_str_idx];
+                    switch (aug)
+                    {
+                        case 'L':
+                            // Indicates the presence of one argument in the
+                            // Augmentation Data of the CIE, and a corresponding
+                            // argument in the Augmentation Data of the FDE. The
+                            // argument in the Augmentation Data of the CIE is
+                            // 1-byte and represents the pointer encoding used
+                            // for the argument in the Augmentation Data of the
+                            // FDE, which is the address of a language-specific
+                            // data area (LSDA). The size of the LSDA pointer is
+                            // specified by the pointer encoding used.
+                            m_cfi_data.GetU8(&offset);
+                            break;
+
+                        case 'P':
+                            // Indicates the presence of two arguments in the
+                            // Augmentation Data of the cie_sp-> The first argument
+                            // is 1-byte and represents the pointer encoding
+                            // used for the second argument, which is the
+                            // address of a personality routine handler. The
+                            // size of the personality routine pointer is
+                            // specified by the pointer encoding used.
+                        {
+                            uint8_t arg_ptr_encoding = m_cfi_data.GetU8(&offset);
+                            m_cfi_data.GetGNUEHPointer(&offset, arg_ptr_encoding, LLDB_INVALID_ADDRESS, LLDB_INVALID_ADDRESS, LLDB_INVALID_ADDRESS);
+                        }
+                            break;
+
+                        case 'R':
+                            // A 'R' may be present at any position after the
+                            // first character of the string. The Augmentation
+                            // Data shall include a 1 byte argument that
+                            // represents the pointer encoding for the address
+                            // pointers used in the FDE.
+                            cie_sp->ptr_encoding = m_cfi_data.GetU8(&offset);
+                            break;
+                    }
+                }
+            }
+            else if (strcmp(cie_sp->augmentation, "eh") == 0)
+            {
+                // If the Augmentation string has the value "eh", then
+                // the EH Data field shall be present
+            }
+
+            // Set the offset to be the end of the augmentation data just in case
+            // we didn't understand any of the data.
+            offset = (uint32_t)aug_data_end;
+        }
+
+        if (end_offset > offset)
+        {
+            cie_sp->inst_offset = offset;
+            cie_sp->inst_length = end_offset - offset;
+        }
+    }
+
+    return cie_sp;
+}
+
+DWARFCallFrameInfo::FDE::shared_ptr
+DWARFCallFrameInfo::ParseFDE(const dw_offset_t fde_offset)
+{
+    const bool for_eh_frame = IsEHFrame();
+    FDE::shared_ptr fde_sp;
+
+    dw_offset_t offset = fde_offset;
+    const uint32_t length = m_cfi_data.GetU32(&offset);
+    dw_offset_t cie_offset = m_cfi_data.GetU32(&offset);
+    const dw_offset_t end_offset = fde_offset + length + 4;
+
+    // Translate the CIE_id from the eh_frame format, which
+    // is relative to the FDE offset, into a __eh_frame section
+    // offset
+    if (for_eh_frame)
+        cie_offset = offset - (cie_offset + 4);
+
+    const CIE* cie = GetCIE(cie_offset);
+    if (cie)
+    {
+        const lldb::addr_t pc_rel_addr = m_section->GetFileAddress();
+        const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS;
+        const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS;
+        lldb::addr_t range_base = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding, pc_rel_addr, text_addr, data_addr);
+        lldb::addr_t range_len = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding & DW_GNU_EH_PE_MASK_ENCODING, pc_rel_addr, text_addr, data_addr);
+
+        if (cie->augmentation[0] == 'z')
+        {
+            uint32_t aug_data_len = (uint32_t)m_cfi_data.GetULEB128(&offset);
+            offset += aug_data_len;
+        }
+
+        AddressRange fde_range (range_base, range_len, m_objfile->GetSectionList ());
+        fde_sp.reset(new FDE(fde_offset, fde_range));
+        if (offset < end_offset)
+        {
+            dw_offset_t fde_instr_offset = offset;
+            uint32_t fde_instr_length = end_offset - offset;
+            if (cie->inst_length > 0)
+                ParseInstructions(cie, fde_sp.get(), cie->inst_offset, cie->inst_length);
+            ParseInstructions(cie, fde_sp.get(), fde_instr_offset, fde_instr_length);
+        }
+    }
+    return fde_sp;
+}
+
+const DWARFCallFrameInfo::FDE *
+DWARFCallFrameInfo::FindFDE(const Address &addr)
+{
+    Index ();
+
+    VMRange find_range(addr.GetFileAddress(), 0);
+    fde_map_t::iterator pos = m_fde_map.lower_bound (find_range);
+    fde_map_t::iterator end = m_fde_map.end();
+
+    if (pos != end)
+    {
+        if (pos->first.Contains(find_range.GetBaseAddress()))
+        {
+            // Parse and cache the FDE if we already haven't
+            if (pos->second.fde_sp.get() == NULL)
+                pos->second.fde_sp = ParseFDE(pos->second.fde_offset);
+
+            return pos->second.fde_sp.get();
+        }
+    }
+    return NULL;
+}
+
+
+void
+DWARFCallFrameInfo::Index ()
+{
+    if (m_flags.IsClear(eFlagParsedIndex))
+    {
+        m_flags.Set (eFlagParsedIndex);
+        const bool for_eh_frame = IsEHFrame();
+        CIE::shared_ptr empty_cie_sp;
+        dw_offset_t offset = 0;
+        // Parse all of the CIEs first since we will need them to be able to
+        // properly parse the FDE addresses due to them possibly having
+        // GNU pointer encodings in their augmentations...
+        while (m_cfi_data.ValidOffsetForDataOfSize(offset, 8))
+        {
+            const dw_offset_t curr_offset = offset;
+            const uint32_t length = m_cfi_data.GetU32(&offset);
+            const dw_offset_t next_offset = offset + length;
+            const dw_offset_t cie_id = m_cfi_data.GetU32(&offset);
+
+            bool is_cie = for_eh_frame ?  cie_id == 0 : cie_id == UINT32_MAX;
+            if (is_cie)
+                m_cie_map[curr_offset]= ParseCIE(curr_offset);
+
+            offset = next_offset;
+        }
+
+        // Now go back through and index all FDEs
+        offset = 0;
+        const lldb::addr_t pc_rel_addr = m_section->GetFileAddress();
+        const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS;
+        const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS;
+        while (m_cfi_data.ValidOffsetForDataOfSize(offset, 8))
+        {
+            const dw_offset_t curr_offset = offset;
+            const uint32_t length = m_cfi_data.GetU32(&offset);
+            const dw_offset_t next_offset = offset + length;
+            const dw_offset_t cie_id = m_cfi_data.GetU32(&offset);
+
+            bool is_fde = for_eh_frame ?  cie_id != 0 : cie_id != UINT32_MAX;
+            if (is_fde)
+            {
+                dw_offset_t cie_offset;
+                if (for_eh_frame)
+                    cie_offset = offset - (cie_id + 4);
+                else
+                    cie_offset = cie_id;
+
+                const CIE* cie = GetCIE(cie_offset);
+                assert(cie);
+                lldb::addr_t addr = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding, pc_rel_addr, text_addr, data_addr);
+                lldb::addr_t length = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding & DW_GNU_EH_PE_MASK_ENCODING, pc_rel_addr, text_addr, data_addr);
+                m_fde_map[VMRange(addr, addr + length)] = FDEInfo(curr_offset);
+            }
+
+            offset = next_offset;
+        }
+    }
+}
+
+//----------------------------------------------------------------------
+// Parse instructions for a FDE. The initial instruction for the CIE
+// are parsed first, then the instructions for the FDE are parsed
+//----------------------------------------------------------------------
+void
+DWARFCallFrameInfo::ParseInstructions(const CIE *cie, FDE *fde, dw_offset_t instr_offset, uint32_t instr_length)
+{
+    if (cie != NULL && fde == NULL)
+        return;
+
+    uint32_t reg_num = 0;
+    int32_t op_offset = 0;
+    uint32_t tmp_uval32;
+    uint32_t code_align = cie->code_align;
+    int32_t data_align = cie->data_align;
+    typedef std::list<Row> RowStack;
+
+    RowStack row_stack;
+    Row row;
+    if (fde->IsValidRowIndex(0))
+        row = fde->GetRowAtIndex(0);
+
+    dw_offset_t offset = instr_offset;
+    const dw_offset_t end_offset = instr_offset + instr_length;
+    RegisterLocation reg_location;
+    while (m_cfi_data.ValidOffset(offset) && offset < end_offset)
+    {
+        uint8_t inst = m_cfi_data.GetU8(&offset);
+        uint8_t primary_opcode  = inst & 0xC0;
+        uint8_t extended_opcode = inst & 0x3F;
+
+        if (primary_opcode)
+        {
+            switch (primary_opcode)
+            {
+                case DW_CFA_advance_loc :   // (Row Creation Instruction)
+                    {   // 0x40 - high 2 bits are 0x1, lower 6 bits are delta
+                        // takes a single argument that represents a constant delta. The
+                        // required action is to create a new table row with a location
+                        // value that is computed by taking the current entry's location
+                        // value and adding (delta * code_align). All other
+                        // values in the new row are initially identical to the current row.
+                        fde->AppendRow(row);
+                        row.SlideOffset(extended_opcode * code_align);
+                    }
+                    break;
+
+                case DW_CFA_offset      :
+                    {   // 0x80 - high 2 bits are 0x2, lower 6 bits are register
+                        // takes two arguments: an unsigned LEB128 constant representing a
+                        // factored offset and a register number. The required action is to
+                        // change the rule for the register indicated by the register number
+                        // to be an offset(N) rule with a value of
+                        // (N = factored offset * data_align).
+                        reg_num = extended_opcode;
+                        op_offset = (int32_t)m_cfi_data.GetULEB128(&offset) * data_align;
+                        reg_location.SetAtCFAPlusOffset(op_offset);
+                        row.SetRegisterInfo (reg_num, reg_location);
+                    }
+                    break;
+
+                case DW_CFA_restore     :
+                    {   // 0xC0 - high 2 bits are 0x3, lower 6 bits are register
+                        // takes a single argument that represents a register number. The
+                        // required action is to change the rule for the indicated register
+                        // to the rule assigned it by the initial_instructions in the CIE.
+                        reg_num = extended_opcode;
+                        // We only keep enough register locations around to
+                        // unwind what is in our thread, and these are organized
+                        // by the register index in that state, so we need to convert our
+                        // GCC register number from the EH frame info, to a registe index
+
+                        if (fde->IsValidRowIndex(0) && fde->GetRowAtIndex(0).GetRegisterInfo(reg_num, reg_location))
+                            row.SetRegisterInfo (reg_num, reg_location);
+                    }
+                    break;
+            }
+        }
+        else
+        {
+            switch (extended_opcode)
+            {
+                case DW_CFA_nop                 : // 0x0
+                    break;
+
+                case DW_CFA_set_loc             : // 0x1 (Row Creation Instruction)
+                    {
+                        // DW_CFA_set_loc takes a single argument that represents an address.
+                        // The required action is to create a new table row using the
+                        // specified address as the location. All other values in the new row
+                        // are initially identical to the current row. The new location value
+                        // should always be greater than the current one.
+                        fde->AppendRow(row);
+                        row.SetOffset(m_cfi_data.GetPointer(&offset) - fde->GetAddressRange().GetBaseAddress().GetFileAddress());
+                    }
+                    break;
+
+                case DW_CFA_advance_loc1        : // 0x2 (Row Creation Instruction)
+                    {
+                        // takes a single uword argument that represents a constant delta.
+                        // This instruction is identical to DW_CFA_advance_loc except for the
+                        // encoding and size of the delta argument.
+                        fde->AppendRow(row);
+                        row.SlideOffset (m_cfi_data.GetU8(&offset) * code_align);
+                    }
+                    break;
+
+                case DW_CFA_advance_loc2        : // 0x3 (Row Creation Instruction)
+                    {
+                        // takes a single uword argument that represents a constant delta.
+                        // This instruction is identical to DW_CFA_advance_loc except for the
+                        // encoding and size of the delta argument.
+                        fde->AppendRow(row);
+                        row.SlideOffset (m_cfi_data.GetU16(&offset) * code_align);
+                    }
+                    break;
+
+                case DW_CFA_advance_loc4        : // 0x4 (Row Creation Instruction)
+                    {
+                        // takes a single uword argument that represents a constant delta.
+                        // This instruction is identical to DW_CFA_advance_loc except for the
+                        // encoding and size of the delta argument.
+                        fde->AppendRow(row);
+                        row.SlideOffset (m_cfi_data.GetU32(&offset) * code_align);
+                    }
+                    break;
+
+                case DW_CFA_offset_extended     : // 0x5
+                    {
+                        // takes two unsigned LEB128 arguments representing a register number
+                        // and a factored offset. This instruction is identical to DW_CFA_offset
+                        // except for the encoding and size of the register argument.
+                        reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
+                        op_offset = (int32_t)m_cfi_data.GetULEB128(&offset) * data_align;
+                        reg_location.SetAtCFAPlusOffset(op_offset);
+                        row.SetRegisterInfo (reg_num, reg_location);
+                    }
+                    break;
+
+                case DW_CFA_restore_extended    : // 0x6
+                    {
+                        // takes a single unsigned LEB128 argument that represents a register
+                        // number. This instruction is identical to DW_CFA_restore except for
+                        // the encoding and size of the register argument.
+                        reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
+                        if (fde->IsValidRowIndex(0) && fde->GetRowAtIndex(0).GetRegisterInfo(reg_num, reg_location))
+                            row.SetRegisterInfo (reg_num, reg_location);
+                    }
+                    break;
+
+                case DW_CFA_undefined           : // 0x7
+                    {
+                        // takes a single unsigned LEB128 argument that represents a register
+                        // number. The required action is to set the rule for the specified
+                        // register to undefined.
+                        reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
+                        reg_location.SetUndefined();
+                        row.SetRegisterInfo (reg_num, reg_location);
+                    }
+                    break;
+
+                case DW_CFA_same_value          : // 0x8
+                    {
+                        // takes a single unsigned LEB128 argument that represents a register
+                        // number. The required action is to set the rule for the specified
+                        // register to same value.
+                        reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
+                        reg_location.SetSame();
+                        row.SetRegisterInfo (reg_num, reg_location);
+                    }
+                    break;
+
+                case DW_CFA_register            : // 0x9
+                    {
+                        // takes two unsigned LEB128 arguments representing register numbers.
+                        // The required action is to set the rule for the first register to be
+                        // the second register.
+
+                        reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
+                        uint32_t other_reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
+                        reg_location.SetInRegister(other_reg_num);
+                        row.SetRegisterInfo (reg_num, reg_location);
+                    }
+                    break;
+
+                case DW_CFA_remember_state      : // 0xA
+                    // These instructions define a stack of information. Encountering the
+                    // DW_CFA_remember_state instruction means to save the rules for every
+                    // register on the current row on the stack. Encountering the
+                    // DW_CFA_restore_state instruction means to pop the set of rules off
+                    // the stack and place them in the current row. (This operation is
+                    // useful for compilers that move epilogue code into the body of a
+                    // function.)
+                    row_stack.push_back(row);
+                    break;
+
+                case DW_CFA_restore_state       : // 0xB
+                    // These instructions define a stack of information. Encountering the
+                    // DW_CFA_remember_state instruction means to save the rules for every
+                    // register on the current row on the stack. Encountering the
+                    // DW_CFA_restore_state instruction means to pop the set of rules off
+                    // the stack and place them in the current row. (This operation is
+                    // useful for compilers that move epilogue code into the body of a
+                    // function.)
+                    {
+                        row = row_stack.back();
+                        row_stack.pop_back();
+                    }
+                    break;
+
+                case DW_CFA_def_cfa             : // 0xC    (CFA Definition Instruction)
+                    {
+                        // Takes two unsigned LEB128 operands representing a register
+                        // number and a (non-factored) offset. The required action
+                        // is to define the current CFA rule to use the provided
+                        // register and offset.
+                        reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
+                        op_offset = (int32_t)m_cfi_data.GetULEB128(&offset);
+                        row.SetCFARegister (reg_num);
+                        row.SetCFAOffset (op_offset);
+                    }
+                    break;
+
+                case DW_CFA_def_cfa_register    : // 0xD    (CFA Definition Instruction)
+                    {
+                        // takes a single unsigned LEB128 argument representing a register
+                        // number. The required action is to define the current CFA rule to
+                        // use the provided register (but to keep the old offset).
+                        reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
+                        row.SetCFARegister (reg_num);
+                    }
+                    break;
+
+                case DW_CFA_def_cfa_offset      : // 0xE    (CFA Definition Instruction)
+                    {
+                        // Takes a single unsigned LEB128 operand representing a
+                        // (non-factored) offset. The required action is to define
+                        // the current CFA rule to use the provided offset (but
+                        // to keep the old register).
+                        op_offset = (int32_t)m_cfi_data.GetULEB128(&offset);
+                        row.SetCFAOffset (op_offset);
+                    }
+                    break;
+
+                case DW_CFA_def_cfa_expression  : // 0xF    (CFA Definition Instruction)
+                    {
+                        size_t block_len = (size_t)m_cfi_data.GetULEB128(&offset);
+                        offset += (uint32_t)block_len;
+                    }
+                    break;
+
+                case DW_CFA_expression          : // 0x10
+                    {
+                        // Takes two operands: an unsigned LEB128 value representing
+                        // a register number, and a DW_FORM_block value representing a DWARF
+                        // expression. The required action is to change the rule for the
+                        // register indicated by the register number to be an expression(E)
+                        // rule where E is the DWARF expression. That is, the DWARF
+                        // expression computes the address. The value of the CFA is
+                        // pushed on the DWARF evaluation stack prior to execution of
+                        // the DWARF expression.
+                        reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
+                        uint32_t block_len = (uint32_t)m_cfi_data.GetULEB128(&offset);
+                        const uint8_t *block_data = (uint8_t *)m_cfi_data.GetData(&offset, block_len);
+
+                        reg_location.SetAtDWARFExpression(block_data, block_len);
+                        row.SetRegisterInfo (reg_num, reg_location);
+                    }
+                    break;
+
+                case DW_CFA_offset_extended_sf  : // 0x11
+                    {
+                        // takes two operands: an unsigned LEB128 value representing a
+                        // register number and a signed LEB128 factored offset. This
+                        // instruction is identical to DW_CFA_offset_extended except
+                        //that the second operand is signed and factored.
+                        reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
+                        op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align;
+                        reg_location.SetAtCFAPlusOffset(op_offset);
+                        row.SetRegisterInfo (reg_num, reg_location);
+                    }
+                    break;
+
+                case DW_CFA_def_cfa_sf          : // 0x12   (CFA Definition Instruction)
+                    {
+                        // Takes two operands: an unsigned LEB128 value representing
+                        // a register number and a signed LEB128 factored offset.
+                        // This instruction is identical to DW_CFA_def_cfa except
+                        // that the second operand is signed and factored.
+                        reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
+                        op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align;
+                        row.SetCFARegister (reg_num);
+                        row.SetCFAOffset (op_offset);
+                    }
+                    break;
+
+                case DW_CFA_def_cfa_offset_sf   : // 0x13   (CFA Definition Instruction)
+                    {
+                        // takes a signed LEB128 operand representing a factored
+                        // offset. This instruction is identical to  DW_CFA_def_cfa_offset
+                        // except that the operand is signed and factored.
+                        op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align;
+                        row.SetCFAOffset (op_offset);
+                    }
+                    break;
+
+                case DW_CFA_val_expression      :   // 0x16
+                    {
+                        // takes two operands: an unsigned LEB128 value representing a register
+                        // number, and a DW_FORM_block value representing a DWARF expression.
+                        // The required action is to change the rule for the register indicated
+                        // by the register number to be a val_expression(E) rule where E is the
+                        // DWARF expression. That is, the DWARF expression computes the value of
+                        // the given register. The value of the CFA is pushed on the DWARF
+                        // evaluation stack prior to execution of the DWARF expression.
+                        reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
+                        uint32_t block_len = (uint32_t)m_cfi_data.GetULEB128(&offset);
+                        const uint8_t* block_data = (uint8_t*)m_cfi_data.GetData(&offset, block_len);
+//#if defined(__i386__) || defined(__x86_64__)
+//                      // The EH frame info for EIP and RIP contains code that looks for traps to
+//                      // be a specific type and increments the PC.
+//                      // For i386:
+//                      // DW_CFA_val_expression where:
+//                      // eip = DW_OP_breg6(+28), DW_OP_deref, DW_OP_dup, DW_OP_plus_uconst(0x34),
+//                      //       DW_OP_deref, DW_OP_swap, DW_OP_plus_uconst(0), DW_OP_deref,
+//                      //       DW_OP_dup, DW_OP_lit3, DW_OP_ne, DW_OP_swap, DW_OP_lit4, DW_OP_ne,
+//                      //       DW_OP_and, DW_OP_plus
+//                      // This basically does a:
+//                      // eip = ucontenxt.mcontext32->gpr.eip;
+//                      // if (ucontenxt.mcontext32->exc.trapno != 3 && ucontenxt.mcontext32->exc.trapno != 4)
+//                      //   eip++;
+//                      //
+//                      // For x86_64:
+//                      // DW_CFA_val_expression where:
+//                      // rip =  DW_OP_breg3(+48), DW_OP_deref, DW_OP_dup, DW_OP_plus_uconst(0x90), DW_OP_deref,
+//                      //          DW_OP_swap, DW_OP_plus_uconst(0), DW_OP_deref_size(4), DW_OP_dup, DW_OP_lit3,
+//                      //          DW_OP_ne, DW_OP_swap, DW_OP_lit4, DW_OP_ne, DW_OP_and, DW_OP_plus
+//                      // This basically does a:
+//                      // rip = ucontenxt.mcontext64->gpr.rip;
+//                      // if (ucontenxt.mcontext64->exc.trapno != 3 && ucontenxt.mcontext64->exc.trapno != 4)
+//                      //   rip++;
+//                      // The trap comparisons and increments are not needed as it hoses up the unwound PC which
+//                      // is expected to point at least past the instruction that causes the fault/trap. So we
+//                      // take it out by trimming the expression right at the first "DW_OP_swap" opcodes
+//                      if (block_data != NULL && thread->GetPCRegNum(Thread::GCC) == reg_num)
+//                      {
+//                          if (thread->Is64Bit())
+//                          {
+//                              if (block_len > 9 && block_data[8] == DW_OP_swap && block_data[9] == DW_OP_plus_uconst)
+//                                  block_len = 8;
+//                          }
+//                          else
+//                          {
+//                              if (block_len > 8 && block_data[7] == DW_OP_swap && block_data[8] == DW_OP_plus_uconst)
+//                                  block_len = 7;
+//                          }
+//                      }
+//#endif
+                        reg_location.SetIsDWARFExpression(block_data, block_len);
+                        row.SetRegisterInfo (reg_num, reg_location);
+                    }
+                    break;
+
+                case DW_CFA_val_offset          :   // 0x14
+                case DW_CFA_val_offset_sf       :   // 0x15
+                default:
+                    tmp_uval32 = extended_opcode;
+                    break;
+            }
+        }
+    }
+    fde->AppendRow(row);
+}
+
+void
+DWARFCallFrameInfo::ParseAll()
+{
+    Index();
+    fde_map_t::iterator pos, end = m_fde_map.end();
+    for (pos = m_fde_map.begin(); pos != end; ++ pos)
+    {
+        if (pos->second.fde_sp.get() == NULL)
+            pos->second.fde_sp = ParseFDE(pos->second.fde_offset);
+    }
+}
+
+
+//bool
+//DWARFCallFrameInfo::UnwindRegisterAtIndex
+//(
+//  const uint32_t reg_idx,
+//  const Thread* currState,
+//  const DWARFCallFrameInfo::Row* row,
+//  mapped_memory_t * memCache,
+//  Thread* unwindState
+//)
+//{
+//    bool get_reg_success = false;
+//
+//    const RegLocation* regLocation = row->regs.GetRegisterInfo(reg_idx);
+//
+//  // On some systems, we may not get unwind info for the program counter,
+//  // but the return address register can be used to get that information.
+//    if (reg_idx == currState->GetPCRegNum(Thread::Index))
+//    {
+//      const RegLocation* returnAddrRegLocation = row->regs.GetRegisterInfo(currState->GetRARegNum(Thread::Index));
+//      if (regLocation == NULL)
+//      {
+//          // We have nothing to the program counter, so lets see if this
+//          // thread state has a return address (link register) that can
+//          // help us track down the previous PC
+//          regLocation = returnAddrRegLocation;
+//      }
+//      else if (regLocation->type == RegLocation::unspecified)
+//      {
+//          // We did have a location that didn't specify a value for unwinding
+//          // the PC, so if there is a info for the return return address
+//          // register (link register) lets use that
+//          if (returnAddrRegLocation)
+//              regLocation = returnAddrRegLocation;
+//      }
+//    }
+//
+//    if (regLocation)
+//    {
+//      mach_vm_address_t unwoundRegValue = INVALID_VMADDR;
+//      switch (regLocation->type)
+//      {
+//          case RegLocation::undefined:
+//              // Register is not available, mark it as invalid
+//              unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false);
+//              return true;
+//
+//          case RegLocation::unspecified:
+//              // Nothing to do if it is the same
+//              return true;
+//
+//          case RegLocation::same:
+//              // Nothing to do if it is the same
+//              return true;
+//
+//          case RegLocation::atFPPlusOffset:
+//          case RegLocation::isFPPlusOffset:
+//          {
+//              uint64_t unwindAddress = currState->GetRegisterValue(row->cfa_register, Thread::GCC, INVALID_VMADDR, &get_reg_success);
+//
+//              if (get_reg_success)
+//              {
+//                  unwindAddress += row->cfa_offset + regLocation->location.offset;
+//
+//                  if (regLocation->type == RegLocation::isFPPlusOffset)
+//                  {
+//                      unwindState->SetRegisterValue(reg_idx, Thread::Index, unwindAddress);
+//                      return true;
+//                  }
+//                  else
+//                  {
+//                      kern_return_t err = mapped_memory_read_pointer(memCache, unwindAddress, &unwoundRegValue);
+//                      if (err != KERN_SUCCESS)
+//                      {
+//                          unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false);
+//                          return false;
+//                      }
+//                      unwindState->SetRegisterValue(reg_idx, Thread::Index, unwoundRegValue);
+//                      return true;
+//                  }
+//              }
+//              else
+//              {
+//                  unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false);
+//              }
+//              return false;
+//          }
+//              break;
+//
+//          case RegLocation::atDWARFExpression:
+//          case RegLocation::isDWARFExpression:
+//          {
+//              bool swap = false;
+//              DWARFExpressionBaton baton = { currState, memCache, swap };
+//              uint64_t expr_result = 0;
+//              CSBinaryDataRef opcodes(regLocation->location.expr.opcodes, regLocation->location.expr.length, swap);
+//              opcodes.SetPointerSize(currState->Is64Bit() ? 8 : 4);
+//              const char * expr_err = CSDWARFExpression::Evaluate(DWARFExpressionReadMemoryDCScriptInterpreter::Type,
+//                                                                  DWARFExpressionReadRegisterDCScriptInterpreter::Type,
+//                                                                  &baton,
+//                                                                  opcodes,
+//                                                                  0,
+//                                                                  regLocation->location.expr.length,
+//                                                                  NULL,
+//                                                                  expr_result);
+//              if (expr_err == NULL)
+//              {
+//                  // SUCCESS!
+//                  if (regLocation->type == RegLocation::isDWARFExpression)
+//                  {
+//                      unwindState->SetRegisterValue(reg_idx, Thread::Index, expr_result);
+//                      return true;
+//                  }
+//                  else
+//                  {
+//                      kern_return_t err = mapped_memory_read_pointer(memCache, expr_result, &unwoundRegValue);
+//                      if (err != KERN_SUCCESS)
+//                      {
+//                          unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false);
+//                          return false;
+//                      }
+//                      unwindState->SetRegisterValue(reg_idx, Thread::Index, unwoundRegValue);
+//                      return true;
+//                  }
+//              }
+//              else
+//              {
+//                  // FAIL
+//                  unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false);
+//              }
+//              return false;
+//          }
+//              break;
+//
+//
+//          case RegLocation::inRegister:
+//              // The value is in another register.
+//              unwoundRegValue = currState->GetRegisterValue(regLocation->location.reg, Thread::GCC, 0, &get_reg_success);
+//              if (get_reg_success)
+//              {
+//                  unwindState->SetRegisterValue(reg_idx, Thread::Index, unwoundRegValue);
+//                  return true;
+//              }
+//              return false;
+//
+//          default:
+//              break;
+//      }
+//    }
+//
+//    if (reg_idx == currState->GetSPRegNum(Thread::Index))
+//    {
+//      uint64_t cfa = currState->GetRegisterValue(row->cfa_register, Thread::GCC, 0, &get_reg_success);
+//      if (get_reg_success)
+//      {
+//          return unwindState->SetSP(cfa + row->cfa_offset);
+//      }
+//      else
+//      {
+//          unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false);
+//          return false;
+//      }
+//    }
+//
+//    return false;
+//}
+
+void
+DWARFCallFrameInfo::Dump(Stream *s, Thread *thread) const
+{
+    s->Indent();
+    s->Printf("DWARFCallFrameInfo for ");
+    *s << m_objfile->GetFileSpec();
+    if (m_flags.IsSet(eFlagParsedIndex))
+    {
+        s->Printf(" (CIE[%zu], FDE[%zu])\n", m_cie_map.size(), m_fde_map.size());
+        s->IndentMore();
+        cie_map_t::const_iterator cie_pos, cie_end = m_cie_map.end();
+        const ArchSpec *arch = &m_objfile->GetModule()->GetArchitecture();
+
+        for (cie_pos = m_cie_map.begin(); cie_pos != cie_end; ++ cie_pos)
+        {
+            if (cie_pos->second.get() == NULL)
+            {
+                s->Indent();
+                s->Printf("CIE{0x%8.8x} - unparsed\n", cie_pos->first);
+            }
+            else
+            {
+                cie_pos->second->Dump(s, thread, arch, m_reg_kind);
+            }
+        }
+
+        fde_map_t::const_iterator fde_pos, fde_end = m_fde_map.end();
+        for (fde_pos = m_fde_map.begin(); fde_pos != fde_end; ++ fde_pos)
+        {
+            if (fde_pos->second.fde_sp.get() == NULL)
+            {
+                s->Indent();
+                s->Printf("FDE{0x%8.8x} - unparsed\n", fde_pos->second.fde_offset);
+            }
+            else
+            {
+                fde_pos->second.fde_sp->Dump(s, *this, thread);
+            }
+        }
+        s->IndentLess();
+    }
+    else
+    {
+        s->PutCString(" (not indexed yet)\n");
+    }
+}
+
+
+//uint32_t
+//DWARFCallFrameInfo::UnwindThreadState(const Thread* currState, mapped_memory_t *memCache, bool is_first_frame, Thread* unwindState)
+//{
+//  if (currState == NULL || unwindState == NULL)
+//      return 0;
+//
+//    *unwindState = *currState;
+//    uint32_t numRegisterUnwound = 0;
+//    uint64_t currPC = currState->GetPC(INVALID_VMADDR);
+//
+//    if (currPC != INVALID_VMADDR)
+//    {
+//      // If this is not the first frame, we care about the previous instruction
+//      // since it will be at the instruction following the instruction that
+//      // made the function call.
+//      uint64_t unwindPC = currPC;
+//      if (unwindPC > 0 && !is_first_frame)
+//          --unwindPC;
+//
+//#if defined(__i386__) || defined(__x86_64__)
+//      // Only on i386 do we have __IMPORT segments that contain trampolines
+//      if (!currState->Is64Bit() && ImportRangesContainsAddress(unwindPC))
+//      {
+//          uint64_t curr_sp = currState->GetSP(INVALID_VMADDR);
+//          mach_vm_address_t pc = INVALID_VMADDR;
+//          unwindState->SetSP(curr_sp + 4);
+//          kern_return_t err = mapped_memory_read_pointer(memCache, curr_sp, &pc);
+//          if (err == KERN_SUCCESS)
+//          {
+//              unwindState->SetPC(pc);
+//              return 2;
+//          }
+//      }
+//#endif
+//      FDE *fde = FindFDE(unwindPC);
+//      if (fde)
+//      {
+//          FindRowUserData rowUserData (currState, unwindPC);
+//          ParseInstructions (currState, fde, FindRowForAddress, &rowUserData);
+//
+//          const uint32_t numRegs = currState->NumRegisters();
+//          for (uint32_t regNum = 0; regNum < numRegs; regNum++)
+//          {
+//              if (UnwindRegisterAtIndex(regNum, currState, &rowUserData.state, memCache, unwindState))
+//                  numRegisterUnwound++;
+//          }
+//      }
+//    }
+//    return numRegisterUnwound;
+//}
+
+
diff --git a/source/Symbol/Declaration.cpp b/source/Symbol/Declaration.cpp
new file mode 100644
index 0000000..a31a304
--- /dev/null
+++ b/source/Symbol/Declaration.cpp
@@ -0,0 +1,172 @@
+//===-- Declaration.cpp -----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/Declaration.h"
+#include "lldb/Core/Stream.h"
+
+using namespace lldb_private;
+
+Declaration::Declaration() :
+    m_file(),
+    m_line(0),
+    m_column(0)
+{
+}
+
+Declaration::Declaration(const FileSpec& f, uint32_t l, uint32_t c) :
+    m_file(f),
+    m_line(l),
+    m_column(c)
+{
+}
+
+Declaration::Declaration(const Declaration& rhs) :
+    m_file(rhs.m_file),
+    m_line(rhs.m_line),
+    m_column(rhs.m_column)
+{
+}
+
+Declaration::Declaration(const Declaration* decl_ptr) :
+    m_file(),
+    m_line(0),
+    m_column(0)
+{
+    if (decl_ptr != NULL)
+        *this = *decl_ptr;
+}
+
+bool
+Declaration::IsValid() const
+{
+    return m_file && m_line != 0;
+}
+
+void
+Declaration::Clear()
+{
+    m_file.Clear();
+    m_line= 0;
+    m_column = 0;
+}
+
+void
+Declaration::Dump(Stream *s) const
+{
+    if (m_file)
+    {
+        *s << ", decl = '" << m_file;
+        if (m_line > 0)
+            s->Printf(":%u", m_line);
+        if (m_column > 0)
+            s->Printf(":%u", m_column);
+        s->PutChar('\'');
+    }
+    else
+    {
+        if (m_line > 0)
+        {
+            s->Printf(", line = %u", m_line);
+            if (m_column > 0)
+                s->Printf(":%u", m_column);
+        }
+        else if (m_column > 0)
+            s->Printf(", column = %u", m_column);
+    }
+}
+
+void
+Declaration::DumpStopContext (Stream *s) const
+{
+    if (m_file)
+    {
+        if (s->GetVerbose())
+            *s << m_file;
+        else
+            m_file.GetFilename().Dump(s);
+
+        if (m_line > 0)
+            s->Printf(":%u", m_line);
+        if (m_column > 0)
+            s->Printf(":%u", m_column);
+    }
+    else
+    {
+        s->Printf(" line %u", m_line);
+        if (m_column > 0)
+            s->Printf(":%u", m_column);
+    }
+}
+
+uint32_t
+Declaration::GetColumn() const
+{
+    return m_column;
+}
+
+FileSpec&
+Declaration::GetFile()
+{
+    return m_file;
+}
+
+const FileSpec&
+Declaration::GetFile() const
+{
+    return m_file;
+}
+
+uint32_t
+Declaration::GetLine() const
+{
+    return m_line;
+}
+
+size_t
+Declaration::MemorySize() const
+{
+    return sizeof(Declaration);
+}
+
+void
+Declaration::SetColumn(uint32_t col)
+{
+    m_column = col;
+}
+
+void
+Declaration::SetFile(const FileSpec& file)
+{
+    m_file = file;
+}
+
+void
+Declaration::SetLine(uint32_t line)
+{
+    m_line = line;
+}
+
+
+
+int
+Declaration::Compare(const Declaration& a, const Declaration& b)
+{
+    int result = FileSpec::Compare(a.m_file, b.m_file, true);
+    if (result)
+        return result;
+    if (a.m_line < b.m_line)
+        return -1;
+    else if (a.m_line > b.m_line)
+        return 1;
+    if (a.m_column < b.m_column)
+        return -1;
+    else if (a.m_column > b.m_column)
+        return 1;
+    return 0;
+}
diff --git a/source/Symbol/Function.cpp b/source/Symbol/Function.cpp
new file mode 100644
index 0000000..51c449a
--- /dev/null
+++ b/source/Symbol/Function.cpp
@@ -0,0 +1,432 @@
+//===-- Function.cpp --------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/Function.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/LineTable.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/CanonicalType.h"
+
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Basic function information is contained in the FunctionInfo class.
+// It is designed to contain the name, linkage name, and declaration
+// location.
+//----------------------------------------------------------------------
+FunctionInfo::FunctionInfo (const char *name, const Declaration *decl_ptr) :
+    m_name(name),
+    m_declaration(decl_ptr)
+{
+}
+
+
+FunctionInfo::FunctionInfo (const ConstString& name, const Declaration *decl_ptr) :
+    m_name(name),
+    m_declaration(decl_ptr)
+{
+}
+
+
+FunctionInfo::~FunctionInfo()
+{
+}
+
+void
+FunctionInfo::Dump(Stream *s) const
+{
+    if (m_name)
+        *s << ", name = \"" << m_name << "\"";
+    m_declaration.Dump(s);
+}
+
+
+int
+FunctionInfo::Compare(const FunctionInfo& a, const FunctionInfo& b)
+{
+    int result = ConstString::Compare(a.GetName(), b.GetName());
+    if (result)
+        return result;
+
+    return Declaration::Compare(a.m_declaration, b.m_declaration);
+}
+
+
+Declaration&
+FunctionInfo::GetDeclaration()
+{
+    return m_declaration;
+}
+
+const Declaration&
+FunctionInfo::GetDeclaration() const
+{
+    return m_declaration;
+}
+
+const ConstString&
+FunctionInfo::GetName() const
+{
+    return m_name;
+}
+
+size_t
+FunctionInfo::MemorySize() const
+{
+    return m_name.MemorySize() + m_declaration.MemorySize();
+}
+
+
+InlineFunctionInfo::InlineFunctionInfo
+(
+    const char *name,
+    const char *mangled,
+    const Declaration *decl_ptr,
+    const Declaration *call_decl_ptr
+) :
+    FunctionInfo(name, decl_ptr),
+    m_mangled(mangled, true),
+    m_call_decl (call_decl_ptr)
+{
+}
+
+InlineFunctionInfo::InlineFunctionInfo
+(
+    const ConstString& name,
+    const Mangled &mangled,
+    const Declaration *decl_ptr,
+    const Declaration *call_decl_ptr
+) :
+    FunctionInfo(name, decl_ptr),
+    m_mangled(mangled),
+    m_call_decl (call_decl_ptr)
+{
+}
+
+InlineFunctionInfo::~InlineFunctionInfo()
+{
+}
+
+int
+InlineFunctionInfo::Compare(const InlineFunctionInfo& a, const InlineFunctionInfo& b)
+{
+
+    int result = FunctionInfo::Compare(a, b);
+    if (result)
+        return result;
+    // only compare the mangled names if both have them
+    return Mangled::Compare(a.m_mangled, a.m_mangled);
+}
+
+void
+InlineFunctionInfo::Dump(Stream *s) const
+{
+    FunctionInfo::Dump(s);
+    if (m_mangled)
+        m_mangled.Dump(s);
+}
+
+void
+InlineFunctionInfo::DumpStopContext (Stream *s) const
+{
+//    s->Indent("[inlined] ");
+    s->Indent();
+    if (m_mangled)
+        s->PutCString (m_mangled.GetName().AsCString());
+    else
+        s->PutCString (m_name.AsCString());
+}
+
+Declaration &
+InlineFunctionInfo::GetCallSite ()
+{
+    return m_call_decl;
+}
+
+const Declaration &
+InlineFunctionInfo::GetCallSite () const
+{
+    return m_call_decl;
+}
+
+
+Mangled&
+InlineFunctionInfo::GetMangled()
+{
+    return m_mangled;
+}
+
+const Mangled&
+InlineFunctionInfo::GetMangled() const
+{
+    return m_mangled;
+}
+
+size_t
+InlineFunctionInfo::MemorySize() const
+{
+    return FunctionInfo::MemorySize() + m_mangled.MemorySize();
+}
+
+//----------------------------------------------------------------------
+//
+//----------------------------------------------------------------------
+Function::Function
+(
+    CompileUnit *comp_unit,
+    lldb::user_id_t func_uid,
+    lldb::user_id_t type_uid,
+    const Mangled &mangled,
+    Type * type,
+    const AddressRange& range
+) :
+    UserID(func_uid),
+    m_comp_unit(comp_unit),
+    m_type_uid(type_uid),
+    m_type(type),
+    m_mangled(mangled),
+    m_blocks(this, range),
+    m_frame_base(),
+    m_flags(),
+    m_prologue_byte_size(0)
+{
+    assert(comp_unit != NULL);
+}
+
+Function::Function
+(
+    CompileUnit *comp_unit,
+    lldb::user_id_t func_uid,
+    lldb::user_id_t type_uid,
+    const char *mangled,
+    Type *type,
+    const AddressRange &range
+) :
+    UserID(func_uid),
+    m_comp_unit(comp_unit),
+    m_type_uid(type_uid),
+    m_type(type),
+    m_mangled(mangled, true),
+    m_blocks(this, range),
+    m_frame_base(),
+    m_flags(),
+    m_prologue_byte_size(0)
+{
+    assert(comp_unit != NULL);
+}
+
+
+Function::~Function()
+{
+}
+
+const AddressRange &
+Function::GetAddressRange()
+{
+    return GetBlocks(true).GetAddressRange();
+}
+
+BlockList &
+Function::GetBlocks(bool can_create)
+{
+    if (m_blocks.IsEmpty() && can_create)
+    {
+        SymbolContext sc;
+        CalculateSymbolContext(&sc);
+        assert(sc.module_sp);
+        sc.module_sp->GetSymbolVendor()->ParseFunctionBlocks(sc);
+    }
+    return m_blocks;
+}
+
+CompileUnit*
+Function::GetCompileUnit()
+{
+    return m_comp_unit;
+}
+
+const CompileUnit*
+Function::GetCompileUnit() const
+{
+    return m_comp_unit;
+}
+
+void
+Function::Dump(Stream *s, bool show_context) const
+{
+    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+    s->Indent();
+    *s << "Function" << (const UserID&)*this;
+
+    m_mangled.Dump(s);
+
+//  FunctionInfo::Dump(s);
+    if (m_type)
+    {
+        *s << ", type = " << (void*)m_type;
+        /// << " (";
+        ///m_type->DumpTypeName(s);
+        ///s->PutChar(')');
+    }
+    else if (m_type_uid != LLDB_INVALID_UID)
+        *s << ", type_uid = " << m_type_uid;
+
+    s->EOL();
+    // Dump the root object
+    if (!m_blocks.IsEmpty())
+        m_blocks.Dump(s, Block::RootID, INT_MAX, show_context);
+}
+
+
+void
+Function::CalculateSymbolContext(SymbolContext* sc)
+{
+    sc->function = this;
+    m_comp_unit->CalculateSymbolContext(sc);
+}
+
+void
+Function::DumpSymbolContext(Stream *s)
+{
+    m_comp_unit->DumpSymbolContext(s);
+    s->Printf(", Function{0x%8.8x}", GetID());
+}
+
+size_t
+Function::MemorySize () const
+{
+    size_t mem_size = sizeof(Function) + m_blocks.MemorySize();
+    return mem_size;
+}
+
+Type*
+Function::GetType()
+{
+    return m_type;
+}
+
+const Type*
+Function::GetType() const
+{
+    return m_type;
+}
+
+Type
+Function::GetReturnType ()
+{
+    clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetOpaqueClangQualType()));
+    assert (clang_type->isFunctionType());
+    clang::FunctionType *function_type = dyn_cast<clang::FunctionType> (clang_type);
+    clang::QualType fun_return_qualtype = function_type->getResultType();
+
+    const ConstString fun_return_name(Type::GetClangTypeName(fun_return_qualtype.getAsOpaquePtr()));
+
+    SymbolContext sc;
+    CalculateSymbolContext (&sc);
+    // Null out everything below the CompUnit 'cause we don't actually know these.
+
+    size_t bit_size = ClangASTContext::GetTypeBitSize ((GetType()->GetClangASTContext().getASTContext()), &fun_return_qualtype);
+    Type return_type (0, GetType()->GetSymbolFile(), fun_return_name, bit_size, sc.comp_unit, 0, Type::eTypeUIDSynthetic, Declaration(), fun_return_qualtype.getAsOpaquePtr());
+    return return_type;
+}
+
+int
+Function::GetArgumentCount ()
+{
+    clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetOpaqueClangQualType()));
+    assert (clang_type->isFunctionType());
+    if (!clang_type->isFunctionProtoType())
+        return -1;
+
+    const clang::FunctionProtoType *function_proto_type = dyn_cast<clang::FunctionProtoType>(clang_type);
+    if (function_proto_type != NULL)
+        return function_proto_type->getNumArgs();
+
+    return 0;
+}
+
+const Type
+Function::GetArgumentTypeAtIndex (size_t idx)
+{
+    clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetOpaqueClangQualType()));
+   assert (clang_type->isFunctionType());
+   if (!clang_type->isFunctionProtoType())
+        return Type();
+
+    const clang::FunctionProtoType *function_proto_type = dyn_cast<clang::FunctionProtoType>(clang_type);
+    if (function_proto_type != NULL)
+    {
+        unsigned num_args = function_proto_type->getNumArgs();
+        if (idx >= num_args)
+            return Type();
+        clang::QualType arg_qualtype = (function_proto_type->arg_type_begin())[idx];
+
+        const ConstString arg_return_name(Type::GetClangTypeName(arg_qualtype.getAsOpaquePtr()));
+        SymbolContext sc;
+        CalculateSymbolContext (&sc);
+        // Null out everything below the CompUnit 'cause we don't actually know these.
+
+        size_t bit_size = ClangASTContext::GetTypeBitSize ((GetType()->GetClangASTContext().getASTContext()), &arg_qualtype);
+        Type arg_type (0, GetType()->GetSymbolFile(), arg_return_name, bit_size, sc.comp_unit, 0, Type::eTypeUIDSynthetic, Declaration(), arg_qualtype.getAsOpaquePtr());
+        return arg_type;
+    }
+
+    return Type();
+}
+
+const char *
+Function::GetArgumentNameAtIndex (size_t idx)
+{
+   clang::Type *clang_type = static_cast<clang::QualType *>(GetType()->GetOpaqueClangQualType())->getTypePtr();
+   assert (clang_type->isFunctionType());
+   if (!clang_type->isFunctionProtoType())
+       return NULL;
+    return NULL;
+}
+
+bool
+Function::IsVariadic ()
+{
+   const clang::Type *clang_type = static_cast<clang::QualType *>(GetType()->GetOpaqueClangQualType())->getTypePtr();
+   assert (clang_type->isFunctionType());
+   if (!clang_type->isFunctionProtoType())
+        return false;
+
+    const clang::FunctionProtoType *function_proto_type = dyn_cast<clang::FunctionProtoType>(clang_type);
+    if (function_proto_type != NULL)
+    {
+        return function_proto_type->isVariadic();
+    }
+
+    return false;
+}
+
+uint32_t
+Function::GetPrologueByteSize ()
+{
+    if (m_prologue_byte_size == 0 && m_flags.IsClear(flagsCalculatedPrologueSize))
+    {
+        m_flags.Set(flagsCalculatedPrologueSize);
+        LineTable* line_table = m_comp_unit->GetLineTable ();
+        if (line_table)
+        {
+            LineEntry line_entry;
+            if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(), line_entry))
+                m_prologue_byte_size = line_entry.range.GetByteSize();
+        }
+    }
+    return m_prologue_byte_size;
+}
+
+
+
diff --git a/source/Symbol/LineEntry.cpp b/source/Symbol/LineEntry.cpp
new file mode 100644
index 0000000..cdc3c54
--- /dev/null
+++ b/source/Symbol/LineEntry.cpp
@@ -0,0 +1,237 @@
+//===-- LineEntry.cpp -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/LineEntry.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb_private;
+
+LineEntry::LineEntry() :
+    range(),
+    file(),
+    line(0),
+    column(0),
+    is_start_of_statement(0),
+    is_start_of_basic_block(0),
+    is_terminal_entry(0),
+    is_prologue_end(0),
+    is_epilogue_begin(0)
+{
+}
+
+LineEntry::LineEntry
+(
+    lldb_private::Section *section,
+    lldb::addr_t section_offset,
+    lldb::addr_t byte_size,
+    const FileSpec &_file,
+    uint32_t _line,
+    uint16_t _column,
+    bool _is_start_of_statement,
+    bool _is_start_of_basic_block,
+    bool _is_prologue_end,
+    bool _is_epilogue_begin,
+    bool _is_terminal_entry
+) :
+    range(section, section_offset, byte_size),
+    file(_file),
+    line(_line),
+    column(_column),
+    is_start_of_statement(_is_start_of_statement),
+    is_start_of_basic_block(_is_start_of_basic_block),
+    is_prologue_end(_is_prologue_end),
+    is_epilogue_begin(_is_epilogue_begin),
+    is_terminal_entry(_is_terminal_entry)
+{
+}
+
+void
+LineEntry::Clear()
+{
+    range.Clear();
+    file.Clear();
+    line = 0;
+    column = 0;
+    is_start_of_statement = 0;
+    is_start_of_basic_block = 0;
+    is_prologue_end = 0;
+    is_epilogue_begin = 0;
+    is_terminal_entry = 0;
+}
+
+
+bool
+LineEntry::IsValid() const
+{
+    return range.GetBaseAddress().IsValid() && line != 0;
+}
+
+bool
+LineEntry::DumpStopContext(Stream *s) const
+{
+    bool result = false;
+    if (file)
+    {
+        file.Dump (s);
+        if (line)
+            s->PutChar(':');
+        result = true;
+    }
+    if (line)
+        s->Printf ("%u", line);
+    else
+        result = false;
+
+    return result;
+}
+
+bool
+LineEntry::Dump
+(
+    Stream *s,
+    Process *process,
+    bool show_file,
+    Address::DumpStyle style,
+    Address::DumpStyle fallback_style,
+    bool show_range
+) const
+{
+    if (show_range)
+    {
+        // Show address range
+        if (!range.Dump(s, process, style, fallback_style))
+            return false;
+    }
+    else
+    {
+        // Show address only
+        if (!range.GetBaseAddress().Dump(s,
+                                         process,
+                                         style,
+                                         fallback_style))
+            return false;
+    }
+    if (line)
+        s->Printf(", line = %u", line);
+    if (column)
+        s->Printf(", column = %u", column);
+    if (show_file)
+    {
+        *s << ", file = " << file;
+    }
+    if (is_start_of_statement)
+        *s << ", is_start_of_statement = TRUE";
+
+    if (is_start_of_basic_block)
+        *s << ", is_start_of_basic_block = TRUE";
+
+    if (is_prologue_end)
+        *s << ", is_prologue_end = TRUE";
+
+    if (is_epilogue_begin)
+        *s << ", is_epilogue_begin = TRUE";
+
+    if (is_terminal_entry)
+        *s << ", is_terminal_entry = TRUE";
+    return true;
+}
+
+bool
+LineEntry::GetDescription (Stream *s, lldb::DescriptionLevel level, CompileUnit* cu, Process *process) const
+{
+
+    if (level == lldb::eDescriptionLevelBrief || level == lldb::eDescriptionLevelFull)
+    {
+        // Show address only
+        range.GetBaseAddress().Dump(s, process, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
+
+        if (file)
+            *s << ' ' << file;
+
+        if (line)
+        {
+            s->Printf(":%u", line);
+            if (column)
+                s->Printf(":%u", column);
+        }
+
+        if (level == lldb::eDescriptionLevelFull)
+        {
+            if (is_start_of_statement)
+                *s << ", is_start_of_statement = TRUE";
+
+            if (is_start_of_basic_block)
+                *s << ", is_start_of_basic_block = TRUE";
+
+            if (is_prologue_end)
+                *s << ", is_prologue_end = TRUE";
+
+            if (is_epilogue_begin)
+                *s << ", is_epilogue_begin = TRUE";
+
+            if (is_terminal_entry)
+                *s << ", is_terminal_entry = TRUE";
+        }
+        else
+        {
+            if (is_terminal_entry)
+                s->EOL();
+        }
+    }
+    else
+    {
+        return Dump (s, process, true, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, true);
+    }
+    return true;
+}
+
+
+bool
+lldb_private::operator< (const LineEntry& a, const LineEntry& b)
+{
+    return LineEntry::Compare (a, b) < 0;
+}
+
+int
+LineEntry::Compare (const LineEntry& a, const LineEntry& b)
+{
+    int result = Address::CompareFileAddress (a.range.GetBaseAddress(), b.range.GetBaseAddress());
+    if (result != 0)
+        return result;
+
+    const lldb::addr_t a_byte_size = a.range.GetByteSize();
+    const lldb::addr_t b_byte_size = b.range.GetByteSize();
+
+    if (a_byte_size < b_byte_size)
+        return -1;
+    if (a_byte_size > b_byte_size)
+        return +1;
+
+    // Check for an end sequence entry mismatch after we have determined
+    // that the address values are equal. If one of the items is an end
+    // sequence, we don't care about the line, file, or column info.
+    if (a.is_terminal_entry > b.is_terminal_entry)
+        return -1;
+    if (a.is_terminal_entry < b.is_terminal_entry)
+        return +1;
+
+    if (a.line < b.line)
+        return -1;
+    if (a.line > b.line)
+        return +1;
+
+    if (a.column < b.column)
+        return -1;
+    if (a.column > b.column)
+        return +1;
+
+    return FileSpec::Compare (a.file, b.file, true);
+}
+
diff --git a/source/Symbol/LineTable.cpp b/source/Symbol/LineTable.cpp
new file mode 100644
index 0000000..326fd6e
--- /dev/null
+++ b/source/Symbol/LineTable.cpp
@@ -0,0 +1,332 @@
+//===-- LineTable.cpp -------------------------------------------*- 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/Address.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/LineTable.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// LineTable constructor
+//----------------------------------------------------------------------
+LineTable::LineTable(CompileUnit* comp_unit) :
+    m_comp_unit(comp_unit),
+    m_section_list(),
+    m_entries()
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+LineTable::~LineTable()
+{
+}
+
+//void
+//LineTable::AddLineEntry(const LineEntry& entry)
+//{
+//  // Do a binary search for the correct entry and insert it
+//  m_line_entries.insert(std::upper_bound(m_line_entries.begin(), m_line_entries.end(), entry), entry);
+//}
+
+void
+LineTable::AppendLineEntry
+(
+    SectionSP& section_sp,
+    lldb::addr_t section_offset,
+    uint32_t line,
+    uint16_t column,
+    uint16_t file_idx,
+    bool is_start_of_statement,
+    bool is_start_of_basic_block,
+    bool is_prologue_end,
+    bool is_epilogue_begin,
+    bool is_terminal_entry
+)
+{
+    uint32_t sect_idx = m_section_list.AddUniqueSection (section_sp);
+    // Make sure we don't user more than 256 sections as that is all we have
+    // room for in the LineTable::Entry::m_sect_idx. If this assert fires,
+    // we will need to m_sect_idx have more bits...
+    assert((section_offset & 0xffffffffff000000ull) == 0);
+    Entry entry(sect_idx, section_offset, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry);
+    m_entries.push_back (entry);
+}
+
+
+void
+LineTable::InsertLineEntry
+(
+    SectionSP& section_sp,
+    lldb::addr_t section_offset,
+    uint32_t line,
+    uint16_t column,
+    uint16_t file_idx,
+    bool is_start_of_statement,
+    bool is_start_of_basic_block,
+    bool is_prologue_end,
+    bool is_epilogue_begin,
+    bool is_terminal_entry
+)
+{
+    SectionSP line_section_sp(section_sp);
+    const Section *linked_section = line_section_sp->GetLinkedSection();
+    if (linked_section)
+    {
+        section_offset += line_section_sp->GetLinkedOffset();
+        line_section_sp = linked_section->GetSharedPointer();
+        assert(line_section_sp.get());
+    }
+
+    uint32_t sect_idx = m_section_list.AddUniqueSection (line_section_sp);
+    // Make sure we don't user more than 256 sections as that is all we have
+    // room for in the LineTable::Entry::m_sect_idx. If this assert fires,
+    // we will need to m_sect_idx have more bits...
+    assert((section_offset & 0xffffffffff000000ull) == 0);
+    Entry entry(sect_idx, section_offset, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry);
+
+    entry_collection::iterator begin_pos = m_entries.begin();
+    entry_collection::iterator end_pos = m_entries.end();
+    LineTable::Entry::LessThanBinaryPredicate less_than_bp(this);
+    entry_collection::iterator pos = upper_bound(begin_pos, end_pos, entry, less_than_bp);
+
+//  Stream s(stdout);
+//  s << "\n\nBefore:\n";
+//  Dump (&s, Address::DumpStyleFileAddress);
+    m_entries.insert(pos, entry);
+//  s << "After:\n";
+//  Dump (&s, Address::DumpStyleFileAddress);
+}
+
+//----------------------------------------------------------------------
+LineTable::Entry::LessThanBinaryPredicate::LessThanBinaryPredicate(LineTable *line_table) :
+    m_line_table (line_table)
+{
+}
+
+bool
+LineTable::Entry::LessThanBinaryPredicate::operator() (const LineTable::Entry& a, const LineTable::Entry& b) const
+{
+    if (a.sect_idx == b.sect_idx)
+    {
+        #define LT_COMPARE(a,b) if (a != b) return a < b
+        LT_COMPARE (a.sect_offset, b.sect_offset);
+        LT_COMPARE (a.line, b.line);
+        LT_COMPARE (a.column, b.column);
+        LT_COMPARE (a.is_start_of_statement, b.is_start_of_statement);
+        LT_COMPARE (a.is_start_of_basic_block, b.is_start_of_basic_block);
+        // b and a reversed on purpose below.
+        LT_COMPARE (b.is_prologue_end, a.is_prologue_end);
+        LT_COMPARE (a.is_epilogue_begin, b.is_epilogue_begin);
+        // b and a reversed on purpose below.
+        LT_COMPARE (b.is_terminal_entry, a.is_terminal_entry);
+        LT_COMPARE (a.file_idx, b.file_idx);
+        return false;
+        #undef LT_COMPARE;
+    }
+
+    const Section *a_section = m_line_table->GetSectionForEntryIndex (a.sect_idx);
+    const Section *b_section = m_line_table->GetSectionForEntryIndex (b.sect_idx);
+    return Section::Compare(*a_section, *b_section) < 0;
+};
+
+
+Section *
+LineTable::GetSectionForEntryIndex (uint32_t idx)
+{
+    if (idx < m_section_list.GetSize())
+        return m_section_list.GetSectionAtIndex(idx).get();
+    return NULL;
+}
+
+uint32_t
+LineTable::GetSize() const
+{
+    return m_entries.size();
+}
+
+bool
+LineTable::GetLineEntryAtIndex(uint32_t idx, LineEntry& line_entry)
+{
+    if (idx < m_entries.size())
+    {
+        ConvertEntryAtIndexToLineEntry (idx, line_entry);
+        return true;
+    }
+    line_entry.Clear();
+    return false;
+}
+
+bool
+LineTable::FindLineEntryByAddress (const Address &so_addr, LineEntry& line_entry, uint32_t *index_ptr)
+{
+    if (index_ptr != NULL )
+        *index_ptr = UINT32_MAX;
+
+    bool success = false;
+    uint32_t sect_idx = m_section_list.FindSectionIndex (so_addr.GetSection());
+    if (sect_idx != UINT32_MAX)
+    {
+        Entry search_entry;
+        search_entry.sect_idx = sect_idx;
+        search_entry.sect_offset = so_addr.GetOffset();
+
+        entry_collection::const_iterator begin_pos = m_entries.begin();
+        entry_collection::const_iterator end_pos = m_entries.end();
+        entry_collection::const_iterator pos = lower_bound(begin_pos, end_pos, search_entry, Entry::EntryAddressLessThan);
+        if (pos != end_pos)
+        {
+            if (pos != begin_pos)
+            {
+                if (pos->sect_offset != search_entry.sect_offset)
+                    --pos;
+                else if (pos->sect_offset == search_entry.sect_offset)
+                {
+                    while (pos != begin_pos)
+                    {
+                        entry_collection::const_iterator prev_pos = pos - 1;
+                        if (prev_pos->sect_idx    == search_entry.sect_idx &&
+                            prev_pos->sect_offset == search_entry.sect_offset)
+                            --pos;
+                        else
+                            break;
+                    }
+                }
+
+            }
+            uint32_t match_idx = std::distance (begin_pos, pos);
+            success = ConvertEntryAtIndexToLineEntry(match_idx, line_entry);
+            if (index_ptr != NULL && success)
+                *index_ptr = match_idx;
+        }
+    }
+    return success;
+}
+
+
+bool
+LineTable::ConvertEntryAtIndexToLineEntry (uint32_t idx, LineEntry &line_entry)
+{
+    if (idx < m_entries.size())
+    {
+        const Entry& entry = m_entries[idx];
+        line_entry.range.GetBaseAddress().SetSection(m_section_list.GetSectionAtIndex (entry.sect_idx).get());
+        line_entry.range.GetBaseAddress().SetOffset(entry.sect_offset);
+        if (!entry.is_terminal_entry && idx + 1 < m_entries.size())
+        {
+            const Entry& next_entry = m_entries[idx+1];
+            if (next_entry.sect_idx == entry.sect_idx)
+            {
+                line_entry.range.SetByteSize(next_entry.sect_offset - entry.sect_offset);
+            }
+            else
+            {
+                Address next_line_addr(m_section_list.GetSectionAtIndex (next_entry.sect_idx).get(), next_entry.sect_offset);
+                line_entry.range.SetByteSize(next_line_addr.GetFileAddress() - line_entry.range.GetBaseAddress().GetFileAddress());
+            }
+        }
+        else
+            line_entry.range.SetByteSize(0);
+        line_entry.file = m_comp_unit->GetSupportFiles().GetFileSpecAtIndex (entry.file_idx);
+        line_entry.line = entry.line;
+        line_entry.column = entry.column;
+        line_entry.is_start_of_statement = entry.is_start_of_statement;
+        line_entry.is_start_of_basic_block = entry.is_start_of_basic_block;
+        line_entry.is_prologue_end = entry.is_prologue_end;
+        line_entry.is_epilogue_begin = entry.is_epilogue_begin;
+        line_entry.is_terminal_entry = entry.is_terminal_entry;
+        return true;
+    }
+    return false;
+}
+
+uint32_t
+LineTable::FindLineEntryIndexByFileIndex (uint32_t start_idx, uint32_t file_idx, uint32_t line, bool exact, LineEntry* line_entry_ptr)
+{
+    const size_t count = m_entries.size();
+    size_t best_match = UINT_MAX;
+
+    for (size_t idx = start_idx; idx < count; ++idx)
+    {
+        // Skip line table rows that terminate the previous row (is_terminal_entry is non-zero)
+        if (m_entries[idx].is_terminal_entry)
+            continue;
+
+        if (m_entries[idx].file_idx != file_idx)
+            continue;
+
+        // Exact match always wins.  Otherwise try to find the closest line > the desired
+        // line.
+        // FIXME: Maybe want to find the line closest before and the line closest after and
+        // if they're not in the same function, don't return a match.
+
+        if (m_entries[idx].line < line)
+        {
+            continue;
+        }
+        else if (m_entries[idx].line == line)
+        {
+            if (line_entry_ptr)
+                ConvertEntryAtIndexToLineEntry (idx, *line_entry_ptr);
+            return idx;
+        }
+        else if (!exact)
+        {
+            if (best_match == UINT32_MAX)
+                best_match = idx;
+            else if (m_entries[idx].line < m_entries[best_match].line)
+                best_match = idx;
+        }
+    }
+
+    if (best_match != UINT_MAX)
+    {
+        if (line_entry_ptr)
+            ConvertEntryAtIndexToLineEntry (best_match, *line_entry_ptr);
+        return best_match;
+    }
+    return UINT_MAX;
+}
+
+void
+LineTable::Dump (Stream *s, Process *process, Address::DumpStyle style, Address::DumpStyle fallback_style, bool show_line_ranges)
+{
+    const size_t count = m_entries.size();
+    LineEntry line_entry;
+    FileSpec prev_file;
+    for (size_t idx = 0; idx < count; ++idx)
+    {
+        ConvertEntryAtIndexToLineEntry (idx, line_entry);
+        line_entry.Dump (s, process, prev_file != line_entry.file, style, fallback_style, show_line_ranges);
+        s->EOL();
+        prev_file = line_entry.file;
+    }
+}
+
+
+void
+LineTable::GetDescription (Stream *s, Process *process, DescriptionLevel level)
+{
+    const size_t count = m_entries.size();
+    LineEntry line_entry;
+    for (size_t idx = 0; idx < count; ++idx)
+    {
+        ConvertEntryAtIndexToLineEntry (idx, line_entry);
+        line_entry.GetDescription (s, level, m_comp_unit, process);
+        s->EOL();
+    }
+}
+
+
+
diff --git a/source/Symbol/ObjectFile.cpp b/source/Symbol/ObjectFile.cpp
new file mode 100644
index 0000000..8d22448
--- /dev/null
+++ b/source/Symbol/ObjectFile.cpp
@@ -0,0 +1,92 @@
+//===-- ObjectFile.cpp ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/ObjectContainer.h"
+#include "lldb/Symbol/SymbolFile.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+ObjectFile*
+ObjectFile::FindPlugin (Module* module, const FileSpec* file, lldb::addr_t file_offset, lldb::addr_t file_size)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "ObjectFile::FindPlugin (module = %s/%s, file = %p, file_offset = 0x%z8.8x, file_size = 0x%z8.8x)",
+                        module->GetFileSpec().GetDirectory().AsCString(),
+                        module->GetFileSpec().GetFilename().AsCString(),
+                        file, file_offset, file_size);
+    std::auto_ptr<ObjectFile> object_file_ap;
+
+    if (module != NULL)
+    {
+        if (file)
+        {
+            if (file_size == 0)
+                file_size = file->GetByteSize();
+
+            if (file_size == 0)
+            {
+                // Check for archive file with format "/path/to/archive.a(object.o)"
+                char path_with_object[PATH_MAX*2];
+                module->GetFileSpec().GetPath(path_with_object, sizeof(path_with_object));
+
+                RegularExpression g_object_regex("(.*)\\(([^\\)]+)\\)$");
+                if (g_object_regex.Execute (path_with_object, 2))
+                {
+                    FileSpec archive_file;
+                    std::string path;
+                    std::string object;
+                    if (g_object_regex.GetMatchAtIndex (path_with_object, 1, path) &&
+                        g_object_regex.GetMatchAtIndex (path_with_object, 2, object))
+                    {
+                        archive_file.SetFile (path.c_str());
+                        file_size = archive_file.GetByteSize();
+                        if (file_size > 0)
+                            module->SetFileSpecAndObjectName (archive_file, ConstString(object.c_str()));
+                    }
+                }
+            }
+
+            DataBufferSP file_header_data_sp(file->ReadFileContents(file_offset, 512));
+            uint32_t idx;
+
+            // Check if this is a normal object file by iterating through
+            // all object file plugin instances.
+            ObjectFileCreateInstance create_object_file_callback;
+            for (idx = 0; (create_object_file_callback = PluginManager::GetObjectFileCreateCallbackAtIndex(idx)) != NULL; ++idx)
+            {
+                object_file_ap.reset (create_object_file_callback(module, file_header_data_sp, file, file_offset, file_size));
+                if (object_file_ap.get())
+                    return object_file_ap.release();
+            }
+
+            // Check if this is a object container by iterating through
+            // all object container plugin instances and then trying to get
+            // an object file from the container.
+            ObjectContainerCreateInstance create_object_container_callback;
+            for (idx = 0; (create_object_container_callback = PluginManager::GetObjectContainerCreateCallbackAtIndex(idx)) != NULL; ++idx)
+            {
+                std::auto_ptr<ObjectContainer> object_container_ap(create_object_container_callback(module, file_header_data_sp, file, file_offset, file_size));
+
+                if (object_container_ap.get())
+                    object_file_ap.reset (object_container_ap->GetObjectFile(file));
+
+                if (object_file_ap.get())
+                    return object_file_ap.release();
+            }
+        }
+    }
+    return NULL;
+}
diff --git a/source/Symbol/Symbol.cpp b/source/Symbol/Symbol.cpp
new file mode 100644
index 0000000..fb01fc1
--- /dev/null
+++ b/source/Symbol/Symbol.cpp
@@ -0,0 +1,463 @@
+//===-- Symbol.cpp ----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/Symbol.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+Symbol::Symbol() :
+    UserID (),
+    m_mangled (),
+    m_type (eSymbolTypeInvalid),
+    m_type_data (0),
+    m_type_data_resolved (false),
+    m_is_synthetic (false),
+    m_is_debug (false),
+    m_is_external (false),
+    m_size_is_sibling (false),
+    m_size_is_synthesized (false),
+    m_searched_for_function (false),
+    m_addr_range (),
+    m_flags (),
+    m_function (NULL)
+{
+}
+
+Symbol::Symbol
+(
+    user_id_t symID,
+    const char *name,
+    bool name_is_mangled,
+    SymbolType type,
+    bool external,
+    bool is_debug,
+    bool is_trampoline,
+    bool is_artificial,
+    const Section* section,
+    addr_t offset,
+    uint32_t size,
+    uint32_t flags
+) :
+    UserID (symID),
+    m_mangled (name, name_is_mangled),
+    m_type (type),
+    m_type_data (0),
+    m_type_data_resolved (false),
+    m_is_synthetic (is_artificial),
+    m_is_debug (is_debug),
+    m_is_external (external),
+    m_size_is_sibling (false),
+    m_size_is_synthesized (false),
+    m_searched_for_function (false),
+    m_addr_range (section, offset, size),
+    m_flags (flags),
+    m_function (NULL)
+{
+}
+
+Symbol::Symbol
+(
+    user_id_t symID,
+    const char *name,
+    bool name_is_mangled,
+    SymbolType type,
+    bool external,
+    bool is_debug,
+    bool is_trampoline,
+    bool is_artificial,
+    const AddressRange &range,
+    uint32_t flags
+) :
+    UserID (symID),
+    m_mangled (name, name_is_mangled),
+    m_type (type),
+    m_type_data (0),
+    m_type_data_resolved (false),
+    m_is_synthetic (is_artificial),
+    m_is_debug (is_debug),
+    m_is_external (external),
+    m_size_is_sibling (false),
+    m_size_is_synthesized (false),
+    m_searched_for_function (false),
+    m_addr_range (range),
+    m_flags (flags),
+    m_function (NULL)
+{
+}
+
+Symbol::Symbol(const Symbol& rhs):
+    UserID (rhs),
+    m_mangled (rhs.m_mangled),
+    m_type (rhs.m_type),
+    m_type_data (rhs.m_type_data),
+    m_type_data_resolved (rhs.m_type_data_resolved),
+    m_is_synthetic (rhs.m_is_synthetic),
+    m_is_debug (rhs.m_is_debug),
+    m_is_external (rhs.m_is_external),
+    m_size_is_sibling (rhs.m_size_is_sibling),
+    m_size_is_synthesized (false),
+    m_searched_for_function (false),
+    m_addr_range (rhs.m_addr_range),
+    m_flags (rhs.m_flags),
+    m_function (NULL)
+{
+}
+
+const Symbol&
+Symbol::operator= (const Symbol& rhs)
+{
+    if (this != &rhs)
+    {
+        UserID::operator= (rhs);
+        m_mangled = rhs.m_mangled;
+        m_type = rhs.m_type;
+        m_type_data = rhs.m_type_data;
+        m_type_data_resolved = rhs.m_type_data_resolved;
+        m_is_synthetic = rhs.m_is_synthetic;
+        m_is_debug = rhs.m_is_debug;
+        m_is_external = rhs.m_is_external;
+        m_size_is_sibling = rhs.m_size_is_sibling;
+        m_size_is_synthesized = rhs.m_size_is_sibling;
+        m_searched_for_function = rhs.m_searched_for_function;
+        m_addr_range = rhs.m_addr_range;
+        m_flags = rhs.m_flags;
+        m_function = rhs.m_function;
+    }
+    return *this;
+}
+
+AddressRange &
+Symbol::GetAddressRangeRef()
+{
+    return m_addr_range;
+}
+
+const AddressRange &
+Symbol::GetAddressRangeRef() const
+{
+    return m_addr_range;
+}
+
+AddressRange *
+Symbol::GetAddressRangePtr()
+{
+    if (m_addr_range.GetBaseAddress().GetSection())
+        return &m_addr_range;
+    return NULL;
+}
+
+const AddressRange *
+Symbol::GetAddressRangePtr() const
+{
+    if (m_addr_range.GetBaseAddress().GetSection())
+        return &m_addr_range;
+    return NULL;
+}
+
+bool
+Symbol::GetSizeIsSibling() const
+{
+    return m_size_is_sibling;
+}
+
+bool
+Symbol::GetSizeIsSynthesized() const
+{
+    return m_size_is_synthesized;
+}
+
+uint32_t
+Symbol::GetSiblingIndex() const
+{
+    return m_size_is_sibling ? m_addr_range.GetByteSize() : 0;
+}
+
+uint32_t
+Symbol::GetFlags() const
+{
+    return m_flags;
+}
+
+void
+Symbol::SetFlags (uint32_t flags)
+{
+    m_flags = flags;
+}
+
+SymbolType
+Symbol::GetType() const
+{
+    return m_type;
+}
+
+void
+Symbol::SetType(SymbolType type)
+{
+    m_type = type;
+}
+
+bool
+Symbol::IsSynthetic () const
+{
+    return m_is_synthetic;
+}
+
+void
+Symbol::SetIsSynthetic (bool b)
+{
+    m_is_synthetic = b;
+}
+
+void
+Symbol::SetSizeIsSynthesized(bool b)
+{
+    m_size_is_synthesized = b;
+}
+
+
+bool
+Symbol::IsDebug() const
+{
+    return m_is_debug;
+}
+
+void
+Symbol::SetDebug (bool b)
+{
+    m_is_debug = b;
+}
+
+bool
+Symbol::IsExternal() const
+{
+    return m_is_external;
+}
+
+void
+Symbol::SetExternal(bool b)
+{
+    m_is_external = b;
+}
+
+bool
+Symbol::IsTrampoline () const
+{
+    return m_type == eSymbolTypeTrampoline;
+}
+
+uint32_t
+Symbol::GetByteSize() const
+{
+    return m_addr_range.GetByteSize();
+}
+
+void
+Symbol::SetByteSize (uint32_t size)
+{
+    m_addr_range.SetByteSize(size);
+}
+
+void
+Symbol::SetSizeIsSibling (bool b)
+{
+    m_size_is_sibling = b;
+}
+
+void
+Symbol::Dump(Stream *s, Process *process, uint32_t index) const
+{
+//  s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+//  s->Indent();
+//  s->Printf("Symbol[%5u] %6u %c%c %-12s ",
+    s->Printf("[%5u] %6u %c%c%c %-12s ",
+              index,
+              GetID(),
+              m_is_debug ? 'D' : ' ',
+              m_is_synthetic ? 'S' : ' ',
+              m_is_external ? 'X' : ' ',
+              GetTypeAsString());
+
+    const Section *section = m_addr_range.GetBaseAddress().GetSection();
+    if (section != NULL)
+    {
+        if (!m_addr_range.GetBaseAddress().Dump(s, NULL, Address::DumpStyleFileAddress))
+            s->Printf("%*s", 18, "");
+
+        s->PutChar(' ');
+
+        if (!m_addr_range.GetBaseAddress().Dump(s, process, Address::DumpStyleLoadAddress))
+            s->Printf("%*s", 18, "");
+
+        const char *format = m_size_is_sibling ?
+                            " Sibling -> [%5llu] 0x%8.8x %s\n":
+                            " 0x%16.16llx 0x%8.8x %s\n";
+        s->Printf(  format,
+                    m_addr_range.GetByteSize(),
+                    m_flags,
+                    m_mangled.GetName().AsCString(""));
+    }
+    else
+    {
+        const char *format = m_size_is_sibling ?
+                            "0x%16.16llx                    Sibling -> [%5llu] 0x%8.8x %s\n":
+                            "0x%16.16llx                    0x%16.16llx 0x%8.8x %s\n";
+        s->Printf(  format,
+                    m_addr_range.GetBaseAddress().GetOffset(),
+                    m_addr_range.GetByteSize(),
+                    m_flags,
+                    m_mangled.GetName().AsCString(""));
+    }
+}
+
+const Mangled&
+Symbol::GetMangled() const
+{
+    return m_mangled;
+}
+
+Mangled&
+Symbol::GetMangled()
+{
+    return m_mangled;
+}
+
+Address &
+Symbol::GetValue()
+{
+    return m_addr_range.GetBaseAddress();
+}
+
+const Address &
+Symbol::GetValue() const
+{
+    return m_addr_range.GetBaseAddress();
+}
+
+void
+Symbol::SetValue (Address &value)
+{
+    m_addr_range.GetBaseAddress() = value;
+}
+
+Function *
+Symbol::GetFunction ()
+{
+    if (m_function == NULL && !m_searched_for_function)
+    {
+        m_searched_for_function = true;
+        Module *module = m_addr_range.GetBaseAddress().GetModule();
+        if (module)
+        {
+            SymbolContext sc;
+            if (module->ResolveSymbolContextForAddress(m_addr_range.GetBaseAddress(), eSymbolContextFunction, sc))
+                m_function = sc.function;
+        }
+    }
+    return m_function;
+}
+
+uint32_t
+Symbol::GetPrologueByteSize ()
+{
+    if (m_type == eSymbolTypeCode || m_type == eSymbolTypeFunction)
+    {
+        if (!m_type_data_resolved)
+        {
+            m_type_data_resolved = true;
+            Module *module = m_addr_range.GetBaseAddress().GetModule();
+            SymbolContext sc;
+            if (module && module->ResolveSymbolContextForAddress (m_addr_range.GetBaseAddress(),
+                                                                  eSymbolContextLineEntry,
+                                                                  sc))
+            {
+                m_type_data = sc.line_entry.range.GetByteSize();
+            }
+            else
+            {
+                // TODO: expose something in Process to figure out the
+                // size of a function prologue.
+            }
+        }
+        return m_type_data;
+    }
+    return 0;
+}
+
+void
+Symbol::SetValue (const AddressRange &range)
+{
+    m_addr_range = range;
+}
+
+
+void
+Symbol::SetValue(addr_t value)
+{
+    m_addr_range.GetBaseAddress().SetSection(NULL);
+    m_addr_range.GetBaseAddress().SetOffset(value);
+}
+
+
+bool
+Symbol::Compare(const ConstString& name, SymbolType type) const
+{
+    if (m_type == eSymbolTypeAny || m_type == type)
+        return m_mangled.GetMangledName() == name || m_mangled.GetDemangledName() == name;
+    return false;
+}
+
+#define ENUM_TO_CSTRING(x)  case eSymbolType##x: return #x;
+
+const char *
+Symbol::GetTypeAsString() const
+{
+    switch (m_type)
+    {
+    ENUM_TO_CSTRING(Invalid);
+    ENUM_TO_CSTRING(Absolute);
+    ENUM_TO_CSTRING(Extern);
+    ENUM_TO_CSTRING(Code);
+    ENUM_TO_CSTRING(Data);
+    ENUM_TO_CSTRING(Trampoline);
+    ENUM_TO_CSTRING(Runtime);
+    ENUM_TO_CSTRING(Exception);
+    ENUM_TO_CSTRING(SourceFile);
+    ENUM_TO_CSTRING(HeaderFile);
+    ENUM_TO_CSTRING(ObjectFile);
+    ENUM_TO_CSTRING(Function);
+    ENUM_TO_CSTRING(FunctionEnd);
+    ENUM_TO_CSTRING(CommonBlock);
+    ENUM_TO_CSTRING(Block);
+    ENUM_TO_CSTRING(Static);
+    ENUM_TO_CSTRING(Global);
+    ENUM_TO_CSTRING(Local);
+    ENUM_TO_CSTRING(Param);
+    ENUM_TO_CSTRING(Variable);
+    ENUM_TO_CSTRING(VariableType);
+    ENUM_TO_CSTRING(LineEntry);
+    ENUM_TO_CSTRING(LineHeader);
+    ENUM_TO_CSTRING(ScopeBegin);
+    ENUM_TO_CSTRING(ScopeEnd);
+    ENUM_TO_CSTRING(Additional);
+    ENUM_TO_CSTRING(Compiler);
+    ENUM_TO_CSTRING(Instrumentation);
+    ENUM_TO_CSTRING(Undefined);
+    default:
+        break;
+    }
+    return "<unknown SymbolType>";
+}
+
diff --git a/source/Symbol/SymbolContext.cpp b/source/Symbol/SymbolContext.cpp
new file mode 100644
index 0000000..0a33d5a
--- /dev/null
+++ b/source/Symbol/SymbolContext.cpp
@@ -0,0 +1,424 @@
+//===-- SymbolContext.cpp ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Symbol/SymbolVendor.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+SymbolContext::SymbolContext() :
+    target_sp   (),
+    module_sp   (),
+    comp_unit   (NULL),
+    function    (NULL),
+    block       (NULL),
+    line_entry  (),
+    symbol      (NULL)
+{
+}
+
+SymbolContext::SymbolContext(const ModuleSP& m, CompileUnit *cu, Function *f, Block *b, LineEntry *le, Symbol *s) :
+    target_sp   (),
+    module_sp   (m),
+    comp_unit   (cu),
+    function    (f),
+    block       (b),
+    line_entry  (),
+    symbol      (s)
+{
+    if (le)
+        line_entry = *le;
+}
+
+SymbolContext::SymbolContext(const TargetSP &t, const ModuleSP& m, CompileUnit *cu, Function *f, Block *b, LineEntry *le, Symbol *s) :
+    target_sp   (t),
+    module_sp   (m),
+    comp_unit   (cu),
+    function    (f),
+    block       (b),
+    line_entry  (),
+    symbol      (s)
+{
+    if (le)
+        line_entry = *le;
+}
+
+SymbolContext::SymbolContext(const SymbolContext& rhs) :
+    target_sp   (rhs.target_sp),
+    module_sp   (rhs.module_sp),
+    comp_unit   (rhs.comp_unit),
+    function    (rhs.function),
+    block       (rhs.block),
+    line_entry  (rhs.line_entry),
+    symbol      (rhs.symbol)
+{
+}
+
+
+SymbolContext::SymbolContext (SymbolContextScope *sc_scope) :
+    target_sp   (),
+    module_sp   (),
+    comp_unit   (NULL),
+    function    (NULL),
+    block       (NULL),
+    line_entry  (),
+    symbol      (NULL)
+{
+    sc_scope->CalculateSymbolContext (this);
+}
+
+const SymbolContext&
+SymbolContext::operator= (const SymbolContext& rhs)
+{
+    if (this != &rhs)
+    {
+        target_sp   = rhs.target_sp;
+        module_sp   = rhs.module_sp;
+        comp_unit   = rhs.comp_unit;
+        function    = rhs.function;
+        block       = rhs.block;
+        line_entry  = rhs.line_entry;
+        symbol      = rhs.symbol;
+    }
+    return *this;
+}
+
+void
+SymbolContext::Clear()
+{
+    target_sp.reset();
+    module_sp.reset();
+    comp_unit   = NULL;
+    function    = NULL;
+    block       = NULL;
+    line_entry.Clear();
+    symbol      = NULL;
+}
+
+void
+SymbolContext::DumpStopContext
+(
+    Stream *s,
+    ExecutionContextScope *exe_scope,
+    const Address &addr,
+    bool show_module
+) const
+{
+    Process *process = NULL;
+    if (exe_scope)
+        process = exe_scope->CalculateProcess();
+    addr_t load_addr = addr.GetLoadAddress (process);
+
+    if (show_module && module_sp)
+    {
+        *s << module_sp->GetFileSpec().GetFilename() << '`';
+    }
+
+    if (function != NULL)
+    {
+        if (function->GetMangled().GetName())
+            function->GetMangled().GetName().Dump(s);
+
+        const addr_t func_load_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress(process);
+        if (load_addr > func_load_addr)
+            s->Printf(" + %llu", load_addr - func_load_addr);
+
+        if (block != NULL)
+        {
+            s->IndentMore();
+            block->DumpStopContext(s, this);
+            s->IndentLess();
+        }
+        else
+        {
+            if (line_entry.IsValid())
+            {
+                s->PutCString(" at ");
+                if (line_entry.DumpStopContext(s))
+                    return;
+            }
+        }
+    }
+    else if (symbol != NULL)
+    {
+        symbol->GetMangled().GetName().Dump(s);
+
+        if (symbol->GetAddressRangePtr())
+        {
+            const addr_t sym_load_addr = symbol->GetAddressRangePtr()->GetBaseAddress().GetLoadAddress(process);
+            if (load_addr > sym_load_addr)
+                s->Printf(" + %llu", load_addr - sym_load_addr);
+        }
+    }
+    else
+    {
+        addr.Dump(s, exe_scope, Address::DumpStyleModuleWithFileAddress);
+    }
+}
+
+void
+SymbolContext::Dump(Stream *s, Process *process) const
+{
+    *s << (void *)this << ": ";
+    s->Indent();
+    s->PutCString("SymbolContext");
+    s->IndentMore();
+    s->EOL();
+    s->IndentMore();
+    s->Indent();
+    *s << "Module    = " << (void *)module_sp.get() << ' ';
+    if (module_sp)
+        module_sp->GetFileSpec().Dump(s);
+    s->EOL();
+    s->Indent();
+    *s << "CompileUnit  = " << (void *)comp_unit;
+    if (comp_unit != NULL)
+        *s << " {" << comp_unit->GetID() << "} " << *(dynamic_cast<FileSpec*> (comp_unit));
+    s->EOL();
+    s->Indent();
+    *s << "Function  = " << (void *)function;
+    if (function != NULL)
+    {
+        *s << " {" << function->GetID() << "} ";/// << function->GetType()->GetName();
+//      Type* func_type = function->Type();
+//      if (func_type)
+//      {
+//          s->EOL();
+//          const UserDefType* func_udt = func_type->GetUserDefinedType().get();
+//          if (func_udt)
+//          {
+//              s->IndentMore();
+//              func_udt->Dump(s, func_type);
+//              s->IndentLess();
+//          }
+//      }
+    }
+    s->EOL();
+    s->Indent();
+    *s << "Block     = " << (void *)block;
+    if (block != NULL)
+        *s << " {" << block->GetID() << '}';
+    // Dump the block and pass it a negative depth to we print all the parent blocks
+    //if (block != NULL)
+    //  block->Dump(s, function->GetFileAddress(), INT_MIN);
+    s->EOL();
+    s->Indent();
+    *s << "LineEntry = ";
+    line_entry.Dump (s, process, true, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, true);
+    s->EOL();
+    s->Indent();
+    *s << "Symbol    = " << (void *)symbol;
+    if (symbol != NULL && symbol->GetMangled())
+        *s << ' ' << symbol->GetMangled().GetName().AsCString();
+    s->EOL();
+    s->IndentLess();
+    s->IndentLess();
+}
+
+bool
+lldb_private::operator== (const SymbolContext& lhs, const SymbolContext& rhs)
+{
+    return lhs.target_sp.get() == rhs.target_sp.get() &&
+           lhs.module_sp.get() == rhs.module_sp.get() &&
+           lhs.comp_unit    == rhs.comp_unit &&
+           lhs.function     == rhs.function &&
+           LineEntry::Compare(lhs.line_entry, rhs.line_entry) == 0 &&
+           lhs.symbol       == rhs.symbol;
+}
+
+bool
+lldb_private::operator!= (const SymbolContext& lhs, const SymbolContext& rhs)
+{
+    return lhs.target_sp.get() != rhs.target_sp.get() ||
+           lhs.module_sp.get() != rhs.module_sp.get() ||
+           lhs.comp_unit    != rhs.comp_unit ||
+           lhs.function     != rhs.function ||
+           LineEntry::Compare(lhs.line_entry, rhs.line_entry) != 0 ||
+           lhs.symbol       != rhs.symbol;
+}
+
+bool
+SymbolContext::GetAddressRange (uint32_t scope, AddressRange &range) const
+{
+    if ((scope & eSymbolContextLineEntry) && line_entry.IsValid())
+    {
+        range = line_entry.range;
+        return true;
+    }
+    else if ((scope & eSymbolContextFunction) && function != NULL)
+    {
+        range = function->GetAddressRange();
+        return true;
+    }
+    else if ((scope & eSymbolContextSymbol) && symbol != NULL && symbol->GetAddressRangePtr())
+    {
+        range = *symbol->GetAddressRangePtr();
+
+        if (range.GetByteSize() == 0)
+        {
+            if (module_sp)
+            {
+                ObjectFile *objfile = module_sp->GetObjectFile();
+                if (objfile)
+                {
+                    Symtab *symtab = objfile->GetSymtab();
+                    if (symtab)
+                        range.SetByteSize(symtab->CalculateSymbolSize (symbol));
+                }
+            }
+        }
+        return true;
+    }
+    range.Clear();
+    return false;
+}
+
+
+Function *
+SymbolContext::FindFunctionByName (const char *name) const
+{
+    ConstString name_const_str (name);
+    if (function != NULL)
+    {
+        // FIXME: Look in the class of the current function, if it exists,
+        // for methods matching name.
+    }
+
+    //
+    if (comp_unit != NULL)
+    {
+        // Make sure we've read in all the functions.  We should be able to check and see
+        // if there's one by this name present before we do this...
+        module_sp->GetSymbolVendor()->ParseCompileUnitFunctions(*this);
+        uint32_t func_idx;
+        lldb::FunctionSP func_sp;
+        for (func_idx = 0; (func_sp = comp_unit->GetFunctionAtIndex(func_idx)) != NULL; ++func_idx)
+        {
+            if (func_sp->GetMangled().GetName() == name_const_str)
+                return func_sp.get();
+        }
+    }
+    if (module_sp != NULL)
+    {
+        SymbolContextList sc_matches;
+        if (module_sp->FindFunctions (name_const_str, false, sc_matches) > 0)
+        {
+            SymbolContext sc;
+            sc_matches.GetContextAtIndex (0, sc);
+            return sc.function;
+        }
+    }
+
+    if (target_sp)
+    {
+        SymbolContextList sc_matches;
+        if (target_sp->GetImages().FindFunctions (name_const_str, sc_matches) > 0)
+        {
+            SymbolContext sc;
+            sc_matches.GetContextAtIndex (0, sc);
+            return sc.function;
+        }
+    }
+
+    return NULL;
+}
+
+lldb::VariableSP
+SymbolContext::FindVariableByName (const char *name) const
+{
+    lldb::VariableSP return_value;
+    return return_value;
+}
+
+lldb::TypeSP
+SymbolContext::FindTypeByName (const char *name) const
+{
+    lldb::TypeSP return_value;
+    return return_value;
+}
+
+//----------------------------------------------------------------------
+//
+//  SymbolContextList
+//
+//----------------------------------------------------------------------
+
+
+SymbolContextList::SymbolContextList() :
+    m_symbol_contexts()
+{
+}
+
+SymbolContextList::~SymbolContextList()
+{
+}
+
+void
+SymbolContextList::Append(const SymbolContext& sc)
+{
+    m_symbol_contexts.push_back(sc);
+}
+
+void
+SymbolContextList::Clear()
+{
+    m_symbol_contexts.clear();
+}
+
+void
+SymbolContextList::Dump(Stream *s, Process *process) const
+{
+
+    *s << (void *)this << ": ";
+    s->Indent();
+    s->PutCString("SymbolContextList");
+    s->EOL();
+    s->IndentMore();
+
+    collection::const_iterator pos, end = m_symbol_contexts.end();
+    for (pos = m_symbol_contexts.begin(); pos != end; ++pos)
+    {
+        pos->Dump(s, process);
+    }
+    s->IndentLess();
+}
+
+bool
+SymbolContextList::GetContextAtIndex(uint32_t idx, SymbolContext& sc) const
+{
+    if (idx < m_symbol_contexts.size())
+    {
+        sc = m_symbol_contexts[idx];
+        return true;
+    }
+    return false;
+}
+
+bool
+SymbolContextList::RemoveContextAtIndex (uint32_t idx)
+{
+    if (idx < m_symbol_contexts.size())
+    {
+        m_symbol_contexts.erase(m_symbol_contexts.begin() + idx);
+        return true;
+    }
+    return false;
+}
+
+uint32_t
+SymbolContextList::GetSize() const
+{
+    return m_symbol_contexts.size();
+}
diff --git a/source/Symbol/SymbolFile.cpp b/source/Symbol/SymbolFile.cpp
new file mode 100644
index 0000000..edfd56d
--- /dev/null
+++ b/source/Symbol/SymbolFile.cpp
@@ -0,0 +1,50 @@
+//===-- SymbolFile.cpp ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-private.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Core/PluginManager.h"
+
+using namespace lldb_private;
+
+SymbolFile*
+SymbolFile::FindPlugin (ObjectFile* obj_file)
+{
+    std::auto_ptr<SymbolFile> best_sym_file_ap;
+    if (obj_file != NULL)
+    {
+        // TODO: Load any plug-ins in the appropriate plug-in search paths and
+        // iterate over all of them to find the best one for the job.
+
+        //----------------------------------------------------------------------
+        // We currently only have one debug symbol parser...
+        //----------------------------------------------------------------------
+        std::auto_ptr<SymbolFile> best_symfile_ap;
+        uint32_t best_symfile_abilities = 0;
+
+        SymbolFileCreateInstance create_callback;
+        for (uint32_t idx = 0; (create_callback = PluginManager::GetSymbolFileCreateCallbackAtIndex(idx)) != NULL; ++idx)
+        {
+            std::auto_ptr<SymbolFile> curr_symfile_ap(create_callback(obj_file));
+
+            if (curr_symfile_ap.get())
+            {
+                uint32_t sym_file_abilities = curr_symfile_ap->GetAbilities();
+                if (sym_file_abilities > best_symfile_abilities)
+                {
+                    best_symfile_abilities = sym_file_abilities;
+                    best_sym_file_ap = curr_symfile_ap;
+                }
+            }
+        }
+    }
+    return best_sym_file_ap.release();
+}
+
+
diff --git a/source/Symbol/SymbolVendor.mm b/source/Symbol/SymbolVendor.mm
new file mode 100644
index 0000000..5fb8b0a
--- /dev/null
+++ b/source/Symbol/SymbolVendor.mm
@@ -0,0 +1,386 @@
+//===-- SymbolVendor.mm -----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/SymbolVendor.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolFile.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+//----------------------------------------------------------------------
+// FindPlugin
+//
+// Platforms can register a callback to use when creating symbol
+// vendors to allow for complex debug information file setups, and to
+// also allow for finding separate debug information files.
+//----------------------------------------------------------------------
+SymbolVendor*
+SymbolVendor::FindPlugin (Module* module)
+{
+    std::auto_ptr<SymbolVendor> instance_ap;
+    //----------------------------------------------------------------------
+    // We currently only have one debug symbol parser...
+    //----------------------------------------------------------------------
+    SymbolVendorCreateInstance create_callback;
+    for (uint32_t idx = 0; (create_callback = PluginManager::GetSymbolVendorCreateCallbackAtIndex(idx)) != NULL; ++idx)
+    {
+        instance_ap.reset(create_callback(module));
+
+        if (instance_ap.get())
+        {
+            // TODO: make sure this symbol vendor is what we want. We
+            // currently are just returning the first one we find, but
+            // we may want to call this function only when we have our
+            // main executable module and then give all symbol vendor
+            // plug-ins a chance to compete for who wins.
+            return instance_ap.release();
+        }
+    }
+    // The default implementation just tries to create debug information using the
+    // file representation for the module.
+    instance_ap.reset(new SymbolVendor(module));
+    if (instance_ap.get())
+        instance_ap->AddSymbolFileRepresendation(module->GetObjectFile());
+    return instance_ap.release();
+}
+
+//----------------------------------------------------------------------
+// SymbolVendor constructor
+//----------------------------------------------------------------------
+SymbolVendor::SymbolVendor(Module *module) :
+    ModuleChild(module),
+    m_mutex (Mutex::eMutexTypeRecursive),
+    m_type_list(),
+    m_compile_units(),
+    m_sym_file_ap()
+{
+    ObjectFile * objfile = module->GetObjectFile();
+    ConstString target_triple;
+    if (objfile && objfile->GetTargetTriple(target_triple))
+    {
+        m_type_list.GetClangASTContext().SetTargetTriple (target_triple.AsCString());
+    }
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+SymbolVendor::~SymbolVendor()
+{
+}
+
+//----------------------------------------------------------------------
+// Add a represantion given an object file.
+//----------------------------------------------------------------------
+void
+SymbolVendor::AddSymbolFileRepresendation(ObjectFile *obj_file)
+{
+    Mutex::Locker locker(m_mutex);
+    if (obj_file != NULL)
+        m_sym_file_ap.reset(SymbolFile::FindPlugin(obj_file));
+}
+
+bool
+SymbolVendor::SetCompileUnitAtIndex
+(CompUnitSP& cu, uint32_t idx)
+{
+    Mutex::Locker locker(m_mutex);
+    const uint32_t num_compile_units = GetNumCompileUnits();
+    if (idx < num_compile_units)
+    {
+        // Fire off an assertion if this compile unit already exists for now.
+        // The partial parsing should take care of only setting the compile
+        // unit once, so if this assertion fails, we need to make sure that
+        // we don't have a race condition, or have a second parse of the same
+        // compile unit.
+        assert(m_compile_units[idx].get() == NULL);
+        m_compile_units[idx] = cu;
+        return true;
+    }
+    return false;
+}
+
+uint32_t
+SymbolVendor::GetNumCompileUnits()
+{
+    Mutex::Locker locker(m_mutex);
+    if (m_compile_units.empty())
+    {
+        if (m_sym_file_ap.get())
+        {
+            // Resize our array of compile unit shared pointers -- which will
+            // each remain NULL until someone asks for the actual compile unit
+            // information. When this happens, the symbol file will be asked
+            // to parse this compile unit information.
+            m_compile_units.resize(m_sym_file_ap->GetNumCompileUnits());
+        }
+    }
+    return m_compile_units.size();
+}
+
+size_t
+SymbolVendor::ParseCompileUnitFunctions (const SymbolContext &sc)
+{
+    Mutex::Locker locker(m_mutex);
+    if (m_sym_file_ap.get())
+        return m_sym_file_ap->ParseCompileUnitFunctions(sc);
+    return 0;
+}
+
+bool
+SymbolVendor::ParseCompileUnitLineTable (const SymbolContext &sc)
+{
+    Mutex::Locker locker(m_mutex);
+    if (m_sym_file_ap.get())
+        return m_sym_file_ap->ParseCompileUnitLineTable(sc);
+    return false;
+}
+
+bool
+SymbolVendor::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList& support_files)
+{
+    Mutex::Locker locker(m_mutex);
+    if (m_sym_file_ap.get())
+        return m_sym_file_ap->ParseCompileUnitSupportFiles(sc, support_files);
+    return false;
+}
+
+size_t
+SymbolVendor::ParseFunctionBlocks (const SymbolContext &sc)
+{
+    Mutex::Locker locker(m_mutex);
+    if (m_sym_file_ap.get())
+        return m_sym_file_ap->ParseFunctionBlocks(sc);
+    return 0;
+}
+
+size_t
+SymbolVendor::ParseTypes (const SymbolContext &sc)
+{
+    Mutex::Locker locker(m_mutex);
+    if (m_sym_file_ap.get())
+        return m_sym_file_ap->ParseTypes(sc);
+    return 0;
+}
+
+size_t
+SymbolVendor::ParseVariablesForContext (const SymbolContext& sc)
+{
+    Mutex::Locker locker(m_mutex);
+    if (m_sym_file_ap.get())
+        return m_sym_file_ap->ParseVariablesForContext(sc);
+    return 0;
+}
+
+Type*
+SymbolVendor::ResolveTypeUID(lldb::user_id_t type_uid)
+{
+    Mutex::Locker locker(m_mutex);
+    if (m_sym_file_ap.get())
+        return m_sym_file_ap->ResolveTypeUID(type_uid);
+    return NULL;
+}
+
+
+uint32_t
+SymbolVendor::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
+{
+    Mutex::Locker locker(m_mutex);
+    if (m_sym_file_ap.get())
+        return m_sym_file_ap->ResolveSymbolContext(so_addr, resolve_scope, sc);
+    return 0;
+}
+
+uint32_t
+SymbolVendor::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
+{
+    Mutex::Locker locker(m_mutex);
+    if (m_sym_file_ap.get())
+        return m_sym_file_ap->ResolveSymbolContext(file_spec, line, check_inlines, resolve_scope, sc_list);
+    return 0;
+}
+
+uint32_t
+SymbolVendor::FindGlobalVariables (const ConstString &name, bool append, uint32_t max_matches, VariableList& variables)
+{
+    Mutex::Locker locker(m_mutex);
+    if (m_sym_file_ap.get())
+        return m_sym_file_ap->FindGlobalVariables(name, append, max_matches, variables);
+    return 0;
+}
+
+uint32_t
+SymbolVendor::FindGlobalVariables (const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables)
+{
+    Mutex::Locker locker(m_mutex);
+    if (m_sym_file_ap.get())
+        return m_sym_file_ap->FindGlobalVariables(regex, append, max_matches, variables);
+    return 0;
+}
+
+uint32_t
+SymbolVendor::FindFunctions(const ConstString &name, bool append, SymbolContextList& sc_list)
+{
+    Mutex::Locker locker(m_mutex);
+    if (m_sym_file_ap.get())
+        return m_sym_file_ap->FindFunctions(name, append, sc_list);
+    return 0;
+}
+
+uint32_t
+SymbolVendor::FindFunctions(const RegularExpression& regex, bool append, SymbolContextList& sc_list)
+{
+    Mutex::Locker locker(m_mutex);
+    if (m_sym_file_ap.get())
+        return m_sym_file_ap->FindFunctions(regex, append, sc_list);
+    return 0;
+}
+
+
+
+//uint32_t
+//SymbolVendor::FindTypes(const SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, Type::Encoding encoding, const char *udt_name, TypeList& types)
+//{
+//  Mutex::Locker locker(m_mutex);
+//  if (m_sym_file_ap.get())
+//  {
+//      lldb::user_id_t udt_uid = LLDB_INVALID_UID;
+//      if (encoding == Type::user_defined_type)
+//          udt_uid = UserDefType::GetUserDefTypeUID(udt_name);
+//
+//      return m_sym_file_ap->FindTypes(sc, name, append, max_matches, encoding, udt_uid, types);
+//  }
+//  return 0;
+//}
+//
+//uint32_t
+//SymbolVendor::FindTypes(const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, Type::Encoding encoding, const char *udt_name, TypeList& types)
+//{
+//  Mutex::Locker locker(m_mutex);
+//  if (m_sym_file_ap.get())
+//  {
+//      lldb::user_id_t udt_uid = LLDB_INVALID_UID;
+//
+//      if (encoding == Type::user_defined_type)
+//          udt_uid = UserDefType::GetUserDefTypeUID(udt_name);
+//
+//      return m_sym_file_ap->FindTypes(sc, regex, append, max_matches, encoding, udt_uid, types);
+//  }
+//  return 0;
+//}
+
+void
+SymbolVendor::Dump(Stream *s)
+{
+    Mutex::Locker locker(m_mutex);
+    bool show_context = false;
+
+    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+    s->Indent();
+    s->PutCString("SymbolVendor");
+    if (m_sym_file_ap.get())
+    {
+        ObjectFile *objfile = m_sym_file_ap->GetObjectFile();
+        if (objfile)
+        {
+            const FileSpec &objfile_file_spec = objfile->GetFileSpec();
+            if (objfile_file_spec)
+            {
+                s->PutCString(" (");
+                objfile_file_spec.Dump(s);
+                s->PutChar(')');
+            }
+        }
+    }
+    s->EOL();
+    s->IndentMore();
+    m_type_list.Dump(s, show_context);
+
+    CompileUnitConstIter cu_pos, cu_end;
+    cu_end = m_compile_units.end();
+    for (cu_pos = m_compile_units.begin(); cu_pos != cu_end; ++cu_pos)
+    {
+        // We currently only dump the compile units that have been parsed
+        if (cu_pos->get())
+            (*cu_pos)->Dump(s, show_context);
+    }
+
+    s->IndentLess();
+
+}
+
+CompUnitSP
+SymbolVendor::GetCompileUnitAtIndex(uint32_t idx)
+{
+    Mutex::Locker locker(m_mutex);
+    CompUnitSP cu_sp;
+    const uint32_t num_compile_units = GetNumCompileUnits();
+    if (idx < num_compile_units)
+    {
+        cu_sp = m_compile_units[idx];
+        if (cu_sp.get() == NULL)
+        {
+            m_compile_units[idx] = m_sym_file_ap->ParseCompileUnitAtIndex(idx);
+            cu_sp = m_compile_units[idx];
+        }
+    }
+    return cu_sp;
+}
+
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+const char *
+SymbolVendor::GetPluginName()
+{
+    return "SymbolVendor";
+}
+
+const char *
+SymbolVendor::GetShortPluginName()
+{
+    return "vendor-default";
+}
+
+uint32_t
+SymbolVendor::GetPluginVersion()
+{
+    return 1;
+}
+
+void
+SymbolVendor::GetPluginCommandHelp (const char *command, Stream *strm)
+{
+}
+
+Error
+SymbolVendor::ExecutePluginCommand (Args &command, Stream *strm)
+{
+    Error error;
+    error.SetErrorString("No plug-in command are currently supported.");
+    return error;
+}
+
+Log *
+SymbolVendor::EnablePluginLogging (Stream *strm, Args &command)
+{
+    return NULL;
+}
+
+
diff --git a/source/Symbol/Symtab.cpp b/source/Symbol/Symtab.cpp
new file mode 100644
index 0000000..f1ed356
--- /dev/null
+++ b/source/Symbol/Symtab.cpp
@@ -0,0 +1,596 @@
+//===-- Symtab.cpp ----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <map>
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/Symtab.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+
+Symtab::Symtab(ObjectFile *objfile) :
+    m_objfile(objfile),
+    m_symbols(),
+    m_addr_indexes(),
+    m_name_to_index()
+{
+}
+
+Symtab::~Symtab()
+{
+}
+
+void
+Symtab::Reserve(uint32_t count)
+{
+    m_symbols.reserve (count);
+}
+
+Symbol *
+Symtab::Resize(uint32_t count)
+{
+    m_symbols.resize (count);
+    return &m_symbols[0];
+}
+
+uint32_t
+Symtab::AddSymbol(const Symbol& symbol)
+{
+    uint32_t symbol_idx = m_symbols.size();
+    m_name_to_index.Clear();
+    m_addr_indexes.clear();
+    m_symbols.push_back(symbol);
+    return symbol_idx;
+}
+
+size_t
+Symtab::GetNumSymbols() const
+{
+    return m_symbols.size();
+}
+
+void
+Symtab::Dump(Stream *s, Process *process) const
+{
+    const_iterator pos;
+    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+    s->Indent();
+    const FileSpec &file_spec = m_objfile->GetFileSpec();
+    const char * object_name = NULL;
+    if (m_objfile->GetModule())
+        object_name = m_objfile->GetModule()->GetObjectName().GetCString();
+
+    if (file_spec)
+        s->Printf("Symtab, file = %s/%s%s%s%s, num_symbols = %u:\n",
+        file_spec.GetDirectory().AsCString(),
+        file_spec.GetFilename().AsCString(),
+        object_name ? "(" : "",
+        object_name ? object_name : "",
+        object_name ? ")" : "",
+        m_symbols.size());
+    else
+        s->Printf("Symtab, num_symbols = %u:\n", m_symbols.size());
+    s->IndentMore();
+
+    if (!m_symbols.empty())
+    {
+        const_iterator begin = m_symbols.begin();
+        const_iterator end = m_symbols.end();
+        DumpSymbolHeader (s);
+        for (pos = m_symbols.begin(); pos != end; ++pos)
+        {
+            s->Indent();
+            pos->Dump(s, process, std::distance(begin, pos));
+        }
+    }
+    s->IndentLess ();
+}
+
+void
+Symtab::Dump(Stream *s, Process *process, std::vector<uint32_t>& indexes) const
+{
+    const size_t num_symbols = GetNumSymbols();
+    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+    s->Indent();
+    s->Printf("Symtab %u symbol indexes (%u symbols total):\n", indexes.size(), m_symbols.size());
+    s->IndentMore();
+
+    if (!indexes.empty())
+    {
+        std::vector<uint32_t>::const_iterator pos;
+        std::vector<uint32_t>::const_iterator end = indexes.end();
+        DumpSymbolHeader (s);
+        for (pos = indexes.begin(); pos != end; ++pos)
+        {
+            uint32_t idx = *pos;
+            if (idx < num_symbols)
+            {
+                s->Indent();
+                m_symbols[idx].Dump(s, process, idx);
+            }
+        }
+    }
+    s->IndentLess ();
+}
+
+void
+Symtab::DumpSymbolHeader (Stream *s)
+{
+    s->Indent("               Debug symbol\n");
+    s->Indent("               |Synthetic symbol\n");
+    s->Indent("               ||Externally Visible\n");
+    s->Indent("               |||\n");
+    s->Indent("Index   UserID DSX Type         File Address/Value Load Address       Size               Flags      Name\n");
+    s->Indent("------- ------ --- ------------ ------------------ ------------------ ------------------ ---------- ----------------------------------\n");
+}
+
+Symbol *
+Symtab::SymbolAtIndex(uint32_t idx)
+{
+    if (idx < m_symbols.size())
+        return &m_symbols[idx];
+    return NULL;
+}
+
+
+const Symbol *
+Symtab::SymbolAtIndex(uint32_t idx) const
+{
+    if (idx < m_symbols.size())
+        return &m_symbols[idx];
+    return NULL;
+}
+
+//----------------------------------------------------------------------
+// InitNameIndexes
+//----------------------------------------------------------------------
+void
+Symtab::InitNameIndexes()
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
+    // Create the name index vector to be able to quickly search by name
+    const size_t count = m_symbols.size();
+    assert(m_objfile != NULL);
+    assert(m_objfile->GetModule() != NULL);
+    m_name_to_index.Reserve (count);
+
+    UniqueCStringMap<uint32_t>::Entry entry;
+
+    for (entry.value = 0; entry.value < count; ++entry.value)
+    {
+        const Symbol *symbol = &m_symbols[entry.value];
+
+        // Don't let trampolines get into the lookup by name map
+        // If we ever need the trampoline symbols to be searchable by name
+        // we can remove this and then possibly add a new bool to any of the
+        // Symtab functions that lookup symbols by name to indicate if they
+        // want trampolines.
+        if (symbol->IsTrampoline())
+            continue;
+
+        const Mangled &mangled = symbol->GetMangled();
+        entry.cstring = mangled.GetMangledName().GetCString();
+        if (entry.cstring && entry.cstring[0])
+            m_name_to_index.Append (entry);
+
+        entry.cstring = mangled.GetDemangledName().GetCString();
+        if (entry.cstring && entry.cstring[0])
+            m_name_to_index.Append (entry);
+    }
+    m_name_to_index.Sort();
+}
+
+uint32_t
+Symtab::AppendSymbolIndexesWithType(SymbolType symbol_type, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const
+{
+    uint32_t prev_size = indexes.size();
+
+    const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
+
+    for (uint32_t i = start_idx; i < count; ++i)
+    {
+        if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
+            indexes.push_back(i);
+    }
+
+    return indexes.size() - prev_size;
+}
+
+struct SymbolSortInfo
+{
+    const bool sort_by_load_addr;
+    const Symbol *symbols;
+};
+
+int
+Symtab::CompareSymbolValueByIndex (void *thunk, const void *a, const void *b)
+{
+    const Symbol *symbols = (const Symbol *)thunk;
+    uint32_t index_a = *((uint32_t *) a);
+    uint32_t index_b = *((uint32_t *) b);
+
+    addr_t value_a;
+    addr_t value_b;
+    if (symbols[index_a].GetValue().GetSection() == symbols[index_b].GetValue().GetSection())
+    {
+        value_a = symbols[index_a].GetValue ().GetOffset();
+        value_b = symbols[index_b].GetValue ().GetOffset();
+    }
+    else
+    {
+        value_a = symbols[index_a].GetValue ().GetFileAddress();
+        value_b = symbols[index_b].GetValue ().GetFileAddress();
+    }
+
+    if (value_a == value_b)
+    {
+        // The if the values are equal, use the original symbol user ID
+        lldb::user_id_t uid_a = symbols[index_a].GetID();
+        lldb::user_id_t uid_b = symbols[index_b].GetID();
+        if (uid_a < uid_b)
+            return -1;
+        if (uid_a > uid_b)
+            return 1;
+        return 0;
+    }
+    else if (value_a < value_b)
+        return -1;
+
+    return 1;
+}
+
+void
+Symtab::SortSymbolIndexesByValue (std::vector<uint32_t>& indexes, bool remove_duplicates) const
+{
+    // No need to sort if we have zero or one items...
+    if (indexes.size() <= 1)
+        return;
+
+    // Sort the indexes in place using qsort
+    ::qsort_r (&indexes[0], indexes.size(), sizeof(uint32_t), (void *)&m_symbols[0], Symtab::CompareSymbolValueByIndex);
+
+    // Remove any duplicates if requested
+    if (remove_duplicates)
+        std::unique(indexes.begin(), indexes.end());
+}
+
+uint32_t
+Symtab::AppendSymbolIndexesWithName(const ConstString& symbol_name, std::vector<uint32_t>& indexes)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
+    if (symbol_name)
+    {
+        const size_t old_size = indexes.size();
+        if (m_name_to_index.IsEmpty())
+            InitNameIndexes();
+
+        const char *symbol_cstr = symbol_name.GetCString();
+        const UniqueCStringMap<uint32_t>::Entry *entry_ptr;
+        for (entry_ptr = m_name_to_index.FindFirstValueForName (symbol_cstr);
+             entry_ptr!= NULL;
+             entry_ptr = m_name_to_index.FindNextValueForName (symbol_cstr, entry_ptr))
+        {
+            indexes.push_back (entry_ptr->value);
+        }
+        return indexes.size() - old_size;
+    }
+    return 0;
+}
+
+uint32_t
+Symtab::AppendSymbolIndexesWithNameAndType(const ConstString& symbol_name, SymbolType symbol_type, std::vector<uint32_t>& indexes)
+{
+    if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0)
+    {
+        std::vector<uint32_t>::iterator pos = indexes.begin();
+        while (pos != indexes.end())
+        {
+            if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
+                ++pos;
+            else
+                indexes.erase(pos);
+        }
+    }
+    return indexes.size();
+}
+
+uint32_t
+Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, std::vector<uint32_t>& indexes)
+{
+    uint32_t prev_size = indexes.size();
+    uint32_t sym_end = m_symbols.size();
+
+    for (int i = 0; i < sym_end; i++)
+    {
+        if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
+        {
+            const char *name = m_symbols[i].GetMangled().GetName().AsCString();
+            if (name)
+            {
+                if (regexp.Execute (name))
+                    indexes.push_back(i);
+            }
+        }
+    }
+    return indexes.size() - prev_size;
+
+}
+
+Symbol *
+Symtab::FindSymbolWithType(SymbolType symbol_type, uint32_t& start_idx)
+{
+    const size_t count = m_symbols.size();
+    for (uint32_t idx = start_idx; idx < count; ++idx)
+    {
+        if (symbol_type == eSymbolTypeAny || m_symbols[idx].GetType() == symbol_type)
+        {
+            start_idx = idx;
+            return &m_symbols[idx];
+        }
+    }
+    return NULL;
+}
+
+const Symbol *
+Symtab::FindSymbolWithType(SymbolType symbol_type, uint32_t& start_idx) const
+{
+    const size_t count = m_symbols.size();
+    for (uint32_t idx = start_idx; idx < count; ++idx)
+    {
+        if (symbol_type == eSymbolTypeAny || m_symbols[idx].GetType() == symbol_type)
+        {
+            start_idx = idx;
+            return &m_symbols[idx];
+        }
+    }
+    return NULL;
+}
+
+size_t
+Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
+    // Initialize all of the lookup by name indexes before converting NAME
+    // to a uniqued string NAME_STR below.
+    if (m_name_to_index.IsEmpty())
+        InitNameIndexes();
+
+    if (name)
+    {
+        // The string table did have a string that matched, but we need
+        // to check the symbols and match the symbol_type if any was given.
+        AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_indexes);
+    }
+    return symbol_indexes.size();
+}
+
+size_t
+Symtab::FindAllSymbolsMatchingRexExAndType (const RegularExpression &regex, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes)
+{
+    AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_indexes);
+    return symbol_indexes.size();
+}
+
+Symbol *
+Symtab::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
+    if (m_name_to_index.IsEmpty())
+        InitNameIndexes();
+
+    if (name)
+    {
+        std::vector<uint32_t> matching_indexes;
+        // The string table did have a string that matched, but we need
+        // to check the symbols and match the symbol_type if any was given.
+        if (AppendSymbolIndexesWithNameAndType(name, symbol_type, matching_indexes))
+        {
+            std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end();
+            for (pos = matching_indexes.begin(); pos != end; ++pos)
+            {
+                Symbol *symbol = SymbolAtIndex(*pos);
+
+                if (symbol->Compare(name, symbol_type))
+                    return symbol;
+            }
+        }
+    }
+    return NULL;
+}
+
+typedef struct
+{
+    const Symtab *symtab;
+    const addr_t file_addr;
+    Symbol *match_symbol;
+    const uint32_t *match_index_ptr;
+    addr_t match_offset;
+} SymbolSearchInfo;
+
+static int
+SymbolWithFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
+{
+    const Symbol *curr_symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
+    if (curr_symbol == NULL)
+        return -1;
+
+    const addr_t info_file_addr = info->file_addr;
+
+    // lldb::Symbol::GetAddressRangePtr() will only return a non NULL address
+    // range if the symbol has a section!
+    const AddressRange *curr_range = curr_symbol->GetAddressRangePtr();
+    if (curr_range)
+    {
+        const addr_t curr_file_addr = curr_range->GetBaseAddress().GetFileAddress();
+        if (info_file_addr < curr_file_addr)
+            return -1;
+        if (info_file_addr > curr_file_addr)
+            return +1;
+        info->match_symbol = const_cast<Symbol *>(curr_symbol);
+        info->match_index_ptr = index_ptr;
+        return 0;
+    }
+
+    return -1;
+}
+
+static int
+SymbolWithClosestFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
+{
+    const Symbol *symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
+    if (symbol == NULL)
+        return -1;
+
+    const addr_t info_file_addr = info->file_addr;
+    const AddressRange *curr_range = symbol->GetAddressRangePtr();
+    if (curr_range)
+    {
+        const addr_t curr_file_addr = curr_range->GetBaseAddress().GetFileAddress();
+        if (info_file_addr < curr_file_addr)
+            return -1;
+
+        // Since we are finding the closest symbol that is greater than or equal
+        // to 'info->file_addr' we set the symbol here. This will get set
+        // multiple times, but after the search is done it will contain the best
+        // symbol match
+        info->match_symbol = const_cast<Symbol *>(symbol);
+        info->match_index_ptr = index_ptr;
+        info->match_offset = info_file_addr - curr_file_addr;
+
+        if (info_file_addr > curr_file_addr)
+            return +1;
+        return 0;
+    }
+    return -1;
+}
+
+static SymbolSearchInfo
+FindIndexPtrForSymbolContainingAddress(Symtab* symtab, addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
+{
+    SymbolSearchInfo info = { symtab, file_addr, NULL, NULL, 0 };
+    bsearch(&info, indexes, num_indexes, sizeof(uint32_t), (comparison_function)SymbolWithClosestFileAddress);
+    return info;
+}
+
+
+void
+Symtab::InitAddressIndexes()
+{
+    if (m_addr_indexes.empty())
+    {
+        AppendSymbolIndexesWithType (eSymbolTypeFunction, m_addr_indexes);
+        AppendSymbolIndexesWithType (eSymbolTypeGlobal, m_addr_indexes);
+        AppendSymbolIndexesWithType (eSymbolTypeStatic, m_addr_indexes);
+        AppendSymbolIndexesWithType (eSymbolTypeCode, m_addr_indexes);
+        AppendSymbolIndexesWithType (eSymbolTypeTrampoline, m_addr_indexes);
+        AppendSymbolIndexesWithType (eSymbolTypeData, m_addr_indexes);
+        SortSymbolIndexesByValue(m_addr_indexes, true);
+        m_addr_indexes.push_back(UINT32_MAX);   // Terminator for bsearch since we might need to look at the next symbol
+    }
+}
+
+size_t
+Symtab::CalculateSymbolSize (Symbol *symbol)
+{
+    // Make sure this symbol is from this symbol table...
+    if (symbol < m_symbols.data() && symbol >= m_symbols.data() + m_symbols.size())
+        return 0;
+
+    // See if this symbol already has a byte size?
+    size_t byte_size = symbol->GetByteSize();
+
+    if (byte_size)
+    {
+        // It does, just return it
+        return byte_size;
+    }
+
+    // Else if this is an address based symbol, figure out the delta between
+    // it and the next address based symbol
+    if (symbol->GetAddressRangePtr())
+    {
+        if (m_addr_indexes.empty())
+            InitAddressIndexes();
+        const size_t num_addr_indexes = m_addr_indexes.size();
+        SymbolSearchInfo info = FindIndexPtrForSymbolContainingAddress(this, symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress(), m_addr_indexes.data(), num_addr_indexes);
+        if (info.match_index_ptr != NULL)
+        {
+            const lldb::addr_t curr_file_addr = symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress();
+            // We can figure out the address range of all symbols except the
+            // last one by taking the delta between the current symbol and
+            // the next symbol
+
+            for (uint32_t addr_index = info.match_index_ptr - m_addr_indexes.data() + 1;
+                 addr_index < num_addr_indexes;
+                 ++addr_index)
+            {
+                Symbol *next_symbol = SymbolAtIndex(m_addr_indexes[addr_index]);
+                if (next_symbol == NULL)
+                    break;
+
+                assert (next_symbol->GetAddressRangePtr());
+                const lldb::addr_t next_file_addr = next_symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress();
+                if (next_file_addr > curr_file_addr)
+                {
+                    byte_size = next_file_addr - curr_file_addr;
+                    symbol->GetAddressRangePtr()->SetByteSize(byte_size);
+                    symbol->SetSizeIsSynthesized(true);
+                    break;
+                }
+            }
+        }
+    }
+    return byte_size;
+}
+
+Symbol *
+Symtab::FindSymbolWithFileAddress (addr_t file_addr)
+{
+    if (m_addr_indexes.empty())
+        InitAddressIndexes();
+
+    SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 };
+
+    uint32_t* match = (uint32_t*)bsearch(&info, &m_addr_indexes[0], m_addr_indexes.size(), sizeof(uint32_t), (comparison_function)SymbolWithFileAddress);
+    if (match)
+        return SymbolAtIndex (*match);
+    return NULL;
+}
+
+
+Symbol *
+Symtab::FindSymbolContainingFileAddress (addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
+{
+    SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 };
+
+    bsearch(&info, indexes, num_indexes, sizeof(uint32_t), (comparison_function)SymbolWithClosestFileAddress);
+
+    if (info.match_symbol)
+    {
+        if (info.match_offset < CalculateSymbolSize(info.match_symbol))
+            return info.match_symbol;
+    }
+    return NULL;
+}
+
+Symbol *
+Symtab::FindSymbolContainingFileAddress (addr_t file_addr)
+{
+    if (m_addr_indexes.empty())
+        InitAddressIndexes();
+
+    return FindSymbolContainingFileAddress (file_addr, &m_addr_indexes[0], m_addr_indexes.size());
+}
+
diff --git a/source/Symbol/Type.cpp b/source/Symbol/Type.cpp
new file mode 100644
index 0000000..9338ea2
--- /dev/null
+++ b/source/Symbol/Type.cpp
@@ -0,0 +1,1531 @@
+//===-- Type.cpp ------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Other libraries and framework includes
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/AST/RecordLayout.h"
+
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/StreamString.h"
+
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolContextScope.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/TypeList.h"
+
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+
+lldb_private::Type::Type
+(
+    lldb::user_id_t uid,
+    SymbolFile* symbol_file,
+    const ConstString &name,
+    uint64_t byte_size,
+    SymbolContextScope *context,
+    lldb::user_id_t encoding_uid,
+    EncodingUIDType encoding_uid_type,
+    const Declaration& decl,
+    void *clang_type
+) :
+    UserID (uid),
+    m_name (name),
+    m_byte_size (byte_size),
+    m_symbol_file (symbol_file),
+    m_context (context),
+    m_encoding_uid (encoding_uid),
+    m_encoding_uid_type (encoding_uid_type),
+    m_decl (decl),
+    m_clang_qual_type (clang_type)
+{
+}
+
+lldb_private::Type::Type () :
+    UserID (0),
+    m_name ("<INVALID TYPE>"),
+    m_byte_size (0),
+    m_symbol_file (NULL),
+    m_context (),
+    m_encoding_uid (0),
+    m_encoding_uid_type (eTypeInvalid),
+    m_decl (),
+    m_clang_qual_type (NULL)
+{
+}
+
+
+const lldb_private::Type&
+lldb_private::Type::operator= (const Type& rhs)
+{
+    if (this != &rhs)
+    {
+        UserID::operator= (rhs);
+        m_name = rhs.m_name;
+        m_byte_size = rhs.m_byte_size;
+        m_symbol_file = rhs.m_symbol_file;
+        m_context = rhs.m_context;
+        m_encoding_uid = rhs.m_encoding_uid;
+        m_decl = rhs.m_decl;
+        m_clang_qual_type = rhs.m_clang_qual_type;
+    }
+    return *this;
+}
+
+
+void
+lldb_private::Type::Dump (Stream *s, bool show_context)
+{
+    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+    s->Indent();
+    *s << "Type" << (const UserID&)*this << ' ';
+    if (m_name)
+        *s << ", name = \"" << m_name << "\"";
+
+    if (m_byte_size != 0)
+        s->Printf(", size = %zu", m_byte_size);
+
+    if (show_context && m_context != NULL)
+    {
+        s->PutCString(", context = ( ");
+        m_context->DumpSymbolContext(s);
+        s->PutCString(" )");
+    }
+
+    m_decl.Dump(s);
+
+    clang::QualType qual_type(clang::QualType::getFromOpaquePtr(m_clang_qual_type));
+
+    if (qual_type.getTypePtr())
+    {
+        *s << ", clang_type = ";
+
+        clang::TagType *tag_type = dyn_cast<clang::TagType>(qual_type.getTypePtr());
+        clang::TagDecl *tag_decl = NULL;
+        if (tag_type)
+            tag_decl = tag_type->getDecl();
+
+        if (tag_decl)
+        {
+            s->EOL();
+            s->EOL();
+            tag_decl->print(llvm::fouts(), 0);
+            s->EOL();
+        }
+        else
+        {
+            const clang::TypedefType *typedef_type = qual_type->getAs<clang::TypedefType>();
+            if (typedef_type)
+            {
+                const clang::TypedefDecl *typedef_decl = typedef_type->getDecl();
+                std::string clang_typedef_name (typedef_decl->getQualifiedNameAsString());
+                if (!clang_typedef_name.empty())
+                    *s << " (" << clang_typedef_name.c_str() << ')';
+            }
+            else
+            {
+                // We have a clang type, lets show it
+                TypeList *type_list = GetTypeList();
+                if (type_list)
+                {
+                    clang::ASTContext *ast_context = GetClangAST();
+                    if (ast_context)
+                    {
+                        std::string clang_type_name(qual_type.getAsString());
+                        if (!clang_type_name.empty())
+                            *s << " (" << clang_type_name.c_str() << ')';
+                    }
+                }
+            }
+        }
+    }
+    else if (m_encoding_uid != LLDB_INVALID_UID)
+    {
+        *s << ", type_uid = " << m_encoding_uid;
+        switch (m_encoding_uid_type)
+        {
+        case eIsTypeWithUID: s->PutCString(" (unresolved type)"); break;
+        case eIsConstTypeWithUID: s->PutCString(" (unresolved const type)"); break;
+        case eIsRestrictTypeWithUID: s->PutCString(" (unresolved restrict type)"); break;
+        case eIsVolatileTypeWithUID: s->PutCString(" (unresolved volatile type)"); break;
+        case eTypedefToTypeWithUID: s->PutCString(" (unresolved typedef)"); break;
+        case ePointerToTypeWithUID: s->PutCString(" (unresolved pointer)"); break;
+        case eLValueReferenceToTypeWithUID: s->PutCString(" (unresolved L value reference)"); break;
+        case eRValueReferenceToTypeWithUID: s->PutCString(" (unresolved R value reference)"); break;
+        }
+    }
+
+//
+//  if (m_access)
+//      s->Printf(", access = %u", m_access);
+    s->EOL();
+}
+
+const lldb_private::ConstString &
+lldb_private::Type::GetName()
+{
+    if (!(m_name))
+    {
+        if (ResolveClangType())
+        {
+            std::string type_name = ClangASTContext::GetTypeName (m_clang_qual_type);
+            if (!type_name.empty())
+                m_name.SetCString (type_name.c_str());
+        }
+    }
+    return m_name;
+}
+
+int
+lldb_private::Type::DumpClangTypeName(Stream *s, void *clang_type)
+{
+    clang::QualType qual_type(clang::QualType::getFromOpaquePtr(clang_type));
+    std::string type_name;
+    const clang::TypedefType *typedef_type = qual_type->getAs<clang::TypedefType>();
+    if (typedef_type)
+    {
+        const clang::TypedefDecl *typedef_decl = typedef_type->getDecl();
+        type_name = typedef_decl->getQualifiedNameAsString();
+    }
+    else
+    {
+        type_name = qual_type.getAsString();
+    }
+    if (!type_name.empty())
+        return s->Printf("(%s) ", type_name.c_str());
+    return 0;
+}
+
+lldb_private::ConstString
+lldb_private::Type::GetClangTypeName (void *clang_type)
+{
+    ConstString clang_type_name;
+    if (clang_type)
+    {
+        clang::QualType qual_type(clang::QualType::getFromOpaquePtr(clang_type));
+
+        const clang::TypedefType *typedef_type = qual_type->getAs<clang::TypedefType>();
+        if (typedef_type)
+        {
+            const clang::TypedefDecl *typedef_decl = typedef_type->getDecl();
+            std::string clang_typedef_name (typedef_decl->getQualifiedNameAsString());
+            if (!clang_typedef_name.empty())
+                clang_type_name.SetCString (clang_typedef_name.c_str());
+        }
+        else
+        {
+            std::string type_name(qual_type.getAsString());
+            if (!type_name.empty())
+                clang_type_name.SetCString (type_name.c_str());
+        }
+    }
+    else
+    {
+        clang_type_name.SetCString ("<invalid>");
+    }
+
+    return clang_type_name;
+}
+
+
+
+void
+lldb_private::Type::DumpTypeName(Stream *s)
+{
+    GetName().Dump(s, "<invalid-type-name>");
+}
+
+
+void
+lldb_private::Type::DumpValue
+(
+    lldb_private::ExecutionContext *exe_ctx,
+    lldb_private::Stream *s,
+    const lldb_private::DataExtractor &data,
+    uint32_t data_byte_offset,
+    bool show_types,
+    bool show_summary,
+    bool verbose,
+    lldb::Format format
+)
+{
+    if (ResolveClangType())
+    {
+        if (show_types)
+        {
+            s->PutChar('(');
+            if (verbose)
+                s->Printf("Type{0x%8.8x} ", GetID());
+            DumpTypeName (s);
+            s->PutCString(") ");
+        }
+
+        lldb_private::Type::DumpValue (exe_ctx,
+                                       GetClangAST (),
+                                       m_clang_qual_type,
+                                       s,
+                                       format == lldb::eFormatDefault ? GetFormat() : format,
+                                       data,
+                                       data_byte_offset,
+                                       GetByteSize(),
+                                       0, // Bitfield bit size
+                                       0, // Bitfield bit offset
+                                       show_types,
+                                       show_summary,
+                                       verbose,
+                                       0);
+    }
+}
+
+
+void
+lldb_private::Type::DumpSummary
+(
+    ExecutionContext *exe_ctx,
+    clang::ASTContext *ast_context,
+    void *clang_type,
+    Stream *s,
+    const lldb_private::DataExtractor &data,
+    uint32_t data_byte_offset,
+    size_t data_byte_size
+)
+{
+    uint32_t length = 0;
+    clang::QualType qual_type(clang::QualType::getFromOpaquePtr(clang_type));
+    if (ClangASTContext::IsCStringType (clang_type, length))
+    {
+
+        if (exe_ctx && exe_ctx->process)
+        {
+            uint32_t offset = data_byte_offset;
+            lldb::addr_t pointer_addresss = data.GetMaxU64(&offset, data_byte_size);
+            const size_t k_max_buf_size = length ? length : 256;
+            uint8_t buf[k_max_buf_size + 1];
+            lldb_private::DataExtractor data(buf, k_max_buf_size, exe_ctx->process->GetByteOrder(), 4);
+            buf[k_max_buf_size] = '\0';
+            size_t bytes_read;
+            size_t total_cstr_len = 0;
+            Error error;
+            while ((bytes_read = exe_ctx->process->ReadMemory (pointer_addresss, buf, k_max_buf_size, error)) > 0)
+            {
+                const size_t len = strlen((const char *)buf);
+                if (len == 0)
+                    break;
+                if (total_cstr_len == 0)
+                    s->PutCString (" \"");
+                data.Dump(s, 0, lldb::eFormatChar, 1, len, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
+                total_cstr_len += len;
+                if (len < k_max_buf_size)
+                    break;
+                pointer_addresss += total_cstr_len;
+            }
+            if (total_cstr_len > 0)
+                s->PutChar ('"');
+        }
+    }
+}
+
+#define DEPTH_INCREMENT 2
+void
+lldb_private::Type::DumpValue
+(
+    ExecutionContext *exe_ctx,
+    clang::ASTContext *ast_context,
+    void *clang_type,
+    Stream *s,
+    lldb::Format format,
+    const lldb_private::DataExtractor &data,
+    uint32_t data_byte_offset,
+    size_t data_byte_size,
+    uint32_t bitfield_bit_size,
+    uint32_t bitfield_bit_offset,
+    bool show_types,
+    bool show_summary,
+    bool verbose,
+    uint32_t depth
+)
+{
+    clang::QualType qual_type(clang::QualType::getFromOpaquePtr(clang_type));
+    switch (qual_type->getTypeClass())
+    {
+    case clang::Type::Record:
+        {
+            const clang::RecordType *record_type = cast<clang::RecordType>(qual_type.getTypePtr());
+            const clang::RecordDecl *record_decl = record_type->getDecl();
+            assert(record_decl);
+            uint32_t field_bit_offset = 0;
+            uint32_t field_byte_offset = 0;
+            const clang::ASTRecordLayout &record_layout = ast_context->getASTRecordLayout(record_decl);
+            uint32_t child_idx = 0;
+
+
+            const clang::CXXRecordDecl *cxx_record_decl = dyn_cast<clang::CXXRecordDecl>(record_decl);
+            if (cxx_record_decl)
+            {
+                // We might have base classes to print out first
+                clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+                for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
+                     base_class != base_class_end;
+                     ++base_class)
+                {
+                    const clang::CXXRecordDecl *base_class_decl = cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl());
+
+                    // Skip empty base classes
+                    if (verbose == false && ClangASTContext::RecordHasFields(base_class_decl) == false)
+                        continue;
+
+                    if (base_class->isVirtual())
+                        field_bit_offset = record_layout.getVBaseClassOffset(base_class_decl);
+                    else
+                        field_bit_offset = record_layout.getBaseClassOffset(base_class_decl);
+                    field_byte_offset = field_bit_offset / 8;
+                    assert (field_bit_offset % 8 == 0);
+                    if (child_idx == 0)
+                        s->PutChar('{');
+                    else
+                        s->PutChar(',');
+
+                    clang::QualType base_class_qual_type = base_class->getType();
+                    std::string base_class_type_name(base_class_qual_type.getAsString());
+
+                    // Indent and print the base class type name
+                    s->Printf("\n%*s%s ", depth + DEPTH_INCREMENT, "", base_class_type_name.c_str());
+
+                    std::pair<uint64_t, unsigned> base_class_type_info = ast_context->getTypeInfo(base_class_qual_type);
+
+                    // Dump the value of the member
+                    Type::DumpValue (
+                        exe_ctx,
+                        ast_context,                        // The clang AST context for this type
+                        base_class_qual_type.getAsOpaquePtr(),// The clang type we want to dump
+                        s,                                  // Stream to dump to
+                        Type::GetFormat(base_class_qual_type.getAsOpaquePtr()), // The format with which to display the member
+                        data,                               // Data buffer containing all bytes for this type
+                        data_byte_offset + field_byte_offset,// Offset into "data" where to grab value from
+                        base_class_type_info.first / 8,     // Size of this type in bytes
+                        0,                                  // Bitfield bit size
+                        0,                                  // Bitfield bit offset
+                        show_types,                         // Boolean indicating if we should show the variable types
+                        show_summary,                       // Boolean indicating if we should show a summary for the current type
+                        verbose,                            // Verbose output?
+                        depth + DEPTH_INCREMENT);           // Scope depth for any types that have children
+
+                    ++child_idx;
+                }
+            }
+            const unsigned num_fields = record_layout.getFieldCount();
+
+            uint32_t field_idx = 0;
+            clang::RecordDecl::field_iterator field, field_end;
+            for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx, ++child_idx)
+            {
+                // Print the starting squiggly bracket (if this is the
+                // first member) or comman (for member 2 and beyong) for
+                // the struct/union/class member.
+                if (child_idx == 0)
+                    s->PutChar('{');
+                else
+                    s->PutChar(',');
+
+                // Indent
+                s->Printf("\n%*s", depth + DEPTH_INCREMENT, "");
+
+                clang::QualType field_type = field->getType();
+                // Print the member type if requested
+                // Figure out the type byte size (field_type_info.first) and
+                // alignment (field_type_info.second) from the AST context.
+                std::pair<uint64_t, unsigned> field_type_info = ast_context->getTypeInfo(field_type);
+                assert(field_idx < num_fields);
+                // Figure out the field offset within the current struct/union/class type
+                field_bit_offset = record_layout.getFieldOffset (field_idx);
+                field_byte_offset = field_bit_offset / 8;
+                uint32_t field_bitfield_bit_size = 0;
+                uint32_t field_bitfield_bit_offset = 0;
+                if (ClangASTContext::FieldIsBitfield (ast_context, *field, field_bitfield_bit_size))
+                    field_bitfield_bit_offset = field_bit_offset % 8;
+
+                if (show_types)
+                {
+                    std::string field_type_name(field_type.getAsString());
+                    if (field_bitfield_bit_size > 0)
+                        s->Printf("(%s:%u) ", field_type_name.c_str(), field_bitfield_bit_size);
+                    else
+                        s->Printf("(%s) ", field_type_name.c_str());
+                }
+                // Print the member name and equal sign
+                s->Printf("%s = ", field->getNameAsString().c_str());
+
+
+                // Dump the value of the member
+                Type::DumpValue (
+                    exe_ctx,
+                    ast_context,                    // The clang AST context for this type
+                    field_type.getAsOpaquePtr(),    // The clang type we want to dump
+                    s,                              // Stream to dump to
+                    Type::GetFormat(field_type.getAsOpaquePtr()),   // The format with which to display the member
+                    data,                           // Data buffer containing all bytes for this type
+                    data_byte_offset + field_byte_offset,// Offset into "data" where to grab value from
+                    field_type_info.first / 8,      // Size of this type in bytes
+                    field_bitfield_bit_size,        // Bitfield bit size
+                    field_bitfield_bit_offset,      // Bitfield bit offset
+                    show_types,                     // Boolean indicating if we should show the variable types
+                    show_summary,                   // Boolean indicating if we should show a summary for the current type
+                    verbose,                        // Verbose output?
+                    depth + DEPTH_INCREMENT);       // Scope depth for any types that have children
+            }
+
+            // Indent the trailing squiggly bracket
+            if (child_idx > 0)
+                s->Printf("\n%*s}", depth, "");
+        }
+        return;
+
+    case clang::Type::Enum:
+        {
+            const clang::EnumType *enum_type = cast<clang::EnumType>(qual_type.getTypePtr());
+            const clang::EnumDecl *enum_decl = enum_type->getDecl();
+            assert(enum_decl);
+            clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos;
+            uint32_t offset = data_byte_offset;
+            const int64_t enum_value = data.GetMaxU64Bitfield(&offset, data_byte_size, bitfield_bit_size, bitfield_bit_offset);
+            for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos)
+            {
+                if (enum_pos->getInitVal() == enum_value)
+                {
+                    s->Printf("%s", enum_pos->getNameAsCString());
+                    return;
+                }
+            }
+            // If we have gotten here we didn't get find the enumerator in the
+            // enum decl, so just print the integer.
+            s->Printf("%lli", enum_value);
+        }
+        return;
+
+    case clang::Type::ConstantArray:
+        {
+            const clang::ConstantArrayType *array = cast<clang::ConstantArrayType>(qual_type.getTypePtr());
+            bool is_array_of_characters = false;
+            clang::QualType element_qual_type = array->getElementType();
+
+            clang::Type *canonical_type = element_qual_type->getCanonicalTypeInternal().getTypePtr();
+            if (canonical_type)
+                is_array_of_characters = canonical_type->isCharType();
+
+            const uint64_t element_count = array->getSize().getLimitedValue();
+
+            std::pair<uint64_t, unsigned> field_type_info = ast_context->getTypeInfo(element_qual_type);
+
+            uint32_t element_idx = 0;
+            uint32_t element_offset = 0;
+            uint64_t element_byte_size = field_type_info.first / 8;
+            uint32_t element_stride = element_byte_size;
+
+            if (is_array_of_characters)
+            {
+                s->PutChar('"');
+                data.Dump(s, data_byte_offset, lldb::eFormatChar, element_byte_size, element_count, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
+                s->PutChar('"');
+                return;
+            }
+            else
+            {
+                lldb::Format element_format = Type::GetFormat(element_qual_type.getAsOpaquePtr());
+
+                for (element_idx = 0; element_idx < element_count; ++element_idx)
+                {
+                    // Print the starting squiggly bracket (if this is the
+                    // first member) or comman (for member 2 and beyong) for
+                    // the struct/union/class member.
+                    if (element_idx == 0)
+                        s->PutChar('{');
+                    else
+                        s->PutChar(',');
+
+                    // Indent and print the index
+                    s->Printf("\n%*s[%u] ", depth + DEPTH_INCREMENT, "", element_idx);
+
+                    // Figure out the field offset within the current struct/union/class type
+                    element_offset = element_idx * element_stride;
+
+                    // Dump the value of the member
+                    Type::DumpValue (
+                        exe_ctx,
+                        ast_context,                    // The clang AST context for this type
+                        element_qual_type.getAsOpaquePtr(), // The clang type we want to dump
+                        s,                              // Stream to dump to
+                        element_format,                 // The format with which to display the element
+                        data,                           // Data buffer containing all bytes for this type
+                        data_byte_offset + element_offset,// Offset into "data" where to grab value from
+                        element_byte_size,              // Size of this type in bytes
+                        0,                              // Bitfield bit size
+                        0,                              // Bitfield bit offset
+                        show_types,                     // Boolean indicating if we should show the variable types
+                        show_summary,                   // Boolean indicating if we should show a summary for the current type
+                        verbose,                        // Verbose output?
+                        depth + DEPTH_INCREMENT);       // Scope depth for any types that have children
+                }
+
+                // Indent the trailing squiggly bracket
+                if (element_idx > 0)
+                    s->Printf("\n%*s}", depth, "");
+            }
+        }
+        return;
+
+    case clang::Type::Typedef:
+        {
+            clang::QualType typedef_qual_type = cast<clang::TypedefType>(qual_type)->LookThroughTypedefs();
+            lldb::Format typedef_format = lldb_private::Type::GetFormat(typedef_qual_type.getAsOpaquePtr());
+            std::pair<uint64_t, unsigned> typedef_type_info = ast_context->getTypeInfo(typedef_qual_type);
+            uint64_t typedef_byte_size = typedef_type_info.first / 8;
+
+            return Type::DumpValue(
+                        exe_ctx,
+                        ast_context,        // The clang AST context for this type
+                        typedef_qual_type.getAsOpaquePtr(), // The clang type we want to dump
+                        s,                  // Stream to dump to
+                        typedef_format,     // The format with which to display the element
+                        data,               // Data buffer containing all bytes for this type
+                        data_byte_offset,   // Offset into "data" where to grab value from
+                        typedef_byte_size,  // Size of this type in bytes
+                        bitfield_bit_size,  // Bitfield bit size
+                        bitfield_bit_offset,// Bitfield bit offset
+                        show_types,         // Boolean indicating if we should show the variable types
+                        show_summary,       // Boolean indicating if we should show a summary for the current type
+                        verbose,            // Verbose output?
+                        depth);             // Scope depth for any types that have children
+        }
+        break;
+
+    default:
+        // We are down the a scalar type that we just need to display.
+        data.Dump(s, data_byte_offset, format, data_byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, bitfield_bit_size, bitfield_bit_offset);
+
+        if (show_summary)
+            Type::DumpSummary (exe_ctx, ast_context, clang_type, s, data, data_byte_offset, data_byte_size);
+        break;
+    }
+}
+
+bool
+lldb_private::Type::DumpTypeValue
+(
+    Stream *s,
+    clang::ASTContext *ast_context,
+    void *clang_type,
+    lldb::Format format,
+    const lldb_private::DataExtractor &data,
+    uint32_t byte_offset,
+    size_t byte_size,
+    uint32_t bitfield_bit_size,
+    uint32_t bitfield_bit_offset
+)
+{
+    clang::QualType qual_type(clang::QualType::getFromOpaquePtr(clang_type));
+    if (ClangASTContext::IsAggregateType (clang_type))
+    {
+        return 0;
+    }
+    else
+    {
+        switch (qual_type->getTypeClass())
+        {
+        case clang::Type::Enum:
+            {
+                const clang::EnumType *enum_type = cast<clang::EnumType>(qual_type.getTypePtr());
+                const clang::EnumDecl *enum_decl = enum_type->getDecl();
+                assert(enum_decl);
+                clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos;
+                uint32_t offset = byte_offset;
+                const int64_t enum_value = data.GetMaxU64Bitfield (&offset, byte_size, bitfield_bit_size, bitfield_bit_offset);
+                for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos)
+                {
+                    if (enum_pos->getInitVal() == enum_value)
+                    {
+                        s->PutCString (enum_pos->getNameAsCString());
+                        return true;
+                    }
+                }
+                // If we have gotten here we didn't get find the enumerator in the
+                // enum decl, so just print the integer.
+
+                s->Printf("%lli", enum_value);
+                return true;
+            }
+            break;
+
+        case clang::Type::Typedef:
+            {
+                clang::QualType typedef_qual_type = cast<clang::TypedefType>(qual_type)->LookThroughTypedefs();
+                lldb::Format typedef_format = Type::GetFormat(typedef_qual_type.getAsOpaquePtr());
+                std::pair<uint64_t, unsigned> typedef_type_info = ast_context->getTypeInfo(typedef_qual_type);
+                uint64_t typedef_byte_size = typedef_type_info.first / 8;
+
+                return Type::DumpTypeValue(
+                            s,
+                            ast_context,            // The clang AST context for this type
+                            typedef_qual_type.getAsOpaquePtr(),     // The clang type we want to dump
+                            typedef_format,         // The format with which to display the element
+                            data,                   // Data buffer containing all bytes for this type
+                            byte_offset,            // Offset into "data" where to grab value from
+                            typedef_byte_size,      // Size of this type in bytes
+                            bitfield_bit_size,      // Size in bits of a bitfield value, if zero don't treat as a bitfield
+                            bitfield_bit_offset);   // Offset in bits of a bitfield value if bitfield_bit_size != 0
+            }
+            break;
+
+        default:
+            // We are down the a scalar type that we just need to display.
+            return data.Dump(s,
+                             byte_offset,
+                             format,
+                             byte_size,
+                             1,
+                             UINT32_MAX,
+                             LLDB_INVALID_ADDRESS,
+                             bitfield_bit_size,
+                             bitfield_bit_offset);
+            break;
+        }
+    }
+    return 0;
+}
+
+bool
+lldb_private::Type::GetValueAsScalar
+(
+    clang::ASTContext *ast_context,
+    void *clang_type,
+    const lldb_private::DataExtractor &data,
+    uint32_t data_byte_offset,
+    size_t data_byte_size,
+    Scalar &value
+)
+{
+    clang::QualType qual_type(clang::QualType::getFromOpaquePtr(clang_type));
+
+    if (ClangASTContext::IsAggregateType (clang_type))
+    {
+        return false;   // Aggregate types don't have scalar values
+    }
+    else
+    {
+        uint32_t count = 0;
+        lldb::Encoding encoding = Type::GetEncoding (clang_type, count);
+
+        if (encoding == lldb::eEncodingInvalid || count != 1)
+            return false;
+
+        uint64_t bit_width = ast_context->getTypeSize(qual_type);
+        uint32_t byte_size = (bit_width + 7 ) / 8;
+        uint32_t offset = data_byte_offset;
+        switch (encoding)
+        {
+        case lldb::eEncodingUint:
+            if (byte_size <= sizeof(unsigned long long))
+            {
+                uint64_t uval64 = data.GetMaxU64 (&offset, byte_size);
+                if (byte_size <= sizeof(unsigned int))
+                {
+                    value = (unsigned int)uval64;
+                    return true;
+                }
+                else if (byte_size <= sizeof(unsigned long))
+                {
+                    value = (unsigned long)uval64;
+                    return true;
+                }
+                else if (byte_size <= sizeof(unsigned long long))
+                {
+                    value = (unsigned long long )uval64;
+                    return true;
+                }
+                else
+                    value.Clear();
+            }
+            break;
+
+        case lldb::eEncodingSint:
+            if (byte_size <= sizeof(long long))
+            {
+                int64_t sval64 = (int64_t)data.GetMaxU64 (&offset, byte_size);
+                if (byte_size <= sizeof(int))
+                {
+                    value = (int)sval64;
+                    return true;
+                }
+                else if (byte_size <= sizeof(long))
+                {
+                    value = (long)sval64;
+                    return true;
+                }
+                else if (byte_size <= sizeof(long long))
+                {
+                    value = (long long )sval64;
+                    return true;
+                }
+                else
+                    value.Clear();
+            }
+            break;
+
+        case lldb::eEncodingIEEE754:
+            if (byte_size <= sizeof(long double))
+            {
+                uint32_t u32;
+                uint64_t u64;
+                if (byte_size == sizeof(float))
+                {
+                    if (sizeof(float) == sizeof(uint32_t))
+                    {
+                        u32 = data.GetU32(&offset);
+                        value = *((float *)&u32);
+                        return true;
+                    }
+                    else if (sizeof(float) == sizeof(uint64_t))
+                    {
+                        u64 = data.GetU64(&offset);
+                        value = *((float *)&u64);
+                        return true;
+                    }
+                }
+                else
+                if (byte_size == sizeof(double))
+                {
+                    if (sizeof(double) == sizeof(uint32_t))
+                    {
+                        u32 = data.GetU32(&offset);
+                        value = *((double *)&u32);
+                        return true;
+                    }
+                    else if (sizeof(double) == sizeof(uint64_t))
+                    {
+                        u64 = data.GetU64(&offset);
+                        value = *((double *)&u64);
+                        return true;
+                    }
+                }
+                else
+                if (byte_size == sizeof(long double))
+                {
+                    if (sizeof(long double) == sizeof(uint32_t))
+                    {
+                        u32 = data.GetU32(&offset);
+                        value = *((long double *)&u32);
+                        return true;
+                    }
+                    else if (sizeof(long double) == sizeof(uint64_t))
+                    {
+                        u64 = data.GetU64(&offset);
+                        value = *((long double *)&u64);
+                        return true;
+                    }
+                }
+            }
+            break;
+        }
+    }
+    return false;
+}
+
+bool
+lldb_private::Type::SetValueFromScalar
+(
+    clang::ASTContext *ast_context,
+    void *clang_type,
+    const Scalar &value,
+    Stream &strm
+)
+{
+    clang::QualType qual_type(clang::QualType::getFromOpaquePtr(clang_type));
+
+    // Aggregate types don't have scalar values
+    if (!ClangASTContext::IsAggregateType (clang_type))
+    {
+        strm.GetFlags().Set(Stream::eBinary);
+        uint32_t count = 0;
+        lldb::Encoding encoding = Type::GetEncoding (clang_type, count);
+
+        if (encoding == lldb::eEncodingInvalid || count != 1)
+            return false;
+
+        uint64_t bit_width = ast_context->getTypeSize(qual_type);
+        // This function doesn't currently handle non-byte aligned assignments
+        if ((bit_width % 8) != 0)
+            return false;
+
+        uint32_t byte_size = (bit_width + 7 ) / 8;
+        switch (encoding)
+        {
+        case lldb::eEncodingUint:
+            switch (byte_size)
+            {
+            case 1: strm.PutHex8(value.UInt()); return true;
+            case 2: strm.PutHex16(value.UInt()); return true;
+            case 4: strm.PutHex32(value.UInt()); return true;
+            case 8: strm.PutHex64(value.ULongLong()); return true;
+            default:
+                break;
+            }
+            break;
+
+        case lldb::eEncodingSint:
+            switch (byte_size)
+            {
+            case 1: strm.PutHex8(value.SInt()); return true;
+            case 2: strm.PutHex16(value.SInt()); return true;
+            case 4: strm.PutHex32(value.SInt()); return true;
+            case 8: strm.PutHex64(value.SLongLong()); return true;
+            default:
+                break;
+            }
+            break;
+
+        case lldb::eEncodingIEEE754:
+            if (byte_size <= sizeof(long double))
+            {
+                if (byte_size == sizeof(float))
+                {
+                    strm.PutFloat(value.Float());
+                    return true;
+                }
+                else
+                if (byte_size == sizeof(double))
+                {
+                    strm.PutDouble(value.Double());
+                    return true;
+                }
+                else
+                if (byte_size == sizeof(long double))
+                {
+                    strm.PutDouble(value.LongDouble());
+                    return true;
+                }
+            }
+            break;
+        }
+    }
+    return false;
+}
+
+
+uint64_t
+lldb_private::Type::GetByteSize()
+{
+    if (m_byte_size == 0)
+    {
+        switch (m_encoding_uid_type)
+        {
+        case eIsTypeWithUID:
+        case eIsConstTypeWithUID:
+        case eIsRestrictTypeWithUID:
+        case eIsVolatileTypeWithUID:
+        case eTypedefToTypeWithUID:
+            if (m_encoding_uid != LLDB_INVALID_UID)
+            {
+                Type *encoding_type = m_symbol_file->ResolveTypeUID (m_encoding_uid);
+                if (encoding_type)
+                    m_byte_size = encoding_type->GetByteSize();
+            }
+            if (m_byte_size == 0)
+            {
+                uint64_t bit_width = GetClangAST()->getTypeSize(clang::QualType::getFromOpaquePtr(GetOpaqueClangQualType()));
+                m_byte_size = (bit_width + 7 ) / 8;
+            }
+            break;
+
+        // If we are a pointer or reference, then this is just a pointer size;
+        case ePointerToTypeWithUID:
+        case eLValueReferenceToTypeWithUID:
+        case eRValueReferenceToTypeWithUID:
+            m_byte_size = GetTypeList()->GetClangASTContext().GetPointerBitSize() / 8;
+            break;
+        }
+    }
+    return m_byte_size;
+}
+
+
+uint32_t
+lldb_private::Type::GetNumChildren (bool omit_empty_base_classes)
+{
+    if (!ResolveClangType())
+        return 0;
+    return ClangASTContext::GetNumChildren (m_clang_qual_type, omit_empty_base_classes);
+
+}
+
+bool
+lldb_private::Type::IsAggregateType ()
+{
+    if (ResolveClangType())
+        return ClangASTContext::IsAggregateType (m_clang_qual_type);
+    return false;
+}
+
+lldb::Format
+lldb_private::Type::GetFormat ()
+{
+    // Make sure we resolve our type if it already hasn't been.
+    if (!ResolveClangType())
+        return lldb::eFormatInvalid;
+    return lldb_private::Type::GetFormat (m_clang_qual_type);
+}
+
+
+lldb::Format
+lldb_private::Type::GetFormat (void *clang_type)
+{
+    clang::QualType qual_type(clang::QualType::getFromOpaquePtr(clang_type));
+
+    switch (qual_type->getTypeClass())
+    {
+    case clang::Type::FunctionNoProto:
+    case clang::Type::FunctionProto:
+        break;
+
+    case clang::Type::IncompleteArray:
+    case clang::Type::VariableArray:
+        break;
+
+    case clang::Type::ConstantArray:
+        break;
+
+    case clang::Type::ExtVector:
+    case clang::Type::Vector:
+        break;
+
+    case clang::Type::Builtin:
+        switch (cast<clang::BuiltinType>(qual_type)->getKind())
+        {
+        default: assert(0 && "Unknown builtin type!");
+        case clang::BuiltinType::Void:
+            break;
+
+        case clang::BuiltinType::Bool:          return lldb::eFormatBoolean;
+        case clang::BuiltinType::Char_S:
+        case clang::BuiltinType::SChar:
+        case clang::BuiltinType::Char_U:
+        case clang::BuiltinType::UChar:
+        case clang::BuiltinType::WChar:         return lldb::eFormatChar;
+        case clang::BuiltinType::Char16:        return lldb::eFormatUnicode16;
+        case clang::BuiltinType::Char32:        return lldb::eFormatUnicode32;
+        case clang::BuiltinType::UShort:        return lldb::eFormatHex;
+        case clang::BuiltinType::Short:         return lldb::eFormatDecimal;
+        case clang::BuiltinType::UInt:          return lldb::eFormatHex;
+        case clang::BuiltinType::Int:           return lldb::eFormatDecimal;
+        case clang::BuiltinType::ULong:         return lldb::eFormatHex;
+        case clang::BuiltinType::Long:          return lldb::eFormatDecimal;
+        case clang::BuiltinType::ULongLong:     return lldb::eFormatHex;
+        case clang::BuiltinType::LongLong:      return lldb::eFormatDecimal;
+        case clang::BuiltinType::UInt128:       return lldb::eFormatHex;
+        case clang::BuiltinType::Int128:        return lldb::eFormatDecimal;
+        case clang::BuiltinType::Float:         return lldb::eFormatFloat;
+        case clang::BuiltinType::Double:        return lldb::eFormatFloat;
+        case clang::BuiltinType::LongDouble:    return lldb::eFormatFloat;
+        case clang::BuiltinType::NullPtr:       return lldb::eFormatHex;
+        }
+        break;
+    case clang::Type::ObjCObjectPointer:        return lldb::eFormatHex;
+    case clang::Type::BlockPointer:             return lldb::eFormatHex;
+    case clang::Type::Pointer:                  return lldb::eFormatHex;
+    case clang::Type::LValueReference:
+    case clang::Type::RValueReference:          return lldb::eFormatHex;
+    case clang::Type::MemberPointer:            break;
+    case clang::Type::Complex:                  return lldb::eFormatComplex;
+    case clang::Type::ObjCInterface:            break;
+    case clang::Type::Record:                   break;
+    case clang::Type::Enum:                     return lldb::eFormatEnum;
+    case clang::Type::Typedef:
+        return lldb_private::Type::GetFormat(cast<clang::TypedefType>(qual_type)->LookThroughTypedefs().getAsOpaquePtr());
+
+    case clang::Type::TypeOfExpr:
+    case clang::Type::TypeOf:
+    case clang::Type::Decltype:
+//    case clang::Type::QualifiedName:
+    case clang::Type::TemplateSpecialization:   break;
+    }
+    // We don't know hot to display this type...
+    return lldb::eFormatBytes;
+}
+
+
+lldb::Encoding
+lldb_private::Type::GetEncoding (uint32_t &count)
+{
+    // Make sure we resolve our type if it already hasn't been.
+    if (!ResolveClangType())
+        return lldb::eEncodingInvalid;
+
+    return Type::GetEncoding (m_clang_qual_type, count);
+}
+
+
+lldb::Encoding
+lldb_private::Type::GetEncoding (void *clang_type, uint32_t &count)
+{
+    count = 1;
+    clang::QualType qual_type(clang::QualType::getFromOpaquePtr(clang_type));
+
+    switch (qual_type->getTypeClass())
+    {
+    case clang::Type::FunctionNoProto:
+    case clang::Type::FunctionProto:
+        break;
+
+    case clang::Type::IncompleteArray:
+    case clang::Type::VariableArray:
+        break;
+
+    case clang::Type::ConstantArray:
+        break;
+
+    case clang::Type::ExtVector:
+    case clang::Type::Vector:
+        // TODO: Set this to more than one???
+        break;
+
+    case clang::Type::Builtin:
+        switch (cast<clang::BuiltinType>(qual_type)->getKind())
+        {
+        default: assert(0 && "Unknown builtin type!");
+        case clang::BuiltinType::Void:
+            break;
+
+        case clang::BuiltinType::Bool:
+        case clang::BuiltinType::Char_S:
+        case clang::BuiltinType::SChar:
+        case clang::BuiltinType::WChar:
+        case clang::BuiltinType::Char16:
+        case clang::BuiltinType::Char32:
+        case clang::BuiltinType::Short:
+        case clang::BuiltinType::Int:
+        case clang::BuiltinType::Long:
+        case clang::BuiltinType::LongLong:
+        case clang::BuiltinType::Int128:        return lldb::eEncodingSint;
+
+        case clang::BuiltinType::Char_U:
+        case clang::BuiltinType::UChar:
+        case clang::BuiltinType::UShort:
+        case clang::BuiltinType::UInt:
+        case clang::BuiltinType::ULong:
+        case clang::BuiltinType::ULongLong:
+        case clang::BuiltinType::UInt128:       return lldb::eEncodingUint;
+
+        case clang::BuiltinType::Float:
+        case clang::BuiltinType::Double:
+        case clang::BuiltinType::LongDouble:    return lldb::eEncodingIEEE754;
+
+        case clang::BuiltinType::NullPtr:       return lldb::eEncodingUint;
+        }
+        break;
+    // All pointer types are represented as unsigned integer encodings.
+    // We may nee to add a eEncodingPointer if we ever need to know the
+    // difference
+    case clang::Type::ObjCObjectPointer:
+    case clang::Type::BlockPointer:
+    case clang::Type::Pointer:
+    case clang::Type::LValueReference:
+    case clang::Type::RValueReference:
+    case clang::Type::MemberPointer:            return lldb::eEncodingUint;
+    // Complex numbers are made up of floats
+    case clang::Type::Complex:
+        count = 2;
+        return lldb::eEncodingIEEE754;
+
+    case clang::Type::ObjCInterface:            break;
+    case clang::Type::Record:                   break;
+    case clang::Type::Enum:                     return lldb::eEncodingSint;
+    case clang::Type::Typedef:
+        return Type::GetEncoding(cast<clang::TypedefType>(qual_type)->LookThroughTypedefs().getAsOpaquePtr(), count);
+        break;
+
+    case clang::Type::TypeOfExpr:
+    case clang::Type::TypeOf:
+    case clang::Type::Decltype:
+//    case clang::Type::QualifiedName:
+    case clang::Type::TemplateSpecialization:   break;
+    }
+    count = 0;
+    return lldb::eEncodingInvalid;
+}
+
+
+bool
+lldb_private::Type::DumpValueInMemory
+(
+    lldb_private::ExecutionContext *exe_ctx,
+    lldb_private::Stream *s,
+    lldb::addr_t address,
+    lldb::AddressType address_type,
+    bool show_types,
+    bool show_summary,
+    bool verbose
+)
+{
+    if (address != LLDB_INVALID_ADDRESS)
+    {
+        lldb_private::DataExtractor data;
+        data.SetByteOrder (exe_ctx->process->GetByteOrder());
+        if (ReadFromMemory (exe_ctx, address, address_type, data))
+        {
+            DumpValue(exe_ctx, s, data, 0, show_types, show_summary, verbose);
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+lldb_private::Type::ReadFromMemory
+(
+    lldb_private::ExecutionContext *exe_ctx,
+    clang::ASTContext *ast_context,
+    void *clang_type,
+    lldb::addr_t addr,
+    lldb::AddressType address_type,
+    lldb_private::DataExtractor &data
+)
+{
+    if (address_type == lldb::eAddressTypeFile)
+    {
+        // Can't convert a file address to anything valid without more
+        // context (which Module it came from)
+        return false;
+    }
+    clang::QualType qual_type(clang::QualType::getFromOpaquePtr(clang_type));
+
+    const uint32_t byte_size = (ast_context->getTypeSize (qual_type) + 7) / 8;
+    if (data.GetByteSize() < byte_size)
+    {
+        lldb::DataBufferSP data_sp(new DataBufferHeap (byte_size, '\0'));
+        data.SetData(data_sp);
+    }
+
+    uint8_t* dst = (uint8_t*)data.PeekData(0, byte_size);
+    if (dst != NULL)
+    {
+        if (address_type == lldb::eAddressTypeHost)
+        {
+            // The address is an address in this process, so just copy it
+            memcpy (dst, (uint8_t*)NULL + addr, byte_size);
+            return true;
+        }
+        else
+        {
+            if (exe_ctx && exe_ctx->process)
+            {
+                Error error;
+                return exe_ctx->process->ReadMemory(addr, dst, byte_size, error) == byte_size;
+            }
+        }
+    }
+    return false;
+}
+
+bool
+lldb_private::Type::WriteToMemory
+(
+    lldb_private::ExecutionContext *exe_ctx,
+    clang::ASTContext *ast_context,
+    void *clang_type,
+    lldb::addr_t addr,
+    lldb::AddressType address_type,
+    StreamString &new_value
+)
+{
+    if (address_type == lldb::eAddressTypeFile)
+    {
+        // Can't convert a file address to anything valid without more
+        // context (which Module it came from)
+        return false;
+    }
+    clang::QualType qual_type(clang::QualType::getFromOpaquePtr(clang_type));
+    const uint32_t byte_size = (ast_context->getTypeSize (qual_type) + 7) / 8;
+
+    if (byte_size > 0)
+    {
+        if (address_type == lldb::eAddressTypeHost)
+        {
+            // The address is an address in this process, so just copy it
+            memcpy ((void *)addr, new_value.GetData(), byte_size);
+            return true;
+        }
+        else
+        {
+            if (exe_ctx && exe_ctx->process)
+            {
+                Error error;
+                return exe_ctx->process->WriteMemory(addr, new_value.GetData(), byte_size, error) == byte_size;
+            }
+        }
+    }
+    return false;
+}
+
+
+bool
+lldb_private::Type::ReadFromMemory (lldb_private::ExecutionContext *exe_ctx, lldb::addr_t addr, lldb::AddressType address_type, lldb_private::DataExtractor &data)
+{
+    if (address_type == lldb::eAddressTypeFile)
+    {
+        // Can't convert a file address to anything valid without more
+        // context (which Module it came from)
+        return false;
+    }
+
+    const uint32_t byte_size = GetByteSize();
+    if (data.GetByteSize() < byte_size)
+    {
+        lldb::DataBufferSP data_sp(new DataBufferHeap (byte_size, '\0'));
+        data.SetData(data_sp);
+    }
+
+    uint8_t* dst = (uint8_t*)data.PeekData(0, byte_size);
+    if (dst != NULL)
+    {
+        if (address_type == lldb::eAddressTypeHost)
+        {
+            // The address is an address in this process, so just copy it
+            memcpy (dst, (uint8_t*)NULL + addr, byte_size);
+            return true;
+        }
+        else
+        {
+            if (exe_ctx && exe_ctx->process)
+            {
+                Error error;
+                return exe_ctx->process->ReadMemory(addr, dst, byte_size, error) == byte_size;
+            }
+        }
+    }
+    return false;
+}
+
+
+bool
+lldb_private::Type::WriteToMemory (lldb_private::ExecutionContext *exe_ctx, lldb::addr_t addr, lldb::AddressType address_type, lldb_private::DataExtractor &data)
+{
+    return false;
+}
+
+
+lldb_private::TypeList*
+lldb_private::Type::GetTypeList()
+{
+    return GetSymbolFile()->GetObjectFile()->GetModule()->GetTypeList();
+}
+
+
+bool
+lldb_private::Type::ResolveClangType()
+{
+    clang::QualType qual_type(clang::QualType::getFromOpaquePtr(m_clang_qual_type));
+    if (qual_type.getTypePtr() == NULL)
+    {
+        clang::QualType resolved_qual_type;
+        TypeList *type_list = GetTypeList();
+        if (m_encoding_uid != LLDB_INVALID_UID)
+        {
+            Type *encoding_type = m_symbol_file->ResolveTypeUID(m_encoding_uid);
+            if (encoding_type)
+            {
+
+                switch (m_encoding_uid_type)
+                {
+                case eIsTypeWithUID:
+                    resolved_qual_type = clang::QualType::getFromOpaquePtr(encoding_type->GetOpaqueClangQualType());
+                    break;
+
+                case eIsConstTypeWithUID:
+                    resolved_qual_type = clang::QualType::getFromOpaquePtr(ClangASTContext::AddConstModifier (encoding_type->GetOpaqueClangQualType()));
+                    break;
+
+                case eIsRestrictTypeWithUID:
+                    resolved_qual_type = clang::QualType::getFromOpaquePtr(ClangASTContext::AddRestrictModifier (encoding_type->GetOpaqueClangQualType()));
+                    break;
+
+                case eIsVolatileTypeWithUID:
+                    resolved_qual_type = clang::QualType::getFromOpaquePtr(ClangASTContext::AddVolatileModifier (encoding_type->GetOpaqueClangQualType()));
+                    break;
+
+                case eTypedefToTypeWithUID:
+                    resolved_qual_type = clang::QualType::getFromOpaquePtr(type_list->CreateClangTypedefType (this, encoding_type));
+                    // Clear the name so it can get fully qualified in case the
+                    // typedef is in a namespace.
+                    m_name.Clear();
+                    break;
+
+                case ePointerToTypeWithUID:
+                    resolved_qual_type = clang::QualType::getFromOpaquePtr(type_list->CreateClangPointerType (encoding_type));
+                    break;
+
+                case eLValueReferenceToTypeWithUID:
+                    resolved_qual_type = clang::QualType::getFromOpaquePtr(type_list->CreateClangLValueReferenceType (encoding_type));
+                    break;
+
+                case eRValueReferenceToTypeWithUID:
+                    resolved_qual_type = clang::QualType::getFromOpaquePtr(type_list->CreateClangRValueReferenceType (encoding_type));
+                    break;
+
+                default:
+                    assert(!"Unhandled encoding_uid_type.");
+                    break;
+                }
+            }
+        }
+        else
+        {
+            // We have no encoding type, return void?
+            void *void_clang_type = type_list->GetClangASTContext().GetVoidBuiltInType();
+            switch (m_encoding_uid_type)
+            {
+            case eIsTypeWithUID:
+                resolved_qual_type = clang::QualType::getFromOpaquePtr(void_clang_type);
+                break;
+
+            case eIsConstTypeWithUID:
+                resolved_qual_type = clang::QualType::getFromOpaquePtr (ClangASTContext::AddConstModifier (void_clang_type));
+                break;
+
+            case eIsRestrictTypeWithUID:
+                resolved_qual_type = clang::QualType::getFromOpaquePtr (ClangASTContext::AddRestrictModifier (void_clang_type));
+                break;
+
+            case eIsVolatileTypeWithUID:
+                resolved_qual_type = clang::QualType::getFromOpaquePtr (ClangASTContext::AddVolatileModifier (void_clang_type));
+                break;
+
+            case eTypedefToTypeWithUID:
+                resolved_qual_type = clang::QualType::getFromOpaquePtr(type_list->GetClangASTContext().CreateTypedefType (m_name.AsCString(), void_clang_type, NULL));
+                break;
+
+            case ePointerToTypeWithUID:
+                resolved_qual_type = clang::QualType::getFromOpaquePtr(type_list->GetClangASTContext().CreatePointerType (void_clang_type));
+                break;
+
+            case eLValueReferenceToTypeWithUID:
+                resolved_qual_type = clang::QualType::getFromOpaquePtr(type_list->GetClangASTContext().CreateLValueReferenceType (void_clang_type));
+                break;
+
+            case eRValueReferenceToTypeWithUID:
+                resolved_qual_type = clang::QualType::getFromOpaquePtr(type_list->GetClangASTContext().CreateRValueReferenceType (void_clang_type));
+                break;
+
+            default:
+                assert(!"Unhandled encoding_uid_type.");
+                break;
+            }
+        }
+        if (resolved_qual_type.getTypePtr())
+        {
+            m_clang_qual_type = resolved_qual_type.getAsOpaquePtr();
+        }
+
+    }
+    return m_clang_qual_type != NULL;
+}
+
+void *
+lldb_private::Type::GetChildClangTypeAtIndex
+(
+    const char *parent_name,
+    uint32_t idx,
+    bool transparent_pointers,
+    bool omit_empty_base_classes,
+    ConstString& name,
+    uint32_t &child_byte_size,
+    int32_t &child_byte_offset,
+    uint32_t &child_bitfield_bit_size,
+    uint32_t &child_bitfield_bit_offset
+)
+{
+    if (!ResolveClangType())
+        return false;
+
+    std::string name_str;
+    void *child_qual_type = GetClangASTContext().GetChildClangTypeAtIndex (
+            parent_name,
+            m_clang_qual_type,
+            idx,
+            transparent_pointers,
+            omit_empty_base_classes,
+            name_str,
+            child_byte_size,
+            child_byte_offset,
+            child_bitfield_bit_size,
+            child_bitfield_bit_offset);
+
+    if (child_qual_type)
+    {
+        if (!name_str.empty())
+            name.SetCString(name_str.c_str());
+        else
+            name.Clear();
+    }
+    return child_qual_type;
+}
+
+
+
+void *
+lldb_private::Type::GetOpaqueClangQualType ()
+{
+    ResolveClangType();
+    return m_clang_qual_type;
+}
+
+clang::ASTContext *
+lldb_private::Type::GetClangAST ()
+{
+    TypeList *type_list = GetTypeList();
+    if (type_list)
+        return type_list->GetClangASTContext().getASTContext();
+    return NULL;
+}
+
+lldb_private::ClangASTContext &
+lldb_private::Type::GetClangASTContext ()
+{
+    return GetTypeList()->GetClangASTContext();
+}
+
+int
+lldb_private::Type::Compare(const Type &a, const Type &b)
+{
+    // Just compare the UID values for now...
+    lldb::user_id_t a_uid = a.GetID();
+    lldb::user_id_t b_uid = b.GetID();
+    if (a_uid < b_uid)
+        return -1;
+    if (a_uid > b_uid)
+        return 1;
+    return 0;
+//  if (a.getQualType() == b.getQualType())
+//      return 0;
+}
+
diff --git a/source/Symbol/TypeList.cpp b/source/Symbol/TypeList.cpp
new file mode 100644
index 0000000..f037035
--- /dev/null
+++ b/source/Symbol/TypeList.cpp
@@ -0,0 +1,239 @@
+//===-- TypeList.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
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclGroup.h"
+
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/raw_ostream.h"
+
+// Project includes
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/TypeList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace clang;
+
+TypeList::TypeList(const char *target_triple) :
+    m_types(),
+    m_ast(target_triple)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+TypeList::~TypeList()
+{
+}
+
+//----------------------------------------------------------------------
+// Add a base type to the type list
+//----------------------------------------------------------------------
+
+//struct CampareDCTypeBaton
+//{
+//  CampareDCTypeBaton(const std::vector<TypeSP>& _types, const Type* _search_type) :
+//      types(_types),
+//      search_type(_search_type)
+//  {
+//  }
+//  const std::vector<TypeSP>& types;
+//  const Type* search_type;
+//};
+//
+//static int
+//compare_dc_type (const void *key, const void *arrmem)
+//{
+//  const Type* search_type = ((CampareDCTypeBaton*) key)->search_type;
+//  uint32_t curr_index = *(uint32_t *)arrmem;
+//  const Type* curr_type = ((CampareDCTypeBaton*) key)->types[curr_index].get();
+//  Type::CompareState state;
+//  return Type::Compare(*search_type, *curr_type, state);
+//}
+//
+//struct LessThanBinaryPredicate
+//{
+//  LessThanBinaryPredicate(const CampareDCTypeBaton& _compare_baton) :
+//      compare_baton(_compare_baton)
+//  {
+//  }
+//
+//  bool operator() (uint32_t a, uint32_t b) const
+//  {
+//      Type::CompareState state;
+//      return Type::Compare(*compare_baton.search_type, *compare_baton.types[b].get(), state) < 0;
+//  }
+//  const CampareDCTypeBaton& compare_baton;
+//};
+
+TypeSP
+TypeList::InsertUnique(TypeSP& type_sp)
+{
+#if 0
+//  Stream s(stdout);
+//  s << "TypeList::InsertUnique for type ";
+//  type_sp->Dump(s);
+//  s << "Current list:\n";
+//  Dump(s);
+
+    CampareDCTypeBaton compare_baton(m_types, type_sp.get());
+    uint32_t* match_index_ptr = (uint32_t*)bsearch(&compare_baton, &m_sorted_indexes[0], m_sorted_indexes.size(), sizeof(uint32_t), compare_dc_type);
+    if (match_index_ptr)
+    {
+//      s << "returning existing type: " << (void *)m_types[*match_index_ptr].get() << "\n";
+        return m_types[*match_index_ptr];
+    }
+
+    // Get the new index within the m_types array before we add the new type
+    uint32_t uniqued_type_index = m_types.size();
+    // Add the new shared pointer to our type by appending it to the end of the types array
+    m_types.push_back(type_sp);
+    // Figure out what the sorted index of this new type should be
+    uint32_t fake_index = 0;
+    LessThanBinaryPredicate compare_func_obj(compare_baton);
+    std::vector<uint32_t>::iterator insert_pos = std::upper_bound(m_sorted_indexes.begin(), m_sorted_indexes.end(), fake_index, compare_func_obj);
+    // Insert the sorted index into our sorted index array
+    m_sorted_indexes.insert(insert_pos, uniqued_type_index);
+#else
+    // Just push each type on the back for now. We will worry about uniquing later
+    m_types.push_back (type_sp);
+#endif
+//  s << "New list:\n";
+//  Dump(s);
+
+    return type_sp;
+}
+
+//----------------------------------------------------------------------
+// Find a base type by its unique ID.
+//----------------------------------------------------------------------
+TypeSP
+TypeList::FindType(lldb::user_id_t uid)
+{
+    TypeSP type_sp;
+    iterator pos, end;
+    for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
+        if ((*pos)->GetID() == uid)
+            return *pos;
+
+    return type_sp;
+}
+
+//----------------------------------------------------------------------
+// Find a type by name.
+//----------------------------------------------------------------------
+TypeList
+TypeList::FindTypes(const ConstString &name)
+{
+    TypeList types(m_ast.getTargetInfo()->getTriple().getTriple().c_str());
+    iterator pos, end;
+    for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
+        if ((*pos)->GetName() == name)
+            types.InsertUnique(*pos);
+    return types;
+}
+
+void
+TypeList::Clear()
+{
+    m_types.clear();
+}
+
+uint32_t
+TypeList::GetSize() const
+{
+    return m_types.size();
+}
+
+TypeSP
+TypeList::GetTypeAtIndex(uint32_t idx)
+{
+    TypeSP type_sp;
+    if (idx < m_types.size())
+        type_sp = m_types[idx];
+    return type_sp;
+}
+
+void
+TypeList::Dump(Stream *s, bool show_context)
+{
+//  std::vector<uint32_t>::const_iterator pos, end;
+//  for (pos = end = m_sorted_indexes.begin(), end = m_sorted_indexes.end(); pos != end; ++pos)
+//  {
+//      m_types[*pos]->Dump(s, show_context);
+//  }
+
+    m_ast.getASTContext()->getTranslationUnitDecl()->print(llvm::fouts(), 0);
+    const size_t num_types = m_types.size();
+    for (size_t i=0; i<num_types; ++i)
+    {
+        m_types[i]->Dump(s, show_context);
+    }
+//  ASTContext *ast_context = GetClangASTContext ().getASTContext();
+//  if (ast_context)
+//      ast_context->PrintStats();
+}
+
+
+ClangASTContext &
+TypeList::GetClangASTContext ()
+{
+    return m_ast;
+}
+
+void *
+TypeList::CreateClangPointerType (Type *type)
+{
+    assert(type);
+    return m_ast.CreatePointerType(type->GetOpaqueClangQualType());
+}
+
+void *
+TypeList::CreateClangTypedefType (Type *typedef_type, Type *base_type)
+{
+    assert(typedef_type && base_type);
+    return m_ast.CreateTypedefType(typedef_type->GetName().AsCString(), base_type->GetOpaqueClangQualType(), typedef_type->GetSymbolFile()->GetClangDeclContextForTypeUID(typedef_type->GetID()));
+}
+
+void *
+TypeList::CreateClangLValueReferenceType (Type *type)
+{
+    assert(type);
+    return m_ast.CreateLValueReferenceType(type->GetOpaqueClangQualType());
+}
+
+void *
+TypeList::CreateClangRValueReferenceType (Type *type)
+{
+    assert(type);
+    return m_ast.CreateRValueReferenceType (type->GetOpaqueClangQualType());
+}
+
+
+
diff --git a/source/Symbol/Variable.cpp b/source/Symbol/Variable.cpp
new file mode 100644
index 0000000..35dcabf
--- /dev/null
+++ b/source/Symbol/Variable.cpp
@@ -0,0 +1,167 @@
+//===-- Variable.cpp --------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/Variable.h"
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Variable constructor
+//----------------------------------------------------------------------
+Variable::Variable(lldb::user_id_t uid,
+                       const ConstString& name,
+                       Type *type,
+                       ValueType scope,
+                       SymbolContextScope *context,
+                       Declaration* decl_ptr,
+                       const DWARFExpression& location,
+                       bool external,
+                       bool artificial) :
+    UserID(uid),
+    m_name(name),
+    m_type(type),
+    m_scope(scope),
+    m_context(context),
+    m_declaration(decl_ptr),
+    m_location(location),
+    m_external(external),
+    m_artificial(artificial)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+Variable::~Variable()
+{
+}
+
+
+void
+Variable::Dump(Stream *s, bool show_context) const
+{
+    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+    s->Indent();
+    *s << "Variable" << (const UserID&)*this;
+
+    if (m_name)
+        *s << ", name = \"" << m_name << "\"";
+
+    if (m_type != NULL)
+    {
+        *s << ", type = " << (void*)m_type << " (";
+        m_type->DumpTypeName(s);
+        s->PutChar(')');
+    }
+
+    if (m_scope != eValueTypeInvalid)
+    {
+        s->PutCString(", scope = ");
+        switch (m_scope)
+        {
+        case eValueTypeVariableGlobal:       s->PutCString(m_external ? "global" : "static"); break;
+        case eValueTypeVariableArgument:    s->PutCString("parameter"); break;
+        case eValueTypeVariableLocal:        s->PutCString("local"); break;
+        default:            *s << "??? (" << m_scope << ')';
+        }
+    }
+
+    if (show_context && m_context != NULL)
+    {
+        s->PutCString(", context = ( ");
+        m_context->DumpSymbolContext(s);
+        s->PutCString(" )");
+    }
+
+    m_declaration.Dump(s);
+
+    if (m_location.IsValid())
+    {
+        s->PutCString(", location = ");
+        m_location.GetDescription(s, lldb::eDescriptionLevelBrief);
+    }
+
+    if (m_external)
+        s->PutCString(", external");
+
+    if (m_artificial)
+        s->PutCString(", artificial");
+
+    s->EOL();
+}
+
+
+size_t
+Variable::MemorySize() const
+{
+    return sizeof(Variable);
+}
+
+
+void
+Variable::CalculateSymbolContext (SymbolContext *sc)
+{
+    if (m_context)
+        m_context->CalculateSymbolContext(sc);
+    else
+        sc->Clear();
+}
+
+
+bool
+Variable::IsInScope (StackFrame *frame)
+{
+    switch (m_scope)
+    {
+    case eValueTypeVariableGlobal:
+        // Globals and statics are always in scope.
+        return true;
+
+    case eValueTypeVariableArgument:
+    case eValueTypeVariableLocal:
+        // Check if the location has a location list that describes the value
+        // of the variable with address ranges and different locations for each
+        // address range?
+        if (m_location.IsLocationList())
+        {
+            // It is a location list. We just need to tell if the location
+            // list contains the current address when converted to a load
+            // address
+            return m_location.LocationListContainsLoadAddress (&frame->GetThread().GetProcess(), frame->GetPC());
+        }
+        else
+        {
+            // We don't have a location list, we just need to see if the block
+            // that this variable was defined in is currently
+            Block *frame_block = frame->GetSymbolContext(eSymbolContextBlock).block;
+            if (frame_block)
+            {
+                SymbolContext variable_sc;
+                CalculateSymbolContext (&variable_sc);
+                if (variable_sc.function && variable_sc.block)
+                    return variable_sc.block->ContainsBlockWithID (frame_block->GetID());
+            }
+        }
+        break;
+
+    default:
+        break;
+    }
+    return false;
+}
+
diff --git a/source/Symbol/VariableList.cpp b/source/Symbol/VariableList.cpp
new file mode 100644
index 0000000..7f864f2
--- /dev/null
+++ b/source/Symbol/VariableList.cpp
@@ -0,0 +1,116 @@
+//===-- VariableList.cpp ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/CompileUnit.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// VariableList constructor
+//----------------------------------------------------------------------
+VariableList::VariableList() :
+    m_variables()
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+VariableList::~VariableList()
+{
+}
+
+
+void
+VariableList::AddVariable(VariableSP &variable_sp)
+{
+    m_variables.push_back(variable_sp);
+}
+
+
+void
+VariableList::AddVariables(VariableList *variable_list)
+{
+    std::copy(  variable_list->m_variables.begin(), // source begin
+                variable_list->m_variables.end(),   // source end
+                back_inserter(m_variables));        // destination
+}
+
+
+void
+VariableList::Clear()
+{
+    m_variables.clear();
+}
+
+
+
+VariableSP
+VariableList::GetVariableAtIndex(uint32_t idx)
+{
+    VariableSP variable_sp;
+    if (idx < m_variables.size())
+        variable_sp = m_variables[idx];
+    return variable_sp;
+}
+
+
+
+VariableSP
+VariableList::FindVariable(const ConstString& name)
+{
+    VariableSP var_sp;
+    iterator pos, end = m_variables.end();
+    for (pos = m_variables.begin(); pos != end; ++pos)
+    {
+        if ((*pos)->GetName() == name)
+        {
+            var_sp = (*pos);
+            break;
+        }
+    }
+    return var_sp;
+}
+
+
+size_t
+VariableList::MemorySize() const
+{
+    size_t mem_size = sizeof(VariableList);
+    const_iterator pos, end = m_variables.end();
+    for (pos = m_variables.begin(); pos != end; ++pos)
+        mem_size += (*pos)->MemorySize();
+    return mem_size;
+}
+
+size_t
+VariableList::GetSize() const
+{
+    return m_variables.size();
+}
+
+
+void
+VariableList::Dump(Stream *s, bool show_context) const
+{
+//  s.Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+//  s.Indent();
+//  s << "VariableList\n";
+
+    const_iterator pos, end = m_variables.end();
+    for (pos = m_variables.begin(); pos != end; ++pos)
+    {
+        (*pos)->Dump(s, show_context);
+    }
+}
+
diff --git a/source/Target/ABI.cpp b/source/Target/ABI.cpp
new file mode 100644
index 0000000..20d35e3
--- /dev/null
+++ b/source/Target/ABI.cpp
@@ -0,0 +1,47 @@
+//===-- ABI.cpp -------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/ABI.h"
+#include "lldb/Core/PluginManager.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+ABI*
+ABI::FindPlugin (const ConstString &triple)
+{
+    std::auto_ptr<ABI> abi_ap;
+    ABICreateInstance create_callback;
+
+    for (uint32_t idx = 0;
+         (create_callback = PluginManager::GetABICreateCallbackAtIndex(idx)) != NULL;
+         ++idx)
+    {
+        abi_ap.reset (create_callback(triple));
+
+        if (abi_ap.get())
+            return abi_ap.release();
+    }
+
+    return NULL;
+}
+
+//----------------------------------------------------------------------
+// Constructor
+//----------------------------------------------------------------------
+ABI::ABI()
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ABI::~ABI()
+{
+}
diff --git a/source/Target/ExecutionContext.cpp b/source/Target/ExecutionContext.cpp
new file mode 100644
index 0000000..e79f8c2
--- /dev/null
+++ b/source/Target/ExecutionContext.cpp
@@ -0,0 +1,107 @@
+//===-- ExecutionContext.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//
+
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/ExecutionContextScope.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb_private;
+
+ExecutionContext::ExecutionContext() :
+    target (NULL),
+    process (NULL),
+    thread (NULL),
+    frame (NULL)
+{
+}
+
+ExecutionContext::ExecutionContext (Target* t, bool fill_current_process_thread_frame) :
+    target (t),
+    process (NULL),
+    thread (NULL),
+    frame (NULL)
+{
+    if (t && fill_current_process_thread_frame)
+    {
+        process = t->GetProcessSP().get();
+        if (process)
+        {
+            thread = process->GetThreadList().GetCurrentThread().get();
+            if (thread)
+                frame = thread->GetCurrentFrame().get();
+        }
+    }
+}
+
+ExecutionContext::ExecutionContext(Process* p, Thread *t, StackFrame *f) :
+    target (p ? &p->GetTarget() : NULL),
+    process (p),
+    thread (t),
+    frame (f)
+{
+}
+
+ExecutionContext::ExecutionContext (ExecutionContextScope *exe_scope_ptr)
+{
+    if (exe_scope_ptr)
+        exe_scope_ptr->Calculate (*this);
+    else
+    {
+        target  = NULL;
+        process = NULL;
+        thread  = NULL;
+        frame   = NULL;
+    }
+}
+
+ExecutionContext::ExecutionContext (ExecutionContextScope &exe_scope_ref)
+{
+    exe_scope_ref.Calculate (*this);
+}
+
+void
+ExecutionContext::Clear()
+{
+    target  = NULL;
+    process = NULL;
+    thread  = NULL;
+    frame   = NULL;
+}
+
+
+RegisterContext *
+ExecutionContext::GetRegisterContext () const
+{
+    if (frame)
+        return frame->GetRegisterContext();
+    else if (thread)
+        return thread->GetRegisterContext();
+    return NULL;
+}
+
+ExecutionContextScope *
+ExecutionContext::GetBestExecutionContextScope () const
+{
+    if (frame)
+        return frame;
+    if (thread)
+        return thread;
+    if (process)
+        return process;
+    return target;
+}
diff --git a/source/Target/ObjCObjectPrinter.cpp b/source/Target/ObjCObjectPrinter.cpp
new file mode 100644
index 0000000..81c73aa
--- /dev/null
+++ b/source/Target/ObjCObjectPrinter.cpp
@@ -0,0 +1,120 @@
+//===-- ObjCObjectPrinter.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
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/StreamString.h"
+#include "lldb/Expression/ClangFunction.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "ObjCObjectPrinter.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// ObjCObjectPrinter constructor
+//----------------------------------------------------------------------
+ObjCObjectPrinter::ObjCObjectPrinter (Process &process) :
+    m_process(process)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ObjCObjectPrinter::~ObjCObjectPrinter ()
+{
+}
+
+bool
+ObjCObjectPrinter::PrintObject (ConstString &str, Value &object_ptr, ExecutionContext &exe_ctx)
+{
+    if (!exe_ctx.process)
+        return false;
+    
+    const Address *function_address = GetPrintForDebuggerAddr();
+
+    if (!function_address)
+        return false;
+    
+    const char *target_triple = exe_ctx.process->GetTargetTriple().GetCString();
+    ClangASTContext *ast_context = exe_ctx.target->GetScratchClangASTContext();
+    
+    void *return_qualtype = ast_context->GetCStringType(true);
+    Value ret;
+    ret.SetContext(Value::eContextTypeOpaqueClangQualType, return_qualtype);
+    
+    ValueList arg_value_list;
+    arg_value_list.PushValue(object_ptr);
+    
+    ClangFunction func(target_triple, ast_context, return_qualtype, *function_address, arg_value_list);
+    StreamString error_stream;
+    
+    lldb::addr_t wrapper_struct_addr = LLDB_INVALID_ADDRESS;
+    func.InsertFunction(exe_ctx, wrapper_struct_addr, error_stream);
+    // FIXME: Check result of ExecuteFunction.
+    func.ExecuteFunction(exe_ctx, &wrapper_struct_addr, error_stream, true, 1000, true, ret);
+        
+    addr_t result_ptr = ret.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
+    
+    // poor man's strcpy
+    
+    size_t len = 0;
+    bool keep_reading = true;
+    Error error;
+    while (keep_reading)
+    {
+        char byte;
+        
+        if (exe_ctx.process->ReadMemory(result_ptr + len, &byte, 1, error) != 1)
+            return false;
+        
+        if (byte == '\0')
+            keep_reading = false;
+        else
+            ++len;
+    }
+    
+    char desc[len + 1];
+    
+    if (exe_ctx.process->ReadMemory(result_ptr, &desc[0], len + 1, error) != len + 1)
+        return false;
+    
+    str.SetCString(desc);
+    
+    return true;
+}
+
+Address *
+ObjCObjectPrinter::GetPrintForDebuggerAddr()
+{
+    if (!m_PrintForDebugger_addr.get())
+    {
+        ModuleList &modules = m_process.GetTarget().GetImages();
+        
+        SymbolContextList contexts;
+        SymbolContext context;
+        
+        if((!modules.FindSymbolsWithNameAndType(ConstString ("_NSPrintForDebugger"), eSymbolTypeCode, contexts)) &&
+           (!modules.FindSymbolsWithNameAndType(ConstString ("_CFPrintForDebugger"), eSymbolTypeCode, contexts)))
+            return NULL;
+        
+        contexts.GetContextAtIndex(0, context);
+        
+        m_PrintForDebugger_addr.reset(new Address(context.symbol->GetValue()));
+    }
+    
+    return m_PrintForDebugger_addr.get();
+}
+
diff --git a/source/Target/PathMappingList.cpp b/source/Target/PathMappingList.cpp
new file mode 100644
index 0000000..02ca067
--- /dev/null
+++ b/source/Target/PathMappingList.cpp
@@ -0,0 +1,125 @@
+//===-- PathMappingList.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
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+// Project includes
+#include "PathMappingList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// PathMappingList constructor
+//----------------------------------------------------------------------
+PathMappingList::PathMappingList 
+(
+    ChangedCallback callback,
+    void *callback_baton
+) :
+    m_pairs (),
+    m_callback (callback),
+    m_callback_baton (callback_baton)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+PathMappingList::~PathMappingList ()
+{
+}
+
+void
+PathMappingList::Append (const ConstString &path,
+                         const ConstString &replacement,
+                         bool notify)
+{
+    m_pairs.push_back(pair(path, replacement));
+    if (notify && m_callback)
+        m_callback (*this, m_callback_baton);
+}
+
+void
+PathMappingList::Insert (const ConstString &path,
+                         const ConstString &replacement,
+                         uint32_t index,
+                         bool notify)
+{
+    iterator insert_iter;
+    if (index >= m_pairs.size())
+        insert_iter = m_pairs.end();
+    else
+        insert_iter = m_pairs.begin() + index;
+    m_pairs.insert(insert_iter, pair(path, replacement));
+    if (notify && m_callback)
+        m_callback (*this, m_callback_baton);
+}
+
+bool
+PathMappingList::Remove (off_t index, bool notify)
+{
+    if (index >= m_pairs.size())
+        return false;
+
+    iterator iter = m_pairs.begin() + index;
+    m_pairs.erase(iter);
+    if (notify && m_callback)
+        m_callback (*this, m_callback_baton);
+    return true;
+}
+
+void
+PathMappingList::Dump (Stream *s)
+{
+    unsigned int numPairs = m_pairs.size();
+    unsigned int index;
+
+    for (index = 0; index < numPairs; ++index)
+    {
+        s->Printf("[%d] \"%s\" -> \"%s\"\n",
+                  index, m_pairs[index].first.GetCString(), m_pairs[index].second.GetCString());
+    }
+}
+
+void
+PathMappingList::Clear (bool notify)
+{
+    m_pairs.clear();
+    if (notify && m_callback)
+        m_callback (*this, m_callback_baton);
+}
+
+size_t
+PathMappingList::GetSize ()
+{
+    return m_pairs.size();
+}
+
+bool
+PathMappingList::RemapPath (const ConstString &path, ConstString &new_path)
+{
+    const_iterator pos, end = m_pairs.end();
+    for (pos = m_pairs.begin(); pos != end; ++pos)
+    {
+        const size_t prefixLen = pos->first.GetLength();
+
+        if (::strncmp (pos->first.GetCString(), path.GetCString(), prefixLen) == 0)
+        {
+            std::string new_path_str (pos->second.GetCString());
+            new_path_str.append(path.GetCString() + prefixLen);
+            new_path.SetCString(new_path_str.c_str());
+            return true;
+        }
+    }
+    return false;
+}
diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp
new file mode 100644
index 0000000..9a6ab0c
--- /dev/null
+++ b/source/Target/Process.cpp
@@ -0,0 +1,1876 @@
+//===-- Process.cpp ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/Process.h"
+
+#include "lldb/lldb-private-log.h"
+
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Event.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/State.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Target/ABI.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/TargetList.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+Process*
+Process::FindPlugin (Target &target, const char *plugin_name, Listener &listener)
+{
+    ProcessCreateInstance create_callback = NULL;
+    if (plugin_name)
+    {
+        create_callback  = PluginManager::GetProcessCreateCallbackForPluginName (plugin_name);
+        if (create_callback)
+        {
+            std::auto_ptr<Process> debugger_ap(create_callback(target, listener));
+            if (debugger_ap->CanDebug(target))
+                return debugger_ap.release();
+        }
+    }
+    else
+    {
+        for (uint32_t idx = 0; create_callback = PluginManager::GetProcessCreateCallbackAtIndex(idx); ++idx)
+        {
+            create_callback = PluginManager::GetProcessCreateCallbackAtIndex (idx);
+            if (create_callback)
+            {
+                std::auto_ptr<Process> debugger_ap(create_callback(target, listener));
+                if (debugger_ap->CanDebug(target))
+                    return debugger_ap.release();
+            }
+        }
+    }
+    return NULL;
+}
+
+
+//----------------------------------------------------------------------
+// Process constructor
+//----------------------------------------------------------------------
+Process::Process(Target &target, Listener &listener) :
+    UserID (LLDB_INVALID_PROCESS_ID),
+    Broadcaster ("Process"),
+    m_target (target),
+    m_section_load_info (),
+    m_public_state (eStateUnloaded),
+    m_private_state (eStateUnloaded),
+    m_private_state_broadcaster ("lldb.process.internal_state_broadcaster"),
+    m_private_state_control_broadcaster ("lldb.process.internal_state_control_broadcaster"),
+    m_private_state_listener ("lldb.process.internal_state_listener"),
+    m_private_state_control_wait(),
+    m_private_state_thread (LLDB_INVALID_HOST_THREAD),
+    m_stop_id (0),
+    m_thread_index_id (0),
+    m_exit_status (-1),
+    m_exit_string (),
+    m_thread_list (this),
+    m_notifications (),
+    m_listener(listener),
+    m_unix_signals (),
+    m_objc_object_printer(*this)
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT);
+    if (log)
+        log->Printf ("%p Process::Process()", this);
+
+    listener.StartListeningForEvents (this,
+                                      eBroadcastBitStateChanged |
+                                      eBroadcastBitInterrupt |
+                                      eBroadcastBitSTDOUT |
+                                      eBroadcastBitSTDERR);
+
+    m_private_state_listener.StartListeningForEvents(&m_private_state_broadcaster,
+                                                     eBroadcastBitStateChanged);
+
+    m_private_state_listener.StartListeningForEvents(&m_private_state_control_broadcaster,
+                                                     eBroadcastInternalStateControlStop |
+                                                     eBroadcastInternalStateControlPause |
+                                                     eBroadcastInternalStateControlResume);
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+Process::~Process()
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT);
+    if (log)
+        log->Printf ("%p Process::~Process()", this);
+    StopPrivateStateThread();
+}
+
+void
+Process::Finalize()
+{
+    // Do any cleanup needed prior to being destructed... Subclasses
+    // that override this method should call this superclass method as well.
+}
+
+void
+Process::RegisterNotificationCallbacks (const Notifications& callbacks)
+{
+    m_notifications.push_back(callbacks);
+    if (callbacks.initialize != NULL)
+        callbacks.initialize (callbacks.baton, this);
+}
+
+bool
+Process::UnregisterNotificationCallbacks(const Notifications& callbacks)
+{
+    std::vector<Notifications>::iterator pos, end = m_notifications.end();
+    for (pos = m_notifications.begin(); pos != end; ++pos)
+    {
+        if (pos->baton == callbacks.baton &&
+            pos->initialize == callbacks.initialize &&
+            pos->process_state_changed == callbacks.process_state_changed)
+        {
+            m_notifications.erase(pos);
+            return true;
+        }
+    }
+    return false;
+}
+
+void
+Process::SynchronouslyNotifyStateChanged (StateType state)
+{
+    std::vector<Notifications>::iterator notification_pos, notification_end = m_notifications.end();
+    for (notification_pos = m_notifications.begin(); notification_pos != notification_end; ++notification_pos)
+    {
+        if (notification_pos->process_state_changed)
+            notification_pos->process_state_changed (notification_pos->baton, this, state);
+    }
+}
+
+// FIXME: We need to do some work on events before the general Listener sees them.
+// For instance if we are continuing from a breakpoint, we need to ensure that we do
+// the little "insert real insn, step & stop" trick.  But we can't do that when the
+// event is delivered by the broadcaster - since that is done on the thread that is
+// waiting for new events, so if we needed more than one event for our handling, we would
+// stall.  So instead we do it when we fetch the event off of the queue.
+//
+
+StateType
+Process::GetNextEvent (EventSP &event_sp)
+{
+    StateType state = eStateInvalid;
+
+    if (m_listener.GetNextEventForBroadcaster (this, event_sp) && event_sp)
+        state = Process::ProcessEventData::GetStateFromEvent (event_sp.get());
+
+    return state;
+}
+
+
+StateType
+Process::WaitForProcessToStop (const TimeValue *timeout)
+{
+    StateType match_states[] = { eStateStopped, eStateCrashed, eStateDetached, eStateExited, eStateUnloaded };
+    return WaitForState (timeout, match_states, sizeof(match_states) / sizeof(StateType));
+}
+
+
+StateType
+Process::WaitForState
+(
+    const TimeValue *timeout,
+    const StateType *match_states, const uint32_t num_match_states
+)
+{
+    EventSP event_sp;
+    uint32_t i;
+    StateType state = eStateUnloaded;
+    while (state != eStateInvalid)
+    {
+        state = WaitForStateChangedEvents (timeout, event_sp);
+
+        for (i=0; i<num_match_states; ++i)
+        {
+            if (match_states[i] == state)
+                return state;
+        }
+    }
+    return state;
+}
+
+StateType
+Process::WaitForStateChangedEvents (const TimeValue *timeout, EventSP &event_sp)
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
+
+    if (log)
+        log->Printf ("Process::%s (timeout = %p, event_sp)...", __FUNCTION__, timeout);
+
+    StateType state = eStateInvalid;
+    if (m_listener.WaitForEventForBroadcasterWithType(timeout,
+                                                      this,
+                                                      eBroadcastBitStateChanged,
+                                                      event_sp))
+        state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+
+    if (log)
+        log->Printf ("Process::%s (timeout = %p, event_sp) => %s",
+                     __FUNCTION__,
+                     timeout,
+                     StateAsCString(state));
+    return state;
+}
+
+Event *
+Process::PeekAtStateChangedEvents ()
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
+
+    if (log)
+        log->Printf ("Process::%s...", __FUNCTION__);
+
+    Event *event_ptr;
+    event_ptr = m_listener.PeekAtNextEventForBroadcasterWithType(this,
+                                                      eBroadcastBitStateChanged);
+    if (log)
+    {
+        if (event_ptr)
+        {
+            log->Printf ("Process::%s (event_ptr) => %s",
+                         __FUNCTION__,
+                         StateAsCString(ProcessEventData::GetStateFromEvent (event_ptr)));
+        }
+        else 
+        {
+            log->Printf ("Process::%s no events found",
+                         __FUNCTION__);
+        }
+    }
+    return event_ptr;
+}
+
+StateType
+Process::WaitForStateChangedEventsPrivate (const TimeValue *timeout, EventSP &event_sp)
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
+
+    if (log)
+        log->Printf ("Process::%s (timeout = %p, event_sp)...", __FUNCTION__, timeout);
+
+    StateType state = eStateInvalid;
+    if (m_private_state_listener.WaitForEventForBroadcasterWithType(timeout,
+                                                                    &m_private_state_broadcaster,
+                                                                    eBroadcastBitStateChanged,
+                                                                    event_sp))
+        state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+
+    // This is a bit of a hack, but when we wait here we could very well return
+    // to the command-line, and that could disable the log, which would render the
+    // log we got above invalid.
+    log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
+    if (log)
+        log->Printf ("Process::%s (timeout = %p, event_sp) => %s", __FUNCTION__, timeout, StateAsCString(state));
+    return state;
+}
+
+bool
+Process::WaitForEventsPrivate (const TimeValue *timeout, EventSP &event_sp, bool control_only)
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
+
+    if (log)
+        log->Printf ("Process::%s (timeout = %p, event_sp)...", __FUNCTION__, timeout);
+
+    if (control_only)
+        return m_private_state_listener.WaitForEventForBroadcaster(timeout, &m_private_state_control_broadcaster, event_sp);
+    else
+        return m_private_state_listener.WaitForEvent(timeout, event_sp);
+}
+
+bool
+Process::IsRunning () const
+{
+    return StateIsRunningState (m_public_state.GetValue());
+}
+
+int
+Process::GetExitStatus ()
+{
+    if (m_public_state.GetValue() == eStateExited)
+        return m_exit_status;
+    return -1;
+}
+
+const char *
+Process::GetExitDescription ()
+{
+    if (m_public_state.GetValue() == eStateExited && !m_exit_string.empty())
+        return m_exit_string.c_str();
+    return NULL;
+}
+
+void
+Process::SetExitStatus (int status, const char *cstr)
+{
+    m_exit_status = status;
+    if (cstr)
+        m_exit_string = cstr;
+    else
+        m_exit_string.clear();
+
+    SetPrivateState (eStateExited);
+}
+
+// This static callback can be used to watch for local child processes on
+// the current host. The the child process exits, the process will be
+// found in the global target list (we want to be completely sure that the
+// lldb_private::Process doesn't go away before we can deliver the signal.
+bool
+Process::SetProcessExitStatus
+(
+    void *callback_baton,
+    lldb::pid_t pid,
+    int signo,      // Zero for no signal
+    int exit_status      // Exit value of process if signal is zero
+)
+{
+    if (signo == 0 || exit_status)
+    {
+        TargetSP target_sp(Debugger::GetSharedInstance().GetTargetList().FindTargetWithProcessID (pid));
+        if (target_sp)
+        {
+            ProcessSP process_sp (target_sp->GetProcessSP());
+            if (process_sp)
+            {
+                const char *signal_cstr = NULL;
+                if (signo)
+                    signal_cstr = process_sp->GetUnixSignals().GetSignalAsCString (signo);
+
+                process_sp->SetExitStatus (exit_status, signal_cstr);
+            }
+        }
+        return true;
+    }
+    return false;
+}
+
+
+uint32_t
+Process::GetNextThreadIndexID ()
+{
+    return ++m_thread_index_id;
+}
+
+StateType
+Process::GetState()
+{
+    // If any other threads access this we will need a mutex for it
+    return m_public_state.GetValue ();
+}
+
+void
+Process::SetPublicState (StateType new_state)
+{
+    Log *log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STATE);
+    if (log)
+        log->Printf("Process::SetPublicState (%s)", StateAsCString(new_state));
+    m_public_state.SetValue (new_state);
+}
+
+StateType
+Process::GetPrivateState ()
+{
+    return m_private_state.GetValue();
+}
+
+void
+Process::SetPrivateState (StateType new_state)
+{
+    Log *log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STATE);
+    bool state_changed = false;
+
+    if (log)
+        log->Printf("Process::SetPrivateState (%s)", StateAsCString(new_state));
+
+    Mutex::Locker locker(m_private_state.GetMutex());
+
+    const StateType old_state = m_private_state.GetValueNoLock ();
+    state_changed = old_state != new_state;
+    if (state_changed)
+    {
+        m_private_state.SetValueNoLock (new_state);
+        if (StateIsStoppedState(new_state))
+        {
+            m_stop_id++;
+            if (log)
+                log->Printf("Process::SetPrivateState (%s) stop_id = %u", StateAsCString(new_state), m_stop_id);
+        }
+        // Use our target to get a shared pointer to ourselves...
+        m_private_state_broadcaster.BroadcastEvent (eBroadcastBitStateChanged, new ProcessEventData (GetTarget().GetProcessSP(), new_state));
+    }
+    else
+    {
+        if (log)
+            log->Printf("Process::SetPrivateState (%s) state didn't change. Ignoring...", StateAsCString(new_state), StateAsCString(old_state));
+    }
+}
+
+
+uint32_t
+Process::GetStopID() const
+{
+    return m_stop_id;
+}
+
+addr_t
+Process::GetImageInfoAddress()
+{
+    return LLDB_INVALID_ADDRESS;
+}
+
+DynamicLoader *
+Process::GetDynamicLoader()
+{
+    return NULL;
+}
+
+const ABI *
+Process::GetABI()
+{
+    ConstString& triple = m_target_triple;
+
+    if (triple.IsEmpty())
+        return NULL;
+
+    if (m_abi_sp.get() == NULL)
+    {
+        m_abi_sp.reset(ABI::FindPlugin(triple));
+    }
+
+    return m_abi_sp.get();
+}
+
+BreakpointSiteList &
+Process::GetBreakpointSiteList()
+{
+    return m_breakpoint_site_list;
+}
+
+const BreakpointSiteList &
+Process::GetBreakpointSiteList() const
+{
+    return m_breakpoint_site_list;
+}
+
+
+void
+Process::DisableAllBreakpointSites ()
+{
+    m_breakpoint_site_list.SetEnabledForAll (false);
+}
+
+Error
+Process::ClearBreakpointSiteByID (lldb::user_id_t break_id)
+{
+    Error error (DisableBreakpointSiteByID (break_id));
+    
+    if (error.Success())
+        m_breakpoint_site_list.Remove(break_id);
+
+    return error;
+}
+
+Error
+Process::DisableBreakpointSiteByID (lldb::user_id_t break_id)
+{
+    Error error;
+    BreakpointSiteSP bp_site_sp = m_breakpoint_site_list.FindByID (break_id);
+    if (bp_site_sp)
+    {
+        if (bp_site_sp->IsEnabled())
+            error = DisableBreakpoint (bp_site_sp.get());
+    }
+    else
+    {
+        error.SetErrorStringWithFormat("invalid breakpoint site ID: %i", break_id);
+    }
+
+    return error;
+}
+
+Error
+Process::EnableBreakpointSiteByID (lldb::user_id_t break_id)
+{
+    Error error;
+    BreakpointSiteSP bp_site_sp = m_breakpoint_site_list.FindByID (break_id);
+    if (bp_site_sp)
+    {
+        if (!bp_site_sp->IsEnabled())
+            error = EnableBreakpoint (bp_site_sp.get());
+    }
+    else
+    {
+        error.SetErrorStringWithFormat("invalid breakpoint site ID: %i", break_id);
+    }
+    return error;
+}
+
+lldb::user_id_t
+Process::CreateBreakpointSite (BreakpointLocationSP &owner, bool use_hardware)
+{
+    const addr_t load_addr = owner->GetAddress().GetLoadAddress (this);
+    if (load_addr != LLDB_INVALID_ADDRESS)
+    {
+        BreakpointSiteSP bp_site_sp;
+
+        // Look up this breakpoint site.  If it exists, then add this new owner, otherwise
+        // create a new breakpoint site and add it.
+
+        bp_site_sp = m_breakpoint_site_list.FindByAddress (load_addr);
+
+        if (bp_site_sp)
+        {
+            bp_site_sp->AddOwner (owner);
+            owner->SetBreakpointSite (bp_site_sp);
+            return bp_site_sp->GetID();
+        }
+        else
+        {
+            bp_site_sp.reset (new BreakpointSite (&m_breakpoint_site_list, owner, load_addr, LLDB_INVALID_THREAD_ID, use_hardware));
+            if (bp_site_sp)
+            {
+                if (EnableBreakpoint (bp_site_sp.get()).Success())
+                {
+                    owner->SetBreakpointSite (bp_site_sp);
+                    return m_breakpoint_site_list.Add (bp_site_sp);
+                }
+            }
+        }
+    }
+    // We failed to enable the breakpoint
+    return LLDB_INVALID_BREAK_ID;
+
+}
+
+void
+Process::RemoveOwnerFromBreakpointSite (lldb::user_id_t owner_id, lldb::user_id_t owner_loc_id, BreakpointSiteSP &bp_site_sp)
+{
+    uint32_t num_owners = bp_site_sp->RemoveOwner (owner_id, owner_loc_id);
+    if (num_owners == 0)
+    {
+        DisableBreakpoint(bp_site_sp.get());
+        m_breakpoint_site_list.RemoveByAddress(bp_site_sp->GetLoadAddress());
+    }
+}
+
+
+size_t
+Process::RemoveBreakpointOpcodesFromBuffer (addr_t bp_addr, size_t size, uint8_t *buf) const
+{
+    size_t bytes_removed = 0;
+    addr_t intersect_addr;
+    size_t intersect_size;
+    size_t opcode_offset;
+    size_t idx;
+    BreakpointSiteSP bp;
+
+    for (idx = 0; (bp = m_breakpoint_site_list.GetByIndex(idx)) != NULL; ++idx)
+    {
+        if (bp->GetType() == BreakpointSite::eSoftware)
+        {
+            if (bp->IntersectsRange(bp_addr, size, &intersect_addr, &intersect_size, &opcode_offset))
+            {
+                assert(bp_addr <= intersect_addr && intersect_addr < bp_addr + size);
+                assert(bp_addr < intersect_addr + intersect_size && intersect_addr + intersect_size <= bp_addr + size);
+                assert(opcode_offset + intersect_size <= bp->GetByteSize());
+                size_t buf_offset = intersect_addr - bp_addr;
+                ::memcpy(buf + buf_offset, bp->GetSavedOpcodeBytes() + opcode_offset, intersect_size);
+            }
+        }
+    }
+    return bytes_removed;
+}
+
+
+Error
+Process::EnableSoftwareBreakpoint (BreakpointSite *bp_site)
+{
+    Error error;
+    assert (bp_site != NULL);
+    Log *log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+    const addr_t bp_addr = bp_site->GetLoadAddress();
+    if (log)
+        log->Printf ("Process::EnableSoftwareBreakpoint (site_id = %d) addr = 0x%llx", bp_site->GetID(), (uint64_t)bp_addr);
+    if (bp_site->IsEnabled())
+    {
+        if (log)
+            log->Printf ("Process::EnableSoftwareBreakpoint (site_id = %d) addr = 0x%llx -- already enabled", bp_site->GetID(), (uint64_t)bp_addr);
+        return error;
+    }
+
+    if (bp_addr == LLDB_INVALID_ADDRESS)
+    {
+        error.SetErrorString("BreakpointSite contains an invalid load address.");
+        return error;
+    }
+    // Ask the lldb::Process subclass to fill in the correct software breakpoint
+    // trap for the breakpoint site
+    const size_t bp_opcode_size = GetSoftwareBreakpointTrapOpcode(bp_site);
+
+    if (bp_opcode_size == 0)
+    {
+        error.SetErrorStringWithFormat ("Process::GetSoftwareBreakpointTrapOpcode() returned zero, unable to get breakpoint trap for address 0x%llx.\n", bp_addr);
+    }
+    else
+    {
+        const uint8_t * const bp_opcode_bytes = bp_site->GetTrapOpcodeBytes();
+
+        if (bp_opcode_bytes == NULL)
+        {
+            error.SetErrorString ("BreakpointSite doesn't contain a valid breakpoint trap opcode.");
+            return error;
+        }
+
+        // Save the original opcode by reading it
+        if (DoReadMemory(bp_addr, bp_site->GetSavedOpcodeBytes(), bp_opcode_size, error) == bp_opcode_size)
+        {
+            // Write a software breakpoint in place of the original opcode
+            if (DoWriteMemory(bp_addr, bp_opcode_bytes, bp_opcode_size, error) == bp_opcode_size)
+            {
+                uint8_t verify_bp_opcode_bytes[64];
+                if (DoReadMemory(bp_addr, verify_bp_opcode_bytes, bp_opcode_size, error) == bp_opcode_size)
+                {
+                    if (::memcmp(bp_opcode_bytes, verify_bp_opcode_bytes, bp_opcode_size) == 0)
+                    {
+                        bp_site->SetEnabled(true);
+                        bp_site->SetType (BreakpointSite::eSoftware);
+                        if (log)
+                            log->Printf ("Process::EnableSoftwareBreakpoint (site_id = %d) addr = 0x%llx -- SUCCESS",
+                                         bp_site->GetID(),
+                                         (uint64_t)bp_addr);
+                    }
+                    else
+                        error.SetErrorString("Failed to verify the breakpoint trap in memory.");
+                }
+                else
+                    error.SetErrorString("Unable to read memory to verify breakpoint trap.");
+            }
+            else
+                error.SetErrorString("Unable to write breakpoint trap to memory.");
+        }
+        else
+            error.SetErrorString("Unable to read memory at breakpoint address.");
+    }
+    if (log)
+        log->Printf ("Process::EnableSoftwareBreakpoint (site_id = %d) addr = 0x%llx -- FAILED: %s",
+                     bp_site->GetID(),
+                     (uint64_t)bp_addr,
+                     error.AsCString());
+    return error;
+}
+
+Error
+Process::DisableSoftwareBreakpoint (BreakpointSite *bp_site)
+{
+    Error error;
+    assert (bp_site != NULL);
+    Log *log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+    addr_t bp_addr = bp_site->GetLoadAddress();
+    lldb::user_id_t breakID = bp_site->GetID();
+    if (log)
+        log->Printf ("ProcessMacOSX::DisableBreakpoint (breakID = %d) addr = 0x%llx", breakID, (uint64_t)bp_addr);
+
+    if (bp_site->IsHardware())
+    {
+        error.SetErrorString("Breakpoint site is a hardware breakpoint.");
+    }
+    else if (bp_site->IsEnabled())
+    {
+        const size_t break_op_size = bp_site->GetByteSize();
+        const uint8_t * const break_op = bp_site->GetTrapOpcodeBytes();
+        if (break_op_size > 0)
+        {
+            // Clear a software breakoint instruction
+            uint8_t curr_break_op[break_op_size];
+            bool break_op_found = false;
+
+            // Read the breakpoint opcode
+            if (DoReadMemory (bp_addr, curr_break_op, break_op_size, error) == break_op_size)
+            {
+                bool verify = false;
+                // Make sure we have the a breakpoint opcode exists at this address
+                if (::memcmp (curr_break_op, break_op, break_op_size) == 0)
+                {
+                    break_op_found = true;
+                    // We found a valid breakpoint opcode at this address, now restore
+                    // the saved opcode.
+                    if (DoWriteMemory (bp_addr, bp_site->GetSavedOpcodeBytes(), break_op_size, error) == break_op_size)
+                    {
+                        verify = true;
+                    }
+                    else
+                        error.SetErrorString("Memory write failed when restoring original opcode.");
+                }
+                else
+                {
+                    error.SetErrorString("Original breakpoint trap is no longer in memory.");
+                    // Set verify to true and so we can check if the original opcode has already been restored
+                    verify = true;
+                }
+
+                if (verify)
+                {
+                    uint8_t verify_opcode[break_op_size];
+                    // Verify that our original opcode made it back to the inferior
+                    if (DoReadMemory (bp_addr, verify_opcode, break_op_size, error) == break_op_size)
+                    {
+                        // compare the memory we just read with the original opcode
+                        if (::memcmp (bp_site->GetSavedOpcodeBytes(), verify_opcode, break_op_size) == 0)
+                        {
+                            // SUCCESS
+                            bp_site->SetEnabled(false);
+                            if (log)
+                                log->Printf ("Process::DisableSoftwareBreakpoint (site_id = %d) addr = 0x%llx -- SUCCESS", bp_site->GetID(), (uint64_t)bp_addr);
+                            return error;
+                        }
+                        else
+                        {
+                            if (break_op_found)
+                                error.SetErrorString("Failed to restore original opcode.");
+                        }
+                    }
+                    else
+                        error.SetErrorString("Failed to read memory to verify that breakpoint trap was restored.");
+                }
+            }
+            else
+                error.SetErrorString("Unable to read memory that should contain the breakpoint trap.");
+        }
+    }
+    else
+    {
+        if (log)
+            log->Printf ("Process::DisableSoftwareBreakpoint (site_id = %d) addr = 0x%llx -- already disabled", bp_site->GetID(), (uint64_t)bp_addr);
+        return error;
+    }
+
+    if (log)
+        log->Printf ("Process::DisableSoftwareBreakpoint (site_id = %d) addr = 0x%llx -- FAILED: %s",
+                     bp_site->GetID(),
+                     (uint64_t)bp_addr,
+                     error.AsCString());
+    return error;
+
+}
+
+
+size_t
+Process::ReadMemory (addr_t addr, void *buf, size_t size, Error &error)
+{
+    if (buf == NULL || size == 0)
+        return 0;
+
+    size_t bytes_read = 0;
+    uint8_t *bytes = (uint8_t *)buf;
+    
+    while (bytes_read < size)
+    {
+        const size_t curr_size = size - bytes_read;
+        const size_t curr_bytes_read = DoReadMemory (addr + bytes_read, 
+                                                     bytes + bytes_read, 
+                                                     curr_size,
+                                                     error);
+        bytes_read += curr_bytes_read;
+        if (curr_bytes_read == curr_size || curr_bytes_read == 0)
+            break;
+    }
+
+    // Replace any software breakpoint opcodes that fall into this range back
+    // into "buf" before we return
+    if (bytes_read > 0)
+        RemoveBreakpointOpcodesFromBuffer (addr, bytes_read, (uint8_t *)buf);
+    return bytes_read;
+}
+
+size_t
+Process::WriteMemoryPrivate (addr_t addr, const void *buf, size_t size, Error &error)
+{
+    size_t bytes_written = 0;
+    const uint8_t *bytes = (const uint8_t *)buf;
+    
+    while (bytes_written < size)
+    {
+        const size_t curr_size = size - bytes_written;
+        const size_t curr_bytes_written = DoWriteMemory (addr + bytes_written, 
+                                                         bytes + bytes_written, 
+                                                         curr_size,
+                                                         error);
+        bytes_written += curr_bytes_written;
+        if (curr_bytes_written == curr_size || curr_bytes_written == 0)
+            break;
+    }
+    return bytes_written;
+}
+
+size_t
+Process::WriteMemory (addr_t addr, const void *buf, size_t size, Error &error)
+{
+    if (buf == NULL || size == 0)
+        return 0;
+    // We need to write any data that would go where any current software traps
+    // (enabled software breakpoints) any software traps (breakpoints) that we
+    // may have placed in our tasks memory.
+
+    BreakpointSiteList::collection::const_iterator iter = m_breakpoint_site_list.GetMap()->lower_bound (addr);
+    BreakpointSiteList::collection::const_iterator end =  m_breakpoint_site_list.GetMap()->end();
+
+    if (iter == end || iter->second->GetLoadAddress() > addr + size)
+        return DoWriteMemory(addr, buf, size, error);
+
+    BreakpointSiteList::collection::const_iterator pos;
+    size_t bytes_written = 0;
+    addr_t intersect_addr;
+    size_t intersect_size;
+    size_t opcode_offset;
+    const uint8_t *ubuf = (const uint8_t *)buf;
+
+    for (pos = iter; pos != end; ++pos)
+    {
+        BreakpointSiteSP bp;
+        bp = pos->second;
+
+        assert(bp->IntersectsRange(addr, size, &intersect_addr, &intersect_size, &opcode_offset));
+        assert(addr <= intersect_addr && intersect_addr < addr + size);
+        assert(addr < intersect_addr + intersect_size && intersect_addr + intersect_size <= addr + size);
+        assert(opcode_offset + intersect_size <= bp->GetByteSize());
+
+        // Check for bytes before this breakpoint
+        const addr_t curr_addr = addr + bytes_written;
+        if (intersect_addr > curr_addr)
+        {
+            // There are some bytes before this breakpoint that we need to
+            // just write to memory
+            size_t curr_size = intersect_addr - curr_addr;
+            size_t curr_bytes_written = WriteMemoryPrivate (curr_addr, 
+                                                            ubuf + bytes_written, 
+                                                            curr_size, 
+                                                            error);
+            bytes_written += curr_bytes_written;
+            if (curr_bytes_written != curr_size)
+            {
+                // We weren't able to write all of the requested bytes, we
+                // are done looping and will return the number of bytes that
+                // we have written so far.
+                break;
+            }
+        }
+
+        // Now write any bytes that would cover up any software breakpoints
+        // directly into the breakpoint opcode buffer
+        ::memcpy(bp->GetSavedOpcodeBytes() + opcode_offset, ubuf + bytes_written, intersect_size);
+        bytes_written += intersect_size;
+    }
+
+    // Write any remaining bytes after the last breakpoint if we have any left
+    if (bytes_written < size)
+        bytes_written += WriteMemoryPrivate (addr + bytes_written, 
+                                             ubuf + bytes_written, 
+                                             size - bytes_written, 
+                                             error);
+    
+    return bytes_written;
+}
+
+addr_t
+Process::AllocateMemory(size_t size, uint32_t permissions, Error &error)
+{
+    // Fixme: we should track the blocks we've allocated, and clean them up...
+    // We could even do our own allocator here if that ends up being more efficient.
+    return DoAllocateMemory (size, permissions, error);
+}
+
+Error
+Process::DeallocateMemory (addr_t ptr)
+{
+    return DoDeallocateMemory (ptr);
+}
+
+
+Error
+Process::EnableWatchpoint (WatchpointLocation *watchpoint)
+{
+    Error error;
+    error.SetErrorString("watchpoints are not supported");
+    return error;
+}
+
+Error
+Process::DisableWatchpoint (WatchpointLocation *watchpoint)
+{
+    Error error;
+    error.SetErrorString("watchpoints are not supported");
+    return error;
+}
+
+StateType
+Process::WaitForProcessStopPrivate (const TimeValue *timeout, EventSP &event_sp)
+{
+    StateType state;
+    // Now wait for the process to launch and return control to us, and then
+    // call DidLaunch:
+    while (1)
+    {
+        // FIXME: Might want to put a timeout in here:
+        state = WaitForStateChangedEventsPrivate (NULL, event_sp);
+        if (state == eStateStopped || state == eStateCrashed || state == eStateExited)
+            break;
+        else
+            HandlePrivateEvent (event_sp);
+    }
+    return state;
+}
+
+Error
+Process::Launch
+(
+    char const *argv[],
+    char const *envp[],
+    const char *stdin_path,
+    const char *stdout_path,
+    const char *stderr_path
+)
+{
+    Error error;
+    m_target_triple.Clear();
+    m_abi_sp.reset();
+
+    Module *exe_module = m_target.GetExecutableModule().get();
+    if (exe_module)
+    {
+        char exec_file_path[PATH_MAX];
+        exe_module->GetFileSpec().GetPath(exec_file_path, sizeof(exec_file_path));
+        if (exe_module->GetFileSpec().Exists())
+        {
+            error = WillLaunch (exe_module);
+            if (error.Success())
+            {
+                // The args coming in should not contain the application name, the
+                // lldb_private::Process class will add this in case the executable
+                // gets resolved to a different file than was given on the command
+                // line (like when an applicaiton bundle is specified and will
+                // resolve to the contained exectuable file, or the file given was
+                // a symlink or other file system link that resolves to a different
+                // file).
+
+                // Get the resolved exectuable path
+
+                // Make a new argument vector
+                std::vector<const char *> exec_path_plus_argv;
+                // Append the resolved executable path
+                exec_path_plus_argv.push_back (exec_file_path);
+
+                // Push all args if there are any
+                if (argv)
+                {
+                    for (int i = 0; argv[i]; ++i)
+                        exec_path_plus_argv.push_back(argv[i]);
+                }
+
+                // Push a NULL to terminate the args.
+                exec_path_plus_argv.push_back(NULL);
+
+                // Now launch using these arguments.
+                error = DoLaunch (exe_module, exec_path_plus_argv.data(), envp, stdin_path, stdout_path, stderr_path);
+
+                if (error.Fail())
+                {
+                    if (GetID() != LLDB_INVALID_PROCESS_ID)
+                    {
+                        SetID (LLDB_INVALID_PROCESS_ID);
+                        const char *error_string = error.AsCString();
+                        if (error_string == NULL)
+                            error_string = "launch failed";
+                        SetExitStatus (-1, error_string);
+                    }
+                }
+                else
+                {
+                    EventSP event_sp;
+                    StateType state = WaitForProcessStopPrivate(NULL, event_sp);
+
+                    if (state == eStateStopped || state == eStateCrashed)
+                    {
+                        DidLaunch ();
+
+                        // This delays passing the stopped event to listeners till DidLaunch gets
+                        // a chance to complete...
+                        HandlePrivateEvent (event_sp);
+                        StartPrivateStateThread ();
+                    }
+                    else if (state == eStateExited)
+                    {
+                        // We exited while trying to launch somehow.  Don't call DidLaunch as that's
+                        // not likely to work, and return an invalid pid.
+                        HandlePrivateEvent (event_sp);
+                    }
+                }
+            }
+        }
+        else
+        {
+            error.SetErrorStringWithFormat("File doesn't exist: '%s'.\n", exec_file_path);
+        }
+    }
+    return error;
+}
+
+Error
+Process::CompleteAttach ()
+{
+    Error error;
+    EventSP event_sp;
+    StateType state = WaitForProcessStopPrivate(NULL, event_sp);
+    if (state == eStateStopped || state == eStateCrashed)
+    {
+        DidAttach ();
+
+        // This delays passing the stopped event to listeners till DidLaunch gets
+        // a chance to complete...
+        HandlePrivateEvent(event_sp);
+        StartPrivateStateThread();
+    }
+    else
+    {
+        // We exited while trying to launch somehow.  Don't call DidLaunch as that's
+        // not likely to work, and return an invalid pid.
+        if (state == eStateExited)
+            HandlePrivateEvent (event_sp);
+        error.SetErrorStringWithFormat("invalid state after attach: %s", 
+                                        lldb_private::StateAsCString(state));
+    }
+    return error;
+}
+
+Error
+Process::Attach (lldb::pid_t attach_pid)
+{
+
+    m_target_triple.Clear();
+    m_abi_sp.reset();
+
+    Error error(WillAttach (attach_pid));
+    if (error.Success())
+    {
+        error = DoAttach (attach_pid);
+        if (error.Success())
+        {
+            error = CompleteAttach();
+        }
+        else
+        {
+            if (GetID() != LLDB_INVALID_PROCESS_ID)
+            {
+                SetID (LLDB_INVALID_PROCESS_ID);
+                const char *error_string = error.AsCString();
+                if (error_string == NULL)
+                    error_string = "attach failed";
+
+                SetExitStatus(-1, error_string);
+            }
+        }
+    }
+    return error;
+}
+
+Error
+Process::Attach (const char *process_name, bool wait_for_launch)
+{
+    m_target_triple.Clear();
+    m_abi_sp.reset();
+
+    Error error (WillAttach (process_name, wait_for_launch));
+    if (error.Success())
+    {
+        StartPrivateStateThread();
+        error = DoAttach (process_name, wait_for_launch);
+        if (error.Fail())
+        {
+            if (GetID() != LLDB_INVALID_PROCESS_ID)
+            {
+                SetID (LLDB_INVALID_PROCESS_ID);
+                const char *error_string = error.AsCString();
+                if (error_string == NULL)
+                    error_string = "attach failed";
+
+                SetExitStatus(-1, error_string);
+            }
+        }
+        else
+        {
+            error = CompleteAttach();
+        }
+    }
+    return error;
+}
+
+Error
+Process::Resume ()
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
+    if (log)
+        log->Printf("Process::Resume() m_stop_id = %u", m_stop_id);
+
+    Error error (WillResume());
+    // Tell the process it is about to resume before the thread list
+    if (error.Success())
+    {
+        // Now let the thread list know we are about to resume to it
+        // can let all of our threads know that they are about to be
+        // resumed. Threads will each be called with
+        // Thread::WillResume(StateType) where StateType contains the state
+        // that they are supposed to have when the process is resumed
+        // (suspended/running/stepping). Threads should also check
+        // their resume signal in lldb::Thread::GetResumeSignal()
+        // to see if they are suppoed to start back up with a signal.
+        if (m_thread_list.WillResume())
+        {
+            error = DoResume();
+            if (error.Success())
+            {
+                DidResume();
+                m_thread_list.DidResume();
+            }
+        }
+        else
+        {
+            error.SetErrorStringWithFormat("thread list returned flase after WillResume");
+        }
+    }
+    return error;
+}
+
+Error
+Process::Halt ()
+{
+    Error error (WillHalt());
+    
+    if (error.Success())
+    {
+        error = DoHalt();
+        if (error.Success())
+            DidHalt();
+    }
+    return error;
+}
+
+Error
+Process::Detach ()
+{
+    Error error (WillDetach());
+
+    if (error.Success())
+    {
+        DisableAllBreakpointSites();
+        error = DoDetach(); 
+        if (error.Success())
+        {
+            DidDetach();
+            StopPrivateStateThread();
+        }
+    }
+    return error;
+}
+
+Error
+Process::Destroy ()
+{
+    Error error (WillDestroy());
+    if (error.Success())
+    {
+        DisableAllBreakpointSites();
+        error = DoDestroy();
+        if (error.Success())
+        {
+            DidDestroy();
+            StopPrivateStateThread();
+        }
+    }
+    return error;
+}
+
+Error
+Process::Signal (int signal)
+{
+    Error error (WillSignal());
+    if (error.Success())
+    {
+        error = DoSignal(signal);
+        if (error.Success())
+            DidSignal();
+    }
+    return error;
+}
+
+UnixSignals &
+Process::GetUnixSignals ()
+{
+    return m_unix_signals;
+}
+
+Target &
+Process::GetTarget ()
+{
+    return m_target;
+}
+
+const Target &
+Process::GetTarget () const
+{
+    return m_target;
+}
+
+uint32_t
+Process::GetAddressByteSize()
+{
+    return m_target.GetArchitecture().GetAddressByteSize();
+}
+
+bool
+Process::ShouldBroadcastEvent (Event *event_ptr)
+{
+    const StateType state = Process::ProcessEventData::GetStateFromEvent (event_ptr);
+    bool return_value = true;
+    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS);
+
+    switch (state)
+    {
+        case eStateAttaching:
+        case eStateLaunching:
+        case eStateDetached:
+        case eStateExited:
+        case eStateUnloaded:
+            // These events indicate changes in the state of the debugging session, always report them.
+            return_value = true;
+            break;
+        case eStateInvalid:
+            // We stopped for no apparent reason, don't report it.
+            return_value = false;
+            break;
+        case eStateRunning:
+        case eStateStepping:
+            // If we've started the target running, we handle the cases where we
+            // are already running and where there is a transition from stopped to
+            // running differently.
+            // running -> running: Automatically suppress extra running events
+            // stopped -> running: Report except when there is one or more no votes
+            //     and no yes votes.
+            SynchronouslyNotifyStateChanged (state);
+            switch (m_public_state.GetValue())
+            {
+                case eStateRunning:
+                case eStateStepping:
+                    // We always suppress multiple runnings with no PUBLIC stop in between.
+                    return_value = false;
+                    break;
+                default:
+                    // TODO: make this work correctly. For now always report
+                    // run if we aren't running so we don't miss any runnning
+                    // events. If I run the lldb/test/thread/a.out file and
+                    // break at main.cpp:58, run and hit the breakpoints on
+                    // multiple threads, then somehow during the stepping over
+                    // of all breakpoints no run gets reported.
+                    return_value = true;
+
+                    // This is a transition from stop to run.
+                    switch (m_thread_list.ShouldReportRun (event_ptr))
+                    {
+                        case eVoteYes:
+                        case eVoteNoOpinion:
+                            return_value = true;
+                            break;
+                        case eVoteNo:
+                            return_value = false;
+                            break;
+                    }
+                    break;
+            }
+            break;
+        case eStateStopped:
+        case eStateCrashed:
+        case eStateSuspended:
+        {
+            // We've stopped.  First see if we're going to restart the target.
+            // If we are going to stop, then we always broadcast the event.
+            // If we aren't going to stop, let the thread plans decide if we're going to report this event.
+            // If no thread has an opinion, we also report it.
+            if (state != eStateInvalid)
+            {
+
+                RefreshStateAfterStop ();
+
+                if (m_thread_list.ShouldStop (event_ptr) == false)
+                {
+                    switch (m_thread_list.ShouldReportStop (event_ptr))
+                    {
+                        case eVoteYes:
+                            Process::ProcessEventData::SetRestartedInEvent (event_ptr, true);
+                        case eVoteNoOpinion:
+                            return_value = true;
+                            break;
+                        case eVoteNo:
+                            return_value = false;
+                            break;
+                    }
+
+                    if (log)
+                        log->Printf ("Process::ShouldBroadcastEvent (%p) Restarting process", event_ptr, StateAsCString(state));
+                    Resume ();
+                }
+                else
+                {
+                    return_value = true;
+                    SynchronouslyNotifyStateChanged (state);
+                }
+            }
+        }
+    }
+
+    if (log)
+        log->Printf ("Process::ShouldBroadcastEvent (%p) => %s", event_ptr, StateAsCString(state), return_value ? "YES" : "NO");
+    return return_value;
+}
+
+//------------------------------------------------------------------
+// Thread Queries
+//------------------------------------------------------------------
+
+ThreadList &
+Process::GetThreadList ()
+{
+    return m_thread_list;
+}
+
+const ThreadList &
+Process::GetThreadList () const
+{
+    return m_thread_list;
+}
+
+
+bool
+Process::StartPrivateStateThread ()
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS);
+
+    if (log)
+        log->Printf ("Process::%s ( )", __FUNCTION__);
+
+    // Create a thread that watches our internal state and controls which
+    // events make it to clients (into the DCProcess event queue).
+    m_private_state_thread = Host::ThreadCreate ("<lldb.process.internal-state>", Process::PrivateStateThread, this, NULL);
+    return m_private_state_thread != LLDB_INVALID_HOST_THREAD;
+}
+
+void
+Process::PausePrivateStateThread ()
+{
+    ControlPrivateStateThread (eBroadcastInternalStateControlPause);
+}
+
+void
+Process::ResumePrivateStateThread ()
+{
+    ControlPrivateStateThread (eBroadcastInternalStateControlResume);
+}
+
+void
+Process::StopPrivateStateThread ()
+{
+    ControlPrivateStateThread (eBroadcastInternalStateControlStop);
+}
+
+void
+Process::ControlPrivateStateThread (uint32_t signal)
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS);
+
+    assert (signal == eBroadcastInternalStateControlStop ||
+            signal == eBroadcastInternalStateControlPause ||
+            signal == eBroadcastInternalStateControlResume);
+
+    if (log)
+        log->Printf ("Process::%s ( ) - signal: %d", __FUNCTION__, signal);
+
+    // Signal the private state thread
+    if (m_private_state_thread != LLDB_INVALID_HOST_THREAD)
+    {
+        TimeValue timeout_time;
+        bool timed_out;
+
+        m_private_state_control_broadcaster.BroadcastEvent (signal, NULL);
+
+        timeout_time = TimeValue::Now();
+        timeout_time.OffsetWithSeconds(2);
+        m_private_state_control_wait.WaitForValueEqualTo (true, &timeout_time, &timed_out);
+        m_private_state_control_wait.SetValue (false, eBroadcastNever);
+
+        if (signal == eBroadcastInternalStateControlStop)
+        {
+            if (timed_out)
+                Host::ThreadCancel (m_private_state_thread, NULL);
+
+            thread_result_t result = NULL;
+            Host::ThreadJoin (m_private_state_thread, &result, NULL);
+        }
+    }
+}
+
+void
+Process::HandlePrivateEvent (EventSP &event_sp)
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
+    const StateType internal_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+    // See if we should broadcast this state to external clients?
+    const bool should_broadcast = ShouldBroadcastEvent (event_sp.get());
+    if (log)
+        log->Printf ("Process::%s (arg = %p, pid = %i) got event '%s' broadcast = %s", __FUNCTION__, this, GetID(), StateAsCString(internal_state), should_broadcast ? "yes" : "no");
+
+    if (should_broadcast)
+    {
+        if (log)
+        {
+            log->Printf ("\tChanging public state from: %s to %s", StateAsCString(GetState ()), StateAsCString (internal_state));
+        }
+        Process::ProcessEventData::SetUpdateStateOnRemoval(event_sp.get());
+        BroadcastEvent (event_sp);
+    }
+    else
+    {
+        if (log)
+        {
+            log->Printf ("\tNot changing public state with event: %s", StateAsCString (internal_state));
+        }
+    }
+}
+
+void *
+Process::PrivateStateThread (void *arg)
+{
+    Process *proc = static_cast<Process*> (arg);
+    void *result = proc->RunPrivateStateThread ();
+    proc->m_private_state_thread = LLDB_INVALID_HOST_THREAD;
+    return result;
+}
+
+void *
+Process::RunPrivateStateThread ()
+{
+    bool control_only = false;
+    m_private_state_control_wait.SetValue (false, eBroadcastNever);
+
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
+    if (log)
+        log->Printf ("Process::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, this, GetID());
+
+    bool exit_now = false;
+    while (!exit_now)
+    {
+        EventSP event_sp;
+        WaitForEventsPrivate (NULL, event_sp, control_only);
+        if (event_sp->BroadcasterIs(&m_private_state_control_broadcaster))
+        {
+            switch (event_sp->GetType())
+            {
+            case eBroadcastInternalStateControlStop:
+                exit_now = true;
+                continue;   // Go to next loop iteration so we exit without
+                break;      // doing any internal state managment below
+
+            case eBroadcastInternalStateControlPause:
+                control_only = true;
+                break;
+
+            case eBroadcastInternalStateControlResume:
+                control_only = false;
+                break;
+            }
+            m_private_state_control_wait.SetValue (true, eBroadcastAlways);
+        }
+
+
+        const StateType internal_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+
+        if (internal_state != eStateInvalid)
+        {
+            HandlePrivateEvent (event_sp);
+        }
+
+        if (internal_state == eStateInvalid || internal_state == eStateExited)
+            break;
+    }
+
+    if (log)
+        log->Printf ("Process::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, this, GetID());
+
+    return NULL;
+}
+
+addr_t
+Process::GetSectionLoadAddress (const Section *section) const
+{
+    // TODO: add support for the same section having multiple load addresses
+    addr_t section_load_addr = LLDB_INVALID_ADDRESS;
+    if (m_section_load_info.GetFirstKeyForValue (section, section_load_addr))
+        return section_load_addr;
+    return LLDB_INVALID_ADDRESS;
+}
+
+bool
+Process::SectionLoaded (const Section *section, addr_t load_addr)
+{
+    Log *log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_SHLIB | LIBLLDB_LOG_VERBOSE);
+
+    if (log)
+        log->Printf ("Process::%s (section = %p (%s.%s), load_addr = 0x%16.16llx)",
+                     __FUNCTION__,
+                     section,
+                     section->GetModule()->GetFileSpec().GetFilename().AsCString(),
+                     section->GetName().AsCString(),
+                     load_addr);
+
+
+    const Section *existing_section = NULL;
+    Mutex::Locker locker(m_section_load_info.GetMutex());
+
+    if (m_section_load_info.GetValueForKeyNoLock (load_addr, existing_section))
+    {
+        if (existing_section == section)
+            return false;   // No change
+    }
+    m_section_load_info.SetValueForKeyNoLock (load_addr, section);
+    return true;    // Changed
+}
+
+size_t
+Process::SectionUnloaded (const Section *section)
+{
+    Log *log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_SHLIB | LIBLLDB_LOG_VERBOSE);
+
+    if (log)
+        log->Printf ("Process::%s (section = %p (%s.%s))",
+                     __FUNCTION__,
+                     section,
+                     section->GetModule()->GetFileSpec().GetFilename().AsCString(),
+                     section->GetName().AsCString());
+
+    Mutex::Locker locker(m_section_load_info.GetMutex());
+
+    size_t unload_count = 0;
+    addr_t section_load_addr;
+    while (m_section_load_info.GetFirstKeyForValueNoLock (section, section_load_addr))
+    {
+        unload_count += m_section_load_info.EraseNoLock (section_load_addr);
+    }
+    return unload_count;
+}
+
+bool
+Process::SectionUnloaded (const Section *section, addr_t load_addr)
+{
+    Log *log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_SHLIB | LIBLLDB_LOG_VERBOSE);
+
+    if (log)
+        log->Printf ("Process::%s (section = %p (%s.%s), load_addr = 0x%16.16llx)",
+                     __FUNCTION__,
+                     section,
+                     section->GetModule()->GetFileSpec().GetFilename().AsCString(),
+                     section->GetName().AsCString(),
+                     load_addr);
+
+    return m_section_load_info.Erase (load_addr) == 1;
+}
+
+
+bool
+Process::ResolveLoadAddress (addr_t load_addr, Address &so_addr) const
+{
+    addr_t section_load_addr = LLDB_INVALID_ADDRESS;
+    const Section *section = NULL;
+
+    // First find the top level section that this load address exists in
+    if (m_section_load_info.LowerBound (load_addr, section_load_addr, section, true))
+    {
+        addr_t offset = load_addr - section_load_addr;
+        if (offset < section->GetByteSize())
+        {
+            // We have found the top level section, now we need to find the
+            // deepest child section.
+            return section->ResolveContainedAddress (offset, so_addr);
+        }
+    }
+    so_addr.Clear();
+    return false;
+}
+
+//------------------------------------------------------------------
+// Process Event Data
+//------------------------------------------------------------------
+
+Process::ProcessEventData::ProcessEventData () :
+    EventData (),
+    m_process_sp (),
+    m_state (eStateInvalid),
+    m_update_state (false),
+    m_restarted (false)
+{
+}
+
+Process::ProcessEventData::ProcessEventData (const ProcessSP &process_sp, StateType state) :
+    EventData (),
+    m_process_sp (process_sp),
+    m_state (state),
+    m_update_state (false),
+    m_restarted (false)
+{
+}
+
+Process::ProcessEventData::~ProcessEventData()
+{
+}
+
+const ConstString &
+Process::ProcessEventData::GetFlavorString ()
+{
+    static ConstString g_flavor ("Process::ProcessEventData");
+    return g_flavor;
+}
+
+const ConstString &
+Process::ProcessEventData::GetFlavor () const
+{
+    return ProcessEventData::GetFlavorString ();
+}
+
+const ProcessSP &
+Process::ProcessEventData::GetProcessSP () const
+{
+    return m_process_sp;
+}
+
+StateType
+Process::ProcessEventData::GetState () const
+{
+    return m_state;
+}
+
+bool
+Process::ProcessEventData::GetRestarted () const
+{
+    return m_restarted;
+}
+
+void
+Process::ProcessEventData::SetRestarted (bool new_value)
+{
+    m_restarted = new_value;
+}
+
+void
+Process::ProcessEventData::DoOnRemoval (Event *event_ptr)
+{
+    // This function gets called twice for each event, once when the event gets pulled 
+    // off of the private process event queue, and once when it gets pulled off of
+    // the public event queue.  m_update_state is used to distinguish these
+    // two cases; it is false when we're just pulling it off for private handling, 
+    // and we don't want to do the breakpoint command handling then.
+    
+    if (!m_update_state)
+        return;
+        
+    m_process_sp->SetPublicState (m_state);
+        
+    // If we're stopped and haven't restarted, then do the breakpoint commands here:
+    if (m_state == eStateStopped && ! m_restarted)
+    {
+        int num_threads = m_process_sp->GetThreadList().GetSize();
+        int idx;
+        
+        for (idx = 0; idx < num_threads; ++idx)
+        {
+            lldb::ThreadSP thread_sp = m_process_sp->GetThreadList().GetThreadAtIndex(idx);
+
+            Thread::StopInfo stop_info;
+            if (thread_sp->GetStopInfo(&stop_info))
+            {
+                StopReason reason = stop_info.GetStopReason();
+                if (reason == eStopReasonBreakpoint)
+                {
+                    BreakpointSiteSP bp_site_sp;
+                    // Look up the breakpoint site in the stop info, but the breakpoint
+                    // might be a temporary one that's been deleted between the time we
+                    // hit the breakpoint and now, if so there's nothing to do.
+                    
+                    bp_site_sp = m_process_sp->GetBreakpointSiteList().FindByID (stop_info.GetBreakpointSiteID());
+                    if (bp_site_sp)
+                    {
+                        size_t num_owners = bp_site_sp->GetNumberOfOwners();
+                        for (size_t j = 0; j < num_owners; j++)
+                        {
+                            lldb::BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(j);
+                            StoppointCallbackContext context (event_ptr, 
+                                                              m_process_sp.get(), 
+                                                              thread_sp.get(), 
+                                                              thread_sp->GetStackFrameAtIndex(0).get(),
+                                                              false);
+                            bp_loc_sp->InvokeCallback (&context);
+                        }
+                    }
+                    else
+                    {
+                        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
+
+                        if (log)
+                            log->Printf ("Process::%s could not find breakpoint site id: %d...", __FUNCTION__, stop_info.GetBreakpointSiteID());
+                    }
+
+                }
+            }
+        }
+        if (m_process_sp->GetPrivateState() == eStateRunning)
+            SetRestarted(true);
+    }
+}
+
+void
+Process::ProcessEventData::Dump (Stream *s) const
+{
+    if (m_process_sp)
+        s->Printf(" process = %p (pid = %u), ", m_process_sp.get(), m_process_sp->GetID());
+
+    s->Printf("state = %s", StateAsCString(GetState()));;
+}
+
+const Process::ProcessEventData *
+Process::ProcessEventData::GetEventDataFromEvent (const Event *event_ptr)
+{
+    if (event_ptr)
+    {
+        const EventData *event_data = event_ptr->GetData();
+        if (event_data && event_data->GetFlavor() == ProcessEventData::GetFlavorString())
+            return static_cast <const ProcessEventData *> (event_ptr->GetData());
+    }
+    return NULL;
+}
+
+ProcessSP
+Process::ProcessEventData::GetProcessFromEvent (const Event *event_ptr)
+{
+    ProcessSP process_sp;
+    const ProcessEventData *data = GetEventDataFromEvent (event_ptr);
+    if (data)
+        process_sp = data->GetProcessSP();
+    return process_sp;
+}
+
+StateType
+Process::ProcessEventData::GetStateFromEvent (const Event *event_ptr)
+{
+    const ProcessEventData *data = GetEventDataFromEvent (event_ptr);
+    if (data == NULL)
+        return eStateInvalid;
+    else
+        return data->GetState();
+}
+
+bool
+Process::ProcessEventData::GetRestartedFromEvent (const Event *event_ptr)
+{
+    const ProcessEventData *data = GetEventDataFromEvent (event_ptr);
+    if (data == NULL)
+        return false;
+    else
+        return data->GetRestarted();
+}
+
+void
+Process::ProcessEventData::SetRestartedInEvent (Event *event_ptr, bool new_value)
+{
+    ProcessEventData *data = const_cast<ProcessEventData *>(GetEventDataFromEvent (event_ptr));
+    if (data != NULL)
+        data->SetRestarted(new_value);
+}
+
+bool
+Process::ProcessEventData::SetUpdateStateOnRemoval (Event *event_ptr)
+{
+    ProcessEventData *data = const_cast<ProcessEventData *>(GetEventDataFromEvent (event_ptr));
+    if (data)
+    {
+        data->SetUpdateStateOnRemoval();
+        return true;
+    }
+    return false;
+}
+
+void
+Process::ProcessEventData::SetUpdateStateOnRemoval()
+{
+    m_update_state = true;
+}
+
+Target *
+Process::CalculateTarget ()
+{
+    return &m_target;
+}
+
+Process *
+Process::CalculateProcess ()
+{
+    return this;
+}
+
+Thread *
+Process::CalculateThread ()
+{
+    return NULL;
+}
+
+StackFrame *
+Process::CalculateStackFrame ()
+{
+    return NULL;
+}
+
+void
+Process::Calculate (ExecutionContext &exe_ctx)
+{
+    exe_ctx.target = &m_target;
+    exe_ctx.process = this;
+    exe_ctx.thread = NULL;
+    exe_ctx.frame = NULL;
+}
+
+lldb::ProcessSP
+Process::GetSP ()
+{
+    return GetTarget().GetProcessSP();
+}
+
+ObjCObjectPrinter &
+Process::GetObjCObjectPrinter()
+{
+    return m_objc_object_printer;
+}
+
diff --git a/source/Target/RegisterContext.cpp b/source/Target/RegisterContext.cpp
new file mode 100644
index 0000000..b1838ba
--- /dev/null
+++ b/source/Target/RegisterContext.cpp
@@ -0,0 +1,238 @@
+//===-- RegisterContext.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
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// RegisterContext constructor
+//----------------------------------------------------------------------
+RegisterContext::RegisterContext (Thread &thread, StackFrame *frame) :
+    m_thread (thread),
+    m_frame (frame)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+RegisterContext::~RegisterContext()
+{
+}
+
+const RegisterInfo *
+RegisterContext::GetRegisterInfoByName (const char *reg_name, uint32_t start_idx)
+{
+    if (reg_name && reg_name[0])
+    {
+        const uint32_t num_registers = GetRegisterCount();
+        for (uint32_t reg = start_idx; reg < num_registers; ++reg)
+        {
+            const RegisterInfo * reg_info = GetRegisterInfoAtIndex(reg);
+
+            if ((reg_info->name != NULL && ::strcasecmp (reg_info->name, reg_name) == 0) ||
+                (reg_info->alt_name != NULL && ::strcasecmp (reg_info->alt_name, reg_name) == 0))
+            {
+                return reg_info;
+            }
+        }
+    }
+    return NULL;
+}
+
+const char *
+RegisterContext::GetRegisterName (uint32_t reg)
+{
+    const RegisterInfo * reg_info = GetRegisterInfoAtIndex(reg);
+    if (reg_info)
+        return reg_info->name;
+    return NULL;
+}
+
+uint64_t
+RegisterContext::GetPC(uint64_t fail_value)
+{
+    uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+    return ReadRegisterAsUnsigned (reg, fail_value);
+}
+
+bool
+RegisterContext::SetPC(uint64_t pc)
+{
+    uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+    bool success = WriteRegisterFromUnsigned (reg, pc);
+    if (success)
+    {
+        if (m_frame)
+            m_frame->ChangePC(pc);
+        else
+            m_thread.ClearStackFrames ();
+    }
+    return success;
+}
+
+uint64_t
+RegisterContext::GetSP(uint64_t fail_value)
+{
+    uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+    return ReadRegisterAsUnsigned (reg, fail_value);
+}
+
+bool
+RegisterContext::SetSP(uint64_t sp)
+{
+    uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+    return WriteRegisterFromUnsigned (reg, sp);
+}
+
+uint64_t
+RegisterContext::GetFP(uint64_t fail_value)
+{
+    uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
+    return ReadRegisterAsUnsigned (reg, fail_value);
+}
+
+bool
+RegisterContext::SetFP(uint64_t fp)
+{
+    uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
+    return WriteRegisterFromUnsigned (reg, fp);
+}
+
+uint64_t
+RegisterContext::GetReturnAddress (uint64_t fail_value)
+{
+    uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
+    return ReadRegisterAsUnsigned (reg, fail_value);
+}
+
+uint64_t
+RegisterContext::GetFlags (uint64_t fail_value)
+{
+    uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
+    return ReadRegisterAsUnsigned (reg, fail_value);
+}
+
+
+uint64_t
+RegisterContext::ReadRegisterAsUnsigned (uint32_t reg, uint64_t fail_value)
+{
+    if (reg != LLDB_INVALID_REGNUM)
+    {
+        Scalar value;
+        if (ReadRegisterValue (reg, value))
+            return value.GetRawBits64(fail_value);
+    }
+    return fail_value;
+}
+
+bool
+RegisterContext::WriteRegisterFromUnsigned (uint32_t reg, uint64_t uval)
+{
+    if (reg == LLDB_INVALID_REGNUM)
+        return false;
+    Scalar value(uval);
+    return WriteRegisterValue (reg, value);
+}
+
+lldb::tid_t
+RegisterContext::GetThreadID() const
+{
+    return m_thread.GetID();
+}
+
+uint32_t
+RegisterContext::NumSupportedHardwareBreakpoints ()
+{
+    return 0;
+}
+
+uint32_t
+RegisterContext::SetHardwareBreakpoint (lldb::addr_t addr, size_t size)
+{
+    return LLDB_INVALID_INDEX32;
+}
+
+bool
+RegisterContext::ClearHardwareBreakpoint (uint32_t hw_idx)
+{
+    return false;
+}
+
+
+uint32_t
+RegisterContext::NumSupportedHardwareWatchpoints ()
+{
+    return 0;
+}
+
+uint32_t
+RegisterContext::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write)
+{
+    return LLDB_INVALID_INDEX32;
+}
+
+bool
+RegisterContext::ClearHardwareWatchpoint (uint32_t hw_index)
+{
+    return false;
+}
+
+bool
+RegisterContext::HardwareSingleStep (bool enable)
+{
+    return false;
+}
+
+Target *
+RegisterContext::CalculateTarget ()
+{
+    return m_thread.CalculateTarget();
+}
+
+
+Process *
+RegisterContext::CalculateProcess ()
+{
+    return m_thread.CalculateProcess ();
+}
+
+Thread *
+RegisterContext::CalculateThread ()
+{
+    return &m_thread;
+}
+
+StackFrame *
+RegisterContext::CalculateStackFrame ()
+{
+    return m_frame;
+}
+
+void
+RegisterContext::Calculate (ExecutionContext &exe_ctx)
+{
+    if (m_frame)
+        m_frame->Calculate (exe_ctx);
+    else
+        m_thread.Calculate (exe_ctx);
+}
+
+
+
diff --git a/source/Target/StackFrame.cpp b/source/Target/StackFrame.cpp
new file mode 100644
index 0000000..cb83295
--- /dev/null
+++ b/source/Target/StackFrame.cpp
@@ -0,0 +1,393 @@
+//===-- StackFrame.cpp ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/StackFrame.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+// The first bits in the flags are reserved for the SymbolContext::Scope bits
+// so we know if we have tried to look up information in our internal symbol
+// context (m_sc) already.
+#define RESOLVED_PC_SO_ADDR (uint32_t(eSymbolContextEverything + 1))
+#define RESOLVED_FRAME_ID   (RESOLVED_PC_SO_ADDR << 1)
+#define GOT_FRAME_BASE      (RESOLVED_FRAME_ID << 1)
+#define FRAME_IS_OBSOLETE   (GOT_FRAME_BASE << 1)
+#define RESOLVED_VARIABLES  (FRAME_IS_OBSOLETE << 1)
+
+StackFrame::StackFrame (lldb::user_id_t frame_idx, Thread &thread, lldb::addr_t cfa, lldb::addr_t pc, const SymbolContext *sc_ptr) :
+    UserID (frame_idx),
+    m_thread (thread),
+    m_reg_context_sp(),
+    m_id(cfa),
+    m_pc(NULL, pc),
+    m_sc(),
+    m_flags(),
+    m_frame_base(),
+    m_frame_base_error(),
+    m_variable_list_sp (),
+    m_value_object_list ()
+{
+    if (sc_ptr != NULL)
+        m_sc = *sc_ptr;
+}
+
+StackFrame::StackFrame (lldb::user_id_t frame_idx, Thread &thread, RegisterContextSP &reg_context_sp, lldb::addr_t cfa, lldb::addr_t pc, const SymbolContext *sc_ptr) :
+    UserID (frame_idx),
+    m_thread (thread),
+    m_reg_context_sp(reg_context_sp),
+    m_id(cfa),
+    m_pc(NULL, pc),
+    m_sc(),
+    m_flags(),
+    m_frame_base(),
+    m_frame_base_error(),
+    m_variable_list_sp (),
+    m_value_object_list ()
+{
+    if (sc_ptr != NULL)
+        m_sc = *sc_ptr;
+}
+
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+StackFrame::~StackFrame()
+{
+}
+
+StackID&
+StackFrame::GetStackID()
+{
+    // Make sure we have resolved our stack ID's address range before we give
+    // it out to any external clients
+    if (m_id.GetStartAddress().IsValid() == 0 && m_flags.IsClear(RESOLVED_FRAME_ID))
+    {
+        m_flags.Set (RESOLVED_FRAME_ID);
+
+        // Resolve our PC to section offset if we haven't alreday done so
+        // and if we don't have a module. The resolved address section will
+        // contain the module to which it belongs.
+        if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_PC_SO_ADDR))
+            GetPC();
+
+        const uint32_t resolve_scope = eSymbolContextModule |
+                                       eSymbolContextCompUnit |
+                                       eSymbolContextFunction;
+
+        if (m_sc.module_sp)
+        {
+            if (m_sc.module_sp->ResolveSymbolContextForAddress (GetPC(), resolve_scope, m_sc) & eSymbolContextFunction)
+            {
+                assert (m_sc.function);
+                m_id.SetStartAddress(m_sc.function->GetAddressRange().GetBaseAddress());
+            }
+            else if (m_sc.module_sp->ResolveSymbolContextForAddress (GetPC(), resolve_scope, m_sc) & eSymbolContextSymbol)
+            {
+                assert (m_sc.symbol);
+                AddressRange *symbol_range_ptr = m_sc.symbol->GetAddressRangePtr();
+                if (symbol_range_ptr)
+                    m_id.SetStartAddress(symbol_range_ptr->GetBaseAddress());
+            }
+        }
+//      else if (m_sc.target != NULL)
+//      {
+//          if (m_sc.target->GetImages().ResolveSymbolContextForAddress (GetPC(), resolve_scope, m_sc) & eSymbolContextFunction)
+//          {
+//              assert (m_sc.function);
+//              m_id.GetAddressRange() = m_sc.function->GetAddressRange();
+//          }
+//          else if (m_sc.target->GetImages().ResolveSymbolContextForAddress (GetPC(), resolve_scope, m_sc) & eSymbolContextSymbol)
+//          {
+//              assert (m_sc.symbol);
+//              AddressRange *symbol_range_ptr = m_sc.symbol->GetAddressRange();
+//              if (symbol_range_ptr)
+//                  m_id.GetAddressRange() = *symbol_range_ptr;
+//          }
+//      }
+    }
+    return m_id;
+}
+
+Address&
+StackFrame::GetPC()
+{
+    if (m_flags.IsClear(RESOLVED_PC_SO_ADDR) && !m_pc.IsSectionOffset())
+    {
+        m_flags.Set (RESOLVED_PC_SO_ADDR);
+
+        // Resolve the PC into a temporary address because if ResolveLoadAddress
+        // fails to resolve the address, it will clear the address object...
+        Address resolved_pc;
+        if (m_thread.GetProcess().ResolveLoadAddress(m_pc.GetOffset(), resolved_pc))
+        {
+            m_pc = resolved_pc;
+            const Section *section = m_pc.GetSection();
+            if (section)
+            {
+                Module *module = section->GetModule();
+                if (module)
+                {
+                    m_sc.module_sp = module->GetSP();
+                    if (m_sc.module_sp)
+                        m_flags.Set(eSymbolContextModule);
+                }
+            }
+        }
+    }
+    return m_pc;
+}
+
+void
+StackFrame::ChangePC (addr_t pc)
+{
+    m_pc.SetOffset(pc);
+    m_pc.SetSection(NULL);
+    m_sc.Clear();
+    m_flags.SetAllFlagBits(0);
+    m_thread.ClearStackFrames ();
+}
+
+const char *
+StackFrame::Disassemble ()
+{
+    if (m_disassembly.GetSize() == 0)
+    {
+        ExecutionContext exe_ctx;
+        Calculate(exe_ctx);
+        Disassembler::Disassemble (m_thread.GetProcess().GetTarget().GetArchitecture(),
+                                   exe_ctx,
+                                   0,
+                                   m_disassembly);
+        if (m_disassembly.GetSize() == 0)
+            return NULL;
+    }
+    return m_disassembly.GetData();
+}
+
+//----------------------------------------------------------------------
+// Get the symbol context if we already haven't done so by resolving the
+// PC address as much as possible. This way when we pass around a
+// StackFrame object, everyone will have as much information as
+// possible and no one will ever have to look things up manually.
+//----------------------------------------------------------------------
+const SymbolContext&
+StackFrame::GetSymbolContext (uint32_t resolve_scope)
+{
+    // Copy our internal symbol context into "sc".
+
+    if ((m_flags.GetAllFlagBits() & resolve_scope) != resolve_scope)
+    {
+        // Resolve our PC to section offset if we haven't alreday done so
+        // and if we don't have a module. The resolved address section will
+        // contain the module to which it belongs
+        if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_PC_SO_ADDR))
+            GetPC();
+
+        // If this is not frame zero, then we need to subtract 1 from the PC
+        // value when doing address lookups since the PC will be on the 
+        // instruction following the function call instruction...
+        
+        Address lookup_addr(GetPC());
+        if (GetID() > 0 && lookup_addr.IsValid())
+        {
+            addr_t offset = lookup_addr.GetOffset();
+            if (offset > 0)
+                lookup_addr.SetOffset(offset - 1);
+        }
+
+        if (m_sc.module_sp)
+        {
+            // We have something in our stack frame symbol context, lets check
+            // if we haven't already tried to lookup one of those things. If we
+            // haven't then we will do the query.
+            if ((m_sc.comp_unit == NULL     && (resolve_scope & eSymbolContextCompUnit ) && m_flags.IsClear(eSymbolContextCompUnit   )) ||
+                (m_sc.function  == NULL     && (resolve_scope & eSymbolContextFunction ) && m_flags.IsClear(eSymbolContextFunction   )) ||
+                (m_sc.block     == NULL     && (resolve_scope & eSymbolContextBlock    ) && m_flags.IsClear(eSymbolContextBlock      )) ||
+                (m_sc.symbol    == NULL     && (resolve_scope & eSymbolContextSymbol   ) && m_flags.IsClear(eSymbolContextSymbol     )) ||
+                (!m_sc.line_entry.IsValid() && (resolve_scope & eSymbolContextLineEntry) && m_flags.IsClear(eSymbolContextLineEntry  )))
+            {
+                // We might be resolving less information than what is already
+                // in our current symbol context so resolve into a temporary 
+                // symbol context "sc" so we don't clear out data we have 
+                // already found in "m_sc"
+                SymbolContext sc;
+                // Set flags that indicate what we have tried to resolve
+                const uint32_t resolved = m_sc.module_sp->ResolveSymbolContextForAddress (lookup_addr, resolve_scope, sc);
+                if (resolved & eSymbolContextCompUnit)  m_sc.comp_unit  = sc.comp_unit;
+                if (resolved & eSymbolContextFunction)  m_sc.function   = sc.function;
+                if (resolved & eSymbolContextBlock)     m_sc.block      = sc.block;
+                if (resolved & eSymbolContextSymbol)    m_sc.symbol     = sc.symbol;
+                if (resolved & eSymbolContextLineEntry) m_sc.line_entry = sc.line_entry;
+            }
+        }
+        else
+        {
+            // If we don't have a module, then we can't have the compile unit,
+            // function, block, line entry or symbol, so we can safely call
+            // ResolveSymbolContextForAddress with our symbol context member m_sc.
+            m_thread.GetProcess().GetTarget().GetImages().ResolveSymbolContextForAddress (lookup_addr, resolve_scope, m_sc);
+        }
+
+        // If the target was requested add that:
+        if (m_sc.target_sp.get() == NULL)
+            m_sc.target_sp = CalculateProcess()->GetTarget().GetSP();
+
+        // Update our internal flags so we remember what we have tried to locate so
+        // we don't have to keep trying when more calls to this function are made.
+        m_flags.Set(resolve_scope);
+    }
+
+    // Return the symbol context with everything that was possible to resolve
+    // resolved.
+    return m_sc;
+}
+
+
+VariableList *
+StackFrame::GetVariableList ()
+{
+    if (m_flags.IsClear(RESOLVED_VARIABLES))
+    {
+        m_flags.Set(RESOLVED_VARIABLES);
+
+        GetSymbolContext(eSymbolContextFunction);
+        if (m_sc.function)
+        {
+            bool get_child_variables = true;
+            bool can_create = true;
+            m_variable_list_sp = m_sc.function->GetBlocks(can_create).GetVariableList (Block::RootID, get_child_variables, can_create);
+        }
+    }
+    return m_variable_list_sp.get();
+}
+
+
+bool
+StackFrame::GetFrameBaseValue (Scalar &frame_base, Error *error_ptr)
+{
+    if (m_flags.IsClear(GOT_FRAME_BASE))
+    {
+        if (m_sc.function)
+        {
+            m_frame_base.Clear();
+            m_frame_base_error.Clear();
+
+            m_flags.Set(GOT_FRAME_BASE);
+            ExecutionContext exe_ctx (&m_thread.GetProcess(), &m_thread, this);
+            Value expr_value;
+            if (m_sc.function->GetFrameBaseExpression().Evaluate(&exe_ctx, NULL, NULL, expr_value, &m_frame_base_error) < 0)
+            {
+                // We should really have an error if evaluate returns, but in case
+                // we don't, lets set the error to something at least.
+                if (m_frame_base_error.Success())
+                    m_frame_base_error.SetErrorString("Evaluation of the frame base expression failed.");
+            }
+            else
+            {
+                m_frame_base = expr_value.ResolveValue(&exe_ctx, NULL);
+            }
+        }
+        else
+        {
+            m_frame_base_error.SetErrorString ("No function in symbol context.");
+        }
+    }
+
+    if (m_frame_base_error.Success())
+        frame_base = m_frame_base;
+
+    if (error_ptr)
+        *error_ptr = m_frame_base_error;
+    return m_frame_base_error.Success();
+}
+
+RegisterContext *
+StackFrame::GetRegisterContext ()
+{
+    if (m_reg_context_sp.get() == NULL)
+        m_reg_context_sp.reset (m_thread.CreateRegisterContextForFrame (this));
+    return m_reg_context_sp.get();
+}
+
+bool
+StackFrame::HasDebugInformation ()
+{
+    GetSymbolContext(eSymbolContextLineEntry);
+    return m_sc.line_entry.IsValid();
+}
+
+ValueObjectList &
+StackFrame::GetValueObjectList()
+{
+    return m_value_object_list;
+}
+
+
+Target *
+StackFrame::CalculateTarget ()
+{
+    return m_thread.CalculateTarget();
+}
+
+Process *
+StackFrame::CalculateProcess ()
+{
+    return m_thread.CalculateProcess();
+}
+
+Thread *
+StackFrame::CalculateThread ()
+{
+    return &m_thread;
+}
+
+StackFrame *
+StackFrame::CalculateStackFrame ()
+{
+    return this;
+}
+
+
+void
+StackFrame::Calculate (ExecutionContext &exe_ctx)
+{
+    m_thread.Calculate (exe_ctx);
+    exe_ctx.frame = this;
+}
+
+void
+StackFrame::Dump (Stream *strm, bool show_frame_index)
+{
+    if (strm == NULL)
+        return;
+
+    if (show_frame_index)
+        strm->Printf("frame #%u: ", GetID());
+    strm->Printf("pc = 0x%0*llx", m_thread.GetProcess().GetAddressByteSize() * 2, GetRegisterContext()->GetPC());
+    SymbolContext sc (GetSymbolContext(eSymbolContextEverything));
+    strm->PutCString(", where = ");
+    sc.DumpStopContext(strm, &m_thread.GetProcess(), GetPC());
+}
+
diff --git a/source/Target/StackFrameList.cpp b/source/Target/StackFrameList.cpp
new file mode 100644
index 0000000..8615f71
--- /dev/null
+++ b/source/Target/StackFrameList.cpp
@@ -0,0 +1,135 @@
+//===-- StackFrameList.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
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/StackFrameList.h"
+#include "lldb/Target/StackFrame.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// StackFrameList constructor
+//----------------------------------------------------------------------
+StackFrameList::StackFrameList() :
+    m_mutex (Mutex::eMutexTypeRecursive),
+    m_frames (),
+    m_current_frame_idx (0)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+StackFrameList::~StackFrameList()
+{
+}
+
+
+uint32_t
+StackFrameList::GetNumFrames() const
+{
+    Mutex::Locker locker (m_mutex);
+    return m_frames.size();
+}
+
+// After we have determined the number of frames, we can set the count here
+// and have the frame info be generated on demand.
+void
+StackFrameList::SetNumFrames(uint32_t count)
+{
+    Mutex::Locker locker (m_mutex);
+    return m_frames.resize(count);
+}
+
+StackFrameSP
+StackFrameList::GetFrameAtIndex (uint32_t idx) const
+{
+    StackFrameSP frame_sp;
+    {
+        Mutex::Locker locker (m_mutex);
+        if (idx < m_frames.size())
+            frame_sp = m_frames[idx];
+    }
+    return frame_sp;
+}
+
+bool
+StackFrameList::SetFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp)
+{
+    Mutex::Locker locker (m_mutex);
+    if (idx >= m_frames.size())
+        m_frames.resize(idx + 1);
+    // Make sure allocation succeeded by checking bounds again
+    if (idx < m_frames.size())
+    {
+        m_frames[idx] = frame_sp;
+        return true;
+    }
+    return false;   // resize failed, out of memory?
+}
+
+uint32_t
+StackFrameList::GetCurrentFrameIndex () const
+{
+    Mutex::Locker locker (m_mutex);
+    return m_current_frame_idx;
+}
+
+
+uint32_t
+StackFrameList::SetCurrentFrame (lldb_private::StackFrame *frame)
+{
+    Mutex::Locker locker (m_mutex);
+    const_iterator pos,
+                   begin = m_frames.begin(),
+                   end = m_frames.end();
+    for (pos = begin; pos != end; ++pos)
+    {
+        if (pos->get() == frame)
+        {
+            m_current_frame_idx = std::distance (begin, pos);
+            return m_current_frame_idx;
+        }
+    }
+    m_current_frame_idx = 0;
+    return m_current_frame_idx;
+}
+
+// Mark a stack frame as the current frame using the frame index
+void
+StackFrameList::SetCurrentFrameByIndex (uint32_t idx)
+{
+    Mutex::Locker locker (m_mutex);
+    m_current_frame_idx = idx;
+}
+
+// The thread has been run, reset the number stack frames to zero so we can
+// determine how many frames we have lazily.
+void
+StackFrameList::Clear ()
+{
+    Mutex::Locker locker (m_mutex);
+    m_frames.clear();
+}
+
+void
+StackFrameList::InvalidateFrames (uint32_t start_idx)
+{
+    Mutex::Locker locker (m_mutex);
+    size_t num_frames = m_frames.size();
+    while (start_idx < num_frames)
+    {
+        m_frames[start_idx].reset();
+        ++start_idx;
+    }
+}
diff --git a/source/Target/StackID.cpp b/source/Target/StackID.cpp
new file mode 100644
index 0000000..6f903ae
--- /dev/null
+++ b/source/Target/StackID.cpp
@@ -0,0 +1,110 @@
+//===-- StackID.cpp ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/StackID.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// StackID constructor
+//----------------------------------------------------------------------
+StackID::StackID() :
+    m_start_address(),
+    m_cfa()
+{
+}
+
+//----------------------------------------------------------------------
+// StackID constructor with args
+//----------------------------------------------------------------------
+StackID::StackID (const Address& start_address, lldb::addr_t cfa) :
+    m_start_address (start_address),
+    m_cfa (cfa)
+{
+}
+
+StackID::StackID (lldb::addr_t cfa) :
+    m_start_address (),
+    m_cfa (cfa)
+{
+}
+
+//----------------------------------------------------------------------
+// StackID copy constructor
+//----------------------------------------------------------------------
+StackID::StackID(const StackID& rhs) :
+    m_start_address (rhs.m_start_address),
+    m_cfa (rhs.m_cfa)
+{
+}
+
+//----------------------------------------------------------------------
+// StackID assignment operator
+//----------------------------------------------------------------------
+const StackID&
+StackID::operator=(const StackID& rhs)
+{
+    if (this != &rhs)
+    {
+        m_start_address = rhs.m_start_address;
+        m_cfa = rhs.m_cfa;
+    }
+    return *this;
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+StackID::~StackID()
+{
+}
+
+
+const Address&
+StackID::GetStartAddress() const
+{
+    return m_start_address;
+}
+
+void
+StackID::SetStartAddress(const Address& start_address)
+{
+    m_start_address = start_address;
+}
+
+lldb::addr_t
+StackID::GetCallFrameAddress() const
+{
+    return m_cfa;
+}
+
+
+bool
+lldb_private::operator== (const StackID& lhs, const StackID& rhs)
+{
+    return lhs.GetCallFrameAddress() == rhs.GetCallFrameAddress() && lhs.GetStartAddress() == rhs.GetStartAddress();
+}
+
+bool
+lldb_private::operator!= (const StackID& lhs, const StackID& rhs)
+{
+    return lhs.GetCallFrameAddress() != rhs.GetCallFrameAddress() || lhs.GetStartAddress() != rhs.GetStartAddress();
+}
+
+bool
+lldb_private::operator< (const StackID& lhs, const StackID& rhs)
+{
+    return lhs.GetCallFrameAddress() < rhs.GetCallFrameAddress();
+}
+
diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp
new file mode 100644
index 0000000..48f2ea7
--- /dev/null
+++ b/source/Target/Target.cpp
@@ -0,0 +1,707 @@
+//===-- Target.cpp ----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/Target.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/BreakpointResolver.h"
+#include "lldb/Breakpoint/BreakpointResolverAddress.h"
+#include "lldb/Breakpoint/BreakpointResolverFileLine.h"
+#include "lldb/Breakpoint/BreakpointResolverName.h"
+#include "lldb/Core/Event.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/Host.h"
+#include "lldb/lldb-private-log.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Core/Debugger.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Target constructor
+//----------------------------------------------------------------------
+Target::Target() :
+    Broadcaster("Target"),
+    m_images(),
+    m_breakpoint_list (false),
+    m_internal_breakpoint_list (true),
+    m_process_sp(),
+    m_triple(),
+    m_search_filter_sp(),
+    m_image_search_paths (ImageSearchPathsChanged, this),
+    m_scratch_ast_context_ap(NULL)
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT);
+    if (log)
+        log->Printf ("%p Target::Target()", this);
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+Target::~Target()
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT);
+    if (log)
+        log->Printf ("%p Target::~Target()", this);
+    DeleteCurrentProcess ();
+}
+
+void
+Target::Dump (Stream *s)
+{
+    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+    s->Indent();
+    s->PutCString("Target\n");
+    s->IndentMore();
+    m_images.Dump(s);
+    m_breakpoint_list.Dump(s);
+    m_internal_breakpoint_list.Dump(s);
+//  if (m_process_sp.get())
+//      m_process_sp->Dump(s);
+    s->IndentLess();
+}
+
+void
+Target::DeleteCurrentProcess ()
+{
+    if (m_process_sp.get())
+    {
+        if (m_process_sp->IsAlive())
+            m_process_sp->Destroy();
+        else
+            m_process_sp->Finalize();
+
+        // Do any cleanup of the target we need to do between process instances.
+        // NB It is better to do this before destroying the process in case the
+        // clean up needs some help from the process.
+        m_breakpoint_list.ClearAllBreakpointSites();
+        m_internal_breakpoint_list.ClearAllBreakpointSites();
+        m_process_sp.reset();
+    }
+}
+
+const lldb::ProcessSP &
+Target::CreateProcess (Listener &listener, const char *plugin_name)
+{
+    DeleteCurrentProcess ();
+    m_process_sp.reset(Process::FindPlugin(*this, plugin_name, listener));
+    return m_process_sp;
+}
+
+const lldb::ProcessSP &
+Target::GetProcessSP () const
+{
+    return m_process_sp;
+}
+
+lldb::TargetSP
+Target::GetSP()
+{
+    return Debugger::GetSharedInstance().GetTargetList().GetTargetSP(this);
+}
+
+BreakpointList &
+Target::GetBreakpointList(bool internal)
+{
+    if (internal)
+        return m_internal_breakpoint_list;
+    else
+        return m_breakpoint_list;
+}
+
+const BreakpointList &
+Target::GetBreakpointList(bool internal) const
+{
+    if (internal)
+        return m_internal_breakpoint_list;
+    else
+        return m_breakpoint_list;
+}
+
+BreakpointSP
+Target::GetBreakpointByID (break_id_t break_id)
+{
+    BreakpointSP bp_sp;
+
+    if (LLDB_BREAK_ID_IS_INTERNAL (break_id))
+        bp_sp = m_internal_breakpoint_list.FindBreakpointByID (break_id);
+    else
+        bp_sp = m_breakpoint_list.FindBreakpointByID (break_id);
+
+    return bp_sp;
+}
+
+BreakpointSP
+Target::CreateBreakpoint (const FileSpec *containingModule, const FileSpec &file, uint32_t line_no, bool check_inlines, bool internal)
+{
+    SearchFilterSP filter_sp(GetSearchFilterForModule (containingModule));
+    BreakpointResolverSP resolver_sp(new BreakpointResolverFileLine (NULL, file, line_no, check_inlines));
+    return CreateBreakpoint (filter_sp, resolver_sp, internal);
+}
+
+
+BreakpointSP
+Target::CreateBreakpoint (lldb::addr_t load_addr, bool internal)
+{
+    BreakpointSP bp_sp;
+    Address so_addr;
+    // Attempt to resolve our load address if possible, though it is ok if
+    // it doesn't resolve to section/offset.
+
+    Process *process = GetProcessSP().get();
+    if (process && process->ResolveLoadAddress(load_addr, so_addr))
+        bp_sp = CreateBreakpoint(so_addr, internal);
+    return bp_sp;
+}
+
+BreakpointSP
+Target::CreateBreakpoint (Address &addr, bool internal)
+{
+    TargetSP target_sp = this->GetSP();
+    SearchFilterSP filter_sp(new SearchFilter (target_sp));
+    BreakpointResolverSP resolver_sp (new BreakpointResolverAddress (NULL, addr));
+    return CreateBreakpoint (filter_sp, resolver_sp, internal);
+}
+
+BreakpointSP
+Target::CreateBreakpoint (FileSpec *containingModule, const char *func_name, bool internal)
+{
+    SearchFilterSP filter_sp(GetSearchFilterForModule (containingModule));
+    BreakpointResolverSP resolver_sp (new BreakpointResolverName (NULL, func_name));
+    return CreateBreakpoint (filter_sp, resolver_sp, internal);
+}
+
+
+SearchFilterSP
+Target::GetSearchFilterForModule (const FileSpec *containingModule)
+{
+    SearchFilterSP filter_sp;
+    lldb::TargetSP target_sp = this->GetSP();
+    if (containingModule != NULL)
+    {
+        // TODO: We should look into sharing module based search filters
+        // across many breakpoints like we do for the simple target based one
+        filter_sp.reset (new SearchFilterByModule (target_sp, *containingModule));
+    }
+    else
+    {
+        if (m_search_filter_sp.get() == NULL)
+            m_search_filter_sp.reset (new SearchFilter (target_sp));
+        filter_sp = m_search_filter_sp;
+    }
+    return filter_sp;
+}
+
+BreakpointSP
+Target::CreateBreakpoint (FileSpec *containingModule, RegularExpression &func_regex, bool internal)
+{
+    SearchFilterSP filter_sp(GetSearchFilterForModule (containingModule));
+    BreakpointResolverSP resolver_sp(new BreakpointResolverName (NULL, func_regex));
+
+    return CreateBreakpoint (filter_sp, resolver_sp, internal);
+}
+
+BreakpointSP
+Target::CreateBreakpoint (SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp, bool internal)
+{
+    BreakpointSP bp_sp;
+    if (filter_sp && resolver_sp)
+    {
+        bp_sp.reset(new Breakpoint (*this, filter_sp, resolver_sp));
+        resolver_sp->SetBreakpoint (bp_sp.get());
+
+        if (internal)
+            m_internal_breakpoint_list.Add (bp_sp);
+        else
+            m_breakpoint_list.Add (bp_sp);
+
+        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+        if (log)
+        {
+            StreamString s;
+            bp_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
+            log->Printf ("Target::%s (internal = %s) => break_id = %s\n", __FUNCTION__, internal ? "yes" : "no", s.GetData());
+        }
+
+        // Broadcast the breakpoint creation event.
+        if (!internal && EventTypeHasListeners(eBroadcastBitBreakpointChanged))
+        {
+            BroadcastEvent (eBroadcastBitBreakpointChanged,
+                            new Breakpoint::BreakpointEventData (Breakpoint::BreakpointEventData::eBreakpointAdded, bp_sp));
+        }
+
+        bp_sp->ResolveBreakpoint();
+    }
+    return bp_sp;
+}
+
+void
+Target::RemoveAllBreakpoints (bool internal_also)
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+    if (log)
+        log->Printf ("Target::%s (internal_also = %s)\n", __FUNCTION__, internal_also ? "yes" : "no");
+
+    m_breakpoint_list.RemoveAll();
+    if (internal_also)
+        m_internal_breakpoint_list.RemoveAll();
+}
+
+void
+Target::DisableAllBreakpoints (bool internal_also)
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+    if (log)
+        log->Printf ("Target::%s (internal_also = %s)\n", __FUNCTION__, internal_also ? "yes" : "no");
+
+    m_breakpoint_list.SetEnabledAll (false);
+    if (internal_also)
+        m_internal_breakpoint_list.SetEnabledAll (false);
+}
+
+void
+Target::EnableAllBreakpoints (bool internal_also)
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+    if (log)
+        log->Printf ("Target::%s (internal_also = %s)\n", __FUNCTION__, internal_also ? "yes" : "no");
+
+    m_breakpoint_list.SetEnabledAll (true);
+    if (internal_also)
+        m_internal_breakpoint_list.SetEnabledAll (true);
+}
+
+bool
+Target::RemoveBreakpointByID (break_id_t break_id)
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+    if (log)
+        log->Printf ("Target::%s (break_id = %i, internal = %s)\n", __FUNCTION__, break_id, LLDB_BREAK_ID_IS_INTERNAL (break_id) ? "yes" : "no");
+
+    if (DisableBreakpointByID (break_id))
+    {
+        if (LLDB_BREAK_ID_IS_INTERNAL (break_id))
+            m_internal_breakpoint_list.Remove(break_id);
+        else
+            m_breakpoint_list.Remove(break_id);
+        return true;
+    }
+    return false;
+}
+
+bool
+Target::DisableBreakpointByID (break_id_t break_id)
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+    if (log)
+        log->Printf ("Target::%s (break_id = %i, internal = %s)\n", __FUNCTION__, break_id, LLDB_BREAK_ID_IS_INTERNAL (break_id) ? "yes" : "no");
+
+    BreakpointSP bp_sp;
+
+    if (LLDB_BREAK_ID_IS_INTERNAL (break_id))
+        bp_sp = m_internal_breakpoint_list.FindBreakpointByID (break_id);
+    else
+        bp_sp = m_breakpoint_list.FindBreakpointByID (break_id);
+    if (bp_sp)
+    {
+        bp_sp->SetEnabled (false);
+        return true;
+    }
+    return false;
+}
+
+bool
+Target::EnableBreakpointByID (break_id_t break_id)
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+    if (log)
+        log->Printf ("Target::%s (break_id = %i, internal = %s)\n",
+                     __FUNCTION__,
+                     break_id,
+                     LLDB_BREAK_ID_IS_INTERNAL (break_id) ? "yes" : "no");
+
+    BreakpointSP bp_sp;
+
+    if (LLDB_BREAK_ID_IS_INTERNAL (break_id))
+        bp_sp = m_internal_breakpoint_list.FindBreakpointByID (break_id);
+    else
+        bp_sp = m_breakpoint_list.FindBreakpointByID (break_id);
+
+    if (bp_sp)
+    {
+        bp_sp->SetEnabled (true);
+        return true;
+    }
+    return false;
+}
+
+ModuleSP
+Target::GetExecutableModule ()
+{
+    ModuleSP executable_sp;
+    if (m_images.GetSize() > 0)
+        executable_sp = m_images.GetModuleAtIndex(0);
+    return executable_sp;
+}
+
+void
+Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files)
+{
+    m_images.Clear();
+    m_scratch_ast_context_ap.reset();
+    
+    if (executable_sp.get())
+    {
+        Timer scoped_timer (__PRETTY_FUNCTION__,
+                            "Target::SetExecutableModule (executable = '%s/%s')",
+                            executable_sp->GetFileSpec().GetDirectory().AsCString(),
+                            executable_sp->GetFileSpec().GetFilename().AsCString());
+
+        m_images.Append(executable_sp); // The first image is our exectuable file
+
+        ArchSpec exe_arch = executable_sp->GetArchitecture();
+        FileSpecList dependent_files;
+        ObjectFile * executable_objfile = executable_sp->GetObjectFile();
+        if (executable_objfile == NULL)
+        {
+
+            FileSpec bundle_executable(executable_sp->GetFileSpec());
+            if (Host::ResolveExecutableInBundle (&bundle_executable))
+            {
+                ModuleSP bundle_exe_module_sp(GetSharedModule(bundle_executable,
+                                                              exe_arch));
+                SetExecutableModule (bundle_exe_module_sp, get_dependent_files);
+                if (bundle_exe_module_sp->GetObjectFile() != NULL)
+                    executable_sp = bundle_exe_module_sp;
+                return;
+            }
+        }
+
+        if (executable_objfile)
+        {
+            executable_objfile->GetDependentModules(dependent_files);
+            for (uint32_t i=0; i<dependent_files.GetSize(); i++)
+            {
+                ModuleSP image_module_sp(GetSharedModule(dependent_files.GetFileSpecPointerAtIndex(i),
+                                                         exe_arch));
+                if (image_module_sp.get())
+                {
+                    //image_module_sp->Dump(&s);// REMOVE THIS, DEBUG ONLY
+                    ObjectFile *objfile = image_module_sp->GetObjectFile();
+                    if (objfile)
+                        objfile->GetDependentModules(dependent_files);
+                }
+            }
+        }
+        
+        // Now see if we know the target triple, and if so, create our scratch AST context:
+        ConstString target_triple;
+        if (GetTargetTriple(target_triple))
+        {
+            m_scratch_ast_context_ap.reset (new ClangASTContext(target_triple.GetCString()));
+        }
+    }
+}
+
+
+ModuleList&
+Target::GetImages ()
+{
+    return m_images;
+}
+
+ArchSpec
+Target::GetArchitecture () const
+{
+    ArchSpec arch;
+    if (m_images.GetSize() > 0)
+    {
+        Module *exe_module = m_images.GetModulePointerAtIndex(0);
+        if (exe_module)
+            arch = exe_module->GetArchitecture();
+    }
+    return arch;
+}
+
+
+
+bool
+Target::GetTargetTriple(ConstString &triple)
+{
+    triple.Clear();
+
+    if (m_triple)
+    {
+        triple = m_triple;
+    }
+    else
+    {
+        Module *exe_module = GetExecutableModule().get();
+        if (exe_module)
+        {
+            ObjectFile *objfile = exe_module->GetObjectFile();
+            if (objfile)
+            {
+                objfile->GetTargetTriple(m_triple);
+                triple = m_triple;
+            }
+        }
+    }
+    return !triple.IsEmpty();
+}
+
+void
+Target::ModuleAdded (ModuleSP &module_sp)
+{
+    // A module is being added to this target for the first time
+    ModuleList module_list;
+    module_list.Append(module_sp);
+    ModulesDidLoad (module_list);
+}
+
+void
+Target::ModuleUpdated (ModuleSP &old_module_sp, ModuleSP &new_module_sp)
+{
+    // A module is being added to this target for the first time
+    ModuleList module_list;
+    module_list.Append (old_module_sp);
+    ModulesDidUnload (module_list);
+    module_list.Clear ();
+    module_list.Append (new_module_sp);
+    ModulesDidLoad (module_list);
+}
+
+void
+Target::ModulesDidLoad (ModuleList &module_list)
+{
+    m_breakpoint_list.UpdateBreakpoints (module_list, true);
+    // TODO: make event data that packages up the module_list
+    BroadcastEvent (eBroadcastBitModulesLoaded, NULL);
+}
+
+void
+Target::ModulesDidUnload (ModuleList &module_list)
+{
+    m_breakpoint_list.UpdateBreakpoints (module_list, false);
+    // TODO: make event data that packages up the module_list
+    BroadcastEvent (eBroadcastBitModulesUnloaded, NULL);
+}
+
+size_t
+Target::ReadMemory
+(
+    lldb::AddressType addr_type,
+    lldb::addr_t addr,
+    void *dst,
+    size_t dst_len,
+    Error &error,
+    ObjectFile* objfile
+)
+{
+    size_t bytes_read = 0;
+    error.Clear();
+    switch (addr_type)
+    {
+    case eAddressTypeFile:
+        if (objfile)
+        {
+            if (m_process_sp.get())
+            {
+                // If we have an execution context with a process, lets try and
+                // resolve the file address in "objfile" and read it from the
+                // process
+                Address so_addr(addr, objfile->GetSectionList());
+                lldb::addr_t load_addr = so_addr.GetLoadAddress(m_process_sp.get());
+                if (load_addr == LLDB_INVALID_ADDRESS)
+                {
+                    if (objfile->GetFileSpec())
+                        error.SetErrorStringWithFormat("0x%llx can't be resolved, %s in not currently loaded.\n", addr, objfile->GetFileSpec().GetFilename().AsCString());
+                    else
+                        error.SetErrorStringWithFormat("0x%llx can't be resolved.\n", addr, objfile->GetFileSpec().GetFilename().AsCString());
+                }
+                else
+                {
+                    bytes_read = m_process_sp->ReadMemory(load_addr, dst, dst_len, error);
+                    if (bytes_read != dst_len)
+                    {
+                        if (error.Success())
+                        {
+                            if (bytes_read == 0)
+                                error.SetErrorStringWithFormat("Read memory from 0x%llx failed.\n", load_addr);
+                            else
+                                error.SetErrorStringWithFormat("Only %zu of %zu bytes were read from memory at 0x%llx.\n", bytes_read, dst_len, load_addr);
+                        }
+                    }
+                }
+            }
+            else
+            {
+                // Try and read the file based address from the object file's
+                // section data.
+            }
+        }
+        break;
+
+    case eAddressTypeLoad:
+        if (m_process_sp.get())
+        {
+            bytes_read = m_process_sp->ReadMemory(addr, dst, dst_len, error);
+            if (bytes_read != dst_len)
+            {
+                if (error.Success())
+                {
+                    if (bytes_read == 0)
+                        error.SetErrorStringWithFormat("Read memory from 0x%llx failed.\n", addr);
+                    else
+                        error.SetErrorStringWithFormat("Only %zu of %zu bytes were read from memory at 0x%llx.\n", bytes_read, dst_len, addr);
+                }
+            }
+        }
+        else
+            error.SetErrorStringWithFormat("Need valid process to read load address.\n");
+        break;
+
+    case eAddressTypeHost:
+        // The address is an address in this process, so just copy it
+        ::memcpy (dst, (uint8_t*)NULL + addr, dst_len);
+        break;
+
+    default:
+        error.SetErrorStringWithFormat ("Unsupported lldb::AddressType value (%i).\n", addr_type);
+        break;
+    }
+    return bytes_read;
+}
+
+
+ModuleSP
+Target::GetSharedModule
+(
+    const FileSpec& file_spec,
+    const ArchSpec& arch,
+    const UUID *uuid_ptr,
+    const ConstString *object_name,
+    off_t object_offset,
+    Error *error_ptr
+)
+{
+    // Don't pass in the UUID so we can tell if we have a stale value in our list
+    ModuleSP old_module_sp; // This will get filled in if we have a new version of the library
+    bool did_create_module = false;
+    ModuleSP module_sp;
+
+    // If there are image search path entries, try to use them first to acquire a suitable image.
+
+    Error error;
+
+    if (m_image_search_paths.GetSize())
+    {
+        FileSpec transformed_spec;        
+        if (m_image_search_paths.RemapPath (file_spec.GetDirectory(), transformed_spec.GetDirectory()))
+        {
+            transformed_spec.GetFilename() = file_spec.GetFilename();
+            error = ModuleList::GetSharedModule (transformed_spec, arch, uuid_ptr, object_name, object_offset, module_sp, &old_module_sp, &did_create_module);
+        }
+    }
+
+    // If a module hasn't been found yet, use the unmodified path.
+
+    if (!module_sp)
+    {
+        error = (ModuleList::GetSharedModule (file_spec, arch, uuid_ptr, object_name, object_offset, module_sp, &old_module_sp, &did_create_module));
+    }
+
+    if (module_sp)
+    {
+        m_images.Append (module_sp);
+        if (did_create_module)
+        {
+            if (old_module_sp && m_images.GetIndexForModule (old_module_sp.get()) != LLDB_INVALID_INDEX32)
+                ModuleUpdated(old_module_sp, module_sp);
+            else
+                ModuleAdded(module_sp);
+        }
+    }
+    if (error_ptr)
+        *error_ptr = error;
+    return module_sp;
+}
+
+
+Target *
+Target::CalculateTarget ()
+{
+    return this;
+}
+
+Process *
+Target::CalculateProcess ()
+{
+    return NULL;
+}
+
+Thread *
+Target::CalculateThread ()
+{
+    return NULL;
+}
+
+StackFrame *
+Target::CalculateStackFrame ()
+{
+    return NULL;
+}
+
+void
+Target::Calculate (ExecutionContext &exe_ctx)
+{
+    exe_ctx.target = this;
+    exe_ctx.process = NULL; // Do NOT fill in process...
+    exe_ctx.thread = NULL;
+    exe_ctx.frame = NULL;
+}
+
+PathMappingList &
+Target::GetImageSearchPathList ()
+{
+    return m_image_search_paths;
+}
+
+void
+Target::ImageSearchPathsChanged 
+(
+    const PathMappingList &path_list,
+    void *baton
+)
+{
+    Target *target = (Target *)baton;
+    if (target->m_images.GetSize() > 1)
+    {
+        ModuleSP exe_module_sp (target->GetExecutableModule());
+        if (exe_module_sp)
+        {
+            target->m_images.Clear();
+            target->SetExecutableModule (exe_module_sp, true);
+        }
+    }
+}
+
+ClangASTContext *
+Target::GetScratchClangASTContext()
+{
+    return m_scratch_ast_context_ap.get();
+}
diff --git a/source/Target/TargetList.cpp b/source/Target/TargetList.cpp
new file mode 100644
index 0000000..d929400
--- /dev/null
+++ b/source/Target/TargetList.cpp
@@ -0,0 +1,342 @@
+//===-- TargetList.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
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Broadcaster.h"
+#include "lldb/Core/Event.h"
+#include "lldb/Core/State.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/TargetList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+//----------------------------------------------------------------------
+// TargetList constructor
+//----------------------------------------------------------------------
+TargetList::TargetList() :
+    Broadcaster("TargetList"),
+    m_target_list(),
+    m_target_list_mutex (Mutex::eMutexTypeRecursive),
+    m_current_target_idx (0)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+TargetList::~TargetList()
+{
+    Mutex::Locker locker(m_target_list_mutex);
+    m_target_list.clear();
+}
+
+Error
+TargetList::CreateTarget
+(
+    const FileSpec& file,
+    const ArchSpec& arch,
+    const UUID *uuid_ptr,
+    bool get_dependent_files,
+    TargetSP &target_sp
+)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "TargetList::CreateTarget (file = '%s/%s', arch = '%s', uuid = %p)",
+                        file.GetDirectory().AsCString(),
+                        file.GetFilename().AsCString(),
+                        arch.AsCString(),
+                        uuid_ptr);
+    ModuleSP exe_module_sp;
+    FileSpec resolved_file(file);
+    if (!Host::ResolveExecutableInBundle (&resolved_file))
+        resolved_file = file;
+
+    Error error = ModuleList::GetSharedModule(resolved_file, 
+                                              arch, 
+                                              uuid_ptr, 
+                                              NULL, 
+                                              0, 
+                                              exe_module_sp, 
+                                              NULL, 
+                                              NULL);
+    if (exe_module_sp)
+    {
+        target_sp.reset(new Target);
+        target_sp->SetExecutableModule (exe_module_sp, get_dependent_files);
+
+        if (target_sp.get())
+        {
+            Mutex::Locker locker(m_target_list_mutex);
+            m_current_target_idx = m_target_list.size();
+            m_target_list.push_back(target_sp);
+        }
+
+//        target_sp.reset(new Target);
+//        // Let the target resolve any funky bundle paths before we try and get
+//        // the object file...
+//        target_sp->SetExecutableModule (exe_module_sp, get_dependent_files);
+//        if (exe_module_sp->GetObjectFile() == NULL)
+//        {
+//            error.SetErrorStringWithFormat("%s%s%s: doesn't contain architecture %s",
+//                                           file.GetDirectory().AsCString(),
+//                                           file.GetDirectory() ? "/" : "",
+//                                           file.GetFilename().AsCString(),
+//                                           arch.AsCString());
+//        }
+//        else
+//        {
+//            if (target_sp.get())
+//            {
+//                error.Clear();
+//                Mutex::Locker locker(m_target_list_mutex);
+//                m_current_target_idx = m_target_list.size();
+//                m_target_list.push_back(target_sp);
+//            }
+//        }
+    }
+    else
+    {
+        target_sp.reset();
+    }
+
+    return error;
+}
+
+bool
+TargetList::DeleteTarget (TargetSP &target_sp)
+{
+    Mutex::Locker locker(m_target_list_mutex);
+    collection::iterator pos, end = m_target_list.end();
+
+    for (pos = m_target_list.begin(); pos != end; ++pos)
+    {
+        if (pos->get() == target_sp.get())
+        {
+            m_target_list.erase(pos);
+            return true;
+        }
+    }
+    return false;
+}
+
+
+TargetSP
+TargetList::FindTargetWithExecutableAndArchitecture
+(
+    const FileSpec &exe_file_spec,
+    const ArchSpec *exe_arch_ptr
+) const
+{
+    Mutex::Locker locker (m_target_list_mutex);
+    TargetSP target_sp;
+    bool full_match = exe_file_spec.GetDirectory();
+
+    collection::const_iterator pos, end = m_target_list.end();
+    for (pos = m_target_list.begin(); pos != end; ++pos)
+    {
+        ModuleSP module_sp ((*pos)->GetExecutableModule());
+
+        if (module_sp)
+        {
+            if (FileSpec::Equal (exe_file_spec, module_sp->GetFileSpec(), full_match))
+            {
+                if (exe_arch_ptr)
+                {
+                    if (*exe_arch_ptr != module_sp->GetArchitecture())
+                        continue;
+                }
+                target_sp = *pos;
+                break;
+            }
+        }
+    }
+    return target_sp;
+}
+
+TargetSP
+TargetList::FindTargetWithProcessID (lldb::pid_t pid) const
+{
+    Mutex::Locker locker(m_target_list_mutex);
+    TargetSP target_sp;
+    collection::const_iterator pos, end = m_target_list.end();
+    for (pos = m_target_list.begin(); pos != end; ++pos)
+    {
+        Process* process = (*pos)->GetProcessSP().get();
+        if (process && process->GetID() == pid)
+        {
+            target_sp = *pos;
+            break;
+        }
+    }
+    return target_sp;
+}
+
+
+TargetSP
+TargetList::FindTargetWithProcess (Process *process) const
+{
+    TargetSP target_sp;
+    if (process)
+    {
+        Mutex::Locker locker(m_target_list_mutex);
+        collection::const_iterator pos, end = m_target_list.end();
+        for (pos = m_target_list.begin(); pos != end; ++pos)
+        {
+            if (process == (*pos)->GetProcessSP().get())
+            {
+                target_sp = *pos;
+                break;
+            }
+        }
+    }
+    return target_sp;
+}
+
+TargetSP
+TargetList::GetTargetSP (Target *target) const
+{
+    TargetSP target_sp;
+    if (target)
+    {
+        Mutex::Locker locker(m_target_list_mutex);
+        collection::const_iterator pos, end = m_target_list.end();
+        for (pos = m_target_list.begin(); pos != end; ++pos)
+        {
+            if (target == (*pos).get())
+            {
+                target_sp = *pos;
+                break;
+            }
+        }
+    }
+    return target_sp;
+}
+
+uint32_t
+TargetList::SendAsyncInterrupt (lldb::pid_t pid)
+{
+    uint32_t num_async_interrupts_sent = 0;
+
+    if (pid != LLDB_INVALID_PROCESS_ID)
+    {
+        TargetSP target_sp(FindTargetWithProcessID (pid));
+        if (target_sp.get())
+        {
+            Process* process = target_sp->GetProcessSP().get();
+            if (process)
+            {
+                process->BroadcastEvent (Process::eBroadcastBitInterrupt, NULL);
+                ++num_async_interrupts_sent;
+            }
+        }
+    }
+    else
+    {
+        // We don't have a valid pid to broadcast to, so broadcast to the target
+        // list's async broadcaster...
+        BroadcastEvent (Process::eBroadcastBitInterrupt, NULL);
+    }
+
+    return num_async_interrupts_sent;
+}
+
+uint32_t
+TargetList::SignalIfRunning (lldb::pid_t pid, int signo)
+{
+    uint32_t num_signals_sent = 0;
+    Process *process = NULL;
+    if (pid == LLDB_INVALID_PROCESS_ID)
+    {
+        // Signal all processes with signal
+        Mutex::Locker locker(m_target_list_mutex);
+        collection::iterator pos, end = m_target_list.end();
+        for (pos = m_target_list.begin(); pos != end; ++pos)
+        {
+            process = (*pos)->GetProcessSP().get();
+            if (process)
+            {
+                if (process->IsAlive())
+                {
+                    ++num_signals_sent;
+                    process->Signal (signo);
+                }
+            }
+        }
+    }
+    else
+    {
+        // Signal a specific process with signal
+        TargetSP target_sp(FindTargetWithProcessID (pid));
+        if (target_sp.get())
+        {
+            process = target_sp->GetProcessSP().get();
+            if (process)
+            {
+                if (process->IsAlive())
+                {
+                    ++num_signals_sent;
+                    process->Signal (signo);
+                }
+            }
+        }
+    }
+    return num_signals_sent;
+}
+
+int
+TargetList::GetNumTargets () const
+{
+    Mutex::Locker locker (m_target_list_mutex);
+    return m_target_list.size();
+}
+
+lldb::TargetSP
+TargetList::GetTargetAtIndex (uint32_t idx) const
+{
+    TargetSP target_sp;
+    Mutex::Locker locker (m_target_list_mutex);
+    if (idx < m_target_list.size())
+        target_sp = m_target_list[idx];
+    return target_sp;
+}
+
+uint32_t
+TargetList::SetCurrentTarget (Target* target)
+{
+    Mutex::Locker locker (m_target_list_mutex);
+    collection::const_iterator pos,
+        begin = m_target_list.begin(),
+        end = m_target_list.end();
+    for (pos = begin; pos != end; ++pos)
+    {
+        if (pos->get() == target)
+        {
+            m_current_target_idx = std::distance (begin, pos);
+            return m_current_target_idx;
+        }
+    }
+    m_current_target_idx = 0;
+    return m_current_target_idx;
+}
+
+lldb::TargetSP
+TargetList::GetCurrentTarget ()
+{
+    Mutex::Locker locker (m_target_list_mutex);
+    if (m_current_target_idx >= m_target_list.size())
+        m_current_target_idx = 0;
+    return GetTargetAtIndex (m_current_target_idx);
+}
diff --git a/source/Target/Thread.cpp b/source/Target/Thread.cpp
new file mode 100644
index 0000000..2f852cc
--- /dev/null
+++ b/source/Target/Thread.cpp
@@ -0,0 +1,1121 @@
+//===-- Thread.cpp ----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-private-log.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanCallFunction.h"
+#include "lldb/Target/ThreadPlanContinue.h"
+#include "lldb/Target/ThreadPlanBase.h"
+#include "lldb/Target/ThreadPlanStepInstruction.h"
+#include "lldb/Target/ThreadPlanStepOut.h"
+#include "lldb/Target/ThreadPlanStepOverBreakpoint.h"
+#include "lldb/Target/ThreadPlanStepThrough.h"
+#include "lldb/Target/ThreadPlanStepInRange.h"
+#include "lldb/Target/ThreadPlanStepOverRange.h"
+#include "lldb/Target/ThreadPlanRunToAddress.h"
+#include "lldb/Target/ThreadPlanStepUntil.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+Thread::Thread (Process &process, lldb::tid_t tid) :
+    UserID (tid),
+    m_index_id (process.GetNextThreadIndexID ()),
+    m_reg_context_sp (),
+    m_process (process),
+    m_state (eStateUnloaded),
+    m_plan_stack (),
+    m_immediate_plan_stack(),
+    m_completed_plan_stack(),
+    m_state_mutex (Mutex::eMutexTypeRecursive),
+    m_frames (),
+    m_current_frame_idx (0),
+    m_resume_signal (LLDB_INVALID_SIGNAL_NUMBER),
+    m_resume_state (eStateRunning)
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT);
+    if (log)
+        log->Printf ("%p Thread::Thread(tid = 0x%4.4x)", this, GetID());
+
+    QueueFundamentalPlan(true);
+}
+
+
+Thread::~Thread()
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT);
+    if (log)
+        log->Printf ("%p Thread::~Thread(tid = 0x%4.4x)", this, GetID());
+}
+
+int
+Thread::GetResumeSignal () const
+{
+    return m_resume_signal;
+}
+
+void
+Thread::SetResumeSignal (int signal)
+{
+    m_resume_signal = signal;
+}
+
+StateType
+Thread::GetResumeState () const
+{
+    return m_resume_state;
+}
+
+void
+Thread::SetResumeState (StateType state)
+{
+    m_resume_state = state;
+}
+
+Thread::StopInfo::StopInfo(Thread *thread) :
+    m_reason (eStopReasonInvalid),
+    m_description (),
+    m_thread (thread),
+    m_details ()
+{
+    m_description[0] = '\0';
+}
+
+Thread::StopInfo::~StopInfo()
+{
+}
+
+
+void
+Thread::StopInfo::Clear()
+{
+    m_reason = eStopReasonInvalid;
+    m_completed_plan_sp.reset();
+    m_description[0] = '\0';
+    ::bzero (&m_details, sizeof(m_details));
+}
+
+StopReason
+Thread::StopInfo::GetStopReason() const
+{
+    return m_reason;
+}
+
+const char *
+Thread::StopInfo::GetStopDescription() const
+{
+    if (m_description[0])
+        return m_description;
+    return NULL;
+}
+
+void
+Thread::StopInfo::SetStopDescription(const char *desc)
+{
+    if (desc && desc[0])
+    {
+        ::snprintf (m_description, sizeof(m_description), "%s", desc);
+    }
+    else
+    {
+        m_description[0] = '\0';
+    }
+}
+
+void
+Thread::StopInfo::SetThread (Thread* thread)
+{
+    m_thread = thread;
+}
+
+Thread *
+Thread::StopInfo::GetThread ()
+{
+    return m_thread;
+}
+
+lldb::user_id_t
+Thread::StopInfo::GetBreakpointSiteID() const
+{
+    if (m_reason == eStopReasonBreakpoint)
+        return m_details.breakpoint.bp_site_id;
+    return LLDB_INVALID_BREAK_ID;
+}
+
+void
+Thread::StopInfo::SetStopReasonWithBreakpointSiteID (lldb::user_id_t bp_site_id)
+{
+    m_reason = eStopReasonBreakpoint;
+    m_details.breakpoint.bp_site_id = bp_site_id;
+}
+
+lldb::user_id_t
+Thread::StopInfo::GetWatchpointID() const
+{
+    if (m_reason == eStopReasonWatchpoint)
+        return m_details.watchpoint.watch_id;
+    return LLDB_INVALID_WATCH_ID;
+}
+
+void
+Thread::StopInfo::SetStopReasonWithWatchpointID (lldb::user_id_t watch_id)
+{
+    m_reason = eStopReasonWatchpoint;
+    m_details.watchpoint.watch_id = watch_id;
+}
+
+
+int
+Thread::StopInfo::GetSignal() const
+{
+    if (m_reason == eStopReasonSignal)
+        return m_details.signal.signo;
+    return 0;
+}
+
+lldb::user_id_t
+Thread::StopInfo::GetPlanID() const
+{
+    if (m_reason == eStopReasonPlanComplete)
+        return m_completed_plan_sp->GetID();
+    return LLDB_INVALID_UID;
+}
+
+void
+Thread::StopInfo::SetStopReasonWithSignal (int signo)
+{
+    m_reason = eStopReasonSignal;
+    m_details.signal.signo = signo;
+}
+
+void
+Thread::StopInfo::SetStopReasonToTrace ()
+{
+    m_reason = eStopReasonTrace;
+}
+
+uint32_t
+Thread::StopInfo::GetExceptionType() const
+{
+    if (m_reason == eStopReasonException)
+        return m_details.exception.type;
+    return 0;
+}
+
+size_t
+Thread::StopInfo::GetExceptionDataCount() const
+{
+    if (m_reason == eStopReasonException)
+        return m_details.exception.data_count;
+    return 0;
+}
+
+void
+Thread::StopInfo::SetStopReasonWithException (uint32_t exc_type, size_t exc_data_count)
+{
+    m_reason = eStopReasonException;
+    m_details.exception.type = exc_type;
+    m_details.exception.data_count = exc_data_count;
+}
+
+void
+Thread::StopInfo::SetStopReasonWithPlan (ThreadPlanSP &thread_plan_sp)
+{
+    m_reason = eStopReasonPlanComplete;
+    m_completed_plan_sp = thread_plan_sp;
+}
+
+void
+Thread::StopInfo::SetStopReasonToNone ()
+{
+    Clear();
+    m_reason = eStopReasonNone;
+}
+
+lldb::addr_t
+Thread::StopInfo::GetExceptionDataAtIndex (uint32_t idx) const
+{
+    if (m_reason == eStopReasonException && idx < m_details.exception.data_count)
+        return m_details.exception.data[idx];
+    return 0;
+
+}
+
+
+bool
+Thread::StopInfo::SetExceptionDataAtIndex (uint32_t idx, lldb::addr_t data)
+{
+    if (m_reason == eStopReasonException && idx < m_details.exception.data_count)
+    {
+        m_details.exception.data[idx] = data;
+        return true;
+    }
+    return false;
+}
+
+void
+Thread::StopInfo::Dump (Stream *s) const
+{
+    if (m_description[0])
+        s->Printf("%s", m_description);
+    else
+    {
+        switch (m_reason)
+        {
+        case eStopReasonInvalid:
+            s->PutCString("invalid");
+            break;
+
+        case eStopReasonNone:
+            s->PutCString("none");
+            break;
+
+        case eStopReasonTrace:
+            s->PutCString("trace");
+            break;
+
+        case eStopReasonBreakpoint:
+            {
+                bool no_details = true;
+                s->PutCString ("breakpoint ");
+                if (m_thread)
+                {
+                    BreakpointSiteSP bp_site_sp = m_thread->GetProcess().GetBreakpointSiteList().FindByID(m_details.breakpoint.bp_site_id);
+                    if (bp_site_sp)
+                    {
+                        bp_site_sp->GetDescription(s, lldb::eDescriptionLevelBrief);
+                        no_details = false;
+                    }
+                }
+
+                if (no_details)
+                    s->Printf ("site id: %d", m_details.breakpoint.bp_site_id);
+            }
+            break;
+
+        case eStopReasonWatchpoint:
+            s->Printf("watchpoint (site id = %u)", m_details.watchpoint.watch_id);
+            break;
+
+        case eStopReasonSignal:
+            {
+                s->Printf("signal: signo = %i", m_details.signal.signo);
+                const char * signal_name = m_thread->GetProcess().GetUnixSignals().GetSignalAsCString (m_details.signal.signo);
+                if (signal_name)
+                    s->Printf(" (%s)", signal_name);
+            }
+            break;
+
+        case eStopReasonException:
+            {
+                s->Printf("exception: type = 0x%8.8x, data_count = %zu", m_details.exception.type, m_details.exception.data_count);
+                uint32_t i;
+                for (i=0; i<m_details.exception.data_count; ++i)
+                {
+                    s->Printf(", data[%u] = 0x%8.8llx", i, m_details.exception.data[i]);
+                }
+            }
+            break;
+
+        case eStopReasonPlanComplete:
+            {
+                m_completed_plan_sp->GetDescription (s, lldb::eDescriptionLevelBrief);
+            }
+            break;
+        }
+    }
+}
+
+bool
+Thread::GetStopInfo (Thread::StopInfo *stop_info)
+{
+    stop_info->SetThread(this);
+    ThreadPlanSP completed_plan = GetCompletedPlan();
+    if (completed_plan != NULL)
+    {
+        stop_info->Clear ();
+        stop_info->SetStopReasonWithPlan (completed_plan);
+        return true;
+    }
+    else
+        return GetRawStopReason (stop_info);
+}
+
+bool
+Thread::ThreadStoppedForAReason (void)
+{
+    Thread::StopInfo stop_info;
+    stop_info.SetThread(this);
+    if (GetRawStopReason (&stop_info))
+    {
+        StopReason reason = stop_info.GetStopReason();
+        if (reason == eStopReasonInvalid || reason == eStopReasonNone)
+            return false;
+        else
+            return true;
+    }
+    else
+        return false;
+}
+
+StateType
+Thread::GetState() const
+{
+    // If any other threads access this we will need a mutex for it
+    Mutex::Locker locker(m_state_mutex);
+    return m_state;
+}
+
+void
+Thread::SetState(StateType state)
+{
+    Mutex::Locker locker(m_state_mutex);
+    m_state = state;
+}
+
+void
+Thread::WillStop()
+{
+    ThreadPlan *current_plan = GetCurrentPlan();
+
+    // FIXME: I may decide to disallow threads with no plans.  In which
+    // case this should go to an assert.
+
+    if (!current_plan)
+        return;
+
+    current_plan->WillStop();
+}
+
+void
+Thread::SetupForResume ()
+{
+    if (GetResumeState() != eStateSuspended)
+    {
+    
+        // If we're at a breakpoint push the step-over breakpoint plan.  Do this before
+        // telling the current plan it will resume, since we might change what the current
+        // plan is.
+
+        lldb::addr_t pc = GetRegisterContext()->GetPC();
+        BreakpointSiteSP bp_site_sp = GetProcess().GetBreakpointSiteList().FindByAddress(pc);
+        if (bp_site_sp && bp_site_sp->IsEnabled())
+        {
+            // Note, don't assume there's a ThreadPlanStepOverBreakpoint, the target may not require anything
+            // special to step over a breakpoint.
+            
+            ThreadPlan *cur_plan = GetCurrentPlan();
+            ThreadPlanStepOverBreakpoint *step_over_bp = dynamic_cast<ThreadPlanStepOverBreakpoint *> (cur_plan);
+            if (step_over_bp == NULL)
+            {
+
+                ThreadPlanSP step_bp_plan_sp (new ThreadPlanStepOverBreakpoint (*this));
+                if (step_bp_plan_sp)
+                {
+                    if (GetCurrentPlan()->RunState() != eStateStepping)
+                    {
+                        ThreadPlanSP continue_plan_sp (new ThreadPlanContinue(*this, false, eVoteNo, eVoteNoOpinion));
+                        continue_plan_sp->SetPrivate (true);
+                        QueueThreadPlan (continue_plan_sp, false);
+                    }
+                    step_bp_plan_sp->SetPrivate (true);
+                    QueueThreadPlan (step_bp_plan_sp, false);
+                }
+            }
+        }
+    }
+}
+
+bool
+Thread::WillResume (StateType resume_state)
+{
+    // At this point clear the completed plan stack.
+    m_completed_plan_stack.clear();
+    m_discarded_plan_stack.clear();
+
+    // If this thread stopped with a signal, work out what its resume state should
+    // be.  Note if the thread resume state is already set, then don't override it,
+    // the user must have asked us to resume with some other signal.
+
+    if (GetResumeSignal() == LLDB_INVALID_SIGNAL_NUMBER)
+    {
+        Thread::StopInfo stop_info;
+        GetRawStopReason(&stop_info);
+
+        StopReason reason = stop_info.GetStopReason();
+        if (reason == eStopReasonSignal)
+        {
+            UnixSignals &signals = GetProcess().GetUnixSignals();
+            int32_t signo = stop_info.GetSignal();
+            if (!signals.GetShouldSuppress(signo))
+            {
+                SetResumeSignal(signo);
+            }
+        }
+    }
+    
+    // Tell all the plans that we are about to resume in case they need to clear any state.
+    // We distinguish between the plan on the top of the stack and the lower
+    // plans in case a plan needs to do any special business before it runs.
+    
+    ThreadPlan *plan_ptr = GetCurrentPlan();
+    plan_ptr->WillResume(resume_state, true);
+
+    while ((plan_ptr = GetPreviousPlan(plan_ptr)) != NULL)
+    {
+        plan_ptr->WillResume (resume_state, false);
+    }
+    return true;
+}
+
+void
+Thread::DidResume ()
+{
+    SetResumeSignal (LLDB_INVALID_SIGNAL_NUMBER);
+}
+
+bool
+Thread::ShouldStop (Event* event_ptr)
+{
+    ThreadPlan *current_plan = GetCurrentPlan();
+    bool should_stop = true;
+
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+    if (log)
+    {
+        StreamString s;
+        DumpThreadPlans(&s);
+        log->PutCString (s.GetData());
+    }
+
+    if (current_plan->PlanExplainsStop())
+    {
+        while (1)
+        {
+            should_stop = current_plan->ShouldStop(event_ptr);
+            if (current_plan->MischiefManaged())
+            {
+                if (should_stop)
+                    current_plan->WillStop();
+
+                // If a Master Plan wants to stop, and wants to stick on the stack, we let it.
+                // Otherwise, see if the plan's parent wants to stop.
+
+                if (should_stop && current_plan->IsMasterPlan() && !current_plan->OkayToDiscard())
+                {
+                    PopPlan();
+                    break;
+                }
+                else
+                {
+
+                    PopPlan();
+
+                    current_plan = GetCurrentPlan();
+                    if (current_plan == NULL)
+                    {
+                        break;
+                    }
+                }
+
+            }
+            else
+            {
+                break;
+            }
+        }
+    }
+    else
+    {
+        // If the current plan doesn't explain the stop, then, find one that
+        // does and let it handle the situation.
+        ThreadPlan *plan_ptr = current_plan;
+        while ((plan_ptr = GetPreviousPlan(plan_ptr)) != NULL)
+        {
+            if (plan_ptr->PlanExplainsStop())
+            {
+                should_stop = plan_ptr->ShouldStop (event_ptr);
+                break;
+            }
+
+        }
+    }
+
+    return should_stop;
+}
+
+Vote
+Thread::ShouldReportStop (Event* event_ptr)
+{
+    StateType thread_state = GetResumeState ();
+    if (thread_state == eStateSuspended
+            || thread_state == eStateInvalid)
+        return eVoteNoOpinion;
+
+    if (m_completed_plan_stack.size() > 0)
+    {
+        // Don't use GetCompletedPlan here, since that suppresses private plans.
+        return m_completed_plan_stack.back()->ShouldReportStop (event_ptr);
+    }
+    else
+        return GetCurrentPlan()->ShouldReportStop (event_ptr);
+}
+
+Vote
+Thread::ShouldReportRun (Event* event_ptr)
+{
+    StateType thread_state = GetResumeState ();
+    if (thread_state == eStateSuspended
+            || thread_state == eStateInvalid)
+        return eVoteNoOpinion;
+
+    if (m_completed_plan_stack.size() > 0)
+    {
+        // Don't use GetCompletedPlan here, since that suppresses private plans.
+        return m_completed_plan_stack.back()->ShouldReportRun (event_ptr);
+    }
+    else
+        return GetCurrentPlan()->ShouldReportRun (event_ptr);
+}
+
+void
+Thread::PushPlan (ThreadPlanSP &thread_plan_sp)
+{
+    if (thread_plan_sp)
+    {
+        if (thread_plan_sp->IsImmediate())
+            m_immediate_plan_stack.push_back (thread_plan_sp);
+        else
+            m_plan_stack.push_back (thread_plan_sp);
+
+        thread_plan_sp->DidPush();
+
+        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+        if (log)
+        {
+            StreamString s;
+            thread_plan_sp->GetDescription (&s, lldb::eDescriptionLevelFull);
+            log->Printf("Pushing plan: \"%s\" for thread: %d immediate: %s.",
+                        s.GetData(),
+                        thread_plan_sp->GetThread().GetID(),
+                        thread_plan_sp->IsImmediate() ? "true" : "false");
+        }
+    }
+}
+
+void
+Thread::PopPlan ()
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+
+    if (!m_immediate_plan_stack.empty())
+    {
+        ThreadPlanSP &plan = m_immediate_plan_stack.back();
+        if (log)
+        {
+            log->Printf("Popping plan: \"%s\" for thread: %d immediate: true.", plan->GetName(), plan->GetThread().GetID());
+        }
+        plan->WillPop();
+        m_immediate_plan_stack.pop_back();
+    }
+    else if (m_plan_stack.empty())
+        return;
+    else
+    {
+        ThreadPlanSP &plan = m_plan_stack.back();
+        if (log)
+        {
+            log->Printf("Popping plan: \"%s\" for thread: 0x%x immediate: false.", plan->GetName(), plan->GetThread().GetID());
+        }
+        m_completed_plan_stack.push_back (plan);
+        plan->WillPop();
+        m_plan_stack.pop_back();
+    }
+}
+
+void
+Thread::DiscardPlan ()
+{
+    if (m_plan_stack.size() > 1)
+    {
+        ThreadPlanSP &plan = m_plan_stack.back();
+        m_discarded_plan_stack.push_back (plan);
+        plan->WillPop();
+        m_plan_stack.pop_back();
+    }
+}
+
+ThreadPlan *
+Thread::GetCurrentPlan ()
+{
+    if (!m_immediate_plan_stack.empty())
+        return m_immediate_plan_stack.back().get();
+    else if (m_plan_stack.empty())
+        return NULL;
+    else
+        return m_plan_stack.back().get();
+}
+
+ThreadPlanSP
+Thread::GetCompletedPlan ()
+{
+    ThreadPlanSP empty_plan_sp;
+    if (!m_completed_plan_stack.empty())
+    {
+        for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--)
+        {
+            ThreadPlanSP completed_plan_sp;
+            completed_plan_sp = m_completed_plan_stack[i];
+            if (!completed_plan_sp->GetPrivate ())
+            return completed_plan_sp;
+        }
+    }
+    return empty_plan_sp;
+}
+
+bool
+Thread::IsThreadPlanDone (ThreadPlan *plan)
+{
+    ThreadPlanSP empty_plan_sp;
+    if (!m_completed_plan_stack.empty())
+    {
+        for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--)
+        {
+            if (m_completed_plan_stack[i].get() == plan)
+                return true;
+        }
+    }
+    return false;
+}
+
+bool
+Thread::WasThreadPlanDiscarded (ThreadPlan *plan)
+{
+    ThreadPlanSP empty_plan_sp;
+    if (!m_discarded_plan_stack.empty())
+    {
+        for (int i = m_discarded_plan_stack.size() - 1; i >= 0; i--)
+        {
+            if (m_discarded_plan_stack[i].get() == plan)
+                return true;
+        }
+    }
+    return false;
+}
+
+ThreadPlan *
+Thread::GetPreviousPlan (ThreadPlan *current_plan)
+{
+    if (current_plan == NULL)
+        return NULL;
+
+    int stack_size = m_completed_plan_stack.size();
+    for (int i = stack_size - 1; i > 0; i--)
+    {
+        if (current_plan == m_completed_plan_stack[i].get())
+            return m_completed_plan_stack[i-1].get();
+    }
+
+    if (stack_size > 0 && m_completed_plan_stack[0].get() == current_plan)
+    {
+        if (m_immediate_plan_stack.size() > 0)
+            return m_immediate_plan_stack.back().get();
+        else if (m_plan_stack.size() > 0)
+            return m_plan_stack.back().get();
+        else
+            return NULL;
+    }
+
+    stack_size = m_immediate_plan_stack.size();
+    for (int i = stack_size - 1; i > 0; i--)
+    {
+        if (current_plan == m_immediate_plan_stack[i].get())
+            return m_immediate_plan_stack[i-1].get();
+    }
+    if (stack_size > 0 && m_immediate_plan_stack[0].get() == current_plan)
+    {
+        if (m_plan_stack.size() > 0)
+            return m_plan_stack.back().get();
+        else
+            return NULL;
+    }
+
+    stack_size = m_plan_stack.size();
+    for (int i = stack_size - 1; i > 0; i--)
+    {
+        if (current_plan == m_plan_stack[i].get())
+            return m_plan_stack[i-1].get();
+    }
+    return NULL;
+}
+
+void
+Thread::QueueThreadPlan (ThreadPlanSP &thread_plan_sp, bool abort_other_plans)
+{
+    if (abort_other_plans)
+       DiscardThreadPlans(true);
+
+    PushPlan (thread_plan_sp);
+}
+
+void
+Thread::DiscardThreadPlans(bool force)
+{
+    // FIXME: It is not always safe to just discard plans.  Some, like the step over
+    // breakpoint trap can't be discarded in general (though you can if you plan to
+    // force a return from a function, for instance.
+    // For now I'm just not clearing immediate plans, but I need a way for plans to
+    // say they really need to be kept on, and then a way to override that.  Humm...
+
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+    if (log)
+    {
+        log->Printf("Discarding thread plans for thread: 0x%x: force %d.", GetID(), force);
+    }
+
+    if (force)
+    {
+        int stack_size = m_plan_stack.size();
+        for (int i = stack_size - 1; i > 0; i--)
+        {
+            DiscardPlan();
+        }
+        return;
+    }
+
+    while (1)
+    {
+
+        int master_plan_idx;
+        bool discard;
+
+        // Find the first master plan, see if it wants discarding, and if yes discard up to it.
+        for (master_plan_idx = m_plan_stack.size() - 1; master_plan_idx >= 0; master_plan_idx--)
+        {
+            if (m_plan_stack[master_plan_idx]->IsMasterPlan())
+            {
+                discard = m_plan_stack[master_plan_idx]->OkayToDiscard();
+                break;
+            }
+        }
+
+        if (discard)
+        {
+            // First pop all the dependent plans:
+            for (int i = m_plan_stack.size() - 1; i > master_plan_idx; i--)
+            {
+
+                // FIXME: Do we need a finalize here, or is the rule that "PrepareForStop"
+                // for the plan leaves it in a state that it is safe to pop the plan
+                // with no more notice?
+                DiscardPlan();
+            }
+
+            // Now discard the master plan itself.
+            // The bottom-most plan never gets discarded.  "OkayToDiscard" for it means
+            // discard it's dependent plans, but not it...
+            if (master_plan_idx > 0)
+            {
+                DiscardPlan();
+            }
+        }
+        else
+        {
+            // If the master plan doesn't want to get discarded, then we're done.
+            break;
+        }
+
+    }
+    // FIXME: What should we do about the immediate plans?
+}
+
+ThreadPlan *
+Thread::QueueFundamentalPlan (bool abort_other_plans)
+{
+    ThreadPlanSP thread_plan_sp (new ThreadPlanBase(*this));
+    QueueThreadPlan (thread_plan_sp, abort_other_plans);
+    return thread_plan_sp.get();
+}
+
+ThreadPlan *
+Thread::QueueThreadPlanForStepSingleInstruction (bool step_over, bool abort_other_plans, bool stop_other_threads)
+{
+    ThreadPlanSP thread_plan_sp (new ThreadPlanStepInstruction (*this, step_over, stop_other_threads, eVoteNoOpinion, eVoteNoOpinion));
+    QueueThreadPlan (thread_plan_sp, abort_other_plans);
+    return thread_plan_sp.get();
+}
+
+ThreadPlan *
+Thread::QueueThreadPlanForStepRange (bool abort_other_plans, StepType type, const AddressRange &range, const SymbolContext &addr_context, lldb::RunMode stop_other_threads)
+{
+    ThreadPlanSP thread_plan_sp;
+    if (type == eStepTypeInto)
+        thread_plan_sp.reset (new ThreadPlanStepInRange (*this, range, addr_context, stop_other_threads));
+    else
+        thread_plan_sp.reset (new ThreadPlanStepOverRange (*this, range, addr_context, stop_other_threads));
+
+    QueueThreadPlan (thread_plan_sp, abort_other_plans);
+    return thread_plan_sp.get();
+}
+
+
+ThreadPlan *
+Thread::QueueThreadPlanForStepOverBreakpointPlan (bool abort_other_plans)
+{
+    ThreadPlanSP thread_plan_sp (new ThreadPlanStepOverBreakpoint (*this));
+    QueueThreadPlan (thread_plan_sp, abort_other_plans);
+    return thread_plan_sp.get();
+}
+
+ThreadPlan *
+Thread::QueueThreadPlanForStepOut (bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
+        bool stop_other_threads, Vote stop_vote, Vote run_vote)
+{
+    ThreadPlanSP thread_plan_sp (new ThreadPlanStepOut (*this, addr_context, first_insn, stop_other_threads, stop_vote, run_vote));
+    QueueThreadPlan (thread_plan_sp, abort_other_plans);
+    return thread_plan_sp.get();
+}
+
+ThreadPlan *
+Thread::QueueThreadPlanForStepThrough (bool abort_other_plans, bool stop_other_threads)
+{
+    ThreadPlanSP thread_plan_sp(GetProcess().GetDynamicLoader()->GetStepThroughTrampolinePlan (*this, stop_other_threads));
+    if (thread_plan_sp.get() == NULL)
+    {
+        thread_plan_sp.reset(new ThreadPlanStepThrough (*this, stop_other_threads));
+        if (thread_plan_sp && !thread_plan_sp->ValidatePlan (NULL))
+            return false;
+    }
+    QueueThreadPlan (thread_plan_sp, abort_other_plans);
+    return thread_plan_sp.get();
+}
+
+ThreadPlan *
+Thread::QueueThreadPlanForContinue (bool abort_other_plans, bool stop_other_threads, Vote stop_vote, Vote run_vote, bool immediate)
+{
+    ThreadPlanSP thread_plan_sp (new ThreadPlanContinue (*this, stop_other_threads, stop_vote, run_vote, immediate));
+    QueueThreadPlan (thread_plan_sp, abort_other_plans);
+    return thread_plan_sp.get();
+}
+
+ThreadPlan *
+Thread::QueueThreadPlanForCallFunction (bool abort_other_plans,
+                                        Address& function,
+                                        lldb::addr_t arg,
+                                        bool stop_other_threads,
+                                        bool discard_on_error)
+{
+    ThreadPlanSP thread_plan_sp (new ThreadPlanCallFunction (*this, function, arg, stop_other_threads, discard_on_error));
+    QueueThreadPlan (thread_plan_sp, abort_other_plans);
+    return thread_plan_sp.get();
+}
+
+ThreadPlan *
+Thread::QueueThreadPlanForCallFunction (bool abort_other_plans,
+                                        Address& function,
+                                        ValueList &args,
+                                        bool stop_other_threads,
+                                        bool discard_on_error)
+{
+    ThreadPlanSP thread_plan_sp (new ThreadPlanCallFunction (*this, function, args, stop_other_threads, discard_on_error));
+    QueueThreadPlan (thread_plan_sp, abort_other_plans);
+    return thread_plan_sp.get();
+}
+
+ThreadPlan *
+Thread::QueueThreadPlanForRunToAddress (bool abort_other_plans,
+                                        Address &target_addr,
+                                        bool stop_other_threads)
+{
+    ThreadPlanSP thread_plan_sp (new ThreadPlanRunToAddress (*this, target_addr, stop_other_threads));
+    QueueThreadPlan (thread_plan_sp, abort_other_plans);
+    return thread_plan_sp.get();
+}
+
+ThreadPlan *
+Thread::QueueThreadPlanForStepUntil (bool abort_other_plans,
+                                       lldb::addr_t *address_list,
+                                       size_t num_addresses,
+                                       bool stop_other_threads)
+{
+    ThreadPlanSP thread_plan_sp (new ThreadPlanStepUntil (*this, address_list, num_addresses, stop_other_threads));
+    QueueThreadPlan (thread_plan_sp, abort_other_plans);
+    return thread_plan_sp.get();
+
+}
+
+uint32_t
+Thread::GetIndexID () const
+{
+    return m_index_id;
+}
+
+void
+Thread::DumpThreadPlans (lldb_private::Stream *s) const
+{
+    uint32_t stack_size = m_plan_stack.size();
+    s->Printf ("Plan Stack: %d elements.\n", stack_size);
+    for (int i = stack_size - 1; i > 0; i--)
+    {
+        s->Printf ("Element %d: ", i);
+        s->IndentMore();
+        m_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
+        s->IndentLess();
+        s->EOL();
+    }
+
+    stack_size = m_immediate_plan_stack.size();
+    s->Printf ("Immediate Plan Stack: %d elements.\n", stack_size);
+    for (int i = stack_size - 1; i > 0; i--)
+    {
+        s->Printf ("Element %d: ", i);
+        s->IndentMore();
+        m_immediate_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
+        s->IndentLess();
+        s->EOL();
+    }
+
+    stack_size = m_completed_plan_stack.size();
+    s->Printf ("Completed Plan Stack: %d elements.\n", stack_size);
+    for (int i = stack_size - 1; i > 0; i--)
+    {
+        s->Printf ("Element %d: ", i);
+        s->IndentMore();
+        m_completed_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
+        s->IndentLess();
+        s->EOL();
+    }
+
+    stack_size = m_discarded_plan_stack.size();
+    s->Printf ("Discarded Plan Stack: %d elements.\n", stack_size);
+    for (int i = stack_size - 1; i > 0; i--)
+    {
+        s->Printf ("Element %d: ", i);
+        s->IndentMore();
+        m_discarded_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
+        s->IndentLess();
+        s->EOL();
+    }
+
+}
+
+Target *
+Thread::CalculateTarget ()
+{
+    return m_process.CalculateTarget();
+}
+
+Process *
+Thread::CalculateProcess ()
+{
+    return &m_process;
+}
+
+Thread *
+Thread::CalculateThread ()
+{
+    return this;
+}
+
+StackFrame *
+Thread::CalculateStackFrame ()
+{
+    return NULL;
+}
+
+void
+Thread::Calculate (ExecutionContext &exe_ctx)
+{
+    m_process.Calculate (exe_ctx);
+    exe_ctx.thread = this;
+    exe_ctx.frame = NULL;
+}
+
+lldb::StackFrameSP
+Thread::GetCurrentFrame ()
+{
+    return GetStackFrameAtIndex (m_frames.GetCurrentFrameIndex());
+}
+
+uint32_t
+Thread::SetCurrentFrame (lldb_private::StackFrame *frame)
+{
+    return m_frames.SetCurrentFrame(frame);
+}
+
+void
+Thread::SetCurrentFrameByIndex (uint32_t frame_idx)
+{
+    m_frames.SetCurrentFrameByIndex(frame_idx);
+}
+
+void
+Thread::DumpInfo
+(
+    Stream &strm,
+    bool show_stop_reason,
+    bool show_name,
+    bool show_queue,
+    uint32_t frame_idx
+)
+{
+    strm.Printf("thread #%u: tid = 0x%4.4x", GetIndexID(), GetID());
+
+    if (frame_idx != LLDB_INVALID_INDEX32)
+    {
+        StackFrameSP frame_sp(GetStackFrameAtIndex (frame_idx));
+        if (frame_sp)
+        {
+            strm.PutCString(", ");
+            frame_sp->Dump (&strm, false);
+        }
+    }
+
+    if (show_stop_reason)
+    {
+        Thread::StopInfo thread_stop_info;
+        if (GetStopInfo(&thread_stop_info))
+        {
+            if (thread_stop_info.GetStopReason() != eStopReasonNone)
+            {
+                strm.PutCString(", stop reason = ");
+                thread_stop_info.Dump(&strm);
+            }
+        }
+    }
+
+    if (show_name)
+    {
+        const char *name = GetName();
+        if (name && name[0])
+            strm.Printf(", name = %s", name);
+    }
+
+    if (show_queue)
+    {
+        const char *queue = GetQueueName();
+        if (queue && queue[0])
+            strm.Printf(", queue = %s", queue);
+    }
+}
+
+lldb::ThreadSP
+Thread::GetSP ()
+{
+    return m_process.GetThreadList().GetThreadSPForThreadPtr(this);
+}
diff --git a/source/Target/ThreadList.cpp b/source/Target/ThreadList.cpp
new file mode 100644
index 0000000..6bc2271
--- /dev/null
+++ b/source/Target/ThreadList.cpp
@@ -0,0 +1,460 @@
+//===-- ThreadList.cpp ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <stdlib.h>
+
+#include <algorithm>
+
+#include "lldb/Target/ThreadList.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+ThreadList::ThreadList (Process *process) :
+    m_process (process),
+    m_stop_id (0),
+    m_threads(),
+    m_threads_mutex (Mutex::eMutexTypeRecursive),
+    m_current_tid (LLDB_INVALID_THREAD_ID)
+{
+}
+
+ThreadList::ThreadList (const ThreadList &rhs) :
+    m_process (),
+    m_stop_id (),
+    m_threads (),
+    m_threads_mutex (Mutex::eMutexTypeRecursive),
+    m_current_tid ()
+{
+    // Use the assignment operator since it uses the mutex
+    *this = rhs;
+}
+
+const ThreadList&
+ThreadList::operator = (const ThreadList& rhs)
+{
+    if (this != &rhs)
+    {
+        // Lock both mutexes to make sure neither side changes anyone on us
+        // while the assignement occurs
+        Mutex::Locker locker_this(m_threads_mutex);
+        Mutex::Locker locker_rhs(rhs.m_threads_mutex);
+        m_process = rhs.m_process;
+        m_stop_id = rhs.m_stop_id;
+        m_threads = rhs.m_threads;
+        m_current_tid = rhs.m_current_tid;
+    }
+    return *this;
+}
+
+
+ThreadList::~ThreadList()
+{
+}
+
+
+uint32_t
+ThreadList::GetStopID () const
+{
+    return m_stop_id;
+}
+
+void
+ThreadList::SetStopID (uint32_t stop_id)
+{
+    m_stop_id = stop_id;
+}
+
+
+void
+ThreadList::AddThread (ThreadSP &thread_sp)
+{
+    Mutex::Locker locker(m_threads_mutex);
+    m_threads.push_back(thread_sp);
+}
+
+uint32_t
+ThreadList::GetSize (bool can_update)
+{
+    Mutex::Locker locker(m_threads_mutex);
+    if (can_update)
+        m_process->UpdateThreadListIfNeeded();
+    return m_threads.size();
+}
+
+ThreadSP
+ThreadList::GetThreadAtIndex (uint32_t idx, bool can_update)
+{
+    Mutex::Locker locker(m_threads_mutex);
+    if (can_update)
+        m_process->UpdateThreadListIfNeeded();
+
+    ThreadSP thread_sp;
+    if (idx < m_threads.size())
+        thread_sp = m_threads[idx];
+    return thread_sp;
+}
+
+ThreadSP
+ThreadList::FindThreadByID (lldb::tid_t tid, bool can_update)
+{
+    Mutex::Locker locker(m_threads_mutex);
+
+    if (can_update)
+        m_process->UpdateThreadListIfNeeded();
+
+    ThreadSP thread_sp;
+    uint32_t idx = 0;
+    const uint32_t num_threads = m_threads.size();
+    for (idx = 0; idx < num_threads; ++idx)
+    {
+        if (m_threads[idx]->GetID() == tid)
+        {
+            thread_sp = m_threads[idx];
+            break;
+        }
+    }
+    return thread_sp;
+}
+
+ThreadSP
+ThreadList::GetThreadSPForThreadPtr (Thread *thread_ptr)
+{
+    ThreadSP thread_sp;
+    if (thread_ptr)
+    {
+        Mutex::Locker locker(m_threads_mutex);
+
+        uint32_t idx = 0;
+        const uint32_t num_threads = m_threads.size();
+        for (idx = 0; idx < num_threads; ++idx)
+        {
+            if (m_threads[idx].get() == thread_ptr)
+            {
+                thread_sp = m_threads[idx];
+                break;
+            }
+        }
+    }
+    return thread_sp;
+}
+
+
+
+ThreadSP
+ThreadList::FindThreadByIndexID (uint32_t index_id, bool can_update)
+{
+    Mutex::Locker locker(m_threads_mutex);
+
+    if (can_update)
+        m_process->UpdateThreadListIfNeeded();
+
+    ThreadSP thread_sp;
+    const uint32_t num_threads = m_threads.size();
+    for (uint32_t idx = 0; idx < num_threads; ++idx)
+    {
+        if (m_threads[idx]->GetIndexID() == index_id)
+        {
+            thread_sp = m_threads[idx];
+            break;
+        }
+    }
+    return thread_sp;
+}
+
+bool
+ThreadList::ShouldStop (Event *event_ptr)
+{
+    Mutex::Locker locker(m_threads_mutex);
+
+    // Running events should never stop, obviously...
+
+
+    bool should_stop = false;
+    m_process->UpdateThreadListIfNeeded();
+
+    collection::iterator pos, end = m_threads.end();
+
+    // Run through the threads and ask whether we should stop.  Don't ask
+    // suspended threads, however, it makes more sense for them to preserve their
+    // state across the times the process runs but they don't get a chance to.
+    for (pos = m_threads.begin(); pos != end; ++pos)
+    {
+        ThreadSP thread_sp(*pos);
+        if ((thread_sp->ThreadStoppedForAReason())
+            && (thread_sp->GetResumeState () != eStateSuspended))
+        {
+            should_stop |= thread_sp->ShouldStop(event_ptr);
+        }
+    }
+    if (should_stop)
+    {
+        for (pos = m_threads.begin(); pos != end; ++pos)
+        {
+            ThreadSP thread_sp(*pos);
+            thread_sp->WillStop ();
+        }
+    }
+
+    return should_stop;
+}
+
+Vote
+ThreadList::ShouldReportStop (Event *event_ptr)
+{
+    Vote result = eVoteNoOpinion;
+    m_process->UpdateThreadListIfNeeded();
+    collection::iterator pos, end = m_threads.end();
+
+    // Run through the threads and ask whether we should report this event.
+    // For stopping, a YES vote wins over everything.  A NO vote wins over NO opinion.
+    for (pos = m_threads.begin(); pos != end; ++pos)
+    {
+        ThreadSP thread_sp(*pos);
+        if (thread_sp->ThreadStoppedForAReason() && (thread_sp->GetResumeState () != eStateSuspended))
+        {
+            switch (thread_sp->ShouldReportStop (event_ptr))
+            {
+                case eVoteNoOpinion:
+                    continue;
+                case eVoteYes:
+                    result = eVoteYes;
+                    break;
+                case eVoteNo:
+                    if (result == eVoteNoOpinion)
+                        result = eVoteNo;
+                    break;
+            }
+        }
+    }
+    return result;
+}
+
+Vote
+ThreadList::ShouldReportRun (Event *event_ptr)
+{
+    Vote result = eVoteNoOpinion;
+    m_process->UpdateThreadListIfNeeded();
+    collection::iterator pos, end = m_threads.end();
+
+    // Run through the threads and ask whether we should report this event.
+    // The rule is NO vote wins over everything, a YES vote wins over no opinion.
+
+    for (pos = m_threads.begin(); pos != end; ++pos)
+    {
+        ThreadSP thread_sp(*pos);
+        if (thread_sp->GetResumeState () != eStateSuspended)
+
+        switch (thread_sp->ShouldReportRun (event_ptr))
+        {
+            case eVoteNoOpinion:
+                continue;
+            case eVoteYes:
+                if (result == eVoteNoOpinion)
+                    result = eVoteYes;
+                break;
+            case eVoteNo:
+                result = eVoteNo;
+                break;
+        }
+    }
+    return result;
+}
+
+void
+ThreadList::Clear()
+{
+    m_stop_id = 0;
+    m_threads.clear();
+    m_current_tid = LLDB_INVALID_THREAD_ID;
+}
+
+void
+ThreadList::RefreshStateAfterStop ()
+{
+    Mutex::Locker locker(m_threads_mutex);
+
+    m_process->UpdateThreadListIfNeeded();
+
+    collection::iterator pos, end = m_threads.end();
+    for (pos = m_threads.begin(); pos != end; ++pos)
+        (*pos)->RefreshStateAfterStop ();
+}
+
+void
+ThreadList::DiscardThreadPlans ()
+{
+    // You don't need to update the thread list here, because only threads
+    // that you currently know about have any thread plans.
+    Mutex::Locker locker(m_threads_mutex);
+
+    collection::iterator pos, end = m_threads.end();
+    for (pos = m_threads.begin(); pos != end; ++pos)
+        (*pos)->DiscardThreadPlans (true);
+
+}
+
+bool
+ThreadList::WillResume ()
+{
+    // Run through the threads and perform their momentary actions.
+    // But we only do this for threads that are running, user suspended
+    // threads stay where they are.
+    bool success = true;
+
+    Mutex::Locker locker(m_threads_mutex);
+    m_process->UpdateThreadListIfNeeded();
+
+    collection::iterator pos, end = m_threads.end();
+    
+    // Give all the threads a last chance to set up their state before we
+    // negotiate who is actually going to get a chance to run...
+
+    for (pos = m_threads.begin(); pos != end; ++pos)
+        (*pos)->SetupForResume ();
+    
+    // Now go through the threads and see if any thread wants to run just itself.
+    // if so then pick one and run it.
+    ThreadList run_me_only_list (m_process);
+    
+    run_me_only_list.SetStopID(m_process->GetStopID());
+
+    ThreadSP immediate_thread_sp;
+    bool run_only_current_thread = false;
+
+    for (pos = m_threads.begin(); pos != end; ++pos)
+    {
+        ThreadSP thread_sp(*pos);
+        if (thread_sp->GetCurrentPlan()->IsImmediate())
+        {
+            // We first do all the immediate plans, so if we find one, set
+            // immediate_thread_sp and break out, and we'll pick it up first thing
+            // when we're negotiating which threads get to run.
+            immediate_thread_sp = thread_sp;
+            break;
+        }
+        else if (thread_sp->GetResumeState() != eStateSuspended &&
+                 thread_sp->GetCurrentPlan()->StopOthers())
+        {
+            // You can't say "stop others" and also want yourself to be suspended.
+            assert (thread_sp->GetCurrentPlan()->RunState() != eStateSuspended);
+
+            if (thread_sp == GetCurrentThread())
+            {
+                run_only_current_thread = true;
+                run_me_only_list.Clear();
+                run_me_only_list.AddThread (thread_sp);
+                break;
+            }
+
+            run_me_only_list.AddThread (thread_sp);
+        }
+
+    }
+
+    if (immediate_thread_sp)
+    {
+        for (pos = m_threads.begin(); pos != end; ++pos)
+        {
+            ThreadSP thread_sp(*pos);
+            if (thread_sp.get() == immediate_thread_sp.get())
+                thread_sp->WillResume(thread_sp->GetCurrentPlan()->RunState());
+            else
+                thread_sp->WillResume (eStateSuspended);
+        }
+    }
+    else if (run_me_only_list.GetSize (false) == 0)
+    {
+        // Everybody runs as they wish:
+        for (pos = m_threads.begin(); pos != end; ++pos)
+        {
+            ThreadSP thread_sp(*pos);
+            thread_sp->WillResume(thread_sp->GetCurrentPlan()->RunState());
+        }
+    }
+    else
+    {
+        ThreadSP thread_to_run;
+
+        if (run_only_current_thread)
+        {
+            thread_to_run = GetCurrentThread();
+        }
+        else if (run_me_only_list.GetSize (false) == 1)
+        {
+            thread_to_run = run_me_only_list.GetThreadAtIndex (0);
+        }
+        else
+        {
+            int random_thread = (int)
+                    ((run_me_only_list.GetSize (false) * (double) rand ()) / (RAND_MAX + 1.0));
+            thread_to_run = run_me_only_list.GetThreadAtIndex (random_thread);
+        }
+
+        for (pos = m_threads.begin(); pos != end; ++pos)
+        {
+            ThreadSP thread_sp(*pos);
+            if (thread_sp == thread_to_run)
+                thread_sp->WillResume(thread_sp->GetCurrentPlan()->RunState());
+            else
+                thread_sp->WillResume (eStateSuspended);
+        }
+    }
+
+    return success;
+}
+
+void
+ThreadList::DidResume ()
+{
+    collection::iterator pos, end = m_threads.end();
+    for (pos = m_threads.begin(); pos != end; ++pos)
+    {
+        // Don't clear out threads that aren't going to get a chance to run, rather
+        // leave their state for the next time around.
+        ThreadSP thread_sp(*pos);
+        if (thread_sp->GetResumeState() != eStateSuspended)
+            thread_sp->DidResume ();
+    }
+}
+
+ThreadSP
+ThreadList::GetCurrentThread ()
+{
+    Mutex::Locker locker(m_threads_mutex);
+    return FindThreadByID(m_current_tid);
+}
+
+bool
+ThreadList::SetCurrentThreadByID (lldb::tid_t tid)
+{
+    Mutex::Locker locker(m_threads_mutex);
+    if  (FindThreadByID(tid).get())
+        m_current_tid = tid;
+    else
+        m_current_tid = LLDB_INVALID_THREAD_ID;
+
+    return m_current_tid != LLDB_INVALID_THREAD_ID;
+}
+
+bool
+ThreadList::SetCurrentThreadByIndexID (uint32_t index_id)
+{
+    Mutex::Locker locker(m_threads_mutex);
+    ThreadSP thread_sp (FindThreadByIndexID(index_id));
+    if  (thread_sp.get())
+        m_current_tid = thread_sp->GetID();
+    else
+        m_current_tid = LLDB_INVALID_THREAD_ID;
+
+    return m_current_tid != LLDB_INVALID_THREAD_ID;
+}
+
diff --git a/source/Target/ThreadPlan.cpp b/source/Target/ThreadPlan.cpp
new file mode 100644
index 0000000..c9005c1
--- /dev/null
+++ b/source/Target/ThreadPlan.cpp
@@ -0,0 +1,185 @@
+//===-- ThreadPlan.cpp ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/ThreadPlan.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/Thread.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/State.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// ThreadPlan constructor
+//----------------------------------------------------------------------
+ThreadPlan::ThreadPlan(const char *name, Thread &thread, Vote stop_vote, Vote run_vote) :
+    m_name (name),
+    m_thread (thread),
+    m_plan_complete(false),
+    m_plan_complete_mutex (Mutex::eMutexTypeRecursive),
+    m_plan_private (false),
+    m_stop_vote (stop_vote),
+    m_run_vote (run_vote),
+    m_okay_to_discard (false)
+{
+    SetID (GetNextID());
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ThreadPlan::~ThreadPlan()
+{
+}
+
+const char *
+ThreadPlan::GetName () const
+{
+    return m_name.c_str();
+}
+
+Thread &
+ThreadPlan::GetThread()
+{
+    return m_thread;
+}
+
+
+const Thread &
+ThreadPlan::GetThread() const
+{
+    return m_thread;
+}
+
+bool
+ThreadPlan::IsPlanComplete ()
+{
+    Mutex::Locker (m_plan_complete_mutex);
+    return m_plan_complete;
+}
+
+void
+ThreadPlan::SetPlanComplete ()
+{
+    Mutex::Locker (m_plan_complete_mutex);
+    m_plan_complete = true;
+}
+
+bool
+ThreadPlan::MischiefManaged ()
+{
+    Mutex::Locker (m_plan_complete_mutex);
+    m_plan_complete = true;
+    return true;
+}
+
+Vote
+ThreadPlan::ShouldReportStop (Event *event_ptr)
+{
+    if (m_stop_vote == eVoteNoOpinion)
+    {
+        ThreadPlan *prev_plan = GetPreviousPlan ();
+        if (prev_plan)
+            return prev_plan->ShouldReportStop (event_ptr);
+    }
+    return m_stop_vote;
+}
+
+Vote
+ThreadPlan::ShouldReportRun (Event *event_ptr)
+{
+    if (m_run_vote == eVoteNoOpinion)
+    {
+        ThreadPlan *prev_plan = GetPreviousPlan ();
+        if (prev_plan)
+            return prev_plan->ShouldReportRun (event_ptr);
+    }
+    return m_run_vote;
+}
+
+bool
+ThreadPlan::StopOthers ()
+{
+    ThreadPlan *prev_plan;
+    prev_plan = GetPreviousPlan ();
+    if (prev_plan == NULL)
+        return false;
+    else
+        return prev_plan->StopOthers();
+}
+
+bool
+ThreadPlan::WillResume (StateType resume_state, bool current_plan)
+{
+    if (current_plan)
+    {
+        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+
+        if (log)
+            log->Printf("About to resume the \"%s\" plan - state: %s - stop others: %d.", 
+                        m_name.c_str(), StateAsCString(resume_state), StopOthers());
+    }
+    return true;
+}
+
+lldb::user_id_t
+ThreadPlan::GetNextID()
+{
+    static uint32_t g_nextPlanID = 0;
+    return ++g_nextPlanID;
+}
+
+void
+ThreadPlan::DidPush()
+{
+}
+
+void
+ThreadPlan::WillPop()
+{
+}
+
+void
+ThreadPlan::PushPlan (ThreadPlanSP &thread_plan_sp)
+{
+    m_thread.PushPlan (thread_plan_sp);
+}
+
+ThreadPlan *
+ThreadPlan::GetPreviousPlan ()
+{
+    return m_thread.GetPreviousPlan (this);
+}
+
+void
+ThreadPlan::SetPrivate (bool input)
+{
+    m_plan_private = input;
+}
+
+bool
+ThreadPlan::GetPrivate (void)
+{
+    return m_plan_private;
+}
+
+bool
+ThreadPlan::OkayToDiscard()
+{
+    if (!IsMasterPlan())
+        return true;
+    else
+        return m_okay_to_discard;
+}
+
diff --git a/source/Target/ThreadPlanBase.cpp b/source/Target/ThreadPlanBase.cpp
new file mode 100644
index 0000000..283f3be
--- /dev/null
+++ b/source/Target/ThreadPlanBase.cpp
@@ -0,0 +1,202 @@
+//===-- ThreadPlanBase.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/ThreadPlanBase.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+//
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Breakpoint/BreakpointSite.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/ThreadPlanContinue.h"
+#include "lldb/Target/ThreadPlanStepOverBreakpoint.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// ThreadPlanBase: This one always stops, and never has anything particular
+// to do.
+// FIXME: The "signal handling" policies should probably go here.
+//----------------------------------------------------------------------
+
+ThreadPlanBase::ThreadPlanBase (Thread &thread) :
+    ThreadPlan("base plan", thread, eVoteYes, eVoteNoOpinion)
+{
+
+}
+
+ThreadPlanBase::~ThreadPlanBase ()
+{
+
+}
+
+void
+ThreadPlanBase::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+    s->Printf ("Base thread plan.");
+}
+
+bool
+ThreadPlanBase::ValidatePlan (Stream *error)
+{
+    return true;
+}
+
+bool
+ThreadPlanBase::PlanExplainsStop ()
+{
+    return true;
+}
+
+bool
+ThreadPlanBase::ShouldStop (Event *event_ptr)
+{
+    m_stop_vote = eVoteYes;
+    m_run_vote = eVoteYes;
+
+    Thread::StopInfo stop_info;
+    if (m_thread.GetStopInfo(&stop_info))
+    {
+        StopReason reason = stop_info.GetStopReason();
+        switch (reason)
+        {
+            case eStopReasonInvalid:
+            case eStopReasonNone:
+            {
+                m_run_vote = eVoteNo;
+                m_stop_vote = eVoteNo;
+                return false;
+            }
+            case eStopReasonBreakpoint:
+            {
+                // The base plan checks for breakpoint hits.
+
+                BreakpointSiteSP bp_site_sp;
+                //RegisterContext *reg_ctx = m_thread.GetRegisterContext();
+                //lldb::addr_t pc = reg_ctx->GetPC();
+                bp_site_sp = m_thread.GetProcess().GetBreakpointSiteList().FindByID (stop_info.GetBreakpointSiteID());
+
+                if (bp_site_sp && bp_site_sp->IsEnabled())
+                {
+                    // We want to step over the breakpoint and then continue.  So push these two plans.
+
+                    StoppointCallbackContext hit_context(event_ptr, &m_thread.GetProcess(), &m_thread, m_thread.GetStackFrameAtIndex(0).get());
+                    bool should_stop = m_thread.GetProcess().GetBreakpointSiteList().ShouldStop(&hit_context, bp_site_sp->GetID());
+
+                    if (!should_stop)
+                    {
+                        // If we aren't going to stop at this breakpoint, and it is internal, don't report this stop or the subsequent
+                        // running event.  Otherwise we will post the stopped & running, but the stopped event will get marked
+                        // with "restarted" so the UI will know to wait and expect the consequent "running".
+                        uint32_t i;
+                        bool is_wholly_internal = true;
+
+                        for (i = 0; i < bp_site_sp->GetNumberOfOwners(); i++)
+                        {
+                            if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal())
+                            {
+                                is_wholly_internal = false;
+                                break;
+                            }
+                        }
+                        if (is_wholly_internal)
+                        {
+                            m_stop_vote = eVoteNo;
+                            m_run_vote = eVoteNo;
+                        }
+                        else
+                        {
+                            m_stop_vote = eVoteYes;
+                            m_run_vote = eVoteYes;
+                        }
+
+                    }
+                    else
+                    {
+                        // If we are going to stop for a breakpoint, then unship the other plans
+                        // at this point.  Don't force the discard, however, so Master plans can stay
+                        // in place if they want to.
+                        m_thread.DiscardThreadPlans(false);
+                    }
+
+                    return should_stop;
+                }
+            }
+            case eStopReasonException:
+                // If we crashed, discard thread plans and stop.  Don't force the discard, however,
+                // since on rerun the target may clean up this exception and continue normally from there.
+                m_thread.DiscardThreadPlans(false);
+                return true;
+            case eStopReasonSignal:
+            {
+                // Check the signal handling, and if we are stopping for the signal,
+                // discard the plans and stop.
+                UnixSignals &signals = m_thread.GetProcess().GetUnixSignals();
+                uint32_t signo = stop_info.GetSignal();
+                if (signals.GetShouldStop(signo))
+                {
+                    m_thread.DiscardThreadPlans(false);
+                    return true;
+                }
+                else
+                {
+                    // We're not going to stop, but while we are here, let's figure out
+                    // whether to report this.
+                    if (signals.GetShouldNotify(signo))
+                        m_stop_vote = eVoteYes;
+                    else
+                        m_stop_vote = eVoteNo;
+
+                    return false;
+                }
+            }
+            default:
+                return true;
+        }
+
+    }
+
+    // If there's no explicit reason to stop, then we will continue.
+    return false;
+}
+
+bool
+ThreadPlanBase::StopOthers ()
+{
+    return false;
+}
+
+StateType
+ThreadPlanBase::RunState ()
+{
+    return eStateRunning;
+}
+
+bool
+ThreadPlanBase::WillStop ()
+{
+    return true;
+}
+
+// The base plan is never done.
+bool
+ThreadPlanBase::MischiefManaged ()
+{
+    // The base plan is never done.
+    return false;
+}
+
diff --git a/source/Target/ThreadPlanCallFunction.cpp b/source/Target/ThreadPlanCallFunction.cpp
new file mode 100644
index 0000000..4b3533a
--- /dev/null
+++ b/source/Target/ThreadPlanCallFunction.cpp
@@ -0,0 +1,250 @@
+//===-- ThreadPlanCallFunction.cpp ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/ThreadPlanCallFunction.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private-log.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlanRunToAddress.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// ThreadPlanCallFunction: Plan to call a single function
+//----------------------------------------------------------------------
+
+ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
+                                                Address &function,
+                                                lldb::addr_t arg,
+                                                bool stop_other_threads,
+                                                bool discard_on_error) :
+    ThreadPlan ("Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
+    m_valid(false),
+    m_process(thread.GetProcess()),
+    m_arg_addr (arg),
+    m_args (NULL),
+    m_thread(thread),
+    m_stop_other_threads(stop_other_threads)
+{
+
+    SetOkayToDiscard (discard_on_error);
+
+    Process& process = thread.GetProcess();
+    Target& target = process.GetTarget();
+    const ABI *abi = process.GetABI();
+
+    if (!abi)
+        return;
+
+    lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
+    
+    SymbolContextList contexts;
+    SymbolContext context;
+    ModuleSP executableModuleSP (target.GetExecutableModule());
+
+    if (!executableModuleSP ||
+        !executableModuleSP->FindSymbolsWithNameAndType(ConstString ("start"), eSymbolTypeCode, contexts))
+        return;
+    
+    contexts.GetContextAtIndex(0, context);
+    
+    m_start_addr = context.symbol->GetValue();
+    lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&process);
+
+    if (!thread.SaveFrameZeroState(m_register_backup))
+        return;
+
+    m_function_addr = function;
+    lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&process);
+        
+    if (!abi->PrepareTrivialCall(thread, 
+                                 spBelowRedZone, 
+                                 FunctionLoadAddr, 
+                                 StartLoadAddr, 
+                                 m_arg_addr))
+        return;
+    
+    m_valid = true;    
+}
+
+ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
+                                                Address &function,
+                                                ValueList &args,
+                                                bool stop_other_threads,
+                                                bool discard_on_error) :
+    ThreadPlan ("Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
+    m_valid(false),
+    m_process(thread.GetProcess()),
+    m_arg_addr (0),
+    m_args (&args),
+    m_thread(thread),
+    m_stop_other_threads(stop_other_threads)
+{
+    
+    SetOkayToDiscard (discard_on_error);
+    
+    Process& process = thread.GetProcess();
+    Target& target = process.GetTarget();
+    const ABI *abi = process.GetABI();
+    
+    if(!abi)
+        return;
+    
+    lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
+    
+    SymbolContextList contexts;
+    SymbolContext context;
+    ModuleSP executableModuleSP (target.GetExecutableModule());
+    
+    if (!executableModuleSP ||
+        !executableModuleSP->FindSymbolsWithNameAndType(ConstString ("start"), eSymbolTypeCode, contexts))
+        return;
+    
+    contexts.GetContextAtIndex(0, context);
+    
+    m_start_addr = context.symbol->GetValue();
+    lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&process);
+    
+    if(!thread.SaveFrameZeroState(m_register_backup))
+        return;
+    
+    m_function_addr = function;
+    lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&process);
+    
+    if (!abi->PrepareNormalCall(thread, 
+                                spBelowRedZone, 
+                                FunctionLoadAddr, 
+                                StartLoadAddr, 
+                                *m_args))
+        return;
+    
+    m_valid = true;    
+}
+
+ThreadPlanCallFunction::~ThreadPlanCallFunction ()
+{
+}
+
+void
+ThreadPlanCallFunction::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+    if (level == lldb::eDescriptionLevelBrief)
+    {
+        s->Printf("Function call thread plan");
+    }
+    else
+    {
+        if (m_args)
+            s->Printf("Thread plan to call 0x%llx with parsed arguments", m_function_addr.GetLoadAddress(&m_process), m_arg_addr);
+        else
+            s->Printf("Thread plan to call 0x%llx void * argument at: 0x%llx", m_function_addr.GetLoadAddress(&m_process), m_arg_addr);
+    }
+}
+
+bool
+ThreadPlanCallFunction::ValidatePlan (Stream *error)
+{
+    if (!m_valid)
+        return false;
+
+    return true;
+}
+
+bool
+ThreadPlanCallFunction::PlanExplainsStop ()
+{
+    if (!m_subplan_sp)
+        return false;
+    else
+        return m_subplan_sp->PlanExplainsStop();
+}
+
+bool
+ThreadPlanCallFunction::ShouldStop (Event *event_ptr)
+{
+    if (PlanExplainsStop())
+    {
+        m_thread.RestoreSaveFrameZero(m_register_backup);
+        m_thread.ClearStackFrames();
+        SetPlanComplete();
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+bool
+ThreadPlanCallFunction::StopOthers ()
+{
+    return m_stop_other_threads;
+}
+
+void
+ThreadPlanCallFunction::SetStopOthers (bool new_value)
+{
+    if (m_subplan_sp)
+    {
+        ThreadPlanRunToAddress *address_plan = static_cast<ThreadPlanRunToAddress *>(m_subplan_sp.get());
+        address_plan->SetStopOthers(new_value);
+    }
+    m_stop_other_threads = new_value;
+}
+
+StateType
+ThreadPlanCallFunction::RunState ()
+{
+    return eStateRunning;
+}
+
+void
+ThreadPlanCallFunction::DidPush ()
+{
+    m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads));
+    
+    m_thread.QueueThreadPlan(m_subplan_sp, false);
+
+}
+
+bool
+ThreadPlanCallFunction::WillStop ()
+{
+    return true;
+}
+
+bool
+ThreadPlanCallFunction::MischiefManaged ()
+{
+    if (IsPlanComplete())
+    {
+        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+
+        if (log)
+            log->Printf("Completed call function plan.");
+
+        ThreadPlan::MischiefManaged ();
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
diff --git a/source/Target/ThreadPlanContinue.cpp b/source/Target/ThreadPlanContinue.cpp
new file mode 100644
index 0000000..63d8a33
--- /dev/null
+++ b/source/Target/ThreadPlanContinue.cpp
@@ -0,0 +1,120 @@
+//===-- ThreadPlanContinue.cpp ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/ThreadPlanContinue.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private-log.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Stream.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// ThreadPlanContinue: Continue plan
+//----------------------------------------------------------------------
+
+ThreadPlanContinue::ThreadPlanContinue (Thread &thread, bool stop_others, Vote stop_vote, Vote run_vote, bool immediate) :
+    ThreadPlan ("Continue after previous plan", thread, stop_vote, run_vote),
+    m_stop_others (stop_others),
+    m_did_run (false),
+    m_immediate (immediate)
+{
+}
+
+ThreadPlanContinue::~ThreadPlanContinue ()
+{
+}
+
+void
+ThreadPlanContinue::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+    if (level == lldb::eDescriptionLevelBrief)
+        s->Printf ("continue");
+    else
+    {
+        s->Printf ("Continue from the previous plan");
+    }
+}
+
+bool
+ThreadPlanContinue::ValidatePlan (Stream *error)
+{
+    // Since we read the instruction we're stepping over from the thread,
+    // this plan will always work.
+    return true;
+}
+
+bool
+ThreadPlanContinue::PlanExplainsStop ()
+{
+    return true;
+}
+
+bool
+ThreadPlanContinue::ShouldStop (Event *event_ptr)
+{
+    return false;
+}
+
+bool
+ThreadPlanContinue::IsImmediate () const
+{
+    return m_immediate;
+    return false;
+}
+
+bool
+ThreadPlanContinue::StopOthers ()
+{
+    return m_stop_others;
+}
+
+StateType
+ThreadPlanContinue::RunState ()
+{
+    return eStateRunning;
+}
+
+bool
+ThreadPlanContinue::WillResume (StateType resume_state, bool current_plan)
+{
+    ThreadPlan::WillResume (resume_state, current_plan);
+    if (current_plan)
+    {
+        m_did_run = true;
+    }
+    return true;
+}
+
+bool
+ThreadPlanContinue::WillStop ()
+{
+    return true;
+}
+
+bool
+ThreadPlanContinue::MischiefManaged ()
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+
+    if (m_did_run)
+    {
+        if (log)
+            log->Printf("Completed continue plan.");
+        ThreadPlan::MischiefManaged ();
+        return true;
+    }
+    else
+        return false;
+}
diff --git a/source/Target/ThreadPlanRunToAddress.cpp b/source/Target/ThreadPlanRunToAddress.cpp
new file mode 100644
index 0000000..0544ea5
--- /dev/null
+++ b/source/Target/ThreadPlanRunToAddress.cpp
@@ -0,0 +1,176 @@
+//===-- ThreadPlanRunToAddress.cpp ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/ThreadPlanRunToAddress.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private-log.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/RegisterContext.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// ThreadPlanRunToAddress: Continue plan
+//----------------------------------------------------------------------
+
+ThreadPlanRunToAddress::ThreadPlanRunToAddress
+(
+    Thread &thread,
+    Address &address,
+    bool stop_others
+) :
+    ThreadPlan ("Run to breakpoint plan", thread, eVoteNoOpinion, eVoteNoOpinion),
+    m_stop_others (stop_others),
+    m_address (LLDB_INVALID_ADDRESS),
+    m_break_id (LLDB_INVALID_BREAK_ID)
+{
+    m_address = address.GetLoadAddress(&m_thread.GetProcess());
+    SetInitialBreakpoint();
+}
+
+ThreadPlanRunToAddress::ThreadPlanRunToAddress
+(
+    Thread &thread,
+    lldb::addr_t address,
+    bool stop_others
+) :
+    ThreadPlan ("Run to breakpoint plan", thread, eVoteNoOpinion, eVoteNoOpinion),
+    m_stop_others (stop_others),
+    m_address (address),
+    m_break_id (LLDB_INVALID_BREAK_ID)
+{
+    SetInitialBreakpoint();
+}
+
+void
+ThreadPlanRunToAddress::SetInitialBreakpoint ()
+{
+    Breakpoint *breakpoint;
+    breakpoint = m_thread.GetProcess().GetTarget().CreateBreakpoint (m_address, true).get();
+    if (breakpoint != NULL)
+    {
+        m_break_id = breakpoint->GetID();
+        breakpoint->SetThreadID(m_thread.GetID());
+    }
+}
+
+ThreadPlanRunToAddress::~ThreadPlanRunToAddress ()
+{
+    if (m_break_id != LLDB_INVALID_BREAK_ID)
+    {
+        m_thread.GetProcess().GetTarget().RemoveBreakpointByID (m_break_id);
+    }
+}
+
+void
+ThreadPlanRunToAddress::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+    if (level == lldb::eDescriptionLevelBrief)
+    {
+        s->Printf ("run to address: ");
+        s->Address (m_address, sizeof (addr_t));
+    }
+    else
+    {
+        s->Printf ("Run to address: ");
+        s->Address(m_address, sizeof (addr_t));
+        s->Printf (" using breakpoint: %d - ", m_break_id);
+        Breakpoint *breakpoint = m_thread.GetProcess().GetTarget().GetBreakpointByID (m_break_id).get();
+        if (breakpoint)
+            breakpoint->Dump (s);
+        else
+            s->Printf ("but the breakpoint has been deleted.");
+    }
+}
+
+bool
+ThreadPlanRunToAddress::ValidatePlan (Stream *error)
+{
+    // If we couldn't set the breakpoint for some reason, then this won't
+    // work.
+    if(m_break_id == LLDB_INVALID_BREAK_ID)
+        return false;
+    else
+        return true;
+}
+
+bool
+ThreadPlanRunToAddress::PlanExplainsStop ()
+{
+    return AtOurAddress();
+}
+
+bool
+ThreadPlanRunToAddress::ShouldStop (Event *event_ptr)
+{
+    return false;
+}
+
+bool
+ThreadPlanRunToAddress::StopOthers ()
+{
+    return m_stop_others;
+}
+
+void
+ThreadPlanRunToAddress::SetStopOthers (bool new_value)
+{
+    m_stop_others = new_value;
+}
+
+StateType
+ThreadPlanRunToAddress::RunState ()
+{
+    return eStateRunning;
+}
+
+bool
+ThreadPlanRunToAddress::WillStop ()
+{
+    return true;
+}
+
+bool
+ThreadPlanRunToAddress::MischiefManaged ()
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+
+    if (AtOurAddress())
+    {
+        // Remove the breakpoint
+        if (m_break_id != LLDB_INVALID_BREAK_ID)
+        {
+            m_thread.GetProcess().GetTarget().RemoveBreakpointByID (m_break_id);
+            m_break_id = LLDB_INVALID_BREAK_ID;
+        }
+
+        if (log)
+            log->Printf("Completed run to address plan.");
+        ThreadPlan::MischiefManaged ();
+        return true;
+    }
+    else
+        return false;
+}
+
+bool
+ThreadPlanRunToAddress::AtOurAddress ()
+{
+    lldb::addr_t current_address = m_thread.GetRegisterContext()->GetPC();
+    return m_address == current_address;
+}
diff --git a/source/Target/ThreadPlanShouldStopHere.cpp b/source/Target/ThreadPlanShouldStopHere.cpp
new file mode 100644
index 0000000..493ab63
--- /dev/null
+++ b/source/Target/ThreadPlanShouldStopHere.cpp
@@ -0,0 +1,53 @@
+//===-- ThreadPlanShouldStopHere.cpp ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlanShouldStopHere.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+//----------------------------------------------------------------------
+// ThreadPlanShouldStopHere constructor
+//----------------------------------------------------------------------
+ThreadPlanShouldStopHere::ThreadPlanShouldStopHere(ThreadPlan *owner, ThreadPlanShouldStopHereCallback callback, void *baton) :
+    m_callback (callback),
+    m_baton (baton),
+    m_owner (owner),
+    m_flags (ThreadPlanShouldStopHere::eNone)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ThreadPlanShouldStopHere::~ThreadPlanShouldStopHere()
+{
+}
+
+void
+ThreadPlanShouldStopHere::SetShouldStopHereCallback (ThreadPlanShouldStopHereCallback callback, void *baton)
+{
+    m_callback = callback;
+    m_baton = baton;
+}
+
+ThreadPlan *
+ThreadPlanShouldStopHere::InvokeShouldStopHereCallback ()
+{
+    if (m_callback)
+        return m_callback (m_owner, m_flags, m_baton);
+    else
+        return NULL;
+}
\ No newline at end of file
diff --git a/source/Target/ThreadPlanStepInRange.cpp b/source/Target/ThreadPlanStepInRange.cpp
new file mode 100644
index 0000000..f62fdb8
--- /dev/null
+++ b/source/Target/ThreadPlanStepInRange.cpp
@@ -0,0 +1,154 @@
+//===-- ThreadPlanStepInRange.cpp -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/ThreadPlanStepInRange.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+#include "lldb/lldb-private-log.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlanStepOut.h"
+#include "lldb/Target/ThreadPlanStepThrough.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+uint32_t ThreadPlanStepInRange::s_default_flag_values = ThreadPlanShouldStopHere::eAvoidNoDebug;
+
+//----------------------------------------------------------------------
+// ThreadPlanStepInRange: Step through a stack range, either stepping over or into
+// based on the value of \a type.
+//----------------------------------------------------------------------
+
+ThreadPlanStepInRange::ThreadPlanStepInRange
+(
+    Thread &thread,
+    const AddressRange &range,
+    const SymbolContext &addr_context,
+    lldb::RunMode stop_others
+) :
+    ThreadPlanStepRange ("Step Range stepping in", thread, range, addr_context, stop_others),
+    ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL)
+{
+    SetFlagsToDefault ();
+}
+
+ThreadPlanStepInRange::~ThreadPlanStepInRange ()
+{
+}
+
+void
+ThreadPlanStepInRange::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+    if (level == lldb::eDescriptionLevelBrief)
+        s->Printf("step in");
+    else
+    {
+        s->Printf ("Stepping through range (stepping into functions): ");
+        m_address_range.Dump (s, &m_thread.GetProcess(), Address::DumpStyleLoadAddress);
+    }
+}
+
+bool
+ThreadPlanStepInRange::ShouldStop (Event *event_ptr)
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+    m_no_more_plans = false;
+    
+    if (log)
+    {
+        StreamString s;
+        s.Address (m_thread.GetRegisterContext()->GetPC(), m_thread.GetProcess().GetAddressByteSize());
+        log->Printf("ThreadPlanStepInRange reached %s.", s.GetData());
+    }
+
+    // If we're still in the range, keep going.
+    if (InRange())
+        return false;
+
+    // If we're in an older frame then we should stop.
+    if (FrameIsOlder())
+        return true;
+        
+    // See if we are in a place we should step through (i.e. a trampoline of some sort):
+    // One tricky bit here is that some stubs don't push a frame, so we have to check
+    // both the case of a frame that is younger, or the same as this frame.  
+    // However, if the frame is the same, and we are still in the symbol we started
+    // in, the we don't need to do this.  This first check isn't strictly necessary,
+    // but it is more efficient.
+    
+    if (!FrameIsYounger() && InSymbol())
+    {
+        SetPlanComplete();
+        return true;
+    }
+    
+    ThreadPlan* new_plan = NULL;
+
+    bool stop_others;
+    if (m_stop_others == lldb::eOnlyThisThread)
+        stop_others = true;
+    else
+        stop_others = false;
+        
+    new_plan = m_thread.QueueThreadPlanForStepThrough (false, stop_others);
+    // If not, give the "should_stop" callback a chance to push a plan to get us out of here.
+    // But only do that if we actually have stepped in.
+    if (!new_plan && FrameIsYounger())
+        new_plan = InvokeShouldStopHereCallback();
+
+    if (new_plan == NULL)
+    {
+        m_no_more_plans = true;
+        SetPlanComplete();
+        return true;
+    }
+    else
+    {
+        m_no_more_plans = false;
+        return false;
+    }
+}
+
+void
+ThreadPlanStepInRange::SetFlagsToDefault ()
+{
+    GetFlags().Set(ThreadPlanStepInRange::s_default_flag_values);
+}
+
+void
+ThreadPlanStepInRange::SetDefaultFlagValue (uint32_t new_value)
+{
+    // TODO: Should we test this for sanity?
+    ThreadPlanStepInRange::s_default_flag_values = new_value;
+}
+
+ThreadPlan *
+ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton)
+{
+    if (flags.IsSet(eAvoidNoDebug))
+    {
+        StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
+
+        if (!frame->HasDebugInformation())
+        {
+            // FIXME: Make sure the ThreadPlanForStepOut does the right thing with inlined functions.
+            return current_plan->GetThread().QueueThreadPlanForStepOut (false, NULL, true, current_plan->StopOthers(), eVoteNo, eVoteNoOpinion);
+        }
+    }
+
+    return NULL;
+}
diff --git a/source/Target/ThreadPlanStepInstruction.cpp b/source/Target/ThreadPlanStepInstruction.cpp
new file mode 100644
index 0000000..41c4373
--- /dev/null
+++ b/source/Target/ThreadPlanStepInstruction.cpp
@@ -0,0 +1,191 @@
+//===-- ThreadPlanStepInstruction.cpp ---------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "lldb/Target/ThreadPlanStepInstruction.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private-log.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// ThreadPlanStepInstruction: Step over the current instruction
+//----------------------------------------------------------------------
+
+ThreadPlanStepInstruction::ThreadPlanStepInstruction
+(
+    Thread &thread,
+    bool step_over,
+    bool stop_other_threads,
+    Vote stop_vote,
+    Vote run_vote
+) :
+    ThreadPlan ("Step over single instruction", thread, stop_vote, run_vote),
+    m_instruction_addr (0),
+    m_step_over (step_over),
+    m_stack_depth(0),
+    m_stop_other_threads (stop_other_threads)
+{
+    m_instruction_addr = m_thread.GetRegisterContext()->GetPC(0);
+    m_stack_depth = m_thread.GetStackFrameCount();
+}
+
+ThreadPlanStepInstruction::~ThreadPlanStepInstruction ()
+{
+}
+
+void
+ThreadPlanStepInstruction::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+    if (level == lldb::eDescriptionLevelBrief)
+    {
+        if (m_step_over)
+            s->Printf ("instruction step over");
+        else
+            s->Printf ("instruction step into");
+    }
+    else
+    {
+        s->Printf ("Stepping one instruction past ");
+        s->Address(m_instruction_addr, sizeof (addr_t));
+        if (m_step_over)
+            s->Printf(" stepping over calls");
+        else
+            s->Printf(" stepping into calls");
+    }
+}
+
+bool
+ThreadPlanStepInstruction::ValidatePlan (Stream *error)
+{
+    // Since we read the instruction we're stepping over from the thread,
+    // this plan will always work.
+    return true;
+}
+
+bool
+ThreadPlanStepInstruction::PlanExplainsStop ()
+{
+    Thread::StopInfo info;
+    if (m_thread.GetStopInfo (&info))
+    {
+        StopReason reason = info.GetStopReason();
+        if (reason == eStopReasonTrace || reason ==eStopReasonNone)
+            return true;
+        else
+            return false;
+    }
+    return false;
+}
+
+bool
+ThreadPlanStepInstruction::ShouldStop (Event *event_ptr)
+{
+    if (m_step_over)
+    {
+        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+        if (m_thread.GetStackFrameCount() <= m_stack_depth)
+        {
+            if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
+            {
+                SetPlanComplete();
+                return true;
+            }
+            else
+                return false;
+        }
+        else
+        {
+            // We've stepped in, step back out again:
+            StackFrame *return_frame = m_thread.GetStackFrameAtIndex(1).get();
+            if (return_frame)
+            {
+                if (log)
+                {
+                    StreamString s;
+                    s.PutCString ("Stepped in to: ");
+                    addr_t stop_addr = m_thread.GetStackFrameAtIndex(0)->GetPC().GetLoadAddress(&m_thread.GetProcess());
+                    s.Address (stop_addr, m_thread.GetProcess().GetAddressByteSize());
+                    s.PutCString (" stepping out to: ");
+                    addr_t return_addr = return_frame->GetPC().GetLoadAddress(&m_thread.GetProcess());
+                    s.Address (return_addr, m_thread.GetProcess().GetAddressByteSize());
+                    log->Printf("%s.", s.GetData());
+                }
+                m_thread.QueueThreadPlanForStepOut(false, NULL, true, m_stop_other_threads, eVoteNo, eVoteNoOpinion);
+                return false;
+            }
+            else
+            {
+                if (log)
+                    log->Printf("Could not find previous frame, stopping.");
+                SetPlanComplete();
+                return true;
+            }
+
+        }
+
+    }
+    else
+    {
+        if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
+        {
+            SetPlanComplete();
+            return true;
+        }
+        else
+            return false;
+    }
+}
+
+bool
+ThreadPlanStepInstruction::StopOthers ()
+{
+    return m_stop_other_threads;
+}
+
+StateType
+ThreadPlanStepInstruction::RunState ()
+{
+    return eStateStepping;
+}
+
+bool
+ThreadPlanStepInstruction::WillStop ()
+{
+    return true;
+}
+
+bool
+ThreadPlanStepInstruction::MischiefManaged ()
+{
+    if (IsPlanComplete())
+    {
+        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+        if (log)
+            log->Printf("Completed single instruction step plan.");
+        ThreadPlan::MischiefManaged ();
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
diff --git a/source/Target/ThreadPlanStepOut.cpp b/source/Target/ThreadPlanStepOut.cpp
new file mode 100644
index 0000000..e05a8a4
--- /dev/null
+++ b/source/Target/ThreadPlanStepOut.cpp
@@ -0,0 +1,228 @@
+//===-- ThreadPlanStepOut.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/ThreadPlanStepOut.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/lldb-private-log.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// ThreadPlanStepOut: Step out of the current frame
+//----------------------------------------------------------------------
+
+ThreadPlanStepOut::ThreadPlanStepOut
+(
+    Thread &thread,
+    SymbolContext *context,
+    bool first_insn,
+    bool stop_others,
+    Vote stop_vote,
+    Vote run_vote
+) :
+    ThreadPlan ("Step out", thread, stop_vote, run_vote),
+    m_step_from_context (context),
+    m_step_from_insn (LLDB_INVALID_ADDRESS),
+    m_return_addr (LLDB_INVALID_ADDRESS),
+    m_first_insn (first_insn),
+    m_return_bp_id(LLDB_INVALID_BREAK_ID),
+    m_stop_others (stop_others)
+{
+    m_step_from_insn = m_thread.GetRegisterContext()->GetPC(0);
+
+    // Find the return address and set a breakpoint there:
+    // FIXME - can we do this more securely if we know first_insn?
+
+    StackFrame *return_frame = m_thread.GetStackFrameAtIndex(1).get();
+    if (return_frame)
+    {
+        m_return_addr = return_frame->GetPC().GetLoadAddress(&m_thread.GetProcess());
+        Breakpoint *return_bp = m_thread.GetProcess().GetTarget().CreateBreakpoint (m_return_addr, true).get();
+        if (return_bp != NULL)
+        {
+            return_bp->SetThreadID(m_thread.GetID());
+            m_return_bp_id = return_bp->GetID();
+        }
+        else
+        {
+            m_return_bp_id = LLDB_INVALID_BREAK_ID;
+        }
+    }
+
+    m_stack_depth = m_thread.GetStackFrameCount();
+}
+
+ThreadPlanStepOut::~ThreadPlanStepOut ()
+{
+    if (m_return_bp_id != LLDB_INVALID_BREAK_ID)
+        m_thread.GetProcess().GetTarget().RemoveBreakpointByID(m_return_bp_id);
+}
+
+void
+ThreadPlanStepOut::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+    if (level == lldb::eDescriptionLevelBrief)
+        s->Printf ("step out");
+    else
+    {
+        s->Printf ("Stepping out from address 0x%llx to return address 0x%llx using breakpoint site %d",
+                   (uint64_t)m_step_from_insn,
+                   (uint64_t)m_return_addr,
+                   m_return_bp_id);
+    }
+}
+
+bool
+ThreadPlanStepOut::ValidatePlan (Stream *error)
+{
+    if (m_return_bp_id == LLDB_INVALID_BREAK_ID)
+        return false;
+    else
+        return true;
+}
+
+bool
+ThreadPlanStepOut::PlanExplainsStop ()
+{
+    // We don't explain signals or breakpoints (breakpoints that handle stepping in or
+    // out will be handled by a child plan.
+    Thread::StopInfo info;
+    if (m_thread.GetStopInfo (&info))
+    {
+        StopReason reason = info.GetStopReason();
+
+        switch (reason)
+        {
+            case eStopReasonBreakpoint:
+            {
+                // If this is OUR breakpoint, we're fine, otherwise we don't know why this happened...
+                BreakpointSiteSP this_site = m_thread.GetProcess().GetBreakpointSiteList().FindByID (info.GetBreakpointSiteID());
+                if (!this_site)
+                    return false;
+
+                if (this_site->IsBreakpointAtThisSite (m_return_bp_id))
+                {
+                    // If there was only one owner, then we're done.  But if we also hit some
+                    // user breakpoint on our way out, we should mark ourselves as done, but
+                    // also not claim to explain the stop, since it is more important to report
+                    // the user breakpoint than the step out completion.
+
+                    if (this_site->GetNumberOfOwners() == 1)
+                        return true;
+                    else
+                    {
+                        SetPlanComplete();
+                        return false;
+                    }
+                }
+                else
+                    return false;
+            }
+            case eStopReasonWatchpoint:
+            case eStopReasonSignal:
+            case eStopReasonException:
+                return false;
+            default:
+                return true;
+        }
+    }
+    return true;
+}
+
+bool
+ThreadPlanStepOut::ShouldStop (Event *event_ptr)
+{
+    if (IsPlanComplete()
+        || m_thread.GetRegisterContext()->GetPC() == m_return_addr
+        || m_stack_depth > m_thread.GetStackFrameCount())
+    {
+        SetPlanComplete();
+        return true;
+    }
+    else
+        return false;
+}
+
+bool
+ThreadPlanStepOut::StopOthers ()
+{
+    return m_stop_others;
+}
+
+StateType
+ThreadPlanStepOut::RunState ()
+{
+    return eStateRunning;
+}
+
+bool
+ThreadPlanStepOut::WillResume (StateType resume_state, bool current_plan)
+{
+    ThreadPlan::WillResume (resume_state, current_plan);
+    if (m_return_bp_id == LLDB_INVALID_BREAK_ID)
+        return false;
+
+    if (current_plan)
+    {
+        Breakpoint *return_bp = m_thread.GetProcess().GetTarget().GetBreakpointByID(m_return_bp_id).get();
+        if (return_bp != NULL)
+            return_bp->SetEnabled (true);
+    }
+    return true;
+}
+
+bool
+ThreadPlanStepOut::WillStop ()
+{
+    Breakpoint *return_bp = m_thread.GetProcess().GetTarget().GetBreakpointByID(m_return_bp_id).get();
+    if (return_bp != NULL)
+        return_bp->SetEnabled (false);
+    return true;
+}
+
+bool
+ThreadPlanStepOut::MischiefManaged ()
+{
+    if (m_return_bp_id == LLDB_INVALID_BREAK_ID)
+    {
+        // If I couldn't set this breakpoint, then I'm just going to jettison myself.
+        return true;
+    }
+    else if (IsPlanComplete())
+    {
+        // Did I reach my breakpoint?  If so I'm done.
+        //
+        // I also check the stack depth, since if we've blown past the breakpoint for some
+        // reason and we're now stopping for some other reason altogether, then we're done
+        // with this step out operation.
+
+        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+        if (log)
+            log->Printf("Completed step out plan.");
+        m_thread.GetProcess().GetTarget().RemoveBreakpointByID (m_return_bp_id);
+        m_return_bp_id = LLDB_INVALID_BREAK_ID;
+        ThreadPlan::MischiefManaged ();
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
diff --git a/source/Target/ThreadPlanStepOverBreakpoint.cpp b/source/Target/ThreadPlanStepOverBreakpoint.cpp
new file mode 100644
index 0000000..2b8b06d
--- /dev/null
+++ b/source/Target/ThreadPlanStepOverBreakpoint.cpp
@@ -0,0 +1,130 @@
+//===-- ThreadPlanStepOverBreakpoint.cpp ------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/ThreadPlanStepOverBreakpoint.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private-log.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// ThreadPlanStepOverBreakpoint: Single steps over a breakpoint bp_site_sp at the pc.
+//----------------------------------------------------------------------
+
+ThreadPlanStepOverBreakpoint::ThreadPlanStepOverBreakpoint (Thread &thread) :
+    ThreadPlan ("Step over breakpoint trap",
+                thread,
+                eVoteNo,
+                eVoteNoOpinion),  // We need to report the run since this happens
+                            // first in the thread plan stack when stepping
+                            // over a breakpoint
+    m_breakpoint_addr (LLDB_INVALID_ADDRESS)
+{
+    m_breakpoint_addr = m_thread.GetRegisterContext()->GetPC();
+    m_breakpoint_site_id =  m_thread.GetProcess().GetBreakpointSiteList().FindIDByAddress (m_breakpoint_addr);
+
+}
+
+ThreadPlanStepOverBreakpoint::~ThreadPlanStepOverBreakpoint ()
+{
+}
+
+void
+ThreadPlanStepOverBreakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+    s->Printf("Single stepping past breakpoint site %d at 0x%llx", m_breakpoint_site_id, (uint64_t)m_breakpoint_addr);
+}
+
+bool
+ThreadPlanStepOverBreakpoint::ValidatePlan (Stream *error)
+{
+    return true;
+}
+
+bool
+ThreadPlanStepOverBreakpoint::PlanExplainsStop ()
+{
+    return true;
+}
+
+bool
+ThreadPlanStepOverBreakpoint::ShouldStop (Event *event_ptr)
+{
+    return false;
+}
+
+bool
+ThreadPlanStepOverBreakpoint::StopOthers ()
+{
+    return true;
+}
+
+StateType
+ThreadPlanStepOverBreakpoint::RunState ()
+{
+    return eStateStepping;
+}
+
+bool
+ThreadPlanStepOverBreakpoint::WillResume (StateType resume_state, bool current_plan)
+{
+    ThreadPlan::WillResume (resume_state, current_plan);
+
+    if (current_plan)
+    {
+        BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
+        if (bp_site_sp  && bp_site_sp->IsEnabled())
+            m_thread.GetProcess().DisableBreakpoint (bp_site_sp.get());
+    }
+    return true;
+}
+
+bool
+ThreadPlanStepOverBreakpoint::WillStop ()
+{
+    BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
+    if (bp_site_sp)
+        m_thread.GetProcess().EnableBreakpoint (bp_site_sp.get());
+    return true;
+}
+
+bool
+ThreadPlanStepOverBreakpoint::MischiefManaged ()
+{
+    lldb::addr_t pc_addr = m_thread.GetRegisterContext()->GetPC();
+
+    if (pc_addr == m_breakpoint_addr)
+    {
+        // If we are still at the PC of our breakpoint, then for some reason we didn't
+        // get a chance to run.
+        return false;
+    }
+    else
+    {
+        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+        if (log)
+            log->Printf("Completed step over breakpoint plan.");
+        // Otherwise, re-enable the breakpoint we were stepping over, and we're done.
+        BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
+        if (bp_site_sp)
+            m_thread.GetProcess().EnableBreakpoint (bp_site_sp.get());
+        ThreadPlan::MischiefManaged ();
+        return true;
+    }
+}
+
diff --git a/source/Target/ThreadPlanStepOverRange.cpp b/source/Target/ThreadPlanStepOverRange.cpp
new file mode 100644
index 0000000..ea56412
--- /dev/null
+++ b/source/Target/ThreadPlanStepOverRange.cpp
@@ -0,0 +1,119 @@
+//===-- ThreadPlanStepOverRange.cpp -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/ThreadPlanStepOverRange.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+#include "lldb/lldb-private-log.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlanStepOut.h"
+#include "lldb/Target/ThreadPlanStepThrough.h"
+
+using namespace lldb_private;
+
+
+//----------------------------------------------------------------------
+// ThreadPlanStepOverRange: Step through a stack range, either stepping over or into
+// based on the value of \a type.
+//----------------------------------------------------------------------
+
+ThreadPlanStepOverRange::ThreadPlanStepOverRange
+(
+    Thread &thread,
+    const AddressRange &range,
+    const SymbolContext &addr_context,
+    lldb::RunMode stop_others,
+    bool okay_to_discard
+) :
+    ThreadPlanStepRange ("Step range stepping over", thread, range, addr_context, stop_others)
+{
+    SetOkayToDiscard (okay_to_discard);
+}
+
+ThreadPlanStepOverRange::~ThreadPlanStepOverRange ()
+{
+}
+
+void
+ThreadPlanStepOverRange::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+    if (level == lldb::eDescriptionLevelBrief)
+        s->Printf("step over");
+    else
+    {
+        s->Printf ("stepping through range (stepping over functions): ");
+        m_address_range.Dump (s, &m_thread.GetProcess(), Address::DumpStyleLoadAddress);
+    }
+}
+
+bool
+ThreadPlanStepOverRange::ShouldStop (Event *event_ptr)
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+
+    if (log)
+    {
+        StreamString s;
+        s.Address (m_thread.GetRegisterContext()->GetPC(), m_thread.GetProcess().GetAddressByteSize());
+        log->Printf("ThreadPlanStepOverRange reached %s.", s.GetData());
+    }
+    
+    // If we're still in the range, keep going.
+    if (InRange())
+        return false;
+
+    // If we're out of the range but in the same frame or in our caller's frame
+    // then we should stop.
+    // When stepping out we only step if we are forcing running one thread.
+    bool stop_others;
+    if (m_stop_others == lldb::eOnlyThisThread)
+        stop_others = true;
+    else 
+        stop_others = false;
+
+    ThreadPlan* new_plan = NULL;
+
+    if (FrameIsOlder())
+        return true;
+    else if (FrameIsYounger())
+    {
+        new_plan = m_thread.QueueThreadPlanForStepOut (false, NULL, true, stop_others, lldb::eVoteNo, lldb::eVoteNoOpinion);
+    }
+    else if (!InSymbol())
+    {
+        // This one is a little tricky.  Sometimes we may be in a stub or something similar,
+        // in which case we need to get out of there.  But if we are in a stub then it's 
+        // likely going to be hard to get out from here.  It is probably easiest to step into the
+        // stub, and then it will be straight-forward to step out.        
+        new_plan = m_thread.QueueThreadPlanForStepThrough (false, stop_others);
+    }
+
+    if (new_plan == NULL)
+        m_no_more_plans = true;
+    else
+        m_no_more_plans = false;
+
+    if (new_plan == NULL)
+    {
+        // For efficiencies sake, we know we're done here so we don't have to do this
+        // calculation again in MischiefManaged.
+        SetPlanComplete();
+        return true;
+    }
+    else
+        return false;
+}
diff --git a/source/Target/ThreadPlanStepRange.cpp b/source/Target/ThreadPlanStepRange.cpp
new file mode 100644
index 0000000..edf80a5
--- /dev/null
+++ b/source/Target/ThreadPlanStepRange.cpp
@@ -0,0 +1,263 @@
+//===-- ThreadPlanStepRange.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/ThreadPlanStepRange.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+#include "lldb/lldb-private-log.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/Symbol.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+//----------------------------------------------------------------------
+// ThreadPlanStepRange: Step through a stack range, either stepping over or into
+// based on the value of \a type.
+//----------------------------------------------------------------------
+
+ThreadPlanStepRange::ThreadPlanStepRange (const char *name, Thread &thread, const AddressRange &range, const SymbolContext &addr_context, lldb::RunMode stop_others) :
+    ThreadPlan (name, thread, eVoteNoOpinion, eVoteNoOpinion),
+    m_address_range (range),
+    m_addr_context (addr_context),
+    m_stop_others (stop_others),
+    m_stack_depth (0),
+    m_no_more_plans (false),
+    m_stack_id (),
+    m_first_run_event (true)
+{
+    m_stack_depth = m_thread.GetStackFrameCount();
+    m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
+}
+
+ThreadPlanStepRange::~ThreadPlanStepRange ()
+{
+}
+
+bool
+ThreadPlanStepRange::ValidatePlan (Stream *error)
+{
+    return true;
+}
+
+bool
+ThreadPlanStepRange::PlanExplainsStop ()
+{
+    // We don't explain signals or breakpoints (breakpoints that handle stepping in or
+    // out will be handled by a child plan.
+    Thread::StopInfo info;
+    if (m_thread.GetStopInfo (&info))
+    {
+        StopReason reason = info.GetStopReason();
+
+        switch (reason)
+        {
+            case eStopReasonBreakpoint:
+            case eStopReasonWatchpoint:
+            case eStopReasonSignal:
+            case eStopReasonException:
+                return false;
+            default:
+                return true;
+        }
+    }
+    return true;
+}
+
+Vote
+ThreadPlanStepRange::ShouldReportStop (Event *event_ptr)
+{
+    if (IsPlanComplete())
+        return eVoteYes;
+    else
+        return eVoteNo;
+}
+
+bool
+ThreadPlanStepRange::InRange ()
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+    bool ret_value = false;
+
+    lldb::addr_t pc_load_addr = m_thread.GetRegisterContext()->GetPC();
+
+    ret_value = m_address_range.ContainsLoadAddress(pc_load_addr, &m_thread.GetProcess());
+    
+    if (!ret_value)
+    {
+        // See if we've just stepped to another part of the same line number...
+        StackFrame *frame = m_thread.GetStackFrameAtIndex(0).get();
+        
+        SymbolContext new_context(frame->GetSymbolContext(eSymbolContextEverything));
+        if (m_addr_context.line_entry.IsValid() && new_context.line_entry.IsValid())
+        {
+           if ((m_addr_context.line_entry.file == new_context.line_entry.file)
+               && (m_addr_context.line_entry.line == new_context.line_entry.line))
+            {
+                m_addr_context = new_context;
+                m_address_range = m_addr_context.line_entry.range;
+                ret_value = true;
+                if (log)
+                {
+                    StreamString s;
+                    m_address_range.Dump (&s, &m_thread.GetProcess(), Address::DumpStyleLoadAddress);
+
+                    log->Printf ("Step range plan stepped to another range of same line: %s", s.GetData());
+                }
+            }
+        }
+        
+    }
+
+    if (!ret_value && log)
+        log->Printf ("Step range plan out of range to 0x%llx", pc_load_addr);
+
+    return ret_value;
+}
+
+bool
+ThreadPlanStepRange::InSymbol()
+{
+    lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC();
+    Process *process = m_thread.CalculateProcess();
+    
+    if (m_addr_context.function != NULL)
+    {
+        return m_addr_context.function->GetAddressRange().ContainsLoadAddress (cur_pc, process);
+    }
+    else if (m_addr_context.symbol != NULL)
+    {
+        return m_addr_context.symbol->GetAddressRangeRef().ContainsLoadAddress (cur_pc, process);
+    }
+    return false;
+}
+
+// FIXME: This should also handle inlining if we aren't going to do inlining in the
+// main stack.
+//
+// Ideally we should remember the whole stack frame list, and then compare that
+// to the current list.
+
+bool
+ThreadPlanStepRange::FrameIsYounger ()
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+    uint32_t current_depth = m_thread.GetStackFrameCount();
+    if (current_depth == m_stack_depth)
+    {
+        if (log)
+            log->Printf ("Step range FrameIsYounger still in start function.");
+        return false;
+    }
+    else if (current_depth < m_stack_depth)
+    {
+        if (log)
+            log->Printf ("Step range FrameIsYounger stepped out: start depth: %d current depth %d.", m_stack_depth, current_depth);
+        return false;
+    }
+    else
+    {
+        if (log)
+            log->Printf ("Step range FrameIsYounger stepped in: start depth: %d current depth %d.", m_stack_depth, current_depth);
+        return true;
+    }
+}
+
+bool
+ThreadPlanStepRange::FrameIsOlder ()
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+    uint32_t current_depth = m_thread.GetStackFrameCount();
+    if (current_depth == m_stack_depth)
+    {
+        if (log)
+            log->Printf ("Step range FrameIsOlder still in start function.");
+        return false;
+    }
+    else if (current_depth < m_stack_depth)
+    {
+        if (log)
+            log->Printf ("Step range FrameIsOlder stepped out: start depth: %d current depth %d.", m_stack_depth, current_depth);
+        return true;
+    }
+    else
+    {
+        if (log)
+            log->Printf ("Step range FrameIsOlder stepped in: start depth: %d current depth %d.", m_stack_depth, current_depth);
+        return false;
+    }
+}
+
+bool
+ThreadPlanStepRange::StopOthers ()
+{
+    if (m_stop_others == lldb::eOnlyThisThread
+        || m_stop_others == lldb::eOnlyDuringStepping)
+        return true;
+    else
+        return false;
+}
+
+bool
+ThreadPlanStepRange::WillStop ()
+{
+    return true;
+}
+
+StateType
+ThreadPlanStepRange::RunState ()
+{
+    return eStateStepping;
+}
+
+bool
+ThreadPlanStepRange::MischiefManaged ()
+{
+    bool done = true;
+    if (!IsPlanComplete())
+    {
+        if (InRange())
+        {
+            done = false;
+        }
+        else if (!FrameIsOlder())
+        {
+            if (m_no_more_plans)
+                done = true;
+            else
+                done = false;
+        }
+        else
+            done = true;
+    }
+
+    if (done)
+    {
+        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+        if (log)
+            log->Printf("Completed step through range plan.");
+        ThreadPlan::MischiefManaged ();
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+
+}
diff --git a/source/Target/ThreadPlanStepThrough.cpp b/source/Target/ThreadPlanStepThrough.cpp
new file mode 100644
index 0000000..5e614e5
--- /dev/null
+++ b/source/Target/ThreadPlanStepThrough.cpp
@@ -0,0 +1,137 @@
+//===-- ThreadPlanStepThrough.cpp -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/ThreadPlanStepThrough.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private-log.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// ThreadPlanStepThrough: If the current instruction is a trampoline, step through it
+// If it is the beginning of the prologue of a function, step through that as well.
+// FIXME: At present only handles DYLD trampolines.
+//----------------------------------------------------------------------
+
+ThreadPlanStepThrough::ThreadPlanStepThrough (Thread &thread, bool stop_others) :
+    ThreadPlan ("Step through trampolines and prologues", thread, eVoteNoOpinion, eVoteNoOpinion),
+    m_start_address (0),
+    m_stop_others (stop_others)
+{
+    m_start_address = GetThread().GetRegisterContext()->GetPC(0);
+}
+
+ThreadPlanStepThrough::~ThreadPlanStepThrough ()
+{
+}
+
+void
+ThreadPlanStepThrough::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+    if (level == lldb::eDescriptionLevelBrief)
+        s->Printf ("Step through");
+    else
+    {
+        s->Printf ("Stepping through trampoline code from: ");
+        s->Address(m_start_address, sizeof (addr_t));
+    }
+}
+
+bool
+ThreadPlanStepThrough::ValidatePlan (Stream *error)
+{
+    if (HappyToStopHere())
+        return false;
+    else
+        return true;
+}
+
+bool
+ThreadPlanStepThrough::PlanExplainsStop ()
+{
+    return true;
+}
+
+bool
+ThreadPlanStepThrough::ShouldStop (Event *event_ptr)
+{
+    return true;
+}
+
+bool
+ThreadPlanStepThrough::StopOthers ()
+{
+    return m_stop_others;
+}
+
+StateType
+ThreadPlanStepThrough::RunState ()
+{
+    return eStateStepping;
+}
+
+bool
+ThreadPlanStepThrough::WillResume (StateType resume_state, bool current_plan)
+{
+    ThreadPlan::WillResume(resume_state, current_plan);
+    if (current_plan)
+    {
+        ThreadPlanSP sub_plan_sp(m_thread.GetProcess().GetDynamicLoader()->GetStepThroughTrampolinePlan (m_thread, m_stop_others));
+        if (sub_plan_sp != NULL)
+            PushPlan (sub_plan_sp);
+    }
+    return true;
+}
+
+bool
+ThreadPlanStepThrough::WillStop ()
+{
+    return true;
+}
+
+bool
+ThreadPlanStepThrough::MischiefManaged ()
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+
+    // Stop if we're happy with the place we've landed...
+
+    if (!HappyToStopHere())
+    {
+        // If we are still at the PC we were trying to step over.
+        return false;
+    }
+    else
+    {
+        if (log)
+            log->Printf("Completed step through step plan.");
+        ThreadPlan::MischiefManaged ();
+        return true;
+    }
+}
+
+bool
+ThreadPlanStepThrough::HappyToStopHere()
+{
+    // This should again ask the various trampolines whether we are still at a
+    // trampoline point, and if so, continue through the possibly nested trampolines.
+
+    return true;
+}
+
diff --git a/source/Target/ThreadPlanStepUntil.cpp b/source/Target/ThreadPlanStepUntil.cpp
new file mode 100644
index 0000000..3f9cdb5
--- /dev/null
+++ b/source/Target/ThreadPlanStepUntil.cpp
@@ -0,0 +1,360 @@
+//===-- ThreadPlanStepUntil.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//m_should_stop
+
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/ThreadPlanStepUntil.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/lldb-private-log.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// ThreadPlanStepUntil: Run until we reach a given line number or step out of the current frame
+//----------------------------------------------------------------------
+
+ThreadPlanStepUntil::ThreadPlanStepUntil
+(
+    Thread &thread,
+    lldb::addr_t *address_list,
+    size_t num_addresses,
+    bool stop_others
+) :
+    ThreadPlan ("Step out", thread, eVoteNoOpinion, eVoteNoOpinion),
+    m_step_from_insn (LLDB_INVALID_ADDRESS),
+    m_return_addr (LLDB_INVALID_ADDRESS),
+    m_return_bp_id(LLDB_INVALID_BREAK_ID),
+    m_stepped_out(false),
+    m_should_stop(false),
+    m_explains_stop(false),
+    m_ran_analyze (false),
+    m_stop_others (stop_others)
+{
+
+    SetOkayToDiscard(true);
+    // Stash away our "until" addresses:
+    Target &target = m_thread.GetProcess().GetTarget();
+
+    m_step_from_insn = m_thread.GetRegisterContext()->GetPC(0);
+    lldb::user_id_t thread_id = m_thread.GetID();
+
+    // Find the return address and set a breakpoint there:
+    // FIXME - can we do this more securely if we know first_insn?
+
+    StackFrame *return_frame = m_thread.GetStackFrameAtIndex(1).get();
+    m_return_addr = return_frame->GetPC().GetLoadAddress(&m_thread.GetProcess());
+    Breakpoint *return_bp = target.CreateBreakpoint (m_return_addr, true).get();
+    if (return_bp != NULL)
+    {
+        return_bp->SetThreadID(thread_id);
+        m_return_bp_id = return_bp->GetID();
+    }
+    else
+    {
+        m_return_bp_id = LLDB_INVALID_BREAK_ID;
+    }
+
+    m_stack_depth = m_thread.GetStackFrameCount();
+
+    // Now set breakpoints on all our return addresses:
+    for (int i = 0; i < num_addresses; i++)
+    {
+        Breakpoint *until_bp = target.CreateBreakpoint (address_list[i], true).get();
+        if (until_bp != NULL)
+        {
+            until_bp->SetThreadID(thread_id);
+            m_until_points[address_list[i]] = until_bp->GetID();
+        }
+        else
+        {
+            m_until_points[address_list[i]] = LLDB_INVALID_BREAK_ID;
+        }
+    }
+}
+
+ThreadPlanStepUntil::~ThreadPlanStepUntil ()
+{
+    Clear();
+}
+
+void
+ThreadPlanStepUntil::Clear()
+{
+    Target &target = m_thread.GetProcess().GetTarget();
+    if (m_return_bp_id != LLDB_INVALID_BREAK_ID)
+    {
+        target.RemoveBreakpointByID(m_return_bp_id);
+        m_return_bp_id = LLDB_INVALID_BREAK_ID;
+    }
+
+    until_collection::iterator pos, end = m_until_points.end();
+    for (pos = m_until_points.begin(); pos != end; pos++)
+    {
+        target.RemoveBreakpointByID((*pos).second);
+    }
+    m_until_points.clear();
+}
+
+void
+ThreadPlanStepUntil::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+    if (level == lldb::eDescriptionLevelBrief)
+    {
+        s->Printf ("step until");
+        if (m_stepped_out)
+            s->Printf (" - stepped out");
+    }
+    else
+    {
+        if (m_until_points.size() == 1)
+            s->Printf ("Stepping from address 0x%llx until we reach 0x%llx using breakpoint %d",
+                       (uint64_t)m_step_from_insn,
+                       (uint64_t) (*m_until_points.begin()).first,
+                       (*m_until_points.begin()).second);
+        else
+        {
+            until_collection::iterator pos, end = m_until_points.end();
+            s->Printf ("Stepping from address 0x%llx until we reach one of:",
+                       (uint64_t)m_step_from_insn);
+            for (pos = m_until_points.begin(); pos != end; pos++)
+            {
+                s->Printf ("\n\t0x%llx (bp: %d)", (uint64_t) (*pos).first, (*pos).second);
+            }
+        }
+        s->Printf(" stepped out address is 0x%lx.", (uint64_t) m_return_addr);
+    }
+}
+
+bool
+ThreadPlanStepUntil::ValidatePlan (Stream *error)
+{
+    if (m_return_bp_id == LLDB_INVALID_BREAK_ID)
+        return false;
+    else
+    {
+        until_collection::iterator pos, end = m_until_points.end();
+        for (pos = m_until_points.begin(); pos != end; pos++)
+        {
+            if (!LLDB_BREAK_ID_IS_VALID ((*pos).second))
+                return false;
+        }
+        return true;
+    }
+}
+
+void
+ThreadPlanStepUntil::AnalyzeStop()
+{
+    if (m_ran_analyze)
+        return;
+        
+    Thread::StopInfo info;
+    m_should_stop = true;
+    m_explains_stop = false;
+    
+    if (m_thread.GetStopInfo (&info))
+    {
+        StopReason reason = info.GetStopReason();
+
+        switch (reason)
+        {
+            case eStopReasonBreakpoint:
+            {
+                // If this is OUR breakpoint, we're fine, otherwise we don't know why this happened...
+                BreakpointSiteSP this_site = m_thread.GetProcess().GetBreakpointSiteList().FindByID (info.GetBreakpointSiteID());
+                if (!this_site)
+                {
+                    m_explains_stop = false;
+                    return;
+                }
+
+                if (this_site->IsBreakpointAtThisSite (m_return_bp_id))
+                {
+                    // If we are at our "step out" breakpoint, and the stack depth has shrunk, then
+                    // this is indeed our stop.
+                    // If the stack depth has grown, then we've hit our step out breakpoint recursively.
+                    // If we are the only breakpoint at that location, then we do explain the stop, and
+                    // we'll just continue.
+                    // If there was another breakpoint here, then we don't explain the stop, but we won't
+                    // mark ourselves Completed, because maybe that breakpoint will continue, and then
+                    // we'll finish the "until".
+                    if (m_stack_depth > m_thread.GetStackFrameCount())
+                    {
+                        m_stepped_out = true;
+                        SetPlanComplete();
+                    }
+                    else
+                        m_should_stop = false;
+
+                    if (this_site->GetNumberOfOwners() == 1)
+                        m_explains_stop = true;
+                    else
+                        m_explains_stop = false;
+                    return;
+                }
+                else
+                {
+                    // Check if we've hit one of our "until" breakpoints.
+                    until_collection::iterator pos, end = m_until_points.end();
+                    for (pos = m_until_points.begin(); pos != end; pos++)
+                    {
+                        if (this_site->IsBreakpointAtThisSite ((*pos).second))
+                        {
+                            // If we're at the right stack depth, then we're done.
+                            if (m_stack_depth == m_thread.GetStackFrameCount())
+                                SetPlanComplete();
+                            else
+                                m_should_stop = false;
+
+                            // Otherwise we've hit this breakpoint recursively.  If we're the
+                            // only breakpoint here, then we do explain the stop, and we'll continue.
+                            // If not then we should let higher plans handle this stop.
+                            if (this_site->GetNumberOfOwners() == 1)
+                                m_explains_stop = true;
+                            else
+                            {
+                                m_should_stop = true;
+                                m_explains_stop = false;
+                            }
+                            return;
+                        }
+                    }
+                }
+                // If we get here we haven't hit any of our breakpoints, so let the higher
+                // plans take care of the stop.
+                m_explains_stop = false;
+                return;
+            }
+            case eStopReasonWatchpoint:
+            case eStopReasonSignal:
+            case eStopReasonException:
+                m_explains_stop = false;
+                break;
+            default:
+                m_explains_stop = true;
+                break;
+        }
+    }
+}
+
+bool
+ThreadPlanStepUntil::PlanExplainsStop ()
+{
+    // We don't explain signals or breakpoints (breakpoints that handle stepping in or
+    // out will be handled by a child plan.
+    AnalyzeStop();
+    return m_explains_stop;
+}
+
+bool
+ThreadPlanStepUntil::ShouldStop (Event *event_ptr)
+{
+    // If we've told our self in ExplainsStop that we plan to continue, then
+    // do so here.  Otherwise, as long as this thread has stopped for a reason,
+    // we will stop.
+
+    Thread::StopInfo stop_info (&m_thread);
+    if (!m_thread.GetStopInfo(&stop_info)
+        || stop_info.GetStopReason() == eStopReasonNone)
+        return false;
+
+    AnalyzeStop();
+    return m_should_stop;
+}
+
+bool
+ThreadPlanStepUntil::StopOthers ()
+{
+    return m_stop_others;
+}
+
+StateType
+ThreadPlanStepUntil::RunState ()
+{
+    return eStateRunning;
+}
+
+bool
+ThreadPlanStepUntil::WillResume (StateType resume_state, bool current_plan)
+{
+    ThreadPlan::WillResume (resume_state, current_plan);
+    if (current_plan)
+    {
+        Target &target = m_thread.GetProcess().GetTarget();
+        Breakpoint *return_bp = target.GetBreakpointByID(m_return_bp_id).get();
+        if (return_bp != NULL)
+            return_bp->SetEnabled (true);
+
+        until_collection::iterator pos, end = m_until_points.end();
+        for (pos = m_until_points.begin(); pos != end; pos++)
+        {
+            Breakpoint *until_bp = target.GetBreakpointByID((*pos).second).get();
+            if (until_bp != NULL)
+                until_bp->SetEnabled (true);
+        }
+    }
+    
+    m_should_stop = true;
+    m_ran_analyze = false;
+    m_explains_stop = false;
+    return true;
+}
+
+bool
+ThreadPlanStepUntil::WillStop ()
+{
+    Target &target = m_thread.GetProcess().GetTarget();
+    Breakpoint *return_bp = target.GetBreakpointByID(m_return_bp_id).get();
+    if (return_bp != NULL)
+        return_bp->SetEnabled (false);
+
+    until_collection::iterator pos, end = m_until_points.end();
+    for (pos = m_until_points.begin(); pos != end; pos++)
+    {
+        Breakpoint *until_bp = target.GetBreakpointByID((*pos).second).get();
+        if (until_bp != NULL)
+            until_bp->SetEnabled (false);
+    }
+    return true;
+}
+
+bool
+ThreadPlanStepUntil::MischiefManaged ()
+{
+
+    // I'm letting "PlanExplainsStop" do all the work, and just reporting that here.
+    bool done = false;
+    if (IsPlanComplete())
+    {
+        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+        if (log)
+            log->Printf("Completed step until plan.");
+
+        Clear();
+        done = true;
+    }
+    if (done)
+        ThreadPlan::MischiefManaged ();
+
+    return done;
+
+}
+
diff --git a/source/Target/UnixSignals.cpp b/source/Target/UnixSignals.cpp
new file mode 100644
index 0000000..e6500c5
--- /dev/null
+++ b/source/Target/UnixSignals.cpp
@@ -0,0 +1,310 @@
+//===-- UnixSignals.cpp -----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/UnixSignals.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb_private;
+
+UnixSignals::Signal::Signal (const char *name, bool default_suppress, bool default_stop, bool default_notify) :
+    m_name (name),
+    m_conditions ()
+{
+    m_conditions[Signal::eCondSuppress] = default_suppress;
+    m_conditions[Signal::eCondStop]     = default_stop;
+    m_conditions[Signal::eCondNotify]   = default_notify;
+}
+
+//----------------------------------------------------------------------
+// UnixSignals constructor
+//----------------------------------------------------------------------
+UnixSignals::UnixSignals ()
+{
+    Reset ();
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+UnixSignals::~UnixSignals ()
+{
+}
+
+void
+UnixSignals::Reset ()
+{
+    // This builds one standard set of Unix Signals.  If yours aren't quite in this
+    // order, you can either subclass this class, and use Add & Remove to change them
+    // or you can subclass and build them afresh in your constructor;
+    m_signals.clear();
+
+    AddSignal(1, "SIGHUP",     false, true,  true );    // 1    hangup
+    AddSignal(2, "SIGINT",     true,  true,  true );    // 2    interrupt
+    AddSignal(3, "SIGQUIT",    false, true,  true );    // 3    quit
+    AddSignal(4, "SIGILL",     false, true,  true );    // 4    illegal instruction (not reset when caught)
+    AddSignal(5, "SIGTRAP",    true,  true,  true );    // 5    trace trap (not reset when caught)
+    AddSignal(6, "SIGABRT",    false, true,  true );    // 6    abort()
+    AddSignal(7, "SIGEMT",     false, true,  true );    // 7    pollable event ([XSR] generated, not supported)
+    AddSignal(8, "SIGFPE",     false, true,  true );    // 8    floating point exception
+    AddSignal(9, "SIGKILL",    false, true,  true );    // 9    kill (cannot be caught or ignored)
+    AddSignal(10, "SIGBUS",    false, true,  true );    // 10    bus error
+    AddSignal(11, "SIGSEGV",   false, true,  true );    // 11    segmentation violation
+    AddSignal(12, "SIGSYS",    false, true,  true );    // 12    bad argument to system call
+    AddSignal(13, "SIGPIPE",   false, true,  true );    // 13    write on a pipe with no one to read it
+    AddSignal(14, "SIGALRM",   false, false, true );    // 14    alarm clock
+    AddSignal(15, "SIGTERM",   false, true,  true );    // 15    software termination signal from kill
+    AddSignal(16, "SIGURG",    false, false, false);    // 16    urgent condition on IO channel
+    AddSignal(17, "SIGSTOP",   false, true,  true );    // 17    sendable stop signal not from tty
+    AddSignal(18, "SIGTSTP",   false, true,  true );    // 18    stop signal from tty
+    AddSignal(19, "SIGCONT",   false, true,  true );    // 19    continue a stopped process
+    AddSignal(20, "SIGCHLD",   false, false, true );    // 20    to parent on child stop or exit
+    AddSignal(21, "SIGTTIN",   false, true,  true );    // 21    to readers pgrp upon background tty read
+    AddSignal(22, "SIGTTOU",   false, true,  true );    // 22    like TTIN for output if (tp->t_local&LTOSTOP)
+    AddSignal(23, "SIGIO",     false, false, false);    // 23    input/output possible signal
+    AddSignal(24, "SIGXCPU",   false, true,  true );    // 24    exceeded CPU time limit
+    AddSignal(25, "SIGXFSZ",   false, true,  true );    // 25    exceeded file size limit
+    AddSignal(26, "SIGVTALRM", false, false, false);    // 26    virtual time alarm
+    AddSignal(27, "SIGPROF",   false, false, false);    // 27    profiling time alarm
+    AddSignal(28, "SIGWINCH",  false, false, false);    // 28    window size changes
+    AddSignal(29, "SIGINFO",   false, true,  true );    // 29    information request
+    AddSignal(30, "SIGUSR1",   false, true,  true );    // 30    user defined signal 1
+    AddSignal(31, "SIGUSR2",   false, true,  true );    // 31    user defined signal 2
+}
+void
+UnixSignals::AddSignal (int signo, const char *name, bool default_suppress, bool default_stop, bool default_notify)
+{
+    collection::iterator iter = m_signals.find (signo);
+    struct Signal new_signal (name, default_suppress, default_stop, default_notify);
+
+    if (iter != m_signals.end())
+        m_signals.erase (iter);
+
+    m_signals.insert (iter, collection::value_type (signo, new_signal));
+}
+
+void
+UnixSignals::RemoveSignal (int signo)
+{
+    collection::iterator pos = m_signals.find (signo);
+    if (pos != m_signals.end())
+        m_signals.erase (pos);
+}
+
+UnixSignals::Signal *
+UnixSignals::GetSignalByName (const char *name, int32_t &signo)
+{
+    ConstString const_name (name);
+
+    collection::iterator pos, end = m_signals.end ();
+    for (pos = m_signals.begin (); pos != end; pos++)
+    {
+        if (const_name == (*pos).second.m_name)
+        {
+            signo = (*pos).first;
+            return &((*pos).second);
+        }
+    }
+    return NULL;
+}
+
+
+const UnixSignals::Signal *
+UnixSignals::GetSignalByName (const char *name, int32_t &signo) const
+{
+    ConstString const_name (name);
+
+    collection::const_iterator pos, end = m_signals.end ();
+    for (pos = m_signals.begin (); pos != end; pos++)
+    {
+        if (const_name == (*pos).second.m_name)
+        {
+            signo = (*pos).first;
+            return &((*pos).second);
+        }
+    }
+    return NULL;
+}
+
+const char *
+UnixSignals::GetSignalAsCString (int signo) const
+{
+    collection::const_iterator pos = m_signals.find (signo);
+    if (pos == m_signals.end())
+        return NULL;
+    else
+        return (*pos).second.m_name.GetCString ();
+}
+
+
+bool
+UnixSignals::SignalIsValid (int32_t signo) const
+{
+    return m_signals.find (signo) != m_signals.end();
+}
+
+
+int32_t
+UnixSignals::GetSignalNumberFromName (const char *name) const
+{
+    int32_t signo;
+    const Signal *signal = GetSignalByName (name, signo);
+    if (signal == NULL)
+        return LLDB_INVALID_SIGNAL_NUMBER;
+    else
+        return signo;
+}
+
+int32_t
+UnixSignals::GetFirstSignalNumber () const
+{
+    if (m_signals.empty())
+        return LLDB_INVALID_SIGNAL_NUMBER;
+
+    return (*m_signals.begin ()).first;
+}
+
+int32_t
+UnixSignals::GetNextSignalNumber (int32_t current_signal) const
+{
+    collection::const_iterator pos = m_signals.find (current_signal);
+    collection::const_iterator end = m_signals.end();
+    if (pos == end)
+        return LLDB_INVALID_SIGNAL_NUMBER;
+    else
+    {
+        pos++;
+        if (pos == end)
+            return LLDB_INVALID_SIGNAL_NUMBER;
+        else
+            return (*pos).first;
+    }
+}
+
+const char *
+UnixSignals::GetSignalInfo
+(
+    int32_t signo,
+    bool &should_suppress,
+    bool &should_stop,
+    bool &should_notify
+) const
+{
+    collection::const_iterator pos = m_signals.find (signo);
+    if (pos == m_signals.end())
+        return NULL;
+    else
+    {
+        const Signal &signal = (*pos).second;
+        should_suppress = signal.m_conditions[Signal::eCondSuppress];
+        should_stop     = signal.m_conditions[Signal::eCondStop];
+        should_notify   = signal.m_conditions[Signal::eCondNotify];
+        return signal.m_name.AsCString("");
+    }
+}
+
+bool
+UnixSignals::GetCondition
+(
+    int32_t signo,
+    UnixSignals::Signal::Condition cond_pos
+) const
+{
+    collection::const_iterator pos = m_signals.find (signo);
+    if (pos == m_signals.end())
+        return false;
+    else
+        return (*pos).second.m_conditions[cond_pos];
+}
+
+bool
+UnixSignals::SetCondition (int32_t signo, UnixSignals::Signal::Condition cond_pos, bool value)
+{
+    collection::iterator pos = m_signals.find (signo);
+    if (pos == m_signals.end())
+        return false;
+    else
+    {
+        bool ret_value = (*pos).second.m_conditions[cond_pos];
+        (*pos).second.m_conditions[cond_pos] = value;
+        return ret_value;
+    }
+}
+
+bool
+UnixSignals::SetCondition (const char *signal_name, UnixSignals::Signal::Condition cond_pos, bool value)
+{
+    int32_t signo;
+    Signal *signal = GetSignalByName (signal_name, signo);
+    if (signal == NULL)
+        return false;
+    else
+    {
+        bool ret_value = signal->m_conditions[cond_pos];
+        signal->m_conditions[cond_pos] = value;
+        return ret_value;
+    }
+}
+
+bool
+UnixSignals::GetShouldSuppress (int signo) const
+{
+    return GetCondition (signo, Signal::eCondSuppress);
+}
+
+bool
+UnixSignals::SetShouldSuppress (int signo, bool value)
+{
+    return SetCondition (signo, Signal::eCondSuppress, value);
+}
+
+bool
+UnixSignals::SetShouldSuppress (const char *signal_name, bool value)
+{
+    return SetCondition (signal_name, Signal::eCondSuppress, value);
+}
+
+bool
+UnixSignals::GetShouldStop (int signo) const
+{
+    return GetCondition (signo, Signal::eCondStop);
+}
+
+bool
+UnixSignals::SetShouldStop (int signo, bool value)
+{
+    return SetCondition (signo, Signal::eCondStop, value);
+}
+
+bool
+UnixSignals::SetShouldStop (const char *signal_name, bool value)
+{
+    return SetCondition (signal_name, Signal::eCondStop, value);
+}
+
+bool
+UnixSignals::GetShouldNotify (int signo) const
+{
+    return GetCondition (signo, Signal::eCondNotify);
+}
+
+bool
+UnixSignals::SetShouldNotify (int signo, bool value)
+{
+    return SetCondition (signo, Signal::eCondNotify, value);
+}
+
+bool
+UnixSignals::SetShouldNotify (const char *signal_name, bool value)
+{
+    return SetCondition (signal_name, Signal::eCondNotify, value);
+}
diff --git a/source/Utility/ARM_DWARF_Registers.h b/source/Utility/ARM_DWARF_Registers.h
new file mode 100644
index 0000000..40b973b
--- /dev/null
+++ b/source/Utility/ARM_DWARF_Registers.h
@@ -0,0 +1,190 @@
+//===-- ARM_DWARF_Registers.h -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef utility_ARM_DWARF_Registers_h_
+#define utility_ARM_DWARF_Registers_h_
+
+enum
+{
+    dwarf_r0 = 0,
+    dwarf_r1,
+    dwarf_r2,
+    dwarf_r3,
+    dwarf_r4,
+    dwarf_r5,
+    dwarf_r6,
+    dwarf_r7,
+    dwarf_r8,
+    dwarf_r9,
+    dwarf_r10,
+    dwarf_r11,
+    dwarf_r12,
+    dwarf_sp,
+    dwarf_lr,
+    dwarf_pc,
+    dwarf_cpsr,
+
+    dwarf_s0 = 64,
+    dwarf_s1,
+    dwarf_s2,
+    dwarf_s3,
+    dwarf_s4,
+    dwarf_s5,
+    dwarf_s6,
+    dwarf_s7,
+    dwarf_s8,
+    dwarf_s9,
+    dwarf_s10,
+    dwarf_s11,
+    dwarf_s12,
+    dwarf_s13,
+    dwarf_s14,
+    dwarf_s15,
+    dwarf_s16,
+    dwarf_s17,
+    dwarf_s18,
+    dwarf_s19,
+    dwarf_s20,
+    dwarf_s21,
+    dwarf_s22,
+    dwarf_s23,
+    dwarf_s24,
+    dwarf_s25,
+    dwarf_s26,
+    dwarf_s27,
+    dwarf_s28,
+    dwarf_s29,
+    dwarf_s30,
+    dwarf_s31,
+
+    // FPA Registers 0-7
+    dwarf_f0 = 96,
+    dwarf_f1,
+    dwarf_f2,
+    dwarf_f3,
+    dwarf_f4,
+    dwarf_f5,
+    dwarf_f6,
+    dwarf_f7,
+
+    // Intel wireless MMX general purpose registers 0–7
+    dwarf_wCGR0 = 104,
+    dwarf_wCGR1,
+    dwarf_wCGR2,
+    dwarf_wCGR3,
+    dwarf_wCGR4,
+    dwarf_wCGR5,
+    dwarf_wCGR6,
+    dwarf_wCGR7,
+
+    // XScale accumulator register 0–7 (they do overlap with wCGR0 - wCGR7)
+    dwarf_ACC0 = 104,
+    dwarf_ACC1,
+    dwarf_ACC2,
+    dwarf_ACC3,
+    dwarf_ACC4,
+    dwarf_ACC5,
+    dwarf_ACC6,
+    dwarf_ACC7,
+
+    // Intel wireless MMX data registers 0–15
+    dwarf_wR0 = 112,
+    dwarf_wR1,
+    dwarf_wR2,
+    dwarf_wR3,
+    dwarf_wR4,
+    dwarf_wR5,
+    dwarf_wR6,
+    dwarf_wR7,
+    dwarf_wR8,
+    dwarf_wR9,
+    dwarf_wR10,
+    dwarf_wR11,
+    dwarf_wR12,
+    dwarf_wR13,
+    dwarf_wR14,
+    dwarf_wR15,
+
+    dwarf_spsr = 128,
+    dwarf_spsr_fiq,
+    dwarf_spsr_irq,
+    dwarf_spsr_abt,
+    dwarf_spsr_und,
+    dwarf_spsr_svc,
+
+    dwarf_r8_usr = 144,
+    dwarf_r9_usr,
+    dwarf_r10_usr,
+    dwarf_r11_usr,
+    dwarf_r12_usr,
+    dwarf_r13_usr,
+    dwarf_r14_usr,
+    dwarf_r8_fiq,
+    dwarf_r9_fiq,
+    dwarf_r10_fiq,
+    dwarf_r11_fiq,
+    dwarf_r12_fiq,
+    dwarf_r13_fiq,
+    dwarf_r14_fiq,
+    dwarf_r13_irq,
+    dwarf_r14_irq,
+    dwarf_r13_abt,
+    dwarf_r14_abt,
+    dwarf_r13_und,
+    dwarf_r14_und,
+    dwarf_r13_svc,
+    dwarf_r14_svc,
+
+    // Intel wireless MMX control register in co-processor 0–7
+    dwarf_wC0 = 192,
+    dwarf_wC1,
+    dwarf_wC2,
+    dwarf_wC3,
+    dwarf_wC4,
+    dwarf_wC5,
+    dwarf_wC6,
+    dwarf_wC7,
+
+    // VFP-v3/Neon
+    dwarf_d0 = 256,
+    dwarf_d1,
+    dwarf_d2,
+    dwarf_d3,
+    dwarf_d4,
+    dwarf_d5,
+    dwarf_d6,
+    dwarf_d7,
+    dwarf_d8,
+    dwarf_d9,
+    dwarf_d10,
+    dwarf_d11,
+    dwarf_d12,
+    dwarf_d13,
+    dwarf_d14,
+    dwarf_d15,
+    dwarf_d16,
+    dwarf_d17,
+    dwarf_d18,
+    dwarf_d19,
+    dwarf_d20,
+    dwarf_d21,
+    dwarf_d22,
+    dwarf_d23,
+    dwarf_d24,
+    dwarf_d25,
+    dwarf_d26,
+    dwarf_d27,
+    dwarf_d28,
+    dwarf_d29,
+    dwarf_d30,
+    dwarf_d31
+};
+
+#endif utility_ARM_DWARF_Registers_h_
+
diff --git a/source/Utility/ARM_GCC_Registers.h b/source/Utility/ARM_GCC_Registers.h
new file mode 100644
index 0000000..fe1327b
--- /dev/null
+++ b/source/Utility/ARM_GCC_Registers.h
@@ -0,0 +1,35 @@
+//===-- ARM_GCC_Registers.h -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef utility_ARM_GCC_Registers_h_
+#define utility_ARM_GCC_Registers_h_
+
+enum
+{
+    gcc_r0 = 0,
+    gcc_r1,
+    gcc_r2,
+    gcc_r3,
+    gcc_r4,
+    gcc_r5,
+    gcc_r6,
+    gcc_r7,
+    gcc_r8,
+    gcc_r9,
+    gcc_r10,
+    gcc_r11,
+    gcc_r12,
+    gcc_sp,
+    gcc_lr,
+    gcc_pc,
+    gcc_cpsr
+};
+
+#endif utility_ARM_GCC_Registers_h_
+
diff --git a/source/Utility/PseudoTerminal.cpp b/source/Utility/PseudoTerminal.cpp
new file mode 100644
index 0000000..9bbecae
--- /dev/null
+++ b/source/Utility/PseudoTerminal.cpp
@@ -0,0 +1,336 @@
+//===-- PseudoTerminal.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PseudoTerminal.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
+using namespace lldb_utility;
+
+//----------------------------------------------------------------------
+// PseudoTerminal constructor
+//----------------------------------------------------------------------
+PseudoTerminal::PseudoTerminal () :
+    m_master_fd(invalid_fd),
+    m_slave_fd(invalid_fd)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//
+// The destructor will close the master and slave file descriptors
+// if they are valid and ownwership has not been released using the
+// ReleaseMasterFileDescriptor() or the ReleaseSaveFileDescriptor()
+// member functions.
+//----------------------------------------------------------------------
+PseudoTerminal::~PseudoTerminal ()
+{
+    CloseMasterFileDescriptor();
+    CloseSlaveFileDescriptor();
+}
+
+//----------------------------------------------------------------------
+// Close the master file descriptor if it is valid.
+//----------------------------------------------------------------------
+void
+PseudoTerminal::CloseMasterFileDescriptor ()
+{
+    if (m_master_fd >= 0)
+    {
+        ::close (m_master_fd);
+        m_master_fd = invalid_fd;
+    }
+}
+
+//----------------------------------------------------------------------
+// Close the slave file descriptor if it is valid.
+//----------------------------------------------------------------------
+void
+PseudoTerminal::CloseSlaveFileDescriptor ()
+{
+    if (m_slave_fd >= 0)
+    {
+        ::close (m_slave_fd);
+        m_slave_fd = invalid_fd;
+    }
+}
+
+//----------------------------------------------------------------------
+// Open the first available pseudo terminal with OFLAG as the
+// permissions. The file descriptor is stored in this object and can
+// be accessed with the MasterFileDescriptor() accessor. The
+// ownership of the master file descriptor can be released using
+// the ReleaseMasterFileDescriptor() accessor. If this object has
+// a valid master files descriptor when its destructor is called, it
+// will close the master file descriptor, therefore clients must
+// call ReleaseMasterFileDescriptor() if they wish to use the master
+// file descriptor after this object is out of scope or destroyed.
+//
+// RETURNS:
+//  Zero when successful, non-zero indicating an error occurred.
+//----------------------------------------------------------------------
+bool
+PseudoTerminal::OpenFirstAvailableMaster (int oflag, char *error_str, size_t error_len)
+{
+    if (error_str)
+        error_str[0] = '\0';
+
+    // Open the master side of a pseudo terminal
+    m_master_fd = ::posix_openpt (oflag);
+    if (m_master_fd < 0)
+    {
+        if (error_str)
+            ::strerror_r (errno, error_str, error_len);
+        return false;
+    }
+
+    // Grant access to the slave pseudo terminal
+    if (::grantpt (m_master_fd) < 0)
+    {
+        if (error_str)
+            ::strerror_r (errno, error_str, error_len);
+        CloseMasterFileDescriptor ();
+        return false;
+    }
+
+    // Clear the lock flag on the slave pseudo terminal
+    if (::unlockpt (m_master_fd) < 0)
+    {
+        if (error_str)
+            ::strerror_r (errno, error_str, error_len);
+        CloseMasterFileDescriptor ();
+        return false;
+    }
+
+    return true;
+}
+
+//----------------------------------------------------------------------
+// Open the slave pseudo terminal for the current master pseudo
+// terminal. A master pseudo terminal should already be valid prior to
+// calling this function (see OpenFirstAvailableMaster()).
+// The file descriptor is stored this object's member variables and can
+// be accessed via the GetSlaveFileDescriptor(), or released using the
+// ReleaseSlaveFileDescriptor() member function.
+//
+// RETURNS:
+//  Zero when successful, non-zero indicating an error occurred.
+//----------------------------------------------------------------------
+bool
+PseudoTerminal::OpenSlave (int oflag, char *error_str, size_t error_len)
+{
+    if (error_str)
+        error_str[0] = '\0';
+
+    CloseSlaveFileDescriptor();
+
+    // Open the master side of a pseudo terminal
+    const char *slave_name = GetSlaveName (error_str, error_len);
+
+    if (slave_name == NULL)
+        return false;
+
+    m_slave_fd = ::open (slave_name, oflag);
+
+    if (m_slave_fd < 0)
+    {
+        if (error_str)
+            ::strerror_r (errno, error_str, error_len);
+        return false;
+    }
+
+    return true;
+}
+
+
+
+//----------------------------------------------------------------------
+// Get the name of the slave pseudo terminal. A master pseudo terminal
+// should already be valid prior to calling this function (see
+// OpenFirstAvailableMaster()).
+//
+// RETURNS:
+//  NULL if no valid master pseudo terminal or if ptsname() fails.
+//  The name of the slave pseudo terminal as a NULL terminated C string
+//  that comes from static memory, so a copy of the string should be
+//  made as subsequent calls can change this value.
+//----------------------------------------------------------------------
+const char*
+PseudoTerminal::GetSlaveName (char *error_str, size_t error_len) const
+{
+    if (error_str)
+        error_str[0] = '\0';
+
+    if (m_master_fd < 0)
+    {
+        if (error_str)
+            ::snprintf (error_str, error_len, "%s", "master file descriptor is invalid");
+        return NULL;
+    }
+    const char *slave_name = ::ptsname (m_master_fd);
+
+    if (error_str && slave_name == NULL)
+        ::strerror_r (errno, error_str, error_len);
+
+    return slave_name;
+}
+
+
+//----------------------------------------------------------------------
+// Fork a child process and have its stdio routed to a pseudo terminal.
+//
+// In the parent process when a valid pid is returned, the master file
+// descriptor can be used as a read/write access to stdio of the
+// child process.
+//
+// In the child process the stdin/stdout/stderr will already be routed
+// to the slave pseudo terminal and the master file descriptor will be
+// closed as it is no longer needed by the child process.
+//
+// This class will close the file descriptors for the master/slave
+// when the destructor is called, so be sure to call
+// ReleaseMasterFileDescriptor() or ReleaseSlaveFileDescriptor() if any
+// file descriptors are going to be used past the lifespan of this
+// object.
+//
+// RETURNS:
+//  in the parent process: the pid of the child, or -1 if fork fails
+//  in the child process: zero
+//----------------------------------------------------------------------
+lldb::pid_t
+PseudoTerminal::Fork (char *error_str, size_t error_len)
+{
+    if (error_str)
+        error_str[0] = '\0';
+
+    pid_t pid = LLDB_INVALID_PROCESS_ID;
+    if (OpenFirstAvailableMaster (O_RDWR, error_str, error_len))
+    {
+        // Successfully opened our master pseudo terminal
+
+        pid = ::fork ();
+        if (pid < 0)
+        {
+            // Fork failed
+            if (error_str)
+            ::strerror_r (errno, error_str, error_len);
+        }
+        else if (pid == 0)
+        {
+            // Child Process
+            ::setsid();
+
+            if (OpenSlave (O_RDWR, error_str, error_len))
+            {
+                // Successfully opened slave
+                // We are done with the master in the child process so lets close it
+                CloseMasterFileDescriptor ();
+
+#if defined (TIOCSCTTY)
+                // Acquire the controlling terminal
+                if (::ioctl (m_slave_fd, TIOCSCTTY, (char *)0) < 0)
+                {
+                    if (error_str)
+                        ::strerror_r (errno, error_str, error_len);
+                }
+#endif
+                // Duplicate all stdio file descriptors to the slave pseudo terminal
+                if (::dup2 (m_slave_fd, STDIN_FILENO) != STDIN_FILENO)
+                {
+                    if (error_str && !error_str[0])
+                        ::strerror_r (errno, error_str, error_len);
+                }
+
+                if (::dup2 (m_slave_fd, STDOUT_FILENO) != STDOUT_FILENO)
+                {
+                    if (error_str && !error_str[0])
+                        ::strerror_r (errno, error_str, error_len);
+                }
+
+                if (::dup2 (m_slave_fd, STDERR_FILENO) != STDERR_FILENO)
+                {
+                    if (error_str && !error_str[0])
+                        ::strerror_r (errno, error_str, error_len);
+                }
+            }
+        }
+        else
+        {
+            // Parent Process
+            // Do nothing and let the pid get returned!
+        }
+    }
+    return pid;
+}
+
+//----------------------------------------------------------------------
+// The master file descriptor accessor. This object retains ownership
+// of the master file descriptor when this accessor is used. Use
+// ReleaseMasterFileDescriptor() if you wish this object to release
+// ownership of the master file descriptor.
+//
+// Returns the master file descriptor, or -1 if the master file
+// descriptor is not currently valid.
+//----------------------------------------------------------------------
+int
+PseudoTerminal::GetMasterFileDescriptor () const
+{
+    return m_master_fd;
+}
+
+//----------------------------------------------------------------------
+// The slave file descriptor accessor.
+//
+// Returns the slave file descriptor, or -1 if the slave file
+// descriptor is not currently valid.
+//----------------------------------------------------------------------
+int
+PseudoTerminal::GetSlaveFileDescriptor () const
+{
+    return m_slave_fd;
+}
+
+//----------------------------------------------------------------------
+// Release ownership of the master pseudo terminal file descriptor
+// without closing it. The destructor for this class will close the
+// master file descriptor if the ownership isn't released using this
+// call and the master file descriptor has been opened.
+//----------------------------------------------------------------------
+int
+PseudoTerminal::ReleaseMasterFileDescriptor ()
+{
+    // Release ownership of the master pseudo terminal file
+    // descriptor without closing it. (the destructor for this
+    // class will close it otherwise!)
+    int fd = m_master_fd;
+    m_master_fd = invalid_fd;
+    return fd;
+}
+
+//----------------------------------------------------------------------
+// Release ownership of the slave pseudo terminal file descriptor
+// without closing it. The destructor for this class will close the
+// slave file descriptor if the ownership isn't released using this
+// call and the slave file descriptor has been opened.
+//----------------------------------------------------------------------
+int
+PseudoTerminal::ReleaseSlaveFileDescriptor ()
+{
+    // Release ownership of the slave pseudo terminal file
+    // descriptor without closing it (the destructor for this
+    // class will close it otherwise!)
+    int fd = m_slave_fd;
+    m_slave_fd = invalid_fd;
+    return fd;
+}
+
diff --git a/source/Utility/PseudoTerminal.h b/source/Utility/PseudoTerminal.h
new file mode 100644
index 0000000..5d68074
--- /dev/null
+++ b/source/Utility/PseudoTerminal.h
@@ -0,0 +1,267 @@
+//===-- PseudoTerminal.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_PseudoTerminal_h_
+#define liblldb_PseudoTerminal_h_
+#if defined(__cplusplus)
+
+
+#include <fcntl.h>
+#include <termios.h>
+#include <string>
+
+#include "lldb/lldb-defines.h"
+
+namespace lldb_utility {
+
+//----------------------------------------------------------------------
+/// @class PseudoTerminal PseudoTerminal.h "lldb/Core/PseudoTerminal.h"
+/// @brief A pseudo terminal helper class.
+///
+/// The pseudo terminal class abtracts the use of pseudo terminals on
+/// the host system.
+//----------------------------------------------------------------------
+class PseudoTerminal
+{
+public:
+    enum
+    {
+        invalid_fd = -1,    ///< Invalid file descriptor value
+    };
+
+    //------------------------------------------------------------------
+    /// Default constructor
+    ///
+    /// Constructs this object with invalid master and slave file
+    /// descriptors.
+    //------------------------------------------------------------------
+    PseudoTerminal ();
+
+    //------------------------------------------------------------------
+    /// Destructor
+    ///
+    /// The destructor will close the master and slave file descriptors
+    /// if they are valid and ownwership has not been released using
+    /// one of:
+    /// @li PseudoTerminal::ReleaseMasterFileDescriptor()
+    /// @li PseudoTerminal::ReleaseSaveFileDescriptor()
+    //------------------------------------------------------------------
+    ~PseudoTerminal ();
+
+    //------------------------------------------------------------------
+    /// Close the master file descriptor if it is valid.
+    //------------------------------------------------------------------
+    void
+    CloseMasterFileDescriptor ();
+
+    //------------------------------------------------------------------
+    /// Close the slave file descriptor if it is valid.
+    //------------------------------------------------------------------
+    void
+    CloseSlaveFileDescriptor ();
+
+    //------------------------------------------------------------------
+    /// Fork a child process that uses pseudo terminals for its stdio.
+    ///
+    /// In the parent process, a call to this function results in a pid
+    /// being returned. If the pid is valid, the master file descriptor
+    /// can be used for read/write access to stdio of the child process.
+    ///
+    /// In the child process the stdin/stdout/stderr will already be
+    /// routed to the slave pseudo terminal and the master file
+    /// descriptor will be closed as it is no longer needed by the child
+    /// process.
+    ///
+    /// This class will close the file descriptors for the master/slave
+    /// when the destructor is called. The file handles can be released
+    /// using either:
+    /// @li PseudoTerminal::ReleaseMasterFileDescriptor()
+    /// @li PseudoTerminal::ReleaseSaveFileDescriptor()
+    ///
+    /// @param[out] error
+    ///     An pointer to an error that can describe any errors that
+    ///     occur. This can be NULL if no error status is desired.
+    ///
+    /// @return
+    ///     @li \b Parent process: a child process ID that is greater
+    ///         than zero, or -1 if the fork fails.
+    ///     @li \b Child process: zero.
+    //------------------------------------------------------------------
+    pid_t
+    Fork (char *error_str, size_t error_len);
+
+    //------------------------------------------------------------------
+    /// The master file descriptor accessor.
+    ///
+    /// This object retains ownership of the master file descriptor when
+    /// this accessor is used. Users can call the member function
+    /// PseudoTerminal::ReleaseMasterFileDescriptor() if this
+    /// object should release ownership of the slave file descriptor.
+    ///
+    /// @return
+    ///     The master file descriptor, or PseudoTerminal::invalid_fd
+    ///     if the master file  descriptor is not currently valid.
+    ///
+    /// @see PseudoTerminal::ReleaseMasterFileDescriptor()
+    //------------------------------------------------------------------
+    int
+    GetMasterFileDescriptor () const;
+
+    //------------------------------------------------------------------
+    /// The slave file descriptor accessor.
+    ///
+    /// This object retains ownership of the slave file descriptor when
+    /// this accessor is used. Users can call the member function
+    /// PseudoTerminal::ReleaseSlaveFileDescriptor() if this
+    /// object should release ownership of the slave file descriptor.
+    ///
+    /// @return
+    ///     The slave file descriptor, or PseudoTerminal::invalid_fd
+    ///     if the slave file descriptor is not currently valid.
+    ///
+    /// @see PseudoTerminal::ReleaseSlaveFileDescriptor()
+    //------------------------------------------------------------------
+    int
+    GetSlaveFileDescriptor () const;
+
+    //------------------------------------------------------------------
+    /// Get the name of the slave pseudo terminal.
+    ///
+    /// A master pseudo terminal should already be valid prior to
+    /// calling this function.
+    ///
+    /// @param[out] error
+    ///     An pointer to an error that can describe any errors that
+    ///     occur. This can be NULL if no error status is desired.
+    ///
+    /// @return
+    ///     The name of the slave pseudo terminal as a NULL terminated
+    ///     C. This string that comes from static memory, so a copy of
+    ///     the string should be made as subsequent calls can change
+    ///     this value. NULL is returned if this object doesn't have
+    ///     a valid master pseudo terminal opened or if the call to
+    ///     \c ptsname() fails.
+    ///
+    /// @see PseudoTerminal::OpenFirstAvailableMaster()
+    //------------------------------------------------------------------
+    const char*
+    GetSlaveName (char *error_str, size_t error_len) const;
+
+    //------------------------------------------------------------------
+    /// Open the first available pseudo terminal.
+    ///
+    /// Opens the first available pseudo terminal with \a oflag as the
+    /// permissions. The opened master file descriptor is stored in this
+    /// object and can be accessed by calling the
+    /// PseudoTerminal::GetMasterFileDescriptor() accessor. Clients
+    /// can call the PseudoTerminal::ReleaseMasterFileDescriptor()
+    /// accessor function if they wish to use the master file descriptor
+    /// beyond the lifespan of this object.
+    ///
+    /// If this object still has a valid master file descriptor when its
+    /// destructor is called, it will close it.
+    ///
+    /// @param[in] oflag
+    ///     Flags to use when calling \c posix_openpt(\a oflag).
+    ///     A value of "O_RDWR|O_NOCTTY" is suggested.
+    ///
+    /// @param[out] error
+    ///     An pointer to an error that can describe any errors that
+    ///     occur. This can be NULL if no error status is desired.
+    ///
+    /// @return
+    ///     @li \b true when the a master files descriptor is
+    ///         successfully opened.
+    ///     @li \b false if anything goes wrong.
+    ///
+    /// @see PseudoTerminal::GetMasterFileDescriptor()
+    /// @see PseudoTerminal::ReleaseMasterFileDescriptor()
+    //------------------------------------------------------------------
+    bool
+    OpenFirstAvailableMaster (int oflag, char *error_str, size_t error_len);
+
+    //------------------------------------------------------------------
+    /// Open the slave for the current master pseudo terminal.
+    ///
+    /// A master pseudo terminal should already be valid prior to
+    /// calling this function. The opened slave file descriptor is
+    /// stored in this object and can be accessed by calling the
+    /// PseudoTerminal::GetSlaveFileDescriptor() accessor. Clients
+    /// can call the PseudoTerminal::ReleaseSlaveFileDescriptor()
+    /// accessor function if they wish to use the slave file descriptor
+    /// beyond the lifespan of this object.
+    ///
+    /// If this object still has a valid slave file descriptor when its
+    /// destructor is called, it will close it.
+    ///
+    /// @param[in] oflag
+    ///     Flags to use when calling \c open(\a oflag).
+    ///
+    /// @param[out] error
+    ///     An pointer to an error that can describe any errors that
+    ///     occur. This can be NULL if no error status is desired.
+    ///
+    /// @return
+    ///     @li \b true when the a master files descriptor is
+    ///         successfully opened.
+    ///     @li \b false if anything goes wrong.
+    ///
+    /// @see PseudoTerminal::OpenFirstAvailableMaster()
+    /// @see PseudoTerminal::GetSlaveFileDescriptor()
+    /// @see PseudoTerminal::ReleaseSlaveFileDescriptor()
+    //------------------------------------------------------------------
+    bool
+    OpenSlave (int oflag, char *error_str, size_t error_len);
+
+    //------------------------------------------------------------------
+    /// Release the master file descriptor.
+    ///
+    /// Releases ownership of the master pseudo terminal file descriptor
+    /// without closing it. The destructor for this class will close the
+    /// master file descriptor if the ownership isn't released using this
+    /// call and the master file descriptor has been opened.
+    ///
+    /// @return
+    ///     The master file descriptor, or PseudoTerminal::invalid_fd
+    ///     if the mast file descriptor is not currently valid.
+    //------------------------------------------------------------------
+    int
+    ReleaseMasterFileDescriptor ();
+
+    //------------------------------------------------------------------
+    /// Release the slave file descriptor.
+    ///
+    /// Release ownership of the slave pseudo terminal file descriptor
+    /// without closing it. The destructor for this class will close the
+    /// slave file descriptor if the ownership isn't released using this
+    /// call and the slave file descriptor has been opened.
+    ///
+    /// @return
+    ///     The slave file descriptor, or PseudoTerminal::invalid_fd
+    ///     if the slave file descriptor is not currently valid.
+    //------------------------------------------------------------------
+    int
+    ReleaseSlaveFileDescriptor ();
+
+protected:
+    //------------------------------------------------------------------
+    // Member variables
+    //------------------------------------------------------------------
+    int m_master_fd;    ///< The file descriptor for the master.
+    int m_slave_fd;     ///< The file descriptor for the slave.
+
+private:
+    DISALLOW_COPY_AND_ASSIGN (PseudoTerminal);
+
+};
+
+} // namespace lldb
+
+#endif  // #if defined(__cplusplus)
+#endif // #ifndef liblldb_PseudoTerminal_h_
diff --git a/source/Utility/StringExtractor.cpp b/source/Utility/StringExtractor.cpp
new file mode 100644
index 0000000..d2f69f9
--- /dev/null
+++ b/source/Utility/StringExtractor.cpp
@@ -0,0 +1,360 @@
+//===-- StringExtractor.cpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "StringExtractor.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+static inline int
+xdigit_to_sint (char ch)
+{
+    ch = tolower(ch);
+    if (ch >= 'a' && ch <= 'f')
+        return 10 + ch - 'a';
+    return ch - '0';
+}
+
+static inline unsigned int
+xdigit_to_uint (uint8_t ch)
+{
+    ch = tolower(ch);
+    if (ch >= 'a' && ch <= 'f')
+        return 10u + ch - 'a';
+    return ch - '0';
+}
+
+//----------------------------------------------------------------------
+// StringExtractor constructor
+//----------------------------------------------------------------------
+StringExtractor::StringExtractor() :
+    m_packet(),
+    m_index (0)
+{
+}
+
+
+StringExtractor::StringExtractor(const char *packet_cstr) :
+    m_packet(),
+    m_index (0)
+{
+    if (packet_cstr)
+        m_packet.assign (packet_cstr);
+}
+
+
+//----------------------------------------------------------------------
+// StringExtractor copy constructor
+//----------------------------------------------------------------------
+StringExtractor::StringExtractor(const StringExtractor& rhs) :
+    m_packet (rhs.m_packet),
+    m_index (rhs.m_index)
+{
+
+}
+
+//----------------------------------------------------------------------
+// StringExtractor assignment operator
+//----------------------------------------------------------------------
+const StringExtractor&
+StringExtractor::operator=(const StringExtractor& rhs)
+{
+    if (this != &rhs)
+    {
+        m_packet = rhs.m_packet;
+        m_index = rhs.m_index;
+
+    }
+    return *this;
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+StringExtractor::~StringExtractor()
+{
+}
+
+
+char
+StringExtractor::GetChar (char fail_value)
+{
+    if (m_index < m_packet.size())
+    {
+        char ch = m_packet[m_index];
+        ++m_index;
+        return ch;
+    }
+    m_index = UINT32_MAX;
+    return fail_value;
+}
+
+uint32_t
+StringExtractor::GetNumHexASCIICharsAtFilePos (uint32_t max) const
+{
+    uint32_t idx = m_index;
+    const size_t size = m_packet.size();
+    while (idx < size && idx - m_index < max && isxdigit(m_packet[idx]))
+        ++idx;
+    return idx - m_index;
+}
+//----------------------------------------------------------------------
+// Extract a signed character from two hex ASCII chars in the packet
+// string
+//----------------------------------------------------------------------
+int8_t
+StringExtractor::GetHexS8 (int8_t fail_value)
+{
+    if (GetNumHexASCIICharsAtFilePos(2))
+    {
+        char hi_nibble_char = m_packet[m_index];
+        char lo_nibble_char = m_packet[m_index+1];
+
+        if (isxdigit(hi_nibble_char) && isxdigit(lo_nibble_char))
+        {
+            char hi_nibble = xdigit_to_sint (hi_nibble_char);
+            char lo_nibble = xdigit_to_sint (lo_nibble_char);
+            m_index += 2;
+            return (hi_nibble << 4) + lo_nibble;
+        }
+    }
+    m_index = UINT32_MAX;
+    return fail_value;
+}
+
+//----------------------------------------------------------------------
+// Extract an unsigned character from two hex ASCII chars in the packet
+// string
+//----------------------------------------------------------------------
+uint8_t
+StringExtractor::GetHexU8 (uint8_t fail_value)
+{
+    if (GetNumHexASCIICharsAtFilePos(2))
+    {
+        uint8_t hi_nibble_char = m_packet[m_index];
+        uint8_t lo_nibble_char = m_packet[m_index+1];
+
+        if (isxdigit(hi_nibble_char) && isxdigit(lo_nibble_char))
+        {
+            uint8_t hi_nibble = xdigit_to_sint (hi_nibble_char);
+            uint8_t lo_nibble = xdigit_to_sint (lo_nibble_char);
+            m_index += 2;
+            return (hi_nibble << 4) + lo_nibble;
+        }
+    }
+    m_index = UINT32_MAX;
+    return fail_value;
+}
+
+uint32_t
+StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
+{
+    uint32_t result = 0;
+    uint32_t nibble_count = 0;
+
+    if (little_endian)
+    {
+        uint32_t shift_amount = 0;
+        while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
+        {
+            // Make sure we don't exceed the size of a uint32_t...
+            if (nibble_count >= (sizeof(uint32_t) * 2))
+            {
+                m_index = UINT32_MAX;
+                return fail_value;
+            }
+
+            uint8_t nibble_lo;
+            uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
+            ++m_index;
+            if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
+            {
+                nibble_lo = xdigit_to_sint (m_packet[m_index]);
+                ++m_index;
+                result |= ((uint32_t)nibble_hi << (shift_amount + 4));
+                result |= ((uint32_t)nibble_lo << shift_amount);
+                nibble_count += 2;
+                shift_amount += 8;
+            }
+            else
+            {
+                result |= ((uint32_t)nibble_hi << shift_amount);
+                nibble_count += 1;
+                shift_amount += 4;
+            }
+
+        }
+    }
+    else
+    {
+        while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
+        {
+            // Make sure we don't exceed the size of a uint32_t...
+            if (nibble_count >= (sizeof(uint32_t) * 2))
+            {
+                m_index = UINT32_MAX;
+                return fail_value;
+            }
+
+            uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
+            // Big Endian
+            result <<= 4;
+            result |= nibble;
+
+            ++m_index;
+            ++nibble_count;
+        }
+    }
+    return result;
+}
+
+uint64_t
+StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
+{
+    uint64_t result = 0;
+    uint32_t nibble_count = 0;
+
+    if (little_endian)
+    {
+        uint32_t shift_amount = 0;
+        while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
+        {
+            // Make sure we don't exceed the size of a uint64_t...
+            if (nibble_count >= (sizeof(uint64_t) * 2))
+            {
+                m_index = UINT32_MAX;
+                return fail_value;
+            }
+
+            uint8_t nibble_lo;
+            uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
+            ++m_index;
+            if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
+            {
+                nibble_lo = xdigit_to_sint (m_packet[m_index]);
+                ++m_index;
+                result |= ((uint64_t)nibble_hi << (shift_amount + 4));
+                result |= ((uint64_t)nibble_lo << shift_amount);
+                nibble_count += 2;
+                shift_amount += 8;
+            }
+            else
+            {
+                result |= ((uint64_t)nibble_hi << shift_amount);
+                nibble_count += 1;
+                shift_amount += 4;
+            }
+
+        }
+    }
+    else
+    {
+        while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
+        {
+            // Make sure we don't exceed the size of a uint64_t...
+            if (nibble_count >= (sizeof(uint64_t) * 2))
+            {
+                m_index = UINT32_MAX;
+                return fail_value;
+            }
+
+            uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
+            // Big Endian
+            result <<= 4;
+            result |= nibble;
+
+            ++m_index;
+            ++nibble_count;
+        }
+    }
+    return result;
+}
+
+size_t
+StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_value)
+{
+    uint8_t *dst = (uint8_t*)dst_void;
+    size_t bytes_extracted = 0;
+    while (bytes_extracted < dst_len && GetBytesLeft ())
+    {
+        dst[bytes_extracted] = GetHexU8 (fail_fill_value);
+        if (IsGood())
+            ++bytes_extracted;
+        else
+            break;
+    }
+
+    for (size_t i = bytes_extracted; i < dst_len; ++i)
+        dst[i] = fail_fill_value;
+
+    return bytes_extracted;
+}
+
+
+// Consume ASCII hex nibble character pairs until we have decoded byte_size
+// bytes of data.
+
+uint64_t
+StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value)
+{
+    if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2)
+    {
+        uint64_t result = 0;
+        uint32_t i;
+        if (little_endian)
+        {
+            // Little Endian
+            uint32_t shift_amount;
+            for (i = 0, shift_amount = 0;
+                 i < byte_size && m_index != UINT32_MAX;
+                 ++i, shift_amount += 8)
+            {
+                result |= ((uint64_t)GetHexU8() << shift_amount);
+            }
+        }
+        else
+        {
+            // Big Endian
+            for (i = 0; i < byte_size && m_index != UINT32_MAX; ++i)
+            {
+                result <<= 8;
+                result |= GetHexU8();
+            }
+        }
+    }
+    m_index = UINT32_MAX;
+    return fail_value;
+}
+
+bool
+StringExtractor::GetNameColonValue (std::string &name, std::string &value)
+{
+    // Read something in the form of NNNN:VVVV; where NNNN is any character
+    // that is not a colon, followed by a ':' character, then a value (one or
+    // more ';' chars), followed by a ';'
+    if (m_index < m_packet.size())
+    {
+        const size_t colon_idx = m_packet.find (':', m_index);
+        if (colon_idx != std::string::npos)
+        {
+            const size_t semicolon_idx = m_packet.find (';', colon_idx);
+            if (semicolon_idx != std::string::npos)
+            {
+                name.assign (m_packet, m_index, colon_idx - m_index);
+                value.assign (m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
+                m_index = semicolon_idx + 1;
+                return true;
+            }
+        }
+    }
+    m_index = UINT32_MAX;
+    return false;
+}
diff --git a/source/Utility/StringExtractor.h b/source/Utility/StringExtractor.h
new file mode 100644
index 0000000..e2312f7
--- /dev/null
+++ b/source/Utility/StringExtractor.h
@@ -0,0 +1,126 @@
+//===-- StringExtractor.h ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef utility_StringExtractor_h_
+#define utility_StringExtractor_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+
+class StringExtractor
+{
+public:
+
+    enum {
+        BigEndian = 0,
+        LittleEndian = 1
+    };
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    StringExtractor();
+    StringExtractor(const char *packet_cstr);
+    StringExtractor(const StringExtractor& rhs);
+    virtual ~StringExtractor();
+
+    //------------------------------------------------------------------
+    // Operators
+    //------------------------------------------------------------------
+    const StringExtractor&
+    operator=(const StringExtractor& rhs);
+
+    // Returns true if the file position is still valid for the data
+    // contained in this string extractor object.
+    bool
+    IsGood() const
+    {
+        return m_index != UINT32_MAX;
+    }
+
+    uint32_t
+    GetFilePos () const
+    {
+        return m_index;
+    }
+
+    void
+    SetFilePos (uint32_t idx)
+    {
+        m_index = idx;
+    }
+
+    void
+    Clear ()
+    {
+        m_packet.clear();
+        m_index = 0;
+    }
+
+    std::string &
+    GetStringRef ()
+    {
+        return m_packet;
+    }
+
+    bool
+    Empty()
+    {
+        return m_packet.empty();
+    }
+
+    uint32_t
+    GetBytesLeft ()
+    {
+        if (m_index < m_packet.size())
+            return m_packet.size() - m_index;
+        return 0;
+    }
+    char
+    GetChar (char fail_value = '\0');
+
+    int8_t
+    GetHexS8 (int8_t fail_value = 0);
+
+    uint8_t
+    GetHexU8 (uint8_t fail_value = 0);
+
+    bool
+    GetNameColonValue (std::string &name, std::string &value);
+
+    uint32_t
+    GetHexMaxU32 (bool little_endian, uint32_t fail_value);
+
+    uint64_t
+    GetHexMaxU64 (bool little_endian, uint64_t fail_value);
+
+    size_t
+    GetHexBytes (void *dst, size_t dst_len, uint8_t fail_fill_value);
+
+    uint64_t
+    GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value);
+
+protected:
+    //------------------------------------------------------------------
+    // For StringExtractor only
+    //------------------------------------------------------------------
+    std::string m_packet;   // The string in which to extract data.
+    uint32_t m_index;       // When extracting data from a packet, this index
+                            // will march along as things get extracted. If set
+                            // to UINT32_MAX the end of the packet data was
+                            // reached when decoding information
+
+    uint32_t
+    GetNumHexASCIICharsAtFilePos (uint32_t max = UINT32_MAX) const;
+};
+
+#endif  // utility_StringExtractor_h_
diff --git a/source/Utility/StringExtractorGDBRemote.cpp b/source/Utility/StringExtractorGDBRemote.cpp
new file mode 100644
index 0000000..f7dcc41
--- /dev/null
+++ b/source/Utility/StringExtractorGDBRemote.cpp
@@ -0,0 +1,89 @@
+//===-- StringExtractorGDBRemote.cpp ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "StringExtractorGDBRemote.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+
+
+StringExtractorGDBRemote::Type
+StringExtractorGDBRemote::GetType () const
+{
+    if (m_packet.empty())
+        return eUnsupported;
+
+    switch (m_packet[0])
+    {
+    case 'E':
+        if (m_packet.size() == 3 &&
+            isxdigit(m_packet[1]) &&
+            isxdigit(m_packet[2]))
+            return eError;
+        break;
+
+    case 'O':
+        if (m_packet.size() == 2 && m_packet[1] == 'K')
+            return eOK;
+        break;
+
+    case '+':
+        if (m_packet.size() == 1)
+            return eAck;
+        break;
+
+    case '-':
+        if (m_packet.size() == 1)
+            return eNack;
+        break;
+    }
+    return eResponse;
+}
+
+bool
+StringExtractorGDBRemote::IsOKPacket() const
+{
+    return GetType () == eOK;
+}
+
+
+bool
+StringExtractorGDBRemote::IsUnsupportedPacket() const
+{
+    return GetType () == eUnsupported;
+}
+
+bool
+StringExtractorGDBRemote::IsNormalPacket() const
+{
+    return GetType () == eResponse;
+}
+
+bool
+StringExtractorGDBRemote::IsErrorPacket() const
+{
+    return GetType () == eError &&
+           m_packet.size() == 3 &&
+           isxdigit(m_packet[1]) &&
+           isxdigit(m_packet[2]);
+}
+
+uint8_t
+StringExtractorGDBRemote::GetError ()
+{
+    if (GetType() == eError)
+    {
+        SetFilePos(1);
+        return GetHexU8(255);
+    }
+    return 0;
+}
diff --git a/source/Utility/StringExtractorGDBRemote.h b/source/Utility/StringExtractorGDBRemote.h
new file mode 100644
index 0000000..813ddad
--- /dev/null
+++ b/source/Utility/StringExtractorGDBRemote.h
@@ -0,0 +1,73 @@
+//===-- StringExtractorGDBRemote.h ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef utility_StringExtractorGDBRemote_h_
+#define utility_StringExtractorGDBRemote_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+// Other libraries and framework includes
+// Project includes
+#include "StringExtractor.h"
+
+class StringExtractorGDBRemote : public StringExtractor
+{
+public:
+
+    StringExtractorGDBRemote() :
+        StringExtractor ()
+    {
+    }
+
+    StringExtractorGDBRemote(const char *cstr) :
+        StringExtractor (cstr)
+    {
+    }
+    StringExtractorGDBRemote(const StringExtractorGDBRemote& rhs) :
+        StringExtractor (rhs)
+    {
+    }
+
+    virtual ~StringExtractorGDBRemote()
+    {
+    }
+
+    enum Type
+    {
+        eUnsupported = 0,
+        eAck,
+        eNack,
+        eError,
+        eOK,
+        eResponse
+    };
+
+    StringExtractorGDBRemote::Type
+    GetType () const;
+
+    bool
+    IsOKPacket() const;
+
+    bool
+    IsUnsupportedPacket() const;
+
+    bool
+    IsNormalPacket () const;
+
+    bool
+    IsErrorPacket() const;
+
+    // Returns zero if the packet isn't a EXX packet where XX are two hex
+    // digits. Otherwise the error encoded in XX is returned.
+    uint8_t
+    GetError();
+};
+
+#endif  // utility_StringExtractorGDBRemote_h_
diff --git a/source/lldb-log.cpp b/source/lldb-log.cpp
new file mode 100644
index 0000000..118a5b3
--- /dev/null
+++ b/source/lldb-log.cpp
@@ -0,0 +1,190 @@
+//===-- lldb-log.cpp --------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-private-log.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamFile.h"
+
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+static Log *
+LogAccessor (bool get, StreamSP *stream_sp_ptr)
+{
+    static Log* g_log = NULL; // Leak for now as auto_ptr was being cleaned up
+                                // by global constructors before other threads
+                                // were done with it.
+    if (!get)
+    {
+        if (g_log)
+            delete g_log;
+        if (stream_sp_ptr)
+            g_log = new Log (*stream_sp_ptr);
+        else
+            g_log = NULL;
+    }
+
+    return g_log;
+
+}
+
+uint32_t
+lldb_private::GetLogMask ()
+{
+    Log *log = LogAccessor (true, NULL);
+    if (log)
+        return log->GetMask().GetAllFlagBits();
+    return 0;
+}
+
+bool
+lldb_private::IsLogVerbose ()
+{
+    uint32_t mask = GetLogMask();
+    return (mask & LIBLLDB_LOG_VERBOSE);
+}
+
+Log *
+lldb_private::GetLogIfAllCategoriesSet (uint32_t mask)
+{
+    Log *log = LogAccessor (true, NULL);
+    if (log && mask)
+    {
+        uint32_t log_mask = log->GetMask().GetAllFlagBits();
+        if ((log_mask & mask) != mask)
+            return NULL;
+    }
+    return log;
+}
+
+void
+lldb_private::LogIfAllCategoriesSet (uint32_t mask, const char *format, ...)
+{
+    Log *log = GetLogIfAllCategoriesSet (mask);
+    if (log)
+    {
+        va_list args;
+        va_start (args, format);
+        log->VAPrintf (format, args);
+        va_end (args);
+    }
+}
+
+void
+lldb_private::LogIfAnyCategoriesSet (uint32_t mask, const char *format, ...)
+{
+    Log *log = GetLogIfAnyCategoriesSet (mask);
+    if (log)
+    {
+        va_list args;
+        va_start (args, format);
+        log->VAPrintf (format, args);
+        va_end (args);
+    }
+}
+
+Log *
+lldb_private::GetLogIfAnyCategoriesSet (uint32_t mask)
+{
+    Log *log = LogAccessor (true, NULL);
+    if (log && mask && (mask & log->GetMask().GetAllFlagBits()))
+        return log;
+    return NULL;
+}
+
+void
+lldb_private::DisableLog ()
+{
+    LogAccessor (false, NULL);
+}
+
+
+Log *
+lldb_private::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &args, Stream *feedback_strm)
+{
+    // Try see if there already is a log - that way we can reuse its settings.
+    // We could reuse the log in toto, but we don't know that the stream is the same.
+    uint32_t flag_bits;
+    Log* log = LogAccessor (true, NULL);
+    if (log)
+        flag_bits = log->GetMask().GetAllFlagBits();
+    else
+        flag_bits = 0;
+
+    // Now make a new log with this stream.
+    log = LogAccessor (false, &log_stream_sp);
+    if (log)
+    {
+        bool got_unknown_category = false;
+        const size_t argc = args.GetArgumentCount();
+        for (size_t i=0; i<argc; ++i)
+        {
+            const char *arg = args.GetArgumentAtIndex(i);
+
+            if      (strcasecmp(arg, "all")     == 0  ) flag_bits |= LIBLLDB_LOG_ALL;
+            else if (strcasestr(arg, "break")   == arg) flag_bits |= LIBLLDB_LOG_BREAKPOINTS;
+            else if (strcasecmp(arg, "default") == 0  ) flag_bits |= LIBLLDB_LOG_DEFAULT;
+            else if (strcasestr(arg, "event")   == arg) flag_bits |= LIBLLDB_LOG_EVENTS;
+            else if (strcasestr(arg, "expr")    == arg) flag_bits |= LIBLLDB_LOG_EXPRESSIONS;
+            else if (strcasestr(arg, "object")  == arg) flag_bits |= LIBLLDB_LOG_OBJECT;
+            else if (strcasecmp(arg, "process") == 0  ) flag_bits |= LIBLLDB_LOG_PROCESS;
+            else if (strcasecmp(arg, "shlib")   == 0  ) flag_bits |= LIBLLDB_LOG_SHLIB;
+            else if (strcasecmp(arg, "state")   == 0  ) flag_bits |= LIBLLDB_LOG_STATE;
+            else if (strcasecmp(arg, "step")    == 0  ) flag_bits |= LIBLLDB_LOG_STEP;
+            else if (strcasecmp(arg, "thread")  == 0  ) flag_bits |= LIBLLDB_LOG_THREAD;
+            else if (strcasecmp(arg, "verbose") == 0  ) flag_bits |= LIBLLDB_LOG_VERBOSE;
+            else if (strcasestr(arg, "watch")   == arg) flag_bits |= LIBLLDB_LOG_WATCHPOINTS;
+            else if (strcasestr(arg, "temp")   == arg)  flag_bits |= LIBLLDB_LOG_TEMPORARY;
+            else if (strcasestr(arg, "comm")   == arg)  flag_bits |= LIBLLDB_LOG_COMMUNICATION;
+            else if (strcasestr(arg, "conn")   == arg)  flag_bits |= LIBLLDB_LOG_CONNECTION;
+            else
+            {
+                feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
+                if (got_unknown_category == false)
+                {
+                    got_unknown_category = true;
+                    ListLogCategories (feedback_strm);
+                    return log;
+                }
+            }
+        }
+
+        log->GetMask().SetAllFlagBits(flag_bits);
+        log->GetOptions().SetAllFlagBits(log_options);
+    }
+    return log;
+}
+
+
+void
+lldb_private::ListLogCategories (Stream *strm)
+{
+    strm->Printf("Logging categories for 'lldb':\n"
+        "\tall - turn on all available logging categories\n"
+        "\tdefault - enable the default set of logging categories for liblldb\n"
+        "\tbreak - log breakpoints\n"
+        "\tevents - log broadcaster, listener and event queue activities\n"
+        "\texpr - log expressions\n"
+        "\tobject - log object construction/destruction for important objects\n"
+        "\tprocess - log process events and activities\n"
+        "\tthread - log thread events and activities\n"
+        "\tshlib - log shared library related activities\n"
+        "\tstate - log private and public process state changes\n"
+        "\tstep - log step related activities\n"
+        "\tverbose - enable verbose loggging\n"
+        "\twatch - log watchpoint related activities\n");
+}
diff --git a/source/lldb.cpp b/source/lldb.cpp
new file mode 100644
index 0000000..187f9ea
--- /dev/null
+++ b/source/lldb.cpp
@@ -0,0 +1,107 @@
+//===-- lldb.cpp ------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-private.h"
+#include "lldb/lldb-private-log.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Host/Host.h"
+#include "ABIMacOSX_i386.h"
+#include "ABISysV_x86_64.h"
+#include "DisassemblerLLVM.h"
+#include "DynamicLoaderMacOSXDYLD.h"
+#include "ObjectContainerBSDArchive.h"
+#include "ObjectContainerUniversalMachO.h"
+#include "ObjectFileELF.h"
+#include "ObjectFileMachO.h"
+#include "ProcessMacOSX.h"
+#include "ProcessGDBRemote.h"
+#include "SymbolFileDWARF.h"
+#include "SymbolFileDWARFDebugMap.h"
+#include "SymbolFileSymtab.h"
+#include "SymbolVendorMacOSX.h"
+
+using namespace lldb_private;
+
+
+void
+lldb_private::Initialize ()
+{
+    // Make sure we inialize only once
+    static Mutex g_inited_mutex(Mutex::eMutexTypeNormal);
+    static bool g_inited = false;
+
+    Mutex::Locker locker(g_inited_mutex);
+    if (!g_inited)
+    {
+        g_inited = true;
+        Timer::Initialize ();
+        Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+
+        Log::Callbacks log_callbacks = { DisableLog, EnableLog, ListLogCategories };
+
+        Log::RegisterLogChannel ("lldb", log_callbacks);
+        ABIMacOSX_i386::Initialize();
+        ABISysV_x86_64::Initialize();
+        DisassemblerLLVM::Initialize();
+        DynamicLoaderMacOSXDYLD::Initialize();
+        ObjectContainerUniversalMachO::Initialize();
+        ObjectContainerBSDArchive::Initialize();
+        ObjectFileELF::Initialize();
+        ObjectFileMachO::Initialize();
+        ProcessGDBRemote::Initialize();
+        ProcessMacOSX::Initialize();
+        SymbolFileDWARF::Initialize();
+        SymbolFileDWARFDebugMap::Initialize();
+        SymbolFileSymtab::Initialize();
+        SymbolVendorMacOSX::Initialize();
+    }
+}
+
+void
+lldb_private::WillTerminate()
+{
+    Host::WillTerminate();
+}
+
+void
+lldb_private::Terminate ()
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+    DisassemblerLLVM::Terminate();
+    DynamicLoaderMacOSXDYLD::Terminate();
+    ObjectContainerUniversalMachO::Terminate();
+    ObjectContainerBSDArchive::Terminate();
+    ObjectFileELF::Terminate();
+    ObjectFileMachO::Terminate();
+    ProcessGDBRemote::Terminate();
+    ProcessMacOSX::Terminate();
+    SymbolFileDWARF::Terminate();
+    SymbolFileDWARFDebugMap::Terminate();
+    SymbolFileSymtab::Terminate();
+    SymbolVendorMacOSX::Terminate();
+}
+
+const char *
+lldb_private::GetVersion ()
+{
+    extern const double LLDBVersionNumber;
+    static char g_version_string[32];
+    if (g_version_string[0] == '\0')
+        ::snprintf (g_version_string, sizeof(g_version_string), "LLDB-%g", LLDBVersionNumber);
+
+    return g_version_string;
+}
+
+ArchSpec &
+lldb_private::GetDefaultArchitecture ()
+{
+    static ArchSpec g_default_arch;
+    return g_default_arch;
+}