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/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
+