[llvm-branch-commits] [lldb] r183468 - Update platform branch with top of tree.

Greg Clayton gclayton at apple.com
Thu Jun 6 17:08:20 PDT 2013


Modified: lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp Thu Jun  6 19:06:43 2013
@@ -7,6 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "lldb/lldb-python.h"
+
 #include "AppleObjCTrampolineHandler.h"
 
 // C Includes
@@ -18,15 +20,15 @@
 #include "lldb/Breakpoint/StoppointCallbackContext.h"
 #include "lldb/Core/ConstString.h"
 #include "lldb/Core/Debugger.h"
-#include "lldb/Host/FileSpec.h"
 #include "lldb/Core/Log.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/Value.h"
 #include "lldb/Expression/ClangExpression.h"
 #include "lldb/Expression/ClangFunction.h"
 #include "lldb/Expression/ClangUtilityFunction.h"
-
+#include "lldb/Host/FileSpec.h"
 #include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/Symbol.h"
 #include "lldb/Target/ObjCLanguageRuntime.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/RegisterContext.h"
@@ -41,7 +43,8 @@ using namespace lldb;
 using namespace lldb_private;
 
 const char *AppleObjCTrampolineHandler::g_lookup_implementation_function_name = "__lldb_objc_find_implementation_for_selector";
-const char *AppleObjCTrampolineHandler::g_lookup_implementation_function_code = "                               \n\
+const char *AppleObjCTrampolineHandler::g_lookup_implementation_function_code = NULL;
+const char *AppleObjCTrampolineHandler::g_lookup_implementation_with_stret_function_code = "                               \n\
 extern \"C\"                                                                                                    \n\
 {                                                                                                               \n\
     extern void *class_getMethodImplementation(void *objc_class, void *sel);                                    \n\
@@ -150,6 +153,106 @@ extern \"C\" void * __lldb_objc_find_imp
     return return_struct.impl_addr;                                                                             \n\
 }                                                                                                               \n\
 ";
+const char *AppleObjCTrampolineHandler::g_lookup_implementation_no_stret_function_code = "                      \n\
+extern \"C\"                                                                                                    \n\
+{                                                                                                               \n\
+    extern void *class_getMethodImplementation(void *objc_class, void *sel);                                    \n\
+    extern void * sel_getUid(char *name);                                                                       \n\
+    extern int printf(const char *format, ...);                                                                 \n\
+}                                                                                                               \n\
+extern \"C\" void * __lldb_objc_find_implementation_for_selector (void *object,                                 \n\
+                                                    void *sel,                                                  \n\
+                                                    int is_stret,                                               \n\
+                                                    int is_super,                                               \n\
+                                                    int is_super2,                                              \n\
+                                                    int is_fixup,                                               \n\
+                                                    int is_fixed,                                               \n\
+                                                    int debug)                                                  \n\
+{                                                                                                               \n\
+    struct __lldb_imp_return_struct                                                                             \n\
+    {                                                                                                           \n\
+        void *class_addr;                                                                                       \n\
+        void *sel_addr;                                                                                         \n\
+        void *impl_addr;                                                                                        \n\
+    };                                                                                                          \n\
+                                                                                                                \n\
+    struct __lldb_objc_class {                                                                                  \n\
+        void *isa;                                                                                              \n\
+        void *super_ptr;                                                                                        \n\
+    };                                                                                                          \n\
+    struct __lldb_objc_super {                                                                                  \n\
+        void *reciever;                                                                                         \n\
+        struct __lldb_objc_class *class_ptr;                                                                    \n\
+    };                                                                                                          \n\
+    struct __lldb_msg_ref {                                                                                     \n\
+        void *dont_know;                                                                                        \n\
+        void *sel;                                                                                              \n\
+    };                                                                                                          \n\
+                                                                                                                \n\
+    struct __lldb_imp_return_struct return_struct;                                                              \n\
+                                                                                                                \n\
+    if (debug)                                                                                                  \n\
+        printf (\"\\n*** Called with obj: 0x%p sel: 0x%p is_stret: %d is_super: %d, \"                          \n\
+                \"is_super2: %d, is_fixup: %d, is_fixed: %d\\n\",                                               \n\
+                 object, sel, is_stret, is_super, is_super2, is_fixup, is_fixed);                               \n\
+    if (is_super)                                                                                               \n\
+    {                                                                                                           \n\
+        if (is_super2)                                                                                          \n\
+        {                                                                                                       \n\
+            return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr->super_ptr;                    \n\
+        }                                                                                                       \n\
+        else                                                                                                    \n\
+        {                                                                                                       \n\
+            return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr;                               \n\
+        }                                                                                                       \n\
+    }                                                                                                           \n\
+    else                                                                                                        \n\
+    {                                                                                                           \n\
+        void *class_ptr = (void *) [(id) object class];                                                         \n\
+        if (class_ptr == object)                                                                                \n\
+        {                                                                                                       \n\
+            struct __lldb_objc_class *class_as_class_struct = (struct __lldb_objc_class *) class_ptr;           \n\
+            if (debug)                                                                                          \n\
+                printf (\"Found a class object, need to return the meta class 0x%p -> 0x%p\\n\",                \n\
+                        class_ptr, class_as_class_struct->isa);                                                 \n\
+            return_struct.class_addr = class_as_class_struct->isa;                                              \n\
+        }                                                                                                       \n\
+        else                                                                                                    \n\
+        {                                                                                                       \n\
+            if (debug)                                                                                          \n\
+                printf (\"[object class] returned: 0x%p.\\n\", class_ptr);                                      \n\
+            return_struct.class_addr = class_ptr;                                                               \n\
+        }                                                                                                       \n\
+    }                                                                                                           \n\
+                                                                                                                \n\
+    if (is_fixup)                                                                                               \n\
+    {                                                                                                           \n\
+        if (is_fixed)                                                                                           \n\
+        {                                                                                                       \n\
+            return_struct.sel_addr = ((__lldb_msg_ref *) sel)->sel;                                             \n\
+        }                                                                                                       \n\
+        else                                                                                                    \n\
+        {                                                                                                       \n\
+            char *sel_name = (char *) ((__lldb_msg_ref *) sel)->sel;                                            \n\
+            return_struct.sel_addr = sel_getUid (sel_name);                                                     \n\
+            if (debug)                                                                                          \n\
+                printf (\"\\n*** Got fixed up selector: 0x%p for name %s.\\n\",                                 \n\
+                        return_struct.sel_addr, sel_name);                                                      \n\
+        }                                                                                                       \n\
+    }                                                                                                           \n\
+    else                                                                                                        \n\
+    {                                                                                                           \n\
+        return_struct.sel_addr = sel;                                                                           \n\
+    }                                                                                                           \n\
+                                                                                                                \n\
+    return_struct.impl_addr = class_getMethodImplementation (return_struct.class_addr,                          \n\
+                                                             return_struct.sel_addr);                           \n\
+    if (debug)                                                                                                  \n\
+        printf (\"\\n*** Returning implementation: 0x%p.\\n\", return_struct.impl_addr);                        \n\
+                                                                                                                \n\
+    return return_struct.impl_addr;                                                                             \n\
+}                                                                                                               \n\
+";
 
 AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::VTableRegion(AppleObjCVTables *owner, lldb::addr_t header_addr) :
     m_valid (true),
@@ -192,12 +295,12 @@ AppleObjCTrampolineHandler::AppleObjCVTa
         return;
     }
     
-    uint32_t offset_ptr = 0;
-    const uint16_t header_size = data.GetU16(&offset_ptr);
-    const uint16_t descriptor_size = data.GetU16(&offset_ptr);
-    const size_t num_descriptors = data.GetU32(&offset_ptr);
+    lldb::offset_t offset = 0;
+    const uint16_t header_size = data.GetU16(&offset);
+    const uint16_t descriptor_size = data.GetU16(&offset);
+    const size_t num_descriptors = data.GetU32(&offset);
     
-    m_next_region = data.GetPointer(&offset_ptr);
+    m_next_region = data.GetPointer(&offset);
     
     // If the header size is 0, that means we've come in too early before this data is set up.
     // Set ourselves as not valid, and continue.
@@ -237,16 +340,16 @@ AppleObjCTrampolineHandler::AppleObjCVTa
     // The actual code for the vtables will be laid out consecutively, so I also
     // compute the start and end of the whole code block.
 
-    offset_ptr = 0;
+    offset = 0;
     m_code_start_addr = 0;
     m_code_end_addr = 0;
 
     for (int i = 0; i < num_descriptors; i++)
     {
-        lldb::addr_t start_offset = offset_ptr;
-        uint32_t offset = desc_extractor.GetU32 (&offset_ptr);
-        uint32_t flags  = desc_extractor.GetU32 (&offset_ptr);
-        lldb::addr_t code_addr = desc_ptr + start_offset + offset;
+        lldb::addr_t start_offset = offset;
+        uint32_t voffset = desc_extractor.GetU32 (&offset);
+        uint32_t flags  = desc_extractor.GetU32 (&offset);
+        lldb::addr_t code_addr = desc_ptr + start_offset + voffset;
         m_descriptors.push_back (VTableDescriptor(flags, code_addr));
         
         if (m_code_start_addr == 0 || code_addr < m_code_start_addr)
@@ -254,7 +357,7 @@ AppleObjCTrampolineHandler::AppleObjCVTa
         if (code_addr > m_code_end_addr)
             m_code_end_addr = code_addr;
             
-        offset_ptr = start_offset + descriptor_size;
+        offset = start_offset + descriptor_size;
     }
     // Finally, a little bird told me that all the vtable code blocks are the same size.  
     // Let's compute the blocks and if they are all the same add the size to the code end address:
@@ -301,13 +404,13 @@ AppleObjCTrampolineHandler::AppleObjCVTa
 void
 AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::Dump (Stream &s)
 {
-    s.Printf ("Header addr: 0x%llx Code start: 0x%llx Code End: 0x%llx Next: 0x%llx\n", 
+    s.Printf ("Header addr: 0x%" PRIx64 " Code start: 0x%" PRIx64 " Code End: 0x%" PRIx64 " Next: 0x%" PRIx64 "\n",
               m_header_addr, m_code_start_addr, m_code_end_addr, m_next_region);
     size_t num_elements = m_descriptors.size();
     for (size_t i = 0; i < num_elements; i++)
     {
         s.Indent();
-        s.Printf ("Code start: 0x%llx Flags: %d\n", m_descriptors[i].code_start, m_descriptors[i].flags);
+        s.Printf ("Code start: 0x%" PRIx64 " Flags: %d\n", m_descriptors[i].code_start, m_descriptors[i].flags);
     }
 }
         
@@ -334,7 +437,7 @@ AppleObjCTrampolineHandler::AppleObjCVTa
         return true;
     Target &target = m_process_sp->GetTarget();
     
-    ModuleList &target_modules = target.GetImages();
+    const ModuleList &target_modules = target.GetImages();
     Mutex::Locker modules_locker(target_modules.GetMutex());
     size_t num_modules = target_modules.GetSize();
     if (!m_objc_module_sp)
@@ -380,6 +483,7 @@ AppleObjCTrampolineHandler::AppleObjCVTa
                     {
                         m_trampolines_changed_bp_id = trampolines_changed_bp_sp->GetID();
                         trampolines_changed_bp_sp->SetCallback (RefreshTrampolines, this, true);
+                        trampolines_changed_bp_sp->SetBreakpointKind ("objc-trampolines-changed");
                         return true;
                     }
                 }
@@ -425,8 +529,8 @@ AppleObjCTrampolineHandler::AppleObjCVTa
                                                                     data, 
                                                                     0,
                                                                     NULL);
-        uint32_t offset_ptr = 0;
-        lldb::addr_t region_addr = data.GetPointer(&offset_ptr);
+        lldb::offset_t offset = 0;
+        lldb::addr_t region_addr = data.GetPointer(&offset);
         
         if (region_addr != 0)
             vtable_handler->ReadRegions(region_addr);
@@ -456,7 +560,7 @@ AppleObjCTrampolineHandler::AppleObjCVTa
     if (!m_process_sp)
         return false;
         
-    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
     
     // We aren't starting at the trampoline symbol.
     InitializeVTableSymbols ();
@@ -553,8 +657,29 @@ AppleObjCTrampolineHandler::AppleObjCTra
         m_msg_forward_stret_addr = msg_forward_stret->GetAddress().GetOpcodeLoadAddress(target);
     
     // FIXME: Do some kind of logging here.
-    if (m_impl_fn_addr == LLDB_INVALID_ADDRESS || m_impl_stret_fn_addr == LLDB_INVALID_ADDRESS)
+    if (m_impl_fn_addr == LLDB_INVALID_ADDRESS)
+    {
+        // If we can't even find the ordinary get method implementation function, then we aren't going to be able to
+        // step through any method dispatches.  Warn to that effect and get out of here.
+        if (process_sp->CanJIT())
+        {
+            process_sp->GetTarget().GetDebugger().GetErrorStream().Printf("Could not find implementation lookup function \"%s\""
+                                                                          " step in through ObjC method dispatch will not work.\n",
+                                                                          get_impl_name.AsCString());
+        }
         return;
+    }
+    else if (m_impl_stret_fn_addr == LLDB_INVALID_ADDRESS)
+    {
+        // It there is no stret return lookup function, assume that it is the same as the straight lookup:
+        m_impl_stret_fn_addr = m_impl_fn_addr;
+        // Also we will use the version of the lookup code that doesn't rely on the stret version of the function.
+        g_lookup_implementation_function_code = g_lookup_implementation_no_stret_function_code;
+    }
+    else
+    {
+        g_lookup_implementation_function_code = g_lookup_implementation_with_stret_function_code;
+    }
         
     // Look up the addresses for the objc dispatch functions and cache them.  For now I'm inspecting the symbol
     // names dynamically to figure out how to dispatch to them.  If it becomes more complicated than this we can 
@@ -589,7 +714,7 @@ AppleObjCTrampolineHandler::SetupDispatc
     ExecutionContext exe_ctx (thread.shared_from_this());
     Address impl_code_address;
     StreamString errors;
-    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
     lldb::addr_t args_addr = LLDB_INVALID_ADDRESS;
 
     // Scope for mutex locker:
@@ -616,7 +741,7 @@ AppleObjCTrampolineHandler::SetupDispatc
                     impl_code_address = sc.symbol->GetAddress();
                     
                 //lldb::addr_t addr = impl_code_address.GetOpcodeLoadAddress (exe_ctx.GetTargetPtr());
-                //printf ("Getting address for our_utility_function: 0x%llx.\n", addr);
+                //printf ("Getting address for our_utility_function: 0x%" PRIx64 ".\n", addr);
             }
             else
             {
@@ -626,15 +751,26 @@ AppleObjCTrampolineHandler::SetupDispatc
         }
         else if (!m_impl_code.get())
         {
-            m_impl_code.reset (new ClangUtilityFunction (g_lookup_implementation_function_code,
-                                                         g_lookup_implementation_function_name));
-            if (!m_impl_code->Install(errors, exe_ctx))
+            if (g_lookup_implementation_function_code != NULL)
+            {
+                m_impl_code.reset (new ClangUtilityFunction (g_lookup_implementation_function_code,
+                                                             g_lookup_implementation_function_name));
+                if (!m_impl_code->Install(errors, exe_ctx))
+                {
+                    if (log)
+                        log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
+                    m_impl_code.reset();
+                    return args_addr;
+                }
+            }
+            else
             {
                 if (log)
-                    log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
-                m_impl_code.reset();
-                return args_addr;
+                    log->Printf("No method lookup implementation code.");
+                errors.Printf ("No method lookup implementation code found.");
+                return LLDB_INVALID_ADDRESS;
             }
+            
             impl_code_address.Clear();
             impl_code_address.SetOffset(m_impl_code->StartAddress());
         }
@@ -732,7 +868,7 @@ AppleObjCTrampolineHandler::GetStepThrou
     
     if (found_it)
     {
-        LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
 
         // We are decoding a method dispatch.  
         // First job is to pull the arguments out:
@@ -882,7 +1018,7 @@ AppleObjCTrampolineHandler::GetStepThrou
         {
             if (log)
             {
-                log->Printf("Resolving call for class - 0x%llx and selector - 0x%llx",
+                log->Printf("Resolving call for class - 0x%" PRIx64 " and selector - 0x%" PRIx64,
                             isa_addr, sel_addr);
             }
             ObjCLanguageRuntime *objc_runtime = m_process_sp->GetObjCLanguageRuntime ();
@@ -896,7 +1032,7 @@ AppleObjCTrampolineHandler::GetStepThrou
             // Yup, it was in the cache, so we can run to that address directly.
             
             if (log)
-                log->Printf ("Found implementation address in cache: 0x%llx", impl_addr);
+                log->Printf ("Found implementation address in cache: 0x%" PRIx64, impl_addr);
                  
             ret_plan_sp.reset (new ThreadPlanRunToAddress (thread, impl_addr, stop_others));
         }
@@ -973,12 +1109,16 @@ AppleObjCTrampolineHandler::GetStepThrou
                 flag_value.GetScalar() = 0;  // FIXME - Set to 0 when debugging is done.
             dispatch_values.PushValue (flag_value);
             
+            
+            // The step through code might have to fill in the cache, so it is not safe to run only one thread.
+            // So we override the stop_others value passed in to us here:
+            const bool trampoline_stop_others = false;
             ret_plan_sp.reset (new AppleThreadPlanStepThroughObjCTrampoline (thread,
                                                                              this,
                                                                              dispatch_values,
                                                                              isa_addr,
                                                                              sel_addr,
-                                                                             stop_others));
+                                                                             trampoline_stop_others));
             if (log)
             {
                 StreamString s;

Modified: lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h Thu Jun  6 19:06:43 2013
@@ -67,6 +67,8 @@ public:
 private:
     static const char *g_lookup_implementation_function_name;
     static const char *g_lookup_implementation_function_code;
+    static const char *g_lookup_implementation_with_stret_function_code;
+    static const char *g_lookup_implementation_no_stret_function_code;
 
     class AppleObjCVTables
     {
@@ -195,14 +197,14 @@ private:
     MsgsendMap m_msgSend_map;
     lldb::ProcessSP m_process_sp;
     lldb::ModuleSP m_objc_module_sp;
-    std::auto_ptr<ClangFunction> m_impl_function;
-    std::auto_ptr<ClangUtilityFunction> m_impl_code;
+    std::unique_ptr<ClangFunction> m_impl_function;
+    std::unique_ptr<ClangUtilityFunction> m_impl_code;
     Mutex m_impl_function_mutex;
     lldb::addr_t m_impl_fn_addr;
     lldb::addr_t m_impl_stret_fn_addr;
     lldb::addr_t m_msg_forward_addr;
     lldb::addr_t m_msg_forward_stret_addr;
-    std::auto_ptr<AppleObjCVTables> m_vtables_ap;
+    std::unique_ptr<AppleObjCVTables> m_vtables_ap;
     
      
 };

Modified: lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp Thu Jun  6 19:06:43 2013
@@ -84,9 +84,15 @@ AppleThreadPlanStepThroughObjCTrampoline
         }
         m_impl_function = m_trampoline_handler->GetLookupImplementationWrapperFunction();
         ExecutionContext exc_ctx;
+        const bool unwind_on_error = true;
+        const bool ignore_breakpoints = true;
         m_thread.CalculateExecutionContext(exc_ctx);
-        m_func_sp.reset(m_impl_function->GetThreadPlanToCallFunction (exc_ctx, m_args_addr, errors, m_stop_others));
-        m_func_sp->SetPrivate(true);
+        m_func_sp.reset(m_impl_function->GetThreadPlanToCallFunction (exc_ctx,
+                                                                      m_args_addr,
+                                                                      errors,
+                                                                      m_stop_others,
+                                                                      unwind_on_error,
+                                                                      ignore_breakpoints));
         m_func_sp->SetOkayToDiscard(true);
         m_thread.QueueThreadPlan (m_func_sp, false);
     }
@@ -108,8 +114,8 @@ AppleThreadPlanStepThroughObjCTrampoline
         s->Printf("Step through ObjC trampoline");
     else
     {
-        s->Printf ("Stepping to implementation of ObjC method - obj: 0x%llx, isa: 0x%llx, sel: 0x%llx",
-        m_input_values.GetValueAtIndex(0)->GetScalar().ULongLong(), m_isa_addr, m_sel_addr);
+        s->Printf ("Stepping to implementation of ObjC method - obj: 0x%llx, isa: 0x%" PRIx64 ", sel: 0x%" PRIx64,
+                   m_input_values.GetValueAtIndex(0)->GetScalar().ULongLong(), m_isa_addr, m_sel_addr);
     }
 }
                 
@@ -120,7 +126,7 @@ AppleThreadPlanStepThroughObjCTrampoline
 }
 
 bool
-AppleThreadPlanStepThroughObjCTrampoline::PlanExplainsStop ()
+AppleThreadPlanStepThroughObjCTrampoline::DoPlanExplainsStop (Event *event_ptr)
 {
     // If we get asked to explain the stop it will be because something went
     // wrong (like the implementation for selector function crashed...  We're going
@@ -167,7 +173,7 @@ AppleThreadPlanStepThroughObjCTrampoline
         lldb::addr_t target_addr = target_addr_value.GetScalar().ULongLong();
         Address target_so_addr;
         target_so_addr.SetOpcodeLoadAddress(target_addr, exc_ctx.GetTargetPtr());
-        LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
         if (target_addr == 0)
         {
             if (log)
@@ -178,7 +184,7 @@ AppleThreadPlanStepThroughObjCTrampoline
         if (m_trampoline_handler->AddrIsMsgForward(target_addr))
         {
             if (log)
-                log->Printf ("Implementation lookup returned msgForward function: 0x%llx, stopping.", target_addr);
+                log->Printf ("Implementation lookup returned msgForward function: 0x%" PRIx64 ", stopping.", target_addr);
 
             SymbolContext sc = m_thread.GetStackFrameAtIndex(0)->GetSymbolContext(eSymbolContextEverything);
             m_run_to_sp.reset(new ThreadPlanStepOut (m_thread, 
@@ -194,13 +200,13 @@ AppleThreadPlanStepThroughObjCTrampoline
         }
         
         if (log)
-            log->Printf("Running to ObjC method implementation: 0x%llx", target_addr);
+            log->Printf("Running to ObjC method implementation: 0x%" PRIx64, target_addr);
         
         ObjCLanguageRuntime *objc_runtime = GetThread().GetProcess()->GetObjCLanguageRuntime();
         assert (objc_runtime != NULL);
         objc_runtime->AddToMethodCache (m_isa_addr, m_sel_addr, target_addr);
         if (log)
-            log->Printf("Adding {isa-addr=0x%llx, sel-addr=0x%llx} = addr=0x%llx to cache.", m_isa_addr, m_sel_addr, target_addr);
+            log->Printf("Adding {isa-addr=0x%" PRIx64 ", sel-addr=0x%" PRIx64 "} = addr=0x%" PRIx64 " to cache.", m_isa_addr, m_sel_addr, target_addr);
 
         // Extract the target address from the value:
         

Modified: lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h Thu Jun  6 19:06:43 2013
@@ -45,15 +45,17 @@ public:
     virtual bool
     ValidatePlan (Stream *error);
 
-    virtual bool
-    PlanExplainsStop ();
-
-
     virtual lldb::StateType
     GetPlanRunState ();
 
     virtual bool
     ShouldStop (Event *event_ptr);
+    
+    virtual bool
+    StopOthers()
+    {
+        return m_stop_others;
+    }
 
     // The base class MischiefManaged does some cleanup - so you have to call it
     // in your MischiefManaged derived class.
@@ -75,6 +77,8 @@ protected:
 	//------------------------------------------------------------------
 	// Classes that inherit from AppleThreadPlanStepThroughObjCTrampoline can see and modify these
 	//------------------------------------------------------------------
+    virtual bool
+    DoPlanExplainsStop (Event *event_ptr);
 	
 private:
     bool

Modified: lldb/branches/lldb-platform-work/source/Plugins/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Makefile?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Makefile (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Makefile Thu Jun  6 19:06:43 2013
@@ -19,19 +19,20 @@ DIRS := ABI/MacOSX-arm ABI/MacOSX-i386 A
 	UnwindAssembly/InstEmulation UnwindAssembly/x86 \
 	LanguageRuntime/CPlusPlus/ItaniumABI \
 	LanguageRuntime/ObjC/AppleObjCRuntime \
-	DynamicLoader/POSIX-DYLD
+	DynamicLoader/POSIX-DYLD \
+	OperatingSystem/Python
 
 ifeq ($(HOST_OS),Darwin)
 DIRS += Process/MacOSX-Kernel
 DIRS += DynamicLoader/MacOSX-DYLD DynamicLoader/Darwin-Kernel
 DIRS +=	ObjectContainer/Universal-Mach-O ObjectFile/Mach-O
 DIRS += SymbolVendor/MacOSX
-DIRS += OperatingSystem/Darwin-Kernel
 #DIRS += Process/MacOSX-User
 DIRS += Process/mach-core
 endif
 
 ifeq ($(HOST_OS),Linux)
+DIRS += DynamicLoader/MacOSX-DYLD
 DIRS += Process/Linux Process/POSIX
 endif
 

Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp Thu Jun  6 19:06:43 2013
@@ -15,7 +15,6 @@
 #include "lldb/Core/ArchSpec.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegularExpression.h"
 #include "lldb/Core/Timer.h"
 #include "lldb/Host/Mutex.h"
 #include "lldb/Symbol/ObjectFile.h"
@@ -50,8 +49,8 @@ ObjectContainerBSDArchive::Object::Clear
     ar_file_size = 0;
 }
 
-uint32_t
-ObjectContainerBSDArchive::Object::Extract (const DataExtractor& data, uint32_t offset)
+lldb::offset_t
+ObjectContainerBSDArchive::Object::Extract (const DataExtractor& data, lldb::offset_t offset)
 {
     size_t ar_name_len = 0;
     std::string str;
@@ -99,17 +98,19 @@ ObjectContainerBSDArchive::Object::Extra
         ar_file_size = ar_size - ar_name_len;
         return offset;
     }
-    return LLDB_INVALID_INDEX32;
+    return LLDB_INVALID_OFFSET;
 }
 
 ObjectContainerBSDArchive::Archive::Archive
 (
     const lldb_private::ArchSpec &arch,
-    const lldb_private::TimeValue &time
+    const lldb_private::TimeValue &time,
+    lldb_private::DataExtractor &data
 ) :
     m_arch (arch),
     m_time (time),
-    m_objects()
+    m_objects(),
+    m_data (data)
 {
 }
 
@@ -118,10 +119,11 @@ ObjectContainerBSDArchive::Archive::~Arc
 }
 
 size_t
-ObjectContainerBSDArchive::Archive::ParseObjects (DataExtractor &data)
+ObjectContainerBSDArchive::Archive::ParseObjects ()
 {
+    DataExtractor &data = m_data;
     std::string str;
-    uint32_t offset = 0;
+    lldb::offset_t offset = 0;
     str.assign((const char *)data.GetData(&offset, SARMAG), SARMAG);
     if (str == ARMAG)
     {
@@ -129,9 +131,9 @@ ObjectContainerBSDArchive::Archive::Pars
         do
         {
             offset = obj.Extract (data, offset);
-            if (offset == LLDB_INVALID_INDEX32)
+            if (offset == LLDB_INVALID_OFFSET)
                 break;
-            uint32_t obj_idx = m_objects.size();
+            size_t obj_idx = m_objects.size();
             m_objects.push_back(obj);
             // Insert all of the C strings out of order for now...
             m_object_name_to_index_map.Append (obj.ar_name.GetCString(), obj_idx);
@@ -146,11 +148,29 @@ ObjectContainerBSDArchive::Archive::Pars
 }
 
 ObjectContainerBSDArchive::Object *
-ObjectContainerBSDArchive::Archive::FindObject (const ConstString &object_name)
+ObjectContainerBSDArchive::Archive::FindObject (const ConstString &object_name, const TimeValue &object_mod_time)
 {
-    const UniqueCStringMap<uint32_t>::Entry *match = m_object_name_to_index_map.FindFirstValueForName (object_name.GetCString());
+    const ObjectNameToIndexMap::Entry *match = m_object_name_to_index_map.FindFirstValueForName (object_name.GetCString());
     if (match)
-        return &m_objects[match->value];
+    {
+        if (object_mod_time.IsValid())
+        {
+            const uint64_t object_date = object_mod_time.GetAsSecondsSinceJan1_1970();
+            if (m_objects[match->value].ar_date == object_date)
+                return &m_objects[match->value];
+            const ObjectNameToIndexMap::Entry *next_match = m_object_name_to_index_map.FindNextValueForName (match);
+            while (next_match)
+            {
+                if (m_objects[next_match->value].ar_date == object_date)
+                    return &m_objects[next_match->value];
+                next_match = m_object_name_to_index_map.FindNextValueForName (next_match);
+            }
+        }
+        else
+        {
+            return &m_objects[match->value];
+        }
+    }
     return NULL;
 }
 
@@ -166,7 +186,7 @@ ObjectContainerBSDArchive::Archive::Find
     // delete an archive entry...
     while (pos != archive_map.end() && pos->first == file)
     {
-        if (pos->second->GetArchitecture() == arch)
+        if (pos->second->GetArchitecture().IsCompatibleMatch(arch))
         {
             if (pos->second->GetModificationTime() == time)
             {
@@ -201,10 +221,10 @@ ObjectContainerBSDArchive::Archive::Pars
     DataExtractor &data
 )
 {
-    shared_ptr archive_sp(new Archive (arch, time));
+    shared_ptr archive_sp(new Archive (arch, time, data));
     if (archive_sp)
     {
-        if (archive_sp->ParseObjects (data) > 0)
+        if (archive_sp->ParseObjects () > 0)
         {
             Mutex::Locker locker(Archive::GetArchiveCacheMutex ());
             Archive::GetArchiveCache().insert(std::make_pair(file, archive_sp));
@@ -237,7 +257,8 @@ ObjectContainerBSDArchive::Initialize()
 {
     PluginManager::RegisterPlugin (GetPluginNameStatic(),
                                    GetPluginDescriptionStatic(),
-                                   CreateInstance);
+                                   CreateInstance,
+                                   GetModuleSpecifications);
 }
 
 void
@@ -247,10 +268,11 @@ ObjectContainerBSDArchive::Terminate()
 }
 
 
-const char *
+lldb_private::ConstString
 ObjectContainerBSDArchive::GetPluginNameStatic()
 {
-    return "object-container.bsd-archive";
+    static ConstString g_name("bsd-archive");
+    return g_name;
 }
 
 const char *
@@ -265,34 +287,69 @@ ObjectContainerBSDArchive::CreateInstanc
 (
     const lldb::ModuleSP &module_sp,
     DataBufferSP& data_sp,
+    lldb::offset_t data_offset,
     const FileSpec *file,
-    addr_t offset,
-    addr_t length)
+    lldb::offset_t file_offset,
+    lldb::offset_t length)
 {
-    DataExtractor data;
-    data.SetData (data_sp, offset, length);
-    if (file && data_sp && ObjectContainerBSDArchive::MagicBytesMatch(data))
+    ConstString object_name (module_sp->GetObjectName());
+    if (object_name)
     {
-        Timer scoped_timer (__PRETTY_FUNCTION__,
-                            "ObjectContainerBSDArchive::CreateInstance (module = %s/%s, file = %p, file_offset = 0x%z8.8x, file_size = 0x%z8.8x)",
-                            module_sp->GetFileSpec().GetDirectory().AsCString(),
-                            module_sp->GetFileSpec().GetFilename().AsCString(),
-                            file, offset, length);
-
-        Archive::shared_ptr archive_sp (Archive::FindCachedArchive (*file, module_sp->GetArchitecture(), module_sp->GetModificationTime()));
-
-        std::auto_ptr<ObjectContainerBSDArchive> container_ap(new ObjectContainerBSDArchive (module_sp, data_sp, file, offset, length));
-
-        if (container_ap.get())
+        if (data_sp)
+        {
+            // We have data, which means this is the first 512 bytes of the file
+            // Check to see if the magic bytes match and if they do, read the entire
+            // table of contents for the archive and cache it
+            DataExtractor data;
+            data.SetData (data_sp, data_offset, length);
+            if (file && data_sp && ObjectContainerBSDArchive::MagicBytesMatch(data))
+            {
+                Timer scoped_timer (__PRETTY_FUNCTION__,
+                                    "ObjectContainerBSDArchive::CreateInstance (module = %s, file = %p, file_offset = 0x%8.8" PRIx64 ", file_size = 0x%8.8" PRIx64 ")",
+                                    module_sp->GetFileSpec().GetPath().c_str(),
+                                    file, (uint64_t) file_offset, (uint64_t) length);
+
+                // Map the entire .a file to be sure that we don't lose any data if the file
+                // gets updated by a new build while this .a file is being used for debugging
+                DataBufferSP archive_data_sp (file->MemoryMapFileContents(file_offset, length));
+                lldb::offset_t archive_data_offset = 0;
+
+                Archive::shared_ptr archive_sp (Archive::FindCachedArchive (*file, module_sp->GetArchitecture(), module_sp->GetModificationTime()));
+                std::unique_ptr<ObjectContainerBSDArchive> container_ap(new ObjectContainerBSDArchive (module_sp,
+                                                                                                       archive_data_sp,
+                                                                                                       archive_data_offset,
+                                                                                                       file,
+                                                                                                       file_offset,
+                                                                                                       length));
+
+                if (container_ap.get())
+                {
+                    if (archive_sp)
+                    {
+                        // We already have this archive in our cache, use it
+                        container_ap->SetArchive (archive_sp);
+                        return container_ap.release();
+                    }
+                    else if (container_ap->ParseHeader())
+                        return container_ap.release();
+                }
+            }
+        }
+        else
         {
+            // No data, just check for a cached archive
+            Archive::shared_ptr archive_sp (Archive::FindCachedArchive (*file, module_sp->GetArchitecture(), module_sp->GetModificationTime()));
             if (archive_sp)
             {
-                // We already have this archive in our cache, use it
-                container_ap->SetArchive (archive_sp);
-                return container_ap.release();
+                std::unique_ptr<ObjectContainerBSDArchive> container_ap(new ObjectContainerBSDArchive (module_sp, data_sp, data_offset, file, file_offset, length));
+                
+                if (container_ap.get())
+                {
+                    // We already have this archive in our cache, use it
+                    container_ap->SetArchive (archive_sp);
+                    return container_ap.release();
+                }
             }
-            else if (container_ap->ParseHeader())
-                return container_ap.release();
         }
     }
     return NULL;
@@ -317,19 +374,20 @@ ObjectContainerBSDArchive::MagicBytesMat
 ObjectContainerBSDArchive::ObjectContainerBSDArchive
 (
     const lldb::ModuleSP &module_sp,
-    DataBufferSP& dataSP,
+    DataBufferSP& data_sp,
+    lldb::offset_t data_offset,
     const lldb_private::FileSpec *file,
-    lldb::addr_t offset,
-    lldb::addr_t size
+    lldb::offset_t file_offset,
+    lldb::offset_t size
 ) :
-    ObjectContainer (module_sp, file, offset, size, dataSP),
+    ObjectContainer (module_sp, file, file_offset, size, data_sp, data_offset),
     m_archive_sp ()
 {
 }
 void
 ObjectContainerBSDArchive::SetArchive (Archive::shared_ptr &archive_sp)
 {
-    m_archive_sp  = archive_sp;
+    m_archive_sp = archive_sp;
 }
 
 
@@ -353,6 +411,9 @@ ObjectContainerBSDArchive::ParseHeader (
                                                                      module_sp->GetModificationTime(),
                                                                      m_data);
             }
+            // Clear the m_data that contains the entire archive
+            // data and let our m_archive_sp hold onto the data.
+            m_data.Clear();
         }
     }
     return m_archive_sp.get() != NULL;
@@ -392,13 +453,18 @@ ObjectContainerBSDArchive::GetObjectFile
     {
         if (module_sp->GetObjectName() && m_archive_sp)
         {
-            Object *object = m_archive_sp->FindObject (module_sp->GetObjectName());
+            Object *object = m_archive_sp->FindObject (module_sp->GetObjectName(),
+                                                       module_sp->GetObjectModificationTime());
             if (object)
-                return ObjectFile::FindPlugin (module_sp, 
+            {
+                lldb::offset_t data_offset = object->ar_file_offset;
+                return ObjectFile::FindPlugin (module_sp,
                                                file, 
-                                               object->ar_file_offset, 
-                                               object->ar_file_size, 
-                                               m_data.GetSharedDataBuffer());
+                                               m_offset + object->ar_file_offset,
+                                               object->ar_file_size,
+                                               m_archive_sp->GetData().GetSharedDataBuffer(),
+                                               data_offset);
+            }
         }
     }
     return ObjectFileSP();
@@ -408,15 +474,9 @@ ObjectContainerBSDArchive::GetObjectFile
 //------------------------------------------------------------------
 // PluginInterface protocol
 //------------------------------------------------------------------
-const char *
+lldb_private::ConstString
 ObjectContainerBSDArchive::GetPluginName()
 {
-    return "object-container.bsd-archive";
-}
-
-const char *
-ObjectContainerBSDArchive::GetShortPluginName()
-{
     return GetPluginNameStatic();
 }
 
@@ -426,3 +486,14 @@ ObjectContainerBSDArchive::GetPluginVers
     return 1;
 }
 
+
+size_t
+ObjectContainerBSDArchive::GetModuleSpecifications (const lldb_private::FileSpec& file,
+                                                    lldb::DataBufferSP& data_sp,
+                                                    lldb::offset_t data_offset,
+                                                    lldb::offset_t file_offset,
+                                                    lldb::offset_t length,
+                                                    lldb_private::ModuleSpecList &specs)
+{
+    return 0;
+}

Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h Thu Jun  6 19:06:43 2013
@@ -32,7 +32,7 @@ public:
     static void
     Terminate();
 
-    static const char *
+    static lldb_private::ConstString
     GetPluginNameStatic();
 
     static const char *
@@ -40,10 +40,19 @@ public:
 
     static lldb_private::ObjectContainer *
     CreateInstance (const lldb::ModuleSP &module_sp,
-                    lldb::DataBufferSP& dataSP,
+                    lldb::DataBufferSP& data_sp,
+                    lldb::offset_t data_offset,
                     const lldb_private::FileSpec *file,
-                    lldb::addr_t offset,
-                    lldb::addr_t length);
+                    lldb::offset_t offset,
+                    lldb::offset_t length);
+
+    static size_t
+    GetModuleSpecifications (const lldb_private::FileSpec& file,
+                             lldb::DataBufferSP& data_sp,
+                             lldb::offset_t data_offset,
+                             lldb::offset_t file_offset,
+                             lldb::offset_t length,
+                             lldb_private::ModuleSpecList &specs);
 
     static bool
     MagicBytesMatch (const lldb_private::DataExtractor &data);
@@ -52,10 +61,11 @@ public:
     // Member Functions
     //------------------------------------------------------------------
     ObjectContainerBSDArchive (const lldb::ModuleSP &module_sp,
-                               lldb::DataBufferSP& dataSP,
+                               lldb::DataBufferSP& data_sp,
+                               lldb::offset_t data_offset,
                                const lldb_private::FileSpec *file,
-                               lldb::addr_t offset,
-                               lldb::addr_t length);
+                               lldb::offset_t offset,
+                               lldb::offset_t length);
 
     virtual
     ~ObjectContainerBSDArchive();
@@ -79,12 +89,9 @@ public:
     //------------------------------------------------------------------
     // PluginInterface protocol
     //------------------------------------------------------------------
-    virtual const char *
+    virtual lldb_private::ConstString
     GetPluginName();
 
-    virtual const char *
-    GetShortPluginName();
-
     virtual uint32_t
     GetPluginVersion();
 
@@ -97,8 +104,8 @@ protected:
         void
         Clear();
 
-        uint32_t
-        Extract (const lldb_private::DataExtractor& data, uint32_t offset);
+        lldb::offset_t
+        Extract (const lldb_private::DataExtractor& data, lldb::offset_t offset);
 
         lldb_private::ConstString       ar_name;        // name
         uint32_t        ar_date;        // modification time
@@ -106,9 +113,8 @@ protected:
         uint16_t        ar_gid;         // group id
         uint16_t        ar_mode;        // octal file permissions
         uint32_t        ar_size;        // size in bytes
-        uint32_t        ar_file_offset; // file offset in bytes from the beginning of the file of the object data
-        uint32_t        ar_file_size;   // length of the object data
-        lldb::ObjectFileSP object_file_sp;
+        lldb::offset_t  ar_file_offset; // file offset in bytes from the beginning of the file of the object data
+        lldb::offset_t  ar_file_size;   // length of the object data
 
         typedef std::vector<Object>         collection;
         typedef collection::iterator        iterator;
@@ -118,7 +124,7 @@ protected:
     class Archive
     {
     public:
-        typedef STD_SHARED_PTR(Archive) shared_ptr;
+        typedef std::shared_ptr<Archive> shared_ptr;
         typedef std::multimap<lldb_private::FileSpec, shared_ptr> Map;
 
         static Map &
@@ -139,7 +145,8 @@ protected:
                                      lldb_private::DataExtractor &data);
 
         Archive (const lldb_private::ArchSpec &arch,
-                 const lldb_private::TimeValue &mod_time);
+                 const lldb_private::TimeValue &mod_time,
+                 lldb_private::DataExtractor &data);
 
         ~Archive ();
 
@@ -150,10 +157,11 @@ protected:
         }
 
         size_t
-        ParseObjects (lldb_private::DataExtractor &data);
+        ParseObjects ();
 
         Object *
-        FindObject (const lldb_private::ConstString &object_name);
+        FindObject (const lldb_private::ConstString &object_name,
+                    const lldb_private::TimeValue &object_mod_time);
 
         const lldb_private::TimeValue &
         GetModificationTime()
@@ -170,15 +178,22 @@ protected:
         bool
         HasNoExternalReferences() const;
 
-    protected:
+        lldb_private::DataExtractor &
+        GetData ()
+        {
+            return m_data;
+        }
 
+    protected:
+        typedef lldb_private::UniqueCStringMap<uint32_t> ObjectNameToIndexMap;
         //----------------------------------------------------------------------
         // Member Variables
         //----------------------------------------------------------------------
         lldb_private::ArchSpec m_arch;
         lldb_private::TimeValue m_time;
-        Object::collection  m_objects;
-        lldb_private::UniqueCStringMap<uint32_t> m_object_name_to_index_map;
+        Object::collection m_objects;
+        ObjectNameToIndexMap m_object_name_to_index_map;
+        lldb_private::DataExtractor m_data; ///< The data for this object container so we don't lose data if the .a files gets modified
     };
 
     void

Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp Thu Jun  6 19:06:43 2013
@@ -8,10 +8,12 @@
 //===----------------------------------------------------------------------===//
 
 #include "ObjectContainerUniversalMachO.h"
-#include "lldb/Core/Stream.h"
 #include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/DataBuffer.h"
 #include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Stream.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Target/Target.h"
 
@@ -24,7 +26,8 @@ ObjectContainerUniversalMachO::Initializ
 {
     PluginManager::RegisterPlugin (GetPluginNameStatic(),
                                    GetPluginDescriptionStatic(),
-                                   CreateInstance);
+                                   CreateInstance,
+                                   GetModuleSpecifications);
 }
 
 void
@@ -34,10 +37,11 @@ ObjectContainerUniversalMachO::Terminate
 }
 
 
-const char *
+lldb_private::ConstString
 ObjectContainerUniversalMachO::GetPluginNameStatic()
 {
-    return "object-container.mach-o";
+    static ConstString g_name("mach-o");
+    return g_name;
 }
 
 const char *
@@ -52,30 +56,34 @@ ObjectContainerUniversalMachO::CreateIns
 (
     const lldb::ModuleSP &module_sp,
     DataBufferSP& data_sp,
+    lldb::offset_t data_offset,
     const FileSpec *file,
-    addr_t offset,
-    addr_t length
+    lldb::offset_t file_offset,
+    lldb::offset_t length
 )
 {
-    DataExtractor data;
-    data.SetData (data_sp, offset, length);
-    if (ObjectContainerUniversalMachO::MagicBytesMatch(data))
+    // We get data when we aren't trying to look for cached container information,
+    // so only try and look for an architecture slice if we get data
+    if (data_sp)
     {
-        std::auto_ptr<ObjectContainerUniversalMachO> container_ap(new ObjectContainerUniversalMachO (module_sp, data_sp, file, offset, length));
-        if (container_ap->ParseHeader())
+        DataExtractor data;
+        data.SetData (data_sp, data_offset, length);
+        if (ObjectContainerUniversalMachO::MagicBytesMatch(data))
         {
-            return container_ap.release();
+            std::unique_ptr<ObjectContainerUniversalMachO> container_ap(new ObjectContainerUniversalMachO (module_sp, data_sp, data_offset, file, file_offset, length));
+            if (container_ap->ParseHeader())
+            {
+                return container_ap.release();
+            }
         }
     }
     return NULL;
 }
 
-
-
 bool
 ObjectContainerUniversalMachO::MagicBytesMatch (const DataExtractor &data)
 {
-    uint32_t offset = 0;
+    lldb::offset_t offset = 0;
     uint32_t magic = data.GetU32(&offset);
     return magic == UniversalMagic || magic == UniversalMagicSwapped;
 }
@@ -83,12 +91,13 @@ ObjectContainerUniversalMachO::MagicByte
 ObjectContainerUniversalMachO::ObjectContainerUniversalMachO
 (
     const lldb::ModuleSP &module_sp,
-    DataBufferSP& dataSP,
+    DataBufferSP& data_sp,
+    lldb::offset_t data_offset,
     const FileSpec *file,
-    addr_t offset,
-    addr_t length
+    lldb::offset_t file_offset,
+    lldb::offset_t length
 ) :
-    ObjectContainer (module_sp, file, offset, length, dataSP),
+    ObjectContainer (module_sp, file, file_offset, length, data_sp, data_offset),
     m_header(),
     m_fat_archs()
 {
@@ -103,41 +112,53 @@ ObjectContainerUniversalMachO::~ObjectCo
 bool
 ObjectContainerUniversalMachO::ParseHeader ()
 {
+    bool success = ParseHeader (m_data, m_header, m_fat_archs);
+    // We no longer need any data, we parsed all we needed to parse
+    // and cached it in m_header and m_fat_archs
+    m_data.Clear();
+    return success;
+}
+
+bool
+ObjectContainerUniversalMachO::ParseHeader (lldb_private::DataExtractor &data,
+                                            llvm::MachO::fat_header &header,
+                                            std::vector<llvm::MachO::fat_arch> &fat_archs)
+{
+    bool success = false;
     // Store the file offset for this universal file as we could have a universal .o file
     // in a BSD archive, or be contained in another kind of object.
-    uint32_t offset = 0;
     // Universal mach-o files always have their headers in big endian.
-    m_data.SetByteOrder (eByteOrderBig);
-    m_header.magic = m_data.GetU32(&offset);
+    lldb::offset_t offset = 0;
+    data.SetByteOrder (eByteOrderBig);
+    header.magic = data.GetU32(&offset);
+    fat_archs.clear();
 
-    if (m_header.magic == UniversalMagic)
+    if (header.magic == UniversalMagic)
     {
-        m_data.SetAddressByteSize(4);
-
-        m_header.nfat_arch = m_data.GetU32(&offset);
 
+        data.SetAddressByteSize(4);
+        
+        header.nfat_arch = data.GetU32(&offset);
+        
         // Now we should have enough data for all of the fat headers, so lets index
         // them so we know how many architectures that this universal binary contains.
         uint32_t arch_idx = 0;
-        for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx)
+        for (arch_idx = 0; arch_idx < header.nfat_arch; ++arch_idx)
         {
-            if (m_data.ValidOffsetForDataOfSize(offset, sizeof(fat_arch)))
+            if (data.ValidOffsetForDataOfSize(offset, sizeof(fat_arch)))
             {
                 fat_arch arch;
-                if (m_data.GetU32(&offset, &arch, sizeof(fat_arch)/sizeof(uint32_t)))
-                {
-                    m_fat_archs.push_back(arch);
-                }
+                if (data.GetU32(&offset, &arch, sizeof(fat_arch)/sizeof(uint32_t)))
+                    fat_archs.push_back(arch);
             }
         }
-        return true;
+        success = true;
     }
     else
     {
-        memset(&m_header, 0, sizeof(m_header));
+        memset(&header, 0, sizeof(header));
     }
-
-    return false;
+    return success;
 }
 
 void
@@ -203,20 +224,34 @@ ObjectContainerUniversalMachO::GetObject
             arch = module_sp->GetArchitecture();
             
         ArchSpec curr_arch;
+        // First, try to find an exact match for the Arch of the Target.
         for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx)
         {
-            if (GetArchitectureAtIndex (arch_idx, curr_arch))
+            if (GetArchitectureAtIndex (arch_idx, curr_arch) && arch.IsExactMatch(curr_arch))
+                break;
+        }
+
+        // Failing an exact match, try to find a compatible Arch of the Target.
+        if (arch_idx >= m_header.nfat_arch)
+        {
+            for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx)
             {
-                if (arch == curr_arch)
-                {
-                    return ObjectFile::FindPlugin (module_sp, 
-                                                   file, 
-                                                   m_offset + m_fat_archs[arch_idx].offset, 
-                                                   m_fat_archs[arch_idx].size,
-                                                   m_data.GetSharedDataBuffer());
-                }
+                if (GetArchitectureAtIndex (arch_idx, curr_arch) && arch.IsCompatibleMatch(curr_arch))
+                    break;
             }
         }
+
+        if (arch_idx < m_header.nfat_arch)
+        {
+            DataBufferSP data_sp;
+            lldb::offset_t data_offset = 0;
+            return ObjectFile::FindPlugin (module_sp,
+                                           file,
+                                           m_offset + m_fat_archs[arch_idx].offset,
+                                           m_fat_archs[arch_idx].size,
+                                           data_sp,
+                                           data_offset);
+        }
     }
     return ObjectFileSP();
 }
@@ -225,15 +260,9 @@ ObjectContainerUniversalMachO::GetObject
 //------------------------------------------------------------------
 // PluginInterface protocol
 //------------------------------------------------------------------
-const char *
+lldb_private::ConstString
 ObjectContainerUniversalMachO::GetPluginName()
 {
-    return "ObjectContainerUniversalMachO";
-}
-
-const char *
-ObjectContainerUniversalMachO::GetShortPluginName()
-{
     return GetPluginNameStatic();
 }
 
@@ -244,3 +273,33 @@ ObjectContainerUniversalMachO::GetPlugin
 }
 
 
+size_t
+ObjectContainerUniversalMachO::GetModuleSpecifications (const lldb_private::FileSpec& file,
+                                                        lldb::DataBufferSP& data_sp,
+                                                        lldb::offset_t data_offset,
+                                                        lldb::offset_t file_offset,
+                                                        lldb::offset_t length,
+                                                        lldb_private::ModuleSpecList &specs)
+{
+    const size_t initial_count = specs.GetSize();
+    
+    DataExtractor data;
+    data.SetData (data_sp, data_offset, length);
+
+    if (ObjectContainerUniversalMachO::MagicBytesMatch(data))
+    {
+        llvm::MachO::fat_header header;
+        std::vector<llvm::MachO::fat_arch> fat_archs;
+        if (ParseHeader (data, header, fat_archs))
+        {
+            for (const llvm::MachO::fat_arch &fat_arch : fat_archs)
+            {
+                ObjectFile::GetModuleSpecifications (file,
+                                                     fat_arch.offset + file_offset,
+                                                     specs);
+            }
+        }
+    }
+    return specs.GetSize() - initial_count;
+}
+

Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h Thu Jun  6 19:06:43 2013
@@ -28,7 +28,7 @@ public:
     static void
     Terminate();
 
-    static const char *
+    static lldb_private::ConstString
     GetPluginNameStatic();
 
     static const char *
@@ -36,10 +36,19 @@ public:
 
     static lldb_private::ObjectContainer *
     CreateInstance (const lldb::ModuleSP &module_sp,
-                    lldb::DataBufferSP& dataSP,
+                    lldb::DataBufferSP& data_sp,
+                    lldb::offset_t data_offset,
                     const lldb_private::FileSpec *file,
-                    lldb::addr_t offset,
-                    lldb::addr_t length);
+                    lldb::offset_t offset,
+                    lldb::offset_t length);
+
+    static size_t
+    GetModuleSpecifications (const lldb_private::FileSpec& file,
+                             lldb::DataBufferSP& data_sp,
+                             lldb::offset_t data_offset,
+                             lldb::offset_t file_offset,
+                             lldb::offset_t length,
+                             lldb_private::ModuleSpecList &specs);
 
     static bool
     MagicBytesMatch (const lldb_private::DataExtractor &data);
@@ -48,10 +57,11 @@ public:
     // Member Functions
     //------------------------------------------------------------------
     ObjectContainerUniversalMachO (const lldb::ModuleSP &module_sp,
-                                   lldb::DataBufferSP& dataSP,
+                                   lldb::DataBufferSP& data_sp,
+                                   lldb::offset_t data_offset,
                                    const lldb_private::FileSpec *file,
-                                   lldb::addr_t offset,
-                                   lldb::addr_t length);
+                                   lldb::offset_t offset,
+                                   lldb::offset_t length);
 
     virtual
     ~ObjectContainerUniversalMachO();
@@ -74,18 +84,21 @@ public:
     //------------------------------------------------------------------
     // PluginInterface protocol
     //------------------------------------------------------------------
-    virtual const char *
+    virtual lldb_private::ConstString
     GetPluginName();
 
-    virtual const char *
-    GetShortPluginName();
-
     virtual uint32_t
     GetPluginVersion();
 
 protected:
     llvm::MachO::fat_header m_header;
     std::vector<llvm::MachO::fat_arch> m_fat_archs;
+    
+    static bool
+    ParseHeader (lldb_private::DataExtractor &data,
+                 llvm::MachO::fat_header &header,
+                 std::vector<llvm::MachO::fat_arch> &fat_archs);
+
 };
 
 #endif  // liblldb_ObjectContainerUniversalMachO_h_

Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ELFHeader.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ELFHeader.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ELFHeader.cpp Thu Jun  6 19:06:43 2013
@@ -10,6 +10,8 @@
 #include <cstring>
 
 #include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/Stream.h"
 
 #include "ELFHeader.h"
 
@@ -23,20 +25,24 @@ using namespace llvm::ELF;
 // GetMaxU64 and GetMaxS64 wrap the similarly named methods from DataExtractor
 // with error handling code and provide for parsing a sequence of values.
 static bool
-GetMaxU64(const lldb_private::DataExtractor &data, 
-          uint32_t *offset, uint64_t *value, uint32_t byte_size) 
+GetMaxU64(const lldb_private::DataExtractor &data,
+          lldb::offset_t *offset,
+          uint64_t *value,
+          uint32_t byte_size)
 {
-    const uint32_t saved_offset = *offset;
+    const lldb::offset_t saved_offset = *offset;
     *value = data.GetMaxU64(offset, byte_size);
     return *offset != saved_offset;
 }
 
 static bool
 GetMaxU64(const lldb_private::DataExtractor &data, 
-          uint32_t *offset, uint64_t *value, uint32_t byte_size, 
+          lldb::offset_t *offset,
+          uint64_t *value,
+          uint32_t byte_size,
           uint32_t count) 
 {
-    uint32_t saved_offset = *offset;
+    lldb::offset_t saved_offset = *offset;
 
     for (uint32_t i = 0; i < count; ++i, ++value)
     {
@@ -51,19 +57,23 @@ GetMaxU64(const lldb_private::DataExtrac
 
 static bool
 GetMaxS64(const lldb_private::DataExtractor &data, 
-          uint32_t *offset, int64_t *value, uint32_t byte_size) 
+          lldb::offset_t *offset,
+          int64_t *value,
+          uint32_t byte_size)
 {
-    const uint32_t saved_offset = *offset;
+    const lldb::offset_t saved_offset = *offset;
     *value = data.GetMaxS64(offset, byte_size);
     return *offset != saved_offset;
 }
 
 static bool
 GetMaxS64(const lldb_private::DataExtractor &data, 
-          uint32_t *offset, int64_t *value, uint32_t byte_size, 
+          lldb::offset_t *offset,
+          int64_t *value,
+          uint32_t byte_size,
           uint32_t count) 
 {
-    uint32_t saved_offset = *offset;
+    lldb::offset_t saved_offset = *offset;
 
     for (uint32_t i = 0; i < count; ++i, ++value)
     {
@@ -95,7 +105,7 @@ ELFHeader::GetByteOrder() const
 }
 
 bool
-ELFHeader::Parse(lldb_private::DataExtractor &data, uint32_t *offset) 
+ELFHeader::Parse(lldb_private::DataExtractor &data, lldb::offset_t *offset) 
 {
     // Read e_ident.  This provides byte order and address size info.
     if (data.GetU8(offset, &e_ident, EI_NIDENT) == NULL)
@@ -190,7 +200,7 @@ ELFSectionHeader::ELFSectionHeader()
 
 bool
 ELFSectionHeader::Parse(const lldb_private::DataExtractor &data,
-                        uint32_t *offset) 
+                        lldb::offset_t *offset)
 {
     const unsigned byte_size = data.GetAddressByteSize();
 
@@ -225,8 +235,92 @@ ELFSymbol::ELFSymbol()
     memset(this, 0, sizeof(ELFSymbol));
 }
 
+#define ENUM_TO_CSTR(e) case e: return #e
+
+const char *
+ELFSymbol::bindingToCString(unsigned char binding)
+{
+    switch (binding)
+    {
+    ENUM_TO_CSTR(STB_LOCAL);
+    ENUM_TO_CSTR(STB_GLOBAL);
+    ENUM_TO_CSTR(STB_WEAK);
+    ENUM_TO_CSTR(STB_LOOS);
+    ENUM_TO_CSTR(STB_HIOS);
+    ENUM_TO_CSTR(STB_LOPROC);
+    ENUM_TO_CSTR(STB_HIPROC);
+    }
+    return "";
+}
+
+const char *
+ELFSymbol::typeToCString(unsigned char type)
+{
+    switch (type)
+    {
+    ENUM_TO_CSTR(STT_NOTYPE);
+    ENUM_TO_CSTR(STT_OBJECT);
+    ENUM_TO_CSTR(STT_FUNC);
+    ENUM_TO_CSTR(STT_SECTION);
+    ENUM_TO_CSTR(STT_FILE);
+    ENUM_TO_CSTR(STT_COMMON);
+    ENUM_TO_CSTR(STT_TLS);
+    ENUM_TO_CSTR(STT_LOOS);
+    ENUM_TO_CSTR(STT_HIOS);
+    ENUM_TO_CSTR(STT_GNU_IFUNC);
+    ENUM_TO_CSTR(STT_LOPROC);
+    ENUM_TO_CSTR(STT_HIPROC);
+    }
+    return "";
+}
+
+const char *
+ELFSymbol::sectionIndexToCString (elf_half shndx,
+                                  const lldb_private::SectionList *section_list)
+{
+    switch (shndx)
+    {
+    ENUM_TO_CSTR(SHN_UNDEF);
+    ENUM_TO_CSTR(SHN_LOPROC);
+    ENUM_TO_CSTR(SHN_HIPROC);
+    ENUM_TO_CSTR(SHN_LOOS);
+    ENUM_TO_CSTR(SHN_HIOS);
+    ENUM_TO_CSTR(SHN_ABS);
+    ENUM_TO_CSTR(SHN_COMMON);
+    ENUM_TO_CSTR(SHN_XINDEX);
+    default:
+        {
+            const lldb_private::Section *section = section_list->GetSectionAtIndex(shndx).get();
+            if (section)
+                return section->GetName().AsCString("");
+        }
+        break;
+    }
+    return "";
+}
+
+void
+ELFSymbol::Dump (lldb_private::Stream *s,
+                 uint32_t idx,
+                 const lldb_private::DataExtractor *strtab_data,
+                 const lldb_private::SectionList *section_list)
+{
+    s->Printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64 " 0x%8.8x 0x%2.2x (%-10s %-13s) 0x%2.2x 0x%4.4x (%-10s) %s\n",
+              idx,
+              st_value,
+              st_size,
+              st_name,
+              st_info,
+              bindingToCString (getBinding()),
+              typeToCString (getType()),
+              st_other,
+              st_shndx,
+              sectionIndexToCString (st_shndx, section_list),
+              strtab_data ? strtab_data->PeekCStr(st_name) : "");
+}
+
 bool
-ELFSymbol::Parse(const lldb_private::DataExtractor &data, uint32_t *offset) 
+ELFSymbol::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
 {
     const unsigned byte_size = data.GetAddressByteSize();
     const bool parsing_32 = byte_size == 4;
@@ -276,7 +370,7 @@ ELFProgramHeader::ELFProgramHeader()
 
 bool
 ELFProgramHeader::Parse(const lldb_private::DataExtractor &data, 
-                        uint32_t *offset) 
+                        lldb::offset_t *offset)
 {
     const uint32_t byte_size = data.GetAddressByteSize();
     const bool parsing_32 = byte_size == 4;
@@ -320,7 +414,7 @@ ELFDynamic::ELFDynamic()
 }
 
 bool
-ELFDynamic::Parse(const lldb_private::DataExtractor &data, uint32_t *offset)
+ELFDynamic::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
 {
     const unsigned byte_size = data.GetAddressByteSize();
     return GetMaxS64(data, offset, &d_tag, byte_size, 2);
@@ -335,7 +429,7 @@ ELFRel::ELFRel()
 }
 
 bool
-ELFRel::Parse(const lldb_private::DataExtractor &data, uint32_t *offset)
+ELFRel::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
 {
     const unsigned byte_size = data.GetAddressByteSize();
 
@@ -355,7 +449,7 @@ ELFRela::ELFRela()
 }
 
 bool
-ELFRela::Parse(const lldb_private::DataExtractor &data, uint32_t *offset)
+ELFRela::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
 {
     const unsigned byte_size = data.GetAddressByteSize();
 

Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ELFHeader.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ELFHeader.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ELFHeader.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ELFHeader.h Thu Jun  6 19:06:43 2013
@@ -107,7 +107,7 @@ struct ELFHeader
     GetRelocationJumpSlotType() const;
 
     //--------------------------------------------------------------------------
-    /// Parse an ELFSectionHeader entry starting at position \p offset and
+    /// Parse an ELFHeader entry starting at position \p offset and
     /// update the data extractor with the address size and byte order
     /// attributes as defined by the header.
     ///
@@ -120,10 +120,10 @@ struct ELFHeader
     ///    advanced by the number of bytes read.
     ///
     /// @return
-    ///    True if the ELFSectionHeader was successfully read and false
+    ///    True if the ELFHeader was successfully read and false
     ///    otherwise.
     bool
-    Parse(lldb_private::DataExtractor &data, uint32_t *offset);
+    Parse(lldb_private::DataExtractor &data, lldb::offset_t *offset);
 
     //--------------------------------------------------------------------------
     /// Examines at most EI_NIDENT bytes starting from the given pointer and
@@ -181,7 +181,7 @@ struct ELFSectionHeader
     ///    True if the ELFSectionHeader was successfully read and false
     ///    otherwise.
     bool
-    Parse(const lldb_private::DataExtractor &data, uint32_t *offset);
+    Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
 };
 
 //------------------------------------------------------------------------------
@@ -216,7 +216,7 @@ struct ELFProgramHeader
     ///    True if the ELFProgramHeader was successfully read and false
     ///    otherwise.
     bool
-    Parse(const lldb_private::DataExtractor &data, uint32_t *offset);
+    Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
 };
 
 //------------------------------------------------------------------------------
@@ -244,6 +244,16 @@ struct ELFSymbol
         st_info = (binding << 4) + (type & 0x0F);
     }
 
+    static const char *
+    bindingToCString(unsigned char binding);
+
+    static const char *
+    typeToCString(unsigned char type);
+
+    static const char *
+    sectionIndexToCString(elf_half shndx,
+                          const lldb_private::SectionList *section_list);
+
     /// Parse an ELFSymbol entry from the given DataExtractor starting at
     /// position \p offset.  The address size of the DataExtractor determines if
     /// a 32 or 64 bit object is to be parsed.
@@ -259,7 +269,13 @@ struct ELFSymbol
     /// @return
     ///    True if the ELFSymbol was successfully read and false otherwise.
     bool
-    Parse(const lldb_private::DataExtractor &data, uint32_t *offset);
+    Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
+    
+    void
+    Dump (lldb_private::Stream *s,
+          uint32_t idx,
+          const lldb_private::DataExtractor *strtab_data,
+          const lldb_private::SectionList *section_list);
 };
 
 //------------------------------------------------------------------------------
@@ -292,7 +308,7 @@ struct ELFDynamic
     ///    True if the ELFDynamic entry was successfully read and false
     ///    otherwise.
     bool
-    Parse(const lldb_private::DataExtractor &data, uint32_t *offset);
+    Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
 };
 
 //------------------------------------------------------------------------------
@@ -320,7 +336,7 @@ struct ELFRel
     /// @return
     ///    True if the ELFRel entry was successfully read and false otherwise.
     bool
-    Parse(const lldb_private::DataExtractor &data, uint32_t *offset);
+    Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
 
     /// Returns the type when the given entry represents a 32-bit relocation.
     static unsigned
@@ -379,7 +395,7 @@ struct ELFRela
     /// @return
     ///    True if the ELFRela entry was successfully read and false otherwise.
     bool
-    Parse(const lldb_private::DataExtractor &data, uint32_t *offset);
+    Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
 
     /// Returns the type when the given entry represents a 32-bit relocation.
     static unsigned

Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp Thu Jun  6 19:06:43 2013
@@ -17,6 +17,7 @@
 #include "lldb/Core/Error.h"
 #include "lldb/Core/FileSpecList.h"
 #include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/Section.h"
 #include "lldb/Core/Stream.h"
@@ -53,7 +54,7 @@ public:
     ~ELFRelocation();
 
     bool
-    Parse(const lldb_private::DataExtractor &data, uint32_t *offset);
+    Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
 
     static unsigned
     RelocType32(const ELFRelocation &rel);
@@ -94,7 +95,7 @@ ELFRelocation::~ELFRelocation()
 }
 
 bool
-ELFRelocation::Parse(const lldb_private::DataExtractor &data, uint32_t *offset)
+ELFRelocation::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
 {
     if (reloc.is<ELFRel*>())
         return reloc.get<ELFRel*>()->Parse(data, offset);
@@ -149,7 +150,8 @@ ObjectFileELF::Initialize()
     PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                   GetPluginDescriptionStatic(),
                                   CreateInstance,
-                                  CreateMemoryInstance);
+                                  CreateMemoryInstance,
+                                  GetModuleSpecifications);
 }
 
 void
@@ -158,10 +160,11 @@ ObjectFileELF::Terminate()
     PluginManager::UnregisterPlugin(CreateInstance);
 }
 
-const char *
+lldb_private::ConstString
 ObjectFileELF::GetPluginNameStatic()
 {
-    return "object-file.elf";
+    static ConstString g_name("elf");
+    return g_name;
 }
 
 const char *
@@ -173,19 +176,32 @@ ObjectFileELF::GetPluginDescriptionStati
 ObjectFile *
 ObjectFileELF::CreateInstance (const lldb::ModuleSP &module_sp,
                                DataBufferSP &data_sp,
-                               const FileSpec *file, 
-                               addr_t offset,
-                               addr_t length)
+                               lldb::offset_t data_offset,
+                               const lldb_private::FileSpec* file,
+                               lldb::offset_t file_offset,
+                               lldb::offset_t length)
 {
-    if (data_sp && data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT + offset))
+    if (!data_sp)
     {
-        const uint8_t *magic = data_sp->GetBytes() + offset;
+        data_sp = file->MemoryMapFileContents(file_offset, length);
+        data_offset = 0;
+    }
+
+    if (data_sp && data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT + data_offset))
+    {
+        const uint8_t *magic = data_sp->GetBytes() + data_offset;
         if (ELFHeader::MagicBytesMatch(magic))
         {
+            // Update the data to contain the entire file if it doesn't already
+            if (data_sp->GetByteSize() < length) {
+                data_sp = file->MemoryMapFileContents(file_offset, length);
+                data_offset = 0;
+                magic = data_sp->GetBytes();
+            }
             unsigned address_size = ELFHeader::AddressSizeInBytes(magic);
             if (address_size == 4 || address_size == 8)
             {
-                std::auto_ptr<ObjectFileELF> objfile_ap(new ObjectFileELF(module_sp, data_sp, file, offset, length));
+                std::unique_ptr<ObjectFileELF> objfile_ap(new ObjectFileELF(module_sp, data_sp, data_offset, file, file_offset, length));
                 ArchSpec spec;
                 if (objfile_ap->GetArchitecture(spec) &&
                     objfile_ap->SetModulesArchitecture(spec))
@@ -206,19 +222,68 @@ ObjectFileELF::CreateMemoryInstance (con
     return NULL;
 }
 
+bool
+ObjectFileELF::MagicBytesMatch (DataBufferSP& data_sp,
+                                  lldb::addr_t data_offset,
+                                  lldb::addr_t data_length)
+{
+    if (data_sp && data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT + data_offset))
+    {
+        const uint8_t *magic = data_sp->GetBytes() + data_offset;
+        return ELFHeader::MagicBytesMatch(magic);
+    }
+    return false;
+}
+
+size_t
+ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file,
+                                        lldb::DataBufferSP& data_sp,
+                                        lldb::offset_t data_offset,
+                                        lldb::offset_t file_offset,
+                                        lldb::offset_t length,
+                                        lldb_private::ModuleSpecList &specs)
+{
+    const size_t initial_count = specs.GetSize();
+
+    if (ObjectFileELF::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize()))
+    {
+        DataExtractor data;
+        data.SetData(data_sp);
+        elf::ELFHeader header;
+        if (header.Parse(data, &data_offset))
+        {
+            if (data_sp)
+            {
+                ModuleSpec spec;
+                spec.GetFileSpec() = file;
+                spec.GetArchitecture().SetArchitecture(eArchTypeELF,
+                                                       header.e_machine,
+                                                       LLDB_INVALID_CPUTYPE);
+                if (spec.GetArchitecture().IsValid())
+                {
+                    // We could parse the ABI tag information (in .note, .notes, or .note.ABI-tag) to get the
+                    // machine information. However, we'd have to read a good bit of the rest of the file,
+                    // and this info isn't guaranteed to exist or be correct. More details here:
+                    //  http://refspecs.linuxfoundation.org/LSB_1.2.0/gLSB/noteabitag.html
+                    // Instead of passing potentially incorrect information down the pipeline, grab
+                    // the host information and use it.
+                    spec.GetArchitecture().GetTriple().setOSName (Host::GetOSString().GetCString());
+                    spec.GetArchitecture().GetTriple().setVendorName(Host::GetVendorString().GetCString());
+                    specs.Append(spec);
+                }
+            }
+        }
+    }
+
+    return specs.GetSize() - initial_count;
+}
 
 //------------------------------------------------------------------
 // PluginInterface protocol
 //------------------------------------------------------------------
-const char *
+lldb_private::ConstString
 ObjectFileELF::GetPluginName()
 {
-    return "ObjectFileELF";
-}
-
-const char *
-ObjectFileELF::GetShortPluginName()
-{
     return GetPluginNameStatic();
 }
 
@@ -232,16 +297,15 @@ ObjectFileELF::GetPluginVersion()
 //------------------------------------------------------------------
 
 ObjectFileELF::ObjectFileELF (const lldb::ModuleSP &module_sp, 
-                              DataBufferSP& dataSP,
+                              DataBufferSP& data_sp,
+                              lldb::offset_t data_offset,
                               const FileSpec* file, 
-                              addr_t offset,
-                              addr_t length) : 
-    ObjectFile(module_sp, file, offset, length, dataSP),
+                              lldb::offset_t file_offset,
+                              lldb::offset_t length) : 
+    ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset),
     m_header(),
     m_program_headers(),
     m_section_headers(),
-    m_sections_ap(),
-    m_symtab_ap(),
     m_filespec_ap(),
     m_shstr_data()
 {
@@ -270,35 +334,40 @@ ObjectFileELF::GetByteOrder() const
     return eByteOrderInvalid;
 }
 
-size_t
+uint32_t
 ObjectFileELF::GetAddressByteSize() const
 {
     return m_data.GetAddressByteSize();
 }
 
-unsigned
+size_t
 ObjectFileELF::SectionIndex(const SectionHeaderCollIter &I)
 {
-    return std::distance(m_section_headers.begin(), I) + 1;
+    return std::distance(m_section_headers.begin(), I) + 1u;
 }
 
-unsigned
+size_t
 ObjectFileELF::SectionIndex(const SectionHeaderCollConstIter &I) const
 {
-    return std::distance(m_section_headers.begin(), I) + 1;
+    return std::distance(m_section_headers.begin(), I) + 1u;
 }
 
 bool
 ObjectFileELF::ParseHeader()
 {
-    uint32_t offset = GetOffset();
+    lldb::offset_t offset = 0;
     return m_header.Parse(m_data, &offset);
 }
 
 bool
 ObjectFileELF::GetUUID(lldb_private::UUID* uuid)
 {
-    // FIXME: Return MD5 sum here.  See comment in ObjectFile.h.
+    if (m_uuid.IsValid())
+    {
+        *uuid = m_uuid;
+        return true;
+    }
+    // FIXME: Return MD5 sum here. See comment in ObjectFile.h.
     return false;
 }
 
@@ -445,8 +514,8 @@ ObjectFileELF::ParseDependentModules()
         ReadSectionData(dynstr, dynstr_data))
     {
         ELFDynamic symbol;
-        const unsigned section_size = dynsym_data.GetByteSize();
-        unsigned offset = 0;
+        const lldb::offset_t section_size = dynsym_data.GetByteSize();
+        lldb::offset_t offset = 0;
 
         // The only type of entries we are concerned with are tagged DT_NEEDED,
         // yielding the name of a required library.
@@ -492,7 +561,7 @@ ObjectFileELF::ParseProgramHeaders()
         return 0;
 
     uint32_t idx;
-    uint32_t offset;
+    lldb::offset_t offset;
     for (idx = 0, offset = 0; idx < m_header.e_phnum; ++idx)
     {
         if (m_program_headers[idx].Parse(data, &offset) == false)
@@ -530,7 +599,7 @@ ObjectFileELF::ParseSectionHeaders()
         return 0;
 
     uint32_t idx;
-    uint32_t offset;
+    lldb::offset_t offset;
     for (idx = 0, offset = 0; idx < m_header.e_shnum; ++idx)
     {
         if (m_section_headers[idx].Parse(data, &offset) == false)
@@ -599,6 +668,51 @@ ObjectFileELF::GetSectionHeaderByIndex(l
     return NULL;
 }
 
+static bool
+ParseNoteGNUBuildID(DataExtractor& data, lldb_private::UUID& uuid)
+{
+    // Try to parse the note section (ie .note.gnu.build-id|.notes|.note|...) and get the build id.
+    // BuildID documentation: https://fedoraproject.org/wiki/Releases/FeatureBuildId
+    struct
+    {
+        uint32_t name_len;  // Length of note name
+        uint32_t desc_len;  // Length of note descriptor
+        uint32_t type;      // Type of note (1 is ABI_TAG, 3 is BUILD_ID)
+    } notehdr;
+    lldb::offset_t offset = 0;
+    static const uint32_t g_gnu_build_id = 3; // NT_GNU_BUILD_ID from elf.h
+
+    while (true)
+    {
+        if (data.GetU32 (&offset, &notehdr, 3) == NULL)
+            return false;
+
+        notehdr.name_len = llvm::RoundUpToAlignment (notehdr.name_len, 4);
+        notehdr.desc_len = llvm::RoundUpToAlignment (notehdr.desc_len, 4);
+
+        lldb::offset_t offset_next_note = offset + notehdr.name_len + notehdr.desc_len;
+
+        // 16 bytes is UUID|MD5, 20 bytes is SHA1
+        if ((notehdr.type == g_gnu_build_id) && (notehdr.name_len == 4) &&
+            (notehdr.desc_len == 16 || notehdr.desc_len == 20))
+        {
+            char name[4];
+            if (data.GetU8 (&offset, name, 4) == NULL)
+                return false;
+            if (!strcmp(name, "GNU"))
+            {
+                uint8_t uuidbuf[20]; 
+                if (data.GetU8 (&offset, &uuidbuf, notehdr.desc_len) == NULL)
+                    return false;
+                uuid.SetBytes (uuidbuf, notehdr.desc_len);
+                return true;
+            }
+        }
+        offset = offset_next_note;
+    }
+    return false;
+}
+ 
 SectionList *
 ObjectFileELF::GetSectionList()
 {
@@ -665,7 +779,17 @@ ObjectFileELF::GetSectionList()
             else if (name == g_sect_name_dwarf_debug_ranges)    sect_type = eSectionTypeDWARFDebugRanges;
             else if (name == g_sect_name_dwarf_debug_str)       sect_type = eSectionTypeDWARFDebugStr;
             else if (name == g_sect_name_eh_frame)              sect_type = eSectionTypeEHFrame;
-            
+            else if (header.sh_type == SHT_NOTE)
+            {
+                if (!m_uuid.IsValid())
+                {
+                    DataExtractor data;
+                    if (vm_size && (GetData (header.sh_offset, vm_size, data) == vm_size))
+                    {
+                        ParseNoteGNUBuildID (data, m_uuid);
+                    }
+                }
+            }
             
             SectionSP section_sp(new Section(
                 GetModule(),        // Module to which this section belongs.
@@ -698,9 +822,8 @@ ParseSymbols(Symtab *symtab,
              const DataExtractor &strtab_data)
 {
     ELFSymbol symbol;
-    uint32_t offset = 0;
-    const unsigned num_symbols = 
-        symtab_data.GetByteSize() / symtab_shdr->sh_entsize;
+    lldb::offset_t offset = 0;
+    const size_t num_symbols = symtab_data.GetByteSize() / symtab_shdr->sh_entsize;
 
     static ConstString text_section_name(".text");
     static ConstString init_section_name(".init");
@@ -714,11 +837,20 @@ ParseSymbols(Symtab *symtab,
     static ConstString data2_section_name(".data1");
     static ConstString bss_section_name(".bss");
 
+    //StreamFile strm(stdout, false);
     unsigned i;
     for (i = 0; i < num_symbols; ++i)
     {
         if (symbol.Parse(symtab_data, &offset) == false)
             break;
+        
+        const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);
+
+        // No need to add symbols that have no names
+        if (symbol_name == NULL || symbol_name[0] == '\0')
+            continue;
+
+        //symbol.Dump (&strm, i, &strtab_data, section_list);
 
         SectionSP symbol_section_sp;
         SymbolType symbol_type = eSymbolTypeInvalid;
@@ -737,37 +869,47 @@ ParseSymbols(Symtab *symtab,
             break;
         }
 
-        switch (symbol.getType())
+        // If a symbol is undefined do not process it further even if it has a STT type
+        if (symbol_type != eSymbolTypeUndefined)
         {
-        default:
-        case STT_NOTYPE:
-            // The symbol's type is not specified.
-            break;
+            switch (symbol.getType())
+            {
+            default:
+            case STT_NOTYPE:
+                // The symbol's type is not specified.
+                break;
 
-        case STT_OBJECT:
-            // The symbol is associated with a data object, such as a variable,
-            // an array, etc.
-            symbol_type = eSymbolTypeData;
-            break;
+            case STT_OBJECT:
+                // The symbol is associated with a data object, such as a variable,
+                // an array, etc.
+                symbol_type = eSymbolTypeData;
+                break;
 
-        case STT_FUNC:
-            // The symbol is associated with a function or other executable code.
-            symbol_type = eSymbolTypeCode;
-            break;
+            case STT_FUNC:
+                // The symbol is associated with a function or other executable code.
+                symbol_type = eSymbolTypeCode;
+                break;
 
-        case STT_SECTION:
-            // The symbol is associated with a section. Symbol table entries of
-            // this type exist primarily for relocation and normally have
-            // STB_LOCAL binding.
-            break;
+            case STT_SECTION:
+                // The symbol is associated with a section. Symbol table entries of
+                // this type exist primarily for relocation and normally have
+                // STB_LOCAL binding.
+                break;
 
-        case STT_FILE:
-            // Conventionally, the symbol's name gives the name of the source
-            // file associated with the object file. A file symbol has STB_LOCAL
-            // binding, its section index is SHN_ABS, and it precedes the other
-            // STB_LOCAL symbols for the file, if it is present.
-            symbol_type = eSymbolTypeObjectFile;
-            break;
+            case STT_FILE:
+                // Conventionally, the symbol's name gives the name of the source
+                // file associated with the object file. A file symbol has STB_LOCAL
+                // binding, its section index is SHN_ABS, and it precedes the other
+                // STB_LOCAL symbols for the file, if it is present.
+                symbol_type = eSymbolTypeSourceFile;
+                break;
+
+            case STT_GNU_IFUNC:
+                // The symbol is associated with an indirect function. The actual
+                // function will be resolved if it is referenced.
+                symbol_type = eSymbolTypeResolver;
+                break;
+            }
         }
 
         if (symbol_type == eSymbolTypeInvalid)
@@ -797,7 +939,6 @@ ParseSymbols(Symtab *symtab,
         uint64_t symbol_value = symbol.st_value;
         if (symbol_section_sp)
             symbol_value -= symbol_section_sp->GetFileAddress();
-        const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);
         bool is_global = symbol.getBinding() == STB_GLOBAL;
         uint32_t flags = symbol.st_other << 8 | symbol.st_info;
         bool is_mangled = symbol_name ? (symbol_name[0] == '_' && symbol_name[1] == 'Z') : false;
@@ -813,6 +954,7 @@ ParseSymbols(Symtab *symtab,
             symbol_section_sp,  // Section in which this symbol is defined or null.
             symbol_value,       // Offset in section or symbol value.
             symbol.st_size,     // Size in bytes of this symbol.
+            true,               // Size is valid
             flags);             // Symbol flags.
         symtab->AddSymbol(dc_symbol);
     }
@@ -877,8 +1019,8 @@ ObjectFileELF::ParseDynamicSymbols()
     DataExtractor dynsym_data;
     if (ReadSectionData(dynsym, dynsym_data))
     {
-        const unsigned section_size = dynsym_data.GetByteSize();
-        unsigned cursor = 0;
+        const lldb::offset_t section_size = dynsym_data.GetByteSize();
+        lldb::offset_t cursor = 0;
 
         while (cursor < section_size)
         {
@@ -956,15 +1098,15 @@ ParsePLTRelocations(Symtab *symbol_table
 {
     ELFRelocation rel(rel_type);
     ELFSymbol symbol;
-    uint32_t offset = 0;
-    const unsigned plt_entsize = plt_hdr->sh_entsize;
-    const unsigned num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;
+    lldb::offset_t offset = 0;
+    const elf_xword plt_entsize = plt_hdr->sh_entsize;
+    const elf_xword num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;
 
     typedef unsigned (*reloc_info_fn)(const ELFRelocation &rel);
     reloc_info_fn reloc_type;
     reloc_info_fn reloc_symbol;
 
-    if (hdr->Is32Bit() == 4)
+    if (hdr->Is32Bit())
     {
         reloc_type = ELFRelocation::RelocType32;
         reloc_symbol = ELFRelocation::RelocSymbol32;
@@ -985,7 +1127,7 @@ ParsePLTRelocations(Symtab *symbol_table
         if (reloc_type(rel) != slot_type)
             continue;
 
-        unsigned symbol_offset = reloc_symbol(rel) * sym_hdr->sh_entsize;
+        lldb::offset_t symbol_offset = reloc_symbol(rel) * sym_hdr->sh_entsize;
         uint64_t plt_index = (i + 1) * plt_entsize;
 
         if (!symbol.Parse(symtab_data, &symbol_offset))
@@ -1006,6 +1148,7 @@ ParsePLTRelocations(Symtab *symbol_table
             plt_section_sp,  // Section in which this symbol is defined or null.
             plt_index,       // Offset in section or symbol value.
             plt_entsize,     // Size in bytes of this symbol.
+            true,            // Size is valid
             0);              // Symbol flags.
 
         symbol_table->AddSymbol(jump_symbol);
@@ -1186,9 +1329,9 @@ ObjectFileELF::DumpELFHeader(Stream *s,
     DumpELFHeader_e_type(s, header.e_type);
     s->Printf("\ne_machine   = 0x%4.4x\n", header.e_machine);
     s->Printf("e_version   = 0x%8.8x\n", header.e_version);
-    s->Printf("e_entry     = 0x%8.8llx\n", header.e_entry);
-    s->Printf("e_phoff     = 0x%8.8llx\n", header.e_phoff);
-    s->Printf("e_shoff     = 0x%8.8llx\n", header.e_shoff);
+    s->Printf("e_entry     = 0x%8.8" PRIx64 "\n", header.e_entry);
+    s->Printf("e_phoff     = 0x%8.8" PRIx64 "\n", header.e_phoff);
+    s->Printf("e_shoff     = 0x%8.8" PRIx64 "\n", header.e_shoff);
     s->Printf("e_flags     = 0x%8.8x\n", header.e_flags);
     s->Printf("e_ehsize    = 0x%4.4x\n", header.e_ehsize);
     s->Printf("e_phentsize = 0x%4.4x\n", header.e_phentsize);
@@ -1246,11 +1389,11 @@ void
 ObjectFileELF::DumpELFProgramHeader(Stream *s, const ELFProgramHeader &ph)
 {
     DumpELFProgramHeader_p_type(s, ph.p_type);
-    s->Printf(" %8.8llx %8.8llx %8.8llx", ph.p_offset, ph.p_vaddr, ph.p_paddr);
-    s->Printf(" %8.8llx %8.8llx %8.8x (", ph.p_filesz, ph.p_memsz, ph.p_flags);
+    s->Printf(" %8.8" PRIx64 " %8.8" PRIx64 " %8.8" PRIx64, ph.p_offset, ph.p_vaddr, ph.p_paddr);
+    s->Printf(" %8.8" PRIx64 " %8.8" PRIx64 " %8.8x (", ph.p_filesz, ph.p_memsz, ph.p_flags);
 
     DumpELFProgramHeader_p_flags(s, ph.p_flags);
-    s->Printf(") %8.8llx", ph.p_align);
+    s->Printf(") %8.8" PRIx64, ph.p_align);
 }
 
 //----------------------------------------------------------------------
@@ -1262,16 +1405,18 @@ ObjectFileELF::DumpELFProgramHeader(Stre
 void
 ObjectFileELF::DumpELFProgramHeader_p_type(Stream *s, elf_word p_type)
 {
-    const int kStrWidth = 10;
+    const int kStrWidth = 15;
     switch (p_type)
     {
-    CASE_AND_STREAM(s, PT_NULL      , kStrWidth);
-    CASE_AND_STREAM(s, PT_LOAD      , kStrWidth);
-    CASE_AND_STREAM(s, PT_DYNAMIC   , kStrWidth);
-    CASE_AND_STREAM(s, PT_INTERP    , kStrWidth);
-    CASE_AND_STREAM(s, PT_NOTE      , kStrWidth);
-    CASE_AND_STREAM(s, PT_SHLIB     , kStrWidth);
-    CASE_AND_STREAM(s, PT_PHDR      , kStrWidth);
+    CASE_AND_STREAM(s, PT_NULL        , kStrWidth);
+    CASE_AND_STREAM(s, PT_LOAD        , kStrWidth);
+    CASE_AND_STREAM(s, PT_DYNAMIC     , kStrWidth);
+    CASE_AND_STREAM(s, PT_INTERP      , kStrWidth);
+    CASE_AND_STREAM(s, PT_NOTE        , kStrWidth);
+    CASE_AND_STREAM(s, PT_SHLIB       , kStrWidth);
+    CASE_AND_STREAM(s, PT_PHDR        , kStrWidth);
+    CASE_AND_STREAM(s, PT_TLS         , kStrWidth);
+    CASE_AND_STREAM(s, PT_GNU_EH_FRAME, kStrWidth);
     default:
         s->Printf("0x%8.8x%*s", p_type, kStrWidth - 10, "");
         break;
@@ -1305,9 +1450,9 @@ ObjectFileELF::DumpELFProgramHeaders(Str
     if (ParseProgramHeaders())
     {
         s->PutCString("Program Headers\n");
-        s->PutCString("IDX  p_type     p_offset p_vaddr  p_paddr  "
+        s->PutCString("IDX  p_type          p_offset p_vaddr  p_paddr  "
                       "p_filesz p_memsz  p_flags                   p_align\n");
-        s->PutCString("==== ---------- -------- -------- -------- "
+        s->PutCString("==== --------------- -------- -------- -------- "
                       "-------- -------- ------------------------- --------\n");
 
         uint32_t idx = 0;
@@ -1331,11 +1476,11 @@ ObjectFileELF::DumpELFSectionHeader(Stre
 {
     s->Printf("%8.8x ", sh.sh_name);
     DumpELFSectionHeader_sh_type(s, sh.sh_type);
-    s->Printf(" %8.8llx (", sh.sh_flags);
+    s->Printf(" %8.8" PRIx64 " (", sh.sh_flags);
     DumpELFSectionHeader_sh_flags(s, sh.sh_flags);
-    s->Printf(") %8.8llx %8.8llx %8.8llx", sh.sh_addr, sh.sh_offset, sh.sh_size);
+    s->Printf(") %8.8" PRIx64 " %8.8" PRIx64 " %8.8" PRIx64, sh.sh_addr, sh.sh_offset, sh.sh_size);
     s->Printf(" %8.8x %8.8x", sh.sh_link, sh.sh_info);
-    s->Printf(" %8.8llx %8.8llx", sh.sh_addralign, sh.sh_entsize);
+    s->Printf(" %8.8" PRIx64 " %8.8" PRIx64, sh.sh_addralign, sh.sh_entsize);
 }
 
 //----------------------------------------------------------------------
@@ -1378,7 +1523,7 @@ ObjectFileELF::DumpELFSectionHeader_sh_t
 // Dump an token value for the ELF section header member sh_flags
 //----------------------------------------------------------------------
 void
-ObjectFileELF::DumpELFSectionHeader_sh_flags(Stream *s, elf_word sh_flags)
+ObjectFileELF::DumpELFSectionHeader_sh_flags(Stream *s, elf_xword sh_flags)
 {
     *s  << ((sh_flags & SHF_WRITE) ? "WRITE" : "     ")
         << (((sh_flags & SHF_WRITE) && (sh_flags & SHF_ALLOC)) ? '+' : ' ')

Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ObjectFileELF.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ObjectFileELF.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ObjectFileELF.h Thu Jun  6 19:06:43 2013
@@ -16,6 +16,7 @@
 #include "lldb/lldb-private.h"
 #include "lldb/Host/FileSpec.h"
 #include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Core/UUID.h"
 
 #include "ELFHeader.h"
 
@@ -38,7 +39,7 @@ public:
     static void
     Terminate();
 
-    static const char *
+    static lldb_private::ConstString
     GetPluginNameStatic();
 
     static const char *
@@ -46,10 +47,11 @@ public:
 
     static lldb_private::ObjectFile *
     CreateInstance(const lldb::ModuleSP &module_sp,
-                   lldb::DataBufferSP& dataSP,
+                   lldb::DataBufferSP& data_sp,
+                   lldb::offset_t data_offset,
                    const lldb_private::FileSpec* file,
-                   lldb::addr_t offset,
-                   lldb::addr_t length);
+                   lldb::offset_t file_offset,
+                   lldb::offset_t length);
 
     static lldb_private::ObjectFile *
     CreateMemoryInstance (const lldb::ModuleSP &module_sp, 
@@ -57,15 +59,25 @@ public:
                           const lldb::ProcessSP &process_sp, 
                           lldb::addr_t header_addr);
 
+    static size_t
+    GetModuleSpecifications (const lldb_private::FileSpec& file,
+                             lldb::DataBufferSP& data_sp,
+                             lldb::offset_t data_offset,
+                             lldb::offset_t file_offset,
+                             lldb::offset_t length,
+                             lldb_private::ModuleSpecList &specs);
+
+    static bool
+    MagicBytesMatch (lldb::DataBufferSP& data_sp,
+                     lldb::addr_t offset, 
+                     lldb::addr_t length);
+
     //------------------------------------------------------------------
     // PluginInterface protocol
     //------------------------------------------------------------------
-    virtual const char *
+    virtual lldb_private::ConstString
     GetPluginName();
 
-    virtual const char *
-    GetShortPluginName();
-
     virtual uint32_t
     GetPluginVersion();
 
@@ -84,7 +96,7 @@ public:
     virtual bool
     IsExecutable () const;
 
-    virtual size_t
+    virtual uint32_t
     GetAddressByteSize() const;
 
     virtual lldb_private::Symtab *
@@ -119,10 +131,11 @@ public:
 
 private:
     ObjectFileELF(const lldb::ModuleSP &module_sp,
-                  lldb::DataBufferSP& dataSP,
+                  lldb::DataBufferSP& data_sp,
+                  lldb::offset_t data_offset,
                   const lldb_private::FileSpec* file,
-                  lldb::addr_t offset,
-                  lldb::addr_t length);
+                  lldb::offset_t offset,
+                  lldb::offset_t length);
 
     typedef std::vector<elf::ELFProgramHeader>  ProgramHeaderColl;
     typedef ProgramHeaderColl::iterator         ProgramHeaderCollIter;
@@ -142,6 +155,9 @@ private:
     /// ELF file header.
     elf::ELFHeader m_header;
 
+    /// ELF build ID
+    lldb_private::UUID m_uuid;
+
     /// Collection of program headers.
     ProgramHeaderColl m_program_headers;
 
@@ -151,15 +167,9 @@ private:
     /// Collection of symbols from the dynamic table.
     DynamicSymbolColl m_dynamic_symbols;
 
-    /// List of sections present in this ELF object file.
-    mutable std::auto_ptr<lldb_private::SectionList> m_sections_ap;
-
-    /// Table of all non-dynamic symbols present in this object file.
-    mutable std::auto_ptr<lldb_private::Symtab> m_symtab_ap;
-
     /// List of file specifications corresponding to the modules (shared
     /// libraries) on which this object file depends.
-    mutable std::auto_ptr<lldb_private::FileSpecList> m_filespec_ap;
+    mutable std::unique_ptr<lldb_private::FileSpecList> m_filespec_ap;
 
     /// Data extractor holding the string table used to resolve section names.
     lldb_private::DataExtractor m_shstr_data;
@@ -168,11 +178,11 @@ private:
     lldb_private::Address  m_entry_point_address;
 
     /// Returns a 1 based index of the given section header.
-    unsigned
+    size_t
     SectionIndex(const SectionHeaderCollIter &I);
 
     /// Returns a 1 based index of the given section header.
-    unsigned
+    size_t
     SectionIndex(const SectionHeaderCollConstIter &I) const;
 
     /// Parses all section headers present in this object file and populates
@@ -282,7 +292,7 @@ private:
 
     static void
     DumpELFSectionHeader_sh_flags(lldb_private::Stream *s, 
-                                  elf::elf_word sh_flags);
+                                  elf::elf_xword sh_flags);
     //@}
 
     /// ELF dependent module dump routine.

Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp Thu Jun  6 19:06:43 2013
@@ -12,10 +12,14 @@
 
 #include "ObjectFileMachO.h"
 
+#include "lldb/lldb-private-log.h"
 #include "lldb/Core/ArchSpec.h"
 #include "lldb/Core/DataBuffer.h"
+#include "lldb/Core/Debugger.h"
 #include "lldb/Core/FileSpecList.h"
+#include "lldb/Core/Log.h"
 #include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/RangeMap.h"
 #include "lldb/Core/Section.h"
@@ -26,6 +30,7 @@
 #include "lldb/Host/Host.h"
 #include "lldb/Host/FileSpec.h"
 #include "lldb/Symbol/ClangNamespaceDecl.h"
+#include "lldb/Symbol/DWARFCallFrameInfo.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Target/Platform.h"
 #include "lldb/Target/Process.h"
@@ -34,11 +39,20 @@
 #include "Plugins/Process/Utility/RegisterContextDarwin_i386.h"
 #include "Plugins/Process/Utility/RegisterContextDarwin_x86_64.h"
 
+#if defined (__APPLE__) && defined (__arm__)
+// GetLLDBSharedCacheUUID() needs to call dlsym()
+#include <dlfcn.h>
+#endif
+
+#ifndef __APPLE__
+#include "Utility/UuidCompatibility.h"
+#endif
+
 using namespace lldb;
 using namespace lldb_private;
 using namespace llvm::MachO;
 
-class RegisterContextDarwin_x86_64_Mach : public RegisterContextDarwin_x86_64 
+class RegisterContextDarwin_x86_64_Mach : public RegisterContextDarwin_x86_64
 {
 public:
     RegisterContextDarwin_x86_64_Mach (lldb_private::Thread &thread, const DataExtractor &data) :
@@ -56,12 +70,12 @@ public:
     void
     SetRegisterDataFrom_LC_THREAD (const DataExtractor &data)
     {
-        uint32_t offset = 0;
+        lldb::offset_t offset = 0;
         SetError (GPRRegSet, Read, -1);
         SetError (FPURegSet, Read, -1);
         SetError (EXCRegSet, Read, -1);
         bool done = false;
-        
+
         while (!done)
         {
             int flavor = data.GetU32 (&offset);
@@ -78,13 +92,13 @@ public:
                             (&gpr.rax)[i] = data.GetU64(&offset);
                         SetError (GPRRegSet, Read, 0);
                         done = true;
-                        
+
                         break;
                     case FPURegSet:
                         // TODO: fill in FPU regs....
                         //SetError (FPURegSet, Read, -1);
                         done = true;
-                        
+
                         break;
                     case EXCRegSet:
                         exc.trapno = data.GetU32(&offset);
@@ -99,7 +113,7 @@ public:
                         // fancy flavors that encapsulate of the the above
                         // falvors...
                         break;
-                        
+
                     default:
                         done = true;
                         break;
@@ -113,31 +127,31 @@ protected:
     {
         return 0;
     }
-    
+
     virtual int
     DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
     {
         return 0;
     }
-    
+
     virtual int
     DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
     {
         return 0;
     }
-    
+
     virtual int
     DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
     {
         return 0;
     }
-    
+
     virtual int
     DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
     {
         return 0;
     }
-    
+
     virtual int
     DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
     {
@@ -146,7 +160,7 @@ protected:
 };
 
 
-class RegisterContextDarwin_i386_Mach : public RegisterContextDarwin_i386 
+class RegisterContextDarwin_i386_Mach : public RegisterContextDarwin_i386
 {
 public:
     RegisterContextDarwin_i386_Mach (lldb_private::Thread &thread, const DataExtractor &data) :
@@ -154,22 +168,22 @@ public:
     {
         SetRegisterDataFrom_LC_THREAD (data);
     }
-    
+
     virtual void
     InvalidateAllRegisters ()
     {
         // Do nothing... registers are always valid...
     }
-    
+
     void
     SetRegisterDataFrom_LC_THREAD (const DataExtractor &data)
     {
-        uint32_t offset = 0;
+        lldb::offset_t offset = 0;
         SetError (GPRRegSet, Read, -1);
         SetError (FPURegSet, Read, -1);
         SetError (EXCRegSet, Read, -1);
         bool done = false;
-        
+
         while (!done)
         {
             int flavor = data.GetU32 (&offset);
@@ -207,7 +221,7 @@ public:
                         // fancy flavors that encapsulate of the the above
                         // falvors...
                         break;
-                        
+
                     default:
                         done = true;
                         break;
@@ -221,31 +235,31 @@ protected:
     {
         return 0;
     }
-    
+
     virtual int
     DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
     {
         return 0;
     }
-    
+
     virtual int
     DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
     {
         return 0;
     }
-    
+
     virtual int
     DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
     {
         return 0;
     }
-    
+
     virtual int
     DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
     {
         return 0;
     }
-    
+
     virtual int
     DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
     {
@@ -253,87 +267,156 @@ protected:
     }
 };
 
-class RegisterContextDarwin_arm_Mach : public RegisterContextDarwin_arm 
+class RegisterContextDarwin_arm_Mach : public RegisterContextDarwin_arm
 {
 public:
     RegisterContextDarwin_arm_Mach (lldb_private::Thread &thread, const DataExtractor &data) :
-    RegisterContextDarwin_arm (thread, 0)
+        RegisterContextDarwin_arm (thread, 0)
     {
         SetRegisterDataFrom_LC_THREAD (data);
     }
-    
+
     virtual void
     InvalidateAllRegisters ()
     {
         // Do nothing... registers are always valid...
     }
-    
+
     void
     SetRegisterDataFrom_LC_THREAD (const DataExtractor &data)
     {
-        uint32_t offset = 0;
+        lldb::offset_t offset = 0;
         SetError (GPRRegSet, Read, -1);
         SetError (FPURegSet, Read, -1);
         SetError (EXCRegSet, Read, -1);
-        int flavor = data.GetU32 (&offset);
-        uint32_t count = data.GetU32 (&offset);
-        switch (flavor)
-        {
-            case GPRRegSet:
-                for (uint32_t i=0; i<count; ++i)
-                    gpr.r[i] = data.GetU32(&offset);
-                SetError (GPRRegSet, Read, 0);
-                break;
-            case FPURegSet:
-                // TODO: fill in FPU regs....
-                //SetError (FPURegSet, Read, -1);
-                break;
-            case EXCRegSet:
-                exc.exception = data.GetU32(&offset);
-                exc.fsr = data.GetU32(&offset);
-                exc.far = data.GetU32(&offset);
-                SetError (EXCRegSet, Read, 0);
-                break;
+        bool done = false;
+
+        while (!done)
+        {
+            int flavor = data.GetU32 (&offset);
+            uint32_t count = data.GetU32 (&offset);
+            lldb::offset_t next_thread_state = offset + (count * 4);
+            switch (flavor)
+            {
+                case GPRRegSet:
+                    for (uint32_t i=0; i<count; ++i)
+                    {
+                        gpr.r[i] = data.GetU32(&offset);
+                    }
+
+                    // Note that gpr.cpsr is also copied by the above loop; this loop technically extends 
+                    // one element past the end of the gpr.r[] array.
+
+                    SetError (GPRRegSet, Read, 0);
+                    offset = next_thread_state;
+                    break;
+
+                case FPURegSet:
+                    {
+                        uint8_t  *fpu_reg_buf = (uint8_t*) &fpu.floats.s[0];
+                        const int fpu_reg_buf_size = sizeof (fpu.floats);
+                        if (data.ExtractBytes (offset, fpu_reg_buf_size, eByteOrderLittle, fpu_reg_buf) == fpu_reg_buf_size)
+                        {
+                            offset += fpu_reg_buf_size;
+                            fpu.fpscr = data.GetU32(&offset);
+                            SetError (FPURegSet, Read, 0);
+                        }
+                        else
+                        {
+                            done = true;
+                        }
+                    }
+                    offset = next_thread_state;
+                    break;
+
+                case EXCRegSet:
+                    if (count == 3)
+                    {
+                        exc.exception = data.GetU32(&offset);
+                        exc.fsr = data.GetU32(&offset);
+                        exc.far = data.GetU32(&offset);
+                        SetError (EXCRegSet, Read, 0);
+                    }
+                    done = true;
+                    offset = next_thread_state;
+                    break;
+
+                // Unknown register set flavor, stop trying to parse.
+                default:
+                    done = true;
+            }
         }
     }
 protected:
     virtual int
     DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
     {
-        return 0;
+        return -1;
     }
-    
+
     virtual int
     DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
     {
-        return 0;
+        return -1;
     }
-    
+
     virtual int
     DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
     {
-        return 0;
+        return -1;
     }
-    
+
+    virtual int
+    DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg)
+    {
+        return -1;
+    }
+
     virtual int
     DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
     {
         return 0;
     }
-    
+
     virtual int
     DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
     {
         return 0;
     }
-    
+
     virtual int
     DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
     {
         return 0;
     }
+
+    virtual int
+    DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg)
+    {
+        return -1;
+    }
 };
 
+static uint32_t
+MachHeaderSizeFromMagic(uint32_t magic)
+{
+    switch (magic)
+    {
+        case HeaderMagic32:
+        case HeaderMagic32Swapped:
+            return sizeof(struct mach_header);
+            
+        case HeaderMagic64:
+        case HeaderMagic64Swapped:
+            return sizeof(struct mach_header_64);
+            break;
+            
+        default:
+            break;
+    }
+    return 0;
+}
+
 #define MACHO_NLIST_ARM_SYMBOL_IS_THUMB 0x0008
 
 void
@@ -342,7 +425,8 @@ ObjectFileMachO::Initialize()
     PluginManager::RegisterPlugin (GetPluginNameStatic(),
                                    GetPluginDescriptionStatic(),
                                    CreateInstance,
-                                   CreateMemoryInstance);
+                                   CreateMemoryInstance,
+                                   GetModuleSpecifications);
 }
 
 void
@@ -352,10 +436,11 @@ ObjectFileMachO::Terminate()
 }
 
 
-const char *
+lldb_private::ConstString
 ObjectFileMachO::GetPluginNameStatic()
 {
-    return "object-file.mach-o";
+    static ConstString g_name("mach-o");
+    return g_name;
 }
 
 const char *
@@ -364,13 +449,29 @@ ObjectFileMachO::GetPluginDescriptionSta
     return "Mach-o object file reader (32 and 64 bit)";
 }
 
-
 ObjectFile *
-ObjectFileMachO::CreateInstance (const lldb::ModuleSP &module_sp, DataBufferSP& data_sp, const FileSpec* file, addr_t offset, addr_t length)
+ObjectFileMachO::CreateInstance (const lldb::ModuleSP &module_sp,
+                                 DataBufferSP& data_sp,
+                                 lldb::offset_t data_offset,
+                                 const FileSpec* file,
+                                 lldb::offset_t file_offset,
+                                 lldb::offset_t length)
 {
-    if (ObjectFileMachO::MagicBytesMatch(data_sp, offset, length))
+    if (!data_sp)
+    {
+        data_sp = file->MemoryMapFileContents(file_offset, length);
+        data_offset = 0;
+    }
+
+    if (ObjectFileMachO::MagicBytesMatch(data_sp, data_offset, length))
     {
-        std::auto_ptr<ObjectFile> objfile_ap(new ObjectFileMachO (module_sp, data_sp, file, offset, length));
+        // Update the data to contain the entire file if it doesn't already
+        if (data_sp->GetByteSize() < length)
+        {
+            data_sp = file->MemoryMapFileContents(file_offset, length);
+            data_offset = 0;
+        }
+        std::unique_ptr<ObjectFile> objfile_ap(new ObjectFileMachO (module_sp, data_sp, data_offset, file, file_offset, length));
         if (objfile_ap.get() && objfile_ap->ParseHeader())
             return objfile_ap.release();
     }
@@ -378,21 +479,62 @@ ObjectFileMachO::CreateInstance (const l
 }
 
 ObjectFile *
-ObjectFileMachO::CreateMemoryInstance (const lldb::ModuleSP &module_sp, 
-                                       DataBufferSP& data_sp, 
-                                       const ProcessSP &process_sp, 
+ObjectFileMachO::CreateMemoryInstance (const lldb::ModuleSP &module_sp,
+                                       DataBufferSP& data_sp,
+                                       const ProcessSP &process_sp,
                                        lldb::addr_t header_addr)
 {
     if (ObjectFileMachO::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize()))
     {
-        std::auto_ptr<ObjectFile> objfile_ap(new ObjectFileMachO (module_sp, data_sp, process_sp, header_addr));
+        std::unique_ptr<ObjectFile> objfile_ap(new ObjectFileMachO (module_sp, data_sp, process_sp, header_addr));
         if (objfile_ap.get() && objfile_ap->ParseHeader())
             return objfile_ap.release();
     }
-    return NULL;    
+    return NULL;
+}
+
+size_t
+ObjectFileMachO::GetModuleSpecifications (const lldb_private::FileSpec& file,
+                                          lldb::DataBufferSP& data_sp,
+                                          lldb::offset_t data_offset,
+                                          lldb::offset_t file_offset,
+                                          lldb::offset_t length,
+                                          lldb_private::ModuleSpecList &specs)
+{
+    const size_t initial_count = specs.GetSize();
+    
+    if (ObjectFileMachO::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize()))
+    {
+        DataExtractor data;
+        data.SetData(data_sp);
+        llvm::MachO::mach_header header;
+        if (ParseHeader (data, &data_offset, header))
+        {
+            if (header.sizeofcmds >= data_sp->GetByteSize())
+            {
+                data_sp = file.ReadFileContents(file_offset, header.sizeofcmds);
+                data_offset = MachHeaderSizeFromMagic(header.magic) + file_offset;
+            }
+            if (data_sp)
+            {
+                ModuleSpec spec;
+                spec.GetFileSpec() = file;
+                spec.GetArchitecture().SetArchitecture(eArchTypeMachO,
+                                                       header.cputype,
+                                                       header.cpusubtype);
+                if (spec.GetArchitecture().IsValid())
+                {
+                    GetUUID (header, data, data_offset, spec.GetUUID());
+                    specs.Append(spec);
+                }
+            }
+        }
+    }
+    return specs.GetSize() - initial_count;
 }
 
 
+
 const ConstString &
 ObjectFileMachO::GetSegmentNameTEXT()
 {
@@ -428,46 +570,26 @@ ObjectFileMachO::GetSectionNameEHFrame()
     return g_section_name_eh_frame;
 }
 
-
-
-static uint32_t
-MachHeaderSizeFromMagic(uint32_t magic)
-{
-    switch (magic)
-    {
-    case HeaderMagic32:
-    case HeaderMagic32Swapped:
-        return sizeof(struct mach_header);
-
-    case HeaderMagic64:
-    case HeaderMagic64Swapped:
-        return sizeof(struct mach_header_64);
-        break;
-
-    default:
-        break;
-    }
-    return 0;
-}
-
-
 bool
-ObjectFileMachO::MagicBytesMatch (DataBufferSP& data_sp, 
-                                  lldb::addr_t data_offset, 
+ObjectFileMachO::MagicBytesMatch (DataBufferSP& data_sp,
+                                  lldb::addr_t data_offset,
                                   lldb::addr_t data_length)
 {
     DataExtractor data;
     data.SetData (data_sp, data_offset, data_length);
-    uint32_t offset = 0;
+    lldb::offset_t offset = 0;
     uint32_t magic = data.GetU32(&offset);
     return MachHeaderSizeFromMagic(magic) != 0;
 }
 
 
-ObjectFileMachO::ObjectFileMachO(const lldb::ModuleSP &module_sp, DataBufferSP& data_sp, const FileSpec* file, addr_t offset, addr_t length) :
-    ObjectFile(module_sp, file, offset, length, data_sp),
-    m_sections_ap(),
-    m_symtab_ap(),
+ObjectFileMachO::ObjectFileMachO(const lldb::ModuleSP &module_sp,
+                                 DataBufferSP& data_sp,
+                                 lldb::offset_t data_offset,
+                                 const FileSpec* file,
+                                 lldb::offset_t file_offset,
+                                 lldb::offset_t length) :
+    ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset),
     m_mach_segments(),
     m_mach_sections(),
     m_entry_point_address(),
@@ -483,8 +605,6 @@ ObjectFileMachO::ObjectFileMachO (const
                                   const lldb::ProcessSP &process_sp,
                                   lldb::addr_t header_addr) :
     ObjectFile(module_sp, process_sp, header_addr, header_data_sp),
-    m_sections_ap(),
-    m_symtab_ap(),
     m_mach_segments(),
     m_mach_sections(),
     m_entry_point_address(),
@@ -499,6 +619,61 @@ ObjectFileMachO::~ObjectFileMachO()
 {
 }
 
+bool
+ObjectFileMachO::ParseHeader (DataExtractor &data,
+                              lldb::offset_t *data_offset_ptr,
+                              llvm::MachO::mach_header &header)
+{
+    data.SetByteOrder (lldb::endian::InlHostByteOrder());
+    // Leave magic in the original byte order
+    header.magic = data.GetU32(data_offset_ptr);
+    bool can_parse = false;
+    bool is_64_bit = false;
+    switch (header.magic)
+    {
+        case HeaderMagic32:
+            data.SetByteOrder (lldb::endian::InlHostByteOrder());
+            data.SetAddressByteSize(4);
+            can_parse = true;
+            break;
+            
+        case HeaderMagic64:
+            data.SetByteOrder (lldb::endian::InlHostByteOrder());
+            data.SetAddressByteSize(8);
+            can_parse = true;
+            is_64_bit = true;
+            break;
+            
+        case HeaderMagic32Swapped:
+            data.SetByteOrder(lldb::endian::InlHostByteOrder() == eByteOrderBig ? eByteOrderLittle : eByteOrderBig);
+            data.SetAddressByteSize(4);
+            can_parse = true;
+            break;
+            
+        case HeaderMagic64Swapped:
+            data.SetByteOrder(lldb::endian::InlHostByteOrder() == eByteOrderBig ? eByteOrderLittle : eByteOrderBig);
+            data.SetAddressByteSize(8);
+            is_64_bit = true;
+            can_parse = true;
+            break;
+            
+        default:
+            break;
+    }
+    
+    if (can_parse)
+    {
+        data.GetU32(data_offset_ptr, &header.cputype, 6);
+        if (is_64_bit)
+            *data_offset_ptr += 4;
+        return true;
+    }
+    else
+    {
+        memset(&header, 0, sizeof(header));
+    }
+    return false;
+}
 
 bool
 ObjectFileMachO::ParseHeader ()
@@ -508,7 +683,7 @@ ObjectFileMachO::ParseHeader ()
     {
         lldb_private::Mutex::Locker locker(module_sp->GetMutex());
         bool can_parse = false;
-        uint32_t offset = 0;
+        lldb::offset_t offset = 0;
         m_data.SetByteOrder (lldb::endian::InlHostByteOrder());
         // Leave magic in the original byte order
         m_header.magic = m_data.GetU32(&offset);
@@ -547,7 +722,12 @@ ObjectFileMachO::ParseHeader ()
             m_data.GetU32(&offset, &m_header.cputype, 6);
 
             ArchSpec mach_arch(eArchTypeMachO, m_header.cputype, m_header.cpusubtype);
-            
+
+            // Check if the module has a required architecture
+            const ArchSpec &module_arch = module_sp->GetArchitecture();
+            if (module_arch.IsValid() && !module_arch.IsCompatibleMatch(mach_arch))
+                return false;
+
             if (SetModulesArchitecture (mach_arch))
             {
                 const size_t header_and_lc_size = m_header.sizeofcmds + MachHeaderSizeFromMagic(m_header.magic);
@@ -557,12 +737,12 @@ ObjectFileMachO::ParseHeader ()
                     ProcessSP process_sp (m_process_wp.lock());
                     if (process_sp)
                     {
-                        data_sp = ReadMemory (process_sp, m_offset, header_and_lc_size);
+                        data_sp = ReadMemory (process_sp, m_memory_addr, header_and_lc_size);
                     }
                     else
                     {
                         // Read in all only the load command data from the file on disk
-                        data_sp = m_file.ReadFileContents(m_offset, header_and_lc_size);
+                        data_sp = m_file.ReadFileContents(m_file_offset, header_and_lc_size);
                         if (data_sp->GetByteSize() != header_and_lc_size)
                             return false;
                     }
@@ -593,7 +773,7 @@ ObjectFileMachO::IsExecutable() const
     return m_header.filetype == HeaderFileTypeExecutable;
 }
 
-size_t
+uint32_t
 ObjectFileMachO::GetAddressByteSize () const
 {
     return m_data.GetAddressByteSize ();
@@ -662,15 +842,16 @@ ObjectFileMachO::GetAddressClass (lldb::
                     }
                 }
             }
-            
+
             const SymbolType symbol_type = symbol->GetType();
             switch (symbol_type)
             {
             case eSymbolTypeAny:            return eAddressClassUnknown;
             case eSymbolTypeAbsolute:       return eAddressClassUnknown;
-                    
+
             case eSymbolTypeCode:
             case eSymbolTypeTrampoline:
+            case eSymbolTypeResolver:
                 if (m_header.cputype == llvm::MachO::CPUTypeARM)
                 {
                     // For ARM we have a bit in the n_desc field of the symbol
@@ -750,7 +931,7 @@ ObjectFileMachO::ParseSections ()
 {
     lldb::user_id_t segID = 0;
     lldb::user_id_t sectID = 0;
-    uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
+    lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
     uint32_t i;
     const bool is_core = GetType() == eTypeCoreFile;
     //bool dump_sections = false;
@@ -761,10 +942,10 @@ ObjectFileMachO::ParseSections ()
     encryption_info_command encryption_cmd;
     for (i=0; i<m_header.ncmds; ++i)
     {
-        const uint32_t load_cmd_offset = offset;
+        const lldb::offset_t load_cmd_offset = offset;
         if (m_data.GetU32(&offset, &encryption_cmd, 2) == NULL)
             break;
-        
+
         if (encryption_cmd.cmd == LoadCommandEncryptionInfo)
         {
             if (m_data.GetU32(&offset, &encryption_cmd.cryptoff, 3))
@@ -786,7 +967,7 @@ ObjectFileMachO::ParseSections ()
     struct segment_command_64 load_cmd;
     for (i=0; i<m_header.ncmds; ++i)
     {
-        const uint32_t load_cmd_offset = offset;
+        const lldb::offset_t load_cmd_offset = offset;
         if (m_data.GetU32(&offset, &load_cmd, 2) == NULL)
             break;
 
@@ -798,16 +979,54 @@ ObjectFileMachO::ParseSections ()
                 load_cmd.vmsize = m_data.GetAddress(&offset);
                 load_cmd.fileoff = m_data.GetAddress(&offset);
                 load_cmd.filesize = m_data.GetAddress(&offset);
-                if (m_data.GetU32(&offset, &load_cmd.maxprot, 4))
+                if (m_length != 0 && load_cmd.filesize != 0)
                 {
+                    if (load_cmd.fileoff > m_length)
+                    {
+                        // We have a load command that says it extends past the end of hte file.  This is likely
+                        // a corrupt file.  We don't have any way to return an error condition here (this method
+                        // was likely invokved from something like ObjectFile::GetSectionList()) -- all we can do
+                        // is null out the SectionList vector and if a process has been set up, dump a message
+                        // to stdout.  The most common case here is core file debugging with a truncated file.
+                        const char *lc_segment_name = load_cmd.cmd == LoadCommandSegment64 ? "LC_SEGMENT_64" : "LC_SEGMENT";
+                        GetModule()->ReportError("is a corrupt mach-o file: load command %u %s has a fileoff (0x%" PRIx64 ") that extends beyond the end of the file (0x%" PRIx64 ")",
+                                                 i,
+                                                 lc_segment_name,
+                                                 load_cmd.fileoff,
+                                                 m_length);
+                        
+                        load_cmd.fileoff = 0;
+                        load_cmd.filesize = 0;
+                    }
                     
+                    if (load_cmd.fileoff + load_cmd.filesize > m_length)
+                    {
+                        // We have a load command that says it extends past the end of hte file.  This is likely
+                        // a corrupt file.  We don't have any way to return an error condition here (this method
+                        // was likely invokved from something like ObjectFile::GetSectionList()) -- all we can do
+                        // is null out the SectionList vector and if a process has been set up, dump a message
+                        // to stdout.  The most common case here is core file debugging with a truncated file.
+                        const char *lc_segment_name = load_cmd.cmd == LoadCommandSegment64 ? "LC_SEGMENT_64" : "LC_SEGMENT";
+                        GetModule()->ReportError("is a corrupt mach-o file: load command %u %s has a fileoff + filesize (0x%" PRIx64 ") that extends beyond the end of the file (0x%" PRIx64 "), the segment will be truncated",
+                                                 i,
+                                                 lc_segment_name,
+                                                 load_cmd.fileoff + load_cmd.filesize,
+                                                 m_length);
+                        
+                        // Tuncase the length
+                        load_cmd.filesize = m_length - load_cmd.fileoff;
+                    }
+                }
+                if (m_data.GetU32(&offset, &load_cmd.maxprot, 4))
+                {
+
                     const bool segment_is_encrypted = (load_cmd.flags & SegmentCommandFlagBitProtectedVersion1) != 0;
 
                     // Keep a list of mach segments around in case we need to
                     // get at data that isn't stored in the abstracted Sections.
                     m_mach_segments.push_back (load_cmd);
 
-                    ConstString segment_name (load_cmd.segname, std::min<int>(strlen(load_cmd.segname), sizeof(load_cmd.segname)));
+                    ConstString segment_name (load_cmd.segname, std::min<size_t>(strlen(load_cmd.segname), sizeof(load_cmd.segname)));
                     // Use a segment ID of the segment index shifted left by 8 so they
                     // never conflict with any of the sections.
                     SectionSP segment_sp;
@@ -830,7 +1049,7 @@ ObjectFileMachO::ParseSections ()
                     struct section_64 sect64;
                     ::memset (&sect64, 0, sizeof(sect64));
                     // Push a section into our mach sections for the section at
-                    // index zero (NListSectionNoSection) if we don't have any 
+                    // index zero (NListSectionNoSection) if we don't have any
                     // mach sections yet...
                     if (m_mach_sections.empty())
                         m_mach_sections.push_back(sect64);
@@ -1011,11 +1230,11 @@ ObjectFileMachO::ParseSections ()
                             // TODO: categorize sections by other flags for regular sections
                             case SectionTypeRegular:
                                 if (segment_sp->GetName() == g_sect_name_TEXT)
-                                    sect_type = eSectionTypeCode; 
+                                    sect_type = eSectionTypeCode;
                                 else if (segment_sp->GetName() == g_sect_name_DATA)
-                                    sect_type = eSectionTypeData; 
+                                    sect_type = eSectionTypeData;
                                 else
-                                    sect_type = eSectionTypeOther; 
+                                    sect_type = eSectionTypeOther;
                                 break;
                             case SectionTypeZeroFill:                   sect_type = eSectionTypeZeroFill; break;
                             case SectionTypeCStringLiterals:            sect_type = eSectionTypeDataCString;    break; // section with only literal C strings
@@ -1048,7 +1267,7 @@ ObjectFileMachO::ParseSections ()
                                                           sect64.offset == 0 ? 0 : sect64.size,
                                                           sect64.flags));
                         // Set the section to be encrypted to match the segment
-                        
+
                         bool section_is_encrypted = false;
                         if (!segment_is_encrypted && load_cmd.filesize != 0)
                             section_is_encrypted = encrypted_file_ranges.FindEntryThatContains(sect64.offset) != NULL;
@@ -1190,14 +1409,14 @@ ObjectFileMachO::ParseSymtab (bool minim
     struct linkedit_data_command function_starts_load_command = { 0, 0, 0, 0 };
     typedef AddressDataArray<lldb::addr_t, bool, 100> FunctionStarts;
     FunctionStarts function_starts;
-    uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
+    lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
     uint32_t i;
 
-    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS));
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS));
 
     for (i=0; i<m_header.ncmds; ++i)
     {
-        const uint32_t cmd_offset = offset;
+        const lldb::offset_t cmd_offset = offset;
         // Read in the load command and load command size
         struct load_command lc;
         if (m_data.GetU32(&offset, &lc, 2) == NULL)
@@ -1214,28 +1433,28 @@ ObjectFileMachO::ParseSymtab (bool minim
             if (symtab_load_command.symoff == 0)
             {
                 if (log)
-                    module_sp->LogMessage(log.get(), "LC_SYMTAB.symoff == 0");
+                    module_sp->LogMessage(log, "LC_SYMTAB.symoff == 0");
                 return 0;
             }
 
             if (symtab_load_command.stroff == 0)
             {
                 if (log)
-                    module_sp->LogMessage(log.get(), "LC_SYMTAB.stroff == 0");
+                    module_sp->LogMessage(log, "LC_SYMTAB.stroff == 0");
                 return 0;
             }
-            
+
             if (symtab_load_command.nsyms == 0)
             {
                 if (log)
-                    module_sp->LogMessage(log.get(), "LC_SYMTAB.nsyms == 0");
+                    module_sp->LogMessage(log, "LC_SYMTAB.nsyms == 0");
                 return 0;
             }
-            
+
             if (symtab_load_command.strsize == 0)
             {
                 if (log)
-                    module_sp->LogMessage(log.get(), "LC_SYMTAB.strsize == 0");
+                    module_sp->LogMessage(log, "LC_SYMTAB.strsize == 0");
                 return 0;
             }
             break;
@@ -1263,14 +1482,16 @@ ObjectFileMachO::ParseSymtab (bool minim
         ProcessSP process_sp (m_process_wp.lock());
         Process *process = process_sp.get();
 
-        const size_t addr_byte_size = m_data.GetAddressByteSize();
+        const uint32_t addr_byte_size = m_data.GetAddressByteSize();
+        const ByteOrder byte_order = m_data.GetByteOrder();
         bool bit_width_32 = addr_byte_size == 4;
         const size_t nlist_byte_size = bit_width_32 ? sizeof(struct nlist) : sizeof(struct nlist_64);
 
-        DataExtractor nlist_data (NULL, 0, m_data.GetByteOrder(), m_data.GetAddressByteSize());
-        DataExtractor strtab_data (NULL, 0, m_data.GetByteOrder(), m_data.GetAddressByteSize());
-        DataExtractor function_starts_data (NULL, 0, m_data.GetByteOrder(), m_data.GetAddressByteSize());
-        
+        DataExtractor nlist_data (NULL, 0, byte_order, addr_byte_size);
+        DataExtractor strtab_data (NULL, 0, byte_order, addr_byte_size);
+        DataExtractor function_starts_data (NULL, 0, byte_order, addr_byte_size);
+        DataExtractor indirect_symbol_index_data (NULL, 0, byte_order, addr_byte_size);
+
         const addr_t nlist_data_byte_size = symtab_load_command.nsyms * nlist_byte_size;
         const addr_t strtab_data_byte_size = symtab_load_command.strsize;
         addr_t strtab_addr = LLDB_INVALID_ADDRESS;
@@ -1306,8 +1527,21 @@ ObjectFileMachO::ParseSymtab (bool minim
                     // symbol and string table. Reading all of this symbol and string table
                     // data across can slow down debug launch times, so we optimize this by
                     // reading the memory for the __LINKEDIT section from this process.
+
+                    UUID lldb_shared_cache(GetLLDBSharedCacheUUID());
+                    UUID process_shared_cache(GetProcessSharedCacheUUID(process));
+                    bool use_lldb_cache = true;
+                    if (lldb_shared_cache.IsValid() && process_shared_cache.IsValid() && lldb_shared_cache != process_shared_cache)
+                    {
+                            use_lldb_cache = false;
+                            ModuleSP module_sp (GetModule());
+                            if (module_sp)
+                                module_sp->ReportWarning ("shared cache in process does not match lldb's own shared cache, startup will be slow.");
+
+                    }
+
                     PlatformSP platform_sp (target.GetPlatform());
-                    if (platform_sp && platform_sp->IsHost())
+                    if (platform_sp && platform_sp->IsHost() && use_lldb_cache)
                     {
                         data_was_read = true;
                         nlist_data.SetData((void *)symoff_addr, nlist_data_byte_size, eByteOrderLittle);
@@ -1329,6 +1563,13 @@ ObjectFileMachO::ParseSymtab (bool minim
                     //DataBufferSP strtab_data_sp (ReadMemory (process_sp, strtab_addr, strtab_data_byte_size));
                     //if (strtab_data_sp)
                     //    strtab_data.SetData (strtab_data_sp, 0, strtab_data_sp->GetByteSize());
+                    if (m_dysymtab.nindirectsyms != 0)
+                    {
+                        const addr_t indirect_syms_addr = linkedit_load_addr + m_dysymtab.indirectsymoff - linkedit_file_offset;
+                        DataBufferSP indirect_syms_data_sp (ReadMemory (process_sp, indirect_syms_addr, m_dysymtab.nindirectsyms * 4));
+                        if (indirect_syms_data_sp)
+                            indirect_symbol_index_data.SetData (indirect_syms_data_sp, 0, indirect_syms_data_sp->GetByteSize());
+                    }
                     if (function_starts_load_command.cmd)
                     {
                         const addr_t func_start_addr = linkedit_load_addr + function_starts_load_command.dataoff - linkedit_file_offset;
@@ -1341,12 +1582,18 @@ ObjectFileMachO::ParseSymtab (bool minim
         }
         else
         {
-            nlist_data.SetData (m_data, 
-                                symtab_load_command.symoff, 
+            nlist_data.SetData (m_data,
+                                symtab_load_command.symoff,
                                 nlist_data_byte_size);
             strtab_data.SetData (m_data,
-                                 symtab_load_command.stroff, 
+                                 symtab_load_command.stroff,
                                  strtab_data_byte_size);
+            if (m_dysymtab.nindirectsyms != 0)
+            {
+                indirect_symbol_index_data.SetData (m_data,
+                                                    m_dysymtab.indirectsymoff,
+                                                    m_dysymtab.nindirectsyms * 4);
+            }
             if (function_starts_load_command.cmd)
             {
                 function_starts_data.SetData (m_data,
@@ -1358,7 +1605,7 @@ ObjectFileMachO::ParseSymtab (bool minim
         if (nlist_data.GetByteSize() == 0)
         {
             if (log)
-                module_sp->LogMessage(log.get(), "failed to read nlist data");
+                module_sp->LogMessage(log, "failed to read nlist data");
             return 0;
         }
 
@@ -1371,14 +1618,14 @@ ObjectFileMachO::ParseSymtab (bool minim
                 if (strtab_addr == LLDB_INVALID_ADDRESS)
                 {
                     if (log)
-                        module_sp->LogMessage(log.get(), "failed to locate the strtab in memory");
+                        module_sp->LogMessage(log, "failed to locate the strtab in memory");
                     return 0;
                 }
             }
             else
             {
                 if (log)
-                    module_sp->LogMessage(log.get(), "failed to read strtab data");
+                    module_sp->LogMessage(log, "failed to read strtab data");
                 return 0;
             }
         }
@@ -1397,11 +1644,22 @@ ObjectFileMachO::ParseSymtab (bool minim
             eh_frame_section_sp = section_list->FindSectionByName (g_section_name_eh_frame);
 
         const bool is_arm = (m_header.cputype == llvm::MachO::CPUTypeARM);
+
+        // lldb works best if it knows the start addresss of all functions in a module.
+        // Linker symbols or debug info are normally the best source of information for start addr / size but
+        // they may be stripped in a released binary.
+        // Two additional sources of information exist in Mach-O binaries:
+        //    LC_FUNCTION_STARTS - a list of ULEB128 encoded offsets of each function's start address in the
+        //                         binary, relative to the text section.
+        //    eh_frame           - the eh_frame FDEs have the start addr & size of each function
+        //  LC_FUNCTION_STARTS is the fastest source to read in, and is present on all modern binaries.
+        //  Binaries built to run on older releases may need to use eh_frame information.
+
         if (text_section_sp && function_starts_data.GetByteSize())
         {
             FunctionStarts::Entry function_start_entry;
             function_start_entry.data = false;
-            uint32_t function_start_offset = 0;
+            lldb::offset_t function_start_offset = 0;
             function_start_entry.addr = text_section_sp->GetFileAddress();
             uint64_t delta;
             while ((delta = function_starts_data.GetULEB128(&function_start_offset)) > 0)
@@ -1411,12 +1669,37 @@ ObjectFileMachO::ParseSymtab (bool minim
                 function_starts.Append(function_start_entry);
             }
         }
-        
-        const uint32_t function_starts_count = function_starts.GetSize();
+        else
+        {
+            // If m_type is eTypeDebugInfo, then this is a dSYM - it will have the load command claiming an eh_frame
+            // but it doesn't actually have the eh_frame content.  And if we have a dSYM, we don't need to do any
+            // of this fill-in-the-missing-symbols works anyway - the debug info should give us all the functions in
+            // the module.
+            if (text_section_sp.get() && eh_frame_section_sp.get() && m_type != eTypeDebugInfo)
+            {
+                DWARFCallFrameInfo eh_frame(*this, eh_frame_section_sp, eRegisterKindGCC, true);
+                DWARFCallFrameInfo::FunctionAddressAndSizeVector functions;
+                eh_frame.GetFunctionAddressAndSizeVector (functions);
+                addr_t text_base_addr = text_section_sp->GetFileAddress();
+                size_t count = functions.GetSize();
+                for (size_t i = 0; i < count; ++i)
+                {
+                    const DWARFCallFrameInfo::FunctionAddressAndSizeVector::Entry *func = functions.GetEntryAtIndex (i);
+                    if (func)
+                    {
+                        FunctionStarts::Entry function_start_entry;
+                        function_start_entry.addr = func->base - text_base_addr;
+                        function_starts.Append(function_start_entry);
+                    }
+                }
+            }
+        }
 
-        uint8_t TEXT_eh_frame_sectID = eh_frame_section_sp.get() ? eh_frame_section_sp->GetID() : NListSectionNoSection;
+        const size_t function_starts_count = function_starts.GetSize();
 
-        uint32_t nlist_data_offset = 0;
+        const user_id_t TEXT_eh_frame_sectID = eh_frame_section_sp.get() ? eh_frame_section_sp->GetID() : NListSectionNoSection;
+
+        lldb::offset_t nlist_data_offset = 0;
 
         uint32_t N_SO_index = UINT32_MAX;
 
@@ -1428,8 +1711,10 @@ ObjectFileMachO::ParseSymtab (bool minim
         std::vector<uint32_t> N_COMM_indexes;
         typedef std::map <uint64_t, uint32_t> ValueToSymbolIndexMap;
         typedef std::map <uint32_t, uint32_t> NListIndexToSymbolIndexMap;
+        typedef std::map <const char *, uint32_t> ConstNameToSymbolIndexMap;
         ValueToSymbolIndexMap N_FUN_addr_to_sym_idx;
         ValueToSymbolIndexMap N_STSYM_addr_to_sym_idx;
+        ConstNameToSymbolIndexMap N_GSYM_name_to_sym_idx;
         // Any symbols that get merged into another will get an entry
         // in this map so we know
         NListIndexToSymbolIndexMap m_nlist_idx_to_sym_idx;
@@ -1438,7 +1723,7 @@ ObjectFileMachO::ParseSymtab (bool minim
 
         uint32_t sym_idx = 0;
         Symbol *sym = NULL;
-        uint32_t num_syms = 0;
+        size_t num_syms = 0;
         std::string memory_symbol_name;
         uint32_t unmapped_local_symbols_found = 0;
 
@@ -1456,59 +1741,75 @@ ObjectFileMachO::ParseSymtab (bool minim
             // Before we can start mapping the DSC, we need to make certain the target process is actually
             // using the cache we can find.
 
-            /*
-             * TODO (FIXME!)
-             *
-             * Consider the case of testing with a separate DSC file.
-             * If we go through the normal code paths, we will give symbols for the wrong DSC, and
-             * that is bad.  We need to read the target process' all_image_infos struct, and look
-             * at the values of the processDetachedFromSharedRegion field. If that is set, we should skip
-             * this code section.
-             */
-
             // Next we need to determine the correct path for the dyld shared cache.
 
             ArchSpec header_arch(eArchTypeMachO, m_header.cputype, m_header.cpusubtype);
             char dsc_path[PATH_MAX];
 
             snprintf(dsc_path, sizeof(dsc_path), "%s%s%s",
-                     "/System/Library/Caches/com.apple.dyld/",	/* IPHONE_DYLD_SHARED_CACHE_DIR */
-                     "dyld_shared_cache_",			/* DYLD_SHARED_CACHE_BASE_NAME */
+                     "/System/Library/Caches/com.apple.dyld/",  /* IPHONE_DYLD_SHARED_CACHE_DIR */
+                     "dyld_shared_cache_",          /* DYLD_SHARED_CACHE_BASE_NAME */
                      header_arch.GetArchitectureName());
 
             FileSpec dsc_filespec(dsc_path, false);
 
             // We need definitions of two structures in the on-disk DSC, copy them here manually
-struct lldb_copy_dyld_cache_header
-{
-	char		magic[16];
-	uint32_t	mappingOffset;
-	uint32_t	mappingCount;
-	uint32_t	imagesOffset;
-	uint32_t	imagesCount;
-	uint64_t	dyldBaseAddress;
-	uint64_t	codeSignatureOffset;
-	uint64_t	codeSignatureSize;
-	uint64_t	slideInfoOffset;
-	uint64_t	slideInfoSize;
-	uint64_t	localSymbolsOffset;
-	uint64_t	localSymbolsSize;
-};
-struct lldb_copy_dyld_cache_local_symbols_info
-{
-        uint32_t        nlistOffset;
-        uint32_t        nlistCount;
-        uint32_t        stringsOffset;
-        uint32_t        stringsSize;
-        uint32_t        entriesOffset;
-        uint32_t        entriesCount;
-};
-struct lldb_copy_dyld_cache_local_symbols_entry
-{
-        uint32_t        dylibOffset;
-        uint32_t        nlistStartIndex;
-        uint32_t        nlistCount;
-};
+            struct lldb_copy_dyld_cache_header_v0
+            {
+                char        magic[16];            // e.g. "dyld_v0    i386", "dyld_v1   armv7", etc.
+                uint32_t    mappingOffset;        // file offset to first dyld_cache_mapping_info
+                uint32_t    mappingCount;         // number of dyld_cache_mapping_info entries
+                uint32_t    imagesOffset;
+                uint32_t    imagesCount;
+                uint64_t    dyldBaseAddress;
+                uint64_t    codeSignatureOffset;
+                uint64_t    codeSignatureSize;
+                uint64_t    slideInfoOffset;
+                uint64_t    slideInfoSize;
+                uint64_t    localSymbolsOffset;   // file offset of where local symbols are stored
+                uint64_t    localSymbolsSize;     // size of local symbols information
+            };
+            struct lldb_copy_dyld_cache_header_v1
+            {
+                char        magic[16];            // e.g. "dyld_v0    i386", "dyld_v1   armv7", etc.
+                uint32_t    mappingOffset;        // file offset to first dyld_cache_mapping_info
+                uint32_t    mappingCount;         // number of dyld_cache_mapping_info entries
+                uint32_t    imagesOffset;
+                uint32_t    imagesCount;
+                uint64_t    dyldBaseAddress;
+                uint64_t    codeSignatureOffset;
+                uint64_t    codeSignatureSize;
+                uint64_t    slideInfoOffset;
+                uint64_t    slideInfoSize;
+                uint64_t    localSymbolsOffset;
+                uint64_t    localSymbolsSize;
+                uint8_t     uuid[16];             // v1 and above, also recorded in dyld_all_image_infos v13 and later
+            };
+
+            struct lldb_copy_dyld_cache_mapping_info
+            {
+                uint64_t        address;
+                uint64_t        size;
+                uint64_t        fileOffset;
+                uint32_t        maxProt;
+                uint32_t        initProt;
+            };
+
+            struct lldb_copy_dyld_cache_local_symbols_info
+            {
+                uint32_t        nlistOffset;
+                uint32_t        nlistCount;
+                uint32_t        stringsOffset;
+                uint32_t        stringsSize;
+                uint32_t        entriesOffset;
+                uint32_t        entriesCount;
+            };
+            struct lldb_copy_dyld_cache_local_symbols_entry
+            {
+                uint32_t        dylibOffset;
+                uint32_t        nlistStartIndex;
+                uint32_t        nlistCount;
+            };
 
             /* The dyld_cache_header has a pointer to the dyld_cache_local_symbols_info structure (localSymbolsOffset).
                The dyld_cache_local_symbols_info structure gives us three things:
@@ -1518,7 +1819,7 @@ struct lldb_copy_dyld_cache_local_symbol
 
                There is one dyld_cache_local_symbols_entry per dylib/framework in the dyld shared cache.
                The "dylibOffset" field is the Mach-O header of this dylib/framework in the dyld shared cache.
-               The dyld_cache_local_symbols_entry also lists the start of this dylib/framework's nlist records 
+               The dyld_cache_local_symbols_entry also lists the start of this dylib/framework's nlist records
                and the count of how many nlist records there are for this dylib/framework.
             */
 
@@ -1526,28 +1827,81 @@ struct lldb_copy_dyld_cache_local_symbol
             //
             // Save some VM space, do not map the entire cache in one shot.
 
-            if (DataBufferSP dsc_data_sp = dsc_filespec.MemoryMapFileContents(0, sizeof(struct lldb_copy_dyld_cache_header))) 
+            DataBufferSP dsc_data_sp;
+            dsc_data_sp = dsc_filespec.MemoryMapFileContents(0, sizeof(struct lldb_copy_dyld_cache_header_v1));
+
+            if (dsc_data_sp)
             {
-                DataExtractor dsc_header_data(dsc_data_sp, m_data.GetByteOrder(), m_data.GetAddressByteSize());
+                DataExtractor dsc_header_data(dsc_data_sp, byte_order, addr_byte_size);
+
+                char version_str[17];
+                int version = -1;
+                lldb::offset_t offset = 0;
+                memcpy (version_str, dsc_header_data.GetData (&offset, 16), 16);
+                version_str[16] = '\0';
+                if (strncmp (version_str, "dyld_v", 6) == 0 && isdigit (version_str[6]))
+                {
+                    int v;
+                    if (::sscanf (version_str + 6, "%d", &v) == 1)
+                    {
+                        version = v;
+                    }
+                }
+
+                UUID dsc_uuid;
+                if (version >= 1)
+                {
+                    offset = offsetof (struct lldb_copy_dyld_cache_header_v1, uuid);
+                    uint8_t uuid_bytes[sizeof (uuid_t)];
+                    memcpy (uuid_bytes, dsc_header_data.GetData (&offset, sizeof (uuid_t)), sizeof (uuid_t));
+                    dsc_uuid.SetBytes (uuid_bytes);
+                }
+
+                bool uuid_match = true;
+                if (dsc_uuid.IsValid() && process)
+                {
+                    UUID shared_cache_uuid(GetProcessSharedCacheUUID(process));
+
+                    if (shared_cache_uuid.IsValid() && dsc_uuid != shared_cache_uuid)
+                    {
+                        // The on-disk dyld_shared_cache file is not the same as the one in this
+                        // process' memory, don't use it.
+                        uuid_match = false;
+                        ModuleSP module_sp (GetModule());
+                        if (module_sp)
+                            module_sp->ReportWarning ("process shared cache does not match on-disk dyld_shared_cache file, some symbol names will be missing.");
+                    }
+                }
+
+                offset = offsetof (struct lldb_copy_dyld_cache_header_v1, mappingOffset);
 
-                uint32_t offset = offsetof (struct lldb_copy_dyld_cache_header, mappingOffset); 
                 uint32_t mappingOffset = dsc_header_data.GetU32(&offset);
 
                 // If the mappingOffset points to a location inside the header, we've
                 // opened an old dyld shared cache, and should not proceed further.
-                if (mappingOffset >= sizeof(struct lldb_copy_dyld_cache_header)) 
+                if (uuid_match && mappingOffset >= sizeof(struct lldb_copy_dyld_cache_header_v0))
                 {
 
-                    offset = offsetof (struct lldb_copy_dyld_cache_header, localSymbolsOffset);
+                    DataBufferSP dsc_mapping_info_data_sp = dsc_filespec.MemoryMapFileContents(mappingOffset, sizeof (struct lldb_copy_dyld_cache_mapping_info));
+                    DataExtractor dsc_mapping_info_data(dsc_mapping_info_data_sp, byte_order, addr_byte_size);
+                    offset = 0;
+
+                    // The File addresses (from the in-memory Mach-O load commands) for the shared libraries
+                    // in the shared library cache need to be adjusted by an offset to match up with the
+                    // dylibOffset identifying field in the dyld_cache_local_symbol_entry's.  This offset is
+                    // recorded in mapping_offset_value.
+                    const uint64_t mapping_offset_value = dsc_mapping_info_data.GetU64(&offset);
+
+                    offset = offsetof (struct lldb_copy_dyld_cache_header_v1, localSymbolsOffset);
                     uint64_t localSymbolsOffset = dsc_header_data.GetU64(&offset);
                     uint64_t localSymbolsSize = dsc_header_data.GetU64(&offset);
 
-                    if (localSymbolsOffset && localSymbolsSize) 
+                    if (localSymbolsOffset && localSymbolsSize)
                     {
                         // Map the local symbols
-                        if (DataBufferSP dsc_local_symbols_data_sp = dsc_filespec.MemoryMapFileContents(localSymbolsOffset, localSymbolsSize)) 
+                        if (DataBufferSP dsc_local_symbols_data_sp = dsc_filespec.MemoryMapFileContents(localSymbolsOffset, localSymbolsSize))
                         {
-                            DataExtractor dsc_local_symbols_data(dsc_local_symbols_data_sp, m_data.GetByteOrder(), m_data.GetAddressByteSize());
+                            DataExtractor dsc_local_symbols_data(dsc_local_symbols_data_sp, byte_order, addr_byte_size);
 
                             offset = 0;
 
@@ -1555,14 +1909,9 @@ struct lldb_copy_dyld_cache_local_symbol
                             struct lldb_copy_dyld_cache_local_symbols_info local_symbols_info;
                             dsc_local_symbols_data.GetU32(&offset, &local_symbols_info.nlistOffset, 6);
 
-                            // The local_symbols_infos offsets are offsets into local symbols memory, NOT file offsets!
-                            // We first need to identify the local "entry" that matches the current header.
-                            // The "entry" is stored as a file offset in the dyld_shared_cache, so we need to
-                            // adjust the raw m_header value by slide and 0x30000000.
-
                             SectionSP text_section_sp(section_list->FindSectionByName(GetSegmentNameTEXT()));
 
-                            uint32_t header_file_offset = (text_section_sp->GetFileAddress() - 0x30000000);
+                            uint32_t header_file_offset = (text_section_sp->GetFileAddress() - mapping_offset_value);
 
                             offset = local_symbols_info.entriesOffset;
                             for (uint32_t entry_index = 0; entry_index < local_symbols_info.entriesCount; entry_index++)
@@ -1572,7 +1921,7 @@ struct lldb_copy_dyld_cache_local_symbol
                                 local_symbols_entry.nlistStartIndex = dsc_local_symbols_data.GetU32(&offset);
                                 local_symbols_entry.nlistCount = dsc_local_symbols_data.GetU32(&offset);
 
-                                if (header_file_offset == local_symbols_entry.dylibOffset) 
+                                if (header_file_offset == local_symbols_entry.dylibOffset)
                                 {
                                     unmapped_local_symbols_found = local_symbols_entry.nlistCount;
 
@@ -1583,7 +1932,7 @@ struct lldb_copy_dyld_cache_local_symbol
                                     nlist_data_offset = local_symbols_info.nlistOffset + (nlist_byte_size * local_symbols_entry.nlistStartIndex);
                                     uint32_t string_table_offset = local_symbols_info.stringsOffset;
 
-                                    for (uint32_t nlist_index = 0; nlist_index < local_symbols_entry.nlistCount; nlist_index++) 
+                                    for (uint32_t nlist_index = 0; nlist_index < local_symbols_entry.nlistCount; nlist_index++)
                                     {
                                         /////////////////////////////
                                         {
@@ -1606,11 +1955,10 @@ struct lldb_copy_dyld_cache_local_symbol
                                                 // string values should have an offset zero which points
                                                 // to an empty C-string
                                                 Host::SystemLog (Host::eSystemLogError,
-                                                                 "error: DSC unmapped local symbol[%u] has invalid string table offset 0x%x in %s/%s, ignoring symbol\n",
+                                                                 "error: DSC unmapped local symbol[%u] has invalid string table offset 0x%x in %s, ignoring symbol\n",
                                                                  entry_index,
                                                                  nlist.n_strx,
-                                                                 module_sp->GetFileSpec().GetDirectory().GetCString(),
-                                                                 module_sp->GetFileSpec().GetFilename().GetCString());
+                                                                 module_sp->GetFileSpec().GetPath().c_str());
                                                 continue;
                                             }
                                             if (symbol_name[0] == '\0')
@@ -1622,6 +1970,8 @@ struct lldb_copy_dyld_cache_local_symbol
                                             uint32_t symbol_byte_size = 0;
                                             bool add_nlist = true;
                                             bool is_debug = ((nlist.n_type & NlistMaskStab) != 0);
+                                            bool demangled_is_synthesized = false;
+                                            bool is_gsym = false;
 
                                             assert (sym_idx < num_syms);
 
@@ -1649,6 +1999,7 @@ struct lldb_copy_dyld_cache_local_symbol
                                                             add_nlist = false;
                                                         else
                                                         {
+                                                            is_gsym = true;
                                                             sym[sym_idx].SetExternal(true);
                                                             if (nlist.n_value != 0)
                                                                 symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
@@ -1820,6 +2171,24 @@ struct lldb_copy_dyld_cache_local_symbol
                                                                 if (so_path && so_path[0])
                                                                 {
                                                                     std::string full_so_path (so_path);
+                                                                    const size_t double_slash_pos = full_so_path.find("//");
+                                                                    if (double_slash_pos != std::string::npos)
+                                                                    {
+                                                                        // The linker has been generating bad N_SO entries with doubled up paths
+                                                                        // in the format "%s%s" where the first stirng in the DW_AT_comp_dir,
+                                                                        // and the second is the directory for the source file so you end up with
+                                                                        // a path that looks like "/tmp/src//tmp/src/"
+                                                                        FileSpec so_dir(so_path, false);
+                                                                        if (!so_dir.Exists())
+                                                                        {
+                                                                            so_dir.SetFile(&full_so_path[double_slash_pos + 1], false);
+                                                                            if (so_dir.Exists())
+                                                                            {
+                                                                                // Trim off the incorrect path
+                                                                                full_so_path.erase(0, double_slash_pos + 1);
+                                                                            }
+                                                                        }
+                                                                    }
                                                                     if (*full_so_path.rbegin() != '/')
                                                                         full_so_path += '/';
                                                                     full_so_path += symbol_name;
@@ -1828,8 +2197,12 @@ struct lldb_copy_dyld_cache_local_symbol
                                                                     m_nlist_idx_to_sym_idx[nlist_idx] = sym_idx - 1;
                                                                 }
                                                             }
+                                                            else
+                                                            {
+                                                                // This could be a relative path to a N_SO
+                                                                N_SO_index = sym_idx;
+                                                            }
                                                         }
-
                                                         break;
 
                                                     case StabObjectFileName:
@@ -1994,68 +2367,67 @@ struct lldb_copy_dyld_cache_local_symbol
                                                         break;
 
                                                     case NListTypeSection:          // N_SECT
-                                                    {
-                                                        symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
-
-                                                        if (symbol_section == NULL)
                                                         {
-                                                            // TODO: warn about this?
-                                                            add_nlist = false;
-                                                            break;
-                                                        }
+                                                            symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
 
-                                                        if (TEXT_eh_frame_sectID == nlist.n_sect)
-                                                        {
-                                                            type = eSymbolTypeException;
-                                                        }
-                                                        else
-                                                        {
-                                                            uint32_t section_type = symbol_section->Get() & SectionFlagMaskSectionType;
-                                                            
-                                                            switch (section_type)
+                                                            if (symbol_section == NULL)
                                                             {
-                                                                case SectionTypeRegular:                     break; // regular section
-                                                                                                                    //case SectionTypeZeroFill:                 type = eSymbolTypeData;    break; // zero fill on demand section
-                                                                case SectionTypeCStringLiterals:            type = eSymbolTypeData;    break; // section with only literal C strings
-                                                                case SectionType4ByteLiterals:              type = eSymbolTypeData;    break; // section with only 4 byte literals
-                                                                case SectionType8ByteLiterals:              type = eSymbolTypeData;    break; // section with only 8 byte literals
-                                                                case SectionTypeLiteralPointers:            type = eSymbolTypeTrampoline; break; // section with only pointers to literals
-                                                                case SectionTypeNonLazySymbolPointers:      type = eSymbolTypeTrampoline; break; // section with only non-lazy symbol pointers
-                                                                case SectionTypeLazySymbolPointers:         type = eSymbolTypeTrampoline; break; // section with only lazy symbol pointers
-                                                                case SectionTypeSymbolStubs:                type = eSymbolTypeTrampoline; break; // section with only symbol stubs, byte size of stub in the reserved2 field
-                                                                case SectionTypeModuleInitFunctionPointers: type = eSymbolTypeCode;    break; // section with only function pointers for initialization
-                                                                case SectionTypeModuleTermFunctionPointers: type = eSymbolTypeCode;    break; // section with only function pointers for termination
-                                                                                                                                              //case SectionTypeCoalesced:                type = eSymbolType;    break; // section contains symbols that are to be coalesced
-                                                                                                                                              //case SectionTypeZeroFillLarge:            type = eSymbolTypeData;    break; // zero fill on demand section (that can be larger than 4 gigabytes)
-                                                                case SectionTypeInterposing:                type = eSymbolTypeTrampoline;  break; // section with only pairs of function pointers for interposing
-                                                                case SectionType16ByteLiterals:             type = eSymbolTypeData;    break; // section with only 16 byte literals
-                                                                case SectionTypeDTraceObjectFormat:         type = eSymbolTypeInstrumentation; break;
-                                                                case SectionTypeLazyDylibSymbolPointers:    type = eSymbolTypeTrampoline; break;
-                                                                default: break;
+                                                                // TODO: warn about this?
+                                                                add_nlist = false;
+                                                                break;
                                                             }
-                                                            
-                                                            if (type == eSymbolTypeInvalid)
+
+                                                            if (TEXT_eh_frame_sectID == nlist.n_sect)
                                                             {
-                                                                const char *symbol_sect_name = symbol_section->GetName().AsCString();
-                                                                if (symbol_section->IsDescendant (text_section_sp.get()))
+                                                                type = eSymbolTypeException;
+                                                            }
+                                                            else
+                                                            {
+                                                                uint32_t section_type = symbol_section->Get() & SectionFlagMaskSectionType;
+
+                                                                switch (section_type)
                                                                 {
-                                                                    if (symbol_section->IsClear(SectionAttrUserPureInstructions | 
-                                                                                                SectionAttrUserSelfModifyingCode | 
-                                                                                                SectionAttrSytemSomeInstructions))
-                                                                        type = eSymbolTypeData;
-                                                                    else
-                                                                        type = eSymbolTypeCode;
+                                                                    case SectionTypeRegular:                     break; // regular section
+                                                                                                                        //case SectionTypeZeroFill:                 type = eSymbolTypeData;    break; // zero fill on demand section
+                                                                    case SectionTypeCStringLiterals:            type = eSymbolTypeData;    break; // section with only literal C strings
+                                                                    case SectionType4ByteLiterals:              type = eSymbolTypeData;    break; // section with only 4 byte literals
+                                                                    case SectionType8ByteLiterals:              type = eSymbolTypeData;    break; // section with only 8 byte literals
+                                                                    case SectionTypeLiteralPointers:            type = eSymbolTypeTrampoline; break; // section with only pointers to literals
+                                                                    case SectionTypeNonLazySymbolPointers:      type = eSymbolTypeTrampoline; break; // section with only non-lazy symbol pointers
+                                                                    case SectionTypeLazySymbolPointers:         type = eSymbolTypeTrampoline; break; // section with only lazy symbol pointers
+                                                                    case SectionTypeSymbolStubs:                type = eSymbolTypeTrampoline; break; // section with only symbol stubs, byte size of stub in the reserved2 field
+                                                                    case SectionTypeModuleInitFunctionPointers: type = eSymbolTypeCode;    break; // section with only function pointers for initialization
+                                                                    case SectionTypeModuleTermFunctionPointers: type = eSymbolTypeCode;    break; // section with only function pointers for termination
+                                                                                                                                                  //case SectionTypeCoalesced:                type = eSymbolType;    break; // section contains symbols that are to be coalesced
+                                                                                                                                                  //case SectionTypeZeroFillLarge:            type = eSymbolTypeData;    break; // zero fill on demand section (that can be larger than 4 gigabytes)
+                                                                    case SectionTypeInterposing:                type = eSymbolTypeTrampoline;  break; // section with only pairs of function pointers for interposing
+                                                                    case SectionType16ByteLiterals:             type = eSymbolTypeData;    break; // section with only 16 byte literals
+                                                                    case SectionTypeDTraceObjectFormat:         type = eSymbolTypeInstrumentation; break;
+                                                                    case SectionTypeLazyDylibSymbolPointers:    type = eSymbolTypeTrampoline; break;
+                                                                    default: break;
                                                                 }
-                                                                else
-                                                                    if (symbol_section->IsDescendant(data_section_sp.get()))
+
+                                                                if (type == eSymbolTypeInvalid)
+                                                                {
+                                                                    const char *symbol_sect_name = symbol_section->GetName().AsCString();
+                                                                    if (symbol_section->IsDescendant (text_section_sp.get()))
+                                                                    {
+                                                                        if (symbol_section->IsClear(SectionAttrUserPureInstructions |
+                                                                                                    SectionAttrUserSelfModifyingCode |
+                                                                                                    SectionAttrSytemSomeInstructions))
+                                                                            type = eSymbolTypeData;
+                                                                        else
+                                                                            type = eSymbolTypeCode;
+                                                                    }
+                                                                    else if (symbol_section->IsDescendant(data_section_sp.get()))
                                                                     {
                                                                         if (symbol_sect_name && ::strstr (symbol_sect_name, "__objc") == symbol_sect_name)
                                                                         {
                                                                             type = eSymbolTypeRuntime;
-                                                                            
-                                                                            if (symbol_name && 
-                                                                                symbol_name[0] == '_' && 
-                                                                                symbol_name[1] == 'O' && 
+
+                                                                            if (symbol_name &&
+                                                                                symbol_name[0] == '_' &&
+                                                                                symbol_name[1] == 'O' &&
                                                                                 symbol_name[2] == 'B')
                                                                             {
                                                                                 llvm::StringRef symbol_name_ref(symbol_name);
@@ -2067,64 +2439,65 @@ struct lldb_copy_dyld_cache_local_symbol
                                                                                     symbol_name_non_abi_mangled = symbol_name + 1;
                                                                                     symbol_name = symbol_name + g_objc_v2_prefix_class.size();
                                                                                     type = eSymbolTypeObjCClass;
+                                                                                    demangled_is_synthesized = true;
                                                                                 }
                                                                                 else if (symbol_name_ref.startswith(g_objc_v2_prefix_metaclass))
                                                                                 {
                                                                                     symbol_name_non_abi_mangled = symbol_name + 1;
                                                                                     symbol_name = symbol_name + g_objc_v2_prefix_metaclass.size();
                                                                                     type = eSymbolTypeObjCMetaClass;
+                                                                                    demangled_is_synthesized = true;
                                                                                 }
                                                                                 else if (symbol_name_ref.startswith(g_objc_v2_prefix_ivar))
                                                                                 {
                                                                                     symbol_name_non_abi_mangled = symbol_name + 1;
                                                                                     symbol_name = symbol_name + g_objc_v2_prefix_ivar.size();
                                                                                     type = eSymbolTypeObjCIVar;
+                                                                                    demangled_is_synthesized = true;
                                                                                 }
                                                                             }
                                                                         }
-                                                                        else
-                                                                            if (symbol_sect_name && ::strstr (symbol_sect_name, "__gcc_except_tab") == symbol_sect_name)
-                                                                            {
-                                                                                type = eSymbolTypeException;
-                                                                            }
-                                                                            else
-                                                                            {
-                                                                                type = eSymbolTypeData;
-                                                                            }
-                                                                    }
-                                                                    else
-                                                                        if (symbol_sect_name && ::strstr (symbol_sect_name, "__IMPORT") == symbol_sect_name)
+                                                                        else if (symbol_sect_name && ::strstr (symbol_sect_name, "__gcc_except_tab") == symbol_sect_name)
                                                                         {
-                                                                            type = eSymbolTypeTrampoline;
+                                                                            type = eSymbolTypeException;
                                                                         }
                                                                         else
-                                                                            if (symbol_section->IsDescendant(objc_section_sp.get()))
+                                                                        {
+                                                                            type = eSymbolTypeData;
+                                                                        }
+                                                                    }
+                                                                    else if (symbol_sect_name && ::strstr (symbol_sect_name, "__IMPORT") == symbol_sect_name)
+                                                                    {
+                                                                        type = eSymbolTypeTrampoline;
+                                                                    }
+                                                                    else if (symbol_section->IsDescendant(objc_section_sp.get()))
+                                                                    {
+                                                                        type = eSymbolTypeRuntime;
+                                                                        if (symbol_name && symbol_name[0] == '.')
+                                                                        {
+                                                                            llvm::StringRef symbol_name_ref(symbol_name);
+                                                                            static const llvm::StringRef g_objc_v1_prefix_class (".objc_class_name_");
+                                                                            if (symbol_name_ref.startswith(g_objc_v1_prefix_class))
                                                                             {
-                                                                                type = eSymbolTypeRuntime;
-                                                                                if (symbol_name && symbol_name[0] == '.')
-                                                                                {
-                                                                                    llvm::StringRef symbol_name_ref(symbol_name);
-                                                                                    static const llvm::StringRef g_objc_v1_prefix_class (".objc_class_name_");
-                                                                                    if (symbol_name_ref.startswith(g_objc_v1_prefix_class))
-                                                                                    {
-                                                                                        symbol_name_non_abi_mangled = symbol_name;
-                                                                                        symbol_name = symbol_name + g_objc_v1_prefix_class.size();
-                                                                                        type = eSymbolTypeObjCClass;
-                                                                                    }
-                                                                                }
+                                                                                symbol_name_non_abi_mangled = symbol_name;
+                                                                                symbol_name = symbol_name + g_objc_v1_prefix_class.size();
+                                                                                type = eSymbolTypeObjCClass;
+                                                                                demangled_is_synthesized = true;
                                                                             }
+                                                                        }
+                                                                    }
+                                                                }
                                                             }
                                                         }
-                                                    }
                                                         break;
-                                                }                            
+                                                }
                                             }
 
                                             if (add_nlist)
                                             {
                                                 uint64_t symbol_value = nlist.n_value;
                                                 bool symbol_name_is_mangled = false;
-                                                
+
                                                 if (symbol_name_non_abi_mangled)
                                                 {
                                                     sym[sym_idx].GetMangled().SetMangledName (ConstString(symbol_name_non_abi_mangled));
@@ -2137,56 +2510,13 @@ struct lldb_copy_dyld_cache_local_symbol
                                                         symbol_name_is_mangled = symbol_name[1] == '_';
                                                         symbol_name++;  // Skip the leading underscore
                                                     }
-                                                    
+
                                                     if (symbol_name)
                                                     {
-                                                        sym[sym_idx].GetMangled().SetValue(ConstString(symbol_name), symbol_name_is_mangled);
-                                                    }
-                                                }
-                                                
-                                                if (is_debug == false)
-                                                {
-                                                    if (type == eSymbolTypeCode)
-                                                    {
-                                                        // See if we can find a N_FUN entry for any code symbols.
-                                                        // If we do find a match, and the name matches, then we
-                                                        // can merge the two into just the function symbol to avoid
-                                                        // duplicate entries in the symbol table
-                                                        ValueToSymbolIndexMap::const_iterator pos = N_FUN_addr_to_sym_idx.find (nlist.n_value);
-                                                        if (pos != N_FUN_addr_to_sym_idx.end())
-                                                        {
-                                                            if ((symbol_name_is_mangled == true && sym[sym_idx].GetMangled().GetMangledName() == sym[pos->second].GetMangled().GetMangledName()) ||
-                                                                (symbol_name_is_mangled == false && sym[sym_idx].GetMangled().GetDemangledName() == sym[pos->second].GetMangled().GetDemangledName()))
-                                                            {
-                                                                m_nlist_idx_to_sym_idx[nlist_idx] = pos->second;
-                                                                // We just need the flags from the linker symbol, so put these flags
-                                                                // into the N_FUN flags to avoid duplicate symbols in the symbol table
-                                                                sym[pos->second].SetFlags (nlist.n_type << 16 | nlist.n_desc);
-                                                                sym[sym_idx].Clear();
-                                                                continue;
-                                                            }
-                                                        }
-                                                    }
-                                                    else if (type == eSymbolTypeData)
-                                                    {
-                                                        // See if we can find a N_STSYM entry for any data symbols.
-                                                        // If we do find a match, and the name matches, then we
-                                                        // can merge the two into just the Static symbol to avoid
-                                                        // duplicate entries in the symbol table
-                                                        ValueToSymbolIndexMap::const_iterator pos = N_STSYM_addr_to_sym_idx.find (nlist.n_value);
-                                                        if (pos != N_STSYM_addr_to_sym_idx.end())
-                                                        {
-                                                            if ((symbol_name_is_mangled == true && sym[sym_idx].GetMangled().GetMangledName() == sym[pos->second].GetMangled().GetMangledName()) ||
-                                                                (symbol_name_is_mangled == false && sym[sym_idx].GetMangled().GetDemangledName() == sym[pos->second].GetMangled().GetDemangledName()))
-                                                            {
-                                                                m_nlist_idx_to_sym_idx[nlist_idx] = pos->second;
-                                                                // We just need the flags from the linker symbol, so put these flags
-                                                                // into the N_STSYM flags to avoid duplicate symbols in the symbol table
-                                                                sym[pos->second].SetFlags (nlist.n_type << 16 | nlist.n_desc);
-                                                                sym[sym_idx].Clear();
-                                                                continue;
-                                                            }
-                                                        }
+                                                        ConstString const_symbol_name(symbol_name);
+                                                        if (is_gsym)
+                                                            N_GSYM_name_to_sym_idx[const_symbol_name.GetCString()] = sym_idx;
+                                                        sym[sym_idx].GetMangled().SetValue(const_symbol_name, symbol_name_is_mangled);
                                                     }
                                                 }
                                                 if (symbol_section)
@@ -2212,7 +2542,7 @@ struct lldb_copy_dyld_cache_local_symbol
                                                         if (func_start_entry)
                                                         {
                                                             func_start_entry->data = true;
-                                                            
+
                                                             addr_t symbol_file_addr = func_start_entry->addr;
                                                             uint32_t symbol_flags = 0;
                                                             if (is_arm)
@@ -2221,7 +2551,7 @@ struct lldb_copy_dyld_cache_local_symbol
                                                                     symbol_flags = MACHO_NLIST_ARM_SYMBOL_IS_THUMB;
                                                                 symbol_file_addr &= 0xfffffffffffffffeull;
                                                             }
-                                                            
+
                                                             const FunctionStarts::Entry *next_func_start_entry = function_starts.FindNextEntry (func_start_entry);
                                                             const addr_t section_end_file_addr = section_file_addr + symbol_section->GetByteSize();
                                                             if (next_func_start_entry)
@@ -2233,31 +2563,98 @@ struct lldb_copy_dyld_cache_local_symbol
                                                                     next_symbol_file_addr &= 0xfffffffffffffffeull;
                                                                 symbol_byte_size = std::min<lldb::addr_t>(next_symbol_file_addr - symbol_file_addr, section_end_file_addr - symbol_file_addr);
                                                             }
-                                                            else
+                                                            else
+                                                            {
+                                                                symbol_byte_size = section_end_file_addr - symbol_file_addr;
+                                                            }
+                                                        }
+                                                    }
+                                                    symbol_value -= section_file_addr;
+                                                }
+
+                                                if (is_debug == false)
+                                                {
+                                                    if (type == eSymbolTypeCode)
+                                                    {
+                                                        // See if we can find a N_FUN entry for any code symbols.
+                                                        // If we do find a match, and the name matches, then we
+                                                        // can merge the two into just the function symbol to avoid
+                                                        // duplicate entries in the symbol table
+                                                        ValueToSymbolIndexMap::const_iterator pos = N_FUN_addr_to_sym_idx.find (nlist.n_value);
+                                                        if (pos != N_FUN_addr_to_sym_idx.end())
+                                                        {
+                                                            if ((symbol_name_is_mangled == true && sym[sym_idx].GetMangled().GetMangledName() == sym[pos->second].GetMangled().GetMangledName()) ||
+                                                                (symbol_name_is_mangled == false && sym[sym_idx].GetMangled().GetDemangledName() == sym[pos->second].GetMangled().GetDemangledName()))
+                                                            {
+                                                                m_nlist_idx_to_sym_idx[nlist_idx] = pos->second;
+                                                                // We just need the flags from the linker symbol, so put these flags
+                                                                // into the N_FUN flags to avoid duplicate symbols in the symbol table
+                                                                sym[pos->second].SetFlags (nlist.n_type << 16 | nlist.n_desc);
+                                                                sym[sym_idx].Clear();
+                                                                continue;
+                                                            }
+                                                        }
+                                                    }
+                                                    else if (type == eSymbolTypeData)
+                                                    {
+                                                        // See if we can find a N_STSYM entry for any data symbols.
+                                                        // If we do find a match, and the name matches, then we
+                                                        // can merge the two into just the Static symbol to avoid
+                                                        // duplicate entries in the symbol table
+                                                        ValueToSymbolIndexMap::const_iterator pos = N_STSYM_addr_to_sym_idx.find (nlist.n_value);
+                                                        if (pos != N_STSYM_addr_to_sym_idx.end())
+                                                        {
+                                                            if ((symbol_name_is_mangled == true && sym[sym_idx].GetMangled().GetMangledName() == sym[pos->second].GetMangled().GetMangledName()) ||
+                                                                (symbol_name_is_mangled == false && sym[sym_idx].GetMangled().GetDemangledName() == sym[pos->second].GetMangled().GetDemangledName()))
+                                                            {
+                                                                m_nlist_idx_to_sym_idx[nlist_idx] = pos->second;
+                                                                // We just need the flags from the linker symbol, so put these flags
+                                                                // into the N_STSYM flags to avoid duplicate symbols in the symbol table
+                                                                sym[pos->second].SetFlags (nlist.n_type << 16 | nlist.n_desc);
+                                                                sym[sym_idx].Clear();
+                                                                continue;
+                                                            }
+                                                        }
+                                                        else
+                                                        {
+                                                            // Combine N_GSYM stab entries with the non stab symbol
+                                                            ConstNameToSymbolIndexMap::const_iterator pos = N_GSYM_name_to_sym_idx.find(sym[sym_idx].GetMangled().GetMangledName().GetCString());
+                                                            if (pos != N_GSYM_name_to_sym_idx.end())
                                                             {
-                                                                symbol_byte_size = section_end_file_addr - symbol_file_addr;
+                                                                const uint32_t GSYM_sym_idx = pos->second;
+                                                                m_nlist_idx_to_sym_idx[nlist_idx] = GSYM_sym_idx;
+                                                                // Copy the address, because often the N_GSYM address has an invalid address of zero
+                                                                // when the global is a common symbol
+                                                                sym[GSYM_sym_idx].GetAddress().SetSection (symbol_section);
+                                                                sym[GSYM_sym_idx].GetAddress().SetOffset (symbol_value);
+                                                                // We just need the flags from the linker symbol, so put these flags
+                                                                // into the N_STSYM flags to avoid duplicate symbols in the symbol table
+                                                                sym[GSYM_sym_idx].SetFlags (nlist.n_type << 16 | nlist.n_desc);
+                                                                sym[sym_idx].Clear();
+                                                                continue;
                                                             }
                                                         }
                                                     }
-                                                    symbol_value -= section_file_addr;
                                                 }
-                                                
+
                                                 sym[sym_idx].SetID (nlist_idx);
                                                 sym[sym_idx].SetType (type);
                                                 sym[sym_idx].GetAddress().SetSection (symbol_section);
                                                 sym[sym_idx].GetAddress().SetOffset (symbol_value);
                                                 sym[sym_idx].SetFlags (nlist.n_type << 16 | nlist.n_desc);
-                                                
+
                                                 if (symbol_byte_size > 0)
                                                     sym[sym_idx].SetByteSize(symbol_byte_size);
 
+                                                if (demangled_is_synthesized)
+                                                    sym[sym_idx].SetDemangledNameIsSynthesized(true);
                                                 ++sym_idx;
                                             }
                                             else
                                             {
                                                 sym[sym_idx].Clear();
                                             }
-                                            
+
                                         }
                                         /////////////////////////////
                                     }
@@ -2307,22 +2704,21 @@ struct lldb_copy_dyld_cache_local_symbol
 
             SymbolType type = eSymbolTypeInvalid;
             const char *symbol_name = NULL;
-            
+
             if (have_strtab_data)
             {
                 symbol_name = strtab_data.PeekCStr(nlist.n_strx);
-                
+
                 if (symbol_name == NULL)
                 {
                     // No symbol should be NULL, even the symbols with no
                     // string values should have an offset zero which points
                     // to an empty C-string
                     Host::SystemLog (Host::eSystemLogError,
-                                     "error: symbol[%u] has invalid string table offset 0x%x in %s/%s, ignoring symbol\n", 
+                                     "error: symbol[%u] has invalid string table offset 0x%x in %s, ignoring symbol\n",
                                      nlist_idx,
                                      nlist.n_strx,
-                                     module_sp->GetFileSpec().GetDirectory().GetCString(),
-                                     module_sp->GetFileSpec().GetFilename().GetCString());
+                                     module_sp->GetFileSpec().GetPath().c_str());
                     continue;
                 }
                 if (symbol_name[0] == '\0')
@@ -2338,9 +2734,11 @@ struct lldb_copy_dyld_cache_local_symbol
             const char *symbol_name_non_abi_mangled = NULL;
 
             SectionSP symbol_section;
-            uint32_t symbol_byte_size = 0;
+            lldb::addr_t symbol_byte_size = 0;
             bool add_nlist = true;
+            bool is_gsym = false;
             bool is_debug = ((nlist.n_type & NlistMaskStab) != 0);
+            bool demangled_is_synthesized = false;
 
             assert (sym_idx < num_syms);
 
@@ -2350,24 +2748,25 @@ struct lldb_copy_dyld_cache_local_symbol
             {
                 switch (nlist.n_type)
                 {
-                case StabGlobalSymbol:    
+                case StabGlobalSymbol:
                     // N_GSYM -- global symbol: name,,NO_SECT,type,0
                     // Sometimes the N_GSYM value contains the address.
-                    
+
                     // FIXME: In the .o files, we have a GSYM and a debug symbol for all the ObjC data.  They
                     // have the same address, but we want to ensure that we always find only the real symbol,
                     // 'cause we don't currently correctly attribute the GSYM one to the ObjCClass/Ivar/MetaClass
                     // symbol type.  This is a temporary hack to make sure the ObjectiveC symbols get treated
                     // correctly.  To do this right, we should coalesce all the GSYM & global symbols that have the
                     // same address.
-                    
-                    if (symbol_name && symbol_name[0] == '_' && symbol_name[1] ==  'O' 
+
+                    if (symbol_name && symbol_name[0] == '_' && symbol_name[1] ==  'O'
                         && (strncmp (symbol_name, "_OBJC_IVAR_$_", strlen ("_OBJC_IVAR_$_")) == 0
                             || strncmp (symbol_name, "_OBJC_CLASS_$_", strlen ("_OBJC_CLASS_$_")) == 0
                             || strncmp (symbol_name, "_OBJC_METACLASS_$_", strlen ("_OBJC_METACLASS_$_")) == 0))
                         add_nlist = false;
                     else
                     {
+                        is_gsym = true;
                         sym[sym_idx].SetExternal(true);
                         if (nlist.n_value != 0)
                             symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
@@ -2380,13 +2779,13 @@ struct lldb_copy_dyld_cache_local_symbol
                     type = eSymbolTypeCompiler;
                     break;
 
-                case StabFunction:       
+                case StabFunction:
                     // N_FUN -- procedure: name,,n_sect,linenumber,address
                     if (symbol_name)
                     {
                         type = eSymbolTypeCode;
                         symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
-                        
+
                         N_FUN_addr_to_sym_idx[nlist.n_value] = sym_idx;
                         // We use the current number of symbols in the symbol table in lieu of
                         // using nlist_idx in case we ever start trimming entries out
@@ -2411,7 +2810,7 @@ struct lldb_copy_dyld_cache_local_symbol
                     }
                     break;
 
-                case StabStaticSymbol:   
+                case StabStaticSymbol:
                     // N_STSYM -- static symbol: name,,n_sect,type,address
                     N_STSYM_addr_to_sym_idx[nlist.n_value] = sym_idx;
                     symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
@@ -2539,6 +2938,24 @@ struct lldb_copy_dyld_cache_local_symbol
                             if (so_path && so_path[0])
                             {
                                 std::string full_so_path (so_path);
+                                const size_t double_slash_pos = full_so_path.find("//");
+                                if (double_slash_pos != std::string::npos)
+                                {
+                                    // The linker has been generating bad N_SO entries with doubled up paths
+                                    // in the format "%s%s" where the first stirng in the DW_AT_comp_dir,
+                                    // and the second is the directory for the source file so you end up with
+                                    // a path that looks like "/tmp/src//tmp/src/"
+                                    FileSpec so_dir(so_path, false);
+                                    if (!so_dir.Exists())
+                                    {
+                                        so_dir.SetFile(&full_so_path[double_slash_pos + 1], false);
+                                        if (so_dir.Exists())
+                                        {
+                                            // Trim off the incorrect path
+                                            full_so_path.erase(0, double_slash_pos + 1);
+                                        }
+                                    }
+                                }
                                 if (*full_so_path.rbegin() != '/')
                                     full_so_path += '/';
                                 full_so_path += symbol_name;
@@ -2547,8 +2964,13 @@ struct lldb_copy_dyld_cache_local_symbol
                                 m_nlist_idx_to_sym_idx[nlist_idx] = sym_idx - 1;
                             }
                         }
+                        else
+                        {
+                            // This could be a relative path to a N_SO
+                            N_SO_index = sym_idx;
+                        }
                     }
-                    
+
                     break;
 
                 case StabObjectFileName:
@@ -2596,7 +3018,7 @@ struct lldb_copy_dyld_cache_local_symbol
                         add_nlist = false;
                     break;
 
-                case StabCompilerParameters:  
+                case StabCompilerParameters:
                     // N_PARAMS - compiler parameters: name,,NO_SECT,0,0
                     type = eSymbolTypeCompiler;
                     break;
@@ -2758,8 +3180,8 @@ struct lldb_copy_dyld_cache_local_symbol
                                 const char *symbol_sect_name = symbol_section->GetName().AsCString();
                                 if (symbol_section->IsDescendant (text_section_sp.get()))
                                 {
-                                    if (symbol_section->IsClear(SectionAttrUserPureInstructions | 
-                                                                SectionAttrUserSelfModifyingCode | 
+                                    if (symbol_section->IsClear(SectionAttrUserPureInstructions |
+                                                                SectionAttrUserSelfModifyingCode |
                                                                 SectionAttrSytemSomeInstructions))
                                         type = eSymbolTypeData;
                                     else
@@ -2772,9 +3194,9 @@ struct lldb_copy_dyld_cache_local_symbol
                                     {
                                         type = eSymbolTypeRuntime;
 
-                                        if (symbol_name && 
-                                            symbol_name[0] == '_' && 
-                                            symbol_name[1] == 'O' && 
+                                        if (symbol_name &&
+                                            symbol_name[0] == '_' &&
+                                            symbol_name[1] == 'O' &&
                                             symbol_name[2] == 'B')
                                         {
                                             llvm::StringRef symbol_name_ref(symbol_name);
@@ -2786,18 +3208,21 @@ struct lldb_copy_dyld_cache_local_symbol
                                                 symbol_name_non_abi_mangled = symbol_name + 1;
                                                 symbol_name = symbol_name + g_objc_v2_prefix_class.size();
                                                 type = eSymbolTypeObjCClass;
+                                                demangled_is_synthesized = true;
                                             }
                                             else if (symbol_name_ref.startswith(g_objc_v2_prefix_metaclass))
                                             {
                                                 symbol_name_non_abi_mangled = symbol_name + 1;
                                                 symbol_name = symbol_name + g_objc_v2_prefix_metaclass.size();
                                                 type = eSymbolTypeObjCMetaClass;
+                                                demangled_is_synthesized = true;
                                             }
                                             else if (symbol_name_ref.startswith(g_objc_v2_prefix_ivar))
                                             {
                                                 symbol_name_non_abi_mangled = symbol_name + 1;
                                                 symbol_name = symbol_name + g_objc_v2_prefix_ivar.size();
                                                 type = eSymbolTypeObjCIVar;
+                                                demangled_is_synthesized = true;
                                             }
                                         }
                                     }
@@ -2829,6 +3254,7 @@ struct lldb_copy_dyld_cache_local_symbol
                                             symbol_name_non_abi_mangled = symbol_name;
                                             symbol_name = symbol_name + g_objc_v1_prefix_class.size();
                                             type = eSymbolTypeObjCClass;
+                                            demangled_is_synthesized = true;
                                         }
                                     }
                                 }
@@ -2836,7 +3262,7 @@ struct lldb_copy_dyld_cache_local_symbol
                         }
                     }
                     break;
-                }                            
+                }
             }
 
             if (add_nlist)
@@ -2859,8 +3285,58 @@ struct lldb_copy_dyld_cache_local_symbol
 
                     if (symbol_name)
                     {
-                        sym[sym_idx].GetMangled().SetValue(ConstString(symbol_name), symbol_name_is_mangled);
+                        ConstString const_symbol_name(symbol_name);
+                        if (is_gsym)
+                            N_GSYM_name_to_sym_idx[const_symbol_name.GetCString()] = sym_idx;
+                        sym[sym_idx].GetMangled().SetValue(const_symbol_name, symbol_name_is_mangled);
+                    }
+                }
+                if (symbol_section)
+                {
+                    const addr_t section_file_addr = symbol_section->GetFileAddress();
+                    if (symbol_byte_size == 0 && function_starts_count > 0)
+                    {
+                        addr_t symbol_lookup_file_addr = nlist.n_value;
+                        // Do an exact address match for non-ARM addresses, else get the closest since
+                        // the symbol might be a thumb symbol which has an address with bit zero set
+                        FunctionStarts::Entry *func_start_entry = function_starts.FindEntry (symbol_lookup_file_addr, !is_arm);
+                        if (is_arm && func_start_entry)
+                        {
+                            // Verify that the function start address is the symbol address (ARM)
+                            // or the symbol address + 1 (thumb)
+                            if (func_start_entry->addr != symbol_lookup_file_addr &&
+                                func_start_entry->addr != (symbol_lookup_file_addr + 1))
+                            {
+                                // Not the right entry, NULL it out...
+                                func_start_entry = NULL;
+                            }
+                        }
+                        if (func_start_entry)
+                        {
+                            func_start_entry->data = true;
+
+                            addr_t symbol_file_addr = func_start_entry->addr;
+                            if (is_arm)
+                                symbol_file_addr &= 0xfffffffffffffffeull;
+
+                            const FunctionStarts::Entry *next_func_start_entry = function_starts.FindNextEntry (func_start_entry);
+                            const addr_t section_end_file_addr = section_file_addr + symbol_section->GetByteSize();
+                            if (next_func_start_entry)
+                            {
+                                addr_t next_symbol_file_addr = next_func_start_entry->addr;
+                                // Be sure the clear the Thumb address bit when we calculate the size
+                                // from the current and next address
+                                if (is_arm)
+                                    next_symbol_file_addr &= 0xfffffffffffffffeull;
+                                symbol_byte_size = std::min<lldb::addr_t>(next_symbol_file_addr - symbol_file_addr, section_end_file_addr - symbol_file_addr);
+                            }
+                            else
+                            {
+                                symbol_byte_size = section_end_file_addr - symbol_file_addr;
+                            }
+                        }
                     }
+                    symbol_value -= section_file_addr;
                 }
 
                 if (is_debug == false)
@@ -2906,54 +3382,26 @@ struct lldb_copy_dyld_cache_local_symbol
                                 continue;
                             }
                         }
-                    }
-                }
-                if (symbol_section)
-                {
-                    const addr_t section_file_addr = symbol_section->GetFileAddress();
-                    if (symbol_byte_size == 0 && function_starts_count > 0)
-                    {
-                        addr_t symbol_lookup_file_addr = nlist.n_value;
-                        // Do an exact address match for non-ARM addresses, else get the closest since
-                        // the symbol might be a thumb symbol which has an address with bit zero set
-                        FunctionStarts::Entry *func_start_entry = function_starts.FindEntry (symbol_lookup_file_addr, !is_arm);
-                        if (is_arm && func_start_entry)
-                        {
-                            // Verify that the function start address is the symbol address (ARM)
-                            // or the symbol address + 1 (thumb)
-                            if (func_start_entry->addr != symbol_lookup_file_addr &&
-                                func_start_entry->addr != (symbol_lookup_file_addr + 1))
-                            {
-                                // Not the right entry, NULL it out...
-                                func_start_entry = NULL;
-                            }
-                        }
-                        if (func_start_entry)
+                        else
                         {
-                            func_start_entry->data = true;
-                            
-                            addr_t symbol_file_addr = func_start_entry->addr;
-                            if (is_arm)
-                                symbol_file_addr &= 0xfffffffffffffffeull;
-
-                            const FunctionStarts::Entry *next_func_start_entry = function_starts.FindNextEntry (func_start_entry);
-                            const addr_t section_end_file_addr = section_file_addr + symbol_section->GetByteSize();
-                            if (next_func_start_entry)
-                            {
-                                addr_t next_symbol_file_addr = next_func_start_entry->addr;
-                                // Be sure the clear the Thumb address bit when we calculate the size
-                                // from the current and next address
-                                if (is_arm)
-                                    next_symbol_file_addr &= 0xfffffffffffffffeull;
-                                symbol_byte_size = std::min<lldb::addr_t>(next_symbol_file_addr - symbol_file_addr, section_end_file_addr - symbol_file_addr);
-                            }
-                            else
+                            // Combine N_GSYM stab entries with the non stab symbol
+                            ConstNameToSymbolIndexMap::const_iterator pos = N_GSYM_name_to_sym_idx.find(sym[sym_idx].GetMangled().GetMangledName().GetCString());
+                            if (pos != N_GSYM_name_to_sym_idx.end())
                             {
-                                symbol_byte_size = section_end_file_addr - symbol_file_addr;
+                                const uint32_t GSYM_sym_idx = pos->second;
+                                m_nlist_idx_to_sym_idx[nlist_idx] = GSYM_sym_idx;
+                                // Copy the address, because often the N_GSYM address has an invalid address of zero
+                                // when the global is a common symbol
+                                sym[GSYM_sym_idx].GetAddress().SetSection (symbol_section);
+                                sym[GSYM_sym_idx].GetAddress().SetOffset (symbol_value);
+                                // We just need the flags from the linker symbol, so put these flags
+                                // into the N_STSYM flags to avoid duplicate symbols in the symbol table
+                                sym[GSYM_sym_idx].SetFlags (nlist.n_type << 16 | nlist.n_desc);
+                                sym[sym_idx].Clear();
+                                continue;
                             }
                         }
                     }
-                    symbol_value -= section_file_addr;
                 }
 
                 sym[sym_idx].SetID (nlist_idx);
@@ -2965,6 +3413,9 @@ struct lldb_copy_dyld_cache_local_symbol
                 if (symbol_byte_size > 0)
                     sym[sym_idx].SetByteSize(symbol_byte_size);
 
+                if (demangled_is_synthesized)
+                    sym[sym_idx].SetDemangledNameIsSynthesized(true);
+
                 ++sym_idx;
             }
             else
@@ -3004,7 +3455,7 @@ struct lldb_copy_dyld_cache_local_symbol
                 }
             }
         }
-        
+
         uint32_t synthetic_sym_id = symtab_load_command.nsyms;
 
         if (function_starts_count > 0)
@@ -3016,7 +3467,7 @@ struct lldb_copy_dyld_cache_local_symbol
                 if (function_starts.GetEntryRef (i).data == false)
                     ++num_synthetic_function_symbols;
             }
-            
+
             if (num_synthetic_function_symbols > 0)
             {
                 if (num_syms < sym_idx + num_synthetic_function_symbols)
@@ -3092,8 +3543,6 @@ struct lldb_copy_dyld_cache_local_symbol
         // Now synthesize indirect symbols
         if (m_dysymtab.nindirectsyms != 0)
         {
-            DataExtractor indirect_symbol_index_data (m_data, m_dysymtab.indirectsymoff, m_dysymtab.nindirectsyms * 4);
-
             if (indirect_symbol_index_data.GetByteSize())
             {
                 NListIndexToSymbolIndexMap::const_iterator end_index_pos = m_nlist_idx_to_sym_idx.end();
@@ -3116,7 +3565,7 @@ struct lldb_copy_dyld_cache_local_symbol
                         {
                             const uint32_t symbol_stub_index = symbol_stub_index_offset + stub_idx;
                             const lldb::addr_t symbol_stub_addr = m_mach_sections[sect_idx].addr + (stub_idx * symbol_stub_byte_size);
-                            uint32_t symbol_stub_offset = symbol_stub_index * 4;
+                            lldb::offset_t symbol_stub_offset = symbol_stub_index * 4;
                             if (indirect_symbol_index_data.ValidOffsetForDataOfSize(symbol_stub_offset, 4))
                             {
                                 const uint32_t stub_sym_id = indirect_symbol_index_data.GetU32 (&symbol_stub_offset);
@@ -3131,15 +3580,14 @@ struct lldb_copy_dyld_cache_local_symbol
                                     // a current symbol index, so just look this up by index
                                     stub_symbol = symtab->SymbolAtIndex (index_pos->second);
                                 }
-                                else 
+                                else
                                 {
                                     // We need to lookup a symbol using the original nlist
-                                    // symbol index since this index is coming from the 
+                                    // symbol index since this index is coming from the
                                     // S_SYMBOL_STUBS
                                     stub_symbol = symtab->FindSymbolByID (stub_sym_id);
                                 }
 
-                                assert (stub_symbol);
                                 if (stub_symbol)
                                 {
                                     Address so_addr(symbol_stub_addr, section_list);
@@ -3173,6 +3621,11 @@ struct lldb_copy_dyld_cache_local_symbol
                                         ++sym_idx;
                                     }
                                 }
+                                else
+                                {
+                                    if (log)
+                                        log->Warning ("symbol stub referencing symbol table symbol %u that isn't in our minimal symbol table, fix this!!!", stub_sym_id);
+                                }
                             }
                         }
                     }
@@ -3211,48 +3664,59 @@ ObjectFileMachO::Dump (Stream *s)
     }
 }
 
-
 bool
-ObjectFileMachO::GetUUID (lldb_private::UUID* uuid)
+ObjectFileMachO::GetUUID (const llvm::MachO::mach_header &header,
+                          const lldb_private::DataExtractor &data,
+                          lldb::offset_t lc_offset,
+                          lldb_private::UUID& uuid)
 {
-    ModuleSP module_sp(GetModule());
-    if (module_sp)
+    uint32_t i;
+    struct uuid_command load_cmd;
+
+    lldb::offset_t offset = lc_offset;
+    for (i=0; i<header.ncmds; ++i)
     {
-        lldb_private::Mutex::Locker locker(module_sp->GetMutex());
-        struct uuid_command load_cmd;
-        uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
-        uint32_t i;
-        for (i=0; i<m_header.ncmds; ++i)
+        const lldb::offset_t cmd_offset = offset;
+        if (data.GetU32(&offset, &load_cmd, 2) == NULL)
+            break;
+        
+        if (load_cmd.cmd == LoadCommandUUID)
         {
-            const uint32_t cmd_offset = offset;
-            if (m_data.GetU32(&offset, &load_cmd, 2) == NULL)
-                break;
-
-            if (load_cmd.cmd == LoadCommandUUID)
+            const uint8_t *uuid_bytes = data.PeekData(offset, 16);
+            
+            if (uuid_bytes)
             {
-                const uint8_t *uuid_bytes = m_data.PeekData(offset, 16);
+                // OpenCL on Mac OS X uses the same UUID for each of its object files.
+                // We pretend these object files have no UUID to prevent crashing.
                 
-                if (uuid_bytes)
-                {
-                    // OpenCL on Mac OS X uses the same UUID for each of its object files.
-                    // We pretend these object files have no UUID to prevent crashing.
-                    
-                    const uint8_t opencl_uuid[] = { 0x8c, 0x8e, 0xb3, 0x9b,
-                                                    0x3b, 0xa8,
-                                                    0x4b, 0x16,
-                                                    0xb6, 0xa4,
-                                                    0x27, 0x63, 0xbb, 0x14, 0xf0, 0x0d };
-                    
-                    if (!memcmp(uuid_bytes, opencl_uuid, 16))
-                        return false;
-                    
-                    uuid->SetBytes (uuid_bytes);
-                    return true;
-                }
-                return false;
+                const uint8_t opencl_uuid[] = { 0x8c, 0x8e, 0xb3, 0x9b,
+                    0x3b, 0xa8,
+                    0x4b, 0x16,
+                    0xb6, 0xa4,
+                    0x27, 0x63, 0xbb, 0x14, 0xf0, 0x0d };
+                
+                if (!memcmp(uuid_bytes, opencl_uuid, 16))
+                    return false;
+                
+                uuid.SetBytes (uuid_bytes);
+                return true;
             }
-            offset = cmd_offset + load_cmd.cmdsize;
+            return false;
         }
+        offset = cmd_offset + load_cmd.cmdsize;
+    }
+    return false;
+}
+
+bool
+ObjectFileMachO::GetUUID (lldb_private::UUID* uuid)
+{
+    ModuleSP module_sp(GetModule());
+    if (module_sp)
+    {
+        lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+        lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
+        return GetUUID (m_header, m_data, offset, *uuid);
     }
     return false;
 }
@@ -3267,7 +3731,7 @@ ObjectFileMachO::GetDependentModules (Fi
     {
         lldb_private::Mutex::Locker locker(module_sp->GetMutex());
         struct load_command load_cmd;
-        uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
+        lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
         const bool resolve_path = false; // Don't resolve the dependend file paths since they may not reside on this system
         uint32_t i;
         for (i=0; i<m_header.ncmds; ++i)
@@ -3309,23 +3773,23 @@ ObjectFileMachO::GetDependentModules (Fi
 }
 
 lldb_private::Address
-ObjectFileMachO::GetEntryPointAddress () 
+ObjectFileMachO::GetEntryPointAddress ()
 {
     // If the object file is not an executable it can't hold the entry point.  m_entry_point_address
     // is initialized to an invalid address, so we can just return that.
     // If m_entry_point_address is valid it means we've found it already, so return the cached value.
-    
+
     if (!IsExecutable() || m_entry_point_address.IsValid())
         return m_entry_point_address;
-    
-    // Otherwise, look for the UnixThread or Thread command.  The data for the Thread command is given in 
+
+    // Otherwise, look for the UnixThread or Thread command.  The data for the Thread command is given in
     // /usr/include/mach-o.h, but it is basically:
     //
     //  uint32_t flavor  - this is the flavor argument you would pass to thread_get_state
     //  uint32_t count   - this is the count of longs in the thread state data
     //  struct XXX_thread_state state - this is the structure from <machine/thread_status.h> corresponding to the flavor.
     //  <repeat this trio>
-    // 
+    //
     // So we just keep reading the various register flavors till we find the GPR one, then read the PC out of there.
     // FIXME: We will need to have a "RegisterContext data provider" class at some point that can get all the registers
     // out of data in this form & attach them to a given thread.  That should underlie the MacOS X User process plugin,
@@ -3340,14 +3804,14 @@ ObjectFileMachO::GetEntryPointAddress ()
     {
         lldb_private::Mutex::Locker locker(module_sp->GetMutex());
         struct load_command load_cmd;
-        uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
+        lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
         uint32_t i;
         lldb::addr_t start_address = LLDB_INVALID_ADDRESS;
         bool done = false;
-        
+
         for (i=0; i<m_header.ncmds; ++i)
         {
-            const uint32_t cmd_offset = offset;
+            const lldb::offset_t cmd_offset = offset;
             if (m_data.GetU32(&offset, &load_cmd, 2) == NULL)
                 break;
 
@@ -3365,7 +3829,7 @@ ObjectFileMachO::GetEntryPointAddress ()
                             // We've gotten off somehow, log and exit;
                             return m_entry_point_address;
                         }
-                        
+
                         switch (m_header.cputype)
                         {
                         case llvm::MachO::CPUTypeARM:
@@ -3423,10 +3887,10 @@ ObjectFileMachO::GetEntryPointAddress ()
             // Go to the next load command:
             offset = cmd_offset + load_cmd.cmdsize;
         }
-        
+
         if (start_address != LLDB_INVALID_ADDRESS)
         {
-            // We got the start address from the load commands, so now resolve that address in the sections 
+            // We got the start address from the load commands, so now resolve that address in the sections
             // of this ObjectFile:
             if (!m_entry_point_address.ResolveAddressUsingFileSections (start_address, GetSectionList()))
             {
@@ -3437,9 +3901,9 @@ ObjectFileMachO::GetEntryPointAddress ()
         {
             // We couldn't read the UnixThread load command - maybe it wasn't there.  As a fallback look for the
             // "start" symbol in the main executable.
-            
+
             ModuleSP module_sp (GetModule());
-            
+
             if (module_sp)
             {
                 SymbolContextList contexts;
@@ -3452,7 +3916,7 @@ ObjectFileMachO::GetEntryPointAddress ()
             }
         }
     }
-    
+
     return m_entry_point_address;
 
 }
@@ -3484,7 +3948,7 @@ ObjectFileMachO::GetNumThreadContexts ()
         if (!m_thread_context_offsets_valid)
         {
             m_thread_context_offsets_valid = true;
-            uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
+            lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
             FileRangeArray::Entry file_range;
             thread_command thread_cmd;
             for (uint32_t i=0; i<m_header.ncmds; ++i)
@@ -3492,7 +3956,7 @@ ObjectFileMachO::GetNumThreadContexts ()
                 const uint32_t cmd_offset = offset;
                 if (m_data.GetU32(&offset, &thread_cmd, 2) == NULL)
                     break;
-                
+
                 if (thread_cmd.cmd == LoadCommandThread)
                 {
                     file_range.SetRangeBase (offset);
@@ -3519,24 +3983,27 @@ ObjectFileMachO::GetThreadContextAtIndex
             GetNumThreadContexts ();
 
         const FileRangeArray::Entry *thread_context_file_range = m_thread_context_offsets.GetEntryAtIndex (idx);
-        
-        DataExtractor data (m_data, 
-                            thread_context_file_range->GetRangeBase(), 
-                            thread_context_file_range->GetByteSize());
-
-        switch (m_header.cputype)
+        if (thread_context_file_range)
         {
-            case llvm::MachO::CPUTypeARM:
-                reg_ctx_sp.reset (new RegisterContextDarwin_arm_Mach (thread, data));
-                break;
-                
-            case llvm::MachO::CPUTypeI386:
-                reg_ctx_sp.reset (new RegisterContextDarwin_i386_Mach (thread, data));
-                break;
-                
-            case llvm::MachO::CPUTypeX86_64:
-                reg_ctx_sp.reset (new RegisterContextDarwin_x86_64_Mach (thread, data));
-                break;
+
+            DataExtractor data (m_data,
+                                thread_context_file_range->GetRangeBase(),
+                                thread_context_file_range->GetByteSize());
+
+            switch (m_header.cputype)
+            {
+                case llvm::MachO::CPUTypeARM:
+                    reg_ctx_sp.reset (new RegisterContextDarwin_arm_Mach (thread, data));
+                    break;
+
+                case llvm::MachO::CPUTypeI386:
+                    reg_ctx_sp.reset (new RegisterContextDarwin_i386_Mach (thread, data));
+                    break;
+
+                case llvm::MachO::CPUTypeX86_64:
+                    reg_ctx_sp.reset (new RegisterContextDarwin_x86_64_Mach (thread, data));
+                    break;
+            }
         }
     }
     return reg_ctx_sp;
@@ -3557,7 +4024,7 @@ ObjectFileMachO::CalculateType()
                 if (GetUUID(&uuid))
                 {
                     // this checking for the UUID load command is not enough
-                    // we could eventually look for the symbol named 
+                    // we could eventually look for the symbol named
                     // "OSKextGetCurrentIdentifier" as this is required of kexts
                     if (m_strata == eStrataInvalid)
                         m_strata = eStrataKernel;
@@ -3595,7 +4062,7 @@ ObjectFileMachO::CalculateStrata()
                 if (GetUUID(&uuid))
                 {
                     // this checking for the UUID load command is not enough
-                    // we could eventually look for the symbol named 
+                    // we could eventually look for the symbol named
                     // "OSKextGetCurrentIdentifier" as this is required of kexts
                     if (m_type == eTypeInvalid)
                         m_type = eTypeSharedLibrary;
@@ -3611,7 +4078,7 @@ ObjectFileMachO::CalculateStrata()
             {
                 return eStrataUser;
             }
-            else 
+            else
             {
                 SectionList *section_list = GetSectionList();
                 if (section_list)
@@ -3647,16 +4114,16 @@ ObjectFileMachO::GetVersion (uint32_t *v
     {
         lldb_private::Mutex::Locker locker(module_sp->GetMutex());
         struct dylib_command load_cmd;
-        uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
+        lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
         uint32_t version_cmd = 0;
         uint64_t version = 0;
         uint32_t i;
         for (i=0; i<m_header.ncmds; ++i)
         {
-            const uint32_t cmd_offset = offset;
+            const lldb::offset_t cmd_offset = offset;
             if (m_data.GetU32(&offset, &load_cmd, 2) == NULL)
                 break;
-            
+
             if (load_cmd.cmd == LoadCommandDylibIdent)
             {
                 if (version_cmd == 0)
@@ -3666,12 +4133,12 @@ ObjectFileMachO::GetVersion (uint32_t *v
                         break;
                     version = load_cmd.dylib.current_version;
                 }
-                break; // Break for now unless there is another more complete version 
+                break; // Break for now unless there is another more complete version
                        // number load command in the future.
             }
             offset = cmd_offset + load_cmd.cmdsize;
         }
-        
+
         if (version_cmd == LoadCommandDylibIdent)
         {
             if (versions != NULL && num_versions > 0)
@@ -3702,9 +4169,9 @@ ObjectFileMachO::GetArchitecture (ArchSp
     {
         lldb_private::Mutex::Locker locker(module_sp->GetMutex());
         arch.SetArchitecture (eArchTypeMachO, m_header.cputype, m_header.cpusubtype);
-    
+
         // Files with type MH_PRELOAD are currently used in cases where the image
-        // debugs at the addresses in the file itself. Below we set the OS to 
+        // debugs at the addresses in the file itself. Below we set the OS to
         // unknown to make sure we use the DynamicLoaderStatic()...
         if (m_header.filetype == HeaderFileTypePreloadedExecutable)
         {
@@ -3716,18 +4183,82 @@ ObjectFileMachO::GetArchitecture (ArchSp
 }
 
 
+UUID
+ObjectFileMachO::GetProcessSharedCacheUUID (Process *process)
+{
+    UUID uuid;
+    if (process)
+    {
+        addr_t all_image_infos = process->GetImageInfoAddress();
+
+        // The address returned by GetImageInfoAddress may be the address of dyld (don't want)
+        // or it may be the address of the dyld_all_image_infos structure (want).  The first four
+        // bytes will be either the version field (all_image_infos) or a Mach-O file magic constant.
+        // Version 13 and higher of dyld_all_image_infos is required to get the sharedCacheUUID field.
+
+        Error err;
+        uint32_t version_or_magic = process->ReadUnsignedIntegerFromMemory (all_image_infos, 4, -1, err);
+        if (version_or_magic != -1 
+            && version_or_magic != HeaderMagic32
+            && version_or_magic != HeaderMagic32Swapped
+            && version_or_magic != HeaderMagic64
+            && version_or_magic != HeaderMagic64Swapped
+            && version_or_magic >= 13)
+        {
+            addr_t sharedCacheUUID_address = LLDB_INVALID_ADDRESS;
+            int wordsize = process->GetAddressByteSize();
+            if (wordsize == 8)
+            {
+                sharedCacheUUID_address = all_image_infos + 160;  // sharedCacheUUID <mach-o/dyld_images.h>
+            }
+            if (wordsize == 4)
+            {
+                sharedCacheUUID_address = all_image_infos + 84;   // sharedCacheUUID <mach-o/dyld_images.h>
+            }
+            if (sharedCacheUUID_address != LLDB_INVALID_ADDRESS)
+            {
+                uuid_t shared_cache_uuid;
+                if (process->ReadMemory (sharedCacheUUID_address, shared_cache_uuid, sizeof (uuid_t), err) == sizeof (uuid_t))
+                {
+                    uuid.SetBytes (shared_cache_uuid);
+                }
+            }
+        }
+    }
+    return uuid;
+}
+
+UUID
+ObjectFileMachO::GetLLDBSharedCacheUUID ()
+{
+    UUID uuid;
+#if defined (__APPLE__) && defined (__arm__)
+    uint8_t *(*dyld_get_all_image_infos)(void);
+    dyld_get_all_image_infos = (uint8_t*(*)()) dlsym (RTLD_DEFAULT, "_dyld_get_all_image_infos");
+    if (dyld_get_all_image_infos)
+    {
+        uint8_t *dyld_all_image_infos_address = dyld_get_all_image_infos();
+        if (dyld_all_image_infos_address)
+        {
+            uint32_t *version = (uint32_t*) dyld_all_image_infos_address;              // version <mach-o/dyld_images.h>
+            if (*version >= 13)
+            {
+                uuid_t *sharedCacheUUID_address = (uuid_t*) ((uint8_t*) dyld_all_image_infos_address + 84);  // sharedCacheUUID <mach-o/dyld_images.h>
+                uuid.SetBytes (sharedCacheUUID_address);
+            }
+        }
+    }
+#endif
+    return uuid;
+}
+
+
 //------------------------------------------------------------------
 // PluginInterface protocol
 //------------------------------------------------------------------
-const char *
+lldb_private::ConstString
 ObjectFileMachO::GetPluginName()
 {
-    return "ObjectFileMachO";
-}
-
-const char *
-ObjectFileMachO::GetShortPluginName()
-{
     return GetPluginNameStatic();
 }
 

Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h Thu Jun  6 19:06:43 2013
@@ -35,7 +35,7 @@ public:
     static void
     Terminate();
 
-    static const char *
+    static lldb_private::ConstString
     GetPluginNameStatic();
 
     static const char *
@@ -43,10 +43,11 @@ public:
 
     static lldb_private::ObjectFile *
     CreateInstance (const lldb::ModuleSP &module_sp,
-                    lldb::DataBufferSP& dataSP,
+                    lldb::DataBufferSP& data_sp,
+                    lldb::offset_t data_offset,
                     const lldb_private::FileSpec* file,
-                    lldb::addr_t offset,
-                    lldb::addr_t length);
+                    lldb::offset_t file_offset,
+                    lldb::offset_t length);
 
     static lldb_private::ObjectFile *
     CreateMemoryInstance (const lldb::ModuleSP &module_sp, 
@@ -54,8 +55,16 @@ public:
                           const lldb::ProcessSP &process_sp, 
                           lldb::addr_t header_addr);
 
+    static size_t
+    GetModuleSpecifications (const lldb_private::FileSpec& file,
+                             lldb::DataBufferSP& data_sp,
+                             lldb::offset_t data_offset,
+                             lldb::offset_t file_offset,
+                             lldb::offset_t length,
+                             lldb_private::ModuleSpecList &specs);
+
     static bool
-    MagicBytesMatch (lldb::DataBufferSP& dataSP, 
+    MagicBytesMatch (lldb::DataBufferSP& data_sp,
                      lldb::addr_t offset, 
                      lldb::addr_t length);
 
@@ -63,13 +72,14 @@ public:
     // Member Functions
     //------------------------------------------------------------------
     ObjectFileMachO (const lldb::ModuleSP &module_sp,
-                     lldb::DataBufferSP& dataSP,
+                     lldb::DataBufferSP& data_sp,
+                     lldb::offset_t data_offset,
                      const lldb_private::FileSpec* file,
-                     lldb::addr_t offset,
-                     lldb::addr_t length);
+                     lldb::offset_t offset,
+                     lldb::offset_t length);
 
     ObjectFileMachO (const lldb::ModuleSP &module_sp,
-                     lldb::DataBufferSP& dataSP,
+                     lldb::DataBufferSP& data_sp,
                      const lldb::ProcessSP &process_sp,
                      lldb::addr_t header_addr);
 
@@ -85,7 +95,7 @@ public:
     virtual bool
     IsExecutable () const;
 
-    virtual size_t
+    virtual uint32_t
     GetAddressByteSize ()  const;
 
     virtual lldb::AddressClass
@@ -112,12 +122,9 @@ public:
     //------------------------------------------------------------------
     // PluginInterface protocol
     //------------------------------------------------------------------
-    virtual const char *
+    virtual lldb_private::ConstString
     GetPluginName();
 
-    virtual const char *
-    GetShortPluginName();
-
     virtual uint32_t
     GetPluginVersion();
 
@@ -143,9 +150,36 @@ public:
     GetVersion (uint32_t *versions, uint32_t num_versions);
 
 protected:
+
+    static bool
+    ParseHeader (lldb_private::DataExtractor &data,
+                 lldb::offset_t *data_offset_ptr,
+                 llvm::MachO::mach_header &header);
+    
+    
+    static bool
+    GetUUID (const llvm::MachO::mach_header &header,
+             const lldb_private::DataExtractor &data,
+             lldb::offset_t lc_offset, // Offset to the first load command
+             lldb_private::UUID& uuid);
+    
+    // Intended for same-host arm device debugging where lldb needs to
+    // detect libraries in the shared cache and augment the nlist entries
+    // with an on-disk dyld_shared_cache file.  The process will record
+    // the shared cache UUID so the on-disk cache can be matched or rejected
+    // correctly.
+    lldb_private::UUID
+    GetProcessSharedCacheUUID (lldb_private::Process *);
+
+    // Intended for same-host arm device debugging where lldb will read
+    // shared cache libraries out of its own memory instead of the remote
+    // process' memory as an optimization.  If lldb's shared cache UUID 
+    // does not match the process' shared cache UUID, this optimization
+    // should not be used.
+    lldb_private::UUID
+    GetLLDBSharedCacheUUID ();
+
     llvm::MachO::mach_header m_header;
-    mutable std::auto_ptr<lldb_private::SectionList> m_sections_ap;
-    mutable std::auto_ptr<lldb_private::Symtab> m_symtab_ap;
     static const lldb_private::ConstString &GetSegmentNameTEXT();
     static const lldb_private::ConstString &GetSegmentNameDATA();
     static const lldb_private::ConstString &GetSegmentNameOBJC();
@@ -155,7 +189,7 @@ protected:
     llvm::MachO::dysymtab_command m_dysymtab;
     std::vector<llvm::MachO::segment_command_64> m_mach_segments;
     std::vector<llvm::MachO::section_64> m_mach_sections;
-    typedef lldb_private::RangeArray<uint32_t, uint32_t, 1> FileRangeArray;
+    typedef lldb_private::RangeVector<uint32_t, uint32_t> FileRangeArray;
     lldb_private::Address  m_entry_point_address;
     FileRangeArray m_thread_context_offsets;
     bool m_thread_context_offsets_valid;

Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp Thu Jun  6 19:06:43 2013
@@ -16,6 +16,7 @@
 #include "lldb/Host/FileSpec.h"
 #include "lldb/Core/FileSpecList.h"
 #include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/Section.h"
 #include "lldb/Core/StreamFile.h"
@@ -121,7 +122,8 @@ ObjectFilePECOFF::Initialize()
     PluginManager::RegisterPlugin (GetPluginNameStatic(),
                                    GetPluginDescriptionStatic(),
                                    CreateInstance,
-                                   CreateMemoryInstance);
+                                   CreateMemoryInstance,
+                                   GetModuleSpecifications);
 }
 
 void
@@ -131,10 +133,11 @@ ObjectFilePECOFF::Terminate()
 }
 
 
-const char *
+lldb_private::ConstString
 ObjectFilePECOFF::GetPluginNameStatic()
 {
-    return "object-file.pe-coff";
+    static ConstString g_name("pe-coff");
+    return g_name;
 }
 
 const char *
@@ -145,11 +148,25 @@ ObjectFilePECOFF::GetPluginDescriptionSt
 
 
 ObjectFile *
-ObjectFilePECOFF::CreateInstance (const lldb::ModuleSP &module_sp, DataBufferSP& dataSP, const FileSpec* file, addr_t offset, addr_t length)
+ObjectFilePECOFF::CreateInstance (const lldb::ModuleSP &module_sp,
+                                  DataBufferSP& data_sp,
+                                  lldb::offset_t data_offset,
+                                  const lldb_private::FileSpec* file,
+                                  lldb::offset_t file_offset,
+                                  lldb::offset_t length)
 {
-    if (ObjectFilePECOFF::MagicBytesMatch(dataSP))
+    if (!data_sp)
     {
-        std::auto_ptr<ObjectFile> objfile_ap(new ObjectFilePECOFF (module_sp, dataSP, file, offset, length));
+        data_sp = file->MemoryMapFileContents(file_offset, length);
+        data_offset = 0;
+    }
+
+    if (ObjectFilePECOFF::MagicBytesMatch(data_sp))
+    {
+        // Update the data to contain the entire file if it doesn't already
+        if (data_sp->GetByteSize() < length)
+            data_sp = file->MemoryMapFileContents(file_offset, length);
+        std::unique_ptr<ObjectFile> objfile_ap(new ObjectFilePECOFF (module_sp, data_sp, data_offset, file, file_offset, length));
         if (objfile_ap.get() && objfile_ap->ParseHeader())
             return objfile_ap.release();
     }
@@ -165,22 +182,35 @@ ObjectFilePECOFF::CreateMemoryInstance (
     return NULL;
 }
 
+size_t
+ObjectFilePECOFF::GetModuleSpecifications (const lldb_private::FileSpec& file,
+                                           lldb::DataBufferSP& data_sp,
+                                           lldb::offset_t data_offset,
+                                           lldb::offset_t file_offset,
+                                           lldb::offset_t length,
+                                           lldb_private::ModuleSpecList &specs)
+{
+    return 0;
+}
+
+
 bool
-ObjectFilePECOFF::MagicBytesMatch (DataBufferSP& dataSP)
+ObjectFilePECOFF::MagicBytesMatch (DataBufferSP& data_sp)
 {
-    DataExtractor data(dataSP, eByteOrderLittle, 4);
-    uint32_t offset = 0;
+    DataExtractor data(data_sp, eByteOrderLittle, 4);
+    lldb::offset_t offset = 0;
     uint16_t magic = data.GetU16 (&offset);
     return magic == IMAGE_DOS_SIGNATURE;
 }
 
 
 ObjectFilePECOFF::ObjectFilePECOFF (const lldb::ModuleSP &module_sp, 
-                                    DataBufferSP& dataSP, 
+                                    DataBufferSP& data_sp,
+                                    lldb::offset_t data_offset,
                                     const FileSpec* file, 
-                                    addr_t offset, 
-                                    addr_t length) :
-    ObjectFile (module_sp, file, offset, length, dataSP),
+                                    lldb::offset_t file_offset,
+                                    lldb::offset_t length) :
+    ObjectFile (module_sp, file, file_offset, length, data_sp, data_offset),
     m_dos_header (),
     m_coff_header (),
     m_coff_header_opt (),
@@ -206,7 +236,7 @@ ObjectFilePECOFF::ParseHeader ()
         lldb_private::Mutex::Locker locker(module_sp->GetMutex());
         m_sect_headers.clear();
         m_data.SetByteOrder (eByteOrderLittle);
-        uint32_t offset = 0;
+        lldb::offset_t offset = 0;
         
         if (ParseDOSHeader())
         {
@@ -220,8 +250,6 @@ ObjectFilePECOFF::ParseHeader ()
                     ParseCOFFOptionalHeader(&offset);
                 ParseSectionHeaders (offset);
             }
-            StreamFile s(stdout, false);// REMOVE THIS LINE!!!
-            Dump(&s);// REMOVE THIS LINE!!!
             return true;
         }
     }
@@ -241,7 +269,7 @@ ObjectFilePECOFF::IsExecutable() const
     return (m_coff_header.flags & IMAGE_FILE_DLL) == 0;
 }
 
-size_t
+uint32_t
 ObjectFilePECOFF::GetAddressByteSize () const
 {
     if (m_coff_header_opt.magic == OPT_HEADER_MAGIC_PE32_PLUS)
@@ -273,7 +301,7 @@ bool
 ObjectFilePECOFF::ParseDOSHeader ()
 {
     bool success = false;
-    uint32_t offset = 0;
+    lldb::offset_t offset = 0;
     success = m_data.ValidOffsetForDataOfSize(0, sizeof(m_dos_header));
     
     if (success)
@@ -328,7 +356,7 @@ ObjectFilePECOFF::ParseDOSHeader ()
 // ParserCOFFHeader
 //----------------------------------------------------------------------
 bool
-ObjectFilePECOFF::ParseCOFFHeader(uint32_t* offset_ptr)
+ObjectFilePECOFF::ParseCOFFHeader(lldb::offset_t *offset_ptr)
 {
     bool success = m_data.ValidOffsetForDataOfSize (*offset_ptr, sizeof(m_coff_header));
     if (success)
@@ -347,10 +375,10 @@ ObjectFilePECOFF::ParseCOFFHeader(uint32
 }
 
 bool
-ObjectFilePECOFF::ParseCOFFOptionalHeader(uint32_t* offset_ptr)
+ObjectFilePECOFF::ParseCOFFOptionalHeader(lldb::offset_t *offset_ptr)
 {
     bool success = false;
-    const uint32_t end_offset = *offset_ptr + m_coff_header.hdrsize;
+    const lldb::offset_t end_offset = *offset_ptr + m_coff_header.hdrsize;
     if (*offset_ptr < end_offset)
     {
         success = true;
@@ -431,7 +459,7 @@ ObjectFilePECOFF::ParseSectionHeaders (u
         DataBufferSP section_header_data_sp(m_file.ReadFileContents (section_header_data_offset, section_header_byte_size));
         DataExtractor section_header_data (section_header_data_sp, GetByteOrder(), addr_byte_size);
 
-        uint32_t offset = 0;
+        lldb::offset_t offset = 0;
         if (section_header_data.ValidOffsetForDataOfSize (offset, section_header_byte_size))
         {
             m_sect_headers.resize(nsects);
@@ -464,8 +492,8 @@ ObjectFilePECOFF::GetSectionName(std::st
 {
     if (sect.name[0] == '/')
     {
-        uint32_t stroff = strtoul(&sect.name[1], NULL, 10);
-        uint32_t string_file_offset = m_coff_header.symoff + (m_coff_header.nsyms * 18) + stroff;
+        lldb::offset_t stroff = strtoul(&sect.name[1], NULL, 10);
+        lldb::offset_t string_file_offset = m_coff_header.symoff + (m_coff_header.nsyms * 18) + stroff;
         const char *name = m_data.GetCStr (&string_file_offset);
         if (name)
         {
@@ -505,7 +533,7 @@ ObjectFilePECOFF::GetSymtab()
                 // Include the 4 bytes string table size at the end of the symbols
                 DataBufferSP symtab_data_sp(m_file.ReadFileContents (m_coff_header.symoff, symbol_data_size + 4));
                 DataExtractor symtab_data (symtab_data_sp, GetByteOrder(), addr_byte_size);
-                uint32_t offset = symbol_data_size;
+                lldb::offset_t offset = symbol_data_size;
                 const uint32_t strtab_size = symtab_data.GetU32 (&offset);
                 DataBufferSP strtab_data_sp(m_file.ReadFileContents (m_coff_header.symoff + symbol_data_size + 4, strtab_size));
                 DataExtractor strtab_data (strtab_data_sp, GetByteOrder(), addr_byte_size);
@@ -789,7 +817,7 @@ ObjectFilePECOFF::DumpOptCOFFHeader(Stre
     s->Printf ("  entry                   = 0x%8.8x\n", header.entry);
     s->Printf ("  code_offset             = 0x%8.8x\n", header.code_offset);
     s->Printf ("  data_offset             = 0x%8.8x\n", header.data_offset);
-    s->Printf ("  image_base              = 0x%16.16llx\n", header.image_base);
+    s->Printf ("  image_base              = 0x%16.16" PRIx64 "\n", header.image_base);
     s->Printf ("  sect_alignment          = 0x%8.8x\n", header.sect_alignment);
     s->Printf ("  file_alignment          = 0x%8.8x\n", header.file_alignment);
     s->Printf ("  major_os_system_version = 0x%4.4x\n", header.major_os_system_version);
@@ -804,10 +832,10 @@ ObjectFilePECOFF::DumpOptCOFFHeader(Stre
     s->Printf ("  checksum                = 0x%8.8x\n", header.checksum);
     s->Printf ("  subsystem               = 0x%4.4x\n", header.subsystem);
     s->Printf ("  dll_flags               = 0x%4.4x\n", header.dll_flags);
-    s->Printf ("  stack_reserve_size      = 0x%16.16llx\n", header.stack_reserve_size);
-    s->Printf ("  stack_commit_size       = 0x%16.16llx\n", header.stack_commit_size);
-    s->Printf ("  heap_reserve_size       = 0x%16.16llx\n", header.heap_reserve_size);
-    s->Printf ("  heap_commit_size        = 0x%16.16llx\n", header.heap_commit_size);
+    s->Printf ("  stack_reserve_size      = 0x%16.16" PRIx64 "\n", header.stack_reserve_size);
+    s->Printf ("  stack_commit_size       = 0x%16.16" PRIx64 "\n", header.stack_commit_size);
+    s->Printf ("  heap_reserve_size       = 0x%16.16" PRIx64 "\n", header.heap_reserve_size);
+    s->Printf ("  heap_commit_size        = 0x%16.16" PRIx64 "\n", header.heap_commit_size);
     s->Printf ("  loader_flags            = 0x%8.8x\n", header.loader_flags);
     s->Printf ("  num_data_dir_entries    = 0x%8.8zx\n", header.data_dirs.size());
     uint32_t i;
@@ -927,15 +955,9 @@ ObjectFilePECOFF::CalculateStrata()
 //------------------------------------------------------------------
 // PluginInterface protocol
 //------------------------------------------------------------------
-const char *
+ConstString
 ObjectFilePECOFF::GetPluginName()
 {
-    return "ObjectFilePECOFF";
-}
-
-const char *
-ObjectFilePECOFF::GetShortPluginName()
-{
     return GetPluginNameStatic();
 }
 

Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h Thu Jun  6 19:06:43 2013
@@ -28,7 +28,7 @@ public:
     static void
     Terminate();
     
-    static const char *
+    static lldb_private::ConstString
     GetPluginNameStatic();
     
     static const char *
@@ -36,25 +36,36 @@ public:
     
     static ObjectFile *
     CreateInstance (const lldb::ModuleSP &module_sp,
-                    lldb::DataBufferSP& dataSP,
+                    lldb::DataBufferSP& data_sp,
+                    lldb::offset_t data_offset,
                     const lldb_private::FileSpec* file,
-                    lldb::addr_t offset,
-                    lldb::addr_t length);
+                    lldb::offset_t offset,
+                    lldb::offset_t length);
     
     static lldb_private::ObjectFile *
     CreateMemoryInstance (const lldb::ModuleSP &module_sp, 
                           lldb::DataBufferSP& data_sp, 
                           const lldb::ProcessSP &process_sp, 
                           lldb::addr_t header_addr);
+    
+    static size_t
+    GetModuleSpecifications (const lldb_private::FileSpec& file,
+                             lldb::DataBufferSP& data_sp,
+                             lldb::offset_t data_offset,
+                             lldb::offset_t file_offset,
+                             lldb::offset_t length,
+                             lldb_private::ModuleSpecList &specs);
+
     static bool
-    MagicBytesMatch (lldb::DataBufferSP& dataSP);
+    MagicBytesMatch (lldb::DataBufferSP& data_sp);
     
     
     ObjectFilePECOFF (const lldb::ModuleSP &module_sp,
-                      lldb::DataBufferSP& dataSP,
+                      lldb::DataBufferSP& data_sp,
+                      lldb::offset_t data_offset,
                       const lldb_private::FileSpec* file,
-                      lldb::addr_t offset,
-                      lldb::addr_t length);
+                      lldb::offset_t file_offset,
+                      lldb::offset_t length);
     
 	virtual 
     ~ObjectFilePECOFF();
@@ -68,7 +79,7 @@ public:
     virtual bool
     IsExecutable () const;
     
-    virtual size_t
+    virtual uint32_t
     GetAddressByteSize ()  const;
     
 //    virtual lldb_private::AddressClass
@@ -95,12 +106,9 @@ public:
     //------------------------------------------------------------------
     // PluginInterface protocol
     //------------------------------------------------------------------
-    virtual const char *
+    virtual lldb_private::ConstString
     GetPluginName();
     
-    virtual const char *
-    GetShortPluginName();
-    
     virtual uint32_t
     GetPluginVersion();
 //    
@@ -212,8 +220,8 @@ protected:
 	} coff_symbol_t;
     
 	bool ParseDOSHeader ();
-	bool ParseCOFFHeader (uint32_t* offset_ptr);
-	bool ParseCOFFOptionalHeader (uint32_t* offset_ptr);
+	bool ParseCOFFHeader (lldb::offset_t *offset_ptr);
+	bool ParseCOFFOptionalHeader (lldb::offset_t *offset_ptr);
 	bool ParseSectionHeaders (uint32_t offset);
 	
 	static	void DumpDOSHeader(lldb_private::Stream *s, const dos_header_t& header);
@@ -227,8 +235,6 @@ protected:
 	typedef SectionHeaderColl::iterator			SectionHeaderCollIter;
 	typedef SectionHeaderColl::const_iterator	SectionHeaderCollConstIter;
 private:
-    mutable std::auto_ptr<lldb_private::SectionList> m_sections_ap;
-    mutable std::auto_ptr<lldb_private::Symtab> m_symtab_ap;
 	dos_header_t		m_dos_header;
 	coff_header_t		m_coff_header;
 	coff_opt_header_t	m_coff_header_opt;

Copied: lldb/branches/lldb-platform-work/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp (from r182522, lldb/trunk/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp)
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp?p2=lldb/branches/lldb-platform-work/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp&p1=lldb/trunk/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp&r1=182522&r2=183468&rev=183468&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp Thu Jun  6 19:06:43 2013
@@ -21,6 +21,7 @@
 #include "lldb/Core/Module.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/StreamString.h"
 #include "lldb/Core/ValueObjectVariable.h"
 #include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Interpreter/PythonDataObjects.h"
@@ -134,7 +135,7 @@ OperatingSystemPython::GetDynamicRegiste
     {
         if (!m_interpreter || !m_python_object_sp)
             return NULL;
-        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OS));
         
         if (log)
             log->Printf ("OperatingSystemPython::GetDynamicRegisterInfo() fetching thread register definitions from python for pid %" PRIu64, m_process->GetID());
@@ -173,7 +174,7 @@ OperatingSystemPython::UpdateThreadList
     if (!m_interpreter || !m_python_object_sp)
         return false;
     
-    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OS));
     
     // First thing we have to do is get the API lock, and the run lock.  We're going to change the thread
     // content of the process, and we're going to use python, which requires the API lock to do it.
@@ -191,6 +192,12 @@ OperatingSystemPython::UpdateThreadList
     PythonList threads_list(m_interpreter->OSPlugin_ThreadsInfo(m_python_object_sp));
     if (threads_list)
     {
+        if (log)
+        {
+            StreamString strm;
+            threads_list.Dump(strm);
+            log->Printf("threads_list = %s", strm.GetString().c_str());
+        }
         uint32_t i;
         const uint32_t num_threads = threads_list.GetSize();
         if (num_threads > 0)
@@ -200,21 +207,6 @@ OperatingSystemPython::UpdateThreadList
                 PythonDictionary thread_dict(threads_list.GetItemAtIndex(i));
                 if (thread_dict)
                 {
-                    if (thread_dict.GetItemForKey("core"))
-                    {
-                        // We have some threads that are saying they are on a "core", which means
-                        // they map the threads that are gotten from the lldb_private::Process subclass
-                        // so clear the new threads list so the core threads don't show up
-                        new_thread_list.Clear();
-                        break;
-                    }
-                }
-            }
-            for (i=0; i<num_threads; ++i)
-            {
-                PythonDictionary thread_dict(threads_list.GetItemAtIndex(i));
-                if (thread_dict)
-                {
                     ThreadSP thread_sp (CreateThreadFromThreadInfo (thread_dict, core_thread_list, old_thread_list, NULL));
                     if (thread_sp)
                         new_thread_list.AddThread(thread_sp);
@@ -223,8 +215,10 @@ OperatingSystemPython::UpdateThreadList
         }
     }
     
+    // No new threads added from the thread info array gotten from python, just
+    // display the core threads.
     if (new_thread_list.GetSize(false) == 0)
-        new_thread_list = old_thread_list;
+        new_thread_list = core_thread_list;
 
     return new_thread_list.GetSize(false) > 0;
 }

Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp Thu Jun  6 19:06:43 2013
@@ -7,6 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "lldb/lldb-python.h"
+
 #include "PlatformFreeBSD.h"
 
 // C Includes
@@ -18,6 +20,8 @@
 // Project includes
 #include "lldb/Core/Error.h"
 #include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Host/Host.h"
 
@@ -41,10 +45,14 @@ PlatformFreeBSD::CreateInstance (bool fo
                 create = true;
                 break;
                 
+#if defined(__FreeBSD__) || defined(__OpenBSD__)
+            // Only accept "unknown" for the vendor if the host is BSD and
+            // it "unknown" wasn't specified (it was just returned becasue it
+            // was NOT specified)
             case llvm::Triple::UnknownArch:
                 create = !arch->TripleVendorWasSpecified();
                 break;
-                
+#endif
             default:
                 break;
         }
@@ -57,10 +65,14 @@ PlatformFreeBSD::CreateInstance (bool fo
                 case llvm::Triple::KFreeBSD:
                     break;
                     
+#if defined(__FreeBSD__) || defined(__OpenBSD__)
+                // Only accept "unknown" for the OS if the host is BSD and
+                // it "unknown" wasn't specified (it was just returned becasue it
+                // was NOT specified)
                 case llvm::Triple::UnknownOS:
                     create = arch->TripleOSWasSpecified();
                     break;
-                    
+#endif
                 default:
                     create = false;
                     break;
@@ -73,19 +85,19 @@ PlatformFreeBSD::CreateInstance (bool fo
 
 }
 
-const char *
-PlatformFreeBSD::GetPluginNameStatic()
-{
-    return "plugin.platform.freebsd";
-}
-
-const char *
-PlatformFreeBSD::GetShortPluginNameStatic (bool is_host)
+lldb_private::ConstString
+PlatformFreeBSD::GetPluginNameStatic (bool is_host)
 {
     if (is_host)
-        return Platform::GetHostPlatformName ();
+    {
+        static ConstString g_host_name(Platform::GetHostPlatformName ());
+        return g_host_name;
+    }
     else
-        return "remote-freebsd";
+    {
+        static ConstString g_remote_name("remote-freebsd");
+        return g_remote_name;
+    }
 }
 
 const char *
@@ -110,7 +122,7 @@ PlatformFreeBSD::Initialize ()
         default_platform_sp->SetSystemArchitecture (Host::GetArchitecture());
         Platform::SetDefaultPlatform (default_platform_sp);
 #endif
-        PluginManager::RegisterPlugin(PlatformFreeBSD::GetShortPluginNameStatic(false),
+        PluginManager::RegisterPlugin(PlatformFreeBSD::GetPluginNameStatic(false),
                                       PlatformFreeBSD::GetDescriptionStatic(false),
                                       PlatformFreeBSD::CreateInstance);
     }
@@ -168,23 +180,128 @@ PlatformFreeBSD::ResolveExecutable (cons
                                     lldb::ModuleSP &exe_module_sp,
                                     const FileSpecList *module_search_paths_ptr)
 {
+    Error error;
     // Nothing special to do here, just use the actual file and architecture
-
-    if (lldb_private::IsLogVerbose())
+    
+    char exe_path[PATH_MAX];
+    FileSpec resolved_exe_file (exe_file);
+    
+    if (IsHost())
     {
-        LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_VERBOSE));
-        log->Printf("Resolve executable '%s/%s'", exe_file.GetDirectory().AsCString(), exe_file.GetFilename().AsCString());
-        log->Printf("Resolve executable arch '%s'", exe_arch.GetArchitectureName());
+        // If we have "ls" as the exe_file, resolve the executable loation based on
+        // the current path variables
+        if (!resolved_exe_file.Exists())
+        {
+            exe_file.GetPath(exe_path, sizeof(exe_path));
+            resolved_exe_file.SetFile(exe_path, true);
         }
-
-    if (IsRemote() && m_remote_platform_sp)
-        return m_remote_platform_sp->ResolveExecutable (exe_file,
+        
+        if (!resolved_exe_file.Exists())
+            resolved_exe_file.ResolveExecutableLocation ();
+        
+        // Resolve any executable within a bundle on MacOSX
+        //Host::ResolveExecutableInBundle (resolved_exe_file);
+        
+        if (resolved_exe_file.Exists())
+            error.Clear();
+        else
+        {
+            exe_file.GetPath(exe_path, sizeof(exe_path));
+            error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path);
+        }
+    }
+    else
+    {
+        if (m_remote_platform_sp)
+        {
+            error = m_remote_platform_sp->ResolveExecutable (exe_file,
                                                              exe_arch,
                                                              exe_module_sp,
                                                              module_search_paths_ptr);
+        }
+        else
+        {
+            // We may connect to a process and use the provided executable (Don't use local $PATH).
+            
+            // Resolve any executable within a bundle on MacOSX
+            Host::ResolveExecutableInBundle (resolved_exe_file);
+            
+            if (resolved_exe_file.Exists()) {
+                error.Clear();
+            }
+            else
+            {
+                exe_file.GetPath(exe_path, sizeof(exe_path));
+                error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path);
+            }
+        }
+    }
+    
+    
+    if (error.Success())
+    {
+        ModuleSpec module_spec (resolved_exe_file, exe_arch);
+        if (module_spec.GetArchitecture().IsValid())
+        {
+            error = ModuleList::GetSharedModule (module_spec,
+                                                 exe_module_sp,
+                                                 module_search_paths_ptr,
+                                                 NULL,
+                                                 NULL);
             
-    return Platform::ResolveExecutable(exe_file, exe_arch, exe_module_sp, module_search_paths_ptr);
+            if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
+            {
+                exe_module_sp.reset();
+                error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
+                                                exe_file.GetPath().c_str(),
+                                                exe_arch.GetArchitectureName());
             }
+        }
+        else
+        {
+            // No valid architecture was specified, ask the platform for
+            // the architectures that we should be using (in the correct order)
+            // and see if we can find a match that way
+            StreamString arch_names;
+            ArchSpec platform_arch;
+            for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
+            {
+                error = ModuleList::GetSharedModule (module_spec,
+                                                     exe_module_sp,
+                                                     module_search_paths_ptr,
+                                                     NULL,
+                                                     NULL);
+                // Did we find an executable using one of the
+                if (error.Success())
+                {
+                    if (exe_module_sp && exe_module_sp->GetObjectFile())
+                        break;
+                    else
+                        error.SetErrorToGenericError();
+                }
+                
+                if (idx > 0)
+                    arch_names.PutCString (", ");
+                arch_names.PutCString (platform_arch.GetArchitectureName());
+            }
+            
+            if (error.Fail() || !exe_module_sp)
+            {
+                error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+                                                exe_file.GetPath().c_str(),
+                                                GetPluginName().GetCString(),
+                                                arch_names.GetString().c_str());
+            }
+        }
+    }
+    else
+    {
+        error.SetErrorStringWithFormat ("'%s' does not exist",
+                                        exe_file.GetPath().c_str());
+    }
+    
+    return error;
+}
 
 size_t
 PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
@@ -280,7 +397,7 @@ PlatformFreeBSD::ConnectRemote (Args& ar
     Error error;
     if (IsHost())
     {
-        error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetShortPluginName());
+        error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
     }
     else
     {
@@ -318,7 +435,7 @@ PlatformFreeBSD::DisconnectRemote ()
 
     if (IsHost())
     {
-        error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetShortPluginName());
+        error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString());
     }
     else
     {
@@ -397,11 +514,10 @@ PlatformFreeBSD::Attach(ProcessAttachInf
         if (target == NULL)
         {
             TargetSP new_target_sp;
-            FileSpec emptyFileSpec;
             ArchSpec emptyArchSpec;
 
             error = debugger.GetTargetList().CreateTarget (debugger,
-                                                           emptyFileSpec,
+                                                           NULL,
                                                            emptyArchSpec,
                                                            false,
                                                            m_remote_platform_sp,
@@ -528,7 +644,7 @@ PlatformFreeBSD::GetSupportedArchitectur
     {
         ArchSpec platform_arch (Host::GetArchitecture (Host::eSystemDefaultArchitecture));
         ArchSpec platform_arch64 (Host::GetArchitecture (Host::eSystemDefaultArchitecture64));
-        if (platform_arch == platform_arch64)
+        if (platform_arch.IsExactMatch(platform_arch64))
         {
             // This freebsd platform supports both 32 and 64 bit. Since we already
             // returned the 64 bit arch for idx == 0, return the 32 bit arch

Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h Thu Jun  6 19:06:43 2013
@@ -33,14 +33,11 @@ public:
     static void
     Terminate ();
 
-    static const char *
-    GetPluginNameStatic();
-
-    static const char *
-    GetShortPluginNameStatic(bool is_host);
+    static lldb_private::ConstString
+    GetPluginNameStatic (bool is_host);
 
     static const char *
-    GetDescriptionStatic(bool is_host);
+    GetDescriptionStatic (bool is_host);
 
     //------------------------------------------------------------
     // Class Methods
@@ -53,16 +50,10 @@ public:
     //------------------------------------------------------------
     // lldb_private::PluginInterface functions
     //------------------------------------------------------------
-    virtual const char *
+    virtual lldb_private::ConstString
     GetPluginName()
     {
-        return GetPluginNameStatic();
-    }
-
-    virtual const char *
-    GetShortPluginName()
-    {
-        return GetShortPluginNameStatic (IsHost());
+        return GetPluginNameStatic (IsHost());
     }
 
     virtual uint32_t

Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/Linux/PlatformLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/Linux/PlatformLinux.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/Linux/PlatformLinux.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/Linux/PlatformLinux.cpp Thu Jun  6 19:06:43 2013
@@ -7,6 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "lldb/lldb-python.h"
+
 #include "PlatformLinux.h"
 
 // C Includes
@@ -20,6 +22,7 @@
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/StreamString.h"
 #include "lldb/Host/FileSpec.h"
@@ -45,10 +48,14 @@ PlatformLinux::CreateInstance (bool forc
                 create = true;
                 break;
                 
+#if defined(__linux__)
+            // Only accept "unknown" for the vendor if the host is linux and
+            // it "unknown" wasn't specified (it was just returned becasue it
+            // was NOT specified_
             case llvm::Triple::UnknownArch:
                 create = !arch->TripleVendorWasSpecified();
                 break;
-                
+#endif
             default:
                 break;
         }
@@ -60,10 +67,14 @@ PlatformLinux::CreateInstance (bool forc
                 case llvm::Triple::Linux:
                     break;
                     
+#if defined(__linux__)
+                // Only accept "unknown" for the OS if the host is linux and
+                // it "unknown" wasn't specified (it was just returned becasue it
+                // was NOT specified)
                 case llvm::Triple::UnknownOS:
                     create = !arch->TripleOSWasSpecified();
                     break;
-                    
+#endif
                 default:
                     create = false;
                     break;
@@ -75,19 +86,20 @@ PlatformLinux::CreateInstance (bool forc
     return NULL;
 }
 
-const char *
-PlatformLinux::GetPluginNameStatic()
-{
-    return "plugin.platform.linux";
-}
 
-const char *
-PlatformLinux::GetShortPluginNameStatic (bool is_host)
+lldb_private::ConstString
+PlatformLinux::GetPluginNameStatic (bool is_host)
 {
     if (is_host)
-        return Platform::GetHostPlatformName ();
+    {
+        static ConstString g_host_name(Platform::GetHostPlatformName ());
+        return g_host_name;
+    }
     else
-        return "remote-linux";
+    {
+        static ConstString g_remote_name("remote-linux");
+        return g_remote_name;
+    }
 }
 
 const char *
@@ -99,6 +111,12 @@ PlatformLinux::GetPluginDescriptionStati
         return "Remote Linux user platform plug-in.";
 }
 
+lldb_private::ConstString
+PlatformLinux::GetPluginName()
+{
+    return GetPluginNameStatic(IsHost());
+}
+
 void
 PlatformLinux::Initialize ()
 {
@@ -109,7 +127,7 @@ PlatformLinux::Initialize ()
         default_platform_sp->SetSystemArchitecture (Host::GetArchitecture());
         Platform::SetDefaultPlatform (default_platform_sp);
 #endif
-        PluginManager::RegisterPlugin(PlatformLinux::GetShortPluginNameStatic(false),
+        PluginManager::RegisterPlugin(PlatformLinux::GetPluginNameStatic(false),
                                       PlatformLinux::GetPluginDescriptionStatic(false),
                                       PlatformLinux::CreateInstance);
     }
@@ -190,14 +208,36 @@ PlatformLinux::ResolveExecutable (const
                                                  NULL, 
                                                  NULL,
                                                  NULL);
+            if (error.Fail())
+            {
+                // If we failed, it may be because the vendor and os aren't known. If that is the
+                // case, try setting them to the host architecture and give it another try.
+                llvm::Triple &module_triple = module_spec.GetArchitecture().GetTriple(); 
+                bool is_vendor_specified = (module_triple.getVendor() != llvm::Triple::UnknownVendor);
+                bool is_os_specified = (module_triple.getOS() != llvm::Triple::UnknownOS);
+                if (!is_vendor_specified || !is_os_specified)
+                {
+                    const llvm::Triple &host_triple = Host::GetArchitecture (Host::eSystemDefaultArchitecture).GetTriple();
+
+                    if (!is_vendor_specified)
+                        module_triple.setVendorName (host_triple.getVendorName());
+                    if (!is_os_specified)
+                        module_triple.setOSName (host_triple.getOSName());
+
+                    error = ModuleList::GetSharedModule (module_spec, 
+                                                         exe_module_sp, 
+                                                         NULL, 
+                                                         NULL,
+                                                         NULL);
+                }
+            }
         
-            if (exe_module_sp->GetObjectFile() == NULL)
+            // TODO find out why exe_module_sp might be NULL            
+            if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
             {
                 exe_module_sp.reset();
-                error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain the architecture %s",
-                                                exe_file.GetDirectory().AsCString(""),
-                                                exe_file.GetDirectory() ? "/" : "",
-                                                exe_file.GetFilename().AsCString(""),
+                error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
+                                                exe_file.GetPath().c_str(),
                                                 exe_arch.GetArchitectureName());
             }
         }
@@ -230,11 +270,9 @@ PlatformLinux::ResolveExecutable (const
             
             if (error.Fail() || !exe_module_sp)
             {
-                error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain any '%s' platform architectures: %s",
-                                                exe_file.GetDirectory().AsCString(""),
-                                                exe_file.GetDirectory() ? "/" : "",
-                                                exe_file.GetFilename().AsCString(""),
-                                                GetShortPluginName(),
+                error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+                                                exe_file.GetPath().c_str(),
+                                                GetPluginName().GetCString(),
                                                 arch_names.GetString().c_str());
             }
         }
@@ -302,6 +340,17 @@ PlatformLinux::GetSupportedArchitectureA
         arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
         return arch.IsValid();
     }
+    else if (idx == 1)
+    {
+        // If the default host architecture is 64-bit, look for a 32-bit variant
+        ArchSpec hostArch
+                      = Host::GetArchitecture(Host::eSystemDefaultArchitecture);
+        if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit())
+        {
+            arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture32);
+            return arch.IsValid();
+        }
+    }
     return false;
 }
 
@@ -310,12 +359,14 @@ PlatformLinux::GetStatus (Stream &strm)
 {
     struct utsname un;
 
-    if (uname(&un)) {
-        strm << "Linux";
+    Platform::GetStatus(strm);
+
+    if (uname(&un))
         return;
-    }
 
-    strm << un.sysname << ' ' << un.release << ' ' << un.version << '\n';
+    strm.Printf ("    Kernel: %s\n", un.sysname);
+    strm.Printf ("   Release: %s\n", un.release);
+    strm.Printf ("   Version: %s\n", un.version);
 }
 
 size_t
@@ -387,11 +438,10 @@ PlatformLinux::Attach(ProcessAttachInfo
         if (target == NULL)
         {
             TargetSP new_target_sp;
-            FileSpec emptyFileSpec;
             ArchSpec emptyArchSpec;
 
             error = debugger.GetTargetList().CreateTarget (debugger,
-                                                           emptyFileSpec,
+                                                           NULL,
                                                            emptyArchSpec,
                                                            false,
                                                            m_remote_platform_sp,

Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/Linux/PlatformLinux.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/Linux/PlatformLinux.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/Linux/PlatformLinux.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/Linux/PlatformLinux.h Thu Jun  6 19:06:43 2013
@@ -39,26 +39,14 @@ namespace lldb_private {
         static Platform *
         CreateInstance (bool force, const lldb_private::ArchSpec *arch);
 
-        static const char *
-        GetPluginNameStatic();
-
-        static const char *
-        GetShortPluginNameStatic(bool is_host);
+        static lldb_private::ConstString
+        GetPluginNameStatic (bool is_host);
 
         static const char *
-        GetPluginDescriptionStatic(bool is_host);
+        GetPluginDescriptionStatic (bool is_host);
 
-        virtual const char *
-        GetPluginName()
-        {
-            return GetPluginNameStatic();
-        }
-        
-        virtual const char *
-        GetShortPluginName()
-        {
-            return "PlatformLinux";
-        }
+        virtual lldb_private::ConstString
+        GetPluginName();
         
         virtual uint32_t
         GetPluginVersion()

Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp Thu Jun  6 19:06:43 2013
@@ -7,6 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "lldb/lldb-python.h"
+
 #include "PlatformDarwin.h"
 
 // C Includes
@@ -16,7 +18,14 @@
 #include "lldb/Breakpoint/BreakpointLocation.h"
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/Error.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/Timer.h"
 #include "lldb/Host/Host.h"
+#include "lldb/Host/Symbols.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
 #include "lldb/Target/Target.h"
 
 using namespace lldb;
@@ -42,6 +51,75 @@ PlatformDarwin::~PlatformDarwin()
 {
 }
 
+FileSpecList
+PlatformDarwin::LocateExecutableScriptingResources (Target *target,
+                                                    Module &module)
+{
+    FileSpecList file_list;
+    if (target && target->GetDebugger().GetScriptLanguage() == eScriptLanguagePython)
+    {
+        // NB some extensions might be meaningful and should not be stripped - "this.binary.file"
+        // should not lose ".file" but GetFileNameStrippingExtension() will do precisely that.
+        // Ideally, we should have a per-platform list of extensions (".exe", ".app", ".dSYM", ".framework")
+        // which should be stripped while leaving "this.binary.file" as-is.
+        FileSpec module_spec = module.GetFileSpec();
+        
+        if (module_spec)
+        {
+            SymbolVendor *symbols = module.GetSymbolVendor ();
+            if (symbols)
+            {
+                SymbolFile *symfile = symbols->GetSymbolFile();
+                if (symfile)
+                {
+                    ObjectFile *objfile = symfile->GetObjectFile();
+                    if (objfile)
+                    {
+                        FileSpec symfile_spec (objfile->GetFileSpec());
+                        if (symfile_spec && symfile_spec.Exists())
+                        {
+                            while (module_spec.GetFilename())
+                            {
+                                std::string module_basename (module_spec.GetFilename().GetCString());
+
+                                // FIXME: for Python, we cannot allow certain characters in module
+                                // filenames we import. Theoretically, different scripting languages may
+                                // have different sets of forbidden tokens in filenames, and that should
+                                // be dealt with by each ScriptInterpreter. For now, we just replace dots
+                                // with underscores, but if we ever support anything other than Python
+                                // we will need to rework this
+                                std::replace(module_basename.begin(), module_basename.end(), '.', '_');
+                                std::replace(module_basename.begin(), module_basename.end(), ' ', '_');
+                                std::replace(module_basename.begin(), module_basename.end(), '-', '_');
+                                
+
+                                StreamString path_string;
+                                // for OSX we are going to be in .dSYM/Contents/Resources/DWARF/<basename>
+                                // let us go to .dSYM/Contents/Resources/Python/<basename>.py and see if the file exists
+                                path_string.Printf("%s/../Python/%s.py",symfile_spec.GetDirectory().GetCString(), module_basename.c_str());
+                                FileSpec script_fspec(path_string.GetData(), true);
+                                if (script_fspec.Exists())
+                                {
+                                    file_list.Append (script_fspec);
+                                    break;
+                                }
+                                
+                                // If we didn't find the python file, then keep
+                                // stripping the extensions and try again
+                                ConstString filename_no_extension (module_spec.GetFileNameStrippingExtension());
+                                if (module_spec.GetFilename() == filename_no_extension)
+                                    break;
+                                
+                                module_spec.GetFilename() = filename_no_extension;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return file_list;
+}
 
 Error
 PlatformDarwin::ResolveExecutable (const FileSpec &exe_file,
@@ -117,10 +195,8 @@ PlatformDarwin::ResolveExecutable (const
             if (error.Fail() || exe_module_sp.get() == NULL || exe_module_sp->GetObjectFile() == NULL)
             {
                 exe_module_sp.reset();
-                error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain the architecture %s",
-                                                exe_file.GetDirectory().AsCString(""),
-                                                exe_file.GetDirectory() ? "/" : "",
-                                                exe_file.GetFilename().AsCString(""),
+                error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
+                                                exe_file.GetPath().c_str(),
                                                 exe_arch.GetArchitectureName());
             }
         }
@@ -153,11 +229,9 @@ PlatformDarwin::ResolveExecutable (const
             
             if (error.Fail() || !exe_module_sp)
             {
-                error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain any '%s' platform architectures: %s",
-                                                exe_file.GetDirectory().AsCString(""),
-                                                exe_file.GetDirectory() ? "/" : "",
-                                                exe_file.GetFilename().AsCString(""),
-                                                GetShortPluginName(),
+                error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+                                                exe_file.GetPath().c_str(),
+                                                GetPluginName().GetCString(),
                                                 arch_names.GetString().c_str());
             }
         }
@@ -166,6 +240,32 @@ PlatformDarwin::ResolveExecutable (const
     return error;
 }
 
+Error
+PlatformDarwin::ResolveSymbolFile (Target &target,
+                                   const ModuleSpec &sym_spec,
+                                   FileSpec &sym_file)
+{
+    Error error;
+    sym_file = sym_spec.GetSymbolFileSpec();
+    if (sym_file.Exists())
+    {
+        if (sym_file.GetFileType() == FileSpec::eFileTypeDirectory)
+        {
+            sym_file = Symbols::FindSymbolFileInBundle (sym_file,
+                                                        sym_spec.GetUUIDPtr(),
+                                                        sym_spec.GetArchitecturePtr());
+        }
+    }
+    else
+    {
+        if (sym_spec.GetUUID().IsValid())
+        {
+            
+        }
+    }
+    return error;
+    
+}
 
 static lldb_private::Error
 MakeCacheFolderForFile (const FileSpec& module_cache_spec)
@@ -209,8 +309,7 @@ PlatformDarwin::GetSharedModuleWithLocal
            module_spec.GetSymbolFileSpec().GetFilename().AsCString());
 
     std::string cache_path(GetLocalCacheDirectory());
-    std::string module_path;
-    module_spec.GetFileSpec().GetPath(module_path);
+    std::string module_path (module_spec.GetFileSpec().GetPath());
     cache_path.append(module_path);
     FileSpec module_cache_spec(cache_path.c_str(),false);
     
@@ -337,33 +436,52 @@ PlatformDarwin::GetSharedModule (const M
             FileSpec bundle_directory;
             if (Host::GetBundleDirectory (platform_file, bundle_directory))
             {
-                char platform_path[PATH_MAX];
-                char bundle_dir[PATH_MAX];
-                platform_file.GetPath (platform_path, sizeof(platform_path));
-                const size_t bundle_directory_len = bundle_directory.GetPath (bundle_dir, sizeof(bundle_dir));
-                char new_path[PATH_MAX];
-                size_t num_module_search_paths = module_search_paths_ptr->GetSize();
-                for (size_t i=0; i<num_module_search_paths; ++i)
+                if (platform_file == bundle_directory)
                 {
-                    const size_t search_path_len = module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath(new_path, sizeof(new_path));
-                    if (search_path_len < sizeof(new_path))
+                    ModuleSpec new_module_spec (module_spec);
+                    new_module_spec.GetFileSpec() = bundle_directory;
+                    if (Host::ResolveExecutableInBundle (new_module_spec.GetFileSpec()))
                     {
-                        snprintf (new_path + search_path_len, sizeof(new_path) - search_path_len, "/%s", platform_path + bundle_directory_len);
-                        FileSpec new_file_spec (new_path, false);
-                        if (new_file_spec.Exists())
+                        Error new_error (Platform::GetSharedModule (new_module_spec,
+                                                                    module_sp,
+                                                                    NULL,
+                                                                    old_module_sp_ptr,
+                                                                    did_create_ptr));
+                        
+                        if (module_sp)
+                            return new_error;
+                    }
+                }
+                else
+                {
+                    char platform_path[PATH_MAX];
+                    char bundle_dir[PATH_MAX];
+                    platform_file.GetPath (platform_path, sizeof(platform_path));
+                    const size_t bundle_directory_len = bundle_directory.GetPath (bundle_dir, sizeof(bundle_dir));
+                    char new_path[PATH_MAX];
+                    size_t num_module_search_paths = module_search_paths_ptr->GetSize();
+                    for (size_t i=0; i<num_module_search_paths; ++i)
+                    {
+                        const size_t search_path_len = module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath(new_path, sizeof(new_path));
+                        if (search_path_len < sizeof(new_path))
                         {
-                            ModuleSpec new_module_spec (module_spec);
-                            new_module_spec.GetFileSpec() = new_file_spec;
-                            Error new_error (Platform::GetSharedModule (new_module_spec,
-                                                                        module_sp,
-                                                                        NULL,
-                                                                        old_module_sp_ptr,
-                                                                        did_create_ptr));
-                            
-                            if (module_sp)
+                            snprintf (new_path + search_path_len, sizeof(new_path) - search_path_len, "/%s", platform_path + bundle_directory_len);
+                            FileSpec new_file_spec (new_path, false);
+                            if (new_file_spec.Exists())
                             {
-                                module_sp->SetPlatformFileSpec(new_file_spec);
-                                return new_error;
+                                ModuleSpec new_module_spec (module_spec);
+                                new_module_spec.GetFileSpec() = new_file_spec;
+                                Error new_error (Platform::GetSharedModule (new_module_spec,
+                                                                            module_sp,
+                                                                            NULL,
+                                                                            old_module_sp_ptr,
+                                                                            did_create_ptr));
+                                
+                                if (module_sp)
+                                {
+                                    module_sp->SetPlatformFileSpec(new_file_spec);
+                                    return new_error;
+                                }
                             }
                         }
                     }
@@ -508,7 +626,7 @@ PlatformDarwin::ConnectRemote (Args& arg
     Error error;
     if (IsHost())
     {
-        error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetShortPluginName());
+        error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
     }
     else
     {
@@ -528,7 +646,7 @@ PlatformDarwin::ConnectRemote (Args& arg
     {
         if (m_options.get())
         {
-            OptionGroupOptions* options = (OptionGroupOptions*)m_options.get();
+            OptionGroupOptions* options = m_options.get();
             OptionGroupPlatformRSync* m_rsync_options = (OptionGroupPlatformRSync*)options->GetGroupWithOption('r');
             OptionGroupPlatformSSH* m_ssh_options = (OptionGroupPlatformSSH*)options->GetGroupWithOption('s');
             OptionGroupPlatformCaching* m_cache_options = (OptionGroupPlatformCaching*)options->GetGroupWithOption('c');
@@ -559,7 +677,7 @@ PlatformDarwin::DisconnectRemote ()
     
     if (IsHost())
     {
-        error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetShortPluginName());
+        error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString());
     }
     else
     {
@@ -642,10 +760,9 @@ PlatformDarwin::Attach (ProcessAttachInf
         if (target == NULL)
         {
             TargetSP new_target_sp;
-            FileSpec emptyFileSpec;
             
             error = debugger.GetTargetList().CreateTarget (debugger,
-                                                           emptyFileSpec,
+                                                           NULL,
                                                            NULL, 
                                                            false,
                                                            NULL,
@@ -730,7 +847,7 @@ PlatformDarwin::x86GetSupportedArchitect
     {
         ArchSpec platform_arch (Host::GetArchitecture (Host::eSystemDefaultArchitecture));
         ArchSpec platform_arch64 (Host::GetArchitecture (Host::eSystemDefaultArchitecture64));
-        if (platform_arch == platform_arch64)
+        if (platform_arch.IsExactMatch(platform_arch64))
         {
             // This macosx platform supports both 32 and 64 bit. Since we already
             // returned the 64 bit arch for idx == 0, return the 32 bit arch 
@@ -759,18 +876,22 @@ PlatformDarwin::ARMGetSupportedArchitect
             case  1: arch.SetTriple ("armv7f-apple-ios");   return true;
             case  2: arch.SetTriple ("armv7k-apple-ios");   return true;
             case  3: arch.SetTriple ("armv7s-apple-ios");   return true;
-            case  4: arch.SetTriple ("armv6-apple-ios");    return true;
-            case  5: arch.SetTriple ("armv5-apple-ios");    return true;
-            case  6: arch.SetTriple ("armv4-apple-ios");    return true;
-            case  7: arch.SetTriple ("arm-apple-ios");      return true;
-            case  8: arch.SetTriple ("thumbv7-apple-ios");  return true;
-            case  9: arch.SetTriple ("thumbv7f-apple-ios"); return true;
-            case 10: arch.SetTriple ("thumbv7k-apple-ios"); return true;
-            case 11: arch.SetTriple ("thumbv7s-apple-ios"); return true;
-            case 12: arch.SetTriple ("thumbv6-apple-ios");  return true;
-            case 13: arch.SetTriple ("thumbv5-apple-ios");  return true;
-            case 14: arch.SetTriple ("thumbv4t-apple-ios"); return true;
-            case 15: arch.SetTriple ("thumb-apple-ios");    return true;
+            case  4: arch.SetTriple ("armv7m-apple-ios");   return true;
+            case  5: arch.SetTriple ("armv7em-apple-ios");  return true;
+            case  6: arch.SetTriple ("armv6-apple-ios");    return true;
+            case  7: arch.SetTriple ("armv5-apple-ios");    return true;
+            case  8: arch.SetTriple ("armv4-apple-ios");    return true;
+            case  9: arch.SetTriple ("arm-apple-ios");      return true;
+            case 10: arch.SetTriple ("thumbv7-apple-ios");  return true;
+            case 11: arch.SetTriple ("thumbv7f-apple-ios"); return true;
+            case 12: arch.SetTriple ("thumbv7k-apple-ios"); return true;
+            case 13: arch.SetTriple ("thumbv7s-apple-ios"); return true;
+            case 14: arch.SetTriple ("thumbv7m-apple-ios"); return true;
+            case 15: arch.SetTriple ("thumbv7em-apple-ios"); return true;
+            case 16: arch.SetTriple ("thumbv6-apple-ios");  return true;
+            case 17: arch.SetTriple ("thumbv5-apple-ios");  return true;
+            case 18: arch.SetTriple ("thumbv4t-apple-ios"); return true;
+            case 19: arch.SetTriple ("thumb-apple-ios");    return true;
         default: break;
         }
         break;
@@ -832,6 +953,44 @@ PlatformDarwin::ARMGetSupportedArchitect
         }
         break;
 
+    case ArchSpec::eCore_arm_armv7m:
+        switch (idx)
+        {
+            case  0: arch.SetTriple ("armv7m-apple-ios");   return true;
+            case  1: arch.SetTriple ("armv7-apple-ios");    return true;
+            case  2: arch.SetTriple ("armv6-apple-ios");    return true;
+            case  3: arch.SetTriple ("armv5-apple-ios");    return true;
+            case  4: arch.SetTriple ("armv4-apple-ios");    return true;
+            case  5: arch.SetTriple ("arm-apple-ios");      return true;
+            case  6: arch.SetTriple ("thumbv7m-apple-ios"); return true;
+            case  7: arch.SetTriple ("thumbv7-apple-ios");  return true;
+            case  8: arch.SetTriple ("thumbv6-apple-ios");  return true;
+            case  9: arch.SetTriple ("thumbv5-apple-ios");  return true;
+            case 10: arch.SetTriple ("thumbv4t-apple-ios"); return true;
+            case 11: arch.SetTriple ("thumb-apple-ios");    return true;
+            default: break;
+        }
+        break;
+
+    case ArchSpec::eCore_arm_armv7em:
+        switch (idx)
+        {
+            case  0: arch.SetTriple ("armv7em-apple-ios");   return true;
+            case  1: arch.SetTriple ("armv7-apple-ios");    return true;
+            case  2: arch.SetTriple ("armv6-apple-ios");    return true;
+            case  3: arch.SetTriple ("armv5-apple-ios");    return true;
+            case  4: arch.SetTriple ("armv4-apple-ios");    return true;
+            case  5: arch.SetTriple ("arm-apple-ios");      return true;
+            case  6: arch.SetTriple ("thumbv7em-apple-ios"); return true;
+            case  7: arch.SetTriple ("thumbv7-apple-ios");  return true;
+            case  8: arch.SetTriple ("thumbv6-apple-ios");  return true;
+            case  9: arch.SetTriple ("thumbv5-apple-ios");  return true;
+            case 10: arch.SetTriple ("thumbv4t-apple-ios"); return true;
+            case 11: arch.SetTriple ("thumb-apple-ios");    return true;
+            default: break;
+        }
+        break;
+
     case ArchSpec::eCore_arm_armv7:
         switch (idx)
         {
@@ -944,6 +1103,43 @@ PlatformDarwin::GetDeveloperDirectory()
             }
         }
         
+        if (!developer_dir_path_valid)
+        {
+            FileSpec xcode_select_cmd ("/usr/bin/xcode-select", false);
+            if (xcode_select_cmd.Exists())
+            {
+                int exit_status = -1;
+                int signo = -1;
+                std::string command_output;
+                Error error = Host::RunShellCommand ("/usr/bin/xcode-select --print-path", 
+                                                     NULL,                                 // current working directory
+                                                     &exit_status,
+                                                     &signo,
+                                                     &command_output,
+                                                     2,                                     // short timeout
+                                                     NULL);                                 // don't run in a shell
+                if (error.Success() && exit_status == 0 && !command_output.empty())
+                {
+                    const char *cmd_output_ptr = command_output.c_str();
+                    developer_dir_path[sizeof (developer_dir_path) - 1] = '\0';
+                    int i;
+                    for (i = 0; i < sizeof (developer_dir_path) - 1; i++)
+                    {
+                        if (cmd_output_ptr[i] == '\r' || cmd_output_ptr[i] == '\n' || cmd_output_ptr[i] == '\0')
+                            break;
+                        developer_dir_path[i] = cmd_output_ptr[i];
+                    }
+                    developer_dir_path[i] = '\0';
+
+                    FileSpec devel_dir (developer_dir_path, false);
+                    if (devel_dir.Exists() && devel_dir.IsDirectory())
+                    {
+                        developer_dir_path_valid = true;
+                    }
+                }
+            }
+        }
+
         if (developer_dir_path_valid)
         {
             temp_file_spec.SetFile (developer_dir_path, false);
@@ -1000,7 +1196,19 @@ PlatformDarwin::SetThreadCreationBreakpo
                                      eFunctionNameTypeFull,
                                      skip_prologue,
                                      internal);
+    bp_sp->SetBreakpointKind("thread-creation");
 
     return bp_sp;
 }
 
+size_t
+PlatformDarwin::GetEnvironment (StringList &env)
+{
+    if (IsRemote())
+    {
+        if (m_remote_platform_sp)
+            return m_remote_platform_sp->GetEnvironment(env);
+        return 0;
+    }
+    return Host::GetEnvironment(env);
+}

Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformDarwin.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformDarwin.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformDarwin.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformDarwin.h Thu Jun  6 19:06:43 2013
@@ -34,6 +34,15 @@ public:
                        const lldb_private::FileSpecList *module_search_paths_ptr);
 
     virtual lldb_private::Error
+    ResolveSymbolFile (lldb_private::Target &target,
+                       const lldb_private::ModuleSpec &sym_spec,
+                       lldb_private::FileSpec &sym_file);
+
+    lldb_private::FileSpecList
+    LocateExecutableScriptingResources (lldb_private::Target *target,
+                                        lldb_private::Module &module);
+    
+    virtual lldb_private::Error
     GetSharedModule (const lldb_private::ModuleSpec &module_spec,
                      lldb::ModuleSP &module_sp,
                      const lldb_private::FileSpecList *module_search_paths_ptr,
@@ -98,7 +107,10 @@ public:
 
     virtual bool
     ModuleIsExcludedForNonModuleSpecificSearches (lldb_private::Target &target, const lldb::ModuleSP &module_sp);
-                
+    
+    virtual size_t
+    GetEnvironment (lldb_private::StringList &environment);
+
     bool
     ARMGetSupportedArchitectureAtIndex (uint32_t idx, lldb_private::ArchSpec &arch);
     

Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp Thu Jun  6 19:06:43 2013
@@ -46,7 +46,7 @@ PlatformMacOSX::Initialize ()
         default_platform_sp->SetSystemArchitecture (Host::GetArchitecture());
         Platform::SetDefaultPlatform (default_platform_sp);
 #endif        
-        PluginManager::RegisterPlugin (PlatformMacOSX::GetShortPluginNameStatic(false),
+        PluginManager::RegisterPlugin (PlatformMacOSX::GetPluginNameStatic(false),
                                        PlatformMacOSX::GetDescriptionStatic(false),
                                        PlatformMacOSX::CreateInstance);
     }
@@ -82,10 +82,14 @@ PlatformMacOSX::CreateInstance (bool for
                 create = true;
                 break;
                 
+#if defined(__APPLE__)
+            // Only accept "unknown" for vendor if the host is Apple and
+            // it "unknown" wasn't specified (it was just returned becasue it
+            // was NOT specified)
             case llvm::Triple::UnknownArch:
                 create = !arch->TripleVendorWasSpecified();
                 break;
-                
+#endif
             default:
                 break;
         }
@@ -97,11 +101,14 @@ PlatformMacOSX::CreateInstance (bool for
                 case llvm::Triple::Darwin:  // Deprecated, but still support Darwin for historical reasons
                 case llvm::Triple::MacOSX:
                     break;
-                    
+#if defined(__APPLE__)
+                // Only accept "vendor" for vendor if the host is Apple and
+                // it "unknown" wasn't specified (it was just returned becasue it
+                // was NOT specified)
                 case llvm::Triple::UnknownOS:
                     create = !arch->TripleOSWasSpecified();
                     break;
-                    
+#endif
                 default:
                     create = false;
                     break;
@@ -113,20 +120,19 @@ PlatformMacOSX::CreateInstance (bool for
     return NULL;
 }
 
-
-const char *
-PlatformMacOSX::GetPluginNameStatic ()
-{
-    return "PlatformMacOSX";
-}
-
-const char *
-PlatformMacOSX::GetShortPluginNameStatic (bool is_host)
+lldb_private::ConstString
+PlatformMacOSX::GetPluginNameStatic (bool is_host)
 {
     if (is_host)
-        return Platform::GetHostPlatformName ();
+    {
+        static ConstString g_host_name(Platform::GetHostPlatformName ());
+        return g_host_name;
+    }
     else
-        return "remote-macosx";
+    {
+        static ConstString g_remote_name("remote-macosx");
+        return g_remote_name;
+    }
 }
 
 const char *
@@ -193,8 +199,7 @@ PlatformMacOSX::GetFile (const lldb_priv
         {
             // try to find the file in the cache
             std::string cache_path(GetLocalCacheDirectory());
-            std::string module_path;
-            platform_file.GetPath(module_path);
+            std::string module_path (platform_file.GetPath());
             cache_path.append(module_path);
             FileSpec module_cache_spec(cache_path.c_str(),false);
             if (module_cache_spec.Exists())

Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformMacOSX.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformMacOSX.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformMacOSX.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformMacOSX.h Thu Jun  6 19:06:43 2013
@@ -32,11 +32,8 @@ public:
     static void
     Terminate ();
     
-    static const char *
-    GetPluginNameStatic ();
-
-    static const char *
-    GetShortPluginNameStatic(bool is_host);
+    static lldb_private::ConstString
+    GetPluginNameStatic (bool is_host);
 
     static const char *
     GetDescriptionStatic(bool is_host);
@@ -52,16 +49,10 @@ public:
     //------------------------------------------------------------
     // lldb_private::PluginInterface functions
     //------------------------------------------------------------
-    virtual const char *
+    virtual lldb_private::ConstString
     GetPluginName()
     {
-        return GetPluginNameStatic ();
-    }
-    
-    virtual const char *
-    GetShortPluginName()
-    {
-        return GetShortPluginNameStatic (IsHost());
+        return GetPluginNameStatic (IsHost());
     }
     
     virtual uint32_t

Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp Thu Jun  6 19:06:43 2013
@@ -18,6 +18,7 @@
 #include "lldb/Core/Error.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/StreamString.h"
 #include "lldb/Host/FileSpec.h"
@@ -64,7 +65,7 @@ PlatformRemoteiOS::Initialize ()
 {
     if (g_initialize_count++ == 0)
     {
-        PluginManager::RegisterPlugin (PlatformRemoteiOS::GetShortPluginNameStatic(),
+        PluginManager::RegisterPlugin (PlatformRemoteiOS::GetPluginNameStatic(),
                                        PlatformRemoteiOS::GetDescriptionStatic(),
                                        PlatformRemoteiOS::CreateInstance);
     }
@@ -101,14 +102,18 @@ PlatformRemoteiOS::CreateInstance (bool
                         create = true;
                         break;
 
+#if defined(__APPLE__)
+                    // Only accept "unknown" for the vendor if the host is Apple and
+                    // it "unknown" wasn't specified (it was just returned becasue it
+                    // was NOT specified)
                     case llvm::Triple::UnknownArch:
                         create = !arch->TripleVendorWasSpecified();
                         break;
 
+#endif
                     default:
                         break;
                 }
-                
                 if (create)
                 {
                     switch (triple.getOS())
@@ -117,10 +122,14 @@ PlatformRemoteiOS::CreateInstance (bool
                         case llvm::Triple::IOS:     // This is the right triple value for iOS debugging
                             break;
 
+#if defined(__APPLE__)
+                        // Only accept "unknown" for the OS if the host is Apple and
+                        // it "unknown" wasn't specified (it was just returned becasue it
+                        // was NOT specified)
                         case llvm::Triple::UnknownOS:
                             create = !arch->TripleOSWasSpecified();
                             break;
-                            
+#endif
                         default:
                             create = false;
                             break;
@@ -139,16 +148,11 @@ PlatformRemoteiOS::CreateInstance (bool
 }
 
 
-const char *
+lldb_private::ConstString
 PlatformRemoteiOS::GetPluginNameStatic ()
 {
-    return "PlatformRemoteiOS";
-}
-
-const char *
-PlatformRemoteiOS::GetShortPluginNameStatic()
-{
-    return "remote-ios";
+    static ConstString g_name("remote-ios");
+    return g_name;
 }
 
 const char *
@@ -196,14 +200,93 @@ PlatformRemoteiOS::GetStatus (Stream &st
     for (uint32_t i=0; i<num_sdk_infos; ++i)
     {
         const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
-        strm.Printf (" SDK Roots: [%2u] \"%s/%s\"\n",
+        strm.Printf (" SDK Roots: [%2u] \"%s\"\n",
                      i,
-                     sdk_dir_info.directory.GetDirectory().GetCString(),
-                     sdk_dir_info.directory.GetFilename().GetCString());
+                     sdk_dir_info.directory.GetPath().c_str());
     }
 }
 
 
+Error
+PlatformRemoteiOS::ResolveExecutable (const FileSpec &exe_file,
+                                      const ArchSpec &exe_arch,
+                                      lldb::ModuleSP &exe_module_sp,
+                                      const FileSpecList *module_search_paths_ptr)
+{
+    Error error;
+    // Nothing special to do here, just use the actual file and architecture
+
+    FileSpec resolved_exe_file (exe_file);
+    
+    // If we have "ls" as the exe_file, resolve the executable loation based on
+    // the current path variables
+    // TODO: resolve bare executables in the Platform SDK
+//    if (!resolved_exe_file.Exists())
+//        resolved_exe_file.ResolveExecutableLocation ();
+
+    // Resolve any executable within a bundle on MacOSX
+    // TODO: verify that this handles shallow bundles, if not then implement one ourselves
+    Host::ResolveExecutableInBundle (resolved_exe_file);
+
+    if (resolved_exe_file.Exists())
+    {
+        if (exe_arch.IsValid())
+        {
+            ModuleSpec module_spec (resolved_exe_file, exe_arch);
+            error = ModuleList::GetSharedModule (module_spec,
+                                                 exe_module_sp, 
+                                                 NULL,
+                                                 NULL, 
+                                                 NULL);
+        
+            if (exe_module_sp && exe_module_sp->GetObjectFile())
+                return error;
+            exe_module_sp.reset();
+        }
+        // No valid architecture was specified or the exact ARM slice wasn't
+        // found so ask the platform for the architectures that we should be
+        // using (in the correct order) and see if we can find a match that way
+        StreamString arch_names;
+        ArchSpec platform_arch;
+        for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
+        {
+            ModuleSpec module_spec (resolved_exe_file, platform_arch);
+            error = ModuleList::GetSharedModule (module_spec, 
+                                                 exe_module_sp, 
+                                                 NULL,
+                                                 NULL, 
+                                                 NULL);
+            // Did we find an executable using one of the 
+            if (error.Success())
+            {
+                if (exe_module_sp && exe_module_sp->GetObjectFile())
+                    break;
+                else
+                    error.SetErrorToGenericError();
+            }
+            
+            if (idx > 0)
+                arch_names.PutCString (", ");
+            arch_names.PutCString (platform_arch.GetArchitectureName());
+        }
+        
+        if (error.Fail() || !exe_module_sp)
+        {
+            error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+                                            exe_file.GetPath().c_str(),
+                                            GetPluginName().GetCString(),
+                                            arch_names.GetString().c_str());
+        }
+    }
+    else
+    {
+        error.SetErrorStringWithFormat ("'%s' does not exist",
+                                        exe_file.GetPath().c_str());
+    }
+
+    return error;
+}
+
 FileSpec::EnumerateDirectoryResult 
 PlatformRemoteiOS::GetContainedFilesIntoVectorOfStringsCallback (void *baton,
                                                                  FileSpec::FileType file_type,
@@ -573,7 +656,7 @@ PlatformRemoteiOS::GetSymbolFile (const
 
         error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'", 
                                         platform_file_path,
-                                        GetPluginName());
+                                        GetPluginName().GetCString());
     }
     else
     {
@@ -619,7 +702,7 @@ PlatformRemoteiOS::GetSharedModule (cons
             {
                 if (GetFileInSDK (platform_file_path, m_last_module_sdk_idx, local_file))
                 {
-                    //printf ("sdk[%u] last: '%s/%s'\n", m_last_module_sdk_idx, local_file.GetDirectory().GetCString(), local_file.GetFilename().GetCString());
+                    //printf ("sdk[%u] last: '%s'\n", m_last_module_sdk_idx, local_file.GetPath().c_str());
                     module_sp.reset();
                     error = ResolveExecutable (local_file,
                                                module_spec.GetArchitecture(),
@@ -645,7 +728,7 @@ PlatformRemoteiOS::GetSharedModule (cons
                 }
                 if (GetFileInSDK (platform_file_path, sdk_idx, local_file))
                 {
-                    //printf ("sdk[%u]: '%s/%s'\n", sdk_idx, local_file.GetDirectory().GetCString(), local_file.GetFilename().GetCString());
+                    //printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());
                     
                     error = ResolveExecutable (local_file,
                                                module_spec.GetArchitecture(),

Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h Thu Jun  6 19:06:43 2013
@@ -34,13 +34,10 @@ public:
     static void
     Terminate ();
     
-    static const char *
+    static lldb_private::ConstString
     GetPluginNameStatic ();
 
     static const char *
-    GetShortPluginNameStatic();
-
-    static const char *
     GetDescriptionStatic();
     
     //------------------------------------------------------------
@@ -54,18 +51,12 @@ public:
     //------------------------------------------------------------
     // lldb_private::PluginInterface functions
     //------------------------------------------------------------
-    virtual const char *
+    virtual lldb_private::ConstString
     GetPluginName()
     {
         return GetPluginNameStatic();
     }
     
-    virtual const char *
-    GetShortPluginName()
-    {
-        return GetShortPluginNameStatic();
-    }
-    
     virtual uint32_t
     GetPluginVersion()
     {
@@ -75,6 +66,12 @@ public:
     //------------------------------------------------------------
     // lldb_private::Platform functions
     //------------------------------------------------------------
+    virtual lldb_private::Error
+    ResolveExecutable (const lldb_private::FileSpec &exe_file,
+                       const lldb_private::ArchSpec &arch,
+                       lldb::ModuleSP &module_sp,
+                       const lldb_private::FileSpecList *module_search_paths_ptr);
+
     virtual const char *
     GetDescription ()
     {

Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp Thu Jun  6 19:06:43 2013
@@ -18,6 +18,7 @@
 #include "lldb/Core/Error.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/StreamString.h"
 #include "lldb/Host/FileSpec.h"
@@ -41,7 +42,7 @@ PlatformiOSSimulator::Initialize ()
 {
     if (g_initialize_count++ == 0)
     {
-        PluginManager::RegisterPlugin (PlatformiOSSimulator::GetShortPluginNameStatic(),
+        PluginManager::RegisterPlugin (PlatformiOSSimulator::GetPluginNameStatic(),
                                        PlatformiOSSimulator::GetDescriptionStatic(),
                                        PlatformiOSSimulator::CreateInstance);
     }
@@ -77,10 +78,14 @@ PlatformiOSSimulator::CreateInstance (bo
                         create = true;
                         break;
                         
+#if defined(__APPLE__)
+                    // Only accept "unknown" for the vendor if the host is Apple and
+                    // it "unknown" wasn't specified (it was just returned becasue it
+                    // was NOT specified)
                     case llvm::Triple::UnknownArch:
                         create = !arch->TripleVendorWasSpecified();
                         break;
-                        
+#endif
                     default:
                         break;
                 }
@@ -94,10 +99,14 @@ PlatformiOSSimulator::CreateInstance (bo
                         case llvm::Triple::IOS:     // IOS is not used for simulator triples, but accept it just in case
                             break;
                             
+#if defined(__APPLE__)
+                        // Only accept "unknown" for the OS if the host is Apple and
+                        // it "unknown" wasn't specified (it was just returned becasue it
+                        // was NOT specified)
                         case llvm::Triple::UnknownOS:
                             create = !arch->TripleOSWasSpecified();
                             break;
-                            
+#endif
                         default:
                             create = false;
                             break;
@@ -115,16 +124,11 @@ PlatformiOSSimulator::CreateInstance (bo
 }
 
 
-const char *
+lldb_private::ConstString
 PlatformiOSSimulator::GetPluginNameStatic ()
 {
-    return "PlatformiOSSimulator";
-}
-
-const char *
-PlatformiOSSimulator::GetShortPluginNameStatic()
-{
-    return "ios-simulator";
+    static ConstString g_name("ios-simulator");
+    return g_name;
 }
 
 const char *
@@ -138,7 +142,7 @@ PlatformiOSSimulator::GetDescriptionStat
 /// Default Constructor
 //------------------------------------------------------------------
 PlatformiOSSimulator::PlatformiOSSimulator () :
-    PlatformDarwin (false),
+    PlatformDarwin (true),
     m_sdk_directory ()
 {
 }
@@ -198,7 +202,7 @@ PlatformiOSSimulator::ResolveExecutable
                                                  NULL, 
                                                  NULL);
         
-            if (exe_module_sp->GetObjectFile())
+            if (exe_module_sp && exe_module_sp->GetObjectFile())
                 return error;
             exe_module_sp.reset();
         }
@@ -231,20 +235,16 @@ PlatformiOSSimulator::ResolveExecutable
         
         if (error.Fail() || !exe_module_sp)
         {
-            error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain any '%s' platform architectures: %s",
-                                            exe_file.GetDirectory().AsCString(""),
-                                            exe_file.GetDirectory() ? "/" : "",
-                                            exe_file.GetFilename().AsCString(""),
-                                            GetShortPluginName(),
+            error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+                                            exe_file.GetPath().c_str(),
+                                            GetPluginName().GetCString(),
                                             arch_names.GetString().c_str());
         }
     }
     else
     {
-        error.SetErrorStringWithFormat ("'%s%s%s' does not exist",
-                                        exe_file.GetDirectory().AsCString(""),
-                                        exe_file.GetDirectory() ? "/" : "",
-                                        exe_file.GetFilename().AsCString(""));
+        error.SetErrorStringWithFormat ("'%s' does not exist",
+                                        exe_file.GetPath().c_str());
     }
 
     return error;
@@ -347,7 +347,7 @@ PlatformiOSSimulator::GetSymbolFile (con
         }
         error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'", 
                                         platform_file_path,
-                                        GetPluginName());
+                                        GetPluginName().GetCString());
     }
     else
     {
@@ -403,14 +403,6 @@ PlatformiOSSimulator::FindProcesses (con
 }
 
 bool
-PlatformiOSSimulator::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
-{
-    // TODO: if connected, send a packet to get the remote process info
-    process_info.Clear();
-    return false;
-}
-
-bool
 PlatformiOSSimulator::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
 {
     if (idx == 0)

Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h Thu Jun  6 19:06:43 2013
@@ -32,13 +32,10 @@ public:
     static void
     Terminate ();
     
-    static const char *
+    static lldb_private::ConstString
     GetPluginNameStatic ();
 
     static const char *
-    GetShortPluginNameStatic();
-
-    static const char *
     GetDescriptionStatic();
     
     //------------------------------------------------------------
@@ -52,18 +49,12 @@ public:
     //------------------------------------------------------------
     // lldb_private::PluginInterface functions
     //------------------------------------------------------------
-    virtual const char *
+    virtual lldb_private::ConstString
     GetPluginName()
     {
         return GetPluginNameStatic();
     }
     
-    virtual const char *
-    GetShortPluginName()
-    {
-        return GetShortPluginNameStatic();
-    }
-    
     virtual uint32_t
     GetPluginVersion()
     {
@@ -105,10 +96,6 @@ public:
                    lldb_private::ProcessInstanceInfoList &process_infos);
 
     virtual bool
-    GetProcessInfo (lldb::pid_t pid, 
-                    lldb_private::ProcessInstanceInfo &proc_info);
-
-    virtual bool
     GetSupportedArchitectureAtIndex (uint32_t idx, 
                                      lldb_private::ArchSpec &arch);
 

Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp Thu Jun  6 19:06:43 2013
@@ -16,6 +16,7 @@
 
 #include "lldb/Core/DataBufferHeap.h"
 #include "lldb/Core/StreamString.h"
+#include "lldb/Host/File.h"
 #include "lldb/Host/FileSpec.h"
 #include "lldb/Host/Host.h"
 
@@ -89,54 +90,62 @@ PlatformPOSIX::MakeDirectory (const std:
 
 lldb::user_id_t
 PlatformPOSIX::OpenFile (const FileSpec& file_spec,
-                          uint32_t flags,
-                          mode_t mode)
+                         uint32_t flags,
+                         mode_t mode,
+                         Error &error)
 {
     if (IsHost())
     {
-        return Host::OpenFile(file_spec, flags, mode);
+        return Host::OpenFile(file_spec, flags, mode, error);
     }
     if (IsRemote() && m_remote_platform_sp)
-        return m_remote_platform_sp->OpenFile(file_spec, flags, mode);
-    return Platform::OpenFile(file_spec, flags, mode);
+        return m_remote_platform_sp->OpenFile(file_spec, flags, mode, error);
+    return Platform::OpenFile(file_spec, flags, mode, error);
 }
 
 bool
-PlatformPOSIX::CloseFile (lldb::user_id_t fd)
+PlatformPOSIX::CloseFile (lldb::user_id_t fd, Error &error)
 {
     if (IsHost())
     {
-        return Host::CloseFile(fd);
+        return Host::CloseFile(fd, error);
     }
     if (IsRemote() && m_remote_platform_sp)
-        return m_remote_platform_sp->CloseFile(fd);
-    return Platform::CloseFile(fd);
+        return m_remote_platform_sp->CloseFile(fd, error);
+    return Platform::CloseFile(fd, error);
 }
 
-uint32_t
-PlatformPOSIX::ReadFile (lldb::user_id_t fd, uint64_t offset,
-                          void *data_ptr, size_t len)
+uint64_t
+PlatformPOSIX::ReadFile (lldb::user_id_t fd,
+                         uint64_t offset,
+                         void *dst,
+                         uint64_t dst_len,
+                         Error &error)
 {
     if (IsHost())
     {
-        return Host::ReadFile(fd, offset, data_ptr, len);
+        return Host::ReadFile(fd, offset, dst, dst_len, error);
     }
     if (IsRemote() && m_remote_platform_sp)
-        return m_remote_platform_sp->ReadFile(fd, offset, data_ptr, len);
-    return Platform::ReadFile(fd, offset, data_ptr, len);
+        return m_remote_platform_sp->ReadFile(fd, offset, dst, dst_len, error);
+    return Platform::ReadFile(fd, offset, dst, dst_len, error);
 }
 
-uint32_t
-PlatformPOSIX::WriteFile (lldb::user_id_t fd, uint64_t offset,
-                           void* data, size_t len)
+uint64_t
+PlatformPOSIX::WriteFile (lldb::user_id_t fd,
+                          uint64_t offset,
+                          const void* src,
+                          uint64_t src_len,
+                          Error &error)
 {
     if (IsHost())
     {
-        return Host::WriteFile(fd, offset, data, len);
+        return Host::WriteFile(fd, offset, src, src_len, error);
     }
     if (IsRemote() && m_remote_platform_sp)
-        return m_remote_platform_sp->WriteFile(fd, offset, data, len);
-    return Platform::WriteFile(fd, offset, data, len);
+        return m_remote_platform_sp->WriteFile(fd, offset, src, src_len, error);
+
+    return Platform::WriteFile(fd, offset, src, src_len, error);
 }
 
 static uint32_t
@@ -174,18 +183,17 @@ PlatformPOSIX::PutFile (const lldb_priva
                          uint32_t uid,
                          uint32_t gid)
 {
-#define PUTFILE_CHUNK_SIZE 1024
     if (IsHost())
     {
         if (FileSpec::Equal(source, destination, true))
             return Error();
         // cp src dst
         // chown uid:gid dst
-        std::string src_path;
-        if (source.GetPath(src_path) == 0)
+        std::string src_path (source.GetPath());
+        if (src_path.empty())
             return Error("unable to get file path for source");
-        std::string dst_path;
-        if (destination.GetPath(dst_path) == 0)
+        std::string dst_path (destination.GetPath());
+        if (dst_path.empty())
             return Error("unable to get file path for destination");
         StreamString command;
         command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str());
@@ -204,15 +212,15 @@ PlatformPOSIX::PutFile (const lldb_priva
             return Error("unable to perform chown");
         return Error();
     }
-    if (IsRemote() && m_remote_platform_sp)
+    else if (IsRemote() && m_remote_platform_sp)
     {
         if (GetSupportsRSync())
         {
-            std::string src_path;
-            if (source.GetPath(src_path) == 0)
+            std::string src_path (source.GetPath());
+            if (src_path.empty())
                 return Error("unable to get file path for source");
-            std::string dst_path;
-            if (destination.GetPath(dst_path) == 0)
+            std::string dst_path (destination.GetPath());
+            if (dst_path.empty())
                 return Error("unable to get file path for destination");
             StreamString command;
             if (GetIgnoresRemoteHostname())
@@ -245,8 +253,9 @@ PlatformPOSIX::PutFile (const lldb_priva
                                   60);
             if (retcode == 0)
             {
-                if (chown_file(this,dst_path.c_str(),uid,gid) != 0)
-                    return Error("unable to perform chown");
+                // Don't chown a local file for a remote system
+//                if (chown_file(this,dst_path.c_str(),uid,gid) != 0)
+//                    return Error("unable to perform chown");
                 return Error();
             }
             // if we are still here rsync has failed - let's try the slow way before giving up
@@ -259,33 +268,38 @@ PlatformPOSIX::PutFile (const lldb_priva
         File source_file(source, File::eOpenOptionRead, File::ePermissionsUserRW);
         if (!source_file.IsValid())
             return Error("unable to open source file");
-        lldb::user_id_t dest_file = OpenFile(destination, File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate,
-                                             File::ePermissionsUserRWX | File::ePermissionsGroupRX | File::ePermissionsWorldRX);
+        Error error;
+        lldb::user_id_t dest_file = OpenFile (destination,
+                                              File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate,
+                                              File::ePermissionsUserRWX | File::ePermissionsGroupRX | File::ePermissionsWorldRX,
+                                              error);
+        printf ("dest_file = %lli\n", dest_file);
+        if (error.Fail())
+            return error;
         if (dest_file == UINT64_MAX)
             return Error("unable to open target file");
-        lldb::DataBufferSP buffer_sp(new DataBufferHeap(PUTFILE_CHUNK_SIZE, 0));
-        Error err;
+        lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
         uint64_t offset = 0;
-        while (err.Success())
+        while (error.Success())
         {
-            size_t read_data = PUTFILE_CHUNK_SIZE;
-            err = source_file.Read(buffer_sp->GetBytes(), read_data);
-            if (read_data)
+            size_t bytes_read = buffer_sp->GetByteSize();
+            error = source_file.Read(buffer_sp->GetBytes(), bytes_read);
+            if (bytes_read)
             {
-                WriteFile(dest_file, offset, buffer_sp->GetBytes(), read_data);
-                offset += read_data;
+                WriteFile(dest_file, offset, buffer_sp->GetBytes(), bytes_read, error);
+                offset += bytes_read;
             }
             else
                 break;
         }
-        CloseFile(dest_file);
+        CloseFile(dest_file, error);
         if (uid == UINT32_MAX && gid == UINT32_MAX)
-            return Error();
-        std::string dst_path;
-        destination.GetPath(dst_path);
-        if (chown_file(this,dst_path.c_str(),uid,gid) != 0)
-            return Error("unable to perform chown");
-        return Error();
+            return error;
+        // This is remopve, don't chown a local file...
+//        std::string dst_path (destination.GetPath());
+//        if (chown_file(this,dst_path.c_str(),uid,gid) != 0)
+//            return Error("unable to perform chown");
+        return error;
     }
     return Platform::PutFile(source,destination,uid,gid);
 }
@@ -314,17 +328,31 @@ PlatformPOSIX::GetFileExists (const File
     return Platform::GetFileExists(file_spec);
 }
 
+uint32_t
+PlatformPOSIX::GetFilePermissions (const lldb_private::FileSpec &file_spec,
+                                   lldb_private::Error &error)
+{
+    if (IsHost())
+    {
+        return File::GetPermissions(file_spec.GetPath().c_str(), error);
+    }
+    if (IsRemote() && m_remote_platform_sp)
+        return m_remote_platform_sp->GetFilePermissions(file_spec, error);
+    return Platform::GetFilePermissions(file_spec, error);
+    
+}
+
+
 lldb_private::Error
 PlatformPOSIX::GetFile (const lldb_private::FileSpec& source /* remote file path */,
                          const lldb_private::FileSpec& destination /* local file path */)
 {
-#define GETFILE_CHUNK_SIZE 1024
-    // Check the args, first. 
-    std::string src_path;
-    if (source.GetPath(src_path) == 0)
+    // Check the args, first.
+    std::string src_path (source.GetPath());
+    if (src_path.empty())
         return Error("unable to get file path for source");
-    std::string dst_path;
-    if (destination.GetPath(dst_path) == 0)
+    std::string dst_path (destination.GetPath());
+    if (dst_path.empty())
         return Error("unable to get file path for destination");
     if (IsHost())
     {
@@ -386,41 +414,71 @@ PlatformPOSIX::GetFile (const lldb_priva
         // close src
         // close dst
         printf("[GetFile] Using block by block transfer....\n");
-        user_id_t fd_src = OpenFile(source, File::eOpenOptionRead, File::ePermissionsDefault);
-        user_id_t fd_dst = Host::OpenFile(destination,
-                                          File::eOpenOptionCanCreate|File::eOpenOptionWrite,
-                                          File::ePermissionsDefault);
+        Error error;
+        user_id_t fd_src = OpenFile (source,
+                                     File::eOpenOptionRead,
+                                     File::ePermissionsDefault,
+                                     error);
+
         if (fd_src == UINT64_MAX)
             return Error("unable to open source file");
-        if (fd_dst == UINT64_MAX)
-            return Error("unable to open destination file");
 
-        lldb::DataBufferSP buffer_sp(new DataBufferHeap(GETFILE_CHUNK_SIZE, 0));
-        uint8_t *cursor = buffer_sp->GetBytes();
-        Error err;
-        uint64_t offset = 0;
-        while (err.Success())
-        {
-            user_id_t n_read = ReadFile(fd_src, offset, cursor, GETFILE_CHUNK_SIZE);
-            if (n_read == UINT32_MAX)
-                return Error("error during read operation");
-            // Break out of the loop once we reach end of file.
-            if (n_read == 0)
-                break;
+        uint32_t permissions = GetFilePermissions(source, error);
+        
+        if (permissions == 0)
+            permissions = File::ePermissionsDefault;
 
-            if (!Host::WriteFile(fd_dst, offset, cursor, n_read))
-                return Error("unable to write to destination file");
+        user_id_t fd_dst = Host::OpenFile(destination,
+                                          File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate,
+                                          permissions,
+                                          error);
 
-            offset += n_read;
-            cursor += n_read;
+        if (fd_dst == UINT64_MAX)
+        {
+            if (error.Success())
+                error.SetErrorString("unable to open destination file");
+        }
 
+        if (error.Success())
+        {
+            lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
+            uint64_t offset = 0;
+            error.Clear();
+            while (error.Success())
+            {
+                const uint64_t n_read = ReadFile (fd_src,
+                                                  offset,
+                                                  buffer_sp->GetBytes(),
+                                                  buffer_sp->GetByteSize(),
+                                                  error);
+                if (error.Fail())
+                    break;
+                if (n_read == 0)
+                    break;
+                if (Host::WriteFile(fd_dst,
+                                    offset,
+                                    buffer_sp->GetBytes(),
+                                    n_read,
+                                    error) != n_read)
+                {
+                    if (!error.Fail())
+                        error.SetErrorString("unable to write to destination file");
+                        break;
+                }
+                offset += n_read;
+            }
         }
         // Ignore the close error of src.
-        CloseFile(fd_src);
+        if (fd_src != UINT64_MAX)
+            CloseFile(fd_src, error);
         // And close the dst file descriptot.
-        if (!Host::CloseFile(fd_dst))
-            return Error("unable to close destination file");
-        return Error();
+        if (fd_dst != UINT64_MAX && !Host::CloseFile(fd_dst, error))
+        {
+            if (!error.Fail())
+                error.SetErrorString("unable to close destination file");
+
+        }
+        return error;
     }
     return Platform::GetFile(source,destination);
 }

Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/POSIX/PlatformPOSIX.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/POSIX/PlatformPOSIX.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/POSIX/PlatformPOSIX.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/POSIX/PlatformPOSIX.h Thu Jun  6 19:06:43 2013
@@ -43,18 +43,26 @@ public:
     virtual lldb::user_id_t
     OpenFile (const lldb_private::FileSpec& file_spec,
               uint32_t flags,
-              mode_t mode);
+              mode_t mode,
+              lldb_private::Error &error);
     
     virtual bool
-    CloseFile (lldb::user_id_t fd);
+    CloseFile (lldb::user_id_t fd,
+               lldb_private::Error &error);
     
-    virtual uint32_t
-    ReadFile (lldb::user_id_t fd, uint64_t offset,
-              void *data_ptr, size_t len);
-    
-    virtual uint32_t
-    WriteFile (lldb::user_id_t fd, uint64_t offset,
-               void* data, size_t len);
+    virtual uint64_t
+    ReadFile (lldb::user_id_t fd,
+              uint64_t offset,
+              void *dst,
+              uint64_t dst_len,
+              lldb_private::Error &error);
+    
+    virtual uint64_t
+    WriteFile (lldb::user_id_t fd,
+               uint64_t offset,
+               const void* src,
+               uint64_t src_len,
+               lldb_private::Error &error);
     
     virtual lldb::user_id_t
     GetFileSize (const lldb_private::FileSpec& file_spec);
@@ -78,6 +86,10 @@ public:
     virtual bool
     GetFileExists (const lldb_private::FileSpec& file_spec);
     
+    virtual uint32_t
+    GetFilePermissions (const lldb_private::FileSpec &file_spec,
+                        lldb_private::Error &error);
+
     virtual std::string
     GetPlatformSpecificConnectionInformation();
     

Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp Thu Jun  6 19:06:43 2013
@@ -7,6 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "lldb/lldb-python.h"
+
 #include "PlatformRemoteGDBServer.h"
 
 // C Includes
@@ -39,7 +41,7 @@ PlatformRemoteGDBServer::Initialize ()
     if (g_initialized == false)
     {
         g_initialized = true;
-        PluginManager::RegisterPlugin (PlatformRemoteGDBServer::GetShortPluginNameStatic(),
+        PluginManager::RegisterPlugin (PlatformRemoteGDBServer::GetPluginNameStatic(),
                                        PlatformRemoteGDBServer::GetDescriptionStatic(),
                                        PlatformRemoteGDBServer::CreateInstance);
     }
@@ -69,10 +71,11 @@ PlatformRemoteGDBServer::CreateInstance
 }
 
 
-const char *
-PlatformRemoteGDBServer::GetShortPluginNameStatic()
+lldb_private::ConstString
+PlatformRemoteGDBServer::GetPluginNameStatic()
 {
-    return "remote-gdb-server";
+    static ConstString g_name("remote-gdb-server");
+    return g_name;
 }
 
 const char *
@@ -372,9 +375,10 @@ PlatformRemoteGDBServer::Attach (lldb_pr
     {
         if (IsConnected())
         {
-            uint16_t port = m_gdb_client.LaunchGDBserverAndGetPort();
+            lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
+            uint16_t port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid);
             
-            if (port == 0)
+            if (port == 0 || debugserver_pid == LLDB_INVALID_PROCESS_ID)
             {
                 error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ());
             }
@@ -383,10 +387,9 @@ PlatformRemoteGDBServer::Attach (lldb_pr
                 if (target == NULL)
                 {
                     TargetSP new_target_sp;
-                    FileSpec emptyFileSpec;
                     
                     error = debugger.GetTargetList().CreateTarget (debugger,
-                                                                   emptyFileSpec,
+                                                                   NULL,
                                                                    NULL, 
                                                                    false,
                                                                    NULL,
@@ -416,9 +419,14 @@ PlatformRemoteGDBServer::Attach (lldb_pr
                                                                 override_hostname ? override_hostname : GetHostname (), 
                                                                 port + port_offset);
                         assert (connect_url_len < sizeof(connect_url));
-                        error = process_sp->ConnectRemote (connect_url);
+                        error = process_sp->ConnectRemote (NULL, connect_url);
                         if (error.Success())
                             error = process_sp->Attach(attach_info);
+                        else
+                        {
+                            bool success = m_gdb_client.KillSpawnedProcess(debugserver_pid);
+                            printf ("success = %i\n", success);
+                        }
                     }
                 }
             }
@@ -441,35 +449,49 @@ PlatformRemoteGDBServer::MakeDirectory (
 lldb::user_id_t
 PlatformRemoteGDBServer::OpenFile (const lldb_private::FileSpec& file_spec,
                                    uint32_t flags,
-                                   mode_t mode)
+                                   mode_t mode,
+                                   Error &error)
 {
-    return m_gdb_client.OpenFile (file_spec, flags, mode);
+    return m_gdb_client.OpenFile (file_spec, flags, mode, error);
 }
 
 bool
-PlatformRemoteGDBServer::CloseFile (lldb::user_id_t fd)
+PlatformRemoteGDBServer::CloseFile (lldb::user_id_t fd, Error &error)
 {
-    return m_gdb_client.CloseFile (fd);
+    return m_gdb_client.CloseFile (fd, error);
 }
 
 lldb::user_id_t
-PlatformRemoteGDBServer::GetFileSize (const lldb_private::FileSpec& source)
+PlatformRemoteGDBServer::GetFileSize (const lldb_private::FileSpec& file_spec)
 {
-    return m_gdb_client.GetFileSize(source);
+    return m_gdb_client.GetFileSize(file_spec);
 }
 
 uint32_t
-PlatformRemoteGDBServer::ReadFile (lldb::user_id_t fd, uint64_t offset,
-                                   void *data_ptr, size_t len)
+PlatformRemoteGDBServer::GetFilePermissions (const lldb_private::FileSpec &file_spec,
+                                             lldb_private::Error &error)
 {
-    return m_gdb_client.ReadFile (fd, offset, data_ptr, len);
+    return m_gdb_client.GetFilePermissions(file_spec, error);
 }
 
-uint32_t
-PlatformRemoteGDBServer::WriteFile (lldb::user_id_t fd, uint64_t offset,
-                                    void* data, size_t len)
+uint64_t
+PlatformRemoteGDBServer::ReadFile (lldb::user_id_t fd,
+                                   uint64_t offset,
+                                   void *dst,
+                                   uint64_t dst_len,
+                                   Error &error)
+{
+    return m_gdb_client.ReadFile (fd, offset, dst, dst_len, error);
+}
+
+uint64_t
+PlatformRemoteGDBServer::WriteFile (lldb::user_id_t fd,
+                                    uint64_t offset,
+                                    const void* src,
+                                    uint64_t src_len,
+                                    Error &error)
 {
-    return m_gdb_client.WriteFile (fd, offset, data, len);
+    return m_gdb_client.WriteFile (fd, offset, src, src_len, error);
 }
 
 lldb_private::Error

Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h Thu Jun  6 19:06:43 2013
@@ -32,8 +32,8 @@ public:
     static lldb_private::Platform* 
     CreateInstance (bool force, const lldb_private::ArchSpec *arch);
 
-    static const char *
-    GetShortPluginNameStatic();
+    static lldb_private::ConstString
+    GetPluginNameStatic();
 
     static const char *
     GetDescriptionStatic();
@@ -47,16 +47,10 @@ public:
     //------------------------------------------------------------
     // lldb_private::PluginInterface functions
     //------------------------------------------------------------
-    virtual const char *
+    virtual lldb_private::ConstString
     GetPluginName()
     {
-        return "PlatformRemoteGDBServer";
-    }
-    
-    virtual const char *
-    GetShortPluginName()
-    {
-        return GetShortPluginNameStatic();
+        return GetPluginNameStatic();
     }
     
     virtual uint32_t
@@ -148,22 +142,30 @@ public:
     virtual lldb::user_id_t
     OpenFile (const lldb_private::FileSpec& file_spec,
               uint32_t flags,
-              mode_t mode);
+              mode_t mode,
+              lldb_private::Error &error);
     
     virtual bool
-    CloseFile (lldb::user_id_t fd);
+    CloseFile (lldb::user_id_t fd,
+               lldb_private::Error &error);
     
+    virtual uint64_t
+    ReadFile (lldb::user_id_t fd,
+              uint64_t offset,
+              void *data_ptr,
+              uint64_t len,
+              lldb_private::Error &error);
+    
+    virtual uint64_t
+    WriteFile (lldb::user_id_t fd,
+               uint64_t offset,
+               const void* data,
+               uint64_t len,
+               lldb_private::Error &error);
+
     virtual lldb::user_id_t
     GetFileSize (const lldb_private::FileSpec& file_spec);
 
-    virtual uint32_t
-    ReadFile (lldb::user_id_t fd, uint64_t offset,
-              void *data_ptr, size_t len);
-    
-    virtual uint32_t
-    WriteFile (lldb::user_id_t fd, uint64_t offset,
-               void* data, size_t len);
-    
     virtual lldb_private::Error
     PutFile (const lldb_private::FileSpec& source,
              const lldb_private::FileSpec& destination,
@@ -173,6 +175,10 @@ public:
     virtual bool
     GetFileExists (const lldb_private::FileSpec& file_spec);
     
+    virtual uint32_t
+    GetFilePermissions (const lldb_private::FileSpec &file_spec,
+                        lldb_private::Error &error);
+
     virtual lldb_private::Error
     RunShellCommand (const char *command,           // Shouldn't be NULL
                      const char *working_dir,       // Pass NULL to use the current working directory

Copied: lldb/branches/lldb-platform-work/source/Plugins/Process/CMakeLists.txt (from r182522, lldb/trunk/source/Plugins/Process/CMakeLists.txt)
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/CMakeLists.txt?p2=lldb/branches/lldb-platform-work/source/Plugins/Process/CMakeLists.txt&p1=lldb/trunk/source/Plugins/Process/CMakeLists.txt&r1=182522&r2=183468&rev=183468&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/CMakeLists.txt (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/CMakeLists.txt Thu Jun  6 19:06:43 2013
@@ -2,7 +2,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux")
   add_subdirectory(Linux)
   add_subdirectory(POSIX)
 elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
-  #add_subdirectory(FreeBSD)
+  add_subdirectory(FreeBSD)
   add_subdirectory(POSIX)
 elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin")
   add_subdirectory(MacOSX-Kernel)

Copied: lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/CMakeLists.txt (from r182522, lldb/trunk/source/Plugins/Process/FreeBSD/CMakeLists.txt)
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/CMakeLists.txt?p2=lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/CMakeLists.txt&p1=lldb/trunk/source/Plugins/Process/FreeBSD/CMakeLists.txt&r1=182522&r2=183468&rev=183468&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/FreeBSD/CMakeLists.txt (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/CMakeLists.txt Thu Jun  6 19:06:43 2013
@@ -1,5 +1,8 @@
 set(LLVM_NO_RTTI 1)
 
+include_directories(.)
+include_directories(../POSIX)
+
 add_lldb_library(lldbPluginProcessFreeBSD
   ProcessFreeBSD.cpp
   ProcessMonitor.cpp

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp Thu Jun  6 19:06:43 2013
@@ -64,10 +64,11 @@ ProcessFreeBSD::Initialize()
     }
 }
 
-const char *
+lldb_private::ConstString
 ProcessFreeBSD::GetPluginNameStatic()
 {
-    return "freebsd";
+    static ConstString g_name("freebsd");
+    return g_name;
 }
 
 const char *
@@ -79,16 +80,10 @@ ProcessFreeBSD::GetPluginDescriptionStat
 //------------------------------------------------------------------------------
 // ProcessInterface protocol.
 
-const char *
+lldb_private::ConstString
 ProcessFreeBSD::GetPluginName()
 {
-    return "process.freebsd";
-}
-
-const char *
-ProcessFreeBSD::GetShortPluginName()
-{
-    return "process.freebsd";
+    return GetPluginNameStatic();
 }
 
 uint32_t

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h Thu Jun  6 19:06:43 2013
@@ -42,7 +42,7 @@ public:
     static void
     Terminate();
 
-    static const char *
+    static lldb_private::ConstString
     GetPluginNameStatic();
 
     static const char *
@@ -60,12 +60,9 @@ public:
     //------------------------------------------------------------------
     // PluginInterface protocol
     //------------------------------------------------------------------
-    virtual const char *
+    virtual lldb_private::ConstString
     GetPluginName();
 
-    virtual const char *
-    GetShortPluginName();
-
     virtual uint32_t
     GetPluginVersion();
 

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp Thu Jun  6 19:06:43 2013
@@ -58,13 +58,15 @@ Get_PT_IO_OP(int op)
     }
 }
 
+// Wrapper for ptrace to catch errors and log calls.
+// Note that ptrace sets errno on error because -1 is reserved as a valid result.
 extern long
-PtraceWrapper(int req, ::pid_t pid, void *addr, int data,
+PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data,
               const char* reqName, const char* file, int line)
 {
     long int result;
 
-    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
 
     if (log) {
         log->Printf("ptrace(%s, %u, %p, %x) called from file %s line %d",
@@ -84,7 +86,7 @@ PtraceWrapper(int req, ::pid_t pid, void
 
     //PtraceDisplayBytes(req, data);
 
-    if (log && (result == -1 || errno != 0))
+    if (log && errno != 0)
     {
         const char* str;
         switch (errno)
@@ -112,10 +114,21 @@ PtraceWrapper(int req, ::pid_t pid, void
     return result;
 }
 
+// Wrapper for ptrace when logging is not required.
+// Sets errno to 0 prior to calling ptrace.
+extern long
+PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data)
+{
+    long result = 0;
+    errno = 0;
+    result = ptrace(req, pid, (caddr_t)addr, data);
+    return result;
+}
+
 #define PTRACE(req, pid, addr, data) \
     PtraceWrapper((req), (pid), (addr), (data), #req, __FILE__, __LINE__)
 #else
-#define PTRACE ptrace
+    PtraceWrapper((req), (pid), (addr), (data))
 #endif
 
 //------------------------------------------------------------------------------
@@ -502,8 +515,8 @@ SingleStepOperation::Execute(ProcessMoni
 class SiginfoOperation : public Operation
 {
 public:
-    SiginfoOperation(lldb::tid_t tid, void *info, bool &result)
-        : m_tid(tid), m_info(info), m_result(result) { }
+    SiginfoOperation(lldb::tid_t tid, void *info, bool &result, int &ptrace_err)
+        : m_tid(tid), m_info(info), m_result(result), m_err(ptrace_err) { }
 
     void Execute(ProcessMonitor *monitor);
 
@@ -511,6 +524,7 @@ private:
     lldb::tid_t m_tid;
     void *m_info;
     bool &m_result;
+    int &m_err;
 };
 
 void
@@ -518,9 +532,10 @@ SiginfoOperation::Execute(ProcessMonitor
 {
     struct ptrace_lwpinfo plwp;
 
-    if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp)))
+    if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) {
         m_result = false;
-    else {
+        m_err = errno;
+    } else {
         memcpy(m_info, &plwp.pl_siginfo, sizeof(siginfo_t));
         m_result = true;
     }
@@ -625,14 +640,16 @@ ProcessMonitor::LaunchArgs::LaunchArgs(P
                                        char const **envp,
                                        const char *stdin_path,
                                        const char *stdout_path,
-                                       const char *stderr_path)
+                                       const char *stderr_path,
+                                       const char *working_dir)
     : OperationArgs(monitor),
       m_module(module),
       m_argv(argv),
       m_envp(envp),
       m_stdin_path(stdin_path),
       m_stdout_path(stdout_path),
-      m_stderr_path(stderr_path) { }
+      m_stderr_path(stderr_path),
+      m_working_dir(working_dir) { }
 
 ProcessMonitor::LaunchArgs::~LaunchArgs()
 { }
@@ -663,6 +680,7 @@ ProcessMonitor::ProcessMonitor(ProcessPO
                                const char *stdin_path,
                                const char *stdout_path,
                                const char *stderr_path,
+                               const char *working_dir,
                                lldb_private::Error &error)
     : m_process(static_cast<ProcessFreeBSD *>(process)),
       m_operation_thread(LLDB_INVALID_HOST_THREAD),
@@ -673,10 +691,10 @@ ProcessMonitor::ProcessMonitor(ProcessPO
       m_client_fd(-1),
       m_server_fd(-1)
 {
-    std::auto_ptr<LaunchArgs> args;
+    std::unique_ptr<LaunchArgs> args;
 
     args.reset(new LaunchArgs(this, module, argv, envp,
-                              stdin_path, stdout_path, stderr_path));
+                              stdin_path, stdout_path, stderr_path, working_dir));
     
 
     // Server/client descriptors.
@@ -734,7 +752,7 @@ ProcessMonitor::ProcessMonitor(ProcessPO
       m_client_fd(-1),
       m_server_fd(-1)
 {
-    std::auto_ptr<AttachArgs> args;
+    std::unique_ptr<AttachArgs> args;
 
     args.reset(new AttachArgs(this, pid));
 
@@ -837,6 +855,7 @@ ProcessMonitor::Launch(LaunchArgs *args)
     const char *stdin_path = args->m_stdin_path;
     const char *stdout_path = args->m_stdout_path;
     const char *stderr_path = args->m_stderr_path;
+    const char *working_dir = args->m_working_dir;
     lldb::pid_t pid;
 
     lldb::ThreadSP inferior;
@@ -851,6 +870,7 @@ ProcessMonitor::Launch(LaunchArgs *args)
         eDupStdinFailed,
         eDupStdoutFailed,
         eDupStderrFailed,
+        eChdirFailed,
         eExecFailed
     };
 
@@ -885,6 +905,11 @@ ProcessMonitor::Launch(LaunchArgs *args)
             if (!DupDescriptor(stderr_path, STDERR_FILENO, O_WRONLY | O_CREAT))
                 exit(eDupStderrFailed);
 
+        // Change working directory
+        if (working_dir != NULL && working_dir[0])
+          if (0 != ::chdir(working_dir))
+              exit(eChdirFailed);
+
         // Execute.  We should never return.
         execve(argv[0],
                const_cast<char *const *>(argv),
@@ -918,6 +943,9 @@ ProcessMonitor::Launch(LaunchArgs *args)
             case eDupStderrFailed: 
                 args->m_error.SetErrorString("Child open stderr failed.");
                 break;
+            case eChdirFailed:
+                args->m_error.SetErrorString("Child failed to set working directory.");
+                break;
             case eExecFailed: 
                 args->m_error.SetErrorString("Child exec failed.");
                 break;
@@ -952,7 +980,7 @@ ProcessMonitor::Launch(LaunchArgs *args)
         goto FINISH;
 
     // Update the process thread list with this new thread.
-    inferior.reset(new POSIXThread(processSP, pid));
+    inferior.reset(new POSIXThread(*processSP, pid));
     process.GetThreadList().AddThread(inferior);
 
     // Let our process instance know the thread has stopped.
@@ -1038,7 +1066,7 @@ ProcessMonitor::Attach(AttachArgs *args)
     }
 
     // Update the process thread list with the attached thread.
-    inferior.reset(new POSIXThread(processSP, pid));
+    inferior.reset(new POSIXThread(*processSP, pid));
     tl.AddThread(inferior);
 
     // Let our process instance know the thread has stopped.
@@ -1060,8 +1088,9 @@ ProcessMonitor::MonitorCallback(void *ca
     ProcessFreeBSD *process = monitor->m_process;
     bool stop_monitoring;
     siginfo_t info;
+    int ptrace_err;
 
-    if (!monitor->GetSignalInfo(pid, &info))
+    if (!monitor->GetSignalInfo(pid, &info, ptrace_err))
         stop_monitoring = true; // pid is gone.  Bail.
     else {
         switch (info.si_signo)
@@ -1088,7 +1117,8 @@ ProcessMonitor::MonitorSIGTRAP(ProcessMo
 {
     ProcessMessage message;
 
-    assert(info->si_signo == SIGTRAP && "Unexpected child signal!");
+    assert(monitor);
+    assert(info && info->si_signo == SIGTRAP && "Unexpected child signal!");
 
     switch (info->si_code)
     {
@@ -1407,7 +1437,8 @@ ProcessMonitor::WriteMemory(lldb::addr_t
 }
 
 bool
-ProcessMonitor::ReadRegisterValue(unsigned offset, unsigned size, RegisterValue &value)
+ProcessMonitor::ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char* reg_name,
+                                  unsigned size, RegisterValue &value)
 {
     bool result;
     ReadRegOperation op(offset, size, value, result);
@@ -1416,7 +1447,8 @@ ProcessMonitor::ReadRegisterValue(unsign
 }
 
 bool
-ProcessMonitor::WriteRegisterValue(unsigned offset, const RegisterValue &value)
+ProcessMonitor::WriteRegisterValue(lldb::tid_t tid, unsigned offset,
+                                   const char* reg_name, const RegisterValue &value)
 {
     bool result;
     WriteRegOperation op(offset, value, result);
@@ -1425,7 +1457,20 @@ ProcessMonitor::WriteRegisterValue(unsig
 }
 
 bool
-ProcessMonitor::ReadGPR(void *buf)
+ProcessMonitor::ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset)
+{
+    return false;
+}
+
+bool
+ProcessMonitor::WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset)
+{
+    return false;
+}
+
+
+bool
+ProcessMonitor::ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size)
 {
     bool result;
     ReadGPROperation op(buf, result);
@@ -1434,7 +1479,7 @@ ProcessMonitor::ReadGPR(void *buf)
 }
 
 bool
-ProcessMonitor::ReadFPR(void *buf)
+ProcessMonitor::ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size)
 {
     bool result;
     ReadFPROperation op(buf, result);
@@ -1443,7 +1488,7 @@ ProcessMonitor::ReadFPR(void *buf)
 }
 
 bool
-ProcessMonitor::WriteGPR(void *buf)
+ProcessMonitor::WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size)
 {
     bool result;
     WriteGPROperation op(buf, result);
@@ -1452,7 +1497,7 @@ ProcessMonitor::WriteGPR(void *buf)
 }
 
 bool
-ProcessMonitor::WriteFPR(void *buf)
+ProcessMonitor::WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size)
 {
     bool result;
     WriteFPROperation op(buf, result);
@@ -1488,10 +1533,10 @@ ProcessMonitor::BringProcessIntoLimbo()
 }
 
 bool
-ProcessMonitor::GetSignalInfo(lldb::tid_t tid, void *siginfo)
+ProcessMonitor::GetSignalInfo(lldb::tid_t tid, void *siginfo, int &ptrace_err)
 {
     bool result;
-    SiginfoOperation op(tid, siginfo, result);
+    SiginfoOperation op(tid, siginfo, result, ptrace_err);
     DoOperation(&op);
     return result;
 }
@@ -1506,7 +1551,7 @@ ProcessMonitor::GetEventMessage(lldb::ti
 }
 
 Error
-ProcessMonitor::Detach()
+ProcessMonitor::Detach(lldb::tid_t tid)
 {
     Error result;
     DetachOperation op(result);

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessMonitor.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessMonitor.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessMonitor.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessMonitor.h Thu Jun  6 19:06:43 2013
@@ -54,6 +54,7 @@ public:
                    const char *stdin_path,
                    const char *stdout_path,
                    const char *stderr_path,
+                   const char *working_dir,
                    lldb_private::Error &error);
 
     ProcessMonitor(ProcessPOSIX *process,
@@ -103,36 +104,66 @@ public:
     /// dependent) offset.
     ///
     /// This method is provided for use by RegisterContextFreeBSD derivatives.
+    /// FIXME: The FreeBSD implementation of this function should use tid in order
+    ///        to enable support for debugging threaded programs.
     bool
-    ReadRegisterValue(unsigned offset, unsigned size, lldb_private::RegisterValue &value);
+    ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
+                      unsigned size, lldb_private::RegisterValue &value);
 
     /// Writes the given value to the register identified by the given
     /// (architecture dependent) offset.
     ///
     /// This method is provided for use by RegisterContextFreeBSD derivatives.
+    /// FIXME: The FreeBSD implementation of this function should use tid in order
+    ///        to enable support for debugging threaded programs.
     bool
-    WriteRegisterValue(unsigned offset, const lldb_private::RegisterValue &value);
+    WriteRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
+                       const lldb_private::RegisterValue &value);
 
     /// Reads all general purpose registers into the specified buffer.
+    /// FIXME: The FreeBSD implementation of this function should use tid in order
+    ///        to enable support for debugging threaded programs.
     bool
-    ReadGPR(void *buf);
+    ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size);
 
     /// Reads all floating point registers into the specified buffer.
+    /// FIXME: The FreeBSD implementation of this function should use tid in order
+    ///        to enable support for debugging threaded programs.
     bool
-    ReadFPR(void *buf);
+    ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size);
+
+    /// Reads the specified register set into the specified buffer.
+    ///
+    /// This method is provided for use by RegisterContextFreeBSD derivatives.
+    /// FIXME: The FreeBSD implementation of this function should use tid in order
+    ///        to enable support for debugging threaded programs.
+    bool
+    ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
 
     /// Writes all general purpose registers into the specified buffer.
+    /// FIXME: The FreeBSD implementation of this function should use tid in order
+    ///        to enable support for debugging threaded programs.
     bool
-    WriteGPR(void *buf);
+    WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size);
 
     /// Writes all floating point registers into the specified buffer.
+    /// FIXME: The FreeBSD implementation of this function should use tid in order
+    ///        to enable support for debugging threaded programs.
     bool
-    WriteFPR(void *buf);
+    WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size);
+
+    /// Writes the specified register set into the specified buffer.
+    ///
+    /// This method is provided for use by RegisterContextFreeBSD derivatives.
+    /// FIXME: The FreeBSD implementation of this function should use tid in order
+    ///        to enable support for debugging threaded programs.
+    bool
+    WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
 
     /// Writes a siginfo_t structure corresponding to the given thread ID to the
     /// memory region pointed to by @p siginfo.
     bool
-    GetSignalInfo(lldb::tid_t tid, void *siginfo);
+    GetSignalInfo(lldb::tid_t tid, void *siginfo, int &error_no);
 
     /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
     /// corresponding to the given thread IDto the memory pointed to by @p
@@ -157,7 +188,7 @@ public:
     BringProcessIntoLimbo();
 
     lldb_private::Error
-    Detach();
+    Detach(lldb::tid_t tid);
 
 
 private:
@@ -196,7 +227,8 @@ private:
                    char const **envp,
                    const char *stdin_path,
                    const char *stdout_path,
-                   const char *stderr_path);
+                   const char *stderr_path,
+                   const char *working_dir);
 
         ~LaunchArgs();
 
@@ -206,6 +238,7 @@ private:
         const char *m_stdin_path;       // Redirect stdin or NULL.
         const char *m_stdout_path;      // Redirect stdout or NULL.
         const char *m_stderr_path;      // Redirect stderr or NULL.
+        const char *m_working_dir;      // Working directory or NULL.
     };
 
     void

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h Thu Jun  6 19:06:43 2013
@@ -1,43 +0,0 @@
-//===-- RegisterContextFreeBSD_x86_64.h ---------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_RegisterContextFreeBSD_x86_64_H_
-#define liblldb_RegisterContextFreeBSD_x86_64_H_
-
-    typedef struct _GPR
-    {
-        uint64_t r15;
-        uint64_t r14;
-        uint64_t r13;
-        uint64_t r12;
-        uint64_t r11;
-        uint64_t r10;
-        uint64_t r9;
-        uint64_t r8;
-        uint64_t rdi;
-        uint64_t rsi;
-        uint64_t rbp;
-        uint64_t rbx;
-        uint64_t rdx;
-        uint64_t rcx;
-        uint64_t rax;
-        uint32_t trapno;
-        uint16_t fs;
-        uint16_t gs;
-        uint32_t err;
-        uint16_t es;
-        uint16_t ds;
-        uint64_t rip;
-        uint64_t cs;
-        uint64_t rflags;
-        uint64_t rsp;
-        uint64_t ss;
-    } GPR;
-
-#endif

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.cpp Thu Jun  6 19:06:43 2013
@@ -64,7 +64,7 @@ ProcessLinux::Initialize()
 // Constructors and destructors.
 
 ProcessLinux::ProcessLinux(Target& target, Listener &listener)
-    : ProcessPOSIX(target, listener)
+    : ProcessPOSIX(target, listener), m_stopping_threads(false)
 {
 #if 0
     // FIXME: Putting this code in the ctor and saving the byte order in a
@@ -81,10 +81,11 @@ void
 ProcessLinux::Terminate()
 {
 }
-const char *
+lldb_private::ConstString
 ProcessLinux::GetPluginNameStatic()
 {
-    return "linux";
+    static ConstString g_name("linux");
+    return g_name;
 }
 
 const char *
@@ -97,23 +98,7 @@ ProcessLinux::GetPluginDescriptionStatic
 bool
 ProcessLinux::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
 {
-    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
-    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
-        log->Printf ("ProcessLinux::%s() (pid = %i)", __FUNCTION__, GetID());
-
-    // Update the process thread list with this new thread.
-    // FIXME: We should be using tid, not pid.
-    assert(m_monitor);
-    ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false));
-    if (!thread_sp) {
-        ProcessSP me = this->shared_from_this();
-        thread_sp.reset(new POSIXThread(me, GetID()));
-    }
-
-    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
-        log->Printf ("ProcessLinux::%s() updated pid = %i", __FUNCTION__, GetID());
-    new_thread_list.AddThread(thread_sp);
-
+    new_thread_list = old_thread_list;
     return new_thread_list.GetSize(false) > 0;
 }
 
@@ -121,16 +106,10 @@ ProcessLinux::UpdateThreadList(ThreadLis
 //------------------------------------------------------------------------------
 // ProcessInterface protocol.
 
-const char *
+lldb_private::ConstString
 ProcessLinux::GetPluginName()
 {
-    return "process.linux";
-}
-
-const char *
-ProcessLinux::GetShortPluginName()
-{
-    return "process.linux";
+    return GetPluginNameStatic();
 }
 
 uint32_t
@@ -155,3 +134,39 @@ ProcessLinux::EnablePluginLogging(Stream
 {
     return NULL;
 }
+
+// ProcessPOSIX override
+void
+ProcessLinux::StopAllThreads(lldb::tid_t stop_tid)
+{
+    // If a breakpoint occurs while we're stopping threads, we'll get back
+    // here, but we don't want to do it again.  Only the MonitorChildProcess
+    // thread calls this function, so we don't need to protect this flag.
+    if (m_stopping_threads)
+      return;
+    m_stopping_threads = true;
+
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+    if (log)
+        log->Printf ("ProcessLinux::%s() stopping all threads", __FUNCTION__);
+
+    // Walk the thread list and stop the other threads.  The thread that caused
+    // the stop should already be marked as stopped before we get here.
+    Mutex::Locker thread_list_lock(m_thread_list.GetMutex());
+
+    uint32_t thread_count = m_thread_list.GetSize(false);
+    for (uint32_t i = 0; i < thread_count; ++i)
+    {
+        POSIXThread *thread = static_cast<POSIXThread*>(
+            m_thread_list.GetThreadAtIndex(i, false).get());
+        assert(thread);
+        lldb::tid_t tid = thread->GetID();
+        if (!StateIsStoppedState(thread->GetState(), false))
+            m_monitor->StopThread(tid);
+    }
+
+    m_stopping_threads = false;
+
+    if (log)
+        log->Printf ("ProcessLinux::%s() finished", __FUNCTION__);
+}

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.h Thu Jun  6 19:06:43 2013
@@ -41,7 +41,7 @@ public:
     static void
     Terminate();
 
-    static const char *
+    static lldb_private::ConstString
     GetPluginNameStatic();
 
     static const char *
@@ -58,12 +58,9 @@ public:
     //------------------------------------------------------------------
     // PluginInterface protocol
     //------------------------------------------------------------------
-    virtual const char *
+    virtual lldb_private::ConstString
     GetPluginName();
 
-    virtual const char *
-    GetShortPluginName();
-
     virtual uint32_t
     GetPluginVersion();
 
@@ -78,11 +75,28 @@ public:
     EnablePluginLogging(lldb_private::Stream *strm,
                         lldb_private::Args &command);
 
+    //------------------------------------------------------------------
+    // Plug-in process overrides
+    //------------------------------------------------------------------
+    virtual lldb_private::UnixSignals &
+    GetUnixSignals ()
+    {
+        return m_linux_signals;
+    }
+
+    //------------------------------------------------------------------
+    // ProcessPOSIX overrides
+    //------------------------------------------------------------------
+    virtual void
+    StopAllThreads(lldb::tid_t stop_tid);
+
 private:
 
     /// Linux-specific signal set.
     LinuxSignals m_linux_signals;
 
+    // Flag to avoid recursion when stopping all threads.
+    bool m_stopping_threads;
 };
 
 #endif  // liblldb_MacOSXProcess_H_

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessMonitor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessMonitor.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessMonitor.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessMonitor.cpp Thu Jun  6 19:06:43 2013
@@ -7,15 +7,18 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "lldb/lldb-python.h"
+
 // C Includes
 #include <errno.h>
 #include <poll.h>
 #include <string.h>
+#include <stdint.h>
 #include <unistd.h>
 #include <sys/ptrace.h>
 #include <sys/socket.h>
+#include <sys/syscall.h>
 #include <sys/types.h>
-#include <sys/user.h>
 #include <sys/wait.h>
 
 // C++ Includes
@@ -37,6 +40,23 @@
 
 #define DEBUG_PTRACE_MAXBYTES 20
 
+// Support ptrace extensions even when compiled without required kernel support
+#ifndef PTRACE_GETREGSET
+  #define PTRACE_GETREGSET 0x4204
+#endif
+#ifndef PTRACE_SETREGSET
+  #define PTRACE_SETREGSET 0x4205
+#endif
+
+// Support hardware breakpoints in case it has not been defined
+#ifndef TRAP_HWBKPT
+  #define TRAP_HWBKPT 4
+#endif
+
+// Try to define a macro to encapsulate the tgkill syscall
+// fall back on kill() if tgkill isn't available
+#define tgkill(pid, tid, sig)  syscall(SYS_tgkill, pid, tid, sig)
+
 using namespace lldb_private;
 
 // FIXME: this code is host-dependent with respect to types and
@@ -61,10 +81,10 @@ DisplayBytes (lldb_private::StreamString
     }
 }
 
-static void PtraceDisplayBytes(__ptrace_request &req, void *data)
+static void PtraceDisplayBytes(int &req, void *data, size_t data_size)
 {
     StreamString buf;
-    LogSP verbose_log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (
+    Log *verbose_log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (
                                         POSIX_LOG_PTRACE | POSIX_LOG_VERBOSE));
 
     if (verbose_log)
@@ -77,36 +97,43 @@ static void PtraceDisplayBytes(__ptrace_
                 verbose_log->Printf("PTRACE_POKETEXT %s", buf.GetData());
                 break;
             }
-        case PTRACE_POKEDATA: 
+        case PTRACE_POKEDATA:
             {
                 DisplayBytes(buf, &data, 8);
                 verbose_log->Printf("PTRACE_POKEDATA %s", buf.GetData());
                 break;
             }
-        case PTRACE_POKEUSER: 
+        case PTRACE_POKEUSER:
             {
                 DisplayBytes(buf, &data, 8);
                 verbose_log->Printf("PTRACE_POKEUSER %s", buf.GetData());
                 break;
             }
-        case PTRACE_SETREGS: 
+        case PTRACE_SETREGS:
             {
-                DisplayBytes(buf, data, sizeof(user_regs_struct));
+                DisplayBytes(buf, data, data_size);
                 verbose_log->Printf("PTRACE_SETREGS %s", buf.GetData());
                 break;
             }
         case PTRACE_SETFPREGS:
             {
-                DisplayBytes(buf, data, sizeof(user_fpregs_struct));
+                DisplayBytes(buf, data, data_size);
                 verbose_log->Printf("PTRACE_SETFPREGS %s", buf.GetData());
                 break;
             }
-        case PTRACE_SETSIGINFO: 
+        case PTRACE_SETSIGINFO:
             {
                 DisplayBytes(buf, data, sizeof(siginfo_t));
                 verbose_log->Printf("PTRACE_SETSIGINFO %s", buf.GetData());
                 break;
             }
+        case PTRACE_SETREGSET:
+            {
+                // Extract iov_base from data, which is a pointer to the struct IOVEC
+                DisplayBytes(buf, *(void **)data, data_size);
+                verbose_log->Printf("PTRACE_SETREGSET %s", buf.GetData());
+                break;
+            }
         default:
             {
             }
@@ -115,26 +142,30 @@ static void PtraceDisplayBytes(__ptrace_
 }
 
 // Wrapper for ptrace to catch errors and log calls.
+// Note that ptrace sets errno on error because -1 can be a valid result (i.e. for PTRACE_PEEK*)
 extern long
-PtraceWrapper(__ptrace_request req, pid_t pid, void *addr, void *data,
+PtraceWrapper(int req, lldb::pid_t pid, void *addr, void *data, size_t data_size,
               const char* reqName, const char* file, int line)
 {
     long int result;
 
-    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PTRACE));
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PTRACE));
 
     if (log)
-        log->Printf("ptrace(%s, %u, %p, %p) called from file %s line %d",
-                    reqName, pid, addr, data, file, line);
-    
-    PtraceDisplayBytes(req, data);
+        log->Printf("ptrace(%s, %lu, %p, %p, %zu) called from file %s line %d",
+                    reqName, pid, addr, data, data_size, file, line);
+
+    PtraceDisplayBytes(req, data, data_size);
 
     errno = 0;
-    result = ptrace(req, pid, addr, data);
+    if (req == PTRACE_GETREGSET || req == PTRACE_SETREGSET)
+        result = ptrace(static_cast<__ptrace_request>(req), pid, *(unsigned int *)addr, data);
+    else
+        result = ptrace(static_cast<__ptrace_request>(req), pid, addr, data);
 
-    PtraceDisplayBytes(req, data);
+    PtraceDisplayBytes(req, data, data_size);
 
-    if (log && (result == -1 || errno != 0))
+    if (log && errno != 0)
     {
         const char* str;
         switch (errno)
@@ -151,10 +182,24 @@ PtraceWrapper(__ptrace_request req, pid_
     return result;
 }
 
-#define PTRACE(req, pid, addr, data) \
-    PtraceWrapper((req), (pid), (addr), (data), #req, __FILE__, __LINE__)
+// Wrapper for ptrace when logging is not required.
+// Sets errno to 0 prior to calling ptrace.
+extern long
+PtraceWrapper(int req, pid_t pid, void *addr, void *data, size_t data_size)
+{
+    long result = 0;
+    errno = 0;
+    if (req == PTRACE_GETREGSET || req == PTRACE_SETREGSET)
+        result = ptrace(static_cast<__ptrace_request>(req), pid, *(unsigned int *)addr, data);
+    else
+        result = ptrace(static_cast<__ptrace_request>(req), pid, addr, data);
+    return result;
+}
+
+#define PTRACE(req, pid, addr, data, data_size) \
+    PtraceWrapper((req), (pid), (addr), (data), (data_size), #req, __FILE__, __LINE__)
 #else
-#define PTRACE ptrace
+    PtraceWrapper((req), (pid), (addr), (data), (data_size))
 #endif
 
 //------------------------------------------------------------------------------
@@ -163,28 +208,29 @@ PtraceWrapper(__ptrace_request req, pid_
 // functions without needed to go thru the thread funnel.
 
 static size_t
-DoReadMemory(lldb::pid_t pid, unsigned word_size,
+DoReadMemory(lldb::pid_t pid,
              lldb::addr_t vm_addr, void *buf, size_t size, Error &error)
 {
+    // ptrace word size is determined by the host, not the child
+    static const unsigned word_size = sizeof(void*);
     unsigned char *dst = static_cast<unsigned char*>(buf);
     size_t bytes_read;
     size_t remainder;
     long data;
 
-    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL));
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL));
     if (log)
         ProcessPOSIXLog::IncNestLevel();
     if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY))
-        log->Printf ("ProcessMonitor::%s(%d, %d, %p, %p, %d, _)", __FUNCTION__,
+        log->Printf ("ProcessMonitor::%s(%" PRIu64 ", %d, %p, %p, %zd, _)", __FUNCTION__,
                      pid, word_size, (void*)vm_addr, buf, size);
 
     assert(sizeof(data) >= word_size);
-    assert(sizeof(void*) == word_size);
     for (bytes_read = 0; bytes_read < size; bytes_read += remainder)
     {
         errno = 0;
-        data = PTRACE(PTRACE_PEEKDATA, pid, (void*)vm_addr, NULL);
-        if (data == -1L && errno)
+        data = PTRACE(PTRACE_PEEKDATA, pid, (void*)vm_addr, NULL, 0);
+        if (errno)
         {
             error.SetErrorToErrno();
             if (log)
@@ -196,8 +242,6 @@ DoReadMemory(lldb::pid_t pid, unsigned w
         remainder = remainder > word_size ? word_size : remainder;
 
         // Copy the data into our buffer
-        if (log)
-            memset(dst, 0, sizeof(dst));
         for (unsigned i = 0; i < remainder; ++i)
             dst[i] = ((data >> i*8) & 0xFF);
 
@@ -205,8 +249,14 @@ DoReadMemory(lldb::pid_t pid, unsigned w
             (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) ||
              (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) &&
               size <= POSIX_LOG_MEMORY_SHORT_BYTES)))
-            log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
-                         (void*)vm_addr, *(unsigned long*)dst, (unsigned long)data);
+            {
+                uintptr_t print_dst = 0;
+                // Format bytes from data by moving into print_dst for log output
+                for (unsigned i = 0; i < remainder; ++i)
+                    print_dst |= (((data >> i*8) & 0xFF) << i*8);
+                log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
+                             (void*)vm_addr, print_dst, (unsigned long)data);
+            }
 
         vm_addr += word_size;
         dst += word_size;
@@ -218,21 +268,22 @@ DoReadMemory(lldb::pid_t pid, unsigned w
 }
 
 static size_t
-DoWriteMemory(lldb::pid_t pid, unsigned word_size,
+DoWriteMemory(lldb::pid_t pid,
               lldb::addr_t vm_addr, const void *buf, size_t size, Error &error)
 {
+    // ptrace word size is determined by the host, not the child
+    static const unsigned word_size = sizeof(void*);
     const unsigned char *src = static_cast<const unsigned char*>(buf);
     size_t bytes_written = 0;
     size_t remainder;
 
-    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL));
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL));
     if (log)
         ProcessPOSIXLog::IncNestLevel();
     if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY))
-        log->Printf ("ProcessMonitor::%s(%d, %d, %p, %p, %d, _)", __FUNCTION__,
+        log->Printf ("ProcessMonitor::%s(%" PRIu64 ", %d, %p, %p, %zd, _)", __FUNCTION__,
                      pid, word_size, (void*)vm_addr, buf, size);
 
-    assert(sizeof(void*) == word_size);
     for (bytes_written = 0; bytes_written < size; bytes_written += remainder)
     {
         remainder = size - bytes_written;
@@ -252,7 +303,7 @@ DoWriteMemory(lldb::pid_t pid, unsigned
                  log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
                               (void*)vm_addr, *(unsigned long*)src, data);
 
-            if (PTRACE(PTRACE_POKEDATA, pid, (void*)vm_addr, (void*)data))
+            if (PTRACE(PTRACE_POKEDATA, pid, (void*)vm_addr, (void*)data, 0))
             {
                 error.SetErrorToErrno();
                 if (log)
@@ -263,7 +314,7 @@ DoWriteMemory(lldb::pid_t pid, unsigned
         else
         {
             unsigned char buff[8];
-            if (DoReadMemory(pid, word_size, vm_addr,
+            if (DoReadMemory(pid, vm_addr,
                              buff, word_size, error) != word_size)
             {
                 if (log)
@@ -273,7 +324,7 @@ DoWriteMemory(lldb::pid_t pid, unsigned
 
             memcpy(buff, src, remainder);
 
-            if (DoWriteMemory(pid, word_size, vm_addr,
+            if (DoWriteMemory(pid, vm_addr,
                               buff, word_size, error) != word_size)
             {
                 if (log)
@@ -333,6 +384,7 @@ EnsureFDFlags(int fd, int flags, Error &
 class Operation
 {
 public:
+    virtual ~Operation() {}
     virtual void Execute(ProcessMonitor *monitor) = 0;
 };
 
@@ -361,10 +413,9 @@ private:
 void
 ReadOperation::Execute(ProcessMonitor *monitor)
 {
-    const unsigned word_size = monitor->GetProcess().GetAddressByteSize();
     lldb::pid_t pid = monitor->GetPID();
 
-    m_result = DoReadMemory(pid, word_size, m_addr, m_buff, m_size, m_error);
+    m_result = DoReadMemory(pid, m_addr, m_buff, m_size, m_error);
 }
 
 //------------------------------------------------------------------------------
@@ -392,10 +443,9 @@ private:
 void
 WriteOperation::Execute(ProcessMonitor *monitor)
 {
-    const unsigned word_size = monitor->GetProcess().GetAddressByteSize();
     lldb::pid_t pid = monitor->GetPID();
 
-    m_result = DoWriteMemory(pid, word_size, m_addr, m_buff, m_size, m_error);
+    m_result = DoWriteMemory(pid, m_addr, m_buff, m_size, m_error);
 }
 
 
@@ -405,14 +455,18 @@ WriteOperation::Execute(ProcessMonitor *
 class ReadRegOperation : public Operation
 {
 public:
-    ReadRegOperation(unsigned offset, RegisterValue &value, bool &result)
-        : m_offset(offset), m_value(value), m_result(result)
+    ReadRegOperation(lldb::tid_t tid, unsigned offset, const char *reg_name,
+                     RegisterValue &value, bool &result)
+        : m_tid(tid), m_offset(offset), m_reg_name(reg_name),
+          m_value(value), m_result(result)
         { }
 
     void Execute(ProcessMonitor *monitor);
 
 private:
-    unsigned m_offset;
+    lldb::tid_t m_tid;
+    uintptr_t m_offset;
+    const char *m_reg_name;
     RegisterValue &m_value;
     bool &m_result;
 };
@@ -420,13 +474,12 @@ private:
 void
 ReadRegOperation::Execute(ProcessMonitor *monitor)
 {
-    lldb::pid_t pid = monitor->GetPID();
-    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
 
     // Set errno to zero so that we can detect a failed peek.
     errno = 0;
-    lldb::addr_t data = PTRACE(PTRACE_PEEKUSER, pid, (void*)m_offset, NULL);
-    if (data == -1UL && errno)
+    lldb::addr_t data = PTRACE(PTRACE_PEEKUSER, m_tid, (void*)m_offset, NULL, 0);
+    if (errno)
         m_result = false;
     else
     {
@@ -434,8 +487,8 @@ ReadRegOperation::Execute(ProcessMonitor
         m_result = true;
     }
     if (log)
-        log->Printf ("ProcessMonitor::%s() reg %s: 0x%x", __FUNCTION__,
-                     POSIXThread::GetRegisterNameFromOffset(m_offset), data);
+        log->Printf ("ProcessMonitor::%s() reg %s: 0x%" PRIx64, __FUNCTION__,
+                     m_reg_name, data);
 }
 
 //------------------------------------------------------------------------------
@@ -444,14 +497,18 @@ ReadRegOperation::Execute(ProcessMonitor
 class WriteRegOperation : public Operation
 {
 public:
-    WriteRegOperation(unsigned offset, const RegisterValue &value, bool &result)
-        : m_offset(offset), m_value(value), m_result(result)
+    WriteRegOperation(lldb::tid_t tid, unsigned offset, const char *reg_name,
+                      const RegisterValue &value, bool &result)
+        : m_tid(tid), m_offset(offset), m_reg_name(reg_name),
+          m_value(value), m_result(result)
         { }
 
     void Execute(ProcessMonitor *monitor);
 
 private:
-    unsigned m_offset;
+    lldb::tid_t m_tid;
+    uintptr_t m_offset;
+    const char *m_reg_name;
     const RegisterValue &m_value;
     bool &m_result;
 };
@@ -460,21 +517,17 @@ void
 WriteRegOperation::Execute(ProcessMonitor *monitor)
 {
     void* buf;
-    lldb::pid_t pid = monitor->GetPID();
-    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
 
-    if (sizeof(void*) == sizeof(uint64_t))
-        buf = (void*) m_value.GetAsUInt64();
-    else
-    {
-        assert(sizeof(void*) == sizeof(uint32_t));
-        buf = (void*) m_value.GetAsUInt32();
-    }
+#if __WORDSIZE == 32
+    buf = (void*) m_value.GetAsUInt32();
+#else
+    buf = (void*) m_value.GetAsUInt64();
+#endif
 
     if (log)
-        log->Printf ("ProcessMonitor::%s() reg %s: %p", __FUNCTION__,
-                     POSIXThread::GetRegisterNameFromOffset(m_offset), buf);
-    if (PTRACE(PTRACE_POKEUSER, pid, (void*)m_offset, buf))
+        log->Printf ("ProcessMonitor::%s() reg %s: %p", __FUNCTION__, m_reg_name, buf);
+    if (PTRACE(PTRACE_POKEUSER, m_tid, (void*)m_offset, buf, 0))
         m_result = false;
     else
         m_result = true;
@@ -486,21 +539,23 @@ WriteRegOperation::Execute(ProcessMonito
 class ReadGPROperation : public Operation
 {
 public:
-    ReadGPROperation(void *buf, bool &result)
-        : m_buf(buf), m_result(result)
+    ReadGPROperation(lldb::tid_t tid, void *buf, size_t buf_size, bool &result)
+        : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_result(result)
         { }
 
     void Execute(ProcessMonitor *monitor);
 
 private:
+    lldb::tid_t m_tid;
     void *m_buf;
+    size_t m_buf_size;
     bool &m_result;
 };
 
 void
 ReadGPROperation::Execute(ProcessMonitor *monitor)
 {
-    if (PTRACE(PTRACE_GETREGS, monitor->GetPID(), NULL, m_buf) < 0)
+    if (PTRACE(PTRACE_GETREGS, m_tid, NULL, m_buf, m_buf_size) < 0)
         m_result = false;
     else
         m_result = true;
@@ -512,21 +567,52 @@ ReadGPROperation::Execute(ProcessMonitor
 class ReadFPROperation : public Operation
 {
 public:
-    ReadFPROperation(void *buf, bool &result)
-        : m_buf(buf), m_result(result)
+    ReadFPROperation(lldb::tid_t tid, void *buf, size_t buf_size, bool &result)
+        : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_result(result)
         { }
 
     void Execute(ProcessMonitor *monitor);
 
 private:
+    lldb::tid_t m_tid;
     void *m_buf;
+    size_t m_buf_size;
     bool &m_result;
 };
 
 void
 ReadFPROperation::Execute(ProcessMonitor *monitor)
 {
-    if (PTRACE(PTRACE_GETFPREGS, monitor->GetPID(), NULL, m_buf) < 0)
+    if (PTRACE(PTRACE_GETFPREGS, m_tid, NULL, m_buf, m_buf_size) < 0)
+        m_result = false;
+    else
+        m_result = true;
+}
+
+//------------------------------------------------------------------------------
+/// @class ReadRegisterSetOperation
+/// @brief Implements ProcessMonitor::ReadRegisterSet.
+class ReadRegisterSetOperation : public Operation
+{
+public:
+    ReadRegisterSetOperation(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset, bool &result)
+        : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_regset(regset), m_result(result)
+        { }
+
+    void Execute(ProcessMonitor *monitor);
+
+private:
+    lldb::tid_t m_tid;
+    void *m_buf;
+    size_t m_buf_size;
+    const unsigned int m_regset;
+    bool &m_result;
+};
+
+void
+ReadRegisterSetOperation::Execute(ProcessMonitor *monitor)
+{
+    if (PTRACE(PTRACE_GETREGSET, m_tid, (void *)&m_regset, m_buf, m_buf_size) < 0)
         m_result = false;
     else
         m_result = true;
@@ -538,21 +624,23 @@ ReadFPROperation::Execute(ProcessMonitor
 class WriteGPROperation : public Operation
 {
 public:
-    WriteGPROperation(void *buf, bool &result)
-        : m_buf(buf), m_result(result)
+    WriteGPROperation(lldb::tid_t tid, void *buf, size_t buf_size, bool &result)
+        : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_result(result)
         { }
 
     void Execute(ProcessMonitor *monitor);
 
 private:
+    lldb::tid_t m_tid;
     void *m_buf;
+    size_t m_buf_size;
     bool &m_result;
 };
 
 void
 WriteGPROperation::Execute(ProcessMonitor *monitor)
 {
-    if (PTRACE(PTRACE_SETREGS, monitor->GetPID(), NULL, m_buf) < 0)
+    if (PTRACE(PTRACE_SETREGS, m_tid, NULL, m_buf, m_buf_size) < 0)
         m_result = false;
     else
         m_result = true;
@@ -564,21 +652,52 @@ WriteGPROperation::Execute(ProcessMonito
 class WriteFPROperation : public Operation
 {
 public:
-    WriteFPROperation(void *buf, bool &result)
-        : m_buf(buf), m_result(result)
+    WriteFPROperation(lldb::tid_t tid, void *buf, size_t buf_size, bool &result)
+        : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_result(result)
         { }
 
     void Execute(ProcessMonitor *monitor);
 
 private:
+    lldb::tid_t m_tid;
     void *m_buf;
+    size_t m_buf_size;
     bool &m_result;
 };
 
 void
 WriteFPROperation::Execute(ProcessMonitor *monitor)
 {
-    if (PTRACE(PTRACE_SETFPREGS, monitor->GetPID(), NULL, m_buf) < 0)
+    if (PTRACE(PTRACE_SETFPREGS, m_tid, NULL, m_buf, m_buf_size) < 0)
+        m_result = false;
+    else
+        m_result = true;
+}
+
+//------------------------------------------------------------------------------
+/// @class WriteRegisterSetOperation
+/// @brief Implements ProcessMonitor::WriteRegisterSet.
+class WriteRegisterSetOperation : public Operation
+{
+public:
+    WriteRegisterSetOperation(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset, bool &result)
+        : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_regset(regset), m_result(result)
+        { }
+
+    void Execute(ProcessMonitor *monitor);
+
+private:
+    lldb::tid_t m_tid;
+    void *m_buf;
+    size_t m_buf_size;
+    const unsigned int m_regset;
+    bool &m_result;
+};
+
+void
+WriteRegisterSetOperation::Execute(ProcessMonitor *monitor)
+{
+    if (PTRACE(PTRACE_SETREGSET, m_tid, (void *)&m_regset, m_buf, m_buf_size) < 0)
         m_result = false;
     else
         m_result = true;
@@ -604,13 +723,19 @@ private:
 void
 ResumeOperation::Execute(ProcessMonitor *monitor)
 {
-    int data = 0;
+    intptr_t data = 0;
 
     if (m_signo != LLDB_INVALID_SIGNAL_NUMBER)
         data = m_signo;
 
-    if (PTRACE(PTRACE_CONT, m_tid, NULL, (void*)data))
+    if (PTRACE(PTRACE_CONT, m_tid, NULL, (void*)data, 0))
+    {
+        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+
+        if (log)
+            log->Printf ("ResumeOperation (%"  PRIu64 ") failed: %s", m_tid, strerror(errno));
         m_result = false;
+    }
     else
         m_result = true;
 }
@@ -635,12 +760,12 @@ private:
 void
 SingleStepOperation::Execute(ProcessMonitor *monitor)
 {
-    int data = 0;
+    intptr_t data = 0;
 
     if (m_signo != LLDB_INVALID_SIGNAL_NUMBER)
         data = m_signo;
 
-    if (PTRACE(PTRACE_SINGLESTEP, m_tid, NULL, (void*)data))
+    if (PTRACE(PTRACE_SINGLESTEP, m_tid, NULL, (void*)data, 0))
         m_result = false;
     else
         m_result = true;
@@ -652,8 +777,8 @@ SingleStepOperation::Execute(ProcessMoni
 class SiginfoOperation : public Operation
 {
 public:
-    SiginfoOperation(lldb::tid_t tid, void *info, bool &result)
-        : m_tid(tid), m_info(info), m_result(result) { }
+    SiginfoOperation(lldb::tid_t tid, void *info, bool &result, int &ptrace_err)
+        : m_tid(tid), m_info(info), m_result(result), m_err(ptrace_err) { }
 
     void Execute(ProcessMonitor *monitor);
 
@@ -661,13 +786,16 @@ private:
     lldb::tid_t m_tid;
     void *m_info;
     bool &m_result;
+    int &m_err;
 };
 
 void
 SiginfoOperation::Execute(ProcessMonitor *monitor)
 {
-    if (PTRACE(PTRACE_GETSIGINFO, m_tid, NULL, m_info))
+    if (PTRACE(PTRACE_GETSIGINFO, m_tid, NULL, m_info, 0)) {
         m_result = false;
+        m_err = errno;
+    }
     else
         m_result = true;
 }
@@ -692,7 +820,7 @@ private:
 void
 EventMessageOperation::Execute(ProcessMonitor *monitor)
 {
-    if (PTRACE(PTRACE_GETEVENTMSG, m_tid, NULL, m_message))
+    if (PTRACE(PTRACE_GETEVENTMSG, m_tid, NULL, m_message, 0))
         m_result = false;
     else
         m_result = true;
@@ -717,7 +845,7 @@ KillOperation::Execute(ProcessMonitor *m
 {
     lldb::pid_t pid = monitor->GetPID();
 
-    if (PTRACE(PTRACE_KILL, pid, NULL, NULL))
+    if (PTRACE(PTRACE_KILL, pid, NULL, NULL, 0))
         m_result = false;
     else
         m_result = true;
@@ -729,22 +857,20 @@ KillOperation::Execute(ProcessMonitor *m
 class DetachOperation : public Operation
 {
 public:
-    DetachOperation(Error &result) : m_error(result) { }
+    DetachOperation(lldb::tid_t tid, Error &result) : m_tid(tid), m_error(result) { }
 
     void Execute(ProcessMonitor *monitor);
 
 private:
+    lldb::tid_t m_tid;
     Error &m_error;
 };
 
 void
 DetachOperation::Execute(ProcessMonitor *monitor)
 {
-    lldb::pid_t pid = monitor->GetPID();
-
-    if (ptrace(PT_DETACH, pid, NULL, 0) < 0)
+    if (ptrace(PT_DETACH, m_tid, NULL, 0) < 0)
         m_error.SetErrorToErrno();
-  
 }
 
 ProcessMonitor::OperationArgs::OperationArgs(ProcessMonitor *monitor)
@@ -764,14 +890,16 @@ ProcessMonitor::LaunchArgs::LaunchArgs(P
                                        char const **envp,
                                        const char *stdin_path,
                                        const char *stdout_path,
-                                       const char *stderr_path)
+                                       const char *stderr_path,
+                                       const char *working_dir)
     : OperationArgs(monitor),
       m_module(module),
       m_argv(argv),
       m_envp(envp),
       m_stdin_path(stdin_path),
       m_stdout_path(stdout_path),
-      m_stderr_path(stderr_path) { }
+      m_stderr_path(stderr_path),
+      m_working_dir(working_dir) { }
 
 ProcessMonitor::LaunchArgs::~LaunchArgs()
 { }
@@ -802,19 +930,20 @@ ProcessMonitor::ProcessMonitor(ProcessPO
                                const char *stdin_path,
                                const char *stdout_path,
                                const char *stderr_path,
+                               const char *working_dir,
                                lldb_private::Error &error)
     : m_process(static_cast<ProcessLinux *>(process)),
       m_operation_thread(LLDB_INVALID_HOST_THREAD),
+      m_monitor_thread(LLDB_INVALID_HOST_THREAD),
       m_pid(LLDB_INVALID_PROCESS_ID),
       m_terminal_fd(-1),
-      m_monitor_thread(LLDB_INVALID_HOST_THREAD),
       m_client_fd(-1),
       m_server_fd(-1)
 {
-    std::auto_ptr<LaunchArgs> args;
+    std::unique_ptr<LaunchArgs> args;
 
     args.reset(new LaunchArgs(this, module, argv, envp,
-                              stdin_path, stdout_path, stderr_path));
+                              stdin_path, stdout_path, stderr_path, working_dir));
 
     // Server/client descriptors.
     if (!EnableIPC())
@@ -843,7 +972,7 @@ WAIT_AGAIN:
     // Check that the launch was a success.
     if (!args->m_error.Success())
     {
-        StopLaunchOpThread();
+        StopOpThread();
         error = args->m_error;
         return;
     }
@@ -864,13 +993,14 @@ ProcessMonitor::ProcessMonitor(ProcessPO
                                lldb_private::Error &error)
   : m_process(static_cast<ProcessLinux *>(process)),
       m_operation_thread(LLDB_INVALID_HOST_THREAD),
+      m_monitor_thread(LLDB_INVALID_HOST_THREAD),
       m_pid(LLDB_INVALID_PROCESS_ID),
       m_terminal_fd(-1),
-      m_monitor_thread(LLDB_INVALID_HOST_THREAD),
+
       m_client_fd(-1),
       m_server_fd(-1)
 {
-    std::auto_ptr<AttachArgs> args;
+    std::unique_ptr<AttachArgs> args;
 
     args.reset(new AttachArgs(this, pid));
 
@@ -898,10 +1028,10 @@ WAIT_AGAIN:
         }
     }
 
-    // Check that the launch was a success.
+    // Check that the attach was a success.
     if (!args->m_error.Success())
     {
-        StopAttachOpThread();
+        StopOpThread();
         error = args->m_error;
         return;
     }
@@ -936,18 +1066,6 @@ ProcessMonitor::StartLaunchOpThread(Laun
         Host::ThreadCreate(g_thread_name, LaunchOpThread, args, &error);
 }
 
-void
-ProcessMonitor::StopLaunchOpThread()
-{
-    lldb::thread_result_t result;
-
-    if (!IS_VALID_LLDB_HOST_THREAD(m_operation_thread))
-        return;
-
-    Host::ThreadCancel(m_operation_thread, NULL);
-    Host::ThreadJoin(m_operation_thread, &result, NULL);
-}
-
 void *
 ProcessMonitor::LaunchOpThread(void *arg)
 {
@@ -967,12 +1085,12 @@ ProcessMonitor::Launch(LaunchArgs *args)
 {
     ProcessMonitor *monitor = args->m_monitor;
     ProcessLinux &process = monitor->GetProcess();
-    lldb::ProcessSP processSP = process.shared_from_this();
     const char **argv = args->m_argv;
     const char **envp = args->m_envp;
     const char *stdin_path = args->m_stdin_path;
     const char *stdout_path = args->m_stdout_path;
     const char *stderr_path = args->m_stderr_path;
+    const char *working_dir = args->m_working_dir;
 
     lldb_utility::PseudoTerminal terminal;
     const size_t err_len = 1024;
@@ -980,7 +1098,7 @@ ProcessMonitor::Launch(LaunchArgs *args)
     lldb::pid_t pid;
 
     lldb::ThreadSP inferior;
-    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
 
     // Propagate the environment if one is not supplied.
     if (envp == NULL || envp[0] == NULL)
@@ -994,7 +1112,7 @@ ProcessMonitor::Launch(LaunchArgs *args)
         goto FINISH;
     }
 
-    if ((pid = terminal.Fork(err_str, err_len)) < 0)
+    if ((pid = terminal.Fork(err_str, err_len)) == -1)
     {
         args->m_error.SetErrorToGenericError();
         args->m_error.SetErrorString("Process fork failed.");
@@ -1007,6 +1125,7 @@ ProcessMonitor::Launch(LaunchArgs *args)
         eDupStdinFailed,
         eDupStdoutFailed,
         eDupStderrFailed,
+        eChdirFailed,
         eExecFailed
     };
 
@@ -1014,7 +1133,7 @@ ProcessMonitor::Launch(LaunchArgs *args)
     if (pid == 0)
     {
         // Trace this process.
-        if (PTRACE(PTRACE_TRACEME, 0, NULL, NULL) < 0)
+        if (PTRACE(PTRACE_TRACEME, 0, NULL, NULL, 0) < 0)
             exit(ePtraceFailed);
 
         // Do not inherit setgid powers.
@@ -1039,6 +1158,11 @@ ProcessMonitor::Launch(LaunchArgs *args)
             if (!DupDescriptor(stderr_path, STDERR_FILENO, O_WRONLY | O_CREAT))
                 exit(eDupStderrFailed);
 
+        // Change working directory
+        if (working_dir != NULL && working_dir[0])
+          if (0 != ::chdir(working_dir))
+              exit(eChdirFailed);
+
         // Execute.  We should never return.
         execve(argv[0],
                const_cast<char *const *>(argv),
@@ -1060,22 +1184,25 @@ ProcessMonitor::Launch(LaunchArgs *args)
         args->m_error.SetErrorToGenericError();
         switch (WEXITSTATUS(status))
         {
-            case ePtraceFailed: 
+            case ePtraceFailed:
                 args->m_error.SetErrorString("Child ptrace failed.");
                 break;
-            case eDupStdinFailed: 
+            case eDupStdinFailed:
                 args->m_error.SetErrorString("Child open stdin failed.");
                 break;
-            case eDupStdoutFailed: 
+            case eDupStdoutFailed:
                 args->m_error.SetErrorString("Child open stdout failed.");
                 break;
-            case eDupStderrFailed: 
+            case eDupStderrFailed:
                 args->m_error.SetErrorString("Child open stderr failed.");
                 break;
-            case eExecFailed: 
+            case eChdirFailed:
+                args->m_error.SetErrorString("Child failed to set working directory.");
+                break;
+            case eExecFailed:
                 args->m_error.SetErrorString("Child exec failed.");
                 break;
-            default: 
+            default:
                 args->m_error.SetErrorString("Child returned unknown exit status.");
                 break;
         }
@@ -1084,9 +1211,7 @@ ProcessMonitor::Launch(LaunchArgs *args)
     assert(WIFSTOPPED(status) && wpid == pid &&
            "Could not sync with inferior process.");
 
-    // Have the child raise an event on exit.  This is used to keep the child in
-    // limbo until it is destroyed.
-    if (PTRACE(PTRACE_SETOPTIONS, pid, NULL, (void*)PTRACE_O_TRACEEXIT) < 0)
+    if (!SetDefaultPtraceOpts(pid))
     {
         args->m_error.SetErrorToErrno();
         goto FINISH;
@@ -1106,9 +1231,9 @@ ProcessMonitor::Launch(LaunchArgs *args)
     // Update the process thread list with this new thread.
     // FIXME: should we be letting UpdateThreadList handle this?
     // FIXME: by using pids instead of tids, we can only support one thread.
-    inferior.reset(new POSIXThread(processSP, pid));
+    inferior.reset(new POSIXThread(process, pid));
     if (log)
-        log->Printf ("ProcessMonitor::%s() adding pid = %i", __FUNCTION__, pid);
+        log->Printf ("ProcessMonitor::%s() adding pid = %" PRIu64, __FUNCTION__, pid);
     process.GetThreadList().AddThread(inferior);
 
     // Let our process instance know the thread has stopped.
@@ -1143,19 +1268,15 @@ ProcessMonitor::StartAttachOpThread(Atta
         Host::ThreadCreate(g_thread_name, AttachOpThread, args, &error);
 }
 
-void
-ProcessMonitor::StopAttachOpThread()
-{
-    assert(!"Not implemented yet!!!");
-}
-
 void *
 ProcessMonitor::AttachOpThread(void *arg)
 {
     AttachArgs *args = static_cast<AttachArgs*>(arg);
 
-    if (!Attach(args))
+    if (!Attach(args)) {
+        sem_post(&args->m_semaphore);
         return NULL;
+    }
 
     ServeOperation(args);
     return NULL;
@@ -1168,9 +1289,11 @@ ProcessMonitor::Attach(AttachArgs *args)
 
     ProcessMonitor *monitor = args->m_monitor;
     ProcessLinux &process = monitor->GetProcess();
-    lldb::ProcessSP processSP = process.shared_from_this();
     lldb::ThreadSP inferior;
-    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+
+    // Use a map to keep track of the threads which we have attached/need to attach.
+    Host::TidMap tids_to_attach;
 
     if (pid <= 1)
     {
@@ -1179,34 +1302,106 @@ ProcessMonitor::Attach(AttachArgs *args)
         goto FINISH;
     }
 
-    // Attach to the requested process.
-    if (PTRACE(PTRACE_ATTACH, pid, NULL, NULL) < 0)
+    while (Host::FindProcessThreads(pid, tids_to_attach))
     {
-        args->m_error.SetErrorToErrno();
-        goto FINISH;
+        for (Host::TidMap::iterator it = tids_to_attach.begin();
+             it != tids_to_attach.end(); ++it)
+        {
+            if (it->second == false)
+            {
+                lldb::tid_t tid = it->first;
+
+                // Attach to the requested process.
+                // An attach will cause the thread to stop with a SIGSTOP.
+                if (PTRACE(PTRACE_ATTACH, tid, NULL, NULL, 0) < 0)
+                {
+                    // No such thread. The thread may have exited.
+                    // More error handling may be needed.
+                    if (errno == ESRCH)
+                    {
+                        tids_to_attach.erase(it);
+                        continue;
+                    }
+                    else
+                    {
+                        args->m_error.SetErrorToErrno();
+                        goto FINISH;
+                    }
+                }
+
+                int status;
+                // Need to use __WALL otherwise we receive an error with errno=ECHLD
+                // At this point we should have a thread stopped if waitpid succeeds.
+                if ((status = waitpid(tid, NULL, __WALL)) < 0)
+                {
+                    // No such thread. The thread may have exited.
+                    // More error handling may be needed.
+                    if (errno == ESRCH)
+                    {
+                        tids_to_attach.erase(it);
+                        continue;
+                    }
+                    else
+                    {
+                        args->m_error.SetErrorToErrno();
+                        goto FINISH;
+                    }
+                }
+
+                if (!SetDefaultPtraceOpts(tid))
+                {
+                    args->m_error.SetErrorToErrno();
+                    goto FINISH;
+                }
+
+                // Update the process thread list with the attached thread.
+                inferior.reset(new POSIXThread(process, tid));
+                if (log)
+                    log->Printf ("ProcessMonitor::%s() adding tid = %" PRIu64, __FUNCTION__, tid);
+                process.GetThreadList().AddThread(inferior);
+                it->second = true;
+            }
+        }
     }
 
-    int status;
-    if ((status = waitpid(pid, NULL, 0)) < 0)
+    if (tids_to_attach.size() > 0)
     {
-        args->m_error.SetErrorToErrno();
-        goto FINISH;
+        monitor->m_pid = pid;
+        // Let our process instance know the thread has stopped.
+        process.SendMessage(ProcessMessage::Trace(pid));
+    }
+    else
+    {
+        args->m_error.SetErrorToGenericError();
+        args->m_error.SetErrorString("No such process.");
     }
-
-    // Update the process thread list with the attached thread.
-    inferior.reset(new POSIXThread(processSP, pid));
-    if (log)
-        log->Printf ("ProcessMonitor::%s() adding tid = %i", __FUNCTION__, pid);
-    process.GetThreadList().AddThread(inferior);
-
-    // Let our process instance know the thread has stopped.
-    process.SendMessage(ProcessMessage::Trace(pid));
 
  FINISH:
     return args->m_error.Success();
 }
 
 bool
+ProcessMonitor::SetDefaultPtraceOpts(lldb::pid_t pid)
+{
+    long ptrace_opts = 0;
+
+    // Have the child raise an event on exit.  This is used to keep the child in
+    // limbo until it is destroyed.
+    ptrace_opts |= PTRACE_O_TRACEEXIT;
+
+    // Have the tracer trace threads which spawn in the inferior process.
+    // TODO: if we want to support tracing the inferiors' child, add the
+    // appropriate ptrace flags here (PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK)
+    ptrace_opts |= PTRACE_O_TRACECLONE;
+
+    // Have the tracer notify us before execve returns
+    // (needed to disable legacy SIGTRAP generation)
+    ptrace_opts |= PTRACE_O_TRACEEXEC;
+
+    return PTRACE(PTRACE_SETOPTIONS, pid, NULL, (void*)ptrace_opts, 0) >= 0;
+}
+
+bool
 ProcessMonitor::MonitorCallback(void *callback_baton,
                                 lldb::pid_t pid,
                                 bool exited,
@@ -1219,23 +1414,52 @@ ProcessMonitor::MonitorCallback(void *ca
     assert(process);
     bool stop_monitoring;
     siginfo_t info;
+    int ptrace_err;
+
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
 
-    if (!monitor->GetSignalInfo(pid, &info))
-        stop_monitoring = true; // pid is gone.  Bail.
+    if (exited)
+    {
+        if (log)
+            log->Printf ("ProcessMonitor::%s() got exit signal, tid = %"  PRIu64, __FUNCTION__, pid);
+        message = ProcessMessage::Exit(pid, status);
+        process->SendMessage(message);
+        return pid == process->GetID();
+    }
+
+    if (!monitor->GetSignalInfo(pid, &info, ptrace_err)) {
+        if (ptrace_err == EINVAL) {
+            if (log)
+                log->Printf ("ProcessMonitor::%s() resuming from group-stop", __FUNCTION__);
+            // inferior process is in 'group-stop', so deliver SIGSTOP signal
+            if (!monitor->Resume(pid, SIGSTOP)) {
+              assert(0 && "SIGSTOP delivery failed while in 'group-stop' state");
+            }
+            stop_monitoring = false;
+        } else {
+            // ptrace(GETSIGINFO) failed (but not due to group-stop). Most likely,
+            // this means the child pid is gone (or not being debugged) therefore
+            // stop the monitor thread if this is the main pid.
+            if (log)
+                log->Printf ("ProcessMonitor::%s() GetSignalInfo failed: %s, tid = %" PRIu64 ", signal = %d, status = %d", 
+                              __FUNCTION__, strerror(ptrace_err), pid, signal, status);
+            stop_monitoring = pid == monitor->m_process->GetID();
+        }
+    }
     else {
         switch (info.si_signo)
         {
         case SIGTRAP:
             message = MonitorSIGTRAP(monitor, &info, pid);
             break;
-            
+
         default:
             message = MonitorSignal(monitor, &info, pid);
             break;
         }
 
         process->SendMessage(message);
-        stop_monitoring = message.GetKind() == ProcessMessage::eExitMessage;
+        stop_monitoring = false;
     }
 
     return stop_monitoring;
@@ -1247,6 +1471,8 @@ ProcessMonitor::MonitorSIGTRAP(ProcessMo
 {
     ProcessMessage message;
 
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+
     assert(monitor);
     assert(info && info->si_signo == SIGTRAP && "Unexpected child signal!");
 
@@ -1256,27 +1482,61 @@ ProcessMonitor::MonitorSIGTRAP(ProcessMo
         assert(false && "Unexpected SIGTRAP code!");
         break;
 
+    // TODO: these two cases are required if we want to support tracing
+    // of the inferiors' children
+    // case (SIGTRAP | (PTRACE_EVENT_FORK << 8)):
+    // case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)):
+
+    case (SIGTRAP | (PTRACE_EVENT_CLONE << 8)):
+    {
+        if (log)
+            log->Printf ("ProcessMonitor::%s() received thread creation event, code = %d", __FUNCTION__, info->si_code ^ SIGTRAP);
+
+        unsigned long tid = 0;
+        if (!monitor->GetEventMessage(pid, &tid))
+            tid = -1;
+        message = ProcessMessage::NewThread(pid, tid);
+        break;
+    }
+
+    case (SIGTRAP | (PTRACE_EVENT_EXEC << 8)):
+        // Don't follow the child by default and resume
+        monitor->Resume(pid, SIGCONT);
+        break;
+
     case (SIGTRAP | (PTRACE_EVENT_EXIT << 8)):
     {
-        // The inferior process is about to exit.  Maintain the process in a
-        // state of "limbo" until we are explicitly commanded to detach,
-        // destroy, resume, etc.
+        // The inferior process or one of its threads is about to exit.
+        // Maintain the process or thread in a state of "limbo" until we are
+        // explicitly commanded to detach, destroy, resume, etc.
         unsigned long data = 0;
         if (!monitor->GetEventMessage(pid, &data))
             data = -1;
+        if (log)
+            log->Printf ("ProcessMonitor::%s() received exit event, data = %lx, pid = %" PRIu64, __FUNCTION__, data, pid);
         message = ProcessMessage::Limbo(pid, (data >> 8));
         break;
     }
 
     case 0:
     case TRAP_TRACE:
+        if (log)
+            log->Printf ("ProcessMonitor::%s() received trace event, pid = %" PRIu64, __FUNCTION__, pid);
         message = ProcessMessage::Trace(pid);
         break;
 
     case SI_KERNEL:
     case TRAP_BRKPT:
+        if (log)
+            log->Printf ("ProcessMonitor::%s() received breakpoint event, pid = %" PRIu64, __FUNCTION__, pid);
         message = ProcessMessage::Break(pid);
         break;
+
+    case TRAP_HWBKPT:
+        if (log)
+            log->Printf ("ProcessMonitor::%s() received watchpoint event, pid = %" PRIu64, __FUNCTION__, pid);
+        message = ProcessMessage::Watch(pid, (lldb::addr_t)info->si_addr);
+        break;
     }
 
     return message;
@@ -1289,6 +1549,8 @@ ProcessMonitor::MonitorSignal(ProcessMon
     ProcessMessage message;
     int signo = info->si_signo;
 
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+
     // POSIX says that process behaviour is undefined after it ignores a SIGFPE,
     // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a
     // kill(2) or raise(3).  Similarly for tgkill(2) on Linux.
@@ -1299,12 +1561,22 @@ ProcessMonitor::MonitorSignal(ProcessMon
     // Similarly, ACK signals generated by this monitor.
     if (info->si_code == SI_TKILL || info->si_code == SI_USER)
     {
+        if (log)
+            log->Printf ("ProcessMonitor::%s() received signal %s with code %s, pid = %d",
+                            __FUNCTION__,
+                            monitor->m_process->GetUnixSignals().GetSignalAsCString (signo),
+                            (info->si_code == SI_TKILL ? "SI_TKILL" : "SI_USER"),
+                            info->si_pid);
+
         if (info->si_pid == getpid())
             return ProcessMessage::SignalDelivered(pid, signo);
         else
             return ProcessMessage::Signal(pid, signo);
     }
 
+    if (log)
+        log->Printf ("ProcessMonitor::%s() received signal %s", __FUNCTION__, monitor->m_process->GetUnixSignals().GetSignalAsCString (signo));
+
     if (signo == SIGSEGV) {
         lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);
         ProcessMessage::CrashReason reason = GetCrashReasonForSIGSEGV(info);
@@ -1334,6 +1606,144 @@ ProcessMonitor::MonitorSignal(ProcessMon
     return ProcessMessage::Signal(pid, signo);
 }
 
+bool
+ProcessMonitor::StopThread(lldb::tid_t tid)
+{
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+
+    // FIXME: Try to use tgkill or tkill
+    int ret = tgkill(m_pid, tid, SIGSTOP);
+    if (log)
+        log->Printf ("ProcessMonitor::%s(bp) stopping thread, tid = %" PRIu64 ", ret = %d", __FUNCTION__, tid, ret);
+
+    // This can happen if a thread exited while we were trying to stop it.  That's OK.
+    // We'll get the signal for that later.
+    if (ret < 0)
+        return false;
+
+    // Wait for the thread to stop
+    while (true)
+    {
+        int status = -1;
+        if (log)
+            log->Printf ("ProcessMonitor::%s(bp) waitpid...", __FUNCTION__);
+        lldb::pid_t wait_pid = ::waitpid (-1*m_pid, &status, __WALL);
+        if (log)
+            log->Printf ("ProcessMonitor::%s(bp) waitpid, pid = %" PRIu64 ", status = %d", __FUNCTION__, wait_pid, status);
+
+        if (wait_pid == -1)
+        {
+            // If we got interrupted by a signal (in our process, not the
+            // inferior) try again.
+            if (errno == EINTR)
+                continue;
+            else
+                return false; // This is bad, but there's nothing we can do.
+        }
+
+        // If this is a thread exit, we won't get any more information.
+        if (WIFEXITED(status))
+        {
+            m_process->SendMessage(ProcessMessage::Exit(wait_pid, WEXITSTATUS(status)));
+            if (wait_pid == tid)
+                return true;
+            continue;
+        }
+
+        siginfo_t info;
+        int ptrace_err;
+        if (!GetSignalInfo(wait_pid, &info, ptrace_err))
+        {
+            if (log)
+            {
+                log->Printf ("ProcessMonitor::%s() GetSignalInfo failed.", __FUNCTION__);
+
+                // This would be a particularly interesting case
+                if (ptrace_err == EINVAL)
+                    log->Printf ("ProcessMonitor::%s() in group-stop", __FUNCTION__);
+            }
+            return false;
+        }
+
+        // Handle events from other threads
+        if (log)
+            log->Printf ("ProcessMonitor::%s(bp) handling event, tid == %" PRIu64, __FUNCTION__, wait_pid);
+
+        ProcessMessage message;
+        if (info.si_signo == SIGTRAP)
+            message = MonitorSIGTRAP(this, &info, wait_pid);
+        else
+            message = MonitorSignal(this, &info, wait_pid);
+
+        POSIXThread *thread = static_cast<POSIXThread*>(m_process->GetThreadList().FindThreadByID(wait_pid).get());
+
+        // When a new thread is created, we may get a SIGSTOP for the new thread
+        // just before we get the SIGTRAP that we use to add the thread to our
+        // process thread list.  We don't need to worry about that signal here.
+        assert(thread || message.GetKind() == ProcessMessage::eSignalMessage);
+
+        if (!thread)
+        {
+            m_process->SendMessage(message);
+            continue;
+        }
+
+        switch (message.GetKind())
+        {
+            case ProcessMessage::eInvalidMessage:
+                break;
+
+            // These need special handling because we don't want to send a
+            // resume even if we already sent a SIGSTOP to this thread. In
+            // this case the resume will cause the thread to disappear.  It is
+            // unlikely that we'll ever get eExitMessage here, but the same
+            // reasoning applies.
+            case ProcessMessage::eLimboMessage:
+            case ProcessMessage::eExitMessage:
+                if (log)
+                    log->Printf ("ProcessMonitor::%s(bp) handling message", __FUNCTION__);
+                // SendMessage will set the thread state as needed.
+                m_process->SendMessage(message);
+                // If this is the thread we're waiting for, stop waiting. Even
+                // though this wasn't the signal we expected, it's the last
+                // signal we'll see while this thread is alive.
+                if (wait_pid == tid)
+                    return true;
+                break;
+
+            case ProcessMessage::eSignalDeliveredMessage:
+                // This is the stop we're expecting.
+                if (wait_pid == tid && WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP && info.si_code == SI_TKILL)
+                {
+                    if (log)
+                        log->Printf ("ProcessMonitor::%s(bp) received signal, done waiting", __FUNCTION__);
+                    thread->SetState(lldb::eStateStopped);
+                    return true;
+                }
+                // else fall-through
+            case ProcessMessage::eSignalMessage:
+            case ProcessMessage::eBreakpointMessage:
+            case ProcessMessage::eTraceMessage:
+            case ProcessMessage::eWatchpointMessage:
+            case ProcessMessage::eCrashMessage:
+            case ProcessMessage::eNewThreadMessage:
+                if (log)
+                    log->Printf ("ProcessMonitor::%s(bp) handling message", __FUNCTION__);
+                // SendMessage will set the thread state as needed.
+                m_process->SendMessage(message);
+                // This isn't the stop we were expecting, but the thread is
+                // stopped. SendMessage will handle processing of this event,
+                // but we need to resume here to get the stop we are waiting
+                // for (otherwise the thread will stop again immediately when
+                // we try to resume).
+                if (wait_pid == tid)
+                    Resume(wait_pid, eResumeSignalNone);
+                break;
+        }
+    }
+    return false;
+}
+
 ProcessMessage::CrashReason
 ProcessMonitor::GetCrashReasonForSIGSEGV(const siginfo_t *info)
 {
@@ -1342,7 +1752,7 @@ ProcessMonitor::GetCrashReasonForSIGSEGV
 
     reason = ProcessMessage::eInvalidCrashReason;
 
-    switch (info->si_code) 
+    switch (info->si_code)
     {
     default:
         assert(false && "unexpected si_code for SIGSEGV");
@@ -1354,7 +1764,7 @@ ProcessMonitor::GetCrashReasonForSIGSEGV
         reason = ProcessMessage::ePrivilegedAddress;
         break;
     }
-        
+
     return reason;
 }
 
@@ -1513,7 +1923,8 @@ ProcessMonitor::ServeOperation(Operation
                 assert(errno == EINTR);
                 goto READ_AGAIN;
             }
-
+            if (status == 0)
+                continue; // Poll again. The connection probably terminated.
             assert(status == sizeof(op));
             op->Execute(monitor);
             write(fdset.fd, &op, sizeof(op));
@@ -1567,55 +1978,75 @@ ProcessMonitor::WriteMemory(lldb::addr_t
 }
 
 bool
-ProcessMonitor::ReadRegisterValue(unsigned offset, unsigned size, RegisterValue &value)
+ProcessMonitor::ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char* reg_name,
+                                  unsigned size, RegisterValue &value)
 {
     bool result;
-    ReadRegOperation op(offset, value, result);
+    ReadRegOperation op(tid, offset, reg_name, value, result);
     DoOperation(&op);
     return result;
 }
 
 bool
-ProcessMonitor::WriteRegisterValue(unsigned offset, const RegisterValue &value)
+ProcessMonitor::WriteRegisterValue(lldb::tid_t tid, unsigned offset,
+                                   const char* reg_name, const RegisterValue &value)
 {
     bool result;
-    WriteRegOperation op(offset, value, result);
+    WriteRegOperation op(tid, offset, reg_name, value, result);
     DoOperation(&op);
     return result;
 }
 
 bool
-ProcessMonitor::ReadGPR(void *buf)
+ProcessMonitor::ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size)
 {
     bool result;
-    ReadGPROperation op(buf, result);
+    ReadGPROperation op(tid, buf, buf_size, result);
     DoOperation(&op);
     return result;
 }
 
 bool
-ProcessMonitor::ReadFPR(void *buf)
+ProcessMonitor::ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size)
 {
     bool result;
-    ReadFPROperation op(buf, result);
+    ReadFPROperation op(tid, buf, buf_size, result);
     DoOperation(&op);
     return result;
 }
 
 bool
-ProcessMonitor::WriteGPR(void *buf)
+ProcessMonitor::ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset)
 {
     bool result;
-    WriteGPROperation op(buf, result);
+    ReadRegisterSetOperation op(tid, buf, buf_size, regset, result);
     DoOperation(&op);
     return result;
 }
 
 bool
-ProcessMonitor::WriteFPR(void *buf)
+ProcessMonitor::WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size)
 {
     bool result;
-    WriteFPROperation op(buf, result);
+    WriteGPROperation op(tid, buf, buf_size, result);
+    DoOperation(&op);
+    return result;
+}
+
+bool
+ProcessMonitor::WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size)
+{
+    bool result;
+    WriteFPROperation op(tid, buf, buf_size, result);
+    DoOperation(&op);
+    return result;
+}
+
+bool
+ProcessMonitor::WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset)
+{
+    bool result;
+    WriteRegisterSetOperation op(tid, buf, buf_size, regset, result);
     DoOperation(&op);
     return result;
 }
@@ -1624,8 +2055,15 @@ bool
 ProcessMonitor::Resume(lldb::tid_t tid, uint32_t signo)
 {
     bool result;
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+
+    if (log)
+        log->Printf ("ProcessMonitor::%s() resuming thread = %"  PRIu64 " with signal %s", __FUNCTION__, tid,
+                                 m_process->GetUnixSignals().GetSignalAsCString (signo));
     ResumeOperation op(tid, signo, result);
     DoOperation(&op);
+    if (log)
+        log->Printf ("ProcessMonitor::%s() resuming result = %s", __FUNCTION__, result ? "true" : "false");
     return result;
 }
 
@@ -1648,10 +2086,10 @@ ProcessMonitor::BringProcessIntoLimbo()
 }
 
 bool
-ProcessMonitor::GetSignalInfo(lldb::tid_t tid, void *siginfo)
+ProcessMonitor::GetSignalInfo(lldb::tid_t tid, void *siginfo, int &ptrace_err)
 {
     bool result;
-    SiginfoOperation op(tid, siginfo, result);
+    SiginfoOperation op(tid, siginfo, result, ptrace_err);
     DoOperation(&op);
     return result;
 }
@@ -1665,17 +2103,17 @@ ProcessMonitor::GetEventMessage(lldb::ti
     return result;
 }
 
-bool
-ProcessMonitor::Detach()
+lldb_private::Error
+ProcessMonitor::Detach(lldb::tid_t tid)
 {
-    bool result;
     lldb_private::Error error;
-    DetachOperation op(error);
-    result = error.Success();
-    DoOperation(&op);
-    StopMonitor();
-    return result;
-}    
+    if (tid != LLDB_INVALID_THREAD_ID)
+    {
+        DetachOperation op(tid, error);
+        DoOperation(&op);
+    }
+    return error;
+}
 
 bool
 ProcessMonitor::DupDescriptor(const char *path, int fd, int flags)
@@ -1705,13 +2143,26 @@ void
 ProcessMonitor::StopMonitor()
 {
     StopMonitoringChildProcess();
-    StopLaunchOpThread();
+    StopOpThread();
     CloseFD(m_terminal_fd);
     CloseFD(m_client_fd);
     CloseFD(m_server_fd);
 }
 
 void
+ProcessMonitor::StopOpThread()
+{
+    lldb::thread_result_t result;
+
+    if (!IS_VALID_LLDB_HOST_THREAD(m_operation_thread))
+        return;
+
+    Host::ThreadCancel(m_operation_thread, NULL);
+    Host::ThreadJoin(m_operation_thread, &result, NULL);
+    m_operation_thread = LLDB_INVALID_HOST_THREAD;
+}
+
+void
 ProcessMonitor::CloseFD(int &fd)
 {
     if (fd != -1)

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessMonitor.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessMonitor.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessMonitor.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessMonitor.h Thu Jun  6 19:06:43 2013
@@ -24,12 +24,10 @@ namespace lldb_private
 class Error;
 class Module;
 class Scalar;
-
 } // End lldb_private namespace.
 
 class ProcessLinux;
 class Operation;
-class ProcessPOSIX;
 
 /// @class ProcessMonitor
 /// @brief Manages communication with the inferior (debugee) process.
@@ -56,6 +54,7 @@ public:
                    const char *stdin_path,
                    const char *stdout_path,
                    const char *stderr_path,
+                   const char *working_dir,
                    lldb_private::Error &error);
 
     ProcessMonitor(ProcessPOSIX *process,
@@ -64,6 +63,11 @@ public:
 
     ~ProcessMonitor();
 
+    enum ResumeSignals 
+    {
+        eResumeSignalNone = 0
+    };
+
     /// Provides the process number of debugee.
     lldb::pid_t
     GetPID() const { return m_pid; }
@@ -106,35 +110,47 @@ public:
     ///
     /// This method is provided for use by RegisterContextLinux derivatives.
     bool
-    ReadRegisterValue(unsigned offset, unsigned size, lldb_private::RegisterValue &value);
+    ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
+                      unsigned size, lldb_private::RegisterValue &value);
 
     /// Writes the given value to the register identified by the given
     /// (architecture dependent) offset.
     ///
     /// This method is provided for use by RegisterContextLinux derivatives.
     bool
-    WriteRegisterValue(unsigned offset, const lldb_private::RegisterValue &value);
+    WriteRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
+                       const lldb_private::RegisterValue &value);
 
     /// Reads all general purpose registers into the specified buffer.
     bool
-    ReadGPR(void *buf);
+    ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size);
+
+    /// Reads generic floating point registers into the specified buffer.
+    bool
+    ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size);
 
-    /// Reads all floating point registers into the specified buffer.
+    /// Reads the specified register set into the specified buffer.
+    /// For instance, the extended floating-point register set.
     bool
-    ReadFPR(void *buf);
+    ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
 
     /// Writes all general purpose registers into the specified buffer.
     bool
-    WriteGPR(void *buf);
+    WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size);
 
-    /// Writes all floating point registers into the specified buffer.
+    /// Writes generic floating point registers into the specified buffer.
     bool
-    WriteFPR(void *buf);
+    WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size);
+
+    /// Writes the specified register set into the specified buffer.
+    /// For instance, the extended floating-point register set.
+    bool
+    WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
 
     /// Writes a siginfo_t structure corresponding to the given thread ID to the
     /// memory region pointed to by @p siginfo.
     bool
-    GetSignalInfo(lldb::tid_t tid, void *siginfo);
+    GetSignalInfo(lldb::tid_t tid, void *siginfo, int &ptrace_err);
 
     /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
     /// corresponding to the given thread IDto the memory pointed to by @p
@@ -158,18 +174,21 @@ public:
     bool
     BringProcessIntoLimbo();
 
-    bool
-    Detach();
+    lldb_private::Error
+    Detach(lldb::tid_t tid);
 
+    /// Stops the requested thread and waits for the stop signal.
+    bool
+    StopThread(lldb::tid_t tid);
 
 private:
     ProcessLinux *m_process;
 
     lldb::thread_t m_operation_thread;
+    lldb::thread_t m_monitor_thread;
     lldb::pid_t m_pid;
     int m_terminal_fd;
 
-    lldb::thread_t m_monitor_thread;
 
     lldb_private::Mutex m_server_mutex;
     int m_client_fd;
@@ -198,7 +217,8 @@ private:
                    char const **envp,
                    const char *stdin_path,
                    const char *stdout_path,
-                   const char *stderr_path);
+                   const char *stderr_path,
+                   const char *working_dir);
 
         ~LaunchArgs();
 
@@ -208,14 +228,12 @@ private:
         const char *m_stdin_path;       // Redirect stdin or NULL.
         const char *m_stdout_path;      // Redirect stdout or NULL.
         const char *m_stderr_path;      // Redirect stderr or NULL.
+        const char *m_working_dir;      // Working directory or NULL.
     };
 
     void
     StartLaunchOpThread(LaunchArgs *args, lldb_private::Error &error);
 
-    void
-    StopLaunchOpThread();
-
     static void *
     LaunchOpThread(void *arg);
 
@@ -238,15 +256,15 @@ private:
     void
     StartAttachOpThread(AttachArgs *args, lldb_private::Error &error);
 
-    void
-    StopAttachOpThread();
-
     static void *
     AttachOpThread(void *args);
 
     static bool
     Attach(AttachArgs *args);
 
+    static bool
+    SetDefaultPtraceOpts(const lldb::pid_t);
+
     static void
     ServeOperation(OperationArgs *args);
 
@@ -287,6 +305,10 @@ private:
     void 
     StopMonitor();
 
+    /// Stops the operation thread used to attach/launch a process.
+    void
+    StopOpThread();
+
     void
     CloseFD(int &fd);
 };

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h Thu Jun  6 19:06:43 2013
@@ -1,44 +0,0 @@
-//===-- RegisterContextLinux_x86_64.h ---------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_RegisterContextLinux_x86_64_H_
-#define liblldb_RegisterContextLinux_x86_64_H_
-
-typedef struct _GPR
-{
-    uint64_t r15;
-    uint64_t r14;
-    uint64_t r13;
-    uint64_t r12;
-    uint64_t rbp;
-    uint64_t rbx;
-    uint64_t r11;
-    uint64_t r10;
-    uint64_t r9;
-    uint64_t r8;
-    uint64_t rax;
-    uint64_t rcx;
-    uint64_t rdx;
-    uint64_t rsi;
-    uint64_t rdi;
-    uint64_t orig_ax;
-    uint64_t rip;
-    uint64_t cs;
-    uint64_t rflags;
-    uint64_t rsp;
-    uint64_t ss;
-    uint64_t fs_base;
-    uint64_t gs_base;
-    uint64_t ds;
-    uint64_t es;
-    uint64_t fs;
-    uint64_t gs;
-} GPR;
-
-#endif

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp Thu Jun  6 19:06:43 2013
@@ -11,6 +11,7 @@
 #include "CommunicationKDP.h"
 
 // C Includes
+#include <errno.h>
 #include <limits.h>
 #include <string.h>
 
@@ -22,6 +23,7 @@
 #include "lldb/Core/DataExtractor.h"
 #include "lldb/Core/Log.h"
 #include "lldb/Core/State.h"
+#include "lldb/Core/UUID.h"
 #include "lldb/Host/FileSpec.h"
 #include "lldb/Host/Host.h"
 #include "lldb/Host/TimeValue.h"
@@ -42,7 +44,7 @@ CommunicationKDP::CommunicationKDP (cons
     m_byte_order (eByteOrderLittle),
     m_packet_timeout (1),
     m_sequence_mutex (Mutex::eMutexTypeRecursive),
-    m_private_is_running (false),
+    m_is_running (false),
     m_session_key (0u),
     m_request_sequence_id (0u),
     m_exception_sequence_id (0u),
@@ -82,7 +84,7 @@ typedef struct {
 #endif
 
 void
-CommunicationKDP::MakeRequestPacketHeader (CommandType request_type, 
+CommunicationKDP::MakeRequestPacketHeader (CommandType request_type,
                                            PacketStreamType &request_packet,
                                            uint16_t request_length)
 {
@@ -95,23 +97,47 @@ CommunicationKDP::MakeRequestPacketHeade
 
 bool
 CommunicationKDP::SendRequestAndGetReply (const CommandType command,
-                                          const uint8_t request_sequence_id,
-                                          const PacketStreamType &request_packet, 
+                                          const PacketStreamType &request_packet,
                                           DataExtractor &reply_packet)
 {
+    if (IsRunning())
+    {
+        Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
+        if (log)
+        {
+            PacketStreamType log_strm;
+            DumpPacket (log_strm, request_packet.GetData(), request_packet.GetSize());
+            log->Printf("error: kdp running, not sending packet: %.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
+        }
+        return false;
+    }
 
-    Mutex::Locker locker(m_sequence_mutex);    
-    if (SendRequestPacketNoLock(request_packet))
+    Mutex::Locker locker(m_sequence_mutex);
+#ifdef LLDB_CONFIGURATION_DEBUG
+    // NOTE: this only works for packets that are in native endian byte order
+    assert (request_packet.GetSize() == *((uint16_t *)(request_packet.GetData() + 2)));
+#endif
+    lldb::offset_t offset = 1;
+    const uint32_t num_retries = 3;
+    for (uint32_t i=0; i<num_retries; ++i)
     {
-        if (WaitForPacketWithTimeoutMicroSecondsNoLock (reply_packet, GetPacketTimeoutInMicroSeconds ()))
+        if (SendRequestPacketNoLock(request_packet))
         {
-            uint32_t offset = 0;
-            const uint8_t reply_command = reply_packet.GetU8 (&offset);
-            const uint8_t reply_sequence_id = reply_packet.GetU8 (&offset);
-            if ((reply_command & eCommandTypeMask) == command)
+            const uint8_t request_sequence_id = (uint8_t)request_packet.GetData()[1];
+            if (WaitForPacketWithTimeoutMicroSecondsNoLock (reply_packet, GetPacketTimeoutInMicroSeconds ()))
             {
-                if (request_sequence_id == reply_sequence_id)
-                    return true;
+                offset = 0;
+                const uint8_t reply_command = reply_packet.GetU8 (&offset);
+                const uint8_t reply_sequence_id = reply_packet.GetU8 (&offset);
+                if ((reply_command & eCommandTypeMask) == command)
+                {
+                    if (request_sequence_id == reply_sequence_id)
+                    {
+                        if (command == KDP_RESUMECPUS)
+                            m_is_running.SetValue(true, eBroadcastAlways);
+                        return true;
+                    }
+                }
             }
         }
     }
@@ -127,7 +153,7 @@ CommunicationKDP::SendRequestPacketNoLoc
         const char *packet_data = request_packet.GetData();
         const size_t packet_size = request_packet.GetSize();
 
-        LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
+        Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
         if (log)
         {
             PacketStreamType log_strm;            
@@ -145,7 +171,7 @@ CommunicationKDP::SendRequestPacketNoLoc
             return true;
         
         if (log)
-            log->Printf ("error: failed to send packet entire packet %zu of %zu bytes sent", bytes_written, packet_size);
+            log->Printf ("error: failed to send packet entire packet %" PRIu64 " of %" PRIu64 " bytes sent", (uint64_t)bytes_written, (uint64_t)packet_size);
     }
     return false;
 }
@@ -160,7 +186,7 @@ CommunicationKDP::GetSequenceMutex (Mute
 bool
 CommunicationKDP::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
 {
-    return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
+    return m_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
 }
 
 size_t
@@ -176,7 +202,7 @@ CommunicationKDP::WaitForPacketWithTimeo
     uint8_t buffer[8192];
     Error error;
 
-    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS | KDP_LOG_VERBOSE));
+    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS | KDP_LOG_VERBOSE));
 
     // Check for a packet from our cache first without trying any reading...
     if (CheckForPacket (NULL, 0, packet))
@@ -189,12 +215,12 @@ CommunicationKDP::WaitForPacketWithTimeo
         size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error);
         
         if (log)
-            log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %zu",
+            log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %" PRIu64,
                          __PRETTY_FUNCTION__,
                          timeout_usec, 
                          Communication::ConnectionStatusAsCString (status),
                          error.AsCString(), 
-                         bytes_read);
+                         (uint64_t)bytes_read);
 
         if (bytes_read > 0)
         {
@@ -231,7 +257,7 @@ CommunicationKDP::CheckForPacket (const
     // Put the packet data into the buffer in a thread safe fashion
     Mutex::Locker locker(m_bytes_mutex);
     
-    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
+    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
 
     if (src && src_len > 0)
     {
@@ -252,10 +278,25 @@ CommunicationKDP::CheckForPacket (const
     if (bytes_available >= 8)
     {
         packet.SetData (&m_bytes[0], bytes_available, m_byte_order);
-        uint32_t offset = 0;
+        lldb::offset_t offset = 0;
         uint8_t reply_command = packet.GetU8(&offset);
         switch (reply_command)
         {
+        case ePacketTypeRequest | KDP_EXCEPTION:
+        case ePacketTypeRequest | KDP_TERMINATION:
+            // We got an exception request, so be sure to send an ACK
+            {
+                PacketStreamType request_ack_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
+                // Set the reply but and make the ACK packet
+                request_ack_packet.PutHex8 (reply_command | ePacketTypeReply);
+                request_ack_packet.PutHex8 (packet.GetU8(&offset));
+                request_ack_packet.PutHex16 (packet.GetU16(&offset));
+                request_ack_packet.PutHex32 (packet.GetU32(&offset));
+                m_is_running.SetValue(false, eBroadcastAlways);
+                // Ack to the exception or termination
+                SendRequestPacketNoLock (request_ack_packet);
+            }
+            // Fall through to case below to get packet contents
         case ePacketTypeReply | KDP_CONNECT:
         case ePacketTypeReply | KDP_DISCONNECT:
         case ePacketTypeReply | KDP_HOSTINFO:
@@ -269,8 +310,6 @@ CommunicationKDP::CheckForPacket (const
         case ePacketTypeReply | KDP_IMAGEPATH:
         case ePacketTypeReply | KDP_SUSPEND:
         case ePacketTypeReply | KDP_RESUMECPUS:
-        case ePacketTypeReply | KDP_EXCEPTION:
-        case ePacketTypeReply | KDP_TERMINATION:
         case ePacketTypeReply | KDP_BREAKPOINT_SET:
         case ePacketTypeReply | KDP_BREAKPOINT_REMOVE:
         case ePacketTypeReply | KDP_REGIONS:
@@ -281,6 +320,13 @@ CommunicationKDP::CheckForPacket (const
         case ePacketTypeReply | KDP_BREAKPOINT_SET64:
         case ePacketTypeReply | KDP_BREAKPOINT_REMOVE64:
         case ePacketTypeReply | KDP_KERNELVERSION:
+        case ePacketTypeReply | KDP_READPHYSMEM64:
+        case ePacketTypeReply | KDP_WRITEPHYSMEM64:
+        case ePacketTypeReply | KDP_READIOPORT:
+        case ePacketTypeReply | KDP_WRITEIOPORT:
+        case ePacketTypeReply | KDP_READMSR64:
+        case ePacketTypeReply | KDP_WRITEMSR64:
+        case ePacketTypeReply | KDP_DUMPINFO:
             {
                 offset = 2;
                 const uint16_t length = packet.GetU16 (&offset);
@@ -331,7 +377,6 @@ CommunicationKDP::SendRequestConnect (ui
     const CommandType command = KDP_CONNECT;
     // Length is 82 uint16_t and the length of the greeting C string with the terminating NULL
     const uint32_t command_length = 8 + 2 + 2 + ::strlen(greeting) + 1;
-    const uint32_t request_sequence_id = m_request_sequence_id;
     MakeRequestPacketHeader (command, request_packet, command_length);
     // Always send connect ports as little endian
     request_packet.SetByteOrder (eByteOrderLittle);
@@ -340,7 +385,7 @@ CommunicationKDP::SendRequestConnect (ui
     request_packet.SetByteOrder (m_byte_order);
     request_packet.PutCString (greeting);
     DataExtractor reply_packet;
-    return SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet);
+    return SendRequestAndGetReply (command, request_packet, reply_packet);
 }
 
 void
@@ -361,18 +406,17 @@ CommunicationKDP::SendRequestReattach (u
     const CommandType command = KDP_REATTACH;
     // Length is 8 bytes for the header plus 2 bytes for the reply UDP port
     const uint32_t command_length = 8 + 2;
-    const uint32_t request_sequence_id = m_request_sequence_id;
     MakeRequestPacketHeader (command, request_packet, command_length);
     // Always send connect ports as little endian
     request_packet.SetByteOrder (eByteOrderLittle);
     request_packet.PutHex16(reply_port);
     request_packet.SetByteOrder (m_byte_order);
     DataExtractor reply_packet;
-    if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+    if (SendRequestAndGetReply (command, request_packet, reply_packet))
     {
         // Reset the sequence ID to zero for reattach
         ClearKDPSettings ();
-        uint32_t offset = 4;
+        lldb::offset_t offset = 4;
         m_session_key = reply_packet.GetU32 (&offset);
         return true;
     }
@@ -401,12 +445,11 @@ CommunicationKDP::SendRequestVersion ()
     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
     const CommandType command = KDP_VERSION;
     const uint32_t command_length = 8;
-    const uint32_t request_sequence_id = m_request_sequence_id;
     MakeRequestPacketHeader (command, request_packet, command_length);
     DataExtractor reply_packet;
-    if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+    if (SendRequestAndGetReply (command, request_packet, reply_packet))
     {
-        uint32_t offset = 8;
+        lldb::offset_t offset = 8;
         m_kdp_version_version = reply_packet.GetU32 (&offset);
         m_kdp_version_feature = reply_packet.GetU32 (&offset);
         return true;
@@ -429,10 +472,9 @@ CommunicationKDP::SendRequestImagePath (
     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
     const CommandType command = KDP_IMAGEPATH;
     const uint32_t command_length = 8;
-    const uint32_t request_sequence_id = m_request_sequence_id;
     MakeRequestPacketHeader (command, request_packet, command_length);
     DataExtractor reply_packet;
-    if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+    if (SendRequestAndGetReply (command, request_packet, reply_packet))
     {
         const char *path = reply_packet.PeekCStr(8);
         if (path && path[0])
@@ -467,18 +509,84 @@ CommunicationKDP::GetCPUSubtype ()
     return m_kdp_hostinfo_cpu_subtype;
 }
 
+lldb_private::UUID
+CommunicationKDP::GetUUID ()
+{
+    UUID uuid;
+    if (GetKernelVersion() == NULL)
+        return uuid;
+
+    if (m_kernel_version.find("UUID=") == std::string::npos)
+        return uuid;
+
+    size_t p = m_kernel_version.find("UUID=") + strlen ("UUID=");
+    std::string uuid_str = m_kernel_version.substr(p, 36);
+    if (uuid_str.size() < 32)
+        return uuid;
+
+    if (uuid.SetFromCString (uuid_str.c_str()) == 0)
+    {
+        UUID invalid_uuid;
+        return invalid_uuid;
+    }
+
+    return uuid;
+}
+
+bool
+CommunicationKDP::RemoteIsEFI ()
+{
+    if (GetKernelVersion() == NULL)
+        return false;
+    if (strncmp (m_kernel_version.c_str(), "EFI", 3) == 0)
+        return true;
+    else
+        return false;
+}
+
+bool
+CommunicationKDP::RemoteIsDarwinKernel ()
+{
+    if (GetKernelVersion() == NULL)
+        return false;
+    if (m_kernel_version.find("Darwin Kernel") != std::string::npos)
+        return true;
+    else
+        return false;
+}
+
+lldb::addr_t
+CommunicationKDP::GetLoadAddress ()
+{
+    if (GetKernelVersion() == NULL)
+        return LLDB_INVALID_ADDRESS;
+
+    if (m_kernel_version.find("stext=") == std::string::npos)
+        return LLDB_INVALID_ADDRESS;
+    size_t p = m_kernel_version.find("stext=") + strlen ("stext=");
+    if (m_kernel_version[p] != '0' || m_kernel_version[p + 1] != 'x')
+        return LLDB_INVALID_ADDRESS;
+
+    addr_t kernel_load_address;
+    errno = 0;
+    kernel_load_address = ::strtoul (m_kernel_version.c_str() + p, NULL, 16);
+    if (errno != 0 || kernel_load_address == 0)
+        return LLDB_INVALID_ADDRESS;
+
+    return kernel_load_address;
+}
+
 bool
 CommunicationKDP::SendRequestHostInfo ()
 {
     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
     const CommandType command = KDP_HOSTINFO;
     const uint32_t command_length = 8;
-    const uint32_t request_sequence_id = m_request_sequence_id;
     MakeRequestPacketHeader (command, request_packet, command_length);
     DataExtractor reply_packet;
-    if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+    if (SendRequestAndGetReply (command, request_packet, reply_packet))
     {
-        uint32_t offset = 8;
+        lldb::offset_t offset = 8;
         m_kdp_hostinfo_cpu_mask     = reply_packet.GetU32 (&offset);
         m_kdp_hostinfo_cpu_type     = reply_packet.GetU32 (&offset);
         m_kdp_hostinfo_cpu_subtype  = reply_packet.GetU32 (&offset);
@@ -509,10 +617,9 @@ CommunicationKDP::SendRequestKernelVersi
     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
     const CommandType command = KDP_KERNELVERSION;
     const uint32_t command_length = 8;
-    const uint32_t request_sequence_id = m_request_sequence_id;
     MakeRequestPacketHeader (command, request_packet, command_length);
     DataExtractor reply_packet;
-    if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+    if (SendRequestAndGetReply (command, request_packet, reply_packet))
     {
         const char *kernel_version_cstr = reply_packet.PeekCStr(8);
         if (kernel_version_cstr && kernel_version_cstr[0])
@@ -528,10 +635,9 @@ CommunicationKDP::SendRequestDisconnect
     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
     const CommandType command = KDP_DISCONNECT;
     const uint32_t command_length = 8;
-    const uint32_t request_sequence_id = m_request_sequence_id;
     MakeRequestPacketHeader (command, request_packet, command_length);
     DataExtractor reply_packet;
-    if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+    if (SendRequestAndGetReply (command, request_packet, reply_packet))
     {
         // Are we supposed to get a reply for disconnect?
     }
@@ -551,14 +657,13 @@ CommunicationKDP::SendRequestReadMemory
     const CommandType command = use_64 ? KDP_READMEM64 : KDP_READMEM;
     // Size is header + address size + uint32_t length
     const uint32_t command_length = 8 + command_addr_byte_size + 4;
-    const uint32_t request_sequence_id = m_request_sequence_id;
     MakeRequestPacketHeader (command, request_packet, command_length);
     request_packet.PutMaxHex64 (addr, command_addr_byte_size);
     request_packet.PutHex32 (dst_len);
     DataExtractor reply_packet;
-    if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+    if (SendRequestAndGetReply (command, request_packet, reply_packet))
     {
-        uint32_t offset = 8;
+        lldb::offset_t offset = 8;
         uint32_t kdp_error = reply_packet.GetU32 (&offset);
         uint32_t src_len = reply_packet.GetByteSize() - 12;
         
@@ -577,6 +682,10 @@ CommunicationKDP::SendRequestReadMemory
         else
             error.SetErrorString ("kdp read memory failed");
     }
+    else
+    {
+        error.SetErrorString ("failed to send packet");
+    }
     return 0;
 }
 
@@ -592,17 +701,16 @@ CommunicationKDP::SendRequestWriteMemory
     uint32_t command_addr_byte_size = use_64 ? 8 : 4;
     const CommandType command = use_64 ? KDP_WRITEMEM64 : KDP_WRITEMEM;
     // Size is header + address size + uint32_t length
-    const uint32_t command_length = 8 + command_addr_byte_size + 4;
-    const uint32_t request_sequence_id = m_request_sequence_id;
+    const uint32_t command_length = 8 + command_addr_byte_size + 4 + src_len;
     MakeRequestPacketHeader (command, request_packet, command_length);
     request_packet.PutMaxHex64 (addr, command_addr_byte_size);
     request_packet.PutHex32 (src_len);
-    request_packet.PutBytesAsRawHex8(src, src_len);
+    request_packet.PutRawBytes(src, src_len);
 
     DataExtractor reply_packet;
-    if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+    if (SendRequestAndGetReply (command, request_packet, reply_packet))
     {
-        uint32_t offset = 8;
+        lldb::offset_t offset = 8;
         uint32_t kdp_error = reply_packet.GetU32 (&offset);
         if (kdp_error)
             error.SetErrorStringWithFormat ("kdp write memory failed (error %u)", kdp_error);
@@ -612,9 +720,47 @@ CommunicationKDP::SendRequestWriteMemory
             return src_len;
         }
     }
+    else
+    {
+        error.SetErrorString ("failed to send packet");
+    }
     return 0;
 }
 
+bool
+CommunicationKDP::SendRawRequest (uint8_t command_byte,
+                                  const void *src,  // Raw packet payload bytes
+                                  uint32_t src_len, // Raw packet payload length
+                                  DataExtractor &reply_packet,
+                                  Error &error)
+{
+    PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
+    // Size is header + address size + uint32_t length
+    const uint32_t command_length = 8 + src_len;
+    const CommandType command = (CommandType)command_byte;
+    MakeRequestPacketHeader (command, request_packet, command_length);
+    request_packet.PutRawBytes(src, src_len);
+    
+    if (SendRequestAndGetReply (command, request_packet, reply_packet))
+    {
+        lldb::offset_t offset = 8;
+        uint32_t kdp_error = reply_packet.GetU32 (&offset);
+        if (kdp_error  && (command_byte != KDP_DUMPINFO))
+            error.SetErrorStringWithFormat ("request packet 0x%8.8x failed (error %u)", command_byte, kdp_error);
+        else
+        {
+            error.Clear();
+            return true;
+        }
+    }
+    else
+    {
+        error.SetErrorString ("failed to send packet");
+    }
+    return false;
+}
+
+
 const char *
 CommunicationKDP::GetCommandAsCString (uint8_t command)
 {
@@ -645,6 +791,13 @@ CommunicationKDP::GetCommandAsCString (u
     case KDP_BREAKPOINT_SET64:      return "KDP_BREAKPOINT64_SET";
     case KDP_BREAKPOINT_REMOVE64:   return "KDP_BREAKPOINT64_REMOVE";
     case KDP_KERNELVERSION:         return "KDP_KERNELVERSION";
+    case KDP_READPHYSMEM64:         return "KDP_READPHYSMEM64";
+    case KDP_WRITEPHYSMEM64:        return "KDP_WRITEPHYSMEM64";
+    case KDP_READIOPORT:            return "KDP_READIOPORT";
+    case KDP_WRITEIOPORT:           return "KDP_WRITEIOPORT";
+    case KDP_READMSR64:             return "KDP_READMSR64";
+    case KDP_WRITEMSR64:            return "KDP_WRITEMSR64";
+    case KDP_DUMPINFO:              return "KDP_DUMPINFO";
     }
     return NULL;
 }
@@ -666,7 +819,7 @@ CommunicationKDP::DumpPacket (Stream &s,
     }
     else
     {
-        uint32_t offset = 0;
+        lldb::offset_t offset = 0;
         const uint8_t first_packet_byte = packet.GetU8 (&offset);
         const uint8_t sequence_id = packet.GetU8 (&offset);
         const uint16_t length = packet.GetU16 (&offset);
@@ -676,12 +829,14 @@ CommunicationKDP::DumpPacket (Stream &s,
         if (command_name)
         {
             const bool is_reply = ExtractIsReply(first_packet_byte);
-            s.Printf ("%s {%u:%u} <0x%4.4x> %s", 
-                      is_reply ? "<--" : "-->", 
-                      key,
+            s.Printf ("(running=%i) %s %24s: 0x%2.2x 0x%2.2x 0x%4.4x 0x%8.8x ",
+                      IsRunning(),
+                      is_reply ? "<--" : "-->",
+                      command_name,
+                      first_packet_byte,
                       sequence_id,
                       length,
-                      command_name);
+                      key);
             
             if (is_reply)
             {
@@ -698,6 +853,8 @@ CommunicationKDP::DumpPacket (Stream &s,
                     case KDP_BREAKPOINT_REMOVE64:
                     case KDP_WRITEREGS:
                     case KDP_LOAD:
+                    case KDP_WRITEIOPORT:
+                    case KDP_WRITEMSR64:
                         {
                             const uint32_t error = packet.GetU32 (&offset);
                             s.Printf(" (error=0x%8.8x)", error);
@@ -741,13 +898,14 @@ CommunicationKDP::DumpPacket (Stream &s,
                                 const addr_t region_addr = packet.GetPointer (&offset);
                                 const uint32_t region_size = packet.GetU32 (&offset);
                                 const uint32_t region_prot = packet.GetU32 (&offset);
-                                s.Printf("\n\tregion[%llu] = { range = [0x%16.16llx - 0x%16.16llx), size = 0x%8.8x, prot = %s }", region_addr, region_addr, region_addr + region_size, region_size, GetPermissionsAsCString (region_prot)); 
+                                s.Printf("\n\tregion[%" PRIu64 "] = { range = [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), size = 0x%8.8x, prot = %s }", region_addr, region_addr, region_addr + region_size, region_size, GetPermissionsAsCString (region_prot));
                             }
                         }
                         break;
 
                     case KDP_READMEM:
                     case KDP_READMEM64:
+                    case KDP_READPHYSMEM64:
                         {
                             const uint32_t error = packet.GetU32 (&offset);
                             const uint32_t count = packet.GetByteSize() - offset;
@@ -800,6 +958,41 @@ CommunicationKDP::DumpPacket (Stream &s,
                             s.Printf(" (path = \"%s\")", path);
                         }
                         break;
+
+                    case KDP_READIOPORT:
+                    case KDP_READMSR64:
+                        {
+                            const uint32_t error = packet.GetU32 (&offset);
+                            const uint32_t count = packet.GetByteSize() - offset;
+                            s.Printf(" (error = 0x%8.8x io:\n", error); 
+                            if (count > 0)
+                                packet.Dump (&s,                        // Stream to dump to
+                                             offset,                    // Offset within "packet"
+                                             eFormatHex,                // Format to use
+                                             1,                         // Size of each item in bytes
+                                             count,                     // Number of items
+                                             16,                        // Number per line
+                                             LLDB_INVALID_ADDRESS,      // Don't show addresses before each line
+                                             0, 0);                     // No bitfields
+                        }
+                        break;
+                    case KDP_DUMPINFO:
+                        {
+                            const uint32_t count = packet.GetByteSize() - offset;
+                            s.Printf(" (count = %u, bytes = \n", count);
+                            if (count > 0)
+                                packet.Dump (&s,                        // Stream to dump to
+                                             offset,                    // Offset within "packet"
+                                             eFormatHex,                // Format to use
+                                             1,                         // Size of each item in bytes
+                                             count,                     // Number of items
+                                             16,                        // Number per line
+                                             LLDB_INVALID_ADDRESS,      // Don't show addresses before each line
+                                             0, 0);                     // No bitfields
+                            
+                        }
+                        break;
+                        
                     default:
                         s.Printf(" (add support for dumping this packet reply!!!"); 
                         break;
@@ -862,7 +1055,17 @@ CommunicationKDP::DumpPacket (Stream &s,
                         {
                             const uint64_t addr = packet.GetU64 (&offset);
                             const uint32_t size = packet.GetU32 (&offset);
-                            s.Printf(" (addr = 0x%16.16llx, size = %u)", addr, size);
+                            s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u)", addr, size);
+                            m_last_read_memory_addr = addr;
+                        }
+                        break;
+
+                    case KDP_READPHYSMEM64:
+                        {
+                            const uint64_t addr = packet.GetU64 (&offset);
+                            const uint32_t size = packet.GetU32 (&offset);
+                            const uint32_t lcpu = packet.GetU16 (&offset);
+                            s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u)", addr, size, lcpu);
                             m_last_read_memory_addr = addr;
                         }
                         break;
@@ -871,7 +1074,18 @@ CommunicationKDP::DumpPacket (Stream &s,
                         {
                             const uint64_t addr = packet.GetU64 (&offset);
                             const uint32_t size = packet.GetU32 (&offset);
-                            s.Printf(" (addr = 0x%16.16llx, size = %u, bytes = \n", addr, size);
+                            s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u, bytes = \n", addr, size);
+                            if (size > 0)
+                                DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr);
+                        }
+                        break;
+
+                    case KDP_WRITEPHYSMEM64:
+                        {
+                            const uint64_t addr = packet.GetU64 (&offset);
+                            const uint32_t size = packet.GetU32 (&offset);
+                            const uint32_t lcpu = packet.GetU16 (&offset);
+                            s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u, bytes = \n", addr, size, lcpu);
                             if (size > 0)
                                 DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr);
                         }
@@ -916,7 +1130,7 @@ CommunicationKDP::DumpPacket (Stream &s,
                     case KDP_BREAKPOINT_REMOVE64:
                         {
                             const uint64_t addr = packet.GetU64 (&offset);
-                            s.Printf(" (addr = 0x%16.16llx)", addr);
+                            s.Printf(" (addr = 0x%16.16" PRIx64 ")", addr);
                         }
                         break;
 
@@ -932,7 +1146,6 @@ CommunicationKDP::DumpPacket (Stream &s,
                         {
                             const uint32_t count = packet.GetU32 (&offset);
                             
-                            s.Printf(" (count = %u:", count);
                             for (uint32_t i=0; i<count; ++i)
                             {
                                 const uint32_t cpu = packet.GetU32 (&offset);
@@ -956,7 +1169,7 @@ CommunicationKDP::DumpPacket (Stream &s,
                                         break;
                                 }
 
-                                s.Printf ("\n  cpu = 0x%8.8x, exc = %s (%u), code = %u (0x%8.8x), subcode = %u (0x%8.8x)\n", 
+                                s.Printf ("{ cpu = 0x%8.8x, exc = %s (%u), code = %u (0x%8.8x), subcode = %u (0x%8.8x)} ", 
                                           cpu, exc_cstr, exc, code, code, subcode, subcode);
                             }
                         }
@@ -976,7 +1189,78 @@ CommunicationKDP::DumpPacket (Stream &s,
                             s.Printf(" (reply_port = %u)", reply_port);
                         }
                         break;
-                }
+
+                    case KDP_READMSR64:
+                        {
+                            const uint32_t address = packet.GetU32 (&offset);
+                            const uint16_t lcpu = packet.GetU16 (&offset);
+                            s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x)", address, lcpu);
+                        }
+                        break;
+
+                    case KDP_WRITEMSR64:
+                        {
+                            const uint32_t address = packet.GetU32 (&offset);
+                            const uint16_t lcpu = packet.GetU16 (&offset);
+                            const uint32_t nbytes = packet.GetByteSize() - offset;
+                            s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x, nbytes=0x%8.8x)", lcpu, address, nbytes);
+                            if (nbytes > 0)
+                                packet.Dump (&s,                        // Stream to dump to
+                                             offset,                    // Offset within "packet"
+                                             eFormatHex,                // Format to use
+                                             1,                         // Size of each item in bytes
+                                             nbytes,                    // Number of items
+                                             16,                        // Number per line
+                                             LLDB_INVALID_ADDRESS,      // Don't show addresses before each line
+                                             0, 0);                     // No bitfields
+                        }
+                        break;
+
+                    case KDP_READIOPORT:
+                        {
+                            const uint16_t lcpu = packet.GetU16 (&offset);
+                            const uint16_t address = packet.GetU16 (&offset);
+                            const uint16_t nbytes = packet.GetU16 (&offset);
+                            s.Printf(" (lcpu=0x%4.4x, address=0x%4.4x, nbytes=%u)", lcpu, address, nbytes);
+                        }
+                        break;
+
+                    case KDP_WRITEIOPORT:
+                         {
+                            const uint16_t lcpu = packet.GetU16 (&offset);
+                            const uint16_t address = packet.GetU16 (&offset);
+                            const uint16_t nbytes = packet.GetU16 (&offset);
+                            s.Printf(" (lcpu = %u, addr = 0x%4.4x, nbytes = %u, bytes = \n", lcpu, address, nbytes);
+                            if (nbytes > 0)
+                                packet.Dump (&s,                        // Stream to dump to
+                                             offset,                    // Offset within "packet"
+                                             eFormatHex,                // Format to use
+                                             1,                         // Size of each item in bytes
+                                             nbytes,                    // Number of items
+                                             16,                        // Number per line
+                                             LLDB_INVALID_ADDRESS,      // Don't show addresses before each line
+                                             0, 0);                     // No bitfields
+                        }
+                        break;
+                        
+                    case KDP_DUMPINFO:
+                        {
+                            const uint32_t count = packet.GetByteSize() - offset;
+                            s.Printf(" (count = %u, bytes = \n", count);
+                            if (count > 0)
+                                packet.Dump (&s,                        // Stream to dump to
+                                             offset,                    // Offset within "packet"
+                                             eFormatHex,                // Format to use
+                                             1,                         // Size of each item in bytes
+                                             count,                     // Number of items
+                                             16,                        // Number per line
+                                             LLDB_INVALID_ADDRESS,      // Don't show addresses before each line
+                                             0, 0);                     // No bitfields
+                            
+                        }
+                        break;
+                        
+               }
             }
         }
         else
@@ -1003,7 +1287,7 @@ CommunicationKDP::DumpPacket (Stream &s,
 uint32_t
 CommunicationKDP::SendRequestReadRegisters (uint32_t cpu,
                                             uint32_t flavor,
-                                            void *dst, 
+                                            void *dst,
                                             uint32_t dst_len,
                                             Error &error)
 {
@@ -1011,14 +1295,13 @@ CommunicationKDP::SendRequestReadRegiste
     const CommandType command = KDP_READREGS;
     // Size is header + 4 byte cpu and 4 byte flavor
     const uint32_t command_length = 8 + 4 + 4;
-    const uint32_t request_sequence_id = m_request_sequence_id;
     MakeRequestPacketHeader (command, request_packet, command_length);
     request_packet.PutHex32 (cpu);
     request_packet.PutHex32 (flavor);
     DataExtractor reply_packet;
-    if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+    if (SendRequestAndGetReply (command, request_packet, reply_packet))
     {
-        uint32_t offset = 8;
+        lldb::offset_t offset = 8;
         uint32_t kdp_error = reply_packet.GetU32 (&offset);
         uint32_t src_len = reply_packet.GetByteSize() - 12;
         
@@ -1032,7 +1315,7 @@ CommunicationKDP::SendRequestReadRegiste
                 error.Clear();
                 // Return the number of bytes we could have returned regardless if
                 // we copied them or not, just so we know when things don't match up
-                return src_len; 
+                return src_len;
             }
         }
         if (kdp_error)
@@ -1040,24 +1323,56 @@ CommunicationKDP::SendRequestReadRegiste
         else
             error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u", cpu, flavor);
     }
+    else
+    {
+        error.SetErrorString ("failed to send packet");
+    }
+    return 0;
+}
+
+uint32_t
+CommunicationKDP::SendRequestWriteRegisters (uint32_t cpu,
+                                             uint32_t flavor,
+                                             const void *src,
+                                             uint32_t src_len,
+                                             Error &error)
+{
+    PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
+    const CommandType command = KDP_WRITEREGS;
+    // Size is header + 4 byte cpu and 4 byte flavor
+    const uint32_t command_length = 8 + 4 + 4 + src_len;
+    MakeRequestPacketHeader (command, request_packet, command_length);
+    request_packet.PutHex32 (cpu);
+    request_packet.PutHex32 (flavor);
+    request_packet.Write(src, src_len);
+    DataExtractor reply_packet;
+    if (SendRequestAndGetReply (command, request_packet, reply_packet))
+    {
+        lldb::offset_t offset = 8;
+        uint32_t kdp_error = reply_packet.GetU32 (&offset);
+        if (kdp_error == 0)
+            return src_len;
+        error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, flavor, kdp_error);
+    }
+    else
+    {
+        error.SetErrorString ("failed to send packet");
+    }
     return 0;
 }
 
 
 bool
-CommunicationKDP::SendRequestResume (uint32_t cpu_mask)
+CommunicationKDP::SendRequestResume ()
 {
-    if (cpu_mask == 0)
-        cpu_mask = GetCPUMask();
     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
     const CommandType command = KDP_RESUMECPUS;
     const uint32_t command_length = 12;
-    const uint32_t request_sequence_id = m_request_sequence_id;
     MakeRequestPacketHeader (command, request_packet, command_length);
-    request_packet.PutHex32(cpu_mask);
+    request_packet.PutHex32(GetCPUMask());
 
     DataExtractor reply_packet;
-    if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+    if (SendRequestAndGetReply (command, request_packet, reply_packet))
         return true;
     return false;
 }
@@ -1072,14 +1387,13 @@ CommunicationKDP::SendRequestBreakpoint
                                       (use_64 ? KDP_BREAKPOINT_REMOVE64 : KDP_BREAKPOINT_REMOVE);
 
     const uint32_t command_length = 8 + command_addr_byte_size;
-    const uint32_t request_sequence_id = m_request_sequence_id;
     MakeRequestPacketHeader (command, request_packet, command_length);
     request_packet.PutMaxHex64 (addr, command_addr_byte_size);
     
     DataExtractor reply_packet;
-    if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+    if (SendRequestAndGetReply (command, request_packet, reply_packet))
     {
-        uint32_t offset = 8;
+        lldb::offset_t offset = 8;
         uint32_t kdp_error = reply_packet.GetU32 (&offset);        
         if (kdp_error == 0)
             return true;
@@ -1093,10 +1407,9 @@ CommunicationKDP::SendRequestSuspend ()
     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
     const CommandType command = KDP_SUSPEND;
     const uint32_t command_length = 8;
-    const uint32_t request_sequence_id = m_request_sequence_id;
     MakeRequestPacketHeader (command, request_packet, command_length);
     DataExtractor reply_packet;
-    if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+    if (SendRequestAndGetReply (command, request_packet, reply_packet))
         return true;
     return false;
 }

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h Thu Jun  6 19:06:43 2013
@@ -62,7 +62,14 @@ public:
         KDP_WRITEMEM64,
         KDP_BREAKPOINT_SET64,
         KDP_BREAKPOINT_REMOVE64,
-        KDP_KERNELVERSION
+        KDP_KERNELVERSION,
+        KDP_READPHYSMEM64,
+        KDP_WRITEPHYSMEM64,
+        KDP_READIOPORT,
+        KDP_WRITEIOPORT,
+        KDP_READMSR64,
+        KDP_WRITEMSR64,
+        KDP_DUMPINFO
     } CommandType;
 
     enum 
@@ -111,7 +118,7 @@ public:
     bool
     IsRunning() const
     {
-        return m_public_is_running.GetValue();
+        return m_is_running.GetValue();
     }
 
     //------------------------------------------------------------------
@@ -171,13 +178,27 @@ public:
                             uint32_t src_len,
                             lldb_private::Error &error);
 
+    bool
+    SendRawRequest (uint8_t command_byte,
+                    const void *src,
+                    uint32_t src_len,
+                    lldb_private::DataExtractor &reply,
+                    lldb_private::Error &error);
+
     uint32_t
     SendRequestReadRegisters (uint32_t cpu,
                               uint32_t flavor,
                               void *dst, 
                               uint32_t dst_size,
                               lldb_private::Error &error);
-    
+
+    uint32_t
+    SendRequestWriteRegisters (uint32_t cpu,
+                               uint32_t flavor,
+                               const void *src,
+                               uint32_t src_size,
+                               lldb_private::Error &error);
+
     const char *
     GetKernelVersion ();
     
@@ -206,9 +227,20 @@ public:
     uint32_t
     GetCPUSubtype ();
 
-    // If cpu_mask is zero, then we will resume all CPUs
+    lldb_private::UUID 
+    GetUUID ();
+
+    bool
+    RemoteIsEFI ();
+
+    bool
+    RemoteIsDarwinKernel ();
+
+    lldb::addr_t
+    GetLoadAddress ();
+
     bool
-    SendRequestResume (uint32_t cpu_mask = 0);
+    SendRequestResume ();
 
     bool
     SendRequestSuspend ();
@@ -293,7 +325,6 @@ protected:
     
     bool
     SendRequestAndGetReply (const CommandType command,
-                            const uint8_t request_sequence_id,
                             const PacketStreamType &request_packet, 
                             lldb_private::DataExtractor &reply_packet);
     //------------------------------------------------------------------
@@ -303,8 +334,7 @@ protected:
     lldb::ByteOrder m_byte_order;
     uint32_t m_packet_timeout;
     lldb_private::Mutex m_sequence_mutex;    // Restrict access to sending/receiving packets to a single thread at a time
-    lldb_private::Predicate<bool> m_public_is_running;
-    lldb_private::Predicate<bool> m_private_is_running;
+    lldb_private::Predicate<bool> m_is_running;
     uint32_t m_session_key;
     uint8_t m_request_sequence_id;
     uint8_t m_exception_sequence_id;

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp Thu Jun  6 19:06:43 2013
@@ -16,8 +16,20 @@
 #include "lldb/Core/ConnectionFileDescriptor.h"
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/State.h"
+#include "lldb/Core/UUID.h"
 #include "lldb/Host/Host.h"
+#include "lldb/Host/Symbols.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionGroupString.h"
+#include "lldb/Interpreter/OptionGroupUInt64.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/RegisterContext.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Target/Thread.h"
 
@@ -25,15 +37,20 @@
 #include "ProcessKDP.h"
 #include "ProcessKDPLog.h"
 #include "ThreadKDP.h"
-#include "StopInfoMachException.h"
+#include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"
+#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"
+#include "Utility/StringExtractor.h"
 
 using namespace lldb;
 using namespace lldb_private;
 
-const char *
+static const lldb::tid_t g_kernel_tid = 1;
+
+ConstString
 ProcessKDP::GetPluginNameStatic()
 {
-    return "kdp-remote";
+    static ConstString g_name("kdp-remote");
+    return g_name;
 }
 
 const char *
@@ -99,10 +116,14 @@ ProcessKDP::ProcessKDP(Target& target, L
     Process (target, listener),
     m_comm("lldb.process.kdp-remote.communication"),
     m_async_broadcaster (NULL, "lldb.process.kdp-remote.async-broadcaster"),
-    m_async_thread (LLDB_INVALID_HOST_THREAD)
+    m_async_thread (LLDB_INVALID_HOST_THREAD),
+    m_dyld_plugin_name (),
+    m_kernel_load_addr (LLDB_INVALID_ADDRESS),
+    m_command_sp(),
+    m_kernel_thread_wp()
 {
-//    m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit,   "async thread should exit");
-//    m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue,           "async thread continue");
+    m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit,   "async thread should exit");
+    m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue,           "async thread continue");
 }
 
 //----------------------------------------------------------------------
@@ -121,15 +142,9 @@ ProcessKDP::~ProcessKDP()
 //----------------------------------------------------------------------
 // PluginInterface
 //----------------------------------------------------------------------
-const char *
+lldb_private::ConstString
 ProcessKDP::GetPluginName()
 {
-    return "Process debugging plug-in that uses the Darwin KDP remote protocol";
-}
-
-const char *
-ProcessKDP::GetShortPluginName()
-{
     return GetPluginNameStatic();
 }
 
@@ -164,15 +179,22 @@ ProcessKDP::WillAttachToProcessWithName
 }
 
 Error
-ProcessKDP::DoConnectRemote (const char *remote_url)
+ProcessKDP::DoConnectRemote (Stream *strm, const char *remote_url)
 {
-    // TODO: fill in the remote connection to the remote KDP here!
     Error error;
-    
+
+    // Don't let any JIT happen when doing KDP as we can't allocate
+    // memory and we don't want to be mucking with threads that might
+    // already be handling exceptions
+    SetCanJIT(false);
+
     if (remote_url == NULL || remote_url[0] == '\0')
-        remote_url = "udp://localhost:41139";
+    {
+        error.SetErrorStringWithFormat ("invalid connection URL '%s'", remote_url);
+        return error;
+    }
 
-    std::auto_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
+    std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
     if (conn_ap.get())
     {
         // Only try once for now.
@@ -204,6 +226,28 @@ ProcessKDP::DoConnectRemote (const char
                     ArchSpec kernel_arch;
                     kernel_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
                     m_target.SetArchitecture(kernel_arch);
+
+                    /* Get the kernel's UUID and load address via KDP_KERNELVERSION packet.  */
+                    /* An EFI kdp session has neither UUID nor load address. */
+
+                    UUID kernel_uuid = m_comm.GetUUID ();
+                    addr_t kernel_load_addr = m_comm.GetLoadAddress ();
+
+                    if (m_comm.RemoteIsEFI ())
+                    {
+                        m_dyld_plugin_name = DynamicLoaderStatic::GetPluginNameStatic();
+                    }
+                    else if (m_comm.RemoteIsDarwinKernel ())
+                    {
+                        m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
+                        if (kernel_load_addr != LLDB_INVALID_ADDRESS)
+                        {
+                            m_kernel_load_addr = kernel_load_addr;
+                        }
+                    }
+
+                    // Set the thread ID
+                    UpdateThreadListIfNeeded ();
                     SetID (1);
                     GetThreadList ();
                     SetPrivateState (eStateStopped);
@@ -223,10 +267,14 @@ ProcessKDP::DoConnectRemote (const char
 //                      }            
                     }
                 }
+                else
+                {
+                    error.SetErrorString("KDP_REATTACH failed");
+                }
             }
             else
             {
-                error.SetErrorString("KDP reattach failed");
+                error.SetErrorString("KDP_REATTACH failed");
             }
         }
         else
@@ -286,7 +334,7 @@ ProcessKDP::DoAttachToProcessWithName (c
 void
 ProcessKDP::DidAttach ()
 {
-    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS));
+    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS));
     if (log)
         log->Printf ("ProcessKDP::DidAttach()");
     if (GetID() != LLDB_INVALID_PROCESS_ID)
@@ -295,6 +343,20 @@ ProcessKDP::DidAttach ()
     }
 }
 
+addr_t
+ProcessKDP::GetImageInfoAddress()
+{
+    return m_kernel_load_addr;
+}
+
+lldb_private::DynamicLoader *
+ProcessKDP::GetDynamicLoader ()
+{
+    if (m_dyld_ap.get() == NULL)
+        m_dyld_ap.reset (DynamicLoader::FindPlugin(this, m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString()));
+    return m_dyld_ap.get();
+}
+
 Error
 ProcessKDP::WillResume ()
 {
@@ -305,42 +367,129 @@ Error
 ProcessKDP::DoResume ()
 {
     Error error;
-    if (!m_comm.SendRequestResume ())
-        error.SetErrorString ("KDP resume failed");
+    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS));
+    // Only start the async thread if we try to do any process control
+    if (!IS_VALID_LLDB_HOST_THREAD(m_async_thread))
+        StartAsyncThread ();
+
+    bool resume = false;
+    
+    // With KDP there is only one thread we can tell what to do
+    ThreadSP kernel_thread_sp (m_thread_list.FindThreadByProtocolID(g_kernel_tid));
+                            
+    if (kernel_thread_sp)
+    {
+        const StateType thread_resume_state = kernel_thread_sp->GetTemporaryResumeState();
+        
+        if (log)
+            log->Printf ("ProcessKDP::DoResume() thread_resume_state = %s", StateAsCString(thread_resume_state));
+        switch (thread_resume_state)
+        {
+            case eStateSuspended:
+                // Nothing to do here when a thread will stay suspended
+                // we just leave the CPU mask bit set to zero for the thread
+                if (log)
+                    log->Printf ("ProcessKDP::DoResume() = suspended???");
+                break;
+                
+            case eStateStepping:
+                {
+                    lldb::RegisterContextSP reg_ctx_sp (kernel_thread_sp->GetRegisterContext());
+
+                    if (reg_ctx_sp)
+                    {
+                        if (log)
+                            log->Printf ("ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);");
+                        reg_ctx_sp->HardwareSingleStep (true);
+                        resume = true;
+                    }
+                    else
+                    {
+                        error.SetErrorStringWithFormat("KDP thread 0x%llx has no register context", kernel_thread_sp->GetID());
+                    }
+                }
+                break;
+    
+            case eStateRunning:
+                {
+                    lldb::RegisterContextSP reg_ctx_sp (kernel_thread_sp->GetRegisterContext());
+                    
+                    if (reg_ctx_sp)
+                    {
+                        if (log)
+                            log->Printf ("ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (false);");
+                        reg_ctx_sp->HardwareSingleStep (false);
+                        resume = true;
+                    }
+                    else
+                    {
+                        error.SetErrorStringWithFormat("KDP thread 0x%llx has no register context", kernel_thread_sp->GetID());
+                    }
+                }
+                break;
+
+            default:
+                // The only valid thread resume states are listed above
+                assert (!"invalid thread resume state");
+                break;
+        }
+    }
+
+    if (resume)
+    {
+        if (log)
+            log->Printf ("ProcessKDP::DoResume () sending resume");
+        
+        if (m_comm.SendRequestResume ())
+        {
+            m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue);
+            SetPrivateState(eStateRunning);
+        }
+        else
+            error.SetErrorString ("KDP resume failed");
+    }
+    else
+    {
+        error.SetErrorString ("kernel thread is suspended");        
+    }
+    
     return error;
 }
 
-bool
-ProcessKDP::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
+lldb::ThreadSP
+ProcessKDP::GetKernelThread()
 {
-    // locker will keep a mutex locked until it goes out of scope
-    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_THREAD));
-    if (log && log->GetMask().Test(KDP_LOG_VERBOSE))
-        log->Printf ("ProcessKDP::%s (pid = %llu)", __FUNCTION__, GetID());
+    // KDP only tells us about one thread/core. Any other threads will usually
+    // be the ones that are read from memory by the OS plug-ins.
     
-    // We currently are making only one thread per core and we
-    // actually don't know about actual threads. Eventually we
-    // want to get the thread list from memory and note which
-    // threads are on CPU as those are the only ones that we 
-    // will be able to resume.
-    const uint32_t cpu_mask = m_comm.GetCPUMask();
-    for (uint32_t cpu_mask_bit = 1; cpu_mask_bit & cpu_mask; cpu_mask_bit <<= 1)
-    {
-        lldb::tid_t tid = cpu_mask_bit;
-        ThreadSP thread_sp (old_thread_list.FindThreadByID (tid, false));
-        if (!thread_sp)
-            thread_sp.reset(new ThreadKDP (shared_from_this(), tid));
-        new_thread_list.AddThread(thread_sp);
+    ThreadSP thread_sp (m_kernel_thread_wp.lock());
+    if (!thread_sp)
+    {
+        thread_sp.reset(new ThreadKDP (*this, g_kernel_tid));
+        m_kernel_thread_wp = thread_sp;
     }
-    return new_thread_list.GetSize(false) > 0;
+    return thread_sp;
 }
 
 
-StateType
-ProcessKDP::SetThreadStopInfo (StringExtractor& stop_packet)
+
+
+bool
+ProcessKDP::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
 {
-    // TODO: figure out why we stopped given the packet that tells us we stopped...
-    return eStateStopped;
+    // locker will keep a mutex locked until it goes out of scope
+    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_THREAD));
+    if (log && log->GetMask().Test(KDP_LOG_VERBOSE))
+        log->Printf ("ProcessKDP::%s (pid = %" PRIu64 ")", __FUNCTION__, GetID());
+    
+    // Even though there is a CPU mask, it doesn't mean we can see each CPU
+    // indivudually, there is really only one. Lets call this thread 1.
+    ThreadSP thread_sp (old_thread_list.FindThreadByProtocolID(g_kernel_tid, false));
+    if (!thread_sp)
+        thread_sp = GetKernelThread ();
+    new_thread_list.AddThread(thread_sp);
+
+    return new_thread_list.GetSize(false) > 0;
 }
 
 void
@@ -349,7 +498,6 @@ ProcessKDP::RefreshStateAfterStop ()
     // Let all threads recover from stopping and do any clean up based
     // on the previous thread state (if any).
     m_thread_list.RefreshStateAfterStop();
-    //SetThreadStopInfo (m_last_stop_packet);
 }
 
 Error
@@ -357,140 +505,57 @@ ProcessKDP::DoHalt (bool &caused_stop)
 {
     Error error;
     
-//    bool timed_out = false;
-    Mutex::Locker locker;
-    
-    if (m_public_state.GetValue() == eStateAttaching)
+    if (m_comm.IsRunning())
     {
-        // We are being asked to halt during an attach. We need to just close
-        // our file handle and debugserver will go away, and we can be done...
-        m_comm.Disconnect();
-    }
-    else
-    {
-        if (!m_comm.SendRequestSuspend ())
-            error.SetErrorString ("KDP halt failed");
+        if (m_destroy_in_process)
+        {
+            // If we are attemping to destroy, we need to not return an error to
+            // Halt or DoDestroy won't get called.
+            // We are also currently running, so send a process stopped event
+            SetPrivateState (eStateStopped);
+        }
+        else
+        {
+            error.SetErrorString ("KDP cannot interrupt a running kernel");
+        }
     }
     return error;
 }
 
 Error
-ProcessKDP::InterruptIfRunning (bool discard_thread_plans,
-                                bool catch_stop_event,
-                                EventSP &stop_event_sp)
+ProcessKDP::DoDetach(bool keep_stopped)
 {
     Error error;
-    
-    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
-    
-    bool paused_private_state_thread = false;
-    const bool is_running = m_comm.IsRunning();
+    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
     if (log)
-        log->Printf ("ProcessKDP::InterruptIfRunning(discard_thread_plans=%i, catch_stop_event=%i) is_running=%i", 
-                     discard_thread_plans, 
-                     catch_stop_event,
-                     is_running);
+        log->Printf ("ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped);
     
-    if (discard_thread_plans)
+    if (m_comm.IsRunning())
     {
-        if (log)
-            log->Printf ("ProcessKDP::InterruptIfRunning() discarding all thread plans");
-        m_thread_list.DiscardThreadPlans();
+        // We are running and we can't interrupt a running kernel, so we need
+        // to just close the connection to the kernel and hope for the best
     }
-    if (is_running)
+    else
     {
-        if (catch_stop_event)
-        {
-            if (log)
-                log->Printf ("ProcessKDP::InterruptIfRunning() pausing private state thread");
-            PausePrivateStateThread();
-            paused_private_state_thread = true;
-        }
-        
-        bool timed_out = false;
-//        bool sent_interrupt = false;
-        Mutex::Locker locker;
-
-        // TODO: implement halt in CommunicationKDP
-//        if (!m_comm.SendInterrupt (locker, 1, sent_interrupt, timed_out))
-//        {
-//            if (timed_out)
-//                error.SetErrorString("timed out sending interrupt packet");
-//            else
-//                error.SetErrorString("unknown error sending interrupt packet");
-//            if (paused_private_state_thread)
-//                ResumePrivateStateThread();
-//            return error;
-//        }
+        DisableAllBreakpointSites ();
         
-        if (catch_stop_event)
-        {
-            // LISTEN HERE
-            TimeValue timeout_time;
-            timeout_time = TimeValue::Now();
-            timeout_time.OffsetWithSeconds(5);
-            StateType state = WaitForStateChangedEventsPrivate (&timeout_time, stop_event_sp);
-            
-            timed_out = state == eStateInvalid;
-            if (log)
-                log->Printf ("ProcessKDP::InterruptIfRunning() catch stop event: state = %s, timed-out=%i", StateAsCString(state), timed_out);
-            
-            if (timed_out)
-                error.SetErrorString("unable to verify target stopped");
-        }
+        m_thread_list.DiscardThreadPlans();
         
-        if (paused_private_state_thread)
+        // If we are going to keep the target stopped, then don't send the disconnect message.
+        if (!keep_stopped && m_comm.IsConnected())
         {
+            const bool success = m_comm.SendRequestDisconnect();
             if (log)
-                log->Printf ("ProcessKDP::InterruptIfRunning() resuming private state thread");
-            ResumePrivateStateThread();
-        }
-    }
-    return error;
-}
-
-Error
-ProcessKDP::WillDetach ()
-{
-    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
-    if (log)
-        log->Printf ("ProcessKDP::WillDetach()");
-    
-    bool discard_thread_plans = true; 
-    bool catch_stop_event = true;
-    EventSP event_sp;
-    return InterruptIfRunning (discard_thread_plans, catch_stop_event, event_sp);
-}
-
-Error
-ProcessKDP::DoDetach()
-{
-    Error error;
-    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
-    if (log)
-        log->Printf ("ProcessKDP::DoDetach()");
-    
-    DisableAllBreakpointSites ();
-    
-    m_thread_list.DiscardThreadPlans();
-    
-    if (m_comm.IsConnected())
-    {
-
-        m_comm.SendRequestDisconnect();
-
-        size_t response_size = m_comm.Disconnect ();
-        if (log)
-        {
-            if (response_size)
-                log->PutCString ("ProcessKDP::DoDetach() detach packet sent successfully");
-            else
-                log->PutCString ("ProcessKDP::DoDetach() detach packet send failed");
+            {
+                if (success)
+                    log->PutCString ("ProcessKDP::DoDetach() detach packet sent successfully");
+                else
+                    log->PutCString ("ProcessKDP::DoDetach() connection channel shutdown failed");
+            }
+            m_comm.Disconnect ();
         }
     }
-    // Sleep for one second to let the process get all detached...
-    StopAsyncThread ();
-    
+    StopAsyncThread ();    
     m_comm.Clear();
     
     SetPrivateState (eStateDetached);
@@ -503,34 +568,9 @@ ProcessKDP::DoDetach()
 Error
 ProcessKDP::DoDestroy ()
 {
-    Error error;
-    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
-    if (log)
-        log->Printf ("ProcessKDP::DoDestroy()");
-    
-    // Interrupt if our inferior is running...
-    if (m_comm.IsConnected())
-    {
-        if (m_public_state.GetValue() == eStateAttaching)
-        {
-            // We are being asked to halt during an attach. We need to just close
-            // our file handle and debugserver will go away, and we can be done...
-            m_comm.Disconnect();
-        }
-        else
-        {
-            DisableAllBreakpointSites ();
-            
-            m_comm.SendRequestDisconnect();
-            
-            StringExtractor response;
-            // TODO: Send kill packet?
-            SetExitStatus(SIGABRT, NULL);
-        }
-    }
-    StopAsyncThread ();
-    m_comm.Clear();
-    return error;
+    // For KDP there really is no difference between destroy and detach
+    bool keep_stopped = false;
+    return DoDetach(keep_stopped);
 }
 
 //------------------------------------------------------------------
@@ -558,7 +598,9 @@ ProcessKDP::DoReadMemory (addr_t addr, v
 size_t
 ProcessKDP::DoWriteMemory (addr_t addr, const void *buf, size_t size, Error &error)
 {
-    error.SetErrorString ("ProcessKDP::DoReadMemory not implemented");
+    if (m_comm.IsConnected())
+        return m_comm.SendRequestWriteMemory (addr, buf, size, error);
+    error.SetErrorString ("not connected");
     return 0;
 }
 
@@ -578,7 +620,7 @@ ProcessKDP::DoDeallocateMemory (lldb::ad
 }
 
 Error
-ProcessKDP::EnableBreakpoint (BreakpointSite *bp_site)
+ProcessKDP::EnableBreakpointSite (BreakpointSite *bp_site)
 {
     if (m_comm.LocalBreakpointsAreSupported ())
     {
@@ -601,7 +643,7 @@ ProcessKDP::EnableBreakpoint (Breakpoint
 }
 
 Error
-ProcessKDP::DisableBreakpoint (BreakpointSite *bp_site)
+ProcessKDP::DisableBreakpointSite (BreakpointSite *bp_site)
 {
     if (m_comm.LocalBreakpointsAreSupported ())
     {
@@ -611,10 +653,18 @@ ProcessKDP::DisableBreakpoint (Breakpoin
             BreakpointSite::Type bp_type = bp_site->GetType();
             if (bp_type == BreakpointSite::eExternal)
             {
-                if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress()))
+                if (m_destroy_in_process && m_comm.IsRunning())
+                {
+                    // We are trying to destroy our connection and we are running
                     bp_site->SetEnabled(false);
+                }
                 else
-                    error.SetErrorString ("KDP remove breakpoint failed");
+                {
+                    if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress()))
+                        bp_site->SetEnabled(false);
+                    else
+                        error.SetErrorString ("KDP remove breakpoint failed");
+                }
             }
             else
             {
@@ -627,7 +677,7 @@ ProcessKDP::DisableBreakpoint (Breakpoin
 }
 
 Error
-ProcessKDP::EnableWatchpoint (Watchpoint *wp)
+ProcessKDP::EnableWatchpoint (Watchpoint *wp, bool notify)
 {
     Error error;
     error.SetErrorString ("watchpoints are not suppported in kdp remote debugging");
@@ -635,7 +685,7 @@ ProcessKDP::EnableWatchpoint (Watchpoint
 }
 
 Error
-ProcessKDP::DisableWatchpoint (Watchpoint *wp)
+ProcessKDP::DisableWatchpoint (Watchpoint *wp, bool notify)
 {
     Error error;
     error.SetErrorString ("watchpoints are not suppported in kdp remote debugging");
@@ -681,13 +731,14 @@ ProcessKDP::Initialize()
 bool
 ProcessKDP::StartAsyncThread ()
 {
-    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
+    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
     
     if (log)
-        log->Printf ("ProcessKDP::%s ()", __FUNCTION__);
+        log->Printf ("ProcessKDP::StartAsyncThread ()");
     
-    // Create a thread that watches our internal state and controls which
-    // events make it to clients (into the DCProcess event queue).
+    if (IS_VALID_LLDB_HOST_THREAD(m_async_thread))
+        return true;
+
     m_async_thread = Host::ThreadCreate ("<lldb.process.kdp-remote.async>", ProcessKDP::AsyncThread, this, NULL);
     return IS_VALID_LLDB_HOST_THREAD(m_async_thread);
 }
@@ -695,10 +746,10 @@ ProcessKDP::StartAsyncThread ()
 void
 ProcessKDP::StopAsyncThread ()
 {
-    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
+    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
     
     if (log)
-        log->Printf ("ProcessKDP::%s ()", __FUNCTION__);
+        log->Printf ("ProcessKDP::StopAsyncThread ()");
     
     m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit);
     
@@ -706,6 +757,7 @@ ProcessKDP::StopAsyncThread ()
     if (IS_VALID_LLDB_HOST_THREAD(m_async_thread))
     {
         Host::ThreadJoin (m_async_thread, NULL, NULL);
+        m_async_thread = LLDB_INVALID_HOST_THREAD;
     }
 }
 
@@ -715,116 +767,291 @@ ProcessKDP::AsyncThread (void *arg)
 {
     ProcessKDP *process = (ProcessKDP*) arg;
     
-    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS));
+    const lldb::pid_t pid = process->GetID();
+
+    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS));
     if (log)
-        log->Printf ("ProcessKDP::%s (arg = %p, pid = %llu) thread starting...", __FUNCTION__, arg, process->GetID());
+        log->Printf ("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 ") thread starting...", arg, pid);
     
     Listener listener ("ProcessKDP::AsyncThread");
     EventSP event_sp;
     const uint32_t desired_event_mask = eBroadcastBitAsyncContinue |
                                         eBroadcastBitAsyncThreadShouldExit;
     
+    
     if (listener.StartListeningForEvents (&process->m_async_broadcaster, desired_event_mask) == desired_event_mask)
     {
-        listener.StartListeningForEvents (&process->m_comm, Communication::eBroadcastBitReadThreadDidExit);
-        
         bool done = false;
         while (!done)
         {
             if (log)
-                log->Printf ("ProcessKDP::%s (arg = %p, pid = %llu) listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID());
+                log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp)...",
+                             pid);
             if (listener.WaitForEvent (NULL, event_sp))
             {
-                const uint32_t event_type = event_sp->GetType();
-                if (event_sp->BroadcasterIs (&process->m_async_broadcaster))
+                uint32_t event_type = event_sp->GetType();
+                if (log)
+                    log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") Got an event of type: %d...",
+                                 pid,
+                                 event_type);
+                
+                // When we are running, poll for 1 second to try and get an exception
+                // to indicate the process has stopped. If we don't get one, check to
+                // make sure no one asked us to exit
+                bool is_running = false;
+                DataExtractor exc_reply_packet;
+                do
                 {
-                    if (log)
-                        log->Printf ("ProcessKDP::%s (arg = %p, pid = %llu) Got an event of type: %d...", __FUNCTION__, arg, process->GetID(), event_type);
-                    
                     switch (event_type)
                     {
-                        case eBroadcastBitAsyncContinue:
+                    case eBroadcastBitAsyncContinue:
                         {
-                            const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get());
-                            
-                            if (continue_packet)
+                            is_running = true;
+                            if (process->m_comm.WaitForPacketWithTimeoutMicroSeconds (exc_reply_packet, 1 * USEC_PER_SEC))
+                            {
+                                ThreadSP thread_sp (process->GetKernelThread());
+                                if (thread_sp)
+                                {
+                                    lldb::RegisterContextSP reg_ctx_sp (thread_sp->GetRegisterContext());
+                                    if (reg_ctx_sp)
+                                        reg_ctx_sp->InvalidateAllRegisters();
+                                    static_cast<ThreadKDP *>(thread_sp.get())->SetStopInfoFrom_KDP_EXCEPTION (exc_reply_packet);
+                                }
+
+                                // TODO: parse the stop reply packet
+                                is_running = false;                                
+                                process->SetPrivateState(eStateStopped);
+                            }
+                            else
                             {
-                                // TODO: do continue support here
-                                
-//                                const char *continue_cstr = (const char *)continue_packet->GetBytes ();
-//                                const size_t continue_cstr_len = continue_packet->GetByteSize ();
-//                                if (log)
-//                                    log->Printf ("ProcessKDP::%s (arg = %p, pid = %i) got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr);
-//                                
-//                                if (::strstr (continue_cstr, "vAttach") == NULL)
-//                                    process->SetPrivateState(eStateRunning);
-//                                StringExtractor response;
-//                                StateType stop_state = process->GetCommunication().SendContinuePacketAndWaitForResponse (process, continue_cstr, continue_cstr_len, response);
-//                                
-//                                switch (stop_state)
-//                                {
-//                                    case eStateStopped:
-//                                    case eStateCrashed:
-//                                    case eStateSuspended:
-//                                        process->m_last_stop_packet = response;
-//                                        process->SetPrivateState (stop_state);
-//                                        break;
-//                                        
-//                                    case eStateExited:
-//                                        process->m_last_stop_packet = response;
-//                                        response.SetFilePos(1);
-//                                        process->SetExitStatus(response.GetHexU8(), NULL);
-//                                        done = true;
-//                                        break;
-//                                        
-//                                    case eStateInvalid:
-//                                        process->SetExitStatus(-1, "lost connection");
-//                                        break;
-//                                        
-//                                    default:
-//                                        process->SetPrivateState (stop_state);
-//                                        break;
-//                                }
+                                // Check to see if we are supposed to exit. There is no way to
+                                // interrupt a running kernel, so all we can do is wait for an
+                                // exception or detach...
+                                if (listener.GetNextEvent(event_sp))
+                                {
+                                    // We got an event, go through the loop again
+                                    event_type = event_sp->GetType();
+                                }
                             }
                         }
-                            break;
+                        break;
                             
-                        case eBroadcastBitAsyncThreadShouldExit:
-                            if (log)
-                                log->Printf ("ProcessKDP::%s (arg = %p, pid = %llu) got eBroadcastBitAsyncThreadShouldExit...", __FUNCTION__, arg, process->GetID());
-                            done = true;
-                            break;
+                    case eBroadcastBitAsyncThreadShouldExit:
+                        if (log)
+                            log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") got eBroadcastBitAsyncThreadShouldExit...",
+                                         pid);
+                        done = true;
+                        is_running = false;
+                        break;
                             
-                        default:
-                            if (log)
-                                log->Printf ("ProcessKDP::%s (arg = %p, pid = %llu) got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type);
-                            done = true;
-                            break;
-                    }
-                }
-                else if (event_sp->BroadcasterIs (&process->m_comm))
-                {
-                    if (event_type & Communication::eBroadcastBitReadThreadDidExit)
-                    {
-                        process->SetExitStatus (-1, "lost connection");
+                    default:
+                        if (log)
+                            log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") got unknown event 0x%8.8x",
+                                         pid,
+                                         event_type);
                         done = true;
+                        is_running = false;
+                        break;
                     }
-                }
+                } while (is_running);
             }
             else
             {
                 if (log)
-                    log->Printf ("ProcessKDP::%s (arg = %p, pid = %llu) listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID());
+                    log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp) => false",
+                                 pid);
                 done = true;
             }
         }
     }
     
     if (log)
-        log->Printf ("ProcessKDP::%s (arg = %p, pid = %llu) thread exiting...", __FUNCTION__, arg, process->GetID());
+        log->Printf ("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 ") thread exiting...",
+                     arg,
+                     pid);
     
     process->m_async_thread = LLDB_INVALID_HOST_THREAD;
     return NULL;
 }
 
 
+class CommandObjectProcessKDPPacketSend : public CommandObjectParsed
+{
+private:
+    
+    OptionGroupOptions m_option_group;
+    OptionGroupUInt64 m_command_byte;
+    OptionGroupString m_packet_data;
+    
+    virtual Options *
+    GetOptions ()
+    {
+        return &m_option_group;
+    }
+    
+
+public:
+    CommandObjectProcessKDPPacketSend(CommandInterpreter &interpreter) :
+        CommandObjectParsed (interpreter,
+                             "process plugin packet send",
+                             "Send a custom packet through the KDP protocol by specifying the command byte and the packet payload data. A packet will be sent with a correct header and payload, and the raw result bytes will be displayed as a string value. ",
+                             NULL),
+        m_option_group (interpreter),
+        m_command_byte(LLDB_OPT_SET_1, true , "command", 'c', 0, eArgTypeNone, "Specify the command byte to use when sending the KDP request packet.", 0),
+        m_packet_data (LLDB_OPT_SET_1, false, "payload", 'p', 0, eArgTypeNone, "Specify packet payload bytes as a hex ASCII string with no spaces or hex prefixes.", NULL)
+    {
+        m_option_group.Append (&m_command_byte, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
+        m_option_group.Append (&m_packet_data , LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
+        m_option_group.Finalize();
+    }
+    
+    ~CommandObjectProcessKDPPacketSend ()
+    {
+    }
+    
+    bool
+    DoExecute (Args& command, CommandReturnObject &result)
+    {
+        const size_t argc = command.GetArgumentCount();
+        if (argc == 0)
+        {
+            if (!m_command_byte.GetOptionValue().OptionWasSet())
+            {
+                result.AppendError ("the --command option must be set to a valid command byte");
+                result.SetStatus (eReturnStatusFailed);
+            }
+            else
+            {
+                const uint64_t command_byte = m_command_byte.GetOptionValue().GetUInt64Value(0);
+                if (command_byte > 0 && command_byte <= UINT8_MAX)
+                {
+                    ProcessKDP *process = (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr();
+                    if (process)
+                    {
+                        const StateType state = process->GetState();
+                        
+                        if (StateIsStoppedState (state, true))
+                        {
+                            std::vector<uint8_t> payload_bytes;
+                            const char *ascii_hex_bytes_cstr = m_packet_data.GetOptionValue().GetCurrentValue();
+                            if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0])
+                            {
+                                StringExtractor extractor(ascii_hex_bytes_cstr);
+                                const size_t ascii_hex_bytes_cstr_len = extractor.GetStringRef().size();
+                                if (ascii_hex_bytes_cstr_len & 1)
+                                {
+                                    result.AppendErrorWithFormat ("payload data must contain an even number of ASCII hex characters: '%s'", ascii_hex_bytes_cstr);
+                                    result.SetStatus (eReturnStatusFailed);
+                                    return false;
+                                }
+                                payload_bytes.resize(ascii_hex_bytes_cstr_len/2);
+                                if (extractor.GetHexBytes(&payload_bytes[0], payload_bytes.size(), '\xdd') != payload_bytes.size())
+                                {
+                                    result.AppendErrorWithFormat ("payload data must only contain ASCII hex characters (no spaces or hex prefixes): '%s'", ascii_hex_bytes_cstr);
+                                    result.SetStatus (eReturnStatusFailed);
+                                    return false;
+                                }
+                            }
+                            Error error;
+                            DataExtractor reply;
+                            process->GetCommunication().SendRawRequest (command_byte,
+                                                                        payload_bytes.empty() ? NULL : payload_bytes.data(),
+                                                                        payload_bytes.size(),
+                                                                        reply,
+                                                                        error);
+                            
+                            if (error.Success())
+                            {
+                                // Copy the binary bytes into a hex ASCII string for the result
+                                StreamString packet;
+                                packet.PutBytesAsRawHex8(reply.GetDataStart(),
+                                                         reply.GetByteSize(),
+                                                         lldb::endian::InlHostByteOrder(),
+                                                         lldb::endian::InlHostByteOrder());
+                                result.AppendMessage(packet.GetString().c_str());
+                                result.SetStatus (eReturnStatusSuccessFinishResult);
+                                return true;
+                            }
+                            else
+                            {
+                                const char *error_cstr = error.AsCString();
+                                if (error_cstr && error_cstr[0])
+                                    result.AppendError (error_cstr);
+                                else
+                                    result.AppendErrorWithFormat ("unknown error 0x%8.8x", error.GetError());
+                                result.SetStatus (eReturnStatusFailed);
+                                return false;
+                            }
+                        }
+                        else
+                        {
+                            result.AppendErrorWithFormat ("process must be stopped in order to send KDP packets, state is %s", StateAsCString (state));
+                            result.SetStatus (eReturnStatusFailed);
+                        }
+                    }
+                    else
+                    {
+                        result.AppendError ("invalid process");
+                        result.SetStatus (eReturnStatusFailed);
+                    }
+                }
+                else
+                {
+                    result.AppendErrorWithFormat ("invalid command byte 0x%" PRIx64 ", valid values are 1 - 255", command_byte);
+                    result.SetStatus (eReturnStatusFailed);
+                }
+            }
+        }
+        else
+        {
+            result.AppendErrorWithFormat ("'%s' takes no arguments, only options.", m_cmd_name.c_str());
+            result.SetStatus (eReturnStatusFailed);
+        }
+        return false;
+    }
+};
+
+class CommandObjectProcessKDPPacket : public CommandObjectMultiword
+{
+private:
+
+public:
+    CommandObjectProcessKDPPacket(CommandInterpreter &interpreter) :
+    CommandObjectMultiword (interpreter,
+                            "process plugin packet",
+                            "Commands that deal with KDP remote packets.",
+                            NULL)
+    {
+        LoadSubCommand ("send", CommandObjectSP (new CommandObjectProcessKDPPacketSend (interpreter)));
+    }
+    
+    ~CommandObjectProcessKDPPacket ()
+    {
+    }
+};
+
+class CommandObjectMultiwordProcessKDP : public CommandObjectMultiword
+{
+public:
+    CommandObjectMultiwordProcessKDP (CommandInterpreter &interpreter) :
+    CommandObjectMultiword (interpreter,
+                            "process plugin",
+                            "A set of commands for operating on a ProcessKDP process.",
+                            "process plugin <subcommand> [<subcommand-options>]")
+    {
+        LoadSubCommand ("packet", CommandObjectSP (new CommandObjectProcessKDPPacket    (interpreter)));
+    }
+    
+    ~CommandObjectMultiwordProcessKDP ()
+    {
+    }
+};
+
+CommandObject *
+ProcessKDP::GetPluginCommandObject()
+{
+    if (!m_command_sp)
+        m_command_sp.reset (new CommandObjectMultiwordProcessKDP (GetTarget().GetDebugger().GetCommandInterpreter()));
+    return m_command_sp.get();
+}
+

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h Thu Jun  6 19:06:43 2013
@@ -19,6 +19,7 @@
 // Other libraries and framework includes
 #include "lldb/Core/ArchSpec.h"
 #include "lldb/Core/Broadcaster.h"
+#include "lldb/Core/ConstString.h"
 #include "lldb/Core/Error.h"
 #include "lldb/Core/InputReader.h"
 #include "lldb/Core/StreamString.h"
@@ -49,7 +50,7 @@ public:
     static void
     Terminate();
     
-    static const char *
+    static lldb_private::ConstString
     GetPluginNameStatic();
     
     static const char *
@@ -70,8 +71,8 @@ public:
     CanDebug (lldb_private::Target &target,
               bool plugin_specified_by_name);
     
-    //    virtual uint32_t
-    //    ListProcessesMatchingName (const char *name, lldb_private::StringList &matches, std::vector<lldb::pid_t> &pids);
+    virtual lldb_private::CommandObject *
+    GetPluginCommandObject();
     
     //------------------------------------------------------------------
     // Creating a new process, or attaching to an existing one
@@ -90,7 +91,7 @@ public:
     WillAttachToProcessWithName (const char *process_name, bool wait_for_launch);
     
     virtual lldb_private::Error
-    DoConnectRemote (const char *remote_url);
+    DoConnectRemote (lldb_private::Stream *strm, const char *remote_url);
     
     virtual lldb_private::Error
     DoAttachToProcessWithID (lldb::pid_t pid);
@@ -104,15 +105,18 @@ public:
     virtual void
     DidAttach ();
     
+    lldb::addr_t
+    GetImageInfoAddress();
+
+    lldb_private::DynamicLoader *
+    GetDynamicLoader ();
+
     //------------------------------------------------------------------
     // PluginInterface protocol
     //------------------------------------------------------------------
-    virtual const char *
+    virtual lldb_private::ConstString
     GetPluginName();
     
-    virtual const char *
-    GetShortPluginName();
-    
     virtual uint32_t
     GetPluginVersion();
     
@@ -129,10 +133,7 @@ public:
     DoHalt (bool &caused_stop);
     
     virtual lldb_private::Error
-    WillDetach ();
-    
-    virtual lldb_private::Error
-    DoDetach ();
+    DoDetach (bool keep_stopped);
     
     virtual lldb_private::Error
     DoSignal (int signal);
@@ -168,19 +169,19 @@ public:
     // Process Breakpoints
     //----------------------------------------------------------------------
     virtual lldb_private::Error
-    EnableBreakpoint (lldb_private::BreakpointSite *bp_site);
+    EnableBreakpointSite (lldb_private::BreakpointSite *bp_site);
     
     virtual lldb_private::Error
-    DisableBreakpoint (lldb_private::BreakpointSite *bp_site);
+    DisableBreakpointSite (lldb_private::BreakpointSite *bp_site);
     
     //----------------------------------------------------------------------
     // Process Watchpoints
     //----------------------------------------------------------------------
     virtual lldb_private::Error
-    EnableWatchpoint (lldb_private::Watchpoint *wp);
+    EnableWatchpoint (lldb_private::Watchpoint *wp, bool notify = true);
     
     virtual lldb_private::Error
-    DisableWatchpoint (lldb_private::Watchpoint *wp);
+    DisableWatchpoint (lldb_private::Watchpoint *wp, bool notify = true);
     
     CommunicationKDP &
     GetCommunication()
@@ -222,12 +223,6 @@ protected:
     bool
     ProcessIDIsValid ( ) const;
     
-    //    static void
-    //    STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len);
-    
-    //    void
-    //    AppendSTDOUT (const char* s, size_t len);
-    
     void
     Clear ( );
     
@@ -240,11 +235,9 @@ protected:
         eBroadcastBitAsyncContinue                  = (1 << 0),
         eBroadcastBitAsyncThreadShouldExit          = (1 << 1)
     };
-
-    lldb_private::Error
-    InterruptIfRunning (bool discard_thread_plans,
-                        bool catch_stop_event,
-                        lldb::EventSP &stop_event_sp);
+    
+    lldb::ThreadSP
+    GetKernelThread ();
 
     //------------------------------------------------------------------
     /// Broadcaster event bits definitions.
@@ -252,6 +245,11 @@ protected:
     CommunicationKDP m_comm;
     lldb_private::Broadcaster m_async_broadcaster;
     lldb::thread_t m_async_thread;
+    lldb_private::ConstString m_dyld_plugin_name;
+    lldb::addr_t m_kernel_load_addr;
+    lldb::CommandObjectSP m_command_sp;
+    lldb::ThreadWP m_kernel_thread_wp;
+
 
     bool
     StartAsyncThread ();
@@ -262,9 +260,6 @@ protected:
     static void *
     AsyncThread (void *arg);
     
-    lldb::StateType
-    SetThreadStopInfo (StringExtractor& stop_packet);
-    
 private:
     //------------------------------------------------------------------
     // For ProcessKDP only

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp Thu Jun  6 19:06:43 2013
@@ -20,24 +20,27 @@ using namespace lldb_private;
 
 // We want to avoid global constructors where code needs to be run so here we
 // control access to our static g_log_sp by hiding it in a singleton function
-// that will construct the static g_lob_sp the first time this function is 
+// that will construct the static g_log_sp the first time this function is 
 // called.
-static LogSP &
+static bool g_log_enabled = false;
+static Log * g_log = NULL;
+static Log *
 GetLog ()
 {
-    static LogSP g_log_sp;
-    return g_log_sp;
+    if (!g_log_enabled)
+        return NULL;
+    return g_log;
 }
 
-LogSP
+Log *
 ProcessKDPLog::GetLogIfAllCategoriesSet (uint32_t mask)
 {
-    LogSP log(GetLog ());
+    Log *log(GetLog ());
     if (log && mask)
     {
         uint32_t log_mask = log->GetMask().Get();
         if ((log_mask & mask) != mask)
-            return LogSP();
+            return NULL;
     }
     return log;
 }
@@ -45,7 +48,7 @@ ProcessKDPLog::GetLogIfAllCategoriesSet
 void
 ProcessKDPLog::DisableLog (const char **categories, Stream *feedback_strm)
 {
-    LogSP log (GetLog ());
+    Log *log (GetLog ());
     if (log)
     {
         uint32_t flag_bits = 0;
@@ -81,33 +84,33 @@ ProcessKDPLog::DisableLog (const char **
             }
         }
         
+        log->GetMask().Reset (flag_bits);
         if (flag_bits == 0)
-            GetLog ().reset();
-        else
-            log->GetMask().Reset (flag_bits);
+            g_log_enabled = false;
     }
     
     return;
 }
 
-LogSP
+Log *
 ProcessKDPLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, const char **categories, Stream *feedback_strm)
 {
     // Try see if there already is a log - that way we can reuse its settings.
     // We could reuse the log in toto, but we don't know that the stream is the same.
     uint32_t flag_bits = 0;
-    LogSP log(GetLog ());
-    if (log)
-        flag_bits = log->GetMask().Get();
+    if (g_log)
+        flag_bits = g_log->GetMask().Get();
 
     // Now make a new log with this stream if one was provided
     if (log_stream_sp)
     {
-        log.reset (new Log(log_stream_sp));
-        GetLog () = log;
+        if (g_log)
+            g_log->SetStream(log_stream_sp);
+        else
+            g_log = new Log(log_stream_sp);
     }
 
-    if (log)
+    if (g_log)
     {
         bool got_unknown_category = false;
         for (size_t i=0; categories[i] != NULL; ++i)
@@ -140,10 +143,11 @@ ProcessKDPLog::EnableLog (StreamSP &log_
         }
         if (flag_bits == 0)
             flag_bits = KDP_LOG_DEFAULT;
-        log->GetMask().Reset(flag_bits);
-        log->GetOptions().Reset(log_options);
+        g_log->GetMask().Reset(flag_bits);
+        g_log->GetOptions().Reset(log_options);
     }
-    return log;
+    g_log_enabled = true;
+    return g_log;
 }
 
 void
@@ -163,14 +167,15 @@ ProcessKDPLog::ListLogCategories (Stream
                   "  thread - log thread events and activities\n"
                   "  step - log step related activities\n"
                   "  verbose - enable verbose logging\n"
-                  "  watch - log watchpoint related activities\n", ProcessKDP::GetPluginNameStatic());
+                  "  watch - log watchpoint related activities\n",
+                  ProcessKDP::GetPluginNameStatic().GetCString());
 }
 
 
 void
 ProcessKDPLog::LogIf (uint32_t mask, const char *format, ...)
 {
-    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (mask));
+    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (mask));
     if (log)
     {
         va_list args;

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h Thu Jun  6 19:06:43 2013
@@ -35,13 +35,13 @@
 class ProcessKDPLog
 {
 public:
-    static lldb::LogSP
+    static lldb_private::Log *
     GetLogIfAllCategoriesSet(uint32_t mask = 0);
 
     static void
     DisableLog (const char **categories, lldb_private::Stream *feedback_strm);
 
-    static lldb::LogSP
+    static lldb_private::Log *
     EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, const char **categories, lldb_private::Stream *feedback_strm);
 
     static void

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp Thu Jun  6 19:06:43 2013
@@ -97,24 +97,64 @@ RegisterContextKDP_arm::DoReadDBG (lldb:
 int
 RegisterContextKDP_arm::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
 {
+    ProcessSP process_sp (CalculateProcess());
+    if (process_sp)
+    {
+        Error error;
+        if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, GPRRegSet, &gpr, sizeof(gpr), error))
+        {
+            if (error.Success())
+                return 0;
+        }
+    }
     return -1;
 }
 
 int
 RegisterContextKDP_arm::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
 {
+    ProcessSP process_sp (CalculateProcess());
+    if (process_sp)
+    {
+        Error error;
+        if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, FPURegSet, &fpu, sizeof(fpu), error))
+        {
+            if (error.Success())
+                return 0;
+        }
+    }
     return -1;
 }
 
 int
 RegisterContextKDP_arm::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
 {
+    ProcessSP process_sp (CalculateProcess());
+    if (process_sp)
+    {
+        Error error;
+        if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, EXCRegSet, &exc, sizeof(exc), error))
+        {
+            if (error.Success())
+                return 0;
+        }
+    }
     return -1;
 }
 
 int
 RegisterContextKDP_arm::DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg)
 {
+    ProcessSP process_sp (CalculateProcess());
+    if (process_sp)
+    {
+        Error error;
+        if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, DBGRegSet, &dbg, sizeof(dbg), error))
+        {
+            if (error.Success())
+                return 0;
+        }
+    }
     return -1;
 }
 

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp Thu Jun  6 19:06:43 2013
@@ -81,18 +81,48 @@ RegisterContextKDP_i386::DoReadEXC (lldb
 int
 RegisterContextKDP_i386::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
 {
+    ProcessSP process_sp (CalculateProcess());
+    if (process_sp)
+    {
+        Error error;
+        if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, GPRRegSet, &gpr, sizeof(gpr), error))
+        {
+            if (error.Success())
+                return 0;
+        }
+    }
     return -1;
 }
 
 int
 RegisterContextKDP_i386::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
 {
+    ProcessSP process_sp (CalculateProcess());
+    if (process_sp)
+    {
+        Error error;
+        if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, FPURegSet, &fpu, sizeof(fpu), error))
+        {
+            if (error.Success())
+                return 0;
+        }
+    }
     return -1;
 }
 
 int
 RegisterContextKDP_i386::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
 {
+    ProcessSP process_sp (CalculateProcess());
+    if (process_sp)
+    {
+        Error error;
+        if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, EXCRegSet, &exc, sizeof(exc), error))
+        {
+            if (error.Success())
+                return 0;
+        }
+    }
     return -1;
 }
 

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp Thu Jun  6 19:06:43 2013
@@ -33,35 +33,95 @@ RegisterContextKDP_x86_64::~RegisterCont
 int
 RegisterContextKDP_x86_64::DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
 {
+    ProcessSP process_sp (CalculateProcess());
+    if (process_sp)
+    {
+        Error error;
+        if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestReadRegisters (tid, GPRRegSet, &gpr, sizeof(gpr), error))
+        {
+            if (error.Success())
+                return 0;
+        }
+    }
     return -1;
 }
 
 int
 RegisterContextKDP_x86_64::DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
 {
+    ProcessSP process_sp (CalculateProcess());
+    if (process_sp)
+    {
+        Error error;
+        if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestReadRegisters (tid, FPURegSet, &fpu, sizeof(fpu), error))
+        {
+            if (error.Success())
+                return 0;
+        }
+    }
     return -1;
 }
 
 int
 RegisterContextKDP_x86_64::DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
 {
+    ProcessSP process_sp (CalculateProcess());
+    if (process_sp)
+    {
+        Error error;
+        if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestReadRegisters (tid, EXCRegSet, &exc, sizeof(exc), error))
+        {
+            if (error.Success())
+                return 0;
+        }
+    }
     return -1;
 }
 
 int
 RegisterContextKDP_x86_64::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
 {
+    ProcessSP process_sp (CalculateProcess());
+    if (process_sp)
+    {
+        Error error;
+        if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, GPRRegSet, &gpr, sizeof(gpr), error))
+        {
+            if (error.Success())
+                return 0;
+        }
+    }
     return -1;
 }
 
 int
 RegisterContextKDP_x86_64::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
 {
+    ProcessSP process_sp (CalculateProcess());
+    if (process_sp)
+    {
+        Error error;
+        if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, FPURegSet, &fpu, sizeof(fpu), error))
+        {
+            if (error.Success())
+                return 0;
+        }
+    }
     return -1;
 }
 
 int
 RegisterContextKDP_x86_64::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
 {
+    ProcessSP process_sp (CalculateProcess());
+    if (process_sp)
+    {
+        Error error;
+        if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, EXCRegSet, &exc, sizeof(exc), error))
+        {
+            if (error.Success())
+                return 0;
+        }
+    }
     return -1;
 }

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp Thu Jun  6 19:06:43 2013
@@ -28,6 +28,7 @@
 #include "RegisterContextKDP_arm.h"
 #include "RegisterContextKDP_i386.h"
 #include "RegisterContextKDP_x86_64.h"
+#include "Plugins/Process/Utility/StopInfoMachException.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -36,8 +37,8 @@ using namespace lldb_private;
 // Thread Registers
 //----------------------------------------------------------------------
 
-ThreadKDP::ThreadKDP (const lldb::ProcessSP &process_sp, lldb::tid_t tid) :
-    Thread(process_sp, tid),
+ThreadKDP::ThreadKDP (Process &process, lldb::tid_t tid) :
+    Thread(process, tid),
     m_thread_name (),
     m_dispatch_queue_name (),
     m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS)
@@ -65,37 +66,6 @@ ThreadKDP::GetQueueName ()
     return NULL;
 }
 
-bool
-ThreadKDP::WillResume (StateType resume_state)
-{
-    ClearStackFrames();
-    // Call the Thread::WillResume first. If we stop at a signal, the stop info
-    // class for signal will set the resume signal that we need below. The signal
-    // stuff obeys the Process::UnixSignal defaults. 
-    Thread::WillResume(resume_state);
-
-    lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
-    if (log)
-        log->Printf ("Resuming thread: %4.4llx with state: %s.", GetID(), StateAsCString(resume_state));
-
-//    ProcessKDP &process = GetKDPProcess();
-//    switch (resume_state)
-//    {
-//    case eStateSuspended:
-//    case eStateStopped:
-//        // Don't append anything for threads that should stay stopped.
-//        break;
-//
-//    case eStateRunning:
-//    case eStateStepping:
-//        break;
-//
-//    default:
-//        break;
-//    }
-    return true;
-}
-
 void
 ThreadKDP::RefreshStateAfterStop()
 {
@@ -108,19 +78,11 @@ ThreadKDP::RefreshStateAfterStop()
     // register supply functions where they check the process stop ID and do
     // the right thing.
     const bool force = false;
-    GetRegisterContext()->InvalidateIfNeeded (force);
+    lldb::RegisterContextSP reg_ctx_sp (GetRegisterContext());
+    if (reg_ctx_sp)
+        reg_ctx_sp->InvalidateIfNeeded (force);
 }
 
-void
-ThreadKDP::ClearStackFrames ()
-{
-    Unwind *unwinder = GetUnwinder ();
-    if (unwinder)
-        unwinder->Clear();
-    Thread::ClearStackFrames();
-}
-
-
 bool
 ThreadKDP::ThreadIDIsValid (lldb::tid_t thread)
 {
@@ -177,40 +139,69 @@ ThreadKDP::CreateRegisterContextForFrame
             }
         }
     }
-    else if (m_unwinder_ap.get())
-        reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame (frame);
+    else
+    {
+        Unwind *unwinder = GetUnwinder ();
+        if (unwinder)
+            reg_ctx_sp = unwinder->CreateRegisterContextForFrame (frame);
+    }
     return reg_ctx_sp;
 }
 
-lldb::StopInfoSP
-ThreadKDP::GetPrivateStopReason ()
+bool
+ThreadKDP::CalculateStopInfo ()
 {
     ProcessSP process_sp (GetProcess());
     if (process_sp)
     {
-        const uint32_t process_stop_id = process_sp->GetStopID();
-        if (m_thread_stop_reason_stop_id != process_stop_id ||
-            (m_actual_stop_info_sp && !m_actual_stop_info_sp->IsValid()))
+        if (m_cached_stop_info_sp)
+        {
+            SetStopInfo (m_cached_stop_info_sp);
+        }
+        else
         {
-            // TODO: can we query the initial state of the thread here?
-            // For now I am just going to pretend that a SIGSTOP happened.
-
             SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, SIGSTOP));
-
-            // If GetKDPProcess().SetThreadStopInfo() doesn't find a stop reason
-            // for this thread, then m_actual_stop_info_sp will not ever contain
-            // a valid stop reason and the "m_actual_stop_info_sp->IsValid() == false"
-            // check will never be able to tell us if we have the correct stop info
-            // for this thread and we will continually send qThreadStopInfo packets
-            // down to the remote KDP server, so we need to keep our own notion
-            // of the stop ID that m_actual_stop_info_sp is valid for (even if it
-            // contains nothing). We use m_thread_stop_reason_stop_id for this below.
-    //        m_thread_stop_reason_stop_id = process_stop_id;
-    //        m_actual_stop_info_sp.reset();
-
         }
+        return true;
     }
-    return m_actual_stop_info_sp;
+    return false;
 }
 
+void
+ThreadKDP::SetStopInfoFrom_KDP_EXCEPTION (const DataExtractor &exc_reply_packet)
+{
+    lldb::offset_t offset = 0;
+    uint8_t reply_command = exc_reply_packet.GetU8(&offset);
+    if (reply_command == CommunicationKDP::KDP_EXCEPTION)
+    {
+        offset = 8;
+        const uint32_t count = exc_reply_packet.GetU32 (&offset);
+        if (count >= 1)
+        {
+            //const uint32_t cpu = exc_reply_packet.GetU32 (&offset);
+            offset += 4; // Skip the useless CPU field
+            const uint32_t exc_type = exc_reply_packet.GetU32 (&offset);
+            const uint32_t exc_code = exc_reply_packet.GetU32 (&offset);
+            const uint32_t exc_subcode = exc_reply_packet.GetU32 (&offset);
+            // We have to make a copy of the stop info because the thread list
+            // will iterate through the threads and clear all stop infos..
+            
+            // Let the StopInfoMachException::CreateStopReasonWithMachException()
+            // function update the PC if needed as we might hit a software breakpoint
+            // and need to decrement the PC (i386 and x86_64 need this) and KDP
+            // doesn't do this for us.
+            const bool pc_already_adjusted = false;
+            const bool adjust_pc_if_needed = true;
+
+            m_cached_stop_info_sp = StopInfoMachException::CreateStopReasonWithMachException (*this,
+                                                                                              exc_type,
+                                                                                              2,
+                                                                                              exc_code,
+                                                                                              exc_subcode,
+                                                                                              0,
+                                                                                              pc_already_adjusted,
+                                                                                              adjust_pc_if_needed);            
+        }
+    }
+}
 

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h Thu Jun  6 19:06:43 2013
@@ -20,15 +20,12 @@ class ProcessKDP;
 class ThreadKDP : public lldb_private::Thread
 {
 public:
-    ThreadKDP (const lldb::ProcessSP &process_sp, 
+    ThreadKDP (lldb_private::Process &process,
                lldb::tid_t tid);
 
     virtual
     ~ThreadKDP ();
 
-    virtual bool
-    WillResume (lldb::StateType resume_state);
-
     virtual void
     RefreshStateAfterStop();
 
@@ -44,9 +41,6 @@ public:
     virtual lldb::RegisterContextSP
     CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
 
-    virtual void
-    ClearStackFrames ();
-
     void
     Dump (lldb_private::Log *log, uint32_t index);
 
@@ -79,6 +73,9 @@ public:
     {
         m_thread_dispatch_qaddr = thread_dispatch_qaddr;
     }
+    
+    void
+    SetStopInfoFrom_KDP_EXCEPTION (const lldb_private::DataExtractor &exc_reply_packet);
 
 protected:
     
@@ -90,14 +87,12 @@ protected:
     std::string m_thread_name;
     std::string m_dispatch_queue_name;
     lldb::addr_t m_thread_dispatch_qaddr;
+    lldb::StopInfoSP m_cached_stop_info_sp;
     //------------------------------------------------------------------
-    // Member variables.
+    // Protected member functions.
     //------------------------------------------------------------------
-
-    virtual lldb::StopInfoSP
-    GetPrivateStopReason ();
-
-
+    virtual bool
+    CalculateStopInfo ();
 };
 
 #endif  // liblldb_ThreadKDP_h_

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/Makefile?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/Makefile (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/Makefile Thu Jun  6 19:06:43 2013
@@ -18,6 +18,10 @@ CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEV
 
 ifeq ($(HOST_OS),Linux)
 CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/Linux
+
+# Disable warning for now as offsetof is used with an index into a structure member array
+# in defining register info tables.
+CPPFLAGS += -Wno-extended-offsetof
 endif
 
 ifeq ($(HOST_OS),FreeBSD)

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXStopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXStopInfo.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXStopInfo.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXStopInfo.cpp Thu Jun  6 19:06:43 2013
@@ -21,7 +21,7 @@ POSIXLimboStopInfo::~POSIXLimboStopInfo(
 lldb::StopReason
 POSIXLimboStopInfo::GetStopReason() const
 {
-    return lldb::eStopReasonTrace;
+    return lldb::eStopReasonThreadExiting;
 }
 
 const char *
@@ -33,13 +33,13 @@ POSIXLimboStopInfo::GetDescription()
 bool
 POSIXLimboStopInfo::ShouldStop(Event *event_ptr)
 {
-    return true;
+    return false;
 }
 
 bool
 POSIXLimboStopInfo::ShouldNotify(Event *event_ptr)
 {
-    return true;
+    return false;
 }
 
 //===----------------------------------------------------------------------===//
@@ -58,3 +58,32 @@ POSIXCrashStopInfo::GetDescription()
 {
     return ProcessMessage::GetCrashReasonString(m_crash_reason);
 }
+
+//===----------------------------------------------------------------------===//
+// POSIXNewThreadStopInfo
+
+POSIXNewThreadStopInfo::~POSIXNewThreadStopInfo() { }
+
+lldb::StopReason
+POSIXNewThreadStopInfo::GetStopReason() const
+{
+    return lldb::eStopReasonNone;
+}
+
+const char *
+POSIXNewThreadStopInfo::GetDescription()
+{
+    return "thread spawned";
+}
+
+bool
+POSIXNewThreadStopInfo::ShouldStop(Event *event_ptr)
+{
+    return false;
+}
+
+bool
+POSIXNewThreadStopInfo::ShouldNotify(Event *event_ptr)
+{
+    return false;
+}

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXStopInfo.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXStopInfo.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXStopInfo.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXStopInfo.h Thu Jun  6 19:06:43 2013
@@ -89,4 +89,32 @@ private:
     ProcessMessage::CrashReason m_crash_reason;
 };    
 
+//===----------------------------------------------------------------------===//
+/// @class POSIXNewThreadStopInfo
+/// @brief Represents the stop state of process when a new thread is spawned.
+///
+
+class POSIXNewThreadStopInfo
+    : public POSIXStopInfo
+{
+public:
+    POSIXNewThreadStopInfo (POSIXThread &thread)
+        : POSIXStopInfo (thread, 0)
+        { }
+
+    ~POSIXNewThreadStopInfo();
+
+    lldb::StopReason
+    GetStopReason() const;
+
+    const char *
+    GetDescription();
+
+    bool
+    ShouldStop(lldb_private::Event *event_ptr);
+
+    bool
+    ShouldNotify(lldb_private::Event *event_ptr);
+};
+
 #endif

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXThread.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXThread.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXThread.cpp Thu Jun  6 19:06:43 2013
@@ -7,13 +7,17 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "lldb/lldb-python.h"
+
 // C Includes
 #include <errno.h>
 
 // C++ Includes
 // Other libraries and framework includes
 // Project includes
+#include "lldb/Breakpoint/Watchpoint.h"
 #include "lldb/Core/Debugger.h"
+#include "lldb/Core/State.h"
 #include "lldb/Host/Host.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/StopInfo.h"
@@ -26,6 +30,8 @@
 #include "RegisterContext_i386.h"
 #include "RegisterContext_x86_64.h"
 #include "RegisterContextPOSIX.h"
+#include "RegisterContextLinux_x86_64.h"
+#include "RegisterContextFreeBSD_x86_64.h"
 
 #include "UnwindLLDB.h"
 
@@ -33,13 +39,27 @@ using namespace lldb;
 using namespace lldb_private;
 
 
-POSIXThread::POSIXThread(ProcessSP &process, lldb::tid_t tid)
+POSIXThread::POSIXThread(Process &process, lldb::tid_t tid)
     : Thread(process, tid),
-      m_frame_ap(0)
+      m_frame_ap()
 {
-    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
     if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
-        log->Printf ("POSIXThread::%s (tid = %i)", __FUNCTION__, tid);
+        log->Printf ("POSIXThread::%s (tid = %" PRIi64 ")", __FUNCTION__, tid);
+
+    // Set the current watchpoints for this thread.
+    Target &target = GetProcess()->GetTarget();
+    const WatchpointList &wp_list = target.GetWatchpointList();
+    size_t wp_size = wp_list.GetSize();
+
+    for (uint32_t wp_idx = 0; wp_idx < wp_size; wp_idx++)
+    {
+        lldb::WatchpointSP wp = wp_list.GetByIndex(wp_idx);
+        if (wp.get() && wp->IsEnabled())
+        {
+            assert(EnableHardwareWatchpoint(wp.get()));
+        }
+    }
 }
 
 POSIXThread::~POSIXThread()
@@ -58,15 +78,24 @@ POSIXThread::GetMonitor()
 void
 POSIXThread::RefreshStateAfterStop()
 {
-    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
-    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
-        log->Printf ("POSIXThread::%s ()", __FUNCTION__);
-
-    // Let all threads recover from stopping and do any clean up based
-    // on the previous thread state (if any).
-    ProcessSP base = GetProcess();
-    ProcessPOSIX &process = static_cast<ProcessPOSIX&>(*base);
-    process.GetThreadList().RefreshStateAfterStop();
+    // Invalidate all registers in our register context. We don't set "force" to
+    // true because the stop reply packet might have had some register values
+    // that were expedited and these will already be copied into the register
+    // context by the time this function gets called. The KDPRegisterContext
+    // class has been made smart enough to detect when it needs to invalidate
+    // which registers are valid by putting hooks in the register read and 
+    // register supply functions where they check the process stop ID and do
+    // the right thing.
+    //if (StateIsStoppedState(GetState())
+    {
+        const bool force = false;
+        GetRegisterContext()->InvalidateIfNeeded (force);
+    }
+    // FIXME: This should probably happen somewhere else.
+    SetResumeState(eStateRunning);
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+    if (log)
+        log->Printf ("POSIXThread::%s (tid = %" PRIi64 ") setting thread resume state to running", __FUNCTION__, GetID());
 }
 
 const char *
@@ -95,7 +124,14 @@ POSIXThread::GetRegisterContext()
             break;
 
         case ArchSpec::eCore_x86_64_x86_64:
-            m_reg_context_sp.reset(new RegisterContext_x86_64(*this, 0));
+// TODO: Use target OS/architecture detection rather than ifdefs so that
+// lldb built on FreeBSD can debug on Linux and vice-versa.
+#ifdef __linux__
+            m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0));
+#endif
+#ifdef __FreeBSD__
+            m_reg_context_sp.reset(new RegisterContextFreeBSD_x86_64(*this, 0));
+#endif
             break;
         }
     }
@@ -108,7 +144,7 @@ POSIXThread::CreateRegisterContextForFra
     lldb::RegisterContextSP reg_ctx_sp;
     uint32_t concrete_frame_idx = 0;
 
-    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
     if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
         log->Printf ("POSIXThread::%s ()", __FUNCTION__);
 
@@ -126,10 +162,11 @@ POSIXThread::CreateRegisterContextForFra
     return reg_ctx_sp;
 }
 
-lldb::StopInfoSP
-POSIXThread::GetPrivateStopReason()
+bool
+POSIXThread::CalculateStopInfo()
 {
-    return m_stop_info;
+    SetStopInfo (m_stop_info_sp);
+    return true;
 }
 
 Unwind *
@@ -141,16 +178,21 @@ POSIXThread::GetUnwinder()
     return m_unwinder_ap.get();
 }
 
-bool
+void
 POSIXThread::WillResume(lldb::StateType resume_state)
 {
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+    if (log)
+        log->Printf ("POSIXThread::%s (tid = %" PRIi64 ") setting thread resume state to %s", __FUNCTION__, GetID(), StateAsCString(resume_state));
+    // TODO: the line below shouldn't really be done, but
+    // the POSIXThread might rely on this so I will leave this in for now
     SetResumeState(resume_state);
+}
 
-    ClearStackFrames();
-    if (m_unwinder_ap.get())
-        m_unwinder_ap->Clear();
-
-    return Thread::WillResume(resume_state);
+void
+POSIXThread::DidStop()
+{
+    // Don't set the thread state to stopped unless we really stopped.
 }
 
 bool
@@ -160,9 +202,10 @@ POSIXThread::Resume()
     ProcessMonitor &monitor = GetMonitor();
     bool status;
 
-    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
-    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
-        log->Printf ("POSIXThread::%s ()", __FUNCTION__);
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+    if (log)
+        log->Printf ("POSIXThread::%s (), resume_state = %s", __FUNCTION__,
+                         StateAsCString(resume_state));
 
     switch (resume_state)
     {
@@ -180,6 +223,10 @@ POSIXThread::Resume()
         SetState(resume_state);
         status = monitor.SingleStep(GetID(), GetResumeSignal());
         break;
+    case lldb::eStateStopped:
+    case lldb::eStateSuspended:
+        status = true;
+        break;
     }
 
     return status;
@@ -188,7 +235,7 @@ POSIXThread::Resume()
 void
 POSIXThread::Notify(const ProcessMessage &message)
 {
-    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
     if (log)
         log->Printf ("POSIXThread::%s () message kind = '%s'", __FUNCTION__, message.PrintKind());
 
@@ -198,10 +245,14 @@ POSIXThread::Notify(const ProcessMessage
         assert(false && "Unexpected message kind!");
         break;
 
+    case ProcessMessage::eExitMessage:
+        // Nothing to be done.
+        break;
+
     case ProcessMessage::eLimboMessage:
         LimboNotify(message);
         break;
-        
+
     case ProcessMessage::eSignalMessage:
         SignalNotify(message);
         break;
@@ -218,17 +269,88 @@ POSIXThread::Notify(const ProcessMessage
         BreakNotify(message);
         break;
 
+    case ProcessMessage::eWatchpointMessage:
+        WatchNotify(message);
+        break;
+
     case ProcessMessage::eCrashMessage:
         CrashNotify(message);
         break;
+
+    case ProcessMessage::eNewThreadMessage:
+        ThreadNotify(message);
+        break;
+    }
+}
+
+bool
+POSIXThread::EnableHardwareWatchpoint(Watchpoint *wp)
+{
+    bool wp_set = false;
+    if (wp)
+    {
+        addr_t wp_addr = wp->GetLoadAddress();
+        size_t wp_size = wp->GetByteSize();
+        bool wp_read = wp->WatchpointRead();
+        bool wp_write = wp->WatchpointWrite();
+        uint32_t wp_hw_index = wp->GetHardwareIndex();
+        RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX();
+        if (reg_ctx)
+            wp_set = reg_ctx->SetHardwareWatchpointWithIndex(wp_addr, wp_size,
+                                                             wp_read, wp_write,
+                                                             wp_hw_index);
+    }
+    return wp_set;
+}
+
+bool
+POSIXThread::DisableHardwareWatchpoint(Watchpoint *wp)
+{
+    bool result = false;
+    if (wp)
+    {
+        lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
+        if (reg_ctx_sp.get())
+            result = reg_ctx_sp->ClearHardwareWatchpoint(wp->GetHardwareIndex());
     }
+    return result;
+}
+
+uint32_t
+POSIXThread::NumSupportedHardwareWatchpoints()
+{
+    lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
+    if (reg_ctx_sp.get())
+        return reg_ctx_sp->NumSupportedHardwareWatchpoints();
+    return 0;
+}
+
+uint32_t
+POSIXThread::FindVacantWatchpointIndex()
+{
+    uint32_t hw_index = LLDB_INVALID_INDEX32;
+    uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
+    uint32_t wp_idx;
+    RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX();
+    if (reg_ctx)
+    {
+        for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
+        {
+            if (reg_ctx->IsWatchpointVacant(wp_idx))
+            {
+                hw_index = wp_idx;
+                break;
+            }
+        }
+    }
+    return hw_index;
 }
 
 void
 POSIXThread::BreakNotify(const ProcessMessage &message)
 {
     bool status;
-    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
 
     assert(GetRegisterContext());
     status = GetRegisterContextPOSIX()->UpdateAfterBreakpoint();
@@ -239,27 +361,82 @@ POSIXThread::BreakNotify(const ProcessMe
     assert(GetRegisterContext());
     lldb::addr_t pc = GetRegisterContext()->GetPC();
     if (log)
-        log->Printf ("POSIXThread::%s () PC=0x%8.8llx", __FUNCTION__, pc);
+        log->Printf ("POSIXThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc);
     lldb::BreakpointSiteSP bp_site(GetProcess()->GetBreakpointSiteList().FindByAddress(pc));
     assert(bp_site);
     lldb::break_id_t bp_id = bp_site->GetID();
     assert(bp_site && bp_site->ValidForThisThread(this));
 
-    
+    // Make this thread the selected thread
+    GetProcess()->GetThreadList().SetSelectedThreadByID(GetID());
+
     m_breakpoint = bp_site;
-    m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id);
+    SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id));
+}
+
+void
+POSIXThread::WatchNotify(const ProcessMessage &message)
+{
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+
+    lldb::addr_t halt_addr = message.GetHWAddress();
+    if (log)
+        log->Printf ("POSIXThread::%s () Hardware Watchpoint Address = 0x%8.8"
+                     PRIx64, __FUNCTION__, halt_addr);
+
+    RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX();
+    if (reg_ctx)
+    {
+        uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
+        uint32_t wp_idx;
+        for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
+        {
+            if (reg_ctx->IsWatchpointHit(wp_idx))
+            {
+                // Clear the watchpoint hit here
+                reg_ctx->ClearWatchpointHits();
+                break;
+            }
+        }
+
+        if (wp_idx == num_hw_wps)
+            return;
+
+        Target &target = GetProcess()->GetTarget();
+        lldb::addr_t wp_monitor_addr = reg_ctx->GetWatchpointAddress(wp_idx);
+        const WatchpointList &wp_list = target.GetWatchpointList();
+        lldb::WatchpointSP wp_sp = wp_list.FindByAddress(wp_monitor_addr);
+
+        if (wp_sp)
+            SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID(*this,
+                                                                    wp_sp->GetID()));
+    }
 }
 
 void
 POSIXThread::TraceNotify(const ProcessMessage &message)
 {
-    m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
+    RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX();
+    if (reg_ctx)
+    {
+        uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
+        uint32_t wp_idx;
+        for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
+        {
+            if (reg_ctx->IsWatchpointHit(wp_idx))
+            {
+                WatchNotify(message);
+                return;
+            }
+        }
+    }
+    SetStopInfo (StopInfo::CreateStopReasonToTrace(*this));
 }
 
 void
 POSIXThread::LimboNotify(const ProcessMessage &message)
 {
-    m_stop_info = lldb::StopInfoSP(new POSIXLimboStopInfo(*this));
+    SetStopInfo (lldb::StopInfoSP(new POSIXLimboStopInfo(*this)));
 }
 
 void
@@ -267,7 +444,7 @@ POSIXThread::SignalNotify(const ProcessM
 {
     int signo = message.GetSignal();
 
-    m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, signo);
+    SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo));
     SetResumeSignal(signo);
 }
 
@@ -276,27 +453,32 @@ POSIXThread::SignalDeliveredNotify(const
 {
     int signo = message.GetSignal();
 
-    // Just treat debugger generated signal events like breakpoints for now.
-    m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
+    SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo));
     SetResumeSignal(signo);
 }
 
 void
 POSIXThread::CrashNotify(const ProcessMessage &message)
 {
+    // FIXME: Update stop reason as per bugzilla 14598
     int signo = message.GetSignal();
 
     assert(message.GetKind() == ProcessMessage::eCrashMessage);
 
-    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
     if (log)
         log->Printf ("POSIXThread::%s () signo = %i, reason = '%s'", __FUNCTION__, signo, message.PrintCrashReason());
 
-    m_stop_info = lldb::StopInfoSP(new POSIXCrashStopInfo(
-                                       *this, signo, message.GetCrashReason()));
+    SetStopInfo (lldb::StopInfoSP(new POSIXCrashStopInfo(*this, signo, message.GetCrashReason())));
     SetResumeSignal(signo);
 }
 
+void
+POSIXThread::ThreadNotify(const ProcessMessage &message)
+{
+    SetStopInfo (lldb::StopInfoSP(new POSIXNewThreadStopInfo(*this)));
+}
+
 unsigned
 POSIXThread::GetRegisterIndexFromOffset(unsigned offset)
 {
@@ -312,11 +494,14 @@ POSIXThread::GetRegisterIndexFromOffset(
     case ArchSpec::eCore_x86_32_i386:
     case ArchSpec::eCore_x86_32_i486:
     case ArchSpec::eCore_x86_32_i486sx:
-        reg = RegisterContext_i386::GetRegisterIndexFromOffset(offset);
-        break;
-
     case ArchSpec::eCore_x86_64_x86_64:
-        reg = RegisterContext_x86_64::GetRegisterIndexFromOffset(offset);
+        {
+            RegisterContextSP base = GetRegisterContext();
+            if (base) {
+                RegisterContextPOSIX &context = static_cast<RegisterContextPOSIX &>(*base);
+                reg = context.GetRegisterIndexFromOffset(offset);
+            }
+        }
         break;
     }
     return reg;
@@ -325,7 +510,7 @@ POSIXThread::GetRegisterIndexFromOffset(
 const char *
 POSIXThread::GetRegisterName(unsigned reg)
 {
-    const char * name;
+    const char * name = nullptr;
     ArchSpec arch = Host::GetArchitecture();
 
     switch (arch.GetCore())
@@ -337,11 +522,8 @@ POSIXThread::GetRegisterName(unsigned re
     case ArchSpec::eCore_x86_32_i386:
     case ArchSpec::eCore_x86_32_i486:
     case ArchSpec::eCore_x86_32_i486sx:
-        name = RegisterContext_i386::GetRegisterName(reg);
-        break;
-
     case ArchSpec::eCore_x86_64_x86_64:
-        name = RegisterContext_x86_64::GetRegisterName(reg);
+        name = GetRegisterContext()->GetRegisterName(reg);
         break;
     }
     return name;

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXThread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXThread.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXThread.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXThread.h Thu Jun  6 19:06:43 2013
@@ -29,16 +29,20 @@ class POSIXThread
     : public lldb_private::Thread
 {
 public:
-    POSIXThread(lldb::ProcessSP &process, lldb::tid_t tid);
+    POSIXThread(lldb_private::Process &process, lldb::tid_t tid);
 
     virtual ~POSIXThread();
 
     void
     RefreshStateAfterStop();
 
-    bool
+    virtual void
     WillResume(lldb::StateType resume_state);
 
+    // This notifies the thread when a private stop occurs.
+    virtual void
+    DidStop ();
+
     const char *
     GetInfo();
 
@@ -49,17 +53,17 @@ public:
     CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
 
     //--------------------------------------------------------------------------
-    // These static functions provide a mapping from the register offset
+    // These functions provide a mapping from the register offset
     // back to the register index or name for use in debugging or log
     // output.
 
-    static unsigned
+    unsigned
     GetRegisterIndexFromOffset(unsigned offset);
 
-    static const char *
+    const char *
     GetRegisterName(unsigned reg);
 
-    static const char *
+    const char *
     GetRegisterNameFromOffset(unsigned offset);
 
     //--------------------------------------------------------------------------
@@ -69,6 +73,17 @@ public:
 
     void Notify(const ProcessMessage &message);
 
+    //--------------------------------------------------------------------------
+    // These methods provide an interface to watchpoints
+    //
+    bool EnableHardwareWatchpoint(lldb_private::Watchpoint *wp);
+
+    bool DisableHardwareWatchpoint(lldb_private::Watchpoint *wp);
+
+    uint32_t NumSupportedHardwareWatchpoints();
+
+    uint32_t FindVacantWatchpointIndex();
+
 private:
     RegisterContextPOSIX *
     GetRegisterContextPOSIX ()
@@ -81,23 +96,25 @@ private:
         return (RegisterContextPOSIX *)m_reg_context_sp.get();
     }
     
-    std::auto_ptr<lldb_private::StackFrame> m_frame_ap;
+    std::unique_ptr<lldb_private::StackFrame> m_frame_ap;
 
     lldb::BreakpointSiteSP m_breakpoint;
-    lldb::StopInfoSP m_stop_info;
 
     ProcessMonitor &
     GetMonitor();
 
-    lldb::StopInfoSP
-    GetPrivateStopReason();
+    virtual bool
+    CalculateStopInfo();
 
     void BreakNotify(const ProcessMessage &message);
+    void WatchNotify(const ProcessMessage &message);
     void TraceNotify(const ProcessMessage &message);
     void LimboNotify(const ProcessMessage &message);
     void SignalNotify(const ProcessMessage &message);
     void SignalDeliveredNotify(const ProcessMessage &message);
     void CrashNotify(const ProcessMessage &message);
+    void ThreadNotify(const ProcessMessage &message);
+    void ExitNotify(const ProcessMessage &message);
 
     lldb_private::Unwind *
     GetUnwinder();

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessMessage.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessMessage.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessMessage.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessMessage.cpp Thu Jun  6 19:06:43 2013
@@ -102,10 +102,6 @@ ProcessMessage::PrintCrashReason(CrashRe
 
     switch (reason)
     {
-    default:
-        assert(false && "invalid CrashReason");
-        break;
-
         case eInvalidCrashReason:
             str = "eInvalidCrashReason";
             break;
@@ -204,10 +200,6 @@ ProcessMessage::PrintKind(Kind kind)
 
     switch (kind)
     {
-    default:
-        assert(false && "invalid Kind");
-        break;
-
     case eInvalidMessage:
         str = "eInvalidMessage";
         break;
@@ -229,9 +221,15 @@ ProcessMessage::PrintKind(Kind kind)
     case eBreakpointMessage:
         str = "eBreakpointMessage";
         break;
+    case eWatchpointMessage:
+        str = "eWatchpointMessage";
+        break;
     case eCrashMessage:
         str = "eCrashMessage";
         break;
+    case eNewThreadMessage:
+        str = "eNewThreadMessage";
+        break;
     }
 #endif
 

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessMessage.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessMessage.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessMessage.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessMessage.h Thu Jun  6 19:06:43 2013
@@ -29,7 +29,9 @@ public:
         eSignalDeliveredMessage,
         eTraceMessage,
         eBreakpointMessage,
-        eCrashMessage
+        eWatchpointMessage,
+        eCrashMessage,
+        eNewThreadMessage
     };
 
     enum CrashReason
@@ -103,6 +105,10 @@ public:
         return ProcessMessage(tid, eBreakpointMessage);
     }
 
+    static ProcessMessage Watch(lldb::tid_t tid, lldb::addr_t wp_addr) {
+        return ProcessMessage(tid, eWatchpointMessage, 0, wp_addr);
+    }
+
     /// Indicates that the thread @p tid crashed.
     static ProcessMessage Crash(lldb::pid_t pid, CrashReason reason,
                                 int signo, lldb::addr_t fault_addr) {
@@ -111,6 +117,16 @@ public:
         return message;
     }
 
+    /// Indicates that the thread @p child_tid was spawned.
+    static ProcessMessage NewThread(lldb::tid_t parent_tid, lldb::tid_t child_tid) {
+        return ProcessMessage(parent_tid, eNewThreadMessage, child_tid);
+    }
+
+    /// Indicates that the thread @p tid is about to exit with status @p status.
+    static ProcessMessage Exit(lldb::tid_t tid, int status) {
+        return ProcessMessage(tid, eExitMessage, status);
+    }
+
     int GetExitStatus() const {
         assert(GetKind() == eExitMessage || GetKind() == eLimboMessage);
         return m_status;
@@ -137,6 +153,16 @@ public:
         return m_addr;
     }
 
+    lldb::addr_t GetHWAddress() const {
+        assert(GetKind() == eWatchpointMessage || GetKind() == eTraceMessage);
+        return m_addr;
+    }
+
+    lldb::tid_t GetChildTID() const {
+        assert(GetKind() == eNewThreadMessage);
+        return m_child_tid;
+    }
+
     static const char *
     GetCrashReasonString(CrashReason reason);
 
@@ -159,13 +185,23 @@ private:
           m_kind(kind),
           m_crash_reason(eInvalidCrashReason),
           m_status(status),
-          m_addr(addr) { }
+          m_addr(addr),
+          m_child_tid(0) { }
+
+    ProcessMessage(lldb::tid_t tid, Kind kind, lldb::tid_t child_tid)
+        : m_tid(tid),
+          m_kind(kind),
+          m_crash_reason(eInvalidCrashReason),
+          m_status(0),
+          m_addr(0),
+          m_child_tid(child_tid) { }
 
     lldb::tid_t m_tid;
     Kind        m_kind         : 8;
     CrashReason m_crash_reason : 8;
     int m_status;
     lldb::addr_t m_addr;
+    lldb::tid_t m_child_tid;
 };
 
 #endif // #ifndef liblldb_ProcessMessage_H_

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.cpp Thu Jun  6 19:06:43 2013
@@ -7,16 +7,22 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "lldb/lldb-python.h"
+
 // C Includes
 #include <errno.h>
 
 // C++ Includes
 // Other libraries and framework includes
+#include "lldb/Breakpoint/Watchpoint.h"
+#include "lldb/Core/Module.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/State.h"
+#include "lldb/Host/FileSpec.h"
 #include "lldb/Host/Host.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/Platform.h"
 #include "lldb/Target/Target.h"
 
 #include "ProcessPOSIX.h"
@@ -69,6 +75,7 @@ ProcessPOSIX::ProcessPOSIX(Target& targe
       m_byte_order(lldb::endian::InlHostByteOrder()),
       m_monitor(NULL),
       m_module(NULL),
+      m_message_mutex (Mutex::eMutexTypeRecursive),
       m_in_limbo(false),
       m_exit_now(false)
 {
@@ -94,7 +101,8 @@ ProcessPOSIX::CanDebug(Target &target, b
     ModuleSP exe_module_sp(target.GetExecutableModule());
     if (exe_module_sp.get())
         return exe_module_sp->GetFileSpec().Exists();
-    return false;
+    // If there is no executable module, we return true since we might be preparing to attach.
+    return true;
 }
 
 Error
@@ -103,20 +111,57 @@ ProcessPOSIX::DoAttachToProcessWithID(ll
     Error error;
     assert(m_monitor == NULL);
 
-    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
     if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
-        log->Printf ("ProcessPOSIX::%s(pid = %i)", __FUNCTION__, GetID());
+        log->Printf ("ProcessPOSIX::%s(pid = %" PRIi64 ")", __FUNCTION__, GetID());
 
     m_monitor = new ProcessMonitor(this, pid, error);
 
     if (!error.Success())
         return error;
 
+    PlatformSP platform_sp (m_target.GetPlatform ());
+    assert (platform_sp.get());
+    if (!platform_sp)
+        return error;  // FIXME: Detatch?
+
+    // Find out what we can about this process
+    ProcessInstanceInfo process_info;
+    platform_sp->GetProcessInfo (pid, process_info);
+
+    // Resolve the executable module
+    ModuleSP exe_module_sp;
+    FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
+    error = platform_sp->ResolveExecutable(process_info.GetExecutableFile(),
+                                           m_target.GetArchitecture(),
+                                           exe_module_sp,
+                                           executable_search_paths.GetSize() ? &executable_search_paths : NULL);
+
+    // Fix the target architecture if necessary
+    const ArchSpec &module_arch = exe_module_sp->GetArchitecture();
+    if (module_arch.IsValid() && !m_target.GetArchitecture().IsExactMatch(module_arch))
+        m_target.SetArchitecture(module_arch);
+
+    // Initialize the target module list
+    m_target.SetExecutableModule (exe_module_sp, true);
+
+    if (!error.Success())
+        return error;
+
+    SetSTDIOFileDescriptor(m_monitor->GetTerminalFD());
+
     SetID(pid);
+
     return error;
 }
 
 Error
+ProcessPOSIX::DoAttachToProcessWithID (lldb::pid_t pid,  const ProcessAttachInfo &attach_info)
+{
+    return DoAttachToProcessWithID(pid);
+}
+
+Error
 ProcessPOSIX::WillLaunch(Module* module)
 {
     Error error;
@@ -153,6 +198,16 @@ ProcessPOSIX::DoLaunch (Module *module,
     Error error;
     assert(m_monitor == NULL);
 
+    const char* working_dir = launch_info.GetWorkingDirectory();
+    if (working_dir) {
+      FileSpec WorkingDir(working_dir, true);
+      if (!WorkingDir || WorkingDir.GetFileType() != FileSpec::eFileTypeDirectory)
+      {
+          error.SetErrorStringWithFormat("No such file or directory: %s", working_dir);
+          return error;
+      }
+    }
+
     SetPrivateState(eStateLaunching);
 
     const lldb_private::ProcessLaunchInfo::FileAction *file_action;
@@ -161,7 +216,7 @@ ProcessPOSIX::DoLaunch (Module *module,
     const char *stdin_path = NULL;
     const char *stdout_path = NULL;
     const char *stderr_path = NULL;
-    
+
     file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
     stdin_path = GetFilePath(file_action, stdin_path);
 
@@ -178,6 +233,7 @@ ProcessPOSIX::DoLaunch (Module *module,
                                     stdin_path, 
                                     stdout_path, 
                                     stderr_path,
+                                    working_dir,
                                     error);
 
     m_module = module;
@@ -185,6 +241,8 @@ ProcessPOSIX::DoLaunch (Module *module,
     if (!error.Success())
         return error;
 
+    SetSTDIOFileDescriptor(m_monitor->GetTerminalFD());
+
     SetID(m_monitor->GetPID());
     return error;
 }
@@ -256,16 +314,29 @@ ProcessPOSIX::DoHalt(bool &caused_stop)
     {
         caused_stop = true;
     }
-
     return error;
 }
 
 Error
-ProcessPOSIX::DoDetach()
+ProcessPOSIX::DoDetach(bool keep_stopped)
 {
     Error error;
+    if (keep_stopped)
+    {
+        // FIXME: If you want to implement keep_stopped on Linux,
+        // this would be the place to do it.
+        error.SetErrorString("Detaching with keep_stopped true is not currently supported on Linux.");
+        return error;
+    }
+
+    uint32_t thread_count = m_thread_list.GetSize(false);
+    for (uint32_t i = 0; i < thread_count; ++i)
+    {
+        POSIXThread *thread = static_cast<POSIXThread*>(
+            m_thread_list.GetThreadAtIndex(i, false).get());
+        error = m_monitor->Detach(thread->GetID());
+    }
 
-    error = m_monitor->Detach();
     if (error.Success())
         SetPrivateState(eStateDetached);
 
@@ -311,83 +382,147 @@ ProcessPOSIX::SendMessage(const ProcessM
 {
     Mutex::Locker lock(m_message_mutex);
 
+    POSIXThread *thread = static_cast<POSIXThread*>(
+        m_thread_list.FindThreadByID(message.GetTID(), false).get());
+
     switch (message.GetKind())
     {
-    default:
-        assert(false && "Unexpected process message!");
-        break;
-
     case ProcessMessage::eInvalidMessage:
         return;
 
     case ProcessMessage::eLimboMessage:
-        m_in_limbo = true;
-        m_exit_status = message.GetExitStatus();
-        if (m_exit_now)
+        assert(thread);
+        thread->SetState(eStateStopped);
+        if (message.GetTID() == GetID())
         {
-            SetPrivateState(eStateExited);
-            m_monitor->Detach();
+            m_in_limbo = true;
+            m_exit_status = message.GetExitStatus();
+            if (m_exit_now)
+            {
+                SetPrivateState(eStateExited);
+                m_monitor->Detach(GetID());
+            }
+            else
+            {
+                StopAllThreads(message.GetTID());
+                SetPrivateState(eStateStopped);
+            }
         }
         else
+        {
+            StopAllThreads(message.GetTID());
             SetPrivateState(eStateStopped);
+        }
         break;
 
     case ProcessMessage::eExitMessage:
-        m_exit_status = message.GetExitStatus();
-        SetExitStatus(m_exit_status, NULL);
+        assert(thread);
+        thread->SetState(eStateExited);
+        // FIXME: I'm not sure we need to do this.
+        if (message.GetTID() == GetID())
+        {
+            m_exit_status = message.GetExitStatus();
+            SetExitStatus(m_exit_status, NULL);
+        }
         break;
 
-    case ProcessMessage::eTraceMessage:
     case ProcessMessage::eBreakpointMessage:
+    case ProcessMessage::eTraceMessage:
+    case ProcessMessage::eWatchpointMessage:
+    case ProcessMessage::eNewThreadMessage:
+    case ProcessMessage::eCrashMessage:
+        assert(thread);
+        thread->SetState(eStateStopped);
+        StopAllThreads(message.GetTID());
         SetPrivateState(eStateStopped);
         break;
 
     case ProcessMessage::eSignalMessage:
     case ProcessMessage::eSignalDeliveredMessage:
-        SetPrivateState(eStateStopped);
-        break;
+    {
+        lldb::tid_t tid = message.GetTID();
+        lldb::tid_t pid = GetID();
+        if (tid == pid) {
+            assert(thread);
+            thread->SetState(eStateStopped);
+            StopAllThreads(message.GetTID());
+            SetPrivateState(eStateStopped);
+            break;
+        } else {
+            // FIXME: Ignore any signals generated by children.
+            return;
+        }
+    }
 
-    case ProcessMessage::eCrashMessage:
-        SetPrivateState(eStateCrashed);
-        break;
     }
 
     m_message_queue.push(message);
 }
 
+void 
+ProcessPOSIX::StopAllThreads(lldb::tid_t stop_tid)
+{
+    // FIXME: Will this work the same way on FreeBSD and Linux?
+}
+
 void
 ProcessPOSIX::RefreshStateAfterStop()
 {
-    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
     if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
-        log->Printf ("ProcessPOSIX::%s()", __FUNCTION__);
+        log->Printf ("ProcessPOSIX::%s(), message_queue size = %d", __FUNCTION__, (int)m_message_queue.size());
 
     Mutex::Locker lock(m_message_mutex);
-    if (m_message_queue.empty())
-        return;
 
-    ProcessMessage &message = m_message_queue.front();
+    // This method used to only handle one message.  Changing it to loop allows
+    // it to handle the case where we hit a breakpoint while handling a different
+    // breakpoint.
+    while (!m_message_queue.empty())
+    {
+        ProcessMessage &message = m_message_queue.front();
+
+        // Resolve the thread this message corresponds to and pass it along.
+        lldb::tid_t tid = message.GetTID();
+        if (log)
+            log->Printf ("ProcessPOSIX::%s(), message_queue size = %d, pid = %" PRIi64, __FUNCTION__, (int)m_message_queue.size(), tid);
+        POSIXThread *thread = static_cast<POSIXThread*>(
+            GetThreadList().FindThreadByID(tid, false).get());
 
-    // Resolve the thread this message corresponds to and pass it along.
-    // FIXME: we're really dealing with the pid here.  This should get
-    // fixed when this code is fixed to handle multiple threads.
-    lldb::tid_t tid = message.GetTID();
-    if (log)
-        log->Printf ("ProcessPOSIX::%s() pid = %i", __FUNCTION__, tid);
-    POSIXThread *thread = static_cast<POSIXThread*>(
-        GetThreadList().FindThreadByID(tid, false).get());
+        if (message.GetKind() == ProcessMessage::eNewThreadMessage)
+        {
+            if (log)
+                log->Printf ("ProcessPOSIX::%s() adding thread, tid = %" PRIi64, __FUNCTION__, message.GetChildTID());
+            ThreadSP thread_sp;
+            thread_sp.reset(new POSIXThread(*this, message.GetChildTID()));
+            m_thread_list.AddThread(thread_sp);
+        }
+
+        m_thread_list.RefreshStateAfterStop();
+
+        if (thread)
+            thread->Notify(message);
 
-    assert(thread);
-    thread->Notify(message);
+        if (message.GetKind() == ProcessMessage::eExitMessage)
+        {
+            // FIXME: We should tell the user about this, but the limbo message is probably better for that.
+            if (log)
+                log->Printf ("ProcessPOSIX::%s() removing thread, tid = %" PRIi64, __FUNCTION__, tid);
+            ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false);
+            thread_sp.reset();
+        }
 
-    m_message_queue.pop();
+        m_message_queue.pop();
+    }
 }
 
 bool
 ProcessPOSIX::IsAlive()
 {
     StateType state = GetPrivateState();
-    return state != eStateDetached && state != eStateExited && state != eStateInvalid;
+    return state != eStateDetached
+        && state != eStateExited
+        && state != eStateInvalid
+        && state != eStateUnloaded;
 }
 
 size_t
@@ -441,11 +576,25 @@ ProcessPOSIX::DoDeallocateMemory(lldb::a
         InferiorCallMunmap(this, addr, pos->second))
         m_addr_to_mmap_size.erase (pos);
     else
-        error.SetErrorStringWithFormat("unable to deallocate memory at 0x%llx", addr);
+        error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr);
 
     return error;
 }
 
+addr_t
+ProcessPOSIX::ResolveIndirectFunction(const Address *address, Error &error)
+{
+    addr_t function_addr = LLDB_INVALID_ADDRESS;
+    if (address == NULL) {
+        error.SetErrorStringWithFormat("unable to determine direct function call for NULL address");
+    } else if (!InferiorCall(this, address, function_addr)) {
+        function_addr = LLDB_INVALID_ADDRESS;
+        error.SetErrorStringWithFormat("unable to determine direct function call for indirect function %s",
+                                       address->CalculateSymbolContextSymbol()->GetName().AsCString());
+    }
+    return function_addr;
+}
+
 size_t
 ProcessPOSIX::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)
 {
@@ -473,23 +622,170 @@ ProcessPOSIX::GetSoftwareBreakpointTrapO
 }
 
 Error
-ProcessPOSIX::EnableBreakpoint(BreakpointSite *bp_site)
+ProcessPOSIX::EnableBreakpointSite(BreakpointSite *bp_site)
 {
     return EnableSoftwareBreakpoint(bp_site);
 }
 
 Error
-ProcessPOSIX::DisableBreakpoint(BreakpointSite *bp_site)
+ProcessPOSIX::DisableBreakpointSite(BreakpointSite *bp_site)
 {
     return DisableSoftwareBreakpoint(bp_site);
 }
 
+Error
+ProcessPOSIX::EnableWatchpoint(Watchpoint *wp, bool notify)
+{
+    Error error;
+    if (wp)
+    {
+        user_id_t watchID = wp->GetID();
+        addr_t addr = wp->GetLoadAddress();
+        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+        if (log)
+            log->Printf ("ProcessPOSIX::EnableWatchpoint(watchID = %" PRIu64 ")",
+                         watchID);
+        if (wp->IsEnabled())
+        {
+            if (log)
+                log->Printf("ProcessPOSIX::EnableWatchpoint(watchID = %" PRIu64
+                            ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.",
+                            watchID, (uint64_t)addr);
+            return error;
+        }
+
+        // Try to find a vacant watchpoint slot in the inferiors' main thread
+        uint32_t wp_hw_index = LLDB_INVALID_INDEX32;
+        POSIXThread *thread = static_cast<POSIXThread*>(
+                               m_thread_list.GetThreadAtIndex(0, false).get());
+
+        if (thread)
+            wp_hw_index = thread->FindVacantWatchpointIndex();
+
+        if (wp_hw_index == LLDB_INVALID_INDEX32)
+        {
+            error.SetErrorString("Setting hardware watchpoint failed.");
+        }
+        else
+        {
+            wp->SetHardwareIndex(wp_hw_index);
+            bool wp_enabled = true;
+            uint32_t thread_count = m_thread_list.GetSize(false);
+            for (uint32_t i = 0; i < thread_count; ++i)
+            {
+                thread = static_cast<POSIXThread*>(
+                         m_thread_list.GetThreadAtIndex(i, false).get());
+                if (thread)
+                    wp_enabled &= thread->EnableHardwareWatchpoint(wp);
+                else
+                    wp_enabled = false;
+            }
+            if (wp_enabled)
+            {
+                wp->SetEnabled(true, notify);
+                return error;
+            }
+            else
+            {
+                // Watchpoint enabling failed on at least one
+                // of the threads so roll back all of them
+                DisableWatchpoint(wp, false);
+                error.SetErrorString("Setting hardware watchpoint failed");
+            }
+        }
+    }
+    else
+        error.SetErrorString("Watchpoint argument was NULL.");
+    return error;
+}
+
+Error
+ProcessPOSIX::DisableWatchpoint(Watchpoint *wp, bool notify)
+{
+    Error error;
+    if (wp)
+    {
+        user_id_t watchID = wp->GetID();
+        addr_t addr = wp->GetLoadAddress();
+        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+        if (log)
+            log->Printf("ProcessPOSIX::DisableWatchpoint(watchID = %" PRIu64 ")",
+                        watchID);
+        if (!wp->IsEnabled())
+        {
+            if (log)
+                log->Printf("ProcessPOSIX::DisableWatchpoint(watchID = %" PRIu64
+                            ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.",
+                            watchID, (uint64_t)addr);
+            // This is needed (for now) to keep watchpoints disabled correctly
+            wp->SetEnabled(false, notify);
+            return error;
+        }
+
+        if (wp->IsHardware())
+        {
+            bool wp_disabled = true;
+            uint32_t thread_count = m_thread_list.GetSize(false);
+            for (uint32_t i = 0; i < thread_count; ++i)
+            {
+                POSIXThread *thread = static_cast<POSIXThread*>(
+                                      m_thread_list.GetThreadAtIndex(i, false).get());
+                if (thread)
+                    wp_disabled &= thread->DisableHardwareWatchpoint(wp);
+                else
+                    wp_disabled = false;
+            }
+            if (wp_disabled)
+            {
+                wp->SetHardwareIndex(LLDB_INVALID_INDEX32);
+                wp->SetEnabled(false, notify);
+                return error;
+            }
+            else
+                error.SetErrorString("Disabling hardware watchpoint failed");
+        }
+    }
+    else
+        error.SetErrorString("Watchpoint argument was NULL.");
+    return error;
+}
+
+Error
+ProcessPOSIX::GetWatchpointSupportInfo(uint32_t &num)
+{
+    Error error;
+    POSIXThread *thread = static_cast<POSIXThread*>(
+                          m_thread_list.GetThreadAtIndex(0, false).get());
+    if (thread)
+        num = thread->NumSupportedHardwareWatchpoints();
+    else
+        error.SetErrorString("Process does not exist.");
+    return error;
+}
+
+Error
+ProcessPOSIX::GetWatchpointSupportInfo(uint32_t &num, bool &after)
+{
+    Error error = GetWatchpointSupportInfo(num);
+    // Watchpoints trigger and halt the inferior after
+    // the corresponding instruction has been executed.
+    after = true;
+    return error;
+}
+
+uint32_t
+ProcessPOSIX::UpdateThreadListIfNeeded()
+{
+    // Do not allow recursive updates.
+    return m_thread_list.GetSize(false);
+}
+
 bool
 ProcessPOSIX::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
 {
-    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
     if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
-        log->Printf ("ProcessPOSIX::%s() (pid = %i)", __FUNCTION__, GetID());
+        log->Printf ("ProcessPOSIX::%s() (pid = %" PRIi64 ")", __FUNCTION__, GetID());
 
     bool has_updated = false;
     // Update the process thread list with this new thread.
@@ -497,13 +793,12 @@ ProcessPOSIX::UpdateThreadList(ThreadLis
     assert(m_monitor);
     ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false));
     if (!thread_sp) {
-        ProcessSP me = this->shared_from_this();
-        thread_sp.reset(new POSIXThread(me, GetID()));
+        thread_sp.reset(new POSIXThread(*this, GetID()));
         has_updated = true;
     }
 
     if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
-        log->Printf ("ProcessPOSIX::%s() updated pid = %i", __FUNCTION__, GetID());
+        log->Printf ("ProcessPOSIX::%s() updated pid = %" PRIi64, __FUNCTION__, GetID());
     new_thread_list.AddThread(thread_sp);
 
     return has_updated; // the list has been updated
@@ -529,27 +824,6 @@ ProcessPOSIX::PutSTDIN(const char *buf,
     return status;
 }
 
-size_t
-ProcessPOSIX::GetSTDOUT(char *buf, size_t len, Error &error)
-{
-    ssize_t bytes_read;
-
-    // The terminal file descriptor is always in non-block mode.
-    if ((bytes_read = read(m_monitor->GetTerminalFD(), buf, len)) < 0) 
-    {
-        if (errno != EAGAIN)
-            error.SetErrorToErrno();
-        return 0;
-    }
-    return bytes_read;
-}
-
-size_t
-ProcessPOSIX::GetSTDERR(char *buf, size_t len, Error &error)
-{
-    return GetSTDOUT(buf, len, error);
-}
-
 UnixSignals &
 ProcessPOSIX::GetUnixSignals()
 {

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.h Thu Jun  6 19:06:43 2013
@@ -49,6 +49,9 @@ public:
     DoAttachToProcessWithID(lldb::pid_t pid);
 
     virtual lldb_private::Error
+    DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info);
+
+    virtual lldb_private::Error
     DoLaunch (lldb_private::Module *exe_module, 
               const lldb_private::ProcessLaunchInfo &launch_info);
 
@@ -62,7 +65,7 @@ public:
     DoHalt(bool &caused_stop);
 
     virtual lldb_private::Error
-    DoDetach();
+    DoDetach(bool keep_stopped);
 
     virtual lldb_private::Error
     DoSignal(int signal);
@@ -93,14 +96,32 @@ public:
     virtual lldb_private::Error
     DoDeallocateMemory(lldb::addr_t ptr);
 
+    virtual lldb::addr_t
+    ResolveIndirectFunction(const lldb_private::Address *address, lldb_private::Error &error);
+
     virtual size_t
     GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site);
 
     virtual lldb_private::Error
-    EnableBreakpoint(lldb_private::BreakpointSite *bp_site);
+    EnableBreakpointSite(lldb_private::BreakpointSite *bp_site);
+
+    virtual lldb_private::Error
+    DisableBreakpointSite(lldb_private::BreakpointSite *bp_site);
+
+    virtual lldb_private::Error
+    EnableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true);
+
+    virtual lldb_private::Error
+    DisableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true);
 
     virtual lldb_private::Error
-    DisableBreakpoint(lldb_private::BreakpointSite *bp_site);
+    GetWatchpointSupportInfo(uint32_t &num);
+
+    virtual lldb_private::Error
+    GetWatchpointSupportInfo(uint32_t &num, bool &after);
+
+    virtual uint32_t
+    UpdateThreadListIfNeeded();
 
     virtual bool
     UpdateThreadList(lldb_private::ThreadList &old_thread_list, 
@@ -115,12 +136,6 @@ public:
     virtual size_t
     PutSTDIN(const char *buf, size_t len, lldb_private::Error &error);
 
-    virtual size_t
-    GetSTDOUT(char *buf, size_t len, lldb_private::Error &error);
-
-    virtual size_t
-    GetSTDERR(char *buf, size_t len, lldb_private::Error &error);
-
     //--------------------------------------------------------------------------
     // ProcessPOSIX internal API.
 
@@ -137,6 +152,11 @@ public:
     GetFilePath(const lldb_private::ProcessLaunchInfo::FileAction *file_action,
                 const char *default_path);
 
+    /// Stops all threads in the process.
+    /// The \p stop_tid parameter indicates the thread which initiated the stop.
+    virtual void
+    StopAllThreads(lldb::tid_t stop_tid);
+
 protected:
     /// Target byte order.
     lldb::ByteOrder m_byte_order;

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp Thu Jun  6 19:06:43 2013
@@ -21,24 +21,28 @@ using namespace lldb_private;
 
 // We want to avoid global constructors where code needs to be run so here we
 // control access to our static g_log_sp by hiding it in a singleton function
-// that will construct the static g_lob_sp the first time this function is 
+// that will construct the static g_log_sp the first time this function is 
 // called.
-static LogSP &
+static bool g_log_enabled = false;
+static Log * g_log = NULL;
+static Log *
 GetLog ()
 {
-    static LogSP g_log_sp;
-    return g_log_sp;
+    if (!g_log_enabled)
+        return NULL;
+    return g_log;
 }
 
-LogSP
+
+Log *
 ProcessPOSIXLog::GetLogIfAllCategoriesSet (uint32_t mask)
 {
-    LogSP log(GetLog ());
+    Log *log(GetLog ());
     if (log && mask)
     {
         uint32_t log_mask = log->GetMask().Get();
         if ((log_mask & mask) != mask)
-            return LogSP();
+            return NULL;
     }
     return log;
 }
@@ -46,7 +50,7 @@ ProcessPOSIXLog::GetLogIfAllCategoriesSe
 void
 ProcessPOSIXLog::DisableLog (const char **args, Stream *feedback_strm)
 {
-    LogSP log (GetLog ());
+    Log *log (GetLog ());
     if (log)
     {
         uint32_t flag_bits = 0;
@@ -79,33 +83,33 @@ ProcessPOSIXLog::DisableLog (const char
             }
         }
         
+        log->GetMask().Reset (flag_bits);
         if (flag_bits == 0)
-            GetLog ().reset();
-        else
-            log->GetMask().Reset (flag_bits);
+            g_log_enabled = false;
     }
     
     return;
 }
 
-LogSP
+Log *
 ProcessPOSIXLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, const char **args, Stream *feedback_strm)
 {
     // Try see if there already is a log - that way we can reuse its settings.
     // We could reuse the log in toto, but we don't know that the stream is the same.
     uint32_t flag_bits = 0;
-    LogSP log(GetLog ());
-    if (log)
-        flag_bits = log->GetMask().Get();
+    if (g_log)
+        flag_bits = g_log->GetMask().Get();
 
     // Now make a new log with this stream if one was provided
     if (log_stream_sp)
     {
-        log = LogSP(new Log(log_stream_sp));
-        GetLog () = log;
+        if (g_log)
+            g_log->SetStream(log_stream_sp);
+        else
+            g_log = new Log(log_stream_sp);
     }
 
-    if (log)
+    if (g_log)
     {
         bool got_unknown_category = false;
         for (; args[0]; args++)
@@ -140,10 +144,11 @@ ProcessPOSIXLog::EnableLog (StreamSP &lo
         }
         if (flag_bits == 0)
             flag_bits = POSIX_LOG_DEFAULT;
-        log->GetMask().Reset(flag_bits);
-        log->GetOptions().Reset(log_options);
+        g_log->GetMask().Reset(flag_bits);
+        g_log->GetOptions().Reset(log_options);
+        g_log_enabled = true;
     }
-    return log;
+    return g_log;
 }
 
 void
@@ -174,7 +179,7 @@ ProcessPOSIXLog::ListLogCategories (Stre
 void
 ProcessPOSIXLog::LogIf (uint32_t mask, const char *format, ...)
 {
-    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (mask));
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (mask));
     if (log)
     {
         va_list args;

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIXLog.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIXLog.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIXLog.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIXLog.h Thu Jun  6 19:06:43 2013
@@ -49,14 +49,19 @@ public:
         m_pluginname = pluginName;
     }
 
+    static void
+    RegisterPluginName(lldb_private::ConstString pluginName)
+        {
+            m_pluginname = pluginName.GetCString();
+        }
 
-    static lldb::LogSP
+    static lldb_private::Log *
     GetLogIfAllCategoriesSet(uint32_t mask = 0);
 
     static void
     DisableLog (const char **args, lldb_private::Stream *feedback_strm);
 
-    static lldb::LogSP
+    static lldb_private::Log *
     EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options,
                const char **args, lldb_private::Stream *feedback_strm);
 

Copied: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp (from r182522, lldb/trunk/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp)
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp?p2=lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp&p1=lldb/trunk/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp&r1=182522&r2=183468&rev=183468&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp Thu Jun  6 19:06:43 2013
@@ -8,6 +8,7 @@
 //===---------------------------------------------------------------------===//
 
 #include "RegisterContextFreeBSD_x86_64.h"
+#include <vector>
 
 using namespace lldb_private;
 
@@ -18,13 +19,13 @@ using namespace lldb_private;
 // Update the FreeBSD specific information (offset and size).
 #define UPDATE_GPR_INFO(reg)                                                \
 do {                                                                        \
-    m_register_infos[gpr_##reg].byte_size = sizeof(GPR::reg);               \
-    m_register_infos[gpr_##reg].byte_offset = GPR_OFFSET(reg);              \
+    GetRegisterContext()[gpr_##reg].byte_size = sizeof(GPR::reg);               \
+    GetRegisterContext()[gpr_##reg].byte_offset = GPR_OFFSET(reg);              \
 } while(false);
 
 #define UPDATE_I386_GPR_INFO(i386_reg, reg)                                 \
 do {                                                                        \
-    m_register_infos[gpr_##i386_reg].byte_offset = GPR_OFFSET(reg);         \
+    GetRegisterContext()[gpr_##i386_reg].byte_offset = GPR_OFFSET(reg);         \
 } while(false);
 
 typedef struct _GPR
@@ -57,20 +58,18 @@ typedef struct _GPR
     uint64_t ss;
 } GPR;
 
-RegisterInfo *RegisterContextFreeBSD_x86_64::m_register_infos = nullptr;
+// Use a singleton function to avoid global constructors in shared libraries.
+static std::vector<RegisterInfo> & GetRegisterContext () {
+    static std::vector<RegisterInfo> g_register_infos;
+    return g_register_infos;
+}
+
 
 RegisterContextFreeBSD_x86_64::RegisterContextFreeBSD_x86_64(Thread &thread, uint32_t concrete_frame_idx):
     RegisterContext_x86_64(thread, concrete_frame_idx)
 {
 }
 
-RegisterContextFreeBSD_x86_64::~RegisterContextFreeBSD_x86_64()
-{
-    if (m_register_infos)
-        delete m_register_infos;
-    m_register_infos = nullptr;
-}
-
 size_t
 RegisterContextFreeBSD_x86_64::GetGPRSize()
 {
@@ -81,19 +80,18 @@ const RegisterInfo *
 RegisterContextFreeBSD_x86_64::GetRegisterInfo()
 {
     // Allocate RegisterInfo only once
-    if (!m_register_infos)
+    if (GetRegisterContext().empty())
     {
-        m_register_infos = new RegisterInfo[k_num_registers];
         // Copy the register information from base class
-        if (m_register_infos)
+        const RegisterInfo *base_info = RegisterContext_x86_64::GetRegisterInfo();
+        if (base_info)
         {
-            memcpy(m_register_infos, RegisterContext_x86_64::GetRegisterInfo(),
-                   sizeof(RegisterInfo) * k_num_registers);
-            // Update the Linux specific register information (offset and size).
+            GetRegisterContext().insert(GetRegisterContext().end(), &base_info[0], &base_info[k_num_registers]);
+            // Update the FreeBSD specific register information (offset and size).
             UpdateRegisterInfo();
         }
     }
-    return m_register_infos;
+    return &GetRegisterContext()[0];
 }
 
 void

Copied: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h (from r182522, lldb/trunk/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h)
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h?p2=lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h&p1=lldb/trunk/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h&r1=182522&r2=183468&rev=183468&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h Thu Jun  6 19:06:43 2013
@@ -17,7 +17,6 @@ class RegisterContextFreeBSD_x86_64:
 {
 public:
     RegisterContextFreeBSD_x86_64(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
-    virtual ~RegisterContextFreeBSD_x86_64();
 
     size_t
     GetGPRSize();
@@ -28,9 +27,6 @@ protected:
 
     virtual void
     UpdateRegisterInfo();
-
-private:
-    static lldb_private::RegisterInfo *m_register_infos;
 };
 
 #endif

Copied: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp (from r182522, lldb/trunk/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp)
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp?p2=lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp&p1=lldb/trunk/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp&r1=182522&r2=183468&rev=183468&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp Thu Jun  6 19:06:43 2013
@@ -8,6 +8,7 @@
 //===---------------------------------------------------------------------===//
 
 #include "RegisterContextLinux_x86_64.h"
+#include <vector>
 
 using namespace lldb_private;
 
@@ -18,13 +19,13 @@ using namespace lldb_private;
 // Update the Linux specific information (offset and size).
 #define UPDATE_GPR_INFO(reg)                                                \
 do {                                                                        \
-    m_register_infos[gpr_##reg].byte_size = sizeof(GPR::reg);               \
-    m_register_infos[gpr_##reg].byte_offset = GPR_OFFSET(reg);              \
+    GetRegisterContext()[gpr_##reg].byte_size = sizeof(GPR::reg);               \
+    GetRegisterContext()[gpr_##reg].byte_offset = GPR_OFFSET(reg);              \
 } while(false);
 
 #define UPDATE_I386_GPR_INFO(i386_reg, reg)                                 \
 do {                                                                        \
-    m_register_infos[gpr_##i386_reg].byte_offset = GPR_OFFSET(reg);         \
+    GetRegisterContext()[gpr_##i386_reg].byte_offset = GPR_OFFSET(reg);         \
 } while(false);
 
 #define DR_OFFSET(reg_index)                                                \
@@ -32,8 +33,8 @@ do {
 
 #define UPDATE_DR_INFO(reg_index)                                                \
 do {                                                                             \
-    m_register_infos[dr##reg_index].byte_size = sizeof(UserArea::u_debugreg[0]); \
-    m_register_infos[dr##reg_index].byte_offset = DR_OFFSET(reg_index);          \
+    GetRegisterContext()[dr##reg_index].byte_size = sizeof(UserArea::u_debugreg[0]); \
+    GetRegisterContext()[dr##reg_index].byte_offset = DR_OFFSET(reg_index);          \
 } while(false);
 
 typedef struct _GPR
@@ -92,20 +93,17 @@ struct UserArea
     uint64_t fault_address; // Control register CR3.
 };
 
-RegisterInfo *RegisterContextLinux_x86_64::m_register_infos = nullptr;
+// Use a singleton function to avoid global constructors in shared libraries.
+static std::vector<RegisterInfo> & GetRegisterContext () {
+    static std::vector<RegisterInfo> g_register_infos;
+    return g_register_infos;
+}
 
 RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(Thread &thread, uint32_t concrete_frame_idx):
     RegisterContext_x86_64(thread, concrete_frame_idx)
 {
 }
 
-RegisterContextLinux_x86_64::~RegisterContextLinux_x86_64()
-{
-    if (m_register_infos)
-        delete m_register_infos;
-    m_register_infos = nullptr;
-}
-
 size_t
 RegisterContextLinux_x86_64::GetGPRSize()
 {
@@ -116,19 +114,18 @@ const RegisterInfo *
 RegisterContextLinux_x86_64::GetRegisterInfo()
 {
     // Allocate RegisterInfo only once
-    if (!m_register_infos)
+    if (GetRegisterContext().empty())
     {
-        m_register_infos = new RegisterInfo[k_num_registers];
         // Copy the register information from base class
-        if (m_register_infos)
+        const RegisterInfo *base_info = RegisterContext_x86_64::GetRegisterInfo();
+        if (base_info)
         {
-            memcpy(m_register_infos, RegisterContext_x86_64::GetRegisterInfo(),
-                   sizeof(RegisterInfo) * k_num_registers);
+            GetRegisterContext().insert(GetRegisterContext().end(), &base_info[0], &base_info[k_num_registers]);
             // Update the Linux specific register information (offset and size).
             UpdateRegisterInfo();
         }
     }
-    return m_register_infos;
+    return &GetRegisterContext()[0];
 }
 
 void

Copied: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h (from r182522, lldb/trunk/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h)
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h?p2=lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h&p1=lldb/trunk/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h&r1=182522&r2=183468&rev=183468&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h Thu Jun  6 19:06:43 2013
@@ -17,7 +17,6 @@ class RegisterContextLinux_x86_64:
 {
 public:
     RegisterContextLinux_x86_64(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
-    virtual ~RegisterContextLinux_x86_64();
 
     size_t
     GetGPRSize();
@@ -28,9 +27,6 @@ protected:
 
     virtual void
     UpdateRegisterInfo();
-
-private:
-    static lldb_private::RegisterInfo *m_register_infos;
 };
 
 #endif

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextPOSIX.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextPOSIX.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextPOSIX.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextPOSIX.h Thu Jun  6 19:06:43 2013
@@ -25,7 +25,8 @@ class RegisterContextPOSIX
 public:
     RegisterContextPOSIX(lldb_private::Thread &thread,
                          uint32_t concrete_frame_idx)
-        : RegisterContext(thread, concrete_frame_idx) { }
+        : RegisterContext(thread, concrete_frame_idx)
+        { m_watchpoints_initialized = false; }
 
     /// Updates the register state of the associated thread after hitting a
     /// breakpoint (if that make sense for the architecture).  Default
@@ -35,6 +36,35 @@ public:
     /// @return
     ///    True if the operation succeeded and false otherwise.
     virtual bool UpdateAfterBreakpoint() { return true; }
+
+    /// Determines the index in lldb's register file given a kernel byte offset.
+    virtual unsigned
+    GetRegisterIndexFromOffset(unsigned offset) { return LLDB_INVALID_REGNUM; }
+
+    // Checks to see if a watchpoint specified by hw_index caused the inferior
+    // to stop.
+    virtual bool
+    IsWatchpointHit (uint32_t hw_index) { return false; }
+
+    // Resets any watchpoints that have been hit.
+    virtual bool
+    ClearWatchpointHits () { return false; }
+
+    // Returns the watchpoint address associated with a watchpoint hardware
+    // index.
+    virtual lldb::addr_t
+    GetWatchpointAddress (uint32_t hw_index) { return LLDB_INVALID_ADDRESS; }
+
+    virtual bool
+    IsWatchpointVacant (uint32_t hw_index) { return false; }
+
+    virtual bool
+    SetHardwareWatchpointWithIndex (lldb::addr_t addr, size_t size,
+                                    bool read, bool write,
+                                    uint32_t hw_index) { return false; }
+
+protected:
+    bool m_watchpoints_initialized;
 };
 
 #endif // #ifndef liblldb_RegisterContextPOSIX_H_

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_i386.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_i386.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_i386.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_i386.cpp Thu Jun  6 19:06:43 2013
@@ -15,6 +15,7 @@
 #include "ProcessPOSIXLog.h"
 #include "ProcessMonitor.h"
 #include "RegisterContext_i386.h"
+#include "RegisterContext_x86.h"
 
 using namespace lldb_private;
 using namespace lldb;
@@ -82,103 +83,6 @@ enum
     k_num_register_sets = 2
 };
 
-enum
-{
-    gcc_eax = 0,
-    gcc_ecx,
-    gcc_edx,
-    gcc_ebx,
-    gcc_ebp,
-    gcc_esp,
-    gcc_esi,
-    gcc_edi,
-    gcc_eip,
-    gcc_eflags
-};
-
-enum
-{
-    dwarf_eax = 0,
-    dwarf_ecx,
-    dwarf_edx,
-    dwarf_ebx,
-    dwarf_esp,
-    dwarf_ebp,
-    dwarf_esi,
-    dwarf_edi,
-    dwarf_eip,
-    dwarf_eflags,
-    dwarf_stmm0 = 11,
-    dwarf_stmm1,
-    dwarf_stmm2,
-    dwarf_stmm3,
-    dwarf_stmm4,
-    dwarf_stmm5,
-    dwarf_stmm6,
-    dwarf_stmm7,
-    dwarf_xmm0 = 21,
-    dwarf_xmm1,
-    dwarf_xmm2,
-    dwarf_xmm3,
-    dwarf_xmm4,
-    dwarf_xmm5,
-    dwarf_xmm6,
-    dwarf_xmm7
-};
-
-enum
-{
-    gdb_eax        =  0,
-    gdb_ecx        =  1,
-    gdb_edx        =  2,
-    gdb_ebx        =  3,
-    gdb_esp        =  4,
-    gdb_ebp        =  5,
-    gdb_esi        =  6,
-    gdb_edi        =  7,
-    gdb_eip        =  8,
-    gdb_eflags     =  9,
-    gdb_cs         = 10,
-    gdb_ss         = 11,
-    gdb_ds         = 12,
-    gdb_es         = 13,
-    gdb_fs         = 14,
-    gdb_gs         = 15,
-    gdb_stmm0      = 16,
-    gdb_stmm1      = 17,
-    gdb_stmm2      = 18,
-    gdb_stmm3      = 19,
-    gdb_stmm4      = 20,
-    gdb_stmm5      = 21,
-    gdb_stmm6      = 22,
-    gdb_stmm7      = 23,
-    gdb_fcw        = 24,
-    gdb_fsw        = 25,
-    gdb_ftw        = 26,
-    gdb_fpu_cs     = 27,
-    gdb_ip         = 28,
-    gdb_fpu_ds     = 29,
-    gdb_dp         = 30,
-    gdb_fop        = 31,
-    gdb_xmm0       = 32,
-    gdb_xmm1       = 33,
-    gdb_xmm2       = 34,
-    gdb_xmm3       = 35,
-    gdb_xmm4       = 36,
-    gdb_xmm5       = 37,
-    gdb_xmm6       = 38,
-    gdb_xmm7       = 39,
-    gdb_mxcsr      = 40,
-    gdb_mm0        = 41,
-    gdb_mm1        = 42,
-    gdb_mm2        = 43,
-    gdb_mm3        = 44,
-    gdb_mm4        = 45,
-    gdb_mm5        = 46,
-    gdb_mm6        = 47,
-    gdb_mm7        = 48
-};
-
 static const
 uint32_t g_gpr_regnums[k_num_gpr_registers] =
 {
@@ -387,7 +291,7 @@ RegisterContext_i386::GetRegisterCount()
 }
 
 const RegisterInfo *
-RegisterContext_i386::GetRegisterInfoAtIndex(uint32_t reg)
+RegisterContext_i386::GetRegisterInfoAtIndex(size_t reg)
 {
     assert(k_num_register_infos == k_num_registers);
     if (reg < k_num_registers)
@@ -403,7 +307,7 @@ RegisterContext_i386::GetRegisterSetCoun
 }
 
 const RegisterSet *
-RegisterContext_i386::GetRegisterSet(uint32_t set)
+RegisterContext_i386::GetRegisterSet(size_t set)
 {
     if (set < k_num_register_sets)
         return &g_reg_sets[set];
@@ -437,7 +341,8 @@ RegisterContext_i386::ReadRegister(const
 {
     const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
     ProcessMonitor &monitor = GetMonitor();
-    return monitor.ReadRegisterValue(GetRegOffset(reg), GetRegSize(reg), value);
+    return monitor.ReadRegisterValue(m_thread.GetID(), GetRegOffset(reg),
+                                     GetRegisterName(reg), GetRegSize(reg), value);
 }
 
 bool
@@ -447,11 +352,12 @@ RegisterContext_i386::ReadAllRegisterVal
 }
 
 bool RegisterContext_i386::WriteRegister(const RegisterInfo *reg_info,
-                                              const RegisterValue &value)
+                                         const RegisterValue &value)
 {
     const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
     ProcessMonitor &monitor = GetMonitor();
-    return monitor.WriteRegisterValue(GetRegOffset(reg), value);
+    return monitor.WriteRegisterValue(m_thread.GetID(), GetRegOffset(reg),
+                                      GetRegisterName(reg), value);
 }
 
 bool
@@ -612,7 +518,7 @@ RegisterContext_i386::HardwareSingleStep
 void
 RegisterContext_i386::LogGPR(const char *title)
 {
-    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
     if (log)
     {
         if (title)
@@ -620,7 +526,7 @@ RegisterContext_i386::LogGPR(const char
         for (uint32_t i=0; i<k_num_gpr_registers; i++)
         {
             uint32_t reg = gpr_eax + i;
-            log->Printf("%12s = 0x%8.8x", g_register_infos[reg].name, (&user.regs)[reg]);
+            log->Printf("%12s = 0x%8.8" PRIx64, g_register_infos[reg].name, ((uint64_t*)&user.regs)[reg]);
         }
     }
 }
@@ -631,7 +537,7 @@ RegisterContext_i386::ReadGPR()
     bool result;
 
     ProcessMonitor &monitor = GetMonitor();
-    result = monitor.ReadGPR(&user.regs);
+    result = monitor.ReadGPR(m_thread.GetID(), &user.regs, sizeof(user.regs));
     LogGPR("RegisterContext_i386::ReadGPR()");
     return result;
 }
@@ -640,5 +546,5 @@ bool
 RegisterContext_i386::ReadFPR()
 {
     ProcessMonitor &monitor = GetMonitor();
-    return monitor.ReadFPR(&user.i387);
+    return monitor.ReadFPR(m_thread.GetID(), &user.i387, sizeof(user.i387));
 }

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_i386.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_i386.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_i386.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_i386.h Thu Jun  6 19:06:43 2013
@@ -35,18 +35,18 @@ public:
     GetRegisterCount();
 
     const lldb_private::RegisterInfo *
-    GetRegisterInfoAtIndex(uint32_t reg);
+    GetRegisterInfoAtIndex(size_t reg);
 
     size_t
     GetRegisterSetCount();
 
     const lldb_private::RegisterSet *
-    GetRegisterSet(uint32_t set);
+    GetRegisterSet(size_t set);
 
-    static unsigned
+    unsigned
     GetRegisterIndexFromOffset(unsigned offset);
 
-    static const char *
+    const char *
     GetRegisterName(unsigned reg);
 
     bool

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp Thu Jun  6 19:06:43 2013
@@ -13,97 +13,28 @@
 
 #include "lldb/Core/DataBufferHeap.h"
 #include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/RegisterValue.h"
 #include "lldb/Core/Scalar.h"
+#include "lldb/Target/Target.h"
 #include "lldb/Target/Thread.h"
 #include "lldb/Host/Endian.h"
 
 #include "ProcessPOSIX.h"
 #include "ProcessMonitor.h"
+#include "RegisterContext_i386.h"
+#include "RegisterContext_x86.h"
 #include "RegisterContext_x86_64.h"
 
 using namespace lldb_private;
 using namespace lldb;
 
-// Internal codes for all x86_64 registers.
-enum
-{
-    k_first_gpr,
-    gpr_rax = k_first_gpr,
-    gpr_rbx,
-    gpr_rcx,
-    gpr_rdx,
-    gpr_rdi,
-    gpr_rsi,
-    gpr_rbp,
-    gpr_rsp,
-    gpr_r8,
-    gpr_r9,
-    gpr_r10,
-    gpr_r11,
-    gpr_r12,
-    gpr_r13,
-    gpr_r14,
-    gpr_r15,
-    gpr_rip,
-    gpr_rflags,
-    gpr_cs,
-    gpr_fs,
-    gpr_gs,
-    gpr_ss,
-    gpr_ds,
-    gpr_es,
-    k_last_gpr = gpr_es,
+// Support ptrace extensions even when compiled without required kernel support
+#ifndef NT_X86_XSTATE
+  #define NT_X86_XSTATE 0x202
+#endif
 
-    k_first_fpr,
-    fpu_fcw = k_first_fpr,
-    fpu_fsw,
-    fpu_ftw,
-    fpu_fop,
-    fpu_ip,
-    fpu_cs,
-    fpu_dp,
-    fpu_ds,
-    fpu_mxcsr,
-    fpu_mxcsrmask,
-    fpu_stmm0,
-    fpu_stmm1,
-    fpu_stmm2,
-    fpu_stmm3,
-    fpu_stmm4,
-    fpu_stmm5,
-    fpu_stmm6,
-    fpu_stmm7,
-    fpu_xmm0,
-    fpu_xmm1,
-    fpu_xmm2,
-    fpu_xmm3,
-    fpu_xmm4,
-    fpu_xmm5,
-    fpu_xmm6,
-    fpu_xmm7,
-    fpu_xmm8,
-    fpu_xmm9,
-    fpu_xmm10,
-    fpu_xmm11,
-    fpu_xmm12,
-    fpu_xmm13,
-    fpu_xmm14,
-    fpu_xmm15,
-    k_last_fpr = fpu_xmm15,
-
-    k_num_registers,
-    k_num_gpr_registers = k_last_gpr - k_first_gpr + 1,
-    k_num_fpu_registers = k_last_fpr - k_first_fpr + 1
-};
-
-// Number of register sets provided by this context.
 enum
 {
-    k_num_register_sets = 2
-};
-
-enum gcc_dwarf_regnums
-{
     gcc_dwarf_gpr_rax = 0,
     gcc_dwarf_gpr_rdx,
     gcc_dwarf_gpr_rcx,
@@ -144,10 +75,26 @@ enum gcc_dwarf_regnums
     gcc_dwarf_fpu_stmm4,
     gcc_dwarf_fpu_stmm5,
     gcc_dwarf_fpu_stmm6,
-    gcc_dwarf_fpu_stmm7
+    gcc_dwarf_fpu_stmm7,
+    gcc_dwarf_fpu_ymm0,
+    gcc_dwarf_fpu_ymm1,
+    gcc_dwarf_fpu_ymm2,
+    gcc_dwarf_fpu_ymm3,
+    gcc_dwarf_fpu_ymm4,
+    gcc_dwarf_fpu_ymm5,
+    gcc_dwarf_fpu_ymm6,
+    gcc_dwarf_fpu_ymm7,
+    gcc_dwarf_fpu_ymm8,
+    gcc_dwarf_fpu_ymm9,
+    gcc_dwarf_fpu_ymm10,
+    gcc_dwarf_fpu_ymm11,
+    gcc_dwarf_fpu_ymm12,
+    gcc_dwarf_fpu_ymm13,
+    gcc_dwarf_fpu_ymm14,
+    gcc_dwarf_fpu_ymm15
 };
 
-enum gdb_regnums
+enum
 {
     gdb_gpr_rax     =   0,
     gdb_gpr_rbx     =   1,
@@ -184,9 +131,9 @@ enum gdb_regnums
     gdb_fpu_fcw     =  32,
     gdb_fpu_fsw     =  33,
     gdb_fpu_ftw     =  34,
-    gdb_fpu_cs      =  35,
+    gdb_fpu_cs_64   =  35,
     gdb_fpu_ip      =  36,
-    gdb_fpu_ds      =  37,
+    gdb_fpu_ds_64   =  37,
     gdb_fpu_dp      =  38,
     gdb_fpu_fop     =  39,
     gdb_fpu_xmm0    =  40,
@@ -205,7 +152,23 @@ enum gdb_regnums
     gdb_fpu_xmm13   =  53,
     gdb_fpu_xmm14   =  54,
     gdb_fpu_xmm15   =  55,
-    gdb_fpu_mxcsr   =  56
+    gdb_fpu_mxcsr   =  56,
+    gdb_fpu_ymm0    =  57,
+    gdb_fpu_ymm1    =  58,
+    gdb_fpu_ymm2    =  59,
+    gdb_fpu_ymm3    =  60,
+    gdb_fpu_ymm4    =  61,
+    gdb_fpu_ymm5    =  62,
+    gdb_fpu_ymm6    =  63,
+    gdb_fpu_ymm7    =  64,
+    gdb_fpu_ymm8    =  65,
+    gdb_fpu_ymm9    =  66,
+    gdb_fpu_ymm10   =  67,
+    gdb_fpu_ymm11   =  68,
+    gdb_fpu_ymm12   =  69,
+    gdb_fpu_ymm13   =  70,
+    gdb_fpu_ymm14   =  71,
+    gdb_fpu_ymm15   =  72
 };
 
 static const
@@ -234,11 +197,21 @@ uint32_t g_gpr_regnums[k_num_gpr_registe
     gpr_gs,
     gpr_ss,
     gpr_ds,
-    gpr_es
+    gpr_es,
+    gpr_eax,
+    gpr_ebx,
+    gpr_ecx,
+    gpr_edx,
+    gpr_edi,
+    gpr_esi,
+    gpr_ebp,
+    gpr_esp,
+    gpr_eip,
+    gpr_eflags
 };
 
 static const uint32_t
-g_fpu_regnums[k_num_fpu_registers] =
+g_fpu_regnums[k_num_fpr_registers] =
 {
     fpu_fcw,
     fpu_fsw,
@@ -276,28 +249,56 @@ g_fpu_regnums[k_num_fpu_registers] =
     fpu_xmm15
 };
 
+static const uint32_t
+g_avx_regnums[k_num_avx_registers] =
+{
+    fpu_ymm0,
+    fpu_ymm1,
+    fpu_ymm2,
+    fpu_ymm3,
+    fpu_ymm4,
+    fpu_ymm5,
+    fpu_ymm6,
+    fpu_ymm7,
+    fpu_ymm8,
+    fpu_ymm9,
+    fpu_ymm10,
+    fpu_ymm11,
+    fpu_ymm12,
+    fpu_ymm13,
+    fpu_ymm14,
+    fpu_ymm15
+};
+
+// Number of register sets provided by this context.
+enum
+{
+    k_num_extended_register_sets = 1,
+    k_num_register_sets = 3
+};
+
 static const RegisterSet
 g_reg_sets[k_num_register_sets] =
 {
-    { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums },
-    { "Floating Point Registers",  "fpu", k_num_fpu_registers, g_fpu_regnums }
+    { "General Purpose Registers",  "gpr", k_num_gpr_registers, g_gpr_regnums },
+    { "Floating Point Registers",   "fpu", k_num_fpr_registers, g_fpu_regnums },
+    { "Advanced Vector Extensions", "avx", k_num_avx_registers, g_avx_regnums }
 };
 
-// Computes the offset of the given GPR in the user data area.
-#define GPR_OFFSET(regname) \
-    (offsetof(RegisterContext_x86_64::UserArea, regs) + \
-     offsetof(GPR, regname))
-
-// Computes the offset of the given FPR in the user data area.
+// Computes the offset of the given FPR in the extended data area.
 #define FPR_OFFSET(regname) \
-    (offsetof(RegisterContext_x86_64::UserArea, i387) + \
-     offsetof(RegisterContext_x86_64::FPU, regname))
+    (offsetof(RegisterContext_x86_64::FPR, xstate) + \
+     offsetof(RegisterContext_x86_64::FXSAVE, regname))
 
-// Number of bytes needed to represent a GPR.
-#define GPR_SIZE(reg) sizeof(((GPR*)NULL)->reg)
+// Computes the offset of the YMM register assembled from register halves.
+#define YMM_OFFSET(regname) \
+    (offsetof(RegisterContext_x86_64::YMM, regname))
+
+// Number of bytes needed to represent a i386 GPR
+#define GPR_i386_SIZE(reg) sizeof(((RegisterContext_i386::GPR*)NULL)->reg)
 
 // Number of bytes needed to represent a FPR.
-#define FPR_SIZE(reg) sizeof(((RegisterContext_x86_64::FPU*)NULL)->reg)
+#define FPR_SIZE(reg) sizeof(((RegisterContext_x86_64::FXSAVE*)NULL)->reg)
 
 // Number of bytes needed to represent the i'th FP register.
 #define FP_SIZE sizeof(((RegisterContext_x86_64::MMSReg*)NULL)->bytes)
@@ -305,12 +306,23 @@ g_reg_sets[k_num_register_sets] =
 // Number of bytes needed to represent an XMM register.
 #define XMM_SIZE sizeof(RegisterContext_x86_64::XMMReg)
 
-#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4)        \
-    { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \
+// Number of bytes needed to represent a YMM register.
+#define YMM_SIZE sizeof(RegisterContext_x86_64::YMMReg)
+
+// Note that the size and offset will be updated by platform-specific classes.
+#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4)           \
+    { #reg, alt, 0, 0, eEncodingUint,                              \
       eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg }, NULL, NULL }
 
-#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4)              \
-    { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \
+// Dummy data for RegisterInfo::value_regs as expected by DumpRegisterSet. 
+static uint32_t value_regs = LLDB_INVALID_REGNUM;
+
+#define DEFINE_GPR_i386(reg_i386, reg_x86_64, alt, kind1, kind2, kind3, kind4) \
+    { #reg_i386, alt, GPR_i386_SIZE(reg_i386), 0, eEncodingUint,   \
+      eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg_i386 }, &value_regs, NULL }
+
+#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4)                \
+    { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint,   \
       eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg }, NULL, NULL }
 
 #define DEFINE_FP(reg, i)                                          \
@@ -325,7 +337,18 @@ g_reg_sets[k_num_register_sets] =
       { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i,            \
         LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i }, NULL, NULL }
 
-#define REG_CONTEXT_SIZE (sizeof(GPR) + sizeof(RegisterContext_x86_64::FPU))
+#define DEFINE_YMM(reg, i)                                         \
+    { #reg#i, NULL, YMM_SIZE, YMM_OFFSET(reg[i]), eEncodingVector, \
+      eFormatVectorOfUInt8,                                        \
+      { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i,            \
+        LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i }, NULL, NULL }
+
+#define DEFINE_DR(reg, i)                                              \
+    { #reg#i, NULL, 0, 0, eEncodingUint, eFormatHex,                   \
+      { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
+      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }
+
+#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof(RegisterContext_x86_64::FPR))
 
 static RegisterInfo
 g_register_infos[k_num_registers] =
@@ -355,7 +378,17 @@ g_register_infos[k_num_registers] =
     DEFINE_GPR(ss,     NULL,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,       gdb_gpr_ss),
     DEFINE_GPR(ds,     NULL,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,       gdb_gpr_ds),
     DEFINE_GPR(es,     NULL,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,       gdb_gpr_es),
-
+    // i386 registers
+    DEFINE_GPR_i386(eax,    rax,    NULL,    gcc_eax,    dwarf_eax,    LLDB_INVALID_REGNUM,       gdb_eax),
+    DEFINE_GPR_i386(ebx,    rbx,    NULL,    gcc_ebx,    dwarf_ebx,    LLDB_INVALID_REGNUM,       gdb_ebx),
+    DEFINE_GPR_i386(ecx,    rcx,    NULL,    gcc_ecx,    dwarf_ecx,    LLDB_INVALID_REGNUM,       gdb_ecx),
+    DEFINE_GPR_i386(edx,    rdx,    NULL,    gcc_edx,    dwarf_edx,    LLDB_INVALID_REGNUM,       gdb_edx),
+    DEFINE_GPR_i386(edi,    rdi,    NULL,    gcc_edi,    dwarf_edi,    LLDB_INVALID_REGNUM,       gdb_edi),
+    DEFINE_GPR_i386(esi,    rsi,    NULL,    gcc_esi,    dwarf_esi,    LLDB_INVALID_REGNUM,       gdb_esi),
+    DEFINE_GPR_i386(ebp,    rbp,    "fp",    gcc_ebp,    dwarf_ebp,    LLDB_REGNUM_GENERIC_FP,    gdb_ebp),
+    DEFINE_GPR_i386(esp,    rsp,    "sp",    gcc_esp,    dwarf_esp,    LLDB_REGNUM_GENERIC_SP,    gdb_esp),
+    DEFINE_GPR_i386(eip,    rip,    "pc",    gcc_eip,    dwarf_eip,    LLDB_REGNUM_GENERIC_PC,    gdb_eip),
+    DEFINE_GPR_i386(eflags, rflags, "flags", gcc_eflags, dwarf_eflags, LLDB_REGNUM_GENERIC_FLAGS, gdb_eflags),
     // i387 Floating point registers.
     DEFINE_FPR(fcw,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fcw),
     DEFINE_FPR(fsw,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fsw),
@@ -363,10 +396,10 @@ g_register_infos[k_num_registers] =
     DEFINE_FPR(fop,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fop),
     DEFINE_FPR(ip,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ip),
     // FIXME: Extract segment from ip.
-    DEFINE_FPR(ip,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs),
+    DEFINE_FPR(ip,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs_64),
     DEFINE_FPR(dp,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_dp),
     // FIXME: Extract segment from dp.
-    DEFINE_FPR(dp,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds),
+    DEFINE_FPR(dp,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds_64),
     DEFINE_FPR(mxcsr,     LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_mxcsr),
     DEFINE_FPR(mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
 
@@ -396,35 +429,77 @@ g_register_infos[k_num_registers] =
     DEFINE_XMM(xmm, 12),
     DEFINE_XMM(xmm, 13),
     DEFINE_XMM(xmm, 14),
-    DEFINE_XMM(xmm, 15)
+    DEFINE_XMM(xmm, 15),
+
+    // Copy of YMM registers assembled from xmm and ymmh
+    DEFINE_YMM(ymm, 0),
+    DEFINE_YMM(ymm, 1),
+    DEFINE_YMM(ymm, 2),
+    DEFINE_YMM(ymm, 3),
+    DEFINE_YMM(ymm, 4),
+    DEFINE_YMM(ymm, 5),
+    DEFINE_YMM(ymm, 6),
+    DEFINE_YMM(ymm, 7),
+    DEFINE_YMM(ymm, 8),
+    DEFINE_YMM(ymm, 9),
+    DEFINE_YMM(ymm, 10),
+    DEFINE_YMM(ymm, 11),
+    DEFINE_YMM(ymm, 12),
+    DEFINE_YMM(ymm, 13),
+    DEFINE_YMM(ymm, 14),
+    DEFINE_YMM(ymm, 15),
+
+    // Debug registers for lldb internal use
+    DEFINE_DR(dr, 0),
+    DEFINE_DR(dr, 1),
+    DEFINE_DR(dr, 2),
+    DEFINE_DR(dr, 3),
+    DEFINE_DR(dr, 4),
+    DEFINE_DR(dr, 5),
+    DEFINE_DR(dr, 6),
+    DEFINE_DR(dr, 7)
 };
 
-static unsigned GetRegOffset(unsigned reg)
+static bool IsGPR(unsigned reg)
 {
-    assert(reg < k_num_registers && "Invalid register number.");
-    return g_register_infos[reg].byte_offset;
+    return reg <= k_last_gpr;   // GPR's come first.
 }
 
-static unsigned GetRegSize(unsigned reg)
+static bool IsAVX(unsigned reg)
 {
-    assert(reg < k_num_registers && "Invalid register number.");
-    return g_register_infos[reg].byte_size;
+    return (k_first_avx <= reg && reg <= k_last_avx);
 }
-
-static bool IsGPR(unsigned reg)
+static bool IsFPR(unsigned reg)
 {
-    return reg <= k_last_gpr;   // GPR's come first.
+    return (k_first_fpr <= reg && reg <= k_last_fpr);
 }
 
-static bool IsFPR(unsigned reg)
+
+bool RegisterContext_x86_64::IsFPR(unsigned reg, FPRType fpr_type)
 {
-    return (k_first_fpr <= reg && reg <= k_last_fpr);
+    bool generic_fpr = ::IsFPR(reg);
+    if (fpr_type == eXSAVE)
+      return generic_fpr || IsAVX(reg);
+
+    return generic_fpr;
 }
 
 RegisterContext_x86_64::RegisterContext_x86_64(Thread &thread,
-                                                         uint32_t concrete_frame_idx)
+                                               uint32_t concrete_frame_idx)
     : RegisterContextPOSIX(thread, concrete_frame_idx)
 {
+    // Initialize m_iovec to point to the buffer and buffer size
+    // using the conventions of Berkeley style UIO structures, as required
+    // by PTRACE extensions.
+    m_iovec.iov_base = &m_fpr.xstate.xsave;
+    m_iovec.iov_len = sizeof(m_fpr.xstate.xsave);
+
+    ::memset(&m_fpr, 0, sizeof(RegisterContext_x86_64::FPR));
+
+    // TODO: Use assembly to call cpuid on the inferior and query ebx or ecx
+    m_fpr_type = eXSAVE; // extended floating-point registers, if available
+    if (false == ReadFPR())
+        m_fpr_type = eFXSAVE; // assume generic floating-point registers
 }
 
 RegisterContext_x86_64::~RegisterContext_x86_64()
@@ -449,17 +524,42 @@ RegisterContext_x86_64::InvalidateAllReg
 {
 }
 
+unsigned
+RegisterContext_x86_64::GetRegisterOffset(unsigned reg)
+{
+    assert(reg < k_num_registers && "Invalid register number.");
+    return GetRegisterInfo()[reg].byte_offset;
+}
+
+unsigned
+RegisterContext_x86_64::GetRegisterSize(unsigned reg)
+{
+    assert(reg < k_num_registers && "Invalid register number.");
+    return GetRegisterInfo()[reg].byte_size;
+}
+
 size_t
 RegisterContext_x86_64::GetRegisterCount()
 {
-    return k_num_registers;
+    size_t num_registers = k_num_gpr_registers + k_num_fpr_registers;
+    if (m_fpr_type == eXSAVE)
+      return num_registers + k_num_avx_registers;
+    return num_registers;
+}
+
+const RegisterInfo *
+RegisterContext_x86_64::GetRegisterInfo()
+{
+    // Commonly, this method is overridden and g_register_infos is copied and specialized.
+    // So, use GetRegisterInfo() rather than g_register_infos in this scope.
+    return g_register_infos;
 }
 
 const RegisterInfo *
-RegisterContext_x86_64::GetRegisterInfoAtIndex(uint32_t reg)
+RegisterContext_x86_64::GetRegisterInfoAtIndex(size_t reg)
 {
     if (reg < k_num_registers)
-        return &g_register_infos[reg];
+        return &GetRegisterInfo()[reg];
     else
         return NULL;
 }
@@ -467,13 +567,18 @@ RegisterContext_x86_64::GetRegisterInfoA
 size_t
 RegisterContext_x86_64::GetRegisterSetCount()
 {
-    return k_num_register_sets;
+    size_t sets = 0;
+    for (size_t set = 0; set < k_num_register_sets; ++set)
+        if (IsRegisterSetAvailable(set))
+            ++sets;
+
+    return sets;
 }
 
 const RegisterSet *
-RegisterContext_x86_64::GetRegisterSet(uint32_t set)
+RegisterContext_x86_64::GetRegisterSet(size_t set)
 {
-    if (set < k_num_register_sets)
+    if (IsRegisterSetAvailable(set))
         return &g_reg_sets[set];
     else
         return NULL;
@@ -485,7 +590,7 @@ RegisterContext_x86_64::GetRegisterIndex
     unsigned reg;
     for (reg = 0; reg < k_num_registers; reg++)
     {
-        if (g_register_infos[reg].byte_offset == offset)
+        if (GetRegisterInfo()[reg].byte_offset == offset)
             break;
     }
     assert(reg < k_num_registers && "Invalid register offset.");
@@ -496,56 +601,322 @@ const char *
 RegisterContext_x86_64::GetRegisterName(unsigned reg)
 {
     assert(reg < k_num_registers && "Invalid register offset.");
-    return g_register_infos[reg].name;
+    return GetRegisterInfo()[reg].name;
+}
+
+lldb::ByteOrder
+RegisterContext_x86_64::GetByteOrder()
+{
+    // Get the target process whose privileged thread was used for the register read.
+    lldb::ByteOrder byte_order = eByteOrderInvalid;
+    Process *process = CalculateProcess().get();
+
+    if (process)
+        byte_order = process->GetByteOrder();
+    return byte_order;
+}
+
+// Parse ymm registers and into xmm.bytes and ymmh.bytes.
+bool RegisterContext_x86_64::CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order)
+{
+    if (!IsAVX(reg))
+        return false;
+
+    if (byte_order == eByteOrderLittle) {
+      ::memcpy(m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes,
+               m_ymm_set.ymm[reg - fpu_ymm0].bytes,
+               sizeof(RegisterContext_x86_64::XMMReg));
+      ::memcpy(m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes,
+               m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg),
+               sizeof(RegisterContext_x86_64::YMMHReg));
+      return true;
+    }
+
+    if (byte_order == eByteOrderBig) {
+      ::memcpy(m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes,
+               m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg),
+               sizeof(RegisterContext_x86_64::XMMReg));
+      ::memcpy(m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes,
+               m_ymm_set.ymm[reg - fpu_ymm0].bytes,
+               sizeof(RegisterContext_x86_64::YMMHReg));
+      return true;
+    }
+    return false; // unsupported or invalid byte order
 }
 
+// Concatenate xmm.bytes with ymmh.bytes
+bool RegisterContext_x86_64::CopyXSTATEtoYMM(uint32_t reg, lldb::ByteOrder byte_order)
+{
+    if (!IsAVX(reg))
+        return false;
+
+    if (byte_order == eByteOrderLittle) {
+      ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes,
+               m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes,
+               sizeof(RegisterContext_x86_64::XMMReg));
+      ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg),
+               m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes,
+               sizeof(RegisterContext_x86_64::YMMHReg));
+      return true;
+    }
+    if (byte_order == eByteOrderBig) {
+      ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg),
+               m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes,
+               sizeof(RegisterContext_x86_64::XMMReg));
+      ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes,
+               m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes,
+               sizeof(RegisterContext_x86_64::YMMHReg));
+      return true;
+    }
+    return false; // unsupported or invalid byte order
+}
+
+bool
+RegisterContext_x86_64::IsRegisterSetAvailable(size_t set_index)
+{
+    // Note: Extended register sets are assumed to be at the end of g_reg_sets...
+    size_t num_sets = k_num_register_sets - k_num_extended_register_sets;
+    if (m_fpr_type == eXSAVE) // ...and to start with AVX registers.
+        ++num_sets;
+
+    return (set_index < num_sets);
+}   
+
 bool
-RegisterContext_x86_64::ReadRegister(const RegisterInfo *reg_info,
-                                          RegisterValue &value)
+RegisterContext_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
 {
+    if (!reg_info)
+        return false;
+
     const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-    ProcessMonitor &monitor = GetMonitor();
-    return monitor.ReadRegisterValue(GetRegOffset(reg), GetRegSize(reg), value);
+
+    if (IsFPR(reg, m_fpr_type)) {
+        if (!ReadFPR())
+            return false;
+    }
+    else {
+        ProcessMonitor &monitor = GetMonitor();
+        bool success = monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg),
+                                                 GetRegisterName(reg), GetRegisterSize(reg), value);
+
+        // If an i386 register should be parsed from an x86_64 register...
+        if (success && reg >= k_first_i386 && reg <= k_last_i386)
+            if (value.GetByteSize() > reg_info->byte_size)
+                value.SetType(reg_info); // ...use the type specified by reg_info rather than the uint64_t default
+        return success; 
+    }
+
+    if (reg_info->encoding == eEncodingVector) {
+        ByteOrder byte_order = GetByteOrder();
+
+        if (byte_order != ByteOrder::eByteOrderInvalid) {
+            if (reg >= fpu_stmm0 && reg <= fpu_stmm7) {
+               value.SetBytes(m_fpr.xstate.fxsave.stmm[reg - fpu_stmm0].bytes, reg_info->byte_size, byte_order);
+            }
+            if (reg >= fpu_xmm0 && reg <= fpu_xmm15) {
+                value.SetBytes(m_fpr.xstate.fxsave.xmm[reg - fpu_xmm0].bytes, reg_info->byte_size, byte_order);
+            }
+            if (reg >= fpu_ymm0 && reg <= fpu_ymm15) {
+                // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes
+                if (m_fpr_type == eXSAVE && CopyXSTATEtoYMM(reg, byte_order))
+                    value.SetBytes(m_ymm_set.ymm[reg - fpu_ymm0].bytes, reg_info->byte_size, byte_order);
+                else
+                    return false;
+            }
+            return value.GetType() == RegisterValue::eTypeBytes;
+        }
+        return false;
+    }
+
+    // Note that lldb uses slightly different naming conventions from sys/user.h
+    switch (reg)
+    {
+    default:
+        return false;
+    case fpu_dp:
+        value = m_fpr.xstate.fxsave.dp;
+        break;
+    case fpu_fcw:
+        value = m_fpr.xstate.fxsave.fcw;
+        break;
+    case fpu_fsw:
+        value = m_fpr.xstate.fxsave.fsw;
+        break;
+    case fpu_ip:
+        value = m_fpr.xstate.fxsave.ip;
+        break;
+    case fpu_fop:
+        value = m_fpr.xstate.fxsave.fop;
+        break;
+    case fpu_ftw:
+        value = m_fpr.xstate.fxsave.ftw;
+        break;
+    case fpu_mxcsr:
+        value = m_fpr.xstate.fxsave.mxcsr;
+        break;
+    case fpu_mxcsrmask:
+        value = m_fpr.xstate.fxsave.mxcsrmask;
+        break;
+    }
+    return true;
 }
 
 bool
 RegisterContext_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp)
 {
+    bool success = false;
     data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
     if (data_sp && ReadGPR () && ReadFPR ())
     {
         uint8_t *dst = data_sp->GetBytes();
-        ::memcpy (dst, &user.regs, sizeof(user.regs));
-        dst += sizeof(user.regs);
+        success = dst != 0;
 
-        ::memcpy (dst, &user.i387, sizeof(user.i387));
-        return true;
+        if (success) {
+            ::memcpy (dst, &m_gpr, GetGPRSize());
+            dst += GetGPRSize();
+        }
+        if (m_fpr_type == eFXSAVE)
+            ::memcpy (dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
+        
+        if (m_fpr_type == eXSAVE) {
+            ByteOrder byte_order = GetByteOrder();
+
+            // Assemble the YMM register content from the register halves.
+            for (uint32_t reg = fpu_ymm0; success && reg <= fpu_ymm15; ++reg)
+                success = CopyXSTATEtoYMM(reg, byte_order);
+
+            if (success) {
+                // Copy the extended register state including the assembled ymm registers.
+                ::memcpy (dst, &m_fpr, sizeof(m_fpr));
+            }
+        }
     }
-    return false;
+    return success;
 }
 
 bool
 RegisterContext_x86_64::WriteRegister(const lldb_private::RegisterInfo *reg_info,
-                                           const lldb_private::RegisterValue &value)
+                                      const lldb_private::RegisterValue &value)
 {
     const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-    ProcessMonitor &monitor = GetMonitor();
-    return monitor.WriteRegisterValue(GetRegOffset(reg), value);
+    if (IsGPR(reg)) {
+        ProcessMonitor &monitor = GetMonitor();
+        return monitor.WriteRegisterValue(m_thread.GetID(), GetRegisterOffset(reg), GetRegisterName(reg), value);
+    }
+
+    if (IsFPR(reg, m_fpr_type)) {
+        switch (reg)
+        {
+        default:
+            if (reg_info->encoding != eEncodingVector)
+                return false;
+
+            if (reg >= fpu_stmm0 && reg <= fpu_stmm7)
+               ::memcpy (m_fpr.xstate.fxsave.stmm[reg - fpu_stmm0].bytes, value.GetBytes(), value.GetByteSize());
+            
+            if (reg >= fpu_xmm0 && reg <= fpu_xmm15)
+               ::memcpy (m_fpr.xstate.fxsave.xmm[reg - fpu_xmm0].bytes, value.GetBytes(), value.GetByteSize());
+            
+            if (reg >= fpu_ymm0 && reg <= fpu_ymm15) {
+               if (m_fpr_type != eXSAVE)
+                   return false; // the target processor does not support AVX
+
+               // Store ymm register content, and split into the register halves in xmm.bytes and ymmh.bytes
+               ::memcpy (m_ymm_set.ymm[reg - fpu_ymm0].bytes, value.GetBytes(), value.GetByteSize());
+               if (false == CopyYMMtoXSTATE(reg, GetByteOrder()))
+                   return false;
+            }
+            break;
+        case fpu_dp:
+            m_fpr.xstate.fxsave.dp = value.GetAsUInt64();
+            break;
+        case fpu_fcw:
+            m_fpr.xstate.fxsave.fcw = value.GetAsUInt16();
+            break;
+        case fpu_fsw:
+            m_fpr.xstate.fxsave.fsw = value.GetAsUInt16();
+            break;
+        case fpu_ip:
+            m_fpr.xstate.fxsave.ip = value.GetAsUInt64();
+            break;
+        case fpu_fop:
+            m_fpr.xstate.fxsave.fop = value.GetAsUInt16();
+            break;
+        case fpu_ftw:
+            m_fpr.xstate.fxsave.ftw = value.GetAsUInt16();
+            break;
+        case fpu_mxcsr:
+            m_fpr.xstate.fxsave.mxcsr = value.GetAsUInt32();
+            break;
+        case fpu_mxcsrmask:
+            m_fpr.xstate.fxsave.mxcsrmask = value.GetAsUInt32();
+            break;
+        }
+        if (WriteFPR()) {
+            if (IsAVX(reg))
+                return CopyYMMtoXSTATE(reg, GetByteOrder());
+            return true;
+        }
+    }
+    return false;
 }
 
 bool
 RegisterContext_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp)
 {
+    bool success = false;
     if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
     {
-        const uint8_t *src = data_sp->GetBytes();
-        ::memcpy (&user.regs, src, sizeof(user.regs));
-        src += sizeof(user.regs);
-
-        ::memcpy (&user.i387, src, sizeof(user.i387));
-        return WriteGPR() & WriteFPR();
+        uint8_t *src = data_sp->GetBytes();
+        if (src) {
+            ::memcpy (&m_gpr, src, GetGPRSize());
+
+            if (WriteGPR()) {
+                src += GetGPRSize();
+                if (m_fpr_type == eFXSAVE)
+                    ::memcpy (&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave));
+                if (m_fpr_type == eXSAVE)
+                    ::memcpy (&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave));
+
+                success = WriteFPR();
+                if (success) {
+                    success = true;
+
+                    if (m_fpr_type == eXSAVE) {
+                        ByteOrder byte_order = GetByteOrder();
+
+                        // Parse the YMM register content from the register halves.
+                        for (uint32_t reg = fpu_ymm0; success && reg <= fpu_ymm15; ++reg)
+                            success = CopyYMMtoXSTATE(reg, byte_order);
+                    }
+                }
+            }
+        }
     }
-    return false;
+    return success;
+}
+
+bool
+RegisterContext_x86_64::ReadRegister(const unsigned reg,
+                                     RegisterValue &value)
+{
+    ProcessMonitor &monitor = GetMonitor();
+    return monitor.ReadRegisterValue(m_thread.GetID(),
+                                     GetRegisterOffset(reg),
+                                     GetRegisterName(reg),
+                                     GetRegisterSize(reg),
+                                     value);
+}
+
+bool
+RegisterContext_x86_64::WriteRegister(const unsigned reg,
+                                      const RegisterValue &value)
+{
+    ProcessMonitor &monitor = GetMonitor();
+    return monitor.WriteRegisterValue(m_thread.GetID(),
+                                      GetRegisterOffset(reg),
+                                      GetRegisterName(reg),
+                                      value);
 }
 
 bool
@@ -565,141 +936,500 @@ uint32_t
 RegisterContext_x86_64::ConvertRegisterKindToRegisterNumber(uint32_t kind,
                                                                  uint32_t num)
 {
-    if (kind == eRegisterKindGeneric)
+    const Process *process = CalculateProcess().get();
+    if (process)
     {
-        switch (num)
+        const ArchSpec arch = process->GetTarget().GetArchitecture();;
+        switch (arch.GetCore())
         {
-        case LLDB_REGNUM_GENERIC_PC:    return gpr_rip;
-        case LLDB_REGNUM_GENERIC_SP:    return gpr_rsp;
-        case LLDB_REGNUM_GENERIC_FP:    return gpr_rbp;
-        case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags;
-        case LLDB_REGNUM_GENERIC_RA:
         default:
-            return LLDB_INVALID_REGNUM;
+            assert(false && "CPU type not supported!");
+            break;
+
+        case ArchSpec::eCore_x86_32_i386:
+        case ArchSpec::eCore_x86_32_i486:
+        case ArchSpec::eCore_x86_32_i486sx:
+        {
+            if (kind == eRegisterKindGeneric)
+            {
+                switch (num)
+                {
+                case LLDB_REGNUM_GENERIC_PC:    return gpr_eip;
+                case LLDB_REGNUM_GENERIC_SP:    return gpr_esp;
+                case LLDB_REGNUM_GENERIC_FP:    return gpr_ebp;
+                case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags;
+                case LLDB_REGNUM_GENERIC_RA:
+                default:
+                    return LLDB_INVALID_REGNUM;
+                }
+            }
+
+            if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
+            {
+                switch (num)
+                {
+                case dwarf_eax:  return gpr_eax;
+                case dwarf_edx:  return gpr_edx;
+                case dwarf_ecx:  return gpr_ecx;
+                case dwarf_ebx:  return gpr_ebx;
+                case dwarf_esi:  return gpr_esi;
+                case dwarf_edi:  return gpr_edi;
+                case dwarf_ebp:  return gpr_ebp;
+                case dwarf_esp:  return gpr_esp;
+                case dwarf_eip:  return gpr_eip;
+                case dwarf_xmm0: return fpu_xmm0;
+                case dwarf_xmm1: return fpu_xmm1;
+                case dwarf_xmm2: return fpu_xmm2;
+                case dwarf_xmm3: return fpu_xmm3;
+                case dwarf_xmm4: return fpu_xmm4;
+                case dwarf_xmm5: return fpu_xmm5;
+                case dwarf_xmm6: return fpu_xmm6;
+                case dwarf_xmm7: return fpu_xmm7;
+                case dwarf_stmm0: return fpu_stmm0;
+                case dwarf_stmm1: return fpu_stmm1;
+                case dwarf_stmm2: return fpu_stmm2;
+                case dwarf_stmm3: return fpu_stmm3;
+                case dwarf_stmm4: return fpu_stmm4;
+                case dwarf_stmm5: return fpu_stmm5;
+                case dwarf_stmm6: return fpu_stmm6;
+                case dwarf_stmm7: return fpu_stmm7;
+                default:
+                    return LLDB_INVALID_REGNUM;
+                }
+            }
+
+            if (kind == eRegisterKindGDB)
+            {
+                switch (num)
+                {
+                case gdb_eax     : return gpr_eax;
+                case gdb_ebx     : return gpr_ebx;
+                case gdb_ecx     : return gpr_ecx;
+                case gdb_edx     : return gpr_edx;
+                case gdb_esi     : return gpr_esi;
+                case gdb_edi     : return gpr_edi;
+                case gdb_ebp     : return gpr_ebp;
+                case gdb_esp     : return gpr_esp;
+                case gdb_eip     : return gpr_eip;
+                case gdb_eflags  : return gpr_eflags;
+                case gdb_cs      : return gpr_cs;
+                case gdb_ss      : return gpr_ss;
+                case gdb_ds      : return gpr_ds;
+                case gdb_es      : return gpr_es;
+                case gdb_fs      : return gpr_fs;
+                case gdb_gs      : return gpr_gs;
+                case gdb_stmm0   : return fpu_stmm0;
+                case gdb_stmm1   : return fpu_stmm1;
+                case gdb_stmm2   : return fpu_stmm2;
+                case gdb_stmm3   : return fpu_stmm3;
+                case gdb_stmm4   : return fpu_stmm4;
+                case gdb_stmm5   : return fpu_stmm5;
+                case gdb_stmm6   : return fpu_stmm6;
+                case gdb_stmm7   : return fpu_stmm7;
+                case gdb_fcw     : return fpu_fcw;
+                case gdb_fsw     : return fpu_fsw;
+                case gdb_ftw     : return fpu_ftw;
+                case gdb_fpu_cs  : return fpu_cs;
+                case gdb_ip      : return fpu_ip;
+                case gdb_fpu_ds  : return fpu_ds; //fpu_fos
+                case gdb_dp      : return fpu_dp; //fpu_foo
+                case gdb_fop     : return fpu_fop;
+                case gdb_xmm0    : return fpu_xmm0;
+                case gdb_xmm1    : return fpu_xmm1;
+                case gdb_xmm2    : return fpu_xmm2;
+                case gdb_xmm3    : return fpu_xmm3;
+                case gdb_xmm4    : return fpu_xmm4;
+                case gdb_xmm5    : return fpu_xmm5;
+                case gdb_xmm6    : return fpu_xmm6;
+                case gdb_xmm7    : return fpu_xmm7;
+                case gdb_mxcsr   : return fpu_mxcsr;
+                default:
+                    return LLDB_INVALID_REGNUM;
+                }
+            }
+            else if (kind == eRegisterKindLLDB)
+            {
+                return num;
+            }
+
+            break;
+        }
+
+        case ArchSpec::eCore_x86_64_x86_64:
+        {
+            if (kind == eRegisterKindGeneric)
+            {
+                switch (num)
+                {
+                case LLDB_REGNUM_GENERIC_PC:    return gpr_rip;
+                case LLDB_REGNUM_GENERIC_SP:    return gpr_rsp;
+                case LLDB_REGNUM_GENERIC_FP:    return gpr_rbp;
+                case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags;
+                case LLDB_REGNUM_GENERIC_RA:
+                default:
+                    return LLDB_INVALID_REGNUM;
+                }
+            }
+
+            if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
+            {
+                switch (num)
+                {
+                case gcc_dwarf_gpr_rax:  return gpr_rax;
+                case gcc_dwarf_gpr_rdx:  return gpr_rdx;
+                case gcc_dwarf_gpr_rcx:  return gpr_rcx;
+                case gcc_dwarf_gpr_rbx:  return gpr_rbx;
+                case gcc_dwarf_gpr_rsi:  return gpr_rsi;
+                case gcc_dwarf_gpr_rdi:  return gpr_rdi;
+                case gcc_dwarf_gpr_rbp:  return gpr_rbp;
+                case gcc_dwarf_gpr_rsp:  return gpr_rsp;
+                case gcc_dwarf_gpr_r8:   return gpr_r8;
+                case gcc_dwarf_gpr_r9:   return gpr_r9;
+                case gcc_dwarf_gpr_r10:  return gpr_r10;
+                case gcc_dwarf_gpr_r11:  return gpr_r11;
+                case gcc_dwarf_gpr_r12:  return gpr_r12;
+                case gcc_dwarf_gpr_r13:  return gpr_r13;
+                case gcc_dwarf_gpr_r14:  return gpr_r14;
+                case gcc_dwarf_gpr_r15:  return gpr_r15;
+                case gcc_dwarf_gpr_rip:  return gpr_rip;
+                case gcc_dwarf_fpu_xmm0: return fpu_xmm0;
+                case gcc_dwarf_fpu_xmm1: return fpu_xmm1;
+                case gcc_dwarf_fpu_xmm2: return fpu_xmm2;
+                case gcc_dwarf_fpu_xmm3: return fpu_xmm3;
+                case gcc_dwarf_fpu_xmm4: return fpu_xmm4;
+                case gcc_dwarf_fpu_xmm5: return fpu_xmm5;
+                case gcc_dwarf_fpu_xmm6: return fpu_xmm6;
+                case gcc_dwarf_fpu_xmm7: return fpu_xmm7;
+                case gcc_dwarf_fpu_xmm8: return fpu_xmm8;
+                case gcc_dwarf_fpu_xmm9: return fpu_xmm9;
+                case gcc_dwarf_fpu_xmm10: return fpu_xmm10;
+                case gcc_dwarf_fpu_xmm11: return fpu_xmm11;
+                case gcc_dwarf_fpu_xmm12: return fpu_xmm12;
+                case gcc_dwarf_fpu_xmm13: return fpu_xmm13;
+                case gcc_dwarf_fpu_xmm14: return fpu_xmm14;
+                case gcc_dwarf_fpu_xmm15: return fpu_xmm15;
+                case gcc_dwarf_fpu_stmm0: return fpu_stmm0;
+                case gcc_dwarf_fpu_stmm1: return fpu_stmm1;
+                case gcc_dwarf_fpu_stmm2: return fpu_stmm2;
+                case gcc_dwarf_fpu_stmm3: return fpu_stmm3;
+                case gcc_dwarf_fpu_stmm4: return fpu_stmm4;
+                case gcc_dwarf_fpu_stmm5: return fpu_stmm5;
+                case gcc_dwarf_fpu_stmm6: return fpu_stmm6;
+                case gcc_dwarf_fpu_stmm7: return fpu_stmm7;
+                case gcc_dwarf_fpu_ymm0: return fpu_ymm0;
+                case gcc_dwarf_fpu_ymm1: return fpu_ymm1;
+                case gcc_dwarf_fpu_ymm2: return fpu_ymm2;
+                case gcc_dwarf_fpu_ymm3: return fpu_ymm3;
+                case gcc_dwarf_fpu_ymm4: return fpu_ymm4;
+                case gcc_dwarf_fpu_ymm5: return fpu_ymm5;
+                case gcc_dwarf_fpu_ymm6: return fpu_ymm6;
+                case gcc_dwarf_fpu_ymm7: return fpu_ymm7;
+                case gcc_dwarf_fpu_ymm8: return fpu_ymm8;
+                case gcc_dwarf_fpu_ymm9: return fpu_ymm9;
+                case gcc_dwarf_fpu_ymm10: return fpu_ymm10;
+                case gcc_dwarf_fpu_ymm11: return fpu_ymm11;
+                case gcc_dwarf_fpu_ymm12: return fpu_ymm12;
+                case gcc_dwarf_fpu_ymm13: return fpu_ymm13;
+                case gcc_dwarf_fpu_ymm14: return fpu_ymm14;
+                case gcc_dwarf_fpu_ymm15: return fpu_ymm15;
+                default:
+                    return LLDB_INVALID_REGNUM;
+                }
+            }
+
+            if (kind == eRegisterKindGDB)
+            {
+                switch (num)
+                {
+                case gdb_gpr_rax     : return gpr_rax;
+                case gdb_gpr_rbx     : return gpr_rbx;
+                case gdb_gpr_rcx     : return gpr_rcx;
+                case gdb_gpr_rdx     : return gpr_rdx;
+                case gdb_gpr_rsi     : return gpr_rsi;
+                case gdb_gpr_rdi     : return gpr_rdi;
+                case gdb_gpr_rbp     : return gpr_rbp;
+                case gdb_gpr_rsp     : return gpr_rsp;
+                case gdb_gpr_r8      : return gpr_r8;
+                case gdb_gpr_r9      : return gpr_r9;
+                case gdb_gpr_r10     : return gpr_r10;
+                case gdb_gpr_r11     : return gpr_r11;
+                case gdb_gpr_r12     : return gpr_r12;
+                case gdb_gpr_r13     : return gpr_r13;
+                case gdb_gpr_r14     : return gpr_r14;
+                case gdb_gpr_r15     : return gpr_r15;
+                case gdb_gpr_rip     : return gpr_rip;
+                case gdb_gpr_rflags  : return gpr_rflags;
+                case gdb_gpr_cs      : return gpr_cs;
+                case gdb_gpr_ss      : return gpr_ss;
+                case gdb_gpr_ds      : return gpr_ds;
+                case gdb_gpr_es      : return gpr_es;
+                case gdb_gpr_fs      : return gpr_fs;
+                case gdb_gpr_gs      : return gpr_gs;
+                case gdb_fpu_stmm0   : return fpu_stmm0;
+                case gdb_fpu_stmm1   : return fpu_stmm1;
+                case gdb_fpu_stmm2   : return fpu_stmm2;
+                case gdb_fpu_stmm3   : return fpu_stmm3;
+                case gdb_fpu_stmm4   : return fpu_stmm4;
+                case gdb_fpu_stmm5   : return fpu_stmm5;
+                case gdb_fpu_stmm6   : return fpu_stmm6;
+                case gdb_fpu_stmm7   : return fpu_stmm7;
+                case gdb_fpu_fcw     : return fpu_fcw;
+                case gdb_fpu_fsw     : return fpu_fsw;
+                case gdb_fpu_ftw     : return fpu_ftw;
+                case gdb_fpu_cs_64   : return fpu_cs;
+                case gdb_fpu_ip      : return fpu_ip;
+                case gdb_fpu_ds_64   : return fpu_ds;
+                case gdb_fpu_dp      : return fpu_dp;
+                case gdb_fpu_fop     : return fpu_fop;
+                case gdb_fpu_xmm0    : return fpu_xmm0;
+                case gdb_fpu_xmm1    : return fpu_xmm1;
+                case gdb_fpu_xmm2    : return fpu_xmm2;
+                case gdb_fpu_xmm3    : return fpu_xmm3;
+                case gdb_fpu_xmm4    : return fpu_xmm4;
+                case gdb_fpu_xmm5    : return fpu_xmm5;
+                case gdb_fpu_xmm6    : return fpu_xmm6;
+                case gdb_fpu_xmm7    : return fpu_xmm7;
+                case gdb_fpu_xmm8    : return fpu_xmm8;
+                case gdb_fpu_xmm9    : return fpu_xmm9;
+                case gdb_fpu_xmm10   : return fpu_xmm10;
+                case gdb_fpu_xmm11   : return fpu_xmm11;
+                case gdb_fpu_xmm12   : return fpu_xmm12;
+                case gdb_fpu_xmm13   : return fpu_xmm13;
+                case gdb_fpu_xmm14   : return fpu_xmm14;
+                case gdb_fpu_xmm15   : return fpu_xmm15;
+                case gdb_fpu_mxcsr   : return fpu_mxcsr;
+                case gdb_fpu_ymm0    : return fpu_ymm0;
+                case gdb_fpu_ymm1    : return fpu_ymm1;
+                case gdb_fpu_ymm2    : return fpu_ymm2;
+                case gdb_fpu_ymm3    : return fpu_ymm3;
+                case gdb_fpu_ymm4    : return fpu_ymm4;
+                case gdb_fpu_ymm5    : return fpu_ymm5;
+                case gdb_fpu_ymm6    : return fpu_ymm6;
+                case gdb_fpu_ymm7    : return fpu_ymm7;
+                case gdb_fpu_ymm8    : return fpu_ymm8;
+                case gdb_fpu_ymm9    : return fpu_ymm9;
+                case gdb_fpu_ymm10   : return fpu_ymm10;
+                case gdb_fpu_ymm11   : return fpu_ymm11;
+                case gdb_fpu_ymm12   : return fpu_ymm12;
+                case gdb_fpu_ymm13   : return fpu_ymm13;
+                case gdb_fpu_ymm14   : return fpu_ymm14;
+                case gdb_fpu_ymm15   : return fpu_ymm15;
+                default:
+                    return LLDB_INVALID_REGNUM;
+                }
+            }
+            else if (kind == eRegisterKindLLDB)
+            {
+                return num;
+            }
+        }
+        }
+    }
+
+    return LLDB_INVALID_REGNUM;
+}
+
+uint32_t
+RegisterContext_x86_64::NumSupportedHardwareWatchpoints()
+{
+    // Available debug address registers: dr0, dr1, dr2, dr3
+    return 4;
+}
+
+bool
+RegisterContext_x86_64::IsWatchpointVacant(uint32_t hw_index)
+{
+    bool is_vacant = false;
+    RegisterValue value;
+
+    assert(hw_index < NumSupportedHardwareWatchpoints());
+
+    if (ReadRegister(dr7, value))
+    {
+        uint64_t val = value.GetAsUInt64();
+        is_vacant = (val & (3 << 2*hw_index)) == 0;
+    }
+
+    return is_vacant;
+}
+
+static uint32_t
+size_and_rw_bits(size_t size, bool read, bool write)
+{
+    uint32_t rw;
+    if (read) {
+        rw = 0x3; // READ or READ/WRITE
+    } else if (write) {
+        rw = 0x1; // WRITE
+    } else {
+        assert(0 && "read and write cannot both be false");
+    }
+
+    switch (size) {
+    case 1:
+        return rw;
+    case 2:
+        return (0x1 << 2) | rw;
+    case 4:
+        return (0x3 << 2) | rw;
+    case 8:
+        return (0x2 << 2) | rw;
+    default:
+        assert(0 && "invalid size, must be one of 1, 2, 4, or 8");
+    }
+}
+
+uint32_t
+RegisterContext_x86_64::SetHardwareWatchpoint(addr_t addr, size_t size,
+                                              bool read, bool write)
+{
+    const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
+    uint32_t hw_index;
+
+    for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index)
+    {
+        if (IsWatchpointVacant(hw_index))
+            return SetHardwareWatchpointWithIndex(addr, size,
+                                                  read, write,
+                                                  hw_index);
+    }
+
+    return LLDB_INVALID_INDEX32;
+}
+
+bool
+RegisterContext_x86_64::SetHardwareWatchpointWithIndex(addr_t addr, size_t size,
+                                                       bool read, bool write,
+                                                       uint32_t hw_index)
+{
+    const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
+
+    if (num_hw_watchpoints == 0 || hw_index >= num_hw_watchpoints)
+        return false;
+
+    if (!(size == 1 || size == 2 || size == 4 || size == 8))
+        return false;
+
+    if (read == false && write == false)
+        return false;
+
+    if (m_watchpoints_initialized == false)
+    {
+        // Reset the debug status and debug control registers
+        RegisterValue zero_bits = RegisterValue(uint64_t(0));
+        if (!WriteRegister(dr6, zero_bits) || !WriteRegister(dr7, zero_bits))
+            return false;
+        m_watchpoints_initialized = true;
+    }
+
+    if (!IsWatchpointVacant(hw_index))
+        return false;
+
+    // Set both dr7 (debug control register) and dri (debug address register).
+
+    // dr7{7-0} encodes the local/gloabl enable bits:
+    //  global enable --. .-- local enable
+    //                  | |
+    //                  v v
+    //      dr0 -> bits{1-0}
+    //      dr1 -> bits{3-2}
+    //      dr2 -> bits{5-4}
+    //      dr3 -> bits{7-6}
+    //
+    // dr7{31-16} encodes the rw/len bits:
+    //  b_x+3, b_x+2, b_x+1, b_x
+    //      where bits{x+1, x} => rw
+    //            0b00: execute, 0b01: write, 0b11: read-or-write,
+    //            0b10: io read-or-write (unused)
+    //      and bits{x+3, x+2} => len
+    //            0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte
+    //
+    //      dr0 -> bits{19-16}
+    //      dr1 -> bits{23-20}
+    //      dr2 -> bits{27-24}
+    //      dr3 -> bits{31-28}
+    if (hw_index < num_hw_watchpoints)
+    {
+        RegisterValue current_dr7_bits;
+
+        if (ReadRegister(dr7, current_dr7_bits))
+        {
+            uint64_t new_dr7_bits = current_dr7_bits.GetAsUInt64() |
+                                    (1 << (2*hw_index) |
+                                    size_and_rw_bits(size, read, write) <<
+                                    (16+4*hw_index));
+
+            if (WriteRegister(dr0 + hw_index, RegisterValue(addr)) &&
+                WriteRegister(dr7, RegisterValue(new_dr7_bits)))
+                return true;
         }
     }
 
-    if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
+    return false;
+}
+
+bool
+RegisterContext_x86_64::ClearHardwareWatchpoint(uint32_t hw_index)
+{
+    if (hw_index < NumSupportedHardwareWatchpoints())
     {
-        switch (num)
+        RegisterValue current_dr7_bits;
+
+        if (ReadRegister(dr7, current_dr7_bits))
         {
-        case gcc_dwarf_gpr_rax:  return gpr_rax;
-        case gcc_dwarf_gpr_rdx:  return gpr_rdx;
-        case gcc_dwarf_gpr_rcx:  return gpr_rcx;
-        case gcc_dwarf_gpr_rbx:  return gpr_rbx;
-        case gcc_dwarf_gpr_rsi:  return gpr_rsi;
-        case gcc_dwarf_gpr_rdi:  return gpr_rdi;
-        case gcc_dwarf_gpr_rbp:  return gpr_rbp;
-        case gcc_dwarf_gpr_rsp:  return gpr_rsp;
-        case gcc_dwarf_gpr_r8:   return gpr_r8;
-        case gcc_dwarf_gpr_r9:   return gpr_r9;
-        case gcc_dwarf_gpr_r10:  return gpr_r10;
-        case gcc_dwarf_gpr_r11:  return gpr_r11;
-        case gcc_dwarf_gpr_r12:  return gpr_r12;
-        case gcc_dwarf_gpr_r13:  return gpr_r13;
-        case gcc_dwarf_gpr_r14:  return gpr_r14;
-        case gcc_dwarf_gpr_r15:  return gpr_r15;
-        case gcc_dwarf_gpr_rip:  return gpr_rip;
-        case gcc_dwarf_fpu_xmm0: return fpu_xmm0;
-        case gcc_dwarf_fpu_xmm1: return fpu_xmm1;
-        case gcc_dwarf_fpu_xmm2: return fpu_xmm2;
-        case gcc_dwarf_fpu_xmm3: return fpu_xmm3;
-        case gcc_dwarf_fpu_xmm4: return fpu_xmm4;
-        case gcc_dwarf_fpu_xmm5: return fpu_xmm5;
-        case gcc_dwarf_fpu_xmm6: return fpu_xmm6;
-        case gcc_dwarf_fpu_xmm7: return fpu_xmm7;
-        case gcc_dwarf_fpu_xmm8: return fpu_xmm8;
-        case gcc_dwarf_fpu_xmm9: return fpu_xmm9;
-        case gcc_dwarf_fpu_xmm10: return fpu_xmm10;
-        case gcc_dwarf_fpu_xmm11: return fpu_xmm11;
-        case gcc_dwarf_fpu_xmm12: return fpu_xmm12;
-        case gcc_dwarf_fpu_xmm13: return fpu_xmm13;
-        case gcc_dwarf_fpu_xmm14: return fpu_xmm14;
-        case gcc_dwarf_fpu_xmm15: return fpu_xmm15;
-        case gcc_dwarf_fpu_stmm0: return fpu_stmm0;
-        case gcc_dwarf_fpu_stmm1: return fpu_stmm1;
-        case gcc_dwarf_fpu_stmm2: return fpu_stmm2;
-        case gcc_dwarf_fpu_stmm3: return fpu_stmm3;
-        case gcc_dwarf_fpu_stmm4: return fpu_stmm4;
-        case gcc_dwarf_fpu_stmm5: return fpu_stmm5;
-        case gcc_dwarf_fpu_stmm6: return fpu_stmm6;
-        case gcc_dwarf_fpu_stmm7: return fpu_stmm7;
-        default:
-            return LLDB_INVALID_REGNUM;
+            uint64_t new_dr7_bits = current_dr7_bits.GetAsUInt64() & ~(3 << (2*hw_index));
+
+            if (WriteRegister(dr7, RegisterValue(new_dr7_bits)))
+                return true;
         }
     }
 
-    if (kind == eRegisterKindGDB)
+    return false;
+}
+
+bool
+RegisterContext_x86_64::IsWatchpointHit(uint32_t hw_index)
+{
+    bool is_hit = false;
+
+    if (hw_index < NumSupportedHardwareWatchpoints())
     {
-        switch (num)
+        RegisterValue value;
+
+        if (ReadRegister(dr6, value))
         {
-        case gdb_gpr_rax     : return gpr_rax;
-        case gdb_gpr_rbx     : return gpr_rbx;
-        case gdb_gpr_rcx     : return gpr_rcx;
-        case gdb_gpr_rdx     : return gpr_rdx;
-        case gdb_gpr_rsi     : return gpr_rsi;
-        case gdb_gpr_rdi     : return gpr_rdi;
-        case gdb_gpr_rbp     : return gpr_rbp;
-        case gdb_gpr_rsp     : return gpr_rsp;
-        case gdb_gpr_r8      : return gpr_r8;
-        case gdb_gpr_r9      : return gpr_r9;
-        case gdb_gpr_r10     : return gpr_r10;
-        case gdb_gpr_r11     : return gpr_r11;
-        case gdb_gpr_r12     : return gpr_r12;
-        case gdb_gpr_r13     : return gpr_r13;
-        case gdb_gpr_r14     : return gpr_r14;
-        case gdb_gpr_r15     : return gpr_r15;
-        case gdb_gpr_rip     : return gpr_rip;
-        case gdb_gpr_rflags  : return gpr_rflags;
-        case gdb_gpr_cs      : return gpr_cs;
-        case gdb_gpr_ss      : return gpr_ss;
-        case gdb_gpr_ds      : return gpr_ds;
-        case gdb_gpr_es      : return gpr_es;
-        case gdb_gpr_fs      : return gpr_fs;
-        case gdb_gpr_gs      : return gpr_gs;
-        case gdb_fpu_stmm0   : return fpu_stmm0;
-        case gdb_fpu_stmm1   : return fpu_stmm1;
-        case gdb_fpu_stmm2   : return fpu_stmm2;
-        case gdb_fpu_stmm3   : return fpu_stmm3;
-        case gdb_fpu_stmm4   : return fpu_stmm4;
-        case gdb_fpu_stmm5   : return fpu_stmm5;
-        case gdb_fpu_stmm6   : return fpu_stmm6;
-        case gdb_fpu_stmm7   : return fpu_stmm7;
-        case gdb_fpu_fcw     : return fpu_fcw;
-        case gdb_fpu_fsw     : return fpu_fsw;
-        case gdb_fpu_ftw     : return fpu_ftw;
-        case gdb_fpu_cs      : return fpu_cs;
-        case gdb_fpu_ip      : return fpu_ip;
-        case gdb_fpu_ds      : return fpu_ds;
-        case gdb_fpu_dp      : return fpu_dp;
-        case gdb_fpu_fop     : return fpu_fop;
-        case gdb_fpu_xmm0    : return fpu_xmm0;
-        case gdb_fpu_xmm1    : return fpu_xmm1;
-        case gdb_fpu_xmm2    : return fpu_xmm2;
-        case gdb_fpu_xmm3    : return fpu_xmm3;
-        case gdb_fpu_xmm4    : return fpu_xmm4;
-        case gdb_fpu_xmm5    : return fpu_xmm5;
-        case gdb_fpu_xmm6    : return fpu_xmm6;
-        case gdb_fpu_xmm7    : return fpu_xmm7;
-        case gdb_fpu_xmm8    : return fpu_xmm8;
-        case gdb_fpu_xmm9    : return fpu_xmm9;
-        case gdb_fpu_xmm10   : return fpu_xmm10;
-        case gdb_fpu_xmm11   : return fpu_xmm11;
-        case gdb_fpu_xmm12   : return fpu_xmm12;
-        case gdb_fpu_xmm13   : return fpu_xmm13;
-        case gdb_fpu_xmm14   : return fpu_xmm14;
-        case gdb_fpu_xmm15   : return fpu_xmm15;
-        case gdb_fpu_mxcsr   : return fpu_mxcsr;
-        default:
-            return LLDB_INVALID_REGNUM;
+            uint64_t val = value.GetAsUInt64();
+            is_hit = val & (1 << hw_index);
         }
     }
-    else if (kind == eRegisterKindLLDB)
+
+    return is_hit;
+}
+
+addr_t
+RegisterContext_x86_64::GetWatchpointAddress(uint32_t hw_index)
+{
+    addr_t wp_monitor_addr = LLDB_INVALID_ADDRESS;
+
+    if (hw_index < NumSupportedHardwareWatchpoints())
     {
-        return num;
+        if (!IsWatchpointVacant(hw_index))
+        {
+            RegisterValue value;
+
+            if (ReadRegister(dr0 + hw_index, value))
+                wp_monitor_addr = value.GetAsUInt64();
+        }
     }
 
-    return LLDB_INVALID_REGNUM;
+    return wp_monitor_addr;
+}
+
+
+bool
+RegisterContext_x86_64::ClearWatchpointHits()
+{
+    return WriteRegister(dr6, RegisterValue((uint64_t)0));
 }
 
 bool
@@ -733,26 +1463,37 @@ bool
 RegisterContext_x86_64::ReadGPR()
 {
      ProcessMonitor &monitor = GetMonitor();
-     return monitor.ReadGPR(&user.regs);
+     return monitor.ReadGPR(m_thread.GetID(), &m_gpr, GetGPRSize());
 }
 
 bool
 RegisterContext_x86_64::ReadFPR()
 {
     ProcessMonitor &monitor = GetMonitor();
-    return monitor.ReadFPR(&user.i387);
+    if (m_fpr_type == eFXSAVE)
+        return monitor.ReadFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
+
+    if (m_fpr_type == eXSAVE)
+        return monitor.ReadRegisterSet(m_thread.GetID(), &m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
+    return false;
 }
 
 bool
 RegisterContext_x86_64::WriteGPR()
 {
-     ProcessMonitor &monitor = GetMonitor();
-     return monitor.WriteGPR(&user.regs);
+    ProcessMonitor &monitor = GetMonitor();
+    return monitor.WriteGPR(m_thread.GetID(), &m_gpr, GetGPRSize());
 }
 
 bool
 RegisterContext_x86_64::WriteFPR()
 {
     ProcessMonitor &monitor = GetMonitor();
-    return monitor.WriteFPR(&user.i387);
+    if (m_fpr_type == eFXSAVE)
+        return monitor.WriteFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
+
+    if (m_fpr_type == eXSAVE)
+        return monitor.WriteRegisterSet(m_thread.GetID(), &m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
+    return false;
 }
+

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_x86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_x86_64.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_x86_64.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_x86_64.h Thu Jun  6 19:06:43 2013
@@ -13,22 +13,126 @@
 #include "lldb/Core/Log.h"
 #include "RegisterContextPOSIX.h"
 
-#ifdef __FreeBSD__
-#include "RegisterContextFreeBSD_x86_64.h"
-#endif
-
-#ifdef __linux__
-#include "RegisterContextLinux_x86_64.h"
-#endif
-
 class ProcessMonitor;
 
+// Internal codes for all x86_64 registers.
+enum
+{
+    k_first_gpr,
+    gpr_rax = k_first_gpr,
+    gpr_rbx,
+    gpr_rcx,
+    gpr_rdx,
+    gpr_rdi,
+    gpr_rsi,
+    gpr_rbp,
+    gpr_rsp,
+    gpr_r8,
+    gpr_r9,
+    gpr_r10,
+    gpr_r11,
+    gpr_r12,
+    gpr_r13,
+    gpr_r14,
+    gpr_r15,
+    gpr_rip,
+    gpr_rflags,
+    gpr_cs,
+    gpr_fs,
+    gpr_gs,
+    gpr_ss,
+    gpr_ds,
+    gpr_es,
+    k_first_i386,
+    gpr_eax = k_first_i386,
+    gpr_ebx,
+    gpr_ecx,
+    gpr_edx,
+    gpr_edi,
+    gpr_esi,
+    gpr_ebp,
+    gpr_esp,
+    gpr_eip,
+    gpr_eflags, // eRegisterKindLLDB == 33
+    k_last_i386 = gpr_eflags,
+    k_last_gpr = gpr_eflags,
+
+    k_first_fpr,
+    fpu_fcw = k_first_fpr,
+    fpu_fsw,
+    fpu_ftw,
+    fpu_fop,
+    fpu_ip,
+    fpu_cs,
+    fpu_dp,
+    fpu_ds,
+    fpu_mxcsr,
+    fpu_mxcsrmask,
+    fpu_stmm0,
+    fpu_stmm1,
+    fpu_stmm2,
+    fpu_stmm3,
+    fpu_stmm4,
+    fpu_stmm5,
+    fpu_stmm6,
+    fpu_stmm7,
+    fpu_xmm0,
+    fpu_xmm1,
+    fpu_xmm2,
+    fpu_xmm3,
+    fpu_xmm4,
+    fpu_xmm5,
+    fpu_xmm6,
+    fpu_xmm7,
+    fpu_xmm8,
+    fpu_xmm9,
+    fpu_xmm10,
+    fpu_xmm11,
+    fpu_xmm12,
+    fpu_xmm13,
+    fpu_xmm14,
+    fpu_xmm15,
+    k_last_fpr = fpu_xmm15,
+    k_first_avx,
+    fpu_ymm0 = k_first_avx,
+    fpu_ymm1,
+    fpu_ymm2,
+    fpu_ymm3,
+    fpu_ymm4,
+    fpu_ymm5,
+    fpu_ymm6,
+    fpu_ymm7,
+    fpu_ymm8,
+    fpu_ymm9,
+    fpu_ymm10,
+    fpu_ymm11,
+    fpu_ymm12,
+    fpu_ymm13,
+    fpu_ymm14,
+    fpu_ymm15,
+    k_last_avx = fpu_ymm15,
+
+    dr0,
+    dr1,
+    dr2,
+    dr3,
+    dr4,
+    dr5,
+    dr6,
+    dr7,
+
+    k_num_registers,
+    k_num_gpr_registers = k_last_gpr - k_first_gpr + 1,
+    k_num_fpr_registers = k_last_fpr - k_first_fpr + 1,
+    k_num_avx_registers = k_last_avx - k_first_avx + 1
+};
+
 class RegisterContext_x86_64
   : public RegisterContextPOSIX
 {
 public:
     RegisterContext_x86_64 (lldb_private::Thread &thread,
-                                 uint32_t concrete_frame_idx);
+                            uint32_t concrete_frame_idx);
 
     ~RegisterContext_x86_64();
 
@@ -41,19 +145,28 @@ public:
     size_t
     GetRegisterCount();
 
+    virtual size_t
+    GetGPRSize() = 0;
+
+    virtual unsigned
+    GetRegisterSize(unsigned reg);
+
+    virtual unsigned
+    GetRegisterOffset(unsigned reg);
+
     const lldb_private::RegisterInfo *
-    GetRegisterInfoAtIndex(uint32_t reg);
+    GetRegisterInfoAtIndex(size_t reg);
 
     size_t
     GetRegisterSetCount();
 
     const lldb_private::RegisterSet *
-    GetRegisterSet(uint32_t set);
+    GetRegisterSet(size_t set);
 
-    static unsigned
+    unsigned
     GetRegisterIndexFromOffset(unsigned offset);
 
-    static const char *
+    const char *
     GetRegisterName(unsigned reg);
 
     virtual bool
@@ -73,12 +186,41 @@ public:
     uint32_t
     ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num);
 
+    uint32_t
+    NumSupportedHardwareWatchpoints();
+
+    uint32_t
+    SetHardwareWatchpoint(lldb::addr_t, size_t size, bool read, bool write);
+
+    bool
+    SetHardwareWatchpointWithIndex(lldb::addr_t, size_t size, bool read,
+                                   bool write, uint32_t hw_index);
+
+    bool
+    ClearHardwareWatchpoint(uint32_t hw_index);
+
     bool
     HardwareSingleStep(bool enable);
 
     bool
     UpdateAfterBreakpoint();
 
+    bool
+    IsWatchpointVacant(uint32_t hw_index);
+
+    bool
+    IsWatchpointHit (uint32_t hw_index);
+
+    lldb::addr_t
+    GetWatchpointAddress (uint32_t hw_index);
+
+    bool
+    ClearWatchpointHits();
+
+    //---------------------------------------------------------------------------
+    // Generic floating-point registers
+    //---------------------------------------------------------------------------
+
     struct MMSReg
     {
         uint8_t bytes[10];
@@ -87,10 +229,10 @@ public:
 
     struct XMMReg
     {
-        uint8_t bytes[16];
+        uint8_t bytes[16]; // 128-bits for each XMM register
     };
 
-    struct FPU
+    struct FXSAVE
     {
         uint16_t fcw;
         uint16_t fsw;
@@ -105,33 +247,95 @@ public:
         uint32_t padding[24];
     };
 
-    struct UserArea
+    //---------------------------------------------------------------------------
+    // Extended floating-point registers
+    //---------------------------------------------------------------------------
+    struct YMMHReg
+    {
+        uint8_t  bytes[16];     // 16 * 8 bits for the high bytes of each YMM register
+    };
+
+    struct YMMReg
     {
-        GPR      regs;          // General purpose registers.
-        int32_t  fpvalid;       // True if FPU is being used.
-        int32_t  pad0;
-        FPU      i387;          // FPU registers.
-        uint64_t tsize;         // Text segment size.
-        uint64_t dsize;         // Data segment size.
-        uint64_t ssize;         // Stack segment size.
-        uint64_t start_code;    // VM address of text.
-        uint64_t start_stack;   // VM address of stack bottom (top in rsp).
-        int64_t  signal;        // Signal causing core dump.
-        int32_t  reserved;      // Unused.
-        int32_t  pad1;
-        uint64_t ar0;           // Location of GPR's.
-        FPU*     fpstate;       // Location of FPR's.
-        uint64_t magic;         // Identifier for core dumps.
-        char     u_comm[32];    // Command causing core dump.
-        uint64_t u_debugreg[8]; // Debug registers (DR0 - DR7).
-        uint64_t error_code;    // CPU error code.
-        uint64_t fault_address; // Control register CR3.
+        uint8_t  bytes[32];     // 16 * 16 bits for each YMM register
     };
 
+    struct YMM
+    {
+        YMMReg   ymm[16];       // assembled from ymmh and xmm registers
+    };
+
+    struct XSAVE_HDR
+    {
+        uint64_t  xstate_bv;    // OS enabled xstate mask to determine the extended states supported by the processor
+        uint64_t  reserved1[2];
+        uint64_t  reserved2[5];
+    } __attribute__((packed));
+
+    // x86 extensions to FXSAVE (i.e. for AVX processors) 
+    struct XSAVE 
+    {
+        FXSAVE    i387;         // floating point registers typical in i387_fxsave_struct
+        XSAVE_HDR header;       // The xsave_hdr_struct can be used to determine if the following extensions are usable
+        YMMHReg   ymmh[16];     // High 16 bytes of each of 16 YMM registers (the low bytes are in FXSAVE.xmm for compatibility with SSE)
+        // Slot any extensions to the register file here
+    } __attribute__((packed, aligned (64)));
+
+    struct IOVEC
+    {
+        void    *iov_base;      // pointer to XSAVE
+        size_t   iov_len;       // sizeof(XSAVE)
+    };
+
+    //---------------------------------------------------------------------------
+    // Note: prefer kernel definitions over user-land
+    //---------------------------------------------------------------------------
+    enum FPRType
+    {
+        eNotValid = 0,
+        eFSAVE,  // TODO
+        eFXSAVE,
+        eSOFT,   // TODO
+        eXSAVE
+    };
+
+    // Floating-point registers
+    struct FPR
+    {
+        // Thread state for the floating-point unit of the processor read by ptrace.
+        union XSTATE {
+            FXSAVE   fxsave;    // Generic floating-point registers.
+            XSAVE    xsave;     // x86 extended processor state.
+        } xstate;
+    };
+
+protected:
+    // Determines if an extended register set is supported on the processor running the inferior process.
+    virtual bool
+    IsRegisterSetAvailable(size_t set_index);
+
+    virtual const lldb_private::RegisterInfo *
+    GetRegisterInfo();
+
+    virtual bool
+    ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
+
+    virtual bool
+    WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value);
+
 private:
-    UserArea user;
+    uint64_t m_gpr[k_num_gpr_registers]; // general purpose registers.
+    FPRType  m_fpr_type;                 // determines the type of data stored by union FPR, if any.
+    FPR      m_fpr;                      // floating-point registers including extended register sets.
+    IOVEC    m_iovec;                    // wrapper for xsave.
+    YMM      m_ymm_set;                  // copy of ymmh and xmm register halves.
 
     ProcessMonitor &GetMonitor();
+    lldb::ByteOrder GetByteOrder();
+
+    bool CopyXSTATEtoYMM(uint32_t reg, lldb::ByteOrder byte_order);
+    bool CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order);
+    bool IsFPR(unsigned reg, FPRType fpr_type);
 
     bool ReadGPR();
     bool ReadFPR();

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp Thu Jun  6 19:06:43 2013
@@ -7,12 +7,19 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "lldb/lldb-python.h"
+
 #include "DynamicRegisterInfo.h"
 
 // C Includes
 // C++ Includes
 // Other libraries and framework includes
 // Project includes
+#include "lldb/Interpreter/Args.h"
+
+#ifndef LLDB_DISABLE_PYTHON
+#include "lldb/Interpreter/PythonDataObjects.h"
+#endif
 
 using namespace lldb;
 using namespace lldb_private;
@@ -21,26 +28,158 @@ DynamicRegisterInfo::DynamicRegisterInfo
     m_regs (),
     m_sets (),
     m_set_reg_nums (),
-    m_reg_names (),
-    m_reg_alt_names (),
     m_set_names (),
     m_reg_data_byte_size (0)
 {
 }
 
+DynamicRegisterInfo::DynamicRegisterInfo (const lldb_private::PythonDictionary &dict) :
+    m_regs (),
+    m_sets (),
+    m_set_reg_nums (),
+    m_set_names (),
+    m_reg_data_byte_size (0)
+{
+    SetRegisterInfo (dict);
+}
+
 DynamicRegisterInfo::~DynamicRegisterInfo ()
 {
 }
 
+
+size_t
+DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict)
+{
+#ifndef LLDB_DISABLE_PYTHON
+    PythonList sets (dict.GetItemForKey("sets"));
+    if (sets)
+    {
+        const uint32_t num_sets = sets.GetSize();
+        for (uint32_t i=0; i<num_sets; ++i)
+        {
+            PythonString py_set_name(sets.GetItemAtIndex(i));
+            ConstString set_name;
+            if (py_set_name)
+                set_name.SetCString(py_set_name.GetString());
+            if (set_name)
+            {
+                RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL };
+                m_sets.push_back (new_set);
+            }
+            else
+            {
+                Clear();
+                return 0;
+            }
+        }
+        m_set_reg_nums.resize(m_sets.size());
+    }
+    PythonList regs (dict.GetItemForKey("registers"));
+    if (regs)
+    {
+        const uint32_t num_regs = regs.GetSize();
+        PythonString name_pystr("name");
+        PythonString altname_pystr("alt-name");
+        PythonString bitsize_pystr("bitsize");
+        PythonString offset_pystr("offset");
+        PythonString encoding_pystr("encoding");
+        PythonString format_pystr("format");
+        PythonString set_pystr("set");
+        PythonString gcc_pystr("gcc");
+        PythonString dwarf_pystr("dwarf");
+        PythonString generic_pystr("generic");
+        for (uint32_t i=0; i<num_regs; ++i)
+        {
+            PythonDictionary reg_info_dict(regs.GetItemAtIndex(i));
+            if (reg_info_dict)
+            {
+                // { 'name':'rcx'       , 'bitsize' :  64, 'offset' :  16, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 2, 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', },
+                RegisterInfo reg_info;
+                bzero (&reg_info, sizeof(reg_info));
+                
+                reg_info.name = ConstString (reg_info_dict.GetItemForKeyAsString(name_pystr)).GetCString();
+                if (reg_info.name == NULL)
+                {
+                    Clear();
+                    return 0;
+                }
+                    
+                reg_info.alt_name = ConstString (reg_info_dict.GetItemForKeyAsString(altname_pystr)).GetCString();
+                
+                reg_info.byte_offset = reg_info_dict.GetItemForKeyAsInteger(offset_pystr, UINT32_MAX);
+
+                if (reg_info.byte_offset == UINT32_MAX)
+                {
+                    Clear();
+                    return 0;
+                }
+                reg_info.byte_size = reg_info_dict.GetItemForKeyAsInteger(bitsize_pystr, 0) / 8;
+                
+                if (reg_info.byte_size == 0)
+                {
+                    Clear();
+                    return 0;
+                }
+                
+                const char *format_cstr = reg_info_dict.GetItemForKeyAsString(format_pystr);
+                if (format_cstr)
+                {
+                    if (Args::StringToFormat(format_cstr, reg_info.format, NULL).Fail())
+                    {
+                        Clear();
+                        return 0;
+                    }
+                }
+                else
+                    reg_info.format = eFormatHex;
+                    
+                const char *encoding_cstr = reg_info_dict.GetItemForKeyAsString(encoding_pystr);
+                if (encoding_cstr)
+                    reg_info.encoding = Args::StringToEncoding (encoding_cstr, eEncodingUint);
+                else
+                    reg_info.encoding = eEncodingUint;
+
+                const int64_t set = reg_info_dict.GetItemForKeyAsInteger(set_pystr, -1);
+                if (set >= m_sets.size())
+                {
+                    Clear();
+                    return 0;
+                }
+
+                reg_info.kinds[lldb::eRegisterKindLLDB]    = i;
+                reg_info.kinds[lldb::eRegisterKindGDB]     = i;
+                reg_info.kinds[lldb::eRegisterKindGCC]     = reg_info_dict.GetItemForKeyAsInteger(gcc_pystr, LLDB_INVALID_REGNUM);
+                reg_info.kinds[lldb::eRegisterKindDWARF]   = reg_info_dict.GetItemForKeyAsInteger(dwarf_pystr, LLDB_INVALID_REGNUM);
+                reg_info.kinds[lldb::eRegisterKindGeneric] = Args::StringToGenericRegister (reg_info_dict.GetItemForKeyAsString(generic_pystr));
+                const size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size;
+                if (m_reg_data_byte_size < end_reg_offset)
+                    m_reg_data_byte_size = end_reg_offset;
+
+                m_regs.push_back (reg_info);
+                m_set_reg_nums[set].push_back(i);
+
+            }
+            else
+            {
+                Clear();
+                return 0;
+            }
+        }
+        Finalize ();
+    }
+#endif
+    return 0;
+}
+
+
 void
-DynamicRegisterInfo::AddRegister (RegisterInfo &reg_info, 
+DynamicRegisterInfo::AddRegister (RegisterInfo &reg_info,
                                   ConstString &reg_name, 
                                   ConstString &reg_alt_name, 
                                   ConstString &set_name)
 {
     const uint32_t reg_num = m_regs.size();
-    m_reg_names.push_back (reg_name);
-    m_reg_alt_names.push_back (reg_alt_name);
     reg_info.name = reg_name.AsCString();
     assert (reg_info.name);
     reg_info.alt_name = reg_alt_name.AsCString(NULL);
@@ -136,7 +275,5 @@ DynamicRegisterInfo::Clear()
     m_regs.clear();
     m_sets.clear();
     m_set_reg_nums.clear();
-    m_reg_names.clear();
-    m_reg_alt_names.clear();
     m_set_names.clear();
 }

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/DynamicRegisterInfo.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/DynamicRegisterInfo.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/DynamicRegisterInfo.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/DynamicRegisterInfo.h Thu Jun  6 19:06:43 2013
@@ -24,9 +24,14 @@ class DynamicRegisterInfo
 public:
     DynamicRegisterInfo ();
 
+    DynamicRegisterInfo (const lldb_private::PythonDictionary &dict);
+    
     virtual 
     ~DynamicRegisterInfo ();
 
+    size_t
+    SetRegisterInfo (const lldb_private::PythonDictionary &dict);
+
     void
     AddRegister (lldb_private::RegisterInfo &reg_info, 
                  lldb_private::ConstString &reg_name, 
@@ -73,8 +78,6 @@ protected:
     reg_collection m_regs;
     set_collection m_sets;
     set_reg_num_collection m_set_reg_nums;
-    name_collection m_reg_names;
-    name_collection m_reg_alt_names;
     name_collection m_set_names;
     size_t m_reg_data_byte_size;   // The number of bytes required to store all registers
 };

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp Thu Jun  6 19:06:43 2013
@@ -8,8 +8,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "InferiorCallPOSIX.h"
+#include "lldb/Core/Address.h"
 #include "lldb/Core/StreamFile.h"
 #include "lldb/Core/ValueObject.h"
+#include "lldb/Symbol/ClangASTContext.h"
 #include "lldb/Symbol/SymbolContext.h"
 #include "lldb/Target/ExecutionContext.h"
 #include "lldb/Target/Process.h"
@@ -47,9 +49,10 @@ bool lldb_private::InferiorCallMmap(Proc
             const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
             const bool use_inline_block_range = false;
             const bool stop_other_threads = true;
-            const bool discard_on_error = true;
+            const bool unwind_on_error = true;
+            const bool ignore_breakpoints = true;
             const bool try_all_threads = true;
-            const uint32_t single_thread_timeout_usec = 500000;
+            const uint32_t timeout_usec = 500000;
 
             addr_t prot_arg, flags_arg = 0;
             if (prot == eMmapProtNone)
@@ -79,7 +82,8 @@ bool lldb_private::InferiorCallMmap(Proc
                                                 mmap_range.GetBaseAddress(),
                                                 ClangASTType (clang_ast_context->getASTContext(), clang_void_ptr_type),
                                                 stop_other_threads,
-                                                discard_on_error,
+                                                unwind_on_error,
+                                                ignore_breakpoints,
                                                 &addr,
                                                 &length,
                                                 &prot_arg,
@@ -103,8 +107,9 @@ bool lldb_private::InferiorCallMmap(Proc
                                                                           call_plan_sp,        
                                                                           stop_other_threads,
                                                                           try_all_threads,
-                                                                          discard_on_error,
-                                                                          single_thread_timeout_usec,
+                                                                          unwind_on_error,
+                                                                          ignore_breakpoints,
+                                                                          timeout_usec,
                                                                           error_strm);
                         if (result == eExecutionCompleted)
                         {
@@ -115,6 +120,11 @@ bool lldb_private::InferiorCallMmap(Proc
                                 if (allocated_addr == UINT32_MAX)
                                     return false;
                             }
+                            else if (process->GetAddressByteSize() == 8)
+                            {
+                                if (allocated_addr == UINT64_MAX)
+                                    return false;
+                            }
                             return true;
                         }
                     }
@@ -151,9 +161,10 @@ bool lldb_private::InferiorCallMunmap(Pr
            const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
            const bool use_inline_block_range = false;
            const bool stop_other_threads = true;
-           const bool discard_on_error = true;
+           const bool unwind_on_error = true;
+           const bool ignore_breakpoints = true;
            const bool try_all_threads = true;
-           const uint32_t single_thread_timeout_usec = 500000;
+           const uint32_t timeout_usec = 500000;
            
            AddressRange munmap_range;
            if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range))
@@ -162,7 +173,8 @@ bool lldb_private::InferiorCallMunmap(Pr
                                                                             munmap_range.GetBaseAddress(),
                                                                             ClangASTType(),
                                                                             stop_other_threads,
-                                                                            discard_on_error,
+                                                                            unwind_on_error,
+                                                                            ignore_breakpoints,
                                                                             &addr,
                                                                             &length));
                if (call_plan_sp)
@@ -181,8 +193,9 @@ bool lldb_private::InferiorCallMunmap(Pr
                                                                          call_plan_sp,        
                                                                          stop_other_threads,
                                                                          try_all_threads,
-                                                                         discard_on_error,
-                                                                         single_thread_timeout_usec,
+                                                                         unwind_on_error,
+                                                                         ignore_breakpoints,
+                                                                         timeout_usec,
                                                                          error_strm);
                        if (result == eExecutionCompleted)
                        {
@@ -196,3 +209,66 @@ bool lldb_private::InferiorCallMunmap(Pr
 
    return false;
 }
+
+bool lldb_private::InferiorCall(Process *process, const Address *address, addr_t &returned_func) {
+    Thread *thread = process->GetThreadList().GetSelectedThread().get();
+    if (thread == NULL || address == NULL)
+        return false;
+
+    const bool stop_other_threads = true;
+    const bool unwind_on_error = true;
+    const bool ignore_breakpoints = true;
+    const bool try_all_threads = true;
+    const uint32_t timeout_usec = 500000;
+
+    ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
+    lldb::clang_type_t clang_void_ptr_type = clang_ast_context->GetVoidPtrType(false);
+    ThreadPlanCallFunction *call_function_thread_plan
+        = new ThreadPlanCallFunction (*thread,
+                                      *address,
+                                      ClangASTType (clang_ast_context->getASTContext(), clang_void_ptr_type),
+                                      stop_other_threads,
+                                      unwind_on_error,
+                                      ignore_breakpoints);
+    lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
+    if (call_plan_sp)
+    {
+        StreamFile error_strm;
+        // This plan is a utility plan, so set it to discard itself when done.
+        call_plan_sp->SetIsMasterPlan (true);
+        call_plan_sp->SetOkayToDiscard(true);
+
+        StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
+        if (frame)
+        {
+            ExecutionContext exe_ctx;
+            frame->CalculateExecutionContext (exe_ctx);
+            ExecutionResults result = process->RunThreadPlan (exe_ctx,
+                                                              call_plan_sp,
+                                                              stop_other_threads,
+                                                              try_all_threads,
+                                                              unwind_on_error,
+                                                              ignore_breakpoints,
+                                                              timeout_usec,
+                                                              error_strm);
+            if (result == eExecutionCompleted)
+            {
+                returned_func = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+
+                if (process->GetAddressByteSize() == 4)
+                {
+                    if (returned_func == UINT32_MAX)
+                        return false;
+                }
+                else if (process->GetAddressByteSize() == 8)
+                {
+                    if (returned_func == UINT64_MAX)
+                        return false;
+                }
+                return true;
+            }
+        }
+    }
+
+    return false;
+}

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/InferiorCallPOSIX.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/InferiorCallPOSIX.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/InferiorCallPOSIX.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/InferiorCallPOSIX.h Thu Jun  6 19:06:43 2013
@@ -36,6 +36,8 @@ bool InferiorCallMmap(Process *proc, lld
 
 bool InferiorCallMunmap(Process *proc, lldb::addr_t addr, lldb::addr_t length);
 
+bool InferiorCall(Process *proc, const Address *address, lldb::addr_t &returned_func);
+
 }   // namespace lldb_private
 
 #endif  // lldb_InferiorCallPOSIX_h_

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp Thu Jun  6 19:06:43 2013
@@ -416,7 +416,7 @@ RegisterContextDarwin_arm::GetRegisterCo
 }
 
 const RegisterInfo *
-RegisterContextDarwin_arm::GetRegisterInfoAtIndex (uint32_t reg)
+RegisterContextDarwin_arm::GetRegisterInfoAtIndex (size_t reg)
 {
     assert(k_num_register_infos == k_num_registers);
     if (reg < k_num_registers)
@@ -464,7 +464,7 @@ RegisterContextDarwin_arm::GetRegisterSe
 }
 
 const RegisterSet *
-RegisterContextDarwin_arm::GetRegisterSet (uint32_t reg_set)
+RegisterContextDarwin_arm::GetRegisterSet (size_t reg_set)
 {
     if (reg_set < k_num_regsets)
         return &g_reg_sets[reg_set];

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h Thu Jun  6 19:06:43 2013
@@ -64,13 +64,13 @@ public:
     GetRegisterCount ();
 
     virtual const lldb_private::RegisterInfo *
-    GetRegisterInfoAtIndex (uint32_t reg);
+    GetRegisterInfoAtIndex (size_t reg);
 
     virtual size_t
     GetRegisterSetCount ();
 
     virtual const lldb_private::RegisterSet *
-    GetRegisterSet (uint32_t set);
+    GetRegisterSet (size_t set);
 
     virtual bool
     ReadRegister (const lldb_private::RegisterInfo *reg_info, 
@@ -114,11 +114,17 @@ public:
     };
 
 
+    struct QReg
+    {
+        uint8_t bytes[16];
+    };
+
     struct FPU
     {
         union {
             uint32_t s[32];
-            uint64_t d[16];
+            uint64_t d[32];
+            QReg     q[16];  // the 128-bit NEON registers
         } floats;
         uint32_t fpscr;
     };
@@ -160,10 +166,10 @@ protected:
 
     enum
     {
-        GPRRegSet = 1,
-        FPURegSet = 2,
-        EXCRegSet = 3,
-        DBGRegSet = 4
+        GPRRegSet = 1, // ARM_THREAD_STATE
+        FPURegSet = 2, // ARM_VFP_STATE
+        EXCRegSet = 3, // ARM_EXCEPTION_STATE
+        DBGRegSet = 4  // ARM_DEBUG_STATE
     };
 
     enum
@@ -284,47 +290,26 @@ protected:
         return -1;
     }
     
-    int
-    DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
-    {
-        return -1;
-    }
+    virtual int
+    DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) = 0;
     
-    int
-    DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
-    {
-        return -1;
-    }
+    virtual int
+    DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) = 0;
 
-    int
-    DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg)
-    {
-        return -1;
-    }
+    virtual int
+    DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg) = 0;
 
-    int
-    DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
-    {
-        return -1;
-    }
+    virtual int
+    DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) = 0;
     
-    int
-    DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
-    {
-        return -1;
-    }
+    virtual int
+    DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) = 0;
     
-    int
-    DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
-    {
-        return -1;
-    }
+    virtual int
+    DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) = 0;
 
-    int
-    DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg)
-    {
-        return -1;
-    }
+    virtual int
+    DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg) = 0;
 
     int
     ReadRegisterSet (uint32_t set, bool force);

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp Thu Jun  6 19:06:43 2013
@@ -298,7 +298,7 @@ RegisterContextDarwin_i386::GetRegisterC
 }
 
 const RegisterInfo *
-RegisterContextDarwin_i386::GetRegisterInfoAtIndex (uint32_t reg)
+RegisterContextDarwin_i386::GetRegisterInfoAtIndex (size_t reg)
 {
     assert(k_num_register_infos == k_num_registers);
     if (reg < k_num_registers)
@@ -410,7 +410,7 @@ RegisterContextDarwin_i386::GetRegisterS
 }
 
 const RegisterSet *
-RegisterContextDarwin_i386::GetRegisterSet (uint32_t reg_set)
+RegisterContextDarwin_i386::GetRegisterSet (size_t reg_set)
 {
     if (reg_set < k_num_regsets)
         return &g_reg_sets[reg_set];

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h Thu Jun  6 19:06:43 2013
@@ -34,13 +34,13 @@ public:
     GetRegisterCount ();
 
     virtual const lldb_private::RegisterInfo *
-    GetRegisterInfoAtIndex (uint32_t reg);
+    GetRegisterInfoAtIndex (size_t reg);
 
     virtual size_t
     GetRegisterSetCount ();
 
     virtual const lldb_private::RegisterSet *
-    GetRegisterSet (uint32_t set);
+    GetRegisterSet (size_t set);
 
     virtual bool
     ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
@@ -230,40 +230,22 @@ protected:
 
     // Subclasses override these to do the actual reading.
     virtual int
-    DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
-    {
-        return -1;
-    }
+    DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr) = 0;
     
-    int
-    DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
-    {
-        return -1;
-    }
+    virtual int
+    DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) = 0;
 
-    int
-    DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
-    {
-        return -1;
-    }
+    virtual int
+    DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) = 0;
 
-    int
-    DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
-    {
-        return -1;
-    }
+    virtual int
+    DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) = 0;
     
-    int
-    DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
-    {
-        return -1;
-    }
+    virtual int
+    DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) = 0;
     
-    int
-    DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
-    {
-        return -1;
-    }
+    virtual int
+    DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) = 0;
 
     int
     ReadRegisterSet (uint32_t set, bool force);

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp Thu Jun  6 19:06:43 2013
@@ -336,7 +336,7 @@ RegisterContextDarwin_x86_64::GetRegiste
 
 
 const RegisterInfo *
-RegisterContextDarwin_x86_64::GetRegisterInfoAtIndex (uint32_t reg)
+RegisterContextDarwin_x86_64::GetRegisterInfoAtIndex (size_t reg)
 {
     assert(k_num_register_infos == k_num_registers);
     if (reg < k_num_registers)
@@ -457,7 +457,7 @@ RegisterContextDarwin_x86_64::GetRegiste
 }
 
 const RegisterSet *
-RegisterContextDarwin_x86_64::GetRegisterSet (uint32_t reg_set)
+RegisterContextDarwin_x86_64::GetRegisterSet (size_t reg_set)
 {
     if (reg_set < k_num_regsets)
         return &g_reg_sets[reg_set];
@@ -491,7 +491,7 @@ RegisterContextDarwin_x86_64::LogGPR(Log
         for (uint32_t i=0; i<k_num_gpr_registers; i++)
         {
             uint32_t reg = gpr_rax + i;
-            log->Printf("%12s = 0x%16.16llx", g_register_infos[reg].name, (&gpr.rax)[reg]);
+            log->Printf("%12s = 0x%16.16" PRIx64, g_register_infos[reg].name, (&gpr.rax)[reg]);
         }
     }
 }

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h Thu Jun  6 19:06:43 2013
@@ -33,13 +33,13 @@ public:
     GetRegisterCount ();
 
     virtual const lldb_private::RegisterInfo *
-    GetRegisterInfoAtIndex (uint32_t reg);
+    GetRegisterInfoAtIndex (size_t reg);
 
     virtual size_t
     GetRegisterSetCount ();
 
     virtual const lldb_private::RegisterSet *
-    GetRegisterSet (uint32_t set);
+    GetRegisterSet (size_t set);
 
     virtual bool
     ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
@@ -234,40 +234,22 @@ protected:
 
     // Subclasses override these to do the actual reading.
     virtual int
-    DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
-    {
-        return -1;
-    }
+    DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr) = 0;
     
     virtual int
-    DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
-    {
-        return -1;
-    }
+    DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) = 0;
     
     virtual int
-    DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
-    {
-        return -1;
-    }
+    DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) = 0;
     
     virtual int
-    DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
-    {
-        return -1;
-    }
+    DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) = 0;
     
     virtual int
-    DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
-    {
-        return -1;
-    }
+    DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) = 0;
     
     virtual int
-    DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
-    {
-        return -1;
-    }
+    DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) = 0;
     
     int
     ReadRegisterSet (uint32_t set, bool force);

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextLLDB.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextLLDB.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextLLDB.cpp Thu Jun  6 19:06:43 2013
@@ -13,13 +13,15 @@
 #include "lldb/Core/AddressRange.h"
 #include "lldb/Core/DataBufferHeap.h"
 #include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
 #include "lldb/Core/RegisterValue.h"
 #include "lldb/Core/Value.h"
+#include "lldb/Expression/DWARFExpression.h"
 #include "lldb/Symbol/FuncUnwinders.h"
 #include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Symbol/SymbolContext.h"
 #include "lldb/Symbol/Symbol.h"
-#include "lldb/Expression/DWARFExpression.h"
 #include "lldb/Target/ABI.h"
 #include "lldb/Target/ExecutionContext.h"
 #include "lldb/Target/Process.h"
@@ -33,24 +35,24 @@
 using namespace lldb;
 using namespace lldb_private;
 
-RegisterContextLLDB::RegisterContextLLDB 
+RegisterContextLLDB::RegisterContextLLDB
 (
-    Thread& thread, 
+    Thread& thread,
     const SharedPtr &next_frame,
     SymbolContext& sym_ctx,
     uint32_t frame_number,
     UnwindLLDB& unwind_lldb
 ) :
-    RegisterContext (thread, frame_number), 
-    m_thread(thread), 
+    RegisterContext (thread, frame_number),
+    m_thread(thread),
     m_fast_unwind_plan_sp (),
     m_full_unwind_plan_sp (),
     m_all_registers_available(false),
     m_frame_type (-1),
     m_cfa (LLDB_INVALID_ADDRESS),
-    m_start_pc (), 
-    m_current_pc (), 
-    m_current_offset (0), 
+    m_start_pc (),
+    m_current_pc (),
+    m_current_offset (0),
     m_current_offset_backed_up_one (0),
     m_sym_ctx(sym_ctx),
     m_sym_ctx_valid (false),
@@ -58,7 +60,7 @@ RegisterContextLLDB::RegisterContextLLDB
     m_registers(),
     m_parent_unwind (unwind_lldb)
 {
-    m_sym_ctx.Clear();
+    m_sym_ctx.Clear(false);
     m_sym_ctx_valid = false;
 
     if (IsFrameZero ())
@@ -71,8 +73,8 @@ RegisterContextLLDB::RegisterContextLLDB
     }
 
     // This same code exists over in the GetFullUnwindPlanForFrame() but it may not have been executed yet
-    if (IsFrameZero() 
-        || next_frame->m_frame_type == eSigtrampFrame 
+    if (IsFrameZero()
+        || next_frame->m_frame_type == eSigtrampFrame
         || next_frame->m_frame_type == eDebuggerFrame)
     {
         m_all_registers_available = true;
@@ -85,11 +87,10 @@ RegisterContextLLDB::RegisterContextLLDB
 void
 RegisterContextLLDB::InitializeZerothFrame()
 {
+    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
     ExecutionContext exe_ctx(m_thread.shared_from_this());
     RegisterContextSP reg_ctx_sp = m_thread.GetRegisterContext();
 
-    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
-
     if (reg_ctx_sp.get() == NULL)
     {
         m_frame_type = eNotAValidFrame;
@@ -122,11 +123,7 @@ RegisterContextLLDB::InitializeZerothFra
     ModuleSP pc_module_sp (m_current_pc.GetModule());
     if (!m_current_pc.IsValid() || !pc_module_sp)
     {
-        if (log)
-        {
-            log->Printf("%*sFrame %u using architectural default unwind method",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
-        }
+        UnwindLogMsg ("using architectural default unwind method");
     }
 
     // We require that eSymbolContextSymbol be successfully filled in or this context is of no use to us.
@@ -138,7 +135,7 @@ RegisterContextLLDB::InitializeZerothFra
 
     AddressRange addr_range;
     m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, addr_range);
-    
+
     static ConstString g_sigtramp_name ("_sigtramp");
     if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == g_sigtramp_name) ||
         (m_sym_ctx.symbol   && m_sym_ctx.symbol->GetName()   == g_sigtramp_name))
@@ -180,8 +177,8 @@ RegisterContextLLDB::InitializeZerothFra
     // We've set m_frame_type and m_sym_ctx before these calls.
 
     m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame ();
-    m_full_unwind_plan_sp = GetFullUnwindPlanForFrame (); 
-    
+    m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();
+
     UnwindPlan::RowSP active_row;
     int cfa_offset = 0;
     int row_register_kind = -1;
@@ -193,8 +190,7 @@ RegisterContextLLDB::InitializeZerothFra
         {
             StreamString active_row_strm;
             active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
-            log->Printf("%*sFrame %u active row: %s",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, active_row_strm.GetString().c_str());
+            UnwindLogMsg ("%s", active_row_strm.GetString().c_str());
         }
     }
 
@@ -204,7 +200,7 @@ RegisterContextLLDB::InitializeZerothFra
         return;
     }
 
-    
+
     addr_t cfa_regval;
     if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval))
     {
@@ -218,23 +214,11 @@ RegisterContextLLDB::InitializeZerothFra
 
     m_cfa = cfa_regval + cfa_offset;
 
-    if (log)
-    {
-        log->Printf("%*sFrame %u cfa_regval = 0x%16.16llx (cfa_regval = 0x%16.16llx, cfa_offset = %i)",
-                    m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                    m_cfa, cfa_regval, cfa_offset);
-    }
-    
-    if (log)
-    {
-        log->Printf("%*sThread %d Frame %u initialized frame current pc is 0x%llx cfa is 0x%llx using %s UnwindPlan", 
-                    m_frame_number < 100 ? m_frame_number : 100, "", 
-                    m_thread.GetIndexID(), 
-                    m_frame_number,
-                    (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), 
-                    (uint64_t) m_cfa,
-                    m_full_unwind_plan_sp->GetSourceName().GetCString());
-    }
+    UnwindLogMsg ("cfa_regval = 0x%16.16" PRIx64 " (cfa_regval = 0x%16.16" PRIx64 ", cfa_offset = %i)", m_cfa, cfa_regval, cfa_offset);
+    UnwindLogMsg ("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64 " using %s UnwindPlan",
+            (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()),
+            (uint64_t) m_cfa,
+            m_full_unwind_plan_sp->GetSourceName().GetCString());
 }
 
 // Initialize a RegisterContextLLDB for the non-zeroth frame -- rely on the RegisterContextLLDB "below" it
@@ -243,14 +227,13 @@ RegisterContextLLDB::InitializeZerothFra
 void
 RegisterContextLLDB::InitializeNonZerothFrame()
 {
-    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
-
+    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
     if (IsFrameZero ())
     {
         m_frame_type = eNotAValidFrame;
         return;
     }
-    
+
     if (!GetNextFrame().get() || !GetNextFrame()->IsValid())
     {
         m_frame_type = eNotAValidFrame;
@@ -265,27 +248,19 @@ RegisterContextLLDB::InitializeNonZeroth
     addr_t pc;
     if (!ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc))
     {
-        if (log)
-        {
-            log->Printf("%*sFrame %u could not get pc value",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
-        }
+        UnwindLogMsg ("could not get pc value");
         m_frame_type = eNotAValidFrame;
         return;
     }
-    
+
     if (log)
     {
-        log->Printf("%*sFrame %u pc = 0x%16.16llx",
-                    m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, pc);
+        UnwindLogMsg ("pc = 0x%16.16" PRIx64, pc);
         addr_t reg_val;
         if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val))
-            log->Printf("%*sFrame %u fp = 0x%16.16llx",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, reg_val);
-
+            UnwindLogMsg ("fp = 0x%16.16" PRIx64, reg_val);
         if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val))
-            log->Printf("%*sFrame %u sp = 0x%16.16llx",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, reg_val);
+            UnwindLogMsg ("sp = 0x%16.16" PRIx64, reg_val);
     }
 
     // A pc of 0x0 means it's the end of the stack crawl
@@ -294,11 +269,11 @@ RegisterContextLLDB::InitializeNonZeroth
         m_frame_type = eNotAValidFrame;
         return;
     }
-    
+
     ExecutionContext exe_ctx(m_thread.shared_from_this());
     Process *process = exe_ctx.GetProcessPtr();
     // Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs
-    // this will strip bit zero in case we read a PC from memory or from the LR.   
+    // this will strip bit zero in case we read a PC from memory or from the LR.
     ABI *abi = process->GetABI().get();
     if (abi)
         pc = abi->FixCodeAddress(pc);
@@ -310,12 +285,8 @@ RegisterContextLLDB::InitializeNonZeroth
     ModuleSP pc_module_sp (m_current_pc.GetModule());
     if (!m_current_pc.IsValid() || !pc_module_sp)
     {
-        if (log)
-        {
-            log->Printf("%*sFrame %u using architectural default unwind method",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
-        }
-        
+        UnwindLogMsg ("using architectural default unwind method");
+
         // Test the pc value to see if we know it's in an unmapped/non-executable region of memory.
         uint32_t permissions;
         if (process->GetLoadAddressPermissions(pc, permissions)
@@ -327,11 +298,8 @@ RegisterContextLLDB::InitializeNonZeroth
             // pc and see if we can get any further.
             if (GetNextFrame().get() && GetNextFrame()->IsValid() && GetNextFrame()->IsFrameZero())
             {
-                if (log)
-                {
-                    log->Printf("%*sFrame %u had a pc of 0x%llx which is not in executable memory but on frame 1 -- allowing it once.",
-                                m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, (uint64_t) pc);
-                }
+                UnwindLogMsg ("had a pc of 0x%" PRIx64 " which is not in executable memory but on frame 1 -- allowing it once.",
+                         (uint64_t) pc);
                 m_frame_type = eSkipFrame;
             }
             else
@@ -363,11 +331,7 @@ RegisterContextLLDB::InitializeNonZeroth
                 int cfa_offset = row->GetCFAOffset();
                 if (!ReadGPRValue (row_register_kind, cfa_regnum, cfa_regval))
                 {
-                    if (log)
-                    {
-                        log->Printf("%*sFrame %u failed to get cfa value",
-                                    m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
-                    }
+                    UnwindLogMsg ("failed to get cfa value");
                     if (m_frame_type != eSkipFrame)   // don't override eSkipFrame
                     {
                         m_frame_type = eNormalFrame;
@@ -379,11 +343,7 @@ RegisterContextLLDB::InitializeNonZeroth
                 // A couple of sanity checks..
                 if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1)
                 {
-                    if (log)
-                    {
-                        log->Printf("%*sFrame %u could not find a valid cfa address",
-                                    m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
-                    }
+                    UnwindLogMsg ("could not find a valid cfa address");
                     m_frame_type = eNotAValidFrame;
                     return;
                 }
@@ -399,21 +359,12 @@ RegisterContextLLDB::InitializeNonZeroth
             }
             else
             {
-                if (log)
-                {
-                    log->Printf("%*sFrame %u could not find a row for function offset zero",
-                                m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
-                }
+                UnwindLogMsg ("could not find a row for function offset zero");
                 m_frame_type = eNotAValidFrame;
                 return;
             }
 
-            if (log)
-            {
-                log->Printf("%*sFrame %u initialized frame cfa is 0x%llx",
-                            m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                            (uint64_t) m_cfa);
-            }
+            UnwindLogMsg ("initialized frame cfa is 0x%" PRIx64, (uint64_t) m_cfa);
             return;
         }
         m_frame_type = eNotAValidFrame;
@@ -454,11 +405,11 @@ RegisterContextLLDB::InitializeNonZeroth
     // value is pointing to the next function, e.g. if a function ends with a CALL instruction.
     // FIXME this may need to be an architectural-dependent behavior; if so we'll need to add a member function
     // to the ABI plugin and consult that.
-    if (decr_pc_and_recompute_addr_range) 
+    if (decr_pc_and_recompute_addr_range)
     {
         Address temporary_pc(m_current_pc);
         temporary_pc.SetOffset(m_current_pc.GetOffset() - 1);
-        m_sym_ctx.Clear();
+        m_sym_ctx.Clear(false);
         m_sym_ctx_valid = false;
         if ((pc_module_sp->ResolveSymbolContextForAddress (temporary_pc, eSymbolContextFunction| eSymbolContextSymbol, m_sym_ctx) & eSymbolContextSymbol) == eSymbolContextSymbol)
         {
@@ -520,11 +471,10 @@ RegisterContextLLDB::InitializeNonZeroth
         {
             StreamString active_row_strm;
             active_row->Dump(active_row_strm, m_fast_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
-            log->Printf("%*sFrame %u active row: %s",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, active_row_strm.GetString().c_str());
+            UnwindLogMsg ("active row: %s", active_row_strm.GetString().c_str());
         }
     }
-    else 
+    else
     {
         m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();
         if (m_full_unwind_plan_sp && m_full_unwind_plan_sp->PlanValidAtAddress (m_current_pc))
@@ -535,8 +485,7 @@ RegisterContextLLDB::InitializeNonZeroth
             {
                 StreamString active_row_strm;
                 active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
-                log->Printf("%*sFrame %u active row: %s",
-                            m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, active_row_strm.GetString().c_str());
+                UnwindLogMsg ("active row: %s", active_row_strm.GetString().c_str());
             }
         }
     }
@@ -550,12 +499,7 @@ RegisterContextLLDB::InitializeNonZeroth
     addr_t cfa_regval;
     if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval))
     {
-        if (log)
-        {
-            log->Printf("%*sFrame %u failed to get cfa reg %d/%d",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                        row_register_kind, active_row->GetCFARegister());
-        }
+        UnwindLogMsg ("failed to get cfa reg %d/%d", row_register_kind, active_row->GetCFARegister());
         m_frame_type = eNotAValidFrame;
         return;
     }
@@ -563,21 +507,12 @@ RegisterContextLLDB::InitializeNonZeroth
 
     m_cfa = cfa_regval + cfa_offset;
 
-    if (log)
-    {
-        log->Printf("%*sFrame %u cfa_regval = 0x%16.16llx (cfa_regval = 0x%16.16llx, cfa_offset = %i)",
-                    m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                    m_cfa, cfa_regval, cfa_offset);
-    }
+    UnwindLogMsg ("cfa_regval = 0x%16.16" PRIx64 " (cfa_regval = 0x%16.16" PRIx64 ", cfa_offset = %i)", m_cfa, cfa_regval, cfa_offset);
 
     // A couple of sanity checks..
     if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1)
-    { 
-        if (log)
-        {
-            log->Printf("%*sFrame %u could not find a valid cfa address",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
-        }
+    {
+        UnwindLogMsg ("could not find a valid cfa address");
         m_frame_type = eNotAValidFrame;
         return;
     }
@@ -602,24 +537,16 @@ RegisterContextLLDB::InitializeNonZeroth
                 repeating_frames = true;
             }
         }
-        if (repeating_frames)
+        if (repeating_frames && abi->FunctionCallsChangeCFA())
         {
-            if (log)
-            {
-                log->Printf("%*sFrame %u same CFA address as next frame, assuming the unwind is looping - stopping",
-                            m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
-            }
+            UnwindLogMsg ("same CFA address as next frame, assuming the unwind is looping - stopping");
             m_frame_type = eNotAValidFrame;
             return;
         }
     }
 
-    if (log)
-    {
-        log->Printf("%*sFrame %u initialized frame current pc is 0x%llx cfa is 0x%llx", 
-                    m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                    (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), (uint64_t) m_cfa);
-    }
+    UnwindLogMsg ("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64,
+            (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), (uint64_t) m_cfa);
 }
 
 
@@ -632,9 +559,9 @@ RegisterContextLLDB::IsFrameZero () cons
 
 // Find a fast unwind plan for this frame, if possible.
 //
-// On entry to this method, 
+// On entry to this method,
 //
-//   1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct, 
+//   1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct,
 //   2. m_sym_ctx should already be filled in, and
 //   3. m_current_pc should have the current pc value for this frame
 //   4. m_current_offset_backed_up_one should have the current byte offset into the function, maybe backed up by 1, -1 if unknown
@@ -655,7 +582,7 @@ RegisterContextLLDB::GetFastUnwindPlanFo
     if (!func_unwinders_sp)
         return unwind_plan_sp;
 
-    // If we're in _sigtramp(), unwinding past this frame requires special knowledge.  
+    // If we're in _sigtramp(), unwinding past this frame requires special knowledge.
     if (m_frame_type == eSigtrampFrame || m_frame_type == eDebuggerFrame)
         return unwind_plan_sp;
 
@@ -664,19 +591,18 @@ RegisterContextLLDB::GetFastUnwindPlanFo
     {
         if (unwind_plan_sp->PlanValidAtAddress (m_current_pc))
         {
-            LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+            Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
             if (log && log->GetVerbose())
             {
-                const char *has_fast = "";
                 if (m_fast_unwind_plan_sp)
-                    has_fast = ", and has a fast UnwindPlan";
-                log->Printf("%*sFrame %u frame%s",
-                            m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, has_fast);
+                    UnwindLogMsgVerbose ("frame, and has a fast UnwindPlan");
+                else
+                    UnwindLogMsgVerbose ("frame");
             }
             m_frame_type = eNormalFrame;
             return unwind_plan_sp;
         }
-        else 
+        else
         {
             unwind_plan_sp.reset();
         }
@@ -684,9 +610,9 @@ RegisterContextLLDB::GetFastUnwindPlanFo
     return unwind_plan_sp;
 }
 
-// On entry to this method, 
+// On entry to this method,
 //
-//   1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct, 
+//   1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct,
 //   2. m_sym_ctx should already be filled in, and
 //   3. m_current_pc should have the current pc value for this frame
 //   4. m_current_offset_backed_up_one should have the current byte offset into the function, maybe backed up by 1, -1 if unknown
@@ -695,7 +621,6 @@ UnwindPlanSP
 RegisterContextLLDB::GetFullUnwindPlanForFrame ()
 {
     UnwindPlanSP unwind_plan_sp;
-    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
     UnwindPlanSP arch_default_unwind_plan_sp;
     ExecutionContext exe_ctx(m_thread.shared_from_this());
     Process *process = exe_ctx.GetProcessPtr();
@@ -707,12 +632,12 @@ RegisterContextLLDB::GetFullUnwindPlanFo
     }
 
     bool behaves_like_zeroth_frame = false;
-    if (IsFrameZero () 
+    if (IsFrameZero ()
         || GetNextFrame()->m_frame_type == eSigtrampFrame
         || GetNextFrame()->m_frame_type == eDebuggerFrame)
     {
         behaves_like_zeroth_frame = true;
-        // If this frame behaves like a 0th frame (currently executing or 
+        // If this frame behaves like a 0th frame (currently executing or
         // interrupted asynchronously), all registers can be retrieved.
         m_all_registers_available = true;
     }
@@ -721,7 +646,7 @@ RegisterContextLLDB::GetFullUnwindPlanFo
     // in the zeroth frame, we need to use the "unwind at first instruction" arch default UnwindPlan
     // Also, if this Process can report on memory region attributes, any non-executable region means
     // we jumped through a bad function pointer - handle the same way as 0x0.
-    // Note, if the symbol context has a function for the symbol, then we don't need to do this check. 
+    // Note, if the symbol context has a function for the symbol, then we don't need to do this check.
 
     if ((!m_sym_ctx_valid  || m_sym_ctx.function == NULL) && behaves_like_zeroth_frame && m_current_pc.IsValid())
     {
@@ -777,17 +702,13 @@ RegisterContextLLDB::GetFullUnwindPlanFo
     // right thing.  It'd be nice if there was a way to ask the eh_frame directly if it is asynchronous
     // (can be trusted at every instruction point) or synchronous (the normal case - only at call sites).
     // But there is not.
-    if (process->GetDynamicLoader() && process->GetDynamicLoader()->AlwaysRelyOnEHUnwindInfo (m_sym_ctx))
+    if (process && process->GetDynamicLoader() && process->GetDynamicLoader()->AlwaysRelyOnEHUnwindInfo (m_sym_ctx))
     {
         unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one);
         if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
         {
-            if (log && log->GetVerbose())
-            {
-                log->Printf("%*sFrame %u frame uses %s for full UnwindPlan because the DynamicLoader suggested we prefer it",
-                            m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                            unwind_plan_sp->GetSourceName().GetCString());
-            }
+            UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan because the DynamicLoader suggested we prefer it",
+                           unwind_plan_sp->GetSourceName().GetCString());
             return unwind_plan_sp;
         }
     }
@@ -798,12 +719,7 @@ RegisterContextLLDB::GetFullUnwindPlanFo
         unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (m_thread);
         if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
         {
-            if (log && log->GetVerbose())
-            {
-                log->Printf("%*sFrame %u frame uses %s for full UnwindPlan",
-                            m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                            unwind_plan_sp->GetSourceName().GetCString());
-            }
+            UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString());
             return unwind_plan_sp;
         }
     }
@@ -812,36 +728,21 @@ RegisterContextLLDB::GetFullUnwindPlanFo
     unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one);
     if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
     {
-        if (log && log->GetVerbose())
-        {
-            log->Printf("%*sFrame %u frame uses %s for full UnwindPlan",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                        unwind_plan_sp->GetSourceName().GetCString());
-        }
+        UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString());
         return unwind_plan_sp;
     }
-    
+
     // We'd prefer to use an UnwindPlan intended for call sites when we're at a call site but if we've
     // struck out on that, fall back to using the non-call-site assembly inspection UnwindPlan if possible.
     unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (m_thread);
     if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
     {
-        if (log && log->GetVerbose())
-        {
-            log->Printf("%*sFrame %u frame uses %s for full UnwindPlan",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                        unwind_plan_sp->GetSourceName().GetCString());
-        }
+        UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString());
         return unwind_plan_sp;
     }
 
     // If nothing else, use the architectural default UnwindPlan and hope that does the job.
-    if (log && log->GetVerbose())
-    {
-        log->Printf("%*sFrame %u frame uses %s for full UnwindPlan",
-                    m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                    arch_default_unwind_plan_sp->GetSourceName().GetCString());
-    }
+    UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", arch_default_unwind_plan_sp->GetSourceName().GetCString());
     return arch_default_unwind_plan_sp;
 }
 
@@ -859,7 +760,7 @@ RegisterContextLLDB::GetRegisterCount ()
 }
 
 const RegisterInfo *
-RegisterContextLLDB::GetRegisterInfoAtIndex (uint32_t reg)
+RegisterContextLLDB::GetRegisterInfoAtIndex (size_t reg)
 {
     return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex (reg);
 }
@@ -871,7 +772,7 @@ RegisterContextLLDB::GetRegisterSetCount
 }
 
 const RegisterSet *
-RegisterContextLLDB::GetRegisterSet (uint32_t reg_set)
+RegisterContextLLDB::GetRegisterSet (size_t reg_set)
 {
     return m_thread.GetRegisterContext()->GetRegisterSet (reg_set);
 }
@@ -883,7 +784,7 @@ RegisterContextLLDB::ConvertRegisterKind
 }
 
 bool
-RegisterContextLLDB::ReadRegisterValueFromRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc, 
+RegisterContextLLDB::ReadRegisterValueFromRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
                                                             const RegisterInfo *reg_info,
                                                             RegisterValue &value)
 {
@@ -896,11 +797,11 @@ RegisterContextLLDB::ReadRegisterValueFr
     case UnwindLLDB::RegisterLocation::eRegisterInRegister:
         {
             const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number);
-            
+
             if (!other_reg_info)
                 return false;
-            
-            if (IsFrameZero ()) 
+
+            if (IsFrameZero ())
             {
                 success = m_thread.GetRegisterContext()->ReadRegister (other_reg_info, value);
             }
@@ -913,7 +814,7 @@ RegisterContextLLDB::ReadRegisterValueFr
     case UnwindLLDB::RegisterLocation::eRegisterValueInferred:
         success = value.SetUInt (regloc.location.inferred_value, reg_info->byte_size);
         break;
-            
+
     case UnwindLLDB::RegisterLocation::eRegisterNotSaved:
         break;
     case UnwindLLDB::RegisterLocation::eRegisterSavedAtHostMemoryLocation:
@@ -921,9 +822,9 @@ RegisterContextLLDB::ReadRegisterValueFr
         break;
     case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation:
         {
-            Error error (ReadRegisterValueFromMemory(reg_info, 
-                                                     regloc.location.target_memory_location, 
-                                                     reg_info->byte_size, 
+            Error error (ReadRegisterValueFromMemory(reg_info,
+                                                     regloc.location.target_memory_location,
+                                                     reg_info->byte_size,
                                                      value));
             success = error.Success();
         }
@@ -936,7 +837,7 @@ RegisterContextLLDB::ReadRegisterValueFr
 }
 
 bool
-RegisterContextLLDB::WriteRegisterValueToRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc, 
+RegisterContextLLDB::WriteRegisterValueToRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
                                                            const RegisterInfo *reg_info,
                                                            const RegisterValue &value)
 {
@@ -944,13 +845,13 @@ RegisterContextLLDB::WriteRegisterValueT
         return false;
 
     bool success = false;
-    
+
     switch (regloc.type)
     {
         case UnwindLLDB::RegisterLocation::eRegisterInRegister:
             {
                 const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number);
-                if (IsFrameZero ()) 
+                if (IsFrameZero ())
                 {
                     success = m_thread.GetRegisterContext()->WriteRegister (other_reg_info, value);
                 }
@@ -968,9 +869,9 @@ RegisterContextLLDB::WriteRegisterValueT
             break;
         case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation:
             {
-                Error error (WriteRegisterValueToMemory (reg_info, 
-                                                         regloc.location.target_memory_location, 
-                                                         reg_info->byte_size, 
+                Error error (WriteRegisterValueToMemory (reg_info,
+                                                         regloc.location.target_memory_location,
+                                                         reg_info->byte_size,
                                                          value));
                 success = error.Success();
             }
@@ -992,7 +893,7 @@ RegisterContextLLDB::IsValid () const
 // A skip frame is a bogus frame on the stack -- but one where we're likely to find a real frame farther
 // up the stack if we keep looking.  It's always the second frame in an unwind (i.e. the first frame after
 // frame zero) where unwinding can be the trickiest.  Ideally we'll mark up this frame in some way so the
-// user knows we're displaying bad data and we may have skipped one frame of their real program in the 
+// user knows we're displaying bad data and we may have skipped one frame of their real program in the
 // process of getting back on track.
 
 bool
@@ -1003,11 +904,9 @@ RegisterContextLLDB::IsSkipFrame () cons
 
 // Answer the question: Where did THIS frame save the CALLER frame ("previous" frame)'s register value?
 
-bool
-RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc, bool check_next_frame)
+enum UnwindLLDB::RegisterSearchResult
+RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc)
 {
-    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
-
     // Have we already found this register location?
     if (!m_registers.empty())
     {
@@ -1016,22 +915,32 @@ RegisterContextLLDB::SavedLocationForReg
         if (iterator != m_registers.end())
         {
             regloc = iterator->second;
-            return true;
+            UnwindLogMsg ("supplying caller's saved reg %d's location, cached", lldb_regnum);
+            return UnwindLLDB::RegisterSearchResult::eRegisterFound;
         }
     }
 
+    static uint32_t sp_regnum = LLDB_INVALID_REGNUM;
+    static uint32_t pc_regnum = LLDB_INVALID_REGNUM;
+    static bool generic_registers_initialized = false;
+    if (!generic_registers_initialized)
+    {
+        m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, eRegisterKindLLDB, sp_regnum);
+        m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, eRegisterKindLLDB, pc_regnum);
+        generic_registers_initialized = true;
+    }
+
     // Are we looking for the CALLER's stack pointer?  The stack pointer is defined to be the same as THIS frame's
     // CFA so just return the CFA value.  This is true on x86-32/x86-64 at least.
-    uint32_t sp_regnum;
-    if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, eRegisterKindLLDB, sp_regnum)
-        && sp_regnum == lldb_regnum)
+    if (sp_regnum != LLDB_INVALID_REGNUM && sp_regnum == lldb_regnum)
     {
         // make sure we won't lose precision copying an addr_t (m_cfa) into a uint64_t (.inferred_value)
         assert (sizeof (addr_t) <= sizeof (uint64_t));
         regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
         regloc.location.inferred_value = m_cfa;
         m_registers[lldb_regnum] = regloc;
-        return true;
+        UnwindLogMsg ("supplying caller's stack pointer (%d) value, computed from CFA", lldb_regnum);
+        return UnwindLLDB::RegisterSearchResult::eRegisterFound;
     }
 
     // Look through the available UnwindPlans for the register location.
@@ -1047,22 +956,13 @@ RegisterContextLLDB::SavedLocationForReg
         uint32_t row_regnum;
         if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum))
         {
-            if (log)
-            {
-                log->Printf("%*sFrame %u could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
-                            m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                            lldb_regnum, (int) unwindplan_registerkind);
-            }
-            return false;
+            UnwindLogMsg ("could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
+                    lldb_regnum, (int) unwindplan_registerkind);
+            return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
         }
         if (active_row->GetRegisterInfo (row_regnum, unwindplan_regloc))
         {
-            if (log)
-            {
-                log->Printf("%*sFrame %u supplying caller's saved reg %d's location using FastUnwindPlan",
-                            m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                            lldb_regnum);
-            }
+            UnwindLogMsg ("supplying caller's saved reg %d's location using FastUnwindPlan", lldb_regnum);
             have_unwindplan_regloc = true;
         }
     }
@@ -1078,41 +978,111 @@ RegisterContextLLDB::SavedLocationForReg
             UnwindPlan::RowSP active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
             unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind ();
             uint32_t row_regnum;
-            if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum))
+            bool row_register_rewritten_to_return_address_reg = false;
+
+            // If we're fetching the saved pc and this UnwindPlan defines a ReturnAddress register (e.g. lr on arm),
+            // look for the return address register number in the UnwindPlan's row.
+            if (lldb_regnum == pc_regnum && m_full_unwind_plan_sp->GetReturnAddressRegister() != LLDB_INVALID_REGNUM)
+            {
+               row_regnum = m_full_unwind_plan_sp->GetReturnAddressRegister();
+               row_register_rewritten_to_return_address_reg = true;
+               UnwindLogMsg ("requested caller's saved PC but this UnwindPlan uses a RA reg; getting reg %d instead",
+                       row_regnum);
+            }
+            else
             {
-                if (log)
+                if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum))
                 {
                     if (unwindplan_registerkind == eRegisterKindGeneric)
-                        log->Printf("%*sFrame %u could not convert lldb regnum %d into eRegisterKindGeneric reg numbering scheme",
-                                    m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                                    lldb_regnum);
+                        UnwindLogMsg ("could not convert lldb regnum %d into eRegisterKindGeneric reg numbering scheme", lldb_regnum);
                     else
-                        log->Printf("%*sFrame %u could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
-                                    m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                                    lldb_regnum, (int) unwindplan_registerkind);
+                        UnwindLogMsg ("could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
+                                lldb_regnum, (int) unwindplan_registerkind);
+                    return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
                 }
-                return false;
             }
 
             if (active_row->GetRegisterInfo (row_regnum, unwindplan_regloc))
             {
                 have_unwindplan_regloc = true;
-                if (log)
-                {                
-                    log->Printf("%*sFrame %u supplying caller's saved reg %d's location using %s UnwindPlan",
-                                m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                                lldb_regnum, m_full_unwind_plan_sp->GetSourceName().GetCString());
+                UnwindLogMsg ("supplying caller's saved reg %d's location using %s UnwindPlan", lldb_regnum,
+                              m_full_unwind_plan_sp->GetSourceName().GetCString());
+            }
+
+            // This is frame 0 and we're retrieving the PC and it's saved in a Return Address register and
+            // it hasn't been saved anywhere yet -- that is, it's still live in the actual register.
+            // Handle this specially.
+
+            if (have_unwindplan_regloc == false 
+                && row_register_rewritten_to_return_address_reg == true 
+                && IsFrameZero()
+                && row_regnum != LLDB_INVALID_REGNUM)
+            {
+                uint32_t ra_regnum_in_lldb_reg_numbering;
+                if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (unwindplan_registerkind, row_regnum, eRegisterKindLLDB, ra_regnum_in_lldb_reg_numbering))
+                {
+                    lldb_private::UnwindLLDB::RegisterLocation new_regloc;
+                    new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister;
+                    new_regloc.location.register_number = ra_regnum_in_lldb_reg_numbering;
+                    m_registers[lldb_regnum] = new_regloc;
+                    regloc = new_regloc;
+                    UnwindLogMsg ("supplying caller's register %d from the live RegisterContext at frame 0, saved in %d", lldb_regnum, ra_regnum_in_lldb_reg_numbering);
+                    return UnwindLLDB::RegisterSearchResult::eRegisterFound;
+                }
+            }
+
+            // If this architecture stores the return address in a register (it defines a Return Address register)
+            // and we're on a non-zero stack frame and the Full UnwindPlan says that the pc is stored in the
+            // RA registers (e.g. lr on arm), then we know that the full unwindplan is not trustworthy -- this
+            // is an impossible situation and the instruction emulation code has likely been misled.  
+            // If this stack frame meets those criteria, we need to throw away the Full UnwindPlan that the 
+            // instruction emulation came up with and fall back to the architecture's Default UnwindPlan so
+            // the stack walk can get past this point.
+
+            // Special note:  If the Full UnwindPlan was generated from the compiler, don't second-guess it 
+            // when we're at a call site location.
+
+            // arch_default_ra_regnum is the return address register # in the Full UnwindPlan register numbering
+            uint32_t arch_default_ra_regnum = LLDB_INVALID_REGNUM; 
+            if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, unwindplan_registerkind, arch_default_ra_regnum)
+                && arch_default_ra_regnum != LLDB_INVALID_REGNUM
+                && pc_regnum != LLDB_INVALID_REGNUM
+                && pc_regnum == lldb_regnum
+                && unwindplan_regloc.IsInOtherRegister()
+                && unwindplan_regloc.GetRegisterNumber() == arch_default_ra_regnum
+                && m_full_unwind_plan_sp->GetSourcedFromCompiler() != eLazyBoolYes
+                && !m_all_registers_available)
+            {
+                UnwindLogMsg ("%s UnwindPlan tried to restore the pc from the link register but this is a non-zero frame",
+                              m_full_unwind_plan_sp->GetSourceName().GetCString());
+
+                // Throw away the full unwindplan; install the arch default unwindplan
+                InvalidateFullUnwindPlan();
+
+                // Now re-fetch the pc value we're searching for
+                uint32_t arch_default_pc_reg = LLDB_INVALID_REGNUM;
+                UnwindPlan::RowSP active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
+                if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, m_full_unwind_plan_sp->GetRegisterKind(), arch_default_pc_reg)
+                    && arch_default_pc_reg != LLDB_INVALID_REGNUM
+                    && active_row
+                    && active_row->GetRegisterInfo (arch_default_pc_reg, unwindplan_regloc))
+                {
+                    have_unwindplan_regloc = true;
+                }
+                else
+                {
+                    have_unwindplan_regloc = false;
                 }
             }
         }
     }
-    
-    
+
+
     ExecutionContext exe_ctx(m_thread.shared_from_this());
     Process *process = exe_ctx.GetProcessPtr();
     if (have_unwindplan_regloc == false)
     {
-        // If a volatile register is being requested, we don't want to forward the next frame's register contents 
+        // If a volatile register is being requested, we don't want to forward the next frame's register contents
         // up the stack -- the register is not retrievable at this frame.
         ABI *abi = process ? process->GetABI().get() : NULL;
         if (abi)
@@ -1120,14 +1090,9 @@ RegisterContextLLDB::SavedLocationForReg
             const RegisterInfo *reg_info = GetRegisterInfoAtIndex(lldb_regnum);
             if (reg_info && abi->RegisterIsVolatile (reg_info))
             {
-                if (log && log->GetVerbose ())
-                {
-                    log->Printf("%*sFrame %u did not supply reg location for %d because it is volatile",
-                                m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                                lldb_regnum);
-                }
-                return false;
-            }  
+                UnwindLogMsg ("did not supply reg location for %d because it is volatile", lldb_regnum);
+                return UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile;
+            }
         }
 
         if (IsFrameZero ())
@@ -1138,20 +1103,12 @@ RegisterContextLLDB::SavedLocationForReg
             new_regloc.location.register_number = lldb_regnum;
             m_registers[lldb_regnum] = new_regloc;
             regloc = new_regloc;
-            return true;
+            UnwindLogMsg ("supplying caller's register %d from the live RegisterContext at frame 0", lldb_regnum);
+            return UnwindLLDB::RegisterSearchResult::eRegisterFound;
         }
         else
-        {
-            if (check_next_frame)
-                return m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1);
-        }
-        if (log)
-        {
-            log->Printf("%*sFrame %u could not supply caller's reg %d location",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                        lldb_regnum);
-        }
-        return false;
+        UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
+        return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
     }
 
     // unwindplan_regloc has valid contents about where to retrieve the register
@@ -1160,33 +1117,20 @@ RegisterContextLLDB::SavedLocationForReg
         lldb_private::UnwindLLDB::RegisterLocation new_regloc;
         new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterNotSaved;
         m_registers[lldb_regnum] = new_regloc;
-        if (log)
-        {
-            log->Printf("%*sFrame %u could not supply caller's reg %d location",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                        lldb_regnum);
-        }
-        return false;
+        UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
+        return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
     }
 
     if (unwindplan_regloc.IsSame())
     {
         if (IsFrameZero ())
         {
-            if (log)
-            {
-                log->Printf("%*sFrame %u could not supply caller's reg %d location",
-                            m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                            lldb_regnum);
-            }
-            return false;
+            UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
+            return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
         }
         else
         {
-            if (check_next_frame)
-                return m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1);
-            else
-                return false;
+            return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
         }
     }
 
@@ -1196,7 +1140,8 @@ RegisterContextLLDB::SavedLocationForReg
         regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
         regloc.location.inferred_value = m_cfa + offset;
         m_registers[lldb_regnum] = regloc;
-        return true;
+        UnwindLogMsg ("supplying caller's register %d, value is CFA plus offset", lldb_regnum);
+        return UnwindLLDB::RegisterSearchResult::eRegisterFound;
     }
 
     if (unwindplan_regloc.IsAtCFAPlusOffset())
@@ -1205,7 +1150,8 @@ RegisterContextLLDB::SavedLocationForReg
         regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation;
         regloc.location.target_memory_location = m_cfa + offset;
         m_registers[lldb_regnum] = regloc;
-        return true;
+        UnwindLogMsg ("supplying caller's register %d from the stack, saved at CFA plus offset", lldb_regnum);
+        return UnwindLLDB::RegisterSearchResult::eRegisterFound;
     }
 
     if (unwindplan_regloc.IsInOtherRegister())
@@ -1214,24 +1160,20 @@ RegisterContextLLDB::SavedLocationForReg
         uint32_t row_regnum_in_lldb;
         if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (unwindplan_registerkind, unwindplan_regnum, eRegisterKindLLDB, row_regnum_in_lldb))
         {
-            if (log)
-            {
-                log->Printf("%*sFrame %u could not supply caller's reg %d location",
-                            m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                            lldb_regnum);
-            }
-            return false;
+            UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
+            return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
         }
         regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister;
         regloc.location.register_number = row_regnum_in_lldb;
         m_registers[lldb_regnum] = regloc;
-        return true;
+        UnwindLogMsg ("supplying caller's register %d, saved in register %d", lldb_regnum, row_regnum_in_lldb);
+        return UnwindLLDB::RegisterSearchResult::eRegisterFound;
     }
 
     if (unwindplan_regloc.IsDWARFExpression() || unwindplan_regloc.IsAtDWARFExpression())
     {
-        DataExtractor dwarfdata (unwindplan_regloc.GetDWARFExpressionBytes(), 
-                                 unwindplan_regloc.GetDWARFExpressionLength(), 
+        DataExtractor dwarfdata (unwindplan_regloc.GetDWARFExpressionBytes(),
+                                 unwindplan_regloc.GetDWARFExpressionLength(),
                                  process->GetByteOrder(), process->GetAddressByteSize());
         DWARFExpression dwarfexpr (dwarfdata, 0, unwindplan_regloc.GetDWARFExpressionLength());
         dwarfexpr.SetRegisterKind (unwindplan_registerkind);
@@ -1246,38 +1188,81 @@ RegisterContextLLDB::SavedLocationForReg
                 regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
                 regloc.location.inferred_value = val;
                 m_registers[lldb_regnum] = regloc;
-                return true;
+                UnwindLogMsg ("supplying caller's register %d via DWARF expression (IsDWARFExpression)", lldb_regnum);
+                return UnwindLLDB::RegisterSearchResult::eRegisterFound;
             }
             else
             {
-               regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation;
-               regloc.location.target_memory_location = val;
-               m_registers[lldb_regnum] = regloc;
-               return true;
+                regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation;
+                regloc.location.target_memory_location = val;
+                m_registers[lldb_regnum] = regloc;
+                UnwindLogMsg ("supplying caller's register %d via DWARF expression (IsAtDWARFExpression)", lldb_regnum);
+                return UnwindLLDB::RegisterSearchResult::eRegisterFound;
             }
         }
-        if (log)
-        {
-            log->Printf("%*sFrame %u tried to use IsDWARFExpression or IsAtDWARFExpression for reg %d but failed",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                        lldb_regnum);
-        }
-        return false;
+        UnwindLogMsg ("tried to use IsDWARFExpression or IsAtDWARFExpression for reg %d but failed", lldb_regnum);
+        return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
     }
 
-    if (log)
+    UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
+
+    // FIXME UnwindPlan::Row types atDWARFExpression and isDWARFExpression are unsupported.
+
+    return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
+}
+
+// If the Full unwindplan has been determined to be incorrect, this method will
+// replace it with the architecture's default unwindplna, if one is defined.
+// It will also find the FuncUnwinders object for this function and replace the
+// Full unwind method for the function there so we don't use the errant Full unwindplan
+// again in the future of this debug session.
+// We're most likely doing this because the Full unwindplan was generated by assembly
+// instruction profiling and the profiler got something wrong.
+
+void
+RegisterContextLLDB::InvalidateFullUnwindPlan ()
+{
+    UnwindPlan::Row::RegisterLocation unwindplan_regloc;
+    ExecutionContext exe_ctx (m_thread.shared_from_this());
+    Process *process = exe_ctx.GetProcessPtr();
+    ABI *abi = process ? process->GetABI().get() : NULL;
+    if (abi)
     {
-        log->Printf("%*sFrame %u could not supply caller's reg %d location",
-                    m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                    lldb_regnum);
-    }
+        UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp;
+        UnwindPlanSP arch_default_unwind_plan_sp;
+        arch_default_unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+        abi->CreateDefaultUnwindPlan(*arch_default_unwind_plan_sp);
+        if (arch_default_unwind_plan_sp)
+        {
+            UnwindPlan::RowSP active_row = arch_default_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
+        
+            if (active_row && active_row->GetCFARegister() != LLDB_INVALID_REGNUM)
+            {
+                FuncUnwindersSP func_unwinders_sp;
+                if (m_sym_ctx_valid && m_current_pc.IsValid() && m_current_pc.GetModule())
+                {
+                    func_unwinders_sp = m_current_pc.GetModule()->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx);
+                    if (func_unwinders_sp)
+                    {
+                        func_unwinders_sp->InvalidateNonCallSiteUnwindPlan (m_thread);
+                    }
+                }
+                m_registers.clear();
+                m_full_unwind_plan_sp = arch_default_unwind_plan_sp;
+                addr_t cfa_regval;
+                if (ReadGPRValue (arch_default_unwind_plan_sp->GetRegisterKind(), active_row->GetCFARegister(), cfa_regval))
+                {
+                    m_cfa = cfa_regval + active_row->GetCFAOffset ();
+                }
 
-    
-    // assert ("UnwindPlan::Row types atDWARFExpression and isDWARFExpression are unsupported.");
-    return false;
+                UnwindLogMsg ("full unwind plan '%s' has been replaced by architecture default unwind plan '%s' for this function from now on.",
+                              original_full_unwind_plan_sp->GetSourceName().GetCString(), arch_default_unwind_plan_sp->GetSourceName().GetCString());
+            }
+        }
+    }
 }
 
-// Retrieve a general purpose register value for THIS from, as saved by the NEXT frame, i.e. the frame that
+// Retrieve a general purpose register value for THIS frame, as saved by the NEXT frame, i.e. the frame that
 // this frame called.  e.g.
 //
 //  foo () { }
@@ -1320,8 +1305,20 @@ RegisterContextLLDB::ReadGPRValue (int r
         return false;
     }
 
+    bool pc_register = false;
+    uint32_t generic_regnum;
+    if (register_kind == eRegisterKindGeneric && regnum == LLDB_REGNUM_GENERIC_PC)
+    {
+        pc_register = true;
+    }
+    else if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (register_kind, regnum, eRegisterKindGeneric, generic_regnum)
+             && generic_regnum == LLDB_REGNUM_GENERIC_PC)
+    {
+        pc_register = true;
+    }
+
     lldb_private::UnwindLLDB::RegisterLocation regloc;
-    if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1))
+    if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, pc_register))
     {
         return false;
     }
@@ -1338,33 +1335,22 @@ RegisterContextLLDB::ReadGPRValue (int r
 bool
 RegisterContextLLDB::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value)
 {
-    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
     if (!IsValid())
         return false;
 
     const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB];
-    if (log && log->GetVerbose ())
-    {
-        log->Printf("%*sFrame %u looking for register saved location for reg %d",
-                    m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                    lldb_regnum);
-    }
+    UnwindLogMsgVerbose ("looking for register saved location for reg %d", lldb_regnum);
 
     // If this is the 0th frame, hand this over to the live register context
     if (IsFrameZero ())
     {
-        if (log && log->GetVerbose ())
-        {
-            log->Printf("%*sFrame %u passing along to the live register context for reg %d",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                        lldb_regnum);
-        }
+        UnwindLogMsgVerbose ("passing along to the live register context for reg %d", lldb_regnum);
         return m_thread.GetRegisterContext()->ReadRegister (reg_info, value);
     }
 
     lldb_private::UnwindLLDB::RegisterLocation regloc;
     // Find out where the NEXT frame saved THIS frame's register contents
-    if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1))
+    if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, false))
         return false;
 
     return ReadRegisterValueFromRegisterLocation (regloc, reg_info, value);
@@ -1373,33 +1359,22 @@ RegisterContextLLDB::ReadRegister (const
 bool
 RegisterContextLLDB::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &value)
 {
-    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
     if (!IsValid())
         return false;
 
     const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB];
-    if (log && log->GetVerbose ())
-    {
-        log->Printf("%*sFrame %u looking for register saved location for reg %d",
-                    m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                    lldb_regnum);
-    }
+    UnwindLogMsgVerbose ("looking for register saved location for reg %d", lldb_regnum);
 
     // If this is the 0th frame, hand this over to the live register context
     if (IsFrameZero ())
     {
-        if (log && log->GetVerbose ())
-        {
-            log->Printf("%*sFrame %u passing along to the live register context for reg %d",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                        lldb_regnum);
-        }
+        UnwindLogMsgVerbose ("passing along to the live register context for reg %d", lldb_regnum);
         return m_thread.GetRegisterContext()->WriteRegister (reg_info, value);
     }
 
     lldb_private::UnwindLLDB::RegisterLocation regloc;
     // Find out where the NEXT frame saved THIS frame's register contents
-    if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1))
+    if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, false))
         return false;
 
     return WriteRegisterValueToRegisterLocation (regloc, reg_info, value);
@@ -1463,7 +1438,7 @@ RegisterContextLLDB::GetStartPC (addr_t&
 
     if (!m_start_pc.IsValid())
     {
-        return ReadPC (start_pc); 
+        return ReadPC (start_pc);
     }
     start_pc = m_start_pc.GetLoadAddress (CalculateTarget().get());
     return true;
@@ -1484,12 +1459,12 @@ RegisterContextLLDB::ReadPC (addr_t& pc)
         // occur if code has jumped through a NULL pointer -- we want to be able to unwind past that frame to help
         // find the bug.
 
-        if (m_all_registers_available == false 
+        if (m_all_registers_available == false
             && (pc == 0 || pc == 1))
         {
             return false;
         }
-        else 
+        else
         {
             return true;
         }
@@ -1499,3 +1474,57 @@ RegisterContextLLDB::ReadPC (addr_t& pc)
         return false;
     }
 }
+
+
+void
+RegisterContextLLDB::UnwindLogMsg (const char *fmt, ...)
+{
+    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+    if (log)
+    {
+        va_list args;
+        va_start (args, fmt);
+
+        char *logmsg;
+        if (vasprintf (&logmsg, fmt, args) == -1 || logmsg == NULL)
+        {
+            if (logmsg)
+                free (logmsg);
+            va_end (args);
+            return;
+        }
+        va_end (args);
+
+        log->Printf ("%*sth%d/fr%u %s",
+                      m_frame_number < 100 ? m_frame_number : 100, "", m_thread.GetIndexID(), m_frame_number,
+                      logmsg);
+        free (logmsg);
+    }
+}
+
+void
+RegisterContextLLDB::UnwindLogMsgVerbose (const char *fmt, ...)
+{
+    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+    if (log && log->GetVerbose())
+    {
+        va_list args;
+        va_start (args, fmt);
+
+        char *logmsg;
+        if (vasprintf (&logmsg, fmt, args) == -1 || logmsg == NULL)
+        {
+            if (logmsg)
+                free (logmsg);
+            va_end (args);
+            return;
+        }
+        va_end (args);
+
+        log->Printf ("%*sth%d/fr%u %s",
+                      m_frame_number < 100 ? m_frame_number : 100, "", m_thread.GetIndexID(), m_frame_number,
+                      logmsg);
+        free (logmsg);
+    }
+}
+

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextLLDB.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextLLDB.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextLLDB.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextLLDB.h Thu Jun  6 19:06:43 2013
@@ -25,7 +25,7 @@ class UnwindLLDB;
 class RegisterContextLLDB : public lldb_private::RegisterContext
 {
 public:
-    typedef STD_SHARED_PTR(RegisterContextLLDB) SharedPtr;
+    typedef std::shared_ptr<RegisterContextLLDB> SharedPtr;
 
     RegisterContextLLDB (lldb_private::Thread &thread,
                          const SharedPtr& next_frame,
@@ -46,20 +46,20 @@ public:
     GetRegisterCount ();
 
     virtual const lldb_private::RegisterInfo *
-    GetRegisterInfoAtIndex (uint32_t reg);
+    GetRegisterInfoAtIndex (size_t reg);
 
     virtual size_t
     GetRegisterSetCount ();
 
     virtual const lldb_private::RegisterSet *
-    GetRegisterSet (uint32_t reg_set);
+    GetRegisterSet (size_t reg_set);
 
     virtual bool
     ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
 
     virtual bool
     WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
-    
+
     virtual bool
     ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
 
@@ -96,14 +96,14 @@ private:
     friend class UnwindLLDB;
 
     // Indicates whether this frame is frame zero -- the currently
-    // executing frame -- or not.  
+    // executing frame -- or not.
     bool
     IsFrameZero () const;
 
-    void 
+    void
     InitializeZerothFrame ();
 
-    void 
+    void
     InitializeNonZerothFrame();
 
     SharedPtr
@@ -112,7 +112,7 @@ private:
     SharedPtr
     GetPrevFrame () const;
 
-    // A SkipFrame occurs when the unwind out of frame 0 didn't go right -- we've got one bogus frame at frame #1.  
+    // A SkipFrame occurs when the unwind out of frame 0 didn't go right -- we've got one bogus frame at frame #1.
     // There is a good chance we'll get back on track if we follow the frame pointer chain (or whatever is appropriate
     // on this ABI) so we allow one invalid frame to be in the stack.  Ideally we'll mark this frame specially at some
     // point and indicate to the user that the unwinder had a hiccup.  Often when this happens we will miss a frame of
@@ -124,32 +124,30 @@ private:
     // Or a frame "below" this one saved it, i.e. a function called by this one, preserved a register that this
     // function didn't modify/use.
     //
-    // The RegisterLocation type may be set to eRegisterNotAvailable -- this will happen for a volatile register 
+    // The RegisterLocation type may be set to eRegisterNotAvailable -- this will happen for a volatile register
     // being queried mid-stack.  Instead of floating frame 0's contents of that register up the stack (which may
     // or may not be the value of that reg when the function was executing), we won't return any value.
     //
     // If a non-volatile register (a "preserved" register) is requested mid-stack and no frames "below" the requested
     // stack have saved the register anywhere, it is safe to assume that frame 0's register values are still the same
     // as the requesting frame's.
-    //
-    // NB this function takes a "check_next_frame" boolean which indicates whether it should call back to the
-    // containing UnwindLLDB object to iterate the search down the stack (true) or if this call should look for
-    // a register save for that reg in the current frame only (false).  Allows UnwindLLDB to iterate through the
-    // RegisterContextLLDB's instead of using recursion to find saved register values.
-    bool
-    SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc, bool check_next_frame);
+    lldb_private::UnwindLLDB::RegisterSearchResult
+    SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc);
 
     bool
-    ReadRegisterValueFromRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc, 
+    ReadRegisterValueFromRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
                                            const lldb_private::RegisterInfo *reg_info,
                                            lldb_private::RegisterValue &value);
 
     bool
-    WriteRegisterValueToRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc, 
+    WriteRegisterValueToRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
                                           const lldb_private::RegisterInfo *reg_info,
                                           const lldb_private::RegisterValue &value);
 
-    // Get the contents of a general purpose (address-size) register for this frame 
+    void
+    InvalidateFullUnwindPlan ();
+
+    // Get the contents of a general purpose (address-size) register for this frame
     // (usually retrieved from the next frame)
     bool
     ReadGPRValue (int register_kind, uint32_t regnum, lldb::addr_t &value);
@@ -160,8 +158,14 @@ private:
     lldb::UnwindPlanSP
     GetFullUnwindPlanForFrame ();
 
+    void
+    UnwindLogMsg (const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
+
+    void
+    UnwindLogMsgVerbose (const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
+
     lldb_private::Thread& m_thread;
-    
+
     ///
     // The following tell us how to retrieve the CALLER's register values (ie the "previous" frame, aka the frame above)
     // i.e. where THIS frame saved them
@@ -182,7 +186,7 @@ private:
     int m_current_offset_backed_up_one;           // how far into the function we've executed; -1 if unknown
                                                   // 0 if no instructions have been executed yet.
                                                   // On architectures where the return address on the stack points
-                                                  // to the instruction after the CALL, this value will have 1 
+                                                  // to the instruction after the CALL, this value will have 1
                                                   // subtracted from it.  Else a function that ends in a CALL will
                                                   // have an offset pointing into the next function's address range.
                                                   // m_current_pc has the actual address of the "current" pc.

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp Thu Jun  6 19:06:43 2013
@@ -59,7 +59,7 @@ RegisterContextMacOSXFrameBackchain::Get
 }
 
 const RegisterInfo *
-RegisterContextMacOSXFrameBackchain::GetRegisterInfoAtIndex (uint32_t reg)
+RegisterContextMacOSXFrameBackchain::GetRegisterInfoAtIndex (size_t reg)
 {
     return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg);
 }
@@ -73,7 +73,7 @@ RegisterContextMacOSXFrameBackchain::Get
 
 
 const RegisterSet *
-RegisterContextMacOSXFrameBackchain::GetRegisterSet (uint32_t reg_set)
+RegisterContextMacOSXFrameBackchain::GetRegisterSet (size_t reg_set)
 {
     return m_thread.GetRegisterContext()->GetRegisterSet (reg_set);
 }

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h Thu Jun  6 19:06:43 2013
@@ -42,13 +42,13 @@ public:
     GetRegisterCount ();
 
     virtual const lldb_private::RegisterInfo *
-    GetRegisterInfoAtIndex (uint32_t reg);
+    GetRegisterInfoAtIndex (size_t reg);
 
     virtual size_t
     GetRegisterSetCount ();
 
     virtual const lldb_private::RegisterSet *
-    GetRegisterSet (uint32_t reg_set);
+    GetRegisterSet (size_t reg_set);
 
     virtual bool
     ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMemory.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMemory.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMemory.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMemory.cpp Thu Jun  6 19:06:43 2013
@@ -61,7 +61,8 @@ RegisterContextMemory::~RegisterContextM
 void
 RegisterContextMemory::InvalidateAllRegisters ()
 {
-    SetAllRegisterValid (false);
+    if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
+        SetAllRegisterValid (false);
 }
 
 void
@@ -79,7 +80,7 @@ RegisterContextMemory::GetRegisterCount
 }
 
 const RegisterInfo *
-RegisterContextMemory::GetRegisterInfoAtIndex (uint32_t reg)
+RegisterContextMemory::GetRegisterInfoAtIndex (size_t reg)
 {
     return m_reg_infos.GetRegisterInfoAtIndex (reg);
 }
@@ -91,7 +92,7 @@ RegisterContextMemory::GetRegisterSetCou
 }
 
 const RegisterSet *
-RegisterContextMemory::GetRegisterSet (uint32_t reg_set)
+RegisterContextMemory::GetRegisterSet (size_t reg_set)
 {
     return m_reg_infos.GetRegisterSet (reg_set);
 }
@@ -164,3 +165,10 @@ RegisterContextMemory::WriteAllRegisterV
     }
     return false;
 }
+
+void
+RegisterContextMemory::SetAllRegisterData  (const lldb::DataBufferSP &data_sp)
+{
+    m_reg_data.SetData(data_sp);
+    SetAllRegisterValid (true);    
+}

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMemory.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMemory.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMemory.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMemory.h Thu Jun  6 19:06:43 2013
@@ -46,13 +46,13 @@ public:
     GetRegisterCount ();
 
     virtual const lldb_private::RegisterInfo *
-    GetRegisterInfoAtIndex (uint32_t reg);
+    GetRegisterInfoAtIndex (size_t reg);
 
     virtual size_t
     GetRegisterSetCount ();
 
     virtual const lldb_private::RegisterSet *
-    GetRegisterSet (uint32_t reg_set);
+    GetRegisterSet (size_t reg_set);
 
     virtual uint32_t
     ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
@@ -60,7 +60,7 @@ public:
     
     //------------------------------------------------------------------
     // If all of the thread register are in a contiguous buffer in 
-    // memory, then the default ReadRegister/WriteRegiter and
+    // memory, then the default ReadRegister/WriteRegister and
     // ReadAllRegisterValues/WriteAllRegisterValues will work. If thread
     // registers are not contiguous, clients will want to subclass this
     // class and modify the read/write functions as needed.
@@ -80,6 +80,8 @@ public:
     virtual bool
     WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
 
+    void
+    SetAllRegisterData  (const lldb::DataBufferSP &data_sp);
 protected:
     
     void

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/StopInfoMachException.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/StopInfoMachException.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/StopInfoMachException.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/StopInfoMachException.cpp Thu Jun  6 19:06:43 2013
@@ -16,6 +16,8 @@
 #include "lldb/Breakpoint/Watchpoint.h"
 #include "lldb/Core/ArchSpec.h"
 #include "lldb/Core/StreamString.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/DynamicLoader.h"
 #include "lldb/Target/ExecutionContext.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/RegisterContext.h"
@@ -32,7 +34,7 @@ StopInfoMachException::GetDescription ()
 {
     if (m_description.empty() && m_value != 0)
     {
-        ExecutionContext exe_ctx (m_thread.shared_from_this());
+        ExecutionContext exe_ctx (m_thread_wp.lock());
         Target *target = exe_ctx.GetTargetPtr();
         const llvm::Triple::ArchType cpu = target ? target->GetArchitecture().GetMachine() : llvm::Triple::UnknownArch;
 
@@ -47,7 +49,14 @@ StopInfoMachException::GetDescription ()
             exc_desc = "EXC_BAD_ACCESS";
             subcode_label = "address";
             switch (cpu)
-            {                        
+            {
+            case llvm::Triple::x86:
+            case llvm::Triple::x86_64:
+                switch (m_exc_code)
+                {
+                case 0xd: code_desc = "EXC_I386_GPFLT"; m_exc_data_count = 1; break;
+                }
+                break;
             case llvm::Triple::arm:
                 switch (m_exc_code)
                 {
@@ -184,6 +193,8 @@ StopInfoMachException::GetDescription ()
                     case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break;
                     case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break;
                     case 1: code_desc = "EXC_ARM_BREAKPOINT"; break;
+                    // FIXME temporary workaround, exc_code 0 does not really mean EXC_ARM_BREAKPOINT
+                    case 0: code_desc = "EXC_ARM_BREAKPOINT"; break;
                     }
                     break;
 
@@ -208,6 +219,12 @@ StopInfoMachException::GetDescription ()
         case 10:
             exc_desc = "EXC_CRASH";
             break;
+        case 11:
+            exc_desc = "EXC_RESOURCE";
+            break;
+        case 12:
+            exc_desc = "EXC_GUARD";
+            break;
         }
         
         StreamString strm;
@@ -215,14 +232,14 @@ StopInfoMachException::GetDescription ()
         if (exc_desc)
             strm.PutCString(exc_desc);
         else
-            strm.Printf("EXC_??? (%llu)", m_value);
+            strm.Printf("EXC_??? (%" PRIu64 ")", m_value);
 
         if (m_exc_data_count >= 1)
         {
             if (code_desc)
                 strm.Printf(" (%s=%s", code_label, code_desc);
             else
-                strm.Printf(" (%s=%llu", code_label, m_exc_code);
+                strm.Printf(" (%s=%" PRIu64, code_label, m_exc_code);
         }
 
         if (m_exc_data_count >= 2)
@@ -230,7 +247,7 @@ StopInfoMachException::GetDescription ()
             if (subcode_desc)
                 strm.Printf(", %s=%s", subcode_label, subcode_desc);
             else
-                strm.Printf(", %s=0x%llx", subcode_label, m_exc_subcode);
+                strm.Printf(", %s=0x%" PRIx64, subcode_label, m_exc_subcode);
         }
         
         if (m_exc_data_count > 0)
@@ -242,6 +259,9 @@ StopInfoMachException::GetDescription ()
 }
 
 
+
+
+
 StopInfoSP
 StopInfoMachException::CreateStopReasonWithMachException 
 (
@@ -250,11 +270,14 @@ StopInfoMachException::CreateStopReasonW
     uint32_t exc_data_count,
     uint64_t exc_code,
     uint64_t exc_sub_code,
-    uint64_t exc_sub_sub_code
+    uint64_t exc_sub_sub_code,
+    bool pc_already_adjusted,
+    bool adjust_pc_if_needed
 )
 {
     if (exc_type != 0)
     {
+        uint32_t pc_decrement = 0;
         ExecutionContext exe_ctx (thread.shared_from_this());
         Target *target = exe_ctx.GetTargetPtr();
         const llvm::Triple::ArchType cpu = target ? target->GetArchitecture().GetMachine() : llvm::Triple::UnknownArch;
@@ -294,12 +317,45 @@ StopInfoMachException::CreateStopReasonW
 
         case 5: // EXC_SOFTWARE
             if (exc_code == 0x10003) // EXC_SOFT_SIGNAL
+            {
+                if (exc_sub_code == 5)
+                {
+                    // On MacOSX, a SIGTRAP can signify that a process has called
+                    // exec, so we should check with our dynamic loader to verify.
+                    ProcessSP process_sp (thread.GetProcess());
+                    if (process_sp)
+                    {
+                        DynamicLoader *dynamic_loader = process_sp->GetDynamicLoader();
+                        if (dynamic_loader && dynamic_loader->ProcessDidExec())
+                        {
+                            // The program was re-exec'ed
+                            return StopInfo::CreateStopReasonWithExec (thread);
+                        }
+//                        if (!process_did_exec)
+//                        {
+//                            // We have a SIGTRAP, make sure we didn't exec by checking
+//                            // for the PC being at "_dyld_start"...
+//                            lldb::StackFrameSP frame_sp (thread.GetStackFrameAtIndex(0));
+//                            if (frame_sp)
+//                            {
+//                                const Symbol *symbol = frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol;
+//                                if (symbol)
+//                                {
+//                                    if (symbol->GetName() == ConstString("_dyld_start"))
+//                                        process_did_exec = true;
+//                                }
+//                            }
+//                        }
+                    }
+                }
                 return StopInfo::CreateStopReasonWithSignal (thread, exc_sub_code);
+            }
             break;
         
         case 6: // EXC_BREAKPOINT
             {
-                bool is_software_breakpoint = false;
+                bool is_actual_breakpoint = false;
+                bool is_trace_if_actual_breakpoint_missing = false;
                 switch (cpu)
                 {
                 case llvm::Triple::x86:
@@ -323,19 +379,26 @@ StopInfoMachException::CreateStopReasonW
                             return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID());
                         }
                     }
-                    else if (exc_code == 2) // EXC_I386_BPT
+                    else if (exc_code == 2 ||   // EXC_I386_BPT
+                             exc_code == 3)     // EXC_I386_BPTFLT
                     {
-                        is_software_breakpoint = true;
+                        // KDP returns EXC_I386_BPTFLT for trace breakpoints
+                        if (exc_code == 3)
+                            is_trace_if_actual_breakpoint_missing = true;
+
+                        is_actual_breakpoint = true;
+                        if (!pc_already_adjusted)
+                            pc_decrement = 1;
                     }
                     break;
 
                 case llvm::Triple::ppc:
                 case llvm::Triple::ppc64:
-                    is_software_breakpoint = exc_code == 1; // EXC_PPC_BREAKPOINT
+                    is_actual_breakpoint = exc_code == 1; // EXC_PPC_BREAKPOINT
                     break;
                 
                 case llvm::Triple::arm:
-                    if (exc_code == 0x102)
+                    if (exc_code == 0x102) // EXC_ARM_DA_DEBUG
                     {
                         // It's a watchpoint, then, if the exc_sub_code indicates a known/enabled
                         // data break address from our watchpoint list.
@@ -351,26 +414,43 @@ StopInfoMachException::CreateStopReasonW
                             return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID());
                         }
                         // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as EXC_BAD_ACCESS
-                        return StopInfo::CreateStopReasonToTrace(thread);
+                        if (thread.GetTemporaryResumeState() == eStateStepping)
+                            return StopInfo::CreateStopReasonToTrace(thread);
+                    }
+                    else if (exc_code == 1) // EXC_ARM_BREAKPOINT
+                    {
+                        is_actual_breakpoint = true;
+                        is_trace_if_actual_breakpoint_missing = true;
+                    }
+                    else if (exc_code == 0) // FIXME not EXC_ARM_BREAKPOINT but a kernel is currently returning this so accept it as indicating a breakpoint until the kernel is fixed
+                    {
+                        is_actual_breakpoint = true;
+                        is_trace_if_actual_breakpoint_missing = true;
                     }
-                    else
-                        is_software_breakpoint = exc_code == 1; // EXC_ARM_BREAKPOINT
                     break;
 
                 default:
                     break;
                 }
 
-                if (is_software_breakpoint)
+                if (is_actual_breakpoint)
                 {
-                    addr_t pc = thread.GetRegisterContext()->GetPC();
+                    RegisterContextSP reg_ctx_sp (thread.GetRegisterContext());
+                    addr_t pc = reg_ctx_sp->GetPC() - pc_decrement;
+
                     ProcessSP process_sp (thread.CalculateProcess());
 
                     lldb::BreakpointSiteSP bp_site_sp;
                     if (process_sp)
                         bp_site_sp = process_sp->GetBreakpointSiteList().FindByAddress(pc);
-                    if (bp_site_sp)
+                    if (bp_site_sp && bp_site_sp->IsEnabled())
                     {
+                        // Update the PC if we were asked to do so, but only do
+                        // so if we find a breakpoint that we know about cause
+                        // this could be a trap instruction in the code
+                        if (pc_decrement > 0 && adjust_pc_if_needed)
+                            reg_ctx_sp->SetPC (pc);
+
                         // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
                         // we can just report no reason.  We don't need to worry about stepping over the breakpoint here, that
                         // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
@@ -379,7 +459,9 @@ StopInfoMachException::CreateStopReasonW
                         else
                             return StopInfoSP();
                     }
-                    else if (cpu == llvm::Triple::arm)
+                    
+                    // Don't call this a trace if we weren't single stepping this thread.
+                    if (is_trace_if_actual_breakpoint_missing && thread.GetTemporaryResumeState() == eStateStepping)
                     {
                         return StopInfo::CreateStopReasonToTrace (thread);
                     }

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/StopInfoMachException.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/StopInfoMachException.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/StopInfoMachException.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/StopInfoMachException.h Thu Jun  6 19:06:43 2013
@@ -61,8 +61,10 @@ public:
                                        uint32_t exc_data_count,
                                        uint64_t exc_code, 
                                        uint64_t exc_sub_code,
-                                       uint64_t exc_sub_sub_code);
-    
+                                       uint64_t exc_sub_sub_code,
+                                       bool pc_already_adjusted = true,
+                                       bool adjust_pc_if_needed = false);
+
 protected:
     uint32_t m_exc_data_count;
     uint64_t m_exc_code;

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/ThreadMemory.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/ThreadMemory.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/ThreadMemory.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/ThreadMemory.cpp Thu Jun  6 19:06:43 2013
@@ -13,48 +13,67 @@
 #include "lldb/Target/Process.h"
 #include "lldb/Target/StopInfo.h"
 #include "lldb/Target/Unwind.h"
+#include "Plugins/Process/Utility/RegisterContextThreadMemory.h"
 
 using namespace lldb;
 using namespace lldb_private;
 
-ThreadMemory::ThreadMemory (const ProcessSP &process_sp, 
-                              tid_t tid, 
-                              const ValueObjectSP &thread_info_valobj_sp) :
-    Thread (process_sp, tid),
-    m_thread_info_valobj_sp (thread_info_valobj_sp)
+ThreadMemory::ThreadMemory (Process &process,
+                            tid_t tid,
+                            const ValueObjectSP &thread_info_valobj_sp) :
+    Thread (process, tid),
+    m_backing_thread_sp (),
+    m_thread_info_valobj_sp (thread_info_valobj_sp),
+    m_name(),
+    m_queue()
 {
 }
 
 
+ThreadMemory::ThreadMemory (Process &process,
+                            lldb::tid_t tid,
+                            const char *name,
+                            const char *queue,
+                            lldb::addr_t register_data_addr) :
+    Thread (process, tid),
+    m_backing_thread_sp (),
+    m_thread_info_valobj_sp (),
+    m_name(),
+    m_queue(),
+    m_register_data_addr (register_data_addr)
+{
+    if (name)
+        m_name = name;
+    if (queue)
+        m_queue = queue;
+}
+
+
 ThreadMemory::~ThreadMemory()
 {
     DestroyThread();
 }
 
-bool
+void
 ThreadMemory::WillResume (StateType resume_state)
 {
-    ClearStackFrames();
-    // Call the Thread::WillResume first. If we stop at a signal, the stop info
-    // class for signal will set the resume signal that we need below. The signal
-    // stuff obeys the Process::UnixSignal defaults. 
-    Thread::WillResume(resume_state);
-    return true;
+    if (m_backing_thread_sp)
+        m_backing_thread_sp->WillResume(resume_state);
+}
+
+void
+ThreadMemory::ClearStackFrames ()
+{
+    if (m_backing_thread_sp)
+        m_backing_thread_sp->ClearStackFrames();
+    Thread::ClearStackFrames();
 }
 
 RegisterContextSP
 ThreadMemory::GetRegisterContext ()
 {
     if (!m_reg_context_sp)
-    {
-        ProcessSP process_sp (GetProcess());
-        if (process_sp)
-        {
-            OperatingSystem *os = process_sp->GetOperatingSystem ();
-            if (os)
-                m_reg_context_sp = os->CreateRegisterContextForThread (this);
-        }
-    }
+        m_reg_context_sp.reset (new RegisterContextThreadMemory (*this, m_register_data_addr));
     return m_reg_context_sp;
 }
 
@@ -71,51 +90,51 @@ ThreadMemory::CreateRegisterContextForFr
     {
         reg_ctx_sp = GetRegisterContext ();
     }
-    else if (m_unwinder_ap.get())
+    else
     {
-        reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame (frame);
+        Unwind *unwinder = GetUnwinder ();
+        if (unwinder)
+            reg_ctx_sp = unwinder->CreateRegisterContextForFrame (frame);
     }
     return reg_ctx_sp;
 }
 
-lldb::StopInfoSP
-ThreadMemory::GetPrivateStopReason ()
+bool
+ThreadMemory::CalculateStopInfo ()
 {
-    ProcessSP process_sp (GetProcess());
-
-    if (process_sp)
+    if (m_backing_thread_sp)
     {
-        const uint32_t process_stop_id = process_sp->GetStopID();
-        if (m_thread_stop_reason_stop_id != process_stop_id ||
-            (m_actual_stop_info_sp && !m_actual_stop_info_sp->IsValid()))
+        lldb::StopInfoSP backing_stop_info_sp (m_backing_thread_sp->GetPrivateStopInfo());
+        if (backing_stop_info_sp)
+        {
+            backing_stop_info_sp->SetThread (shared_from_this());
+            SetStopInfo (backing_stop_info_sp);
+            return true;
+        }
+    }
+    else
+    {
+        ProcessSP process_sp (GetProcess());
+
+        if (process_sp)
         {
-            // If GetGDBProcess().SetThreadStopInfo() doesn't find a stop reason
-            // for this thread, then m_actual_stop_info_sp will not ever contain
-            // a valid stop reason and the "m_actual_stop_info_sp->IsValid() == false"
-            // check will never be able to tell us if we have the correct stop info
-            // for this thread and we will continually send qThreadStopInfo packets
-            // down to the remote GDB server, so we need to keep our own notion
-            // of the stop ID that m_actual_stop_info_sp is valid for (even if it
-            // contains nothing). We use m_thread_stop_reason_stop_id for this below.
-            m_thread_stop_reason_stop_id = process_stop_id;
-            m_actual_stop_info_sp.reset();
-            
             OperatingSystem *os = process_sp->GetOperatingSystem ();
             if (os)
-                m_actual_stop_info_sp = os->CreateThreadStopReason (this);
+            {
+                SetStopInfo (os->CreateThreadStopReason (this));
+                return true;
+            }
         }
     }
-    return m_actual_stop_info_sp;
-    
+    return false;
 }
 
 void
 ThreadMemory::RefreshStateAfterStop()
 {
-    RegisterContextSP reg_ctx_sp(GetRegisterContext());
-    if (reg_ctx_sp)
-    {
-        const bool force = true;
-        reg_ctx_sp->InvalidateIfNeeded (force);
-    }
+    if (m_backing_thread_sp)
+        return m_backing_thread_sp->RefreshStateAfterStop();
+    
+    if (m_reg_context_sp)
+        m_reg_context_sp->InvalidateAllRegisters();
 }

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/ThreadMemory.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/ThreadMemory.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/ThreadMemory.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/ThreadMemory.h Thu Jun  6 19:06:43 2013
@@ -17,43 +17,131 @@ class ThreadMemory :
 {
 public:
 
-    ThreadMemory (const lldb::ProcessSP &process_sp, 
+    ThreadMemory (lldb_private::Process &process,
                   lldb::tid_t tid,
                   const lldb::ValueObjectSP &thread_info_valobj_sp);
 
-    virtual 
+    ThreadMemory (lldb_private::Process &process,
+                  lldb::tid_t tid,
+                  const char *name,
+                  const char *queue,
+                  lldb::addr_t register_data_addr);
+
+    virtual
     ~ThreadMemory();
 
     //------------------------------------------------------------------
     // lldb_private::Thread methods
     //------------------------------------------------------------------
-    virtual void
-    RefreshStateAfterStop();
-
     virtual lldb::RegisterContextSP
     GetRegisterContext ();
 
     virtual lldb::RegisterContextSP
     CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
 
-    virtual lldb::StopInfoSP
-    GetPrivateStopReason ();
-
     virtual bool
+    CalculateStopInfo ();
+
+    virtual const char *
+    GetInfo ()
+    {
+        if (m_backing_thread_sp)
+            m_backing_thread_sp->GetInfo();
+        return NULL;
+    }
+
+    virtual const char *
+    GetName ()
+    {
+        if (!m_name.empty())
+            return m_name.c_str();
+        if (m_backing_thread_sp)
+            m_backing_thread_sp->GetName();
+        return NULL;
+    }
+    
+    virtual const char *
+    GetQueueName ()
+    {
+        if (!m_queue.empty())
+            return m_queue.c_str();
+        if (m_backing_thread_sp)
+            m_backing_thread_sp->GetQueueName();
+        return NULL;
+    }
+
+    virtual void
     WillResume (lldb::StateType resume_state);
 
+    virtual void
+    DidResume ()
+    {
+        if (m_backing_thread_sp)
+            m_backing_thread_sp->DidResume();
+    }
+    
+    virtual lldb::user_id_t
+    GetProtocolID () const
+    {
+        if (m_backing_thread_sp)
+            return m_backing_thread_sp->GetProtocolID();
+        return Thread::GetProtocolID();
+    }
+
+    virtual void
+    RefreshStateAfterStop();
+    
     lldb::ValueObjectSP &
     GetValueObject ()
     {
         return m_thread_info_valobj_sp;
     }
+    
+    virtual void
+    ClearStackFrames ();
+
+    virtual void
+    ClearBackingThread ()
+    {
+        m_backing_thread_sp.reset();
+    }
+
+    virtual bool
+    SetBackingThread (const lldb::ThreadSP &thread_sp)
+    {
+        //printf ("Thread 0x%llx is being backed by thread 0x%llx\n", GetID(), thread_sp->GetID());
+        m_backing_thread_sp = thread_sp;
+        return (bool)thread_sp;
+    }
+    
+    virtual lldb::ThreadSP
+    GetBackingThread () const
+    {
+        return m_backing_thread_sp;
+    }
 
 protected:
+    
+    virtual bool
+    IsOperatingSystemPluginThread () const
+    {
+        return true;
+    }
+    
+
     //------------------------------------------------------------------
     // For ThreadMemory and subclasses
     //------------------------------------------------------------------
+    // If this memory thread is actually represented by a thread from the
+    // lldb_private::Process subclass, then fill in the thread here and
+    // all APIs will be routed through this thread object. If m_backing_thread_sp
+    // is empty, then this thread is simply in memory with no representation
+    // through the process plug-in.
+    lldb::ThreadSP m_backing_thread_sp;
     lldb::ValueObjectSP m_thread_info_valobj_sp;
-    
+    std::string m_name;
+    std::string m_queue;
+    lldb::addr_t m_register_data_addr;
 private:
     //------------------------------------------------------------------
     // For ThreadMemory only

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindLLDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindLLDB.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindLLDB.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindLLDB.cpp Thu Jun  6 19:06:43 2013
@@ -53,7 +53,7 @@ UnwindLLDB::DoGetFrameCount()
             {
                 TimeValue now(TimeValue::Now());
                 uint64_t delta_t = now - time_value;
-                printf ("%u frames in %llu.%09llu ms (%g frames/sec)\n", 
+                printf ("%u frames in %" PRIu64 ".%09llu ms (%g frames/sec)\n",
                         FRAME_COUNT,
                         delta_t / TimeValue::NanoSecPerSec, 
                         delta_t % TimeValue::NanoSecPerSec,
@@ -108,7 +108,7 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
     if (m_unwind_complete)
         return false;
         
-    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
     CursorSP cursor_sp(new Cursor ());
 
     // Frame zero is a little different
@@ -121,6 +121,22 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
                                                               cursor_sp->sctx, 
                                                               cur_idx, 
                                                               *this));
+
+    // We want to detect an unwind that cycles erronously and stop backtracing.
+    // Don't want this maximum unwind limit to be too low -- if you have a backtrace
+    // with an "infinitely recursing" bug, it will crash when the stack blows out
+    // and the first 35,000 frames are uninteresting - it's the top most 5 frames that
+    // you actually care about.  So you can't just cap the unwind at 10,000 or something.
+    // Realistically anything over around 200,000 is going to blow out the stack space.
+    // If we're still unwinding at that point, we're probably never going to finish.
+    if (cur_idx > 300000)
+    {
+        if (log)
+            log->Printf ("%*sFrame %d unwound too many frames, assuming unwind has gone astray, stopping.", 
+                         cur_idx < 100 ? cur_idx : 100, "", cur_idx);
+        goto unwind_done;
+    }
+
     if (reg_ctx_sp.get() == NULL)
         goto unwind_done;
 
@@ -175,7 +191,7 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
         {
             if (m_frames.back()->cfa == cursor_sp->cfa)
                 goto unwind_done; // Infinite loop where the current cursor is the same as the previous one...
-            else if (abi->StackUsesFrames())
+            else if (abi && abi->StackUsesFrames())
             {
                 // We might have a CFA that is not using the frame pointer and
                 // we want to validate that the frame pointer is valid.
@@ -262,15 +278,44 @@ UnwindLLDB::GetRegisterContextForFrameNu
 }
 
 bool
-UnwindLLDB::SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc, uint32_t starting_frame_num)
+UnwindLLDB::SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc, uint32_t starting_frame_num, bool pc_reg)
 {
     int64_t frame_num = starting_frame_num;
     if (frame_num >= m_frames.size())
         return false;
+
+    // Never interrogate more than one level while looking for the saved pc value.  If the value
+    // isn't saved by frame_num, none of the frames lower on the stack will have a useful value.
+    if (pc_reg)
+    {
+        UnwindLLDB::RegisterSearchResult result;
+        result = m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc);
+        if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound)
+          return true;
+        else
+          return false;
+    }
     while (frame_num >= 0)
     {
-        if (m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc, false))
+        UnwindLLDB::RegisterSearchResult result;
+        result = m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc);
+
+        // If we have unwind instructions saying that register N is saved in register M in the middle of
+        // the stack (and N can equal M here, meaning the register was not used in this function), then
+        // change the register number we're looking for to M and keep looking for a concrete  location 
+        // down the stack, or an actual value from a live RegisterContext at frame 0.
+        if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound
+            && regloc.type == UnwindLLDB::RegisterLocation::eRegisterInRegister
+            && frame_num > 0)
+        {
+            result = UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
+            lldb_regnum = regloc.location.register_number;
+        }
+
+        if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound)
             return true;
+        if (result == UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile)
+            return false;
         frame_num--;
     }
     return false;

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindLLDB.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindLLDB.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindLLDB.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindLLDB.h Thu Jun  6 19:06:43 2013
@@ -30,6 +30,13 @@ public:
     virtual
     ~UnwindLLDB() { }
 
+    enum RegisterSearchResult
+    {
+        eRegisterFound = 0,
+        eRegisterNotFound,
+        eRegisterIsVolatile
+    };
+
 protected:
     friend class lldb_private::RegisterContextLLDB;
 
@@ -70,7 +77,7 @@ protected:
     lldb::RegisterContextSP
     DoCreateRegisterContextForFrame (lldb_private::StackFrame *frame);
 
-    typedef STD_SHARED_PTR(RegisterContextLLDB) RegisterContextLLDBSP;
+    typedef std::shared_ptr<RegisterContextLLDB> RegisterContextLLDBSP;
 
     // Needed to retrieve the "next" frame (e.g. frame 2 needs to retrieve frame 1's RegisterContextLLDB)
     // The RegisterContext for frame_num must already exist or this returns an empty shared pointer.
@@ -80,7 +87,7 @@ protected:
     // Iterate over the RegisterContextLLDB's in our m_frames vector, look for the first one that
     // has a saved location for this reg.
     bool
-    SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc, uint32_t starting_frame_num);
+    SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc, uint32_t starting_frame_num, bool pc_register);
 
 
 private:
@@ -97,7 +104,7 @@ private:
         DISALLOW_COPY_AND_ASSIGN (Cursor);
     };
 
-    typedef STD_SHARED_PTR(Cursor) CursorSP;
+    typedef std::shared_ptr<Cursor> CursorSP;
     std::vector<CursorSP> m_frames;
     bool m_unwind_complete; // If this is true, we've enumerated all the frames in the stack, and m_frames.size() is the 
                             // number of frames, etc.  Otherwise we've only gone as far as directly asked, and m_frames.size()

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp Thu Jun  6 19:06:43 2013
@@ -12,6 +12,9 @@
 // Other libraries and framework includes
 // Project includes
 #include "lldb/Core/ArchSpec.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Target/ExecutionContext.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/Target.h"
@@ -173,7 +176,7 @@ UnwindMacOSXFrameBackchain::GetStackFram
 //    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);
+//        printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64 "\n", i, m_cursors[i].pc, m_cursors[i].fp);
 //    }
     return m_cursors.size();
 }

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp Thu Jun  6 19:06:43 2013
@@ -92,7 +92,7 @@ GDBRemoteCommunication::History::Dump (l
         const Entry &entry = m_packets[idx];
         if (entry.type == ePacketTypeInvalid || entry.packet.empty())
             break;
-        strm.Printf ("history[%u] tid=0x%4.4llx <%4u> %s packet: %s\n",
+        strm.Printf ("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s\n",
                      entry.packet_idx,
                      entry.tid,
                      entry.bytes_transmitted,
@@ -116,7 +116,7 @@ GDBRemoteCommunication::History::Dump (l
             const Entry &entry = m_packets[idx];
             if (entry.type == ePacketTypeInvalid || entry.packet.empty())
                 break;
-            log->Printf ("history[%u] tid=0x%4.4llx <%4u> %s packet: %s",
+            log->Printf ("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s",
                          entry.packet_idx,
                          entry.tid,
                          entry.bytes_transmitted,
@@ -175,7 +175,7 @@ GDBRemoteCommunication::CalculcateChecks
 size_t
 GDBRemoteCommunication::SendAck ()
 {
-    LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
     ConnectionStatus status = eConnectionStatusSuccess;
     char ch = '+';
     const size_t bytes_written = Write (&ch, 1, status, NULL);
@@ -188,7 +188,7 @@ GDBRemoteCommunication::SendAck ()
 size_t
 GDBRemoteCommunication::SendNack ()
 {
-    LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
     ConnectionStatus status = eConnectionStatusSuccess;
     char ch = '-';
     const size_t bytes_written = Write (&ch, 1, status, NULL);
@@ -217,7 +217,7 @@ GDBRemoteCommunication::SendPacketNoLock
         packet.PutChar('#');
         packet.PutHex8(CalculcateChecksum (payload, payload_length));
 
-        LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
+        Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
         ConnectionStatus status = eConnectionStatusSuccess;
         size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL);
         if (log)
@@ -227,7 +227,7 @@ GDBRemoteCommunication::SendPacketNoLock
             // logs all of the packet will set a boolean so that we don't dump this more
             // than once
             if (!m_history.DidDumpToLog ())
-                m_history.Dump (log.get());
+                m_history.Dump (log);
 
             log->Printf ("<%4zu> send packet: %.*s", bytes_written, (int)packet.GetSize(), packet.GetData());
         }
@@ -289,7 +289,7 @@ GDBRemoteCommunication::WaitForPacketWit
     uint8_t buffer[8192];
     Error error;
 
-    LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE));
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE));
 
     // Check for a packet from our cache first without trying any reading...
     if (CheckForPacket (NULL, 0, packet))
@@ -302,12 +302,12 @@ GDBRemoteCommunication::WaitForPacketWit
         size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error);
         
         if (log)
-            log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %zu",
+            log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %" PRIu64,
                          __PRETTY_FUNCTION__,
                          timeout_usec, 
                          Communication::ConnectionStatusAsCString (status),
                          error.AsCString(), 
-                         bytes_read);
+                         (uint64_t)bytes_read);
 
         if (bytes_read > 0)
         {
@@ -344,7 +344,7 @@ GDBRemoteCommunication::CheckForPacket (
     // Put the packet data into the buffer in a thread safe fashion
     Mutex::Locker locker(m_bytes_mutex);
     
-    LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
 
     if (src && src_len > 0)
     {
@@ -461,7 +461,7 @@ GDBRemoteCommunication::CheckForPacket (
                 // logs all of the packet will set a boolean so that we don't dump this more
                 // than once
                 if (!m_history.DidDumpToLog ())
-                    m_history.Dump (log.get());
+                    m_history.Dump (log);
                 
                 log->Printf ("<%4zu> read packet: %.*s", total_length, (int)(total_length), m_bytes.c_str());
             }

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp Thu Jun  6 19:06:43 2013
@@ -12,6 +12,8 @@
 
 // C Includes
 // C++ Includes
+#include <sstream>
+
 // Other libraries and framework includes
 #include "llvm/ADT/Triple.h"
 #include "lldb/Interpreter/Args.h"
@@ -47,9 +49,11 @@ GDBRemoteCommunicationClient::GDBRemoteC
     m_supports_vCont_s (eLazyBoolCalculate),
     m_supports_vCont_S (eLazyBoolCalculate),
     m_qHostInfo_is_valid (eLazyBoolCalculate),
+    m_qProcessInfo_is_valid (eLazyBoolCalculate),
     m_supports_alloc_dealloc_memory (eLazyBoolCalculate),
     m_supports_memory_region_info  (eLazyBoolCalculate),
     m_supports_watchpoint_support_info  (eLazyBoolCalculate),
+    m_supports_detach_stay_stopped (eLazyBoolCalculate),
     m_watchpoints_trigger_after_instruction(eLazyBoolCalculate),
     m_attach_or_wait_reply(eLazyBoolCalculate),
     m_prepare_for_reg_writing_reply (eLazyBoolCalculate),
@@ -71,7 +75,9 @@ GDBRemoteCommunicationClient::GDBRemoteC
     m_async_packet (),
     m_async_response (),
     m_async_signal (-1),
+    m_thread_id_to_used_usec_map (),
     m_host_arch(),
+    m_process_arch(),
     m_os_version_major (UINT32_MAX),
     m_os_version_minor (UINT32_MAX),
     m_os_version_update (UINT32_MAX)
@@ -188,6 +194,7 @@ GDBRemoteCommunicationClient::ResetDisco
     m_supports_vCont_s = eLazyBoolCalculate;
     m_supports_vCont_S = eLazyBoolCalculate;
     m_qHostInfo_is_valid = eLazyBoolCalculate;
+    m_qProcessInfo_is_valid = eLazyBoolCalculate;
     m_supports_alloc_dealloc_memory = eLazyBoolCalculate;
     m_supports_memory_region_info = eLazyBoolCalculate;
     m_prepare_for_reg_writing_reply = eLazyBoolCalculate;
@@ -204,6 +211,7 @@ GDBRemoteCommunicationClient::ResetDisco
     m_supports_z3 = true;
     m_supports_z4 = true;
     m_host_arch.Clear();
+    m_process_arch.Clear();
 }
 
 
@@ -305,7 +313,7 @@ GDBRemoteCommunicationClient::SendPacket
 )
 {
     Mutex::Locker locker;
-    LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
     size_t response_len = 0;
     if (GetSequenceMutex (locker))
     {
@@ -418,6 +426,99 @@ GDBRemoteCommunicationClient::SendPacket
     return response_len;
 }
 
+static const char *end_delimiter = "--end--;";
+static const int end_delimiter_len = 8;
+
+std::string
+GDBRemoteCommunicationClient::HarmonizeThreadIdsForProfileData
+(   ProcessGDBRemote *process,
+    StringExtractorGDBRemote& profileDataExtractor
+)
+{
+    std::map<uint64_t, uint32_t> new_thread_id_to_used_usec_map;
+    std::stringstream final_output;
+    std::string name, value;
+
+    // Going to assuming thread_used_usec comes first, else bail out.
+    while (profileDataExtractor.GetNameColonValue(name, value))
+    {
+        if (name.compare("thread_used_id") == 0)
+        {
+            StringExtractor threadIDHexExtractor(value.c_str());
+            uint64_t thread_id = threadIDHexExtractor.GetHexMaxU64(false, 0);
+            
+            bool has_used_usec = false;
+            uint32_t curr_used_usec = 0;
+            std::string usec_name, usec_value;
+            uint32_t input_file_pos = profileDataExtractor.GetFilePos();
+            if (profileDataExtractor.GetNameColonValue(usec_name, usec_value))
+            {
+                if (usec_name.compare("thread_used_usec") == 0)
+                {
+                    has_used_usec = true;
+                    curr_used_usec = strtoull(usec_value.c_str(), NULL, 0);
+                }
+                else
+                {
+                    // We didn't find what we want, it is probably
+                    // an older version. Bail out.
+                    profileDataExtractor.SetFilePos(input_file_pos);
+                }
+            }
+
+            if (has_used_usec)
+            {
+                uint32_t prev_used_usec = 0;
+                std::map<uint64_t, uint32_t>::iterator iterator = m_thread_id_to_used_usec_map.find(thread_id);
+                if (iterator != m_thread_id_to_used_usec_map.end())
+                {
+                    prev_used_usec = m_thread_id_to_used_usec_map[thread_id];
+                }
+                
+                uint32_t real_used_usec = curr_used_usec - prev_used_usec;
+                // A good first time record is one that runs for at least 0.25 sec
+                bool good_first_time = (prev_used_usec == 0) && (real_used_usec > 250000);
+                bool good_subsequent_time = (prev_used_usec > 0) &&
+                    ((real_used_usec > 0) || (process->HasAssignedIndexIDToThread(thread_id)));
+                
+                if (good_first_time || good_subsequent_time)
+                {
+                    // We try to avoid doing too many index id reservation,
+                    // resulting in fast increase of index ids.
+                    
+                    final_output << name << ":";
+                    int32_t index_id = process->AssignIndexIDToThread(thread_id);
+                    final_output << index_id << ";";
+                    
+                    final_output << usec_name << ":" << usec_value << ";";
+                }
+                else
+                {
+                    // Skip past 'thread_used_name'.
+                    std::string local_name, local_value;
+                    profileDataExtractor.GetNameColonValue(local_name, local_value);
+                }
+                
+                // Store current time as previous time so that they can be compared later.
+                new_thread_id_to_used_usec_map[thread_id] = curr_used_usec;
+            }
+            else
+            {
+                // Bail out and use old string.
+                final_output << name << ":" << value << ";";
+            }
+        }
+        else
+        {
+            final_output << name << ":" << value << ";";
+        }
+    }
+    final_output << end_delimiter;
+    m_thread_id_to_used_usec_map = new_thread_id_to_used_usec_map;
+    
+    return final_output.str();
+}
+
 StateType
 GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
 (
@@ -428,7 +529,7 @@ GDBRemoteCommunicationClient::SendContin
 )
 {
     m_curr_tid = LLDB_INVALID_THREAD_ID;
-    LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
     if (log)
         log->Printf ("GDBRemoteCommunicationClient::%s ()", __FUNCTION__);
 
@@ -441,11 +542,11 @@ GDBRemoteCommunicationClient::SendContin
     // may change if we are interrupted and we continue after an async packet...
     std::string continue_packet(payload, packet_length);
     
-    bool got_stdout = false;
+    bool got_async_packet = false;
     
     while (state == eStateRunning)
     {
-        if (!got_stdout)
+        if (!got_async_packet)
         {
             if (log)
                 log->Printf ("GDBRemoteCommunicationClient::%s () sending continue packet: %s", __FUNCTION__, continue_packet.c_str());
@@ -455,7 +556,7 @@ GDBRemoteCommunicationClient::SendContin
             m_private_is_running.SetValue (true, eBroadcastAlways);
         }
         
-        got_stdout = false;
+        got_async_packet = false;
 
         if (log)
             log->Printf ("GDBRemoteCommunicationClient::%s () WaitForPacket(%s)", __FUNCTION__, continue_packet.c_str());
@@ -578,7 +679,7 @@ GDBRemoteCommunicationClient::SendContin
                         }
                         else if (m_async_packet_predicate.GetValue())
                         {
-                            LogSP packet_log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
+                            Log * packet_log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
 
                             // We are supposed to send an asynchronous packet while
                             // we are running. 
@@ -638,7 +739,7 @@ GDBRemoteCommunicationClient::SendContin
                 case 'O':
                     // STDOUT
                     {
-                        got_stdout = true;
+                        got_async_packet = true;
                         std::string inferior_stdout;
                         inferior_stdout.reserve(response.GetBytesLeft () / 2);
                         char ch;
@@ -648,6 +749,36 @@ GDBRemoteCommunicationClient::SendContin
                     }
                     break;
 
+                case 'A':
+                    // Async miscellaneous reply. Right now, only profile data is coming through this channel.
+                    {
+                        got_async_packet = true;
+                        std::string input = response.GetStringRef().substr(1); // '1' to move beyond 'A'
+                        if (m_partial_profile_data.length() > 0)
+                        {
+                            m_partial_profile_data.append(input);
+                            input = m_partial_profile_data;
+                            m_partial_profile_data.clear();
+                        }
+                        
+                        size_t found, pos = 0, len = input.length();
+                        while ((found = input.find(end_delimiter, pos)) != std::string::npos)
+                        {
+                            StringExtractorGDBRemote profileDataExtractor(input.substr(pos, found).c_str());
+                            const std::string& profile_data = HarmonizeThreadIdsForProfileData(process, profileDataExtractor);
+                            process->BroadcastAsyncProfileData (profile_data.c_str(), profile_data.length());
+                            
+                            pos = found + end_delimiter_len;
+                        }
+                        
+                        if (pos < len)
+                        {
+                            // Last incomplete chunk.
+                            m_partial_profile_data = input.substr(pos);
+                        }
+                    }
+                    break;
+
                 case 'E':
                     // ERROR
                     state = eStateInvalid;
@@ -708,7 +839,7 @@ GDBRemoteCommunicationClient::SendInterr
 )
 {
     timed_out = false;
-    LogSP log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS));
+    Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS));
 
     if (IsRunning())
     {
@@ -954,6 +1085,14 @@ GDBRemoteCommunicationClient::GetSystemA
     return ArchSpec();
 }
 
+const lldb_private::ArchSpec &
+GDBRemoteCommunicationClient::GetProcessArchitecture ()
+{
+    if (m_qProcessInfo_is_valid == eLazyBoolCalculate)
+        GetCurrentProcessInfo ();
+    return m_process_arch;
+}
+
 
 bool
 GDBRemoteCommunicationClient::GetHostInfo (bool force)
@@ -1189,7 +1328,7 @@ GDBRemoteCommunicationClient::SendAttach
     if (pid != LLDB_INVALID_PROCESS_ID)
     {
         char packet[64];
-        const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%llx", pid);
+        const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%" PRIx64, pid);
         assert (packet_len < sizeof(packet));
         if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
         {
@@ -1216,7 +1355,8 @@ GDBRemoteCommunicationClient::AllocateMe
     {
         m_supports_alloc_dealloc_memory = eLazyBoolYes;
         char packet[64];
-        const int packet_len = ::snprintf (packet, sizeof(packet), "_M%zx,%s%s%s", size,
+        const int packet_len = ::snprintf (packet, sizeof(packet), "_M%" PRIx64 ",%s%s%s",
+                                           (uint64_t)size,
                                            permissions & lldb::ePermissionsReadable ? "r" : "",
                                            permissions & lldb::ePermissionsWritable ? "w" : "",
                                            permissions & lldb::ePermissionsExecutable ? "x" : "");
@@ -1242,7 +1382,7 @@ GDBRemoteCommunicationClient::Deallocate
     {
         m_supports_alloc_dealloc_memory = eLazyBoolYes;
         char packet[64];
-        const int packet_len = ::snprintf(packet, sizeof(packet), "_m%llx", (uint64_t)addr);
+        const int packet_len = ::snprintf(packet, sizeof(packet), "_m%" PRIx64, (uint64_t)addr);
         assert (packet_len < sizeof(packet));
         StringExtractorGDBRemote response;
         if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
@@ -1258,10 +1398,48 @@ GDBRemoteCommunicationClient::Deallocate
     return false;
 }
 
-bool
-GDBRemoteCommunicationClient::Detach ()
+Error
+GDBRemoteCommunicationClient::Detach (bool keep_stopped)
 {
-    return SendPacket ("D", 1) > 0;
+    Error error;
+    
+    if (keep_stopped)
+    {
+        if (m_supports_detach_stay_stopped == eLazyBoolCalculate)
+        {
+            char packet[64];
+            const int packet_len = ::snprintf(packet, sizeof(packet), "qSupportsDetachAndStayStopped:");
+            assert (packet_len < sizeof(packet));
+            StringExtractorGDBRemote response;
+            if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+            {
+                m_supports_detach_stay_stopped = eLazyBoolYes;        
+            }
+            else
+            {
+                m_supports_detach_stay_stopped = eLazyBoolNo;
+            }
+        }
+
+        if (m_supports_detach_stay_stopped == eLazyBoolNo)
+        {
+            error.SetErrorString("Stays stopped not supported by this target.");
+            return error;
+        }
+        else
+        {
+            size_t num_sent = SendPacket ("D1", 2);
+            if (num_sent == 0)
+                error.SetErrorString ("Sending extended disconnect packet failed.");
+        }
+    }
+    else
+    {
+        size_t num_sent = SendPacket ("D", 1);
+        if (num_sent == 0)
+            error.SetErrorString ("Sending disconnect packet failed.");
+    }
+    return error;
 }
 
 Error
@@ -1275,7 +1453,7 @@ GDBRemoteCommunicationClient::GetMemoryR
     {
         m_supports_memory_region_info = eLazyBoolYes;
         char packet[64];
-        const int packet_len = ::snprintf(packet, sizeof(packet), "qMemoryRegionInfo:%llx", (uint64_t)addr);
+        const int packet_len = ::snprintf(packet, sizeof(packet), "qMemoryRegionInfo:%" PRIx64, (uint64_t)addr);
         assert (packet_len < sizeof(packet));
         StringExtractorGDBRemote response;
         if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
@@ -1608,7 +1786,7 @@ GDBRemoteCommunicationClient::GetProcess
     if (m_supports_qProcessInfoPID)
     {
         char packet[32];
-        const int packet_len = ::snprintf (packet, sizeof (packet), "qProcessInfoPID:%llu", pid);
+        const int packet_len = ::snprintf (packet, sizeof (packet), "qProcessInfoPID:%" PRIu64, pid);
         assert (packet_len < sizeof(packet));
         StringExtractorGDBRemote response;
         if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
@@ -1624,6 +1802,100 @@ GDBRemoteCommunicationClient::GetProcess
     return false;
 }
 
+bool
+GDBRemoteCommunicationClient::GetCurrentProcessInfo ()
+{
+    if (m_qProcessInfo_is_valid == eLazyBoolYes)
+        return true;
+    if (m_qProcessInfo_is_valid == eLazyBoolNo)
+        return false;
+
+    GetHostInfo ();
+
+    StringExtractorGDBRemote response;
+    if (SendPacketAndWaitForResponse ("qProcessInfo", response, false))
+    {
+        if (response.IsNormalResponse())
+        {
+            std::string name;
+            std::string value;
+            uint32_t cpu = LLDB_INVALID_CPUTYPE;
+            uint32_t sub = 0;
+            std::string arch_name;
+            std::string os_name;
+            std::string vendor_name;
+            std::string triple;
+            uint32_t pointer_byte_size = 0;
+            StringExtractor extractor;
+            ByteOrder byte_order = eByteOrderInvalid;
+            uint32_t num_keys_decoded = 0;
+            while (response.GetNameColonValue(name, value))
+            {
+                if (name.compare("cputype") == 0)
+                {
+                    cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 16);
+                    if (cpu != LLDB_INVALID_CPUTYPE)
+                        ++num_keys_decoded;
+                }
+                else if (name.compare("cpusubtype") == 0)
+                {
+                    sub = Args::StringToUInt32 (value.c_str(), 0, 16);
+                    if (sub != 0)
+                        ++num_keys_decoded;
+                }
+                else if (name.compare("ostype") == 0)
+                {
+                    os_name.swap (value);
+                    ++num_keys_decoded;
+                }
+                else if (name.compare("vendor") == 0)
+                {
+                    vendor_name.swap(value);
+                    ++num_keys_decoded;
+                }
+                else if (name.compare("endian") == 0)
+                {
+                    ++num_keys_decoded;
+                    if (value.compare("little") == 0)
+                        byte_order = eByteOrderLittle;
+                    else if (value.compare("big") == 0)
+                        byte_order = eByteOrderBig;
+                    else if (value.compare("pdp") == 0)
+                        byte_order = eByteOrderPDP;
+                    else
+                        --num_keys_decoded;
+                }
+                else if (name.compare("ptrsize") == 0)
+                {
+                    pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 16);
+                    if (pointer_byte_size != 0)
+                        ++num_keys_decoded;
+                }
+            }
+            if (num_keys_decoded > 0)
+                m_qProcessInfo_is_valid = eLazyBoolYes;
+            if (cpu != LLDB_INVALID_CPUTYPE && !os_name.empty() && !vendor_name.empty())
+            {
+                m_process_arch.SetArchitecture (eArchTypeMachO, cpu, sub);
+                if (pointer_byte_size)
+                {
+                    assert (pointer_byte_size == m_process_arch.GetAddressByteSize());
+                }
+                m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name));
+                m_host_arch.GetTriple().setOSName (llvm::StringRef (os_name));
+                return true;
+            }
+        }
+    }
+    else
+    {
+        m_qProcessInfo_is_valid = eLazyBoolNo;
+    }
+
+    return false;
+}
+
+
 uint32_t
 GDBRemoteCommunicationClient::FindProcesses (const ProcessInstanceInfoMatch &match_info,
                                              ProcessInstanceInfoList &process_infos)
@@ -1678,9 +1950,9 @@ GDBRemoteCommunicationClient::FindProces
             }
             
             if (match_info.GetProcessInfo().ProcessIDIsValid())
-                packet.Printf("pid:%llu;",match_info.GetProcessInfo().GetProcessID());
+                packet.Printf("pid:%" PRIu64 ";",match_info.GetProcessInfo().GetProcessID());
             if (match_info.GetProcessInfo().ParentProcessIDIsValid())
-                packet.Printf("parent_pid:%llu;",match_info.GetProcessInfo().GetParentProcessID());
+                packet.Printf("parent_pid:%" PRIu64 ";",match_info.GetProcessInfo().GetParentProcessID());
             if (match_info.GetProcessInfo().UserIDIsValid())
                 packet.Printf("uid:%u;",match_info.GetProcessInfo().GetUserID());
             if (match_info.GetProcessInfo().GroupIDIsValid())
@@ -1803,7 +2075,7 @@ GDBRemoteCommunicationClient::TestPacket
                 end_time = TimeValue::Now();
                 total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - start_time.GetAsNanoSecondsSinceJan1_1970();
                 packets_per_second = (((float)num_packets)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec;
-                printf ("%u qSpeedTest(send=%-5u, recv=%-5u) in %llu.%9.9llu sec for %f packets/sec.\n", 
+                printf ("%u qSpeedTest(send=%-5u, recv=%-5u) in %" PRIu64 ".%9.9" PRIu64 " sec for %f packets/sec.\n",
                         num_packets, 
                         send_size,
                         recv_size,
@@ -1827,7 +2099,7 @@ GDBRemoteCommunicationClient::TestPacket
         end_time = TimeValue::Now();
         total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - start_time.GetAsNanoSecondsSinceJan1_1970();
         packets_per_second = (((float)num_packets)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec;
-        printf ("%u 'qC' packets packets in 0x%llu%9.9llu sec for %f packets/sec.\n", 
+        printf ("%u 'qC' packets packets in 0x%" PRIu64 "%9.9" PRIu64 " sec for %f packets/sec.\n",
                 num_packets, 
                 total_time_nsec / TimeValue::NanoSecPerSec, 
                 total_time_nsec % TimeValue::NanoSecPerSec, 
@@ -1861,21 +2133,37 @@ GDBRemoteCommunicationClient::SendSpeedT
 }
 
 uint16_t
-GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort ()
+GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid)
 {
+    pid = LLDB_INVALID_PROCESS_ID;
     StringExtractorGDBRemote response;
-    if (SendPacketAndWaitForResponse("qLaunchGDBServer", strlen("qLaunchGDBServer"), response, false))
+    StreamString stream;
+    stream.PutCString("qLaunchGDBServer:port:0;");
+    std::string hostname;
+    if (Host::GetHostname (hostname))
+    {
+        // Make the GDB server we launch only accept connections from this host
+        stream.Printf("host:%s;", hostname.c_str());
+    }
+    else
+    {
+        // Make the GDB server we launch accept connections from any host since we can't figure out the hostname
+        stream.Printf("host:*;");
+    }
+    const char *packet = stream.GetData();
+    int packet_len = stream.GetSize();
+
+    if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
     {
         std::string name;
         std::string value;
         uint16_t port = 0;
-        //lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
         while (response.GetNameColonValue(name, value))
         {
-            if (name.size() == 4 && name.compare("port") == 0)
+            if (name.compare("port") == 0)
                 port = Args::StringToUInt32(value.c_str(), 0, 0);
-//            if (name.size() == 3 && name.compare("pid") == 0)
-//                pid = Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0);
+            else if (name.compare("pid") == 0)
+                pid = Args::StringToUInt64(value.c_str(), LLDB_INVALID_PROCESS_ID, 0);
         }
         return port;
     }
@@ -1883,17 +2171,34 @@ GDBRemoteCommunicationClient::LaunchGDBs
 }
 
 bool
-GDBRemoteCommunicationClient::SetCurrentThread (int tid)
+GDBRemoteCommunicationClient::KillSpawnedProcess (lldb::pid_t pid)
+{
+    StreamString stream;
+    stream.Printf ("qKillSpawnedProcess:%" PRId64 , pid);
+    const char *packet = stream.GetData();
+    int packet_len = stream.GetSize();
+    pid = LLDB_INVALID_PROCESS_ID;
+    StringExtractorGDBRemote response;
+    if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+    {
+        if (response.IsOKResponse())
+            return true;
+    }
+    return false;
+}
+
+bool
+GDBRemoteCommunicationClient::SetCurrentThread (uint64_t tid)
 {
     if (m_curr_tid == tid)
         return true;
-    
+
     char packet[32];
     int packet_len;
-    if (tid <= 0)
-        packet_len = ::snprintf (packet, sizeof(packet), "Hg%i", tid);
+    if (tid == UINT64_MAX)
+        packet_len = ::snprintf (packet, sizeof(packet), "Hg-1");
     else
-        packet_len = ::snprintf (packet, sizeof(packet), "Hg%x", tid);
+        packet_len = ::snprintf (packet, sizeof(packet), "Hg%" PRIx64, tid);
     assert (packet_len + 1 < sizeof(packet));
     StringExtractorGDBRemote response;
     if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
@@ -1908,18 +2213,18 @@ GDBRemoteCommunicationClient::SetCurrent
 }
 
 bool
-GDBRemoteCommunicationClient::SetCurrentThreadForRun (int tid)
+GDBRemoteCommunicationClient::SetCurrentThreadForRun (uint64_t tid)
 {
     if (m_curr_tid_run == tid)
         return true;
-    
+
     char packet[32];
     int packet_len;
-    if (tid <= 0)
-        packet_len = ::snprintf (packet, sizeof(packet), "Hc%i", tid);
+    if (tid == UINT64_MAX)
+        packet_len = ::snprintf (packet, sizeof(packet), "Hc-1");
     else
-        packet_len = ::snprintf (packet, sizeof(packet), "Hc%x", tid);
-    
+        packet_len = ::snprintf (packet, sizeof(packet), "Hc%" PRIx64, tid);
+
     assert (packet_len + 1 < sizeof(packet));
     StringExtractorGDBRemote response;
     if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
@@ -1942,12 +2247,12 @@ GDBRemoteCommunicationClient::GetStopRep
 }
 
 bool
-GDBRemoteCommunicationClient::GetThreadStopInfo (uint32_t tid, StringExtractorGDBRemote &response)
+GDBRemoteCommunicationClient::GetThreadStopInfo (lldb::tid_t tid, StringExtractorGDBRemote &response)
 {
     if (m_supports_qThreadStopInfo)
     {
         char packet[256];
-        int packet_len = ::snprintf(packet, sizeof(packet), "qThreadStopInfo%x", tid);
+        int packet_len = ::snprintf(packet, sizeof(packet), "qThreadStopInfo%" PRIx64, tid);
         assert (packet_len < sizeof(packet));
         if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
         {
@@ -1977,13 +2282,12 @@ GDBRemoteCommunicationClient::SendGDBSto
     case eWatchpointWrite:      if (!m_supports_z2) return UINT8_MAX; break;
     case eWatchpointRead:       if (!m_supports_z3) return UINT8_MAX; break;
     case eWatchpointReadWrite:  if (!m_supports_z4) return UINT8_MAX; break;
-    default:                    return UINT8_MAX;
     }
 
     char packet[64];
     const int packet_len = ::snprintf (packet, 
                                        sizeof(packet), 
-                                       "%c%i,%llx,%x", 
+                                       "%c%i,%" PRIx64 ",%x",
                                        insert ? 'Z' : 'z', 
                                        type, 
                                        addr, 
@@ -2007,7 +2311,6 @@ GDBRemoteCommunicationClient::SendGDBSto
             case eWatchpointWrite:      m_supports_z2 = false; break;
             case eWatchpointRead:       m_supports_z3 = false; break;
             case eWatchpointReadWrite:  m_supports_z4 = false; break;
-            default:                    break;
         }
     }
 
@@ -2037,7 +2340,7 @@ GDBRemoteCommunicationClient::GetCurrent
             {
                 do
                 {
-                    tid_t tid = response.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID);
+                    tid_t tid = response.GetHexMaxU64(false, LLDB_INVALID_THREAD_ID);
                     
                     if (tid != LLDB_INVALID_THREAD_ID)
                     {
@@ -2053,7 +2356,7 @@ GDBRemoteCommunicationClient::GetCurrent
 #if defined (LLDB_CONFIGURATION_DEBUG)
         // assert(!"ProcessGDBRemote::UpdateThreadList() failed due to not getting the sequence mutex");
 #else
-        LogSP log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS));
+        Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS));
         if (log)
             log->Printf("error: failed to get packet sequence mutex, not sending packet 'qfThreadInfo'");
 #endif
@@ -2145,19 +2448,44 @@ GDBRemoteCommunicationClient::MakeDirect
 
 }
 
+static uint64_t
+ParseHostIOPacketResponse (StringExtractorGDBRemote &response,
+                           uint64_t fail_result,
+                           Error &error)
+{
+    response.SetFilePos(0);
+    if (response.GetChar() != 'F')
+        return fail_result;
+    int32_t result = response.GetS32 (-2);
+    if (result == -2)
+        return fail_result;
+    if (response.GetChar() == ',')
+    {
+        int result_errno = response.GetS32 (-2);
+        if (result_errno != -2)
+            error.SetError(result_errno, eErrorTypePOSIX);
+        else
+            error.SetError(-1, eErrorTypeGeneric);
+    }
+    else
+        error.Clear();
+    return  result;
+}
 lldb::user_id_t
 GDBRemoteCommunicationClient::OpenFile (const lldb_private::FileSpec& file_spec,
                                         uint32_t flags,
-                                        mode_t mode)
+                                        mode_t mode,
+                                        Error &error)
 {
     lldb_private::StreamString stream;
     stream.PutCString("vFile:open:");
-    std::string path;
-    if (file_spec.GetPath(path) == 0)
+    std::string path (file_spec.GetPath());
+    if (path.empty())
         return UINT64_MAX;
     stream.PutCStringAsRawHex8(path.c_str());
     stream.PutChar(',');
-    stream.PutHex32(flags);
+    const uint32_t posix_open_flags = File::ConvertOpenOptionsForPOSIXOpen(flags);
+    stream.PutHex32(posix_open_flags);
     stream.PutChar(',');
     stream.PutHex32(mode);
     const char* packet = stream.GetData();
@@ -2165,28 +2493,23 @@ GDBRemoteCommunicationClient::OpenFile (
     StringExtractorGDBRemote response;
     if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
     {
-        if (response.GetChar() != 'F')
-            return UINT64_MAX;
-        uint32_t retcode = response.GetHexMaxU64(false, UINT64_MAX);
-        return retcode;
+        return ParseHostIOPacketResponse (response, UINT64_MAX, error);
     }
     return UINT64_MAX;
 }
 
 bool
-GDBRemoteCommunicationClient::CloseFile (lldb::user_id_t fd)
+GDBRemoteCommunicationClient::CloseFile (lldb::user_id_t fd,
+                                         Error &error)
 {
     lldb_private::StreamString stream;
-    stream.PutCString("vFile:close:");
-    stream.PutHex64(fd);
+    stream.Printf("vFile:close:%i", (int)fd);
     const char* packet = stream.GetData();
     int packet_len = stream.GetSize();
     StringExtractorGDBRemote response;
     if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
     {
-        if (response.GetChar() != 'F')
-            return UINT64_MAX;
-        return true;
+        return ParseHostIOPacketResponse (response, -1, error) == 0;
     }
     return UINT64_MAX;
 }
@@ -2197,10 +2520,8 @@ GDBRemoteCommunicationClient::GetFileSiz
 {
     lldb_private::StreamString stream;
     stream.PutCString("vFile:size:");
-    std::string path;
-    file_spec.GetPath(path);
+    std::string path (file_spec.GetPath());
     stream.PutCStringAsRawHex8(path.c_str());
-    stream.PutChar(',');
     const char* packet = stream.GetData();
     int packet_len = stream.GetSize();
     StringExtractorGDBRemote response;
@@ -2215,66 +2536,122 @@ GDBRemoteCommunicationClient::GetFileSiz
 }
 
 uint32_t
-GDBRemoteCommunicationClient::ReadFile (lldb::user_id_t fd, uint64_t offset,
-                                        void *data_ptr, size_t len)
+GDBRemoteCommunicationClient::GetFilePermissions(const lldb_private::FileSpec& file_spec, Error &error)
 {
     lldb_private::StreamString stream;
-    stream.PutCString("vFile:pread:");
-    stream.PutHex64(fd);
-    stream.PutChar(',');
-    stream.PutHex32(len);
-    stream.PutChar(',');
-    stream.PutHex32(offset);
+    stream.PutCString("vFile:mode:");
+    std::string path (file_spec.GetPath());
+    stream.PutCStringAsRawHex8(path.c_str());
     const char* packet = stream.GetData();
     int packet_len = stream.GetSize();
     StringExtractorGDBRemote response;
     if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
     {
         if (response.GetChar() != 'F')
-            return UINT32_MAX;
+        {
+            error.SetErrorStringWithFormat ("invalid response to '%s' packet", packet);
+            return 0;
+        }
+        const uint32_t mode = response.GetS32(-1);
+        if (mode == -1)
+        {
+            if (response.GetChar() == ',')
+            {
+                int response_errno = response.GetS32(-1);
+                if (response_errno > 0)
+                    error.SetError(response_errno, lldb::eErrorTypePOSIX);
+                else
+                    error.SetErrorToGenericError();
+            }
+        }
+        else
+            error.Clear();
+        return mode & (S_IRWXU|S_IRWXG|S_IRWXO);
+    }
+    else
+    {
+        error.SetErrorStringWithFormat ("failed to send '%s' packet", packet);
+    }
+    return 0;
+}
+
+uint64_t
+GDBRemoteCommunicationClient::ReadFile (lldb::user_id_t fd,
+                                        uint64_t offset,
+                                        void *dst,
+                                        uint64_t dst_len,
+                                        Error &error)
+{
+    lldb_private::StreamString stream;
+    stream.Printf("vFile:pread:%i,%" PRId64 ",%" PRId64, (int)fd, dst_len, offset);
+    const char* packet = stream.GetData();
+    int packet_len = stream.GetSize();
+    StringExtractorGDBRemote response;
+    if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+    {
+        if (response.GetChar() != 'F')
+            return 0;
         uint32_t retcode = response.GetHexMaxU32(false, UINT32_MAX);
         if (retcode == UINT32_MAX)
             return retcode;
         const char next = (response.Peek() ? *response.Peek() : 0);
         if (next == ',')
-            return UINT32_MAX;
+            return 0;
         if (next == ';')
         {
             response.GetChar(); // skip the semicolon
             std::string buffer;
-            response.GetEscapedBinaryData(buffer);
-            size_t data_to_write = len;
-            if (buffer.size() < len)
-                data_to_write = buffer.size();
-            memcpy(data_ptr, &buffer[0], data_to_write);
+            if (response.GetEscapedBinaryData(buffer))
+            {
+                const uint64_t data_to_write = std::min<uint64_t>(dst_len, buffer.size());
+                if (data_to_write > 0)
+                    memcpy(dst, &buffer[0], data_to_write);
+                return data_to_write;
+            }
         }
-        return retcode;
     }
-    return UINT32_MAX;
+    return 0;
 }
 
-uint32_t
-GDBRemoteCommunicationClient::WriteFile (lldb::user_id_t fd, uint64_t offset,
-                                         void* data, size_t len)
+uint64_t
+GDBRemoteCommunicationClient::WriteFile (lldb::user_id_t fd,
+                                         uint64_t offset,
+                                         const void* src,
+                                         uint64_t src_len,
+                                         Error &error)
 {
     lldb_private::StreamGDBRemote stream;
-    stream.PutCString("vFile:pwrite:");
-    stream.PutHex64(fd);
-    stream.PutChar(',');
-    stream.PutHex32(offset);
-    stream.PutChar(',');
-    stream.PutEscapedBytes(data, len);
+    stream.Printf("vFile:pwrite:%i,%" PRId64 ",", (int)fd, offset);
+    stream.PutEscapedBytes(src, src_len);
     const char* packet = stream.GetData();
     int packet_len = stream.GetSize();
     StringExtractorGDBRemote response;
     if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
     {
         if (response.GetChar() != 'F')
-            return UINT32_MAX;
-        uint32_t retcode = response.GetHexMaxU32(false, UINT32_MAX);
-        return retcode;
+        {
+            error.SetErrorStringWithFormat("write file failed");
+            return 0;
+        }
+        uint64_t bytes_written = response.GetU64(UINT64_MAX);
+        if (bytes_written == UINT64_MAX)
+        {
+            error.SetErrorToGenericError();
+            if (response.GetChar() == ',')
+            {
+                int response_errno = response.GetS32(-1);
+                if (response_errno > 0)
+                    error.SetError(response_errno, lldb::eErrorTypePOSIX);
+            }
+            return 0;
+        }
+        return bytes_written;
     }
-    return UINT32_MAX;
+    else
+    {
+        error.SetErrorString ("failed to send vFile:pwrite packet");
+    }
+    return 0;
 }
 
 // Extension of host I/O packets to get whether a file exists.
@@ -2283,8 +2660,7 @@ GDBRemoteCommunicationClient::GetFileExi
 {
     lldb_private::StreamString stream;
     stream.PutCString("vFile:exists:");
-    std::string path;
-    file_spec.GetPath(path);
+    std::string path (file_spec.GetPath());
     stream.PutCStringAsRawHex8(path.c_str());
     const char* packet = stream.GetData();
     int packet_len = stream.GetSize();
@@ -2308,8 +2684,7 @@ GDBRemoteCommunicationClient::CalculateM
 {
     lldb_private::StreamString stream;
     stream.PutCString("vFile:MD5:");
-    std::string path;
-    file_spec.GetPath(path);
+    std::string path (file_spec.GetPath());
     stream.PutCStringAsRawHex8(path.c_str());
     const char* packet = stream.GetData();
     int packet_len = stream.GetSize();

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h Thu Jun  6 19:06:43 2013
@@ -89,7 +89,10 @@ public:
     GetLaunchSuccess (std::string &error_str);
 
     uint16_t
-    LaunchGDBserverAndGetPort ();
+    LaunchGDBserverAndGetPort (lldb::pid_t &pid);
+    
+    bool
+    KillSpawnedProcess (lldb::pid_t pid);
 
     //------------------------------------------------------------------
     /// Sends a GDB remote protocol 'A' packet that delivers program
@@ -199,8 +202,8 @@ public:
     bool
     DeallocateMemory (lldb::addr_t addr);
 
-    bool
-    Detach ();
+    lldb_private::Error
+    Detach (bool keep_stopped);
 
     lldb_private::Error
     GetMemoryRegionInfo (lldb::addr_t addr, 
@@ -217,7 +220,10 @@ public:
 
     const lldb_private::ArchSpec &
     GetHostArchitecture ();
-    
+
+    const lldb_private::ArchSpec &
+    GetProcessArchitecture ();
+
     bool
     GetVContSupported (char flavor);
 
@@ -294,7 +300,7 @@ public:
     GetStopReply (StringExtractorGDBRemote &response);
 
     bool
-    GetThreadStopInfo (uint32_t tid, 
+    GetThreadStopInfo (lldb::tid_t tid, 
                        StringExtractorGDBRemote &response);
 
     bool
@@ -307,7 +313,6 @@ public:
         case eWatchpointWrite:      return m_supports_z2;
         case eWatchpointRead:       return m_supports_z3;
         case eWatchpointReadWrite:  return m_supports_z4;
-        default:                    break;
         }
         return false;
     }
@@ -330,10 +335,10 @@ public:
                          uint32_t recv_size);
     
     bool
-    SetCurrentThread (int tid);
+    SetCurrentThread (uint64_t tid);
     
     bool
-    SetCurrentThreadForRun (int tid);
+    SetCurrentThreadForRun (uint64_t tid);
 
     lldb_private::LazyBool
     SupportsAllocDeallocMemory () // const
@@ -356,21 +361,33 @@ public:
     virtual lldb::user_id_t
     OpenFile (const lldb_private::FileSpec& file_spec,
               uint32_t flags,
-              mode_t mode);
+              mode_t mode,
+              lldb_private::Error &error);
     
     virtual bool
-    CloseFile (lldb::user_id_t fd);
+    CloseFile (lldb::user_id_t fd,
+               lldb_private::Error &error);
     
     virtual lldb::user_id_t
     GetFileSize (const lldb_private::FileSpec& file_spec);
-
-    virtual uint32_t
-    ReadFile (lldb::user_id_t fd, uint64_t offset,
-              void *data_ptr, size_t len);
     
     virtual uint32_t
-    WriteFile (lldb::user_id_t fd, uint64_t offset,
-               void* data, size_t len);
+    GetFilePermissions(const lldb_private::FileSpec& file_spec,
+                       lldb_private::Error &error);
+
+    virtual uint64_t
+    ReadFile (lldb::user_id_t fd,
+              uint64_t offset,
+              void *dst,
+              uint64_t dst_len,
+              lldb_private::Error &error);
+    
+    virtual uint64_t
+    WriteFile (lldb::user_id_t fd,
+               uint64_t offset,
+               const void* src,
+               uint64_t src_len,
+               lldb_private::Error &error);
     
     virtual uint32_t
     MakeDirectory (const std::string &path,
@@ -392,8 +409,15 @@ public:
                   uint64_t &high,
                   uint64_t &low);
     
+    std::string
+    HarmonizeThreadIdsForProfileData (ProcessGDBRemote *process,
+                                      StringExtractorGDBRemote &inputStringExtractor);
+
 protected:
 
+    bool
+    GetCurrentProcessInfo ();
+
     //------------------------------------------------------------------
     // Classes that inherit from GDBRemoteCommunicationClient can see and modify these
     //------------------------------------------------------------------
@@ -407,9 +431,11 @@ protected:
     lldb_private::LazyBool m_supports_vCont_s;
     lldb_private::LazyBool m_supports_vCont_S;
     lldb_private::LazyBool m_qHostInfo_is_valid;
+    lldb_private::LazyBool m_qProcessInfo_is_valid;
     lldb_private::LazyBool m_supports_alloc_dealloc_memory;
     lldb_private::LazyBool m_supports_memory_region_info;
     lldb_private::LazyBool m_supports_watchpoint_support_info;
+    lldb_private::LazyBool m_supports_detach_stay_stopped;
     lldb_private::LazyBool m_watchpoints_trigger_after_instruction;
     lldb_private::LazyBool m_attach_or_wait_reply;
     lldb_private::LazyBool m_prepare_for_reg_writing_reply;
@@ -441,8 +467,11 @@ protected:
     StringExtractorGDBRemote m_async_response;
     int m_async_signal; // We were asked to deliver a signal to the inferior process.
     bool m_interrupt_sent;
+    std::string m_partial_profile_data;
+    std::map<uint64_t, uint32_t> m_thread_id_to_used_usec_map;
     
     lldb_private::ArchSpec m_host_arch;
+    lldb_private::ArchSpec m_process_arch;
     uint32_t m_os_version_major;
     uint32_t m_os_version_minor;
     uint32_t m_os_version_update;

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp Thu Jun  6 19:06:43 2013
@@ -21,6 +21,7 @@
 #include "lldb/Core/State.h"
 #include "lldb/Core/StreamString.h"
 #include "lldb/Host/Endian.h"
+#include "lldb/Host/File.h"
 #include "lldb/Host/Host.h"
 #include "lldb/Host/TimeValue.h"
 #include "lldb/Target/Process.h"
@@ -41,6 +42,8 @@ GDBRemoteCommunicationServer::GDBRemoteC
     m_async_thread (LLDB_INVALID_HOST_THREAD),
     m_process_launch_info (),
     m_process_launch_error (),
+    m_spawned_pids (),
+    m_spawned_pids_mutex (Mutex::eMutexTypeRecursive),
     m_proc_infos (),
     m_proc_infos_index (0),
     m_lo_port_num (0),
@@ -62,7 +65,6 @@ GDBRemoteCommunicationServer::GDBRemoteC
         hi_port_num = ::atoi(hi_port_c_str);
     if (lo_port_num && hi_port_num && lo_port_num < hi_port_num)
     {
-        printf("SetPortRange(%u, %u) called\n", lo_port_num, hi_port_num);
         SetPortRange(lo_port_num, hi_port_num);
     }
 }
@@ -80,7 +82,7 @@ GDBRemoteCommunicationServer::~GDBRemote
 //{
 //    GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer*) arg;
 //
-//    LogSP log;// (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
+//    Log *log;// (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
 //    if (log)
 //        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID());
 //
@@ -145,6 +147,9 @@ GDBRemoteCommunicationServer::GetPacketA
             case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer:
                 return Handle_qLaunchGDBServer (packet);
                 
+            case StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess:
+                return Handle_qKillSpawnedProcess (packet);
+                
             case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess:
                 return Handle_qLaunchSuccess (packet);
                 
@@ -204,7 +209,10 @@ GDBRemoteCommunicationServer::GetPacketA
 
             case StringExtractorGDBRemote::eServerPacketType_vFile_Size:
                 return Handle_vFile_Size (packet);
-                
+
+            case StringExtractorGDBRemote::eServerPacketType_vFile_Mode:
+                return Handle_vFile_Mode (packet);
+
             case StringExtractorGDBRemote::eServerPacketType_vFile_Exists:
                 return Handle_vFile_Exists (packet);
                 
@@ -333,7 +341,7 @@ GDBRemoteCommunicationServer::Handle_qHo
 static void
 CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &response)
 {
-    response.Printf ("pid:%llu;ppid:%llu;uid:%i;gid:%i;euid:%i;egid:%i;", 
+    response.Printf ("pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;",
                      proc_info.GetProcessID(),
                      proc_info.GetParentProcessID(),
                      proc_info.GetUserID(),
@@ -699,7 +707,7 @@ GDBRemoteCommunicationServer::Handle_qC
 {
     lldb::pid_t pid = m_process_launch_info.GetProcessID();
     StreamString response;
-    response.Printf("QC%llx", pid);
+    response.Printf("QC%" PRIx64, pid);
     if (m_is_platform)
     {
         // If we launch a process and this GDB server is acting as a platform, 
@@ -719,6 +727,24 @@ GDBRemoteCommunicationServer::Handle_qC
 }
 
 bool
+GDBRemoteCommunicationServer::DebugserverProcessReaped (lldb::pid_t pid)
+{
+    Mutex::Locker locker (m_spawned_pids_mutex);
+    return m_spawned_pids.erase(pid) > 0;
+}
+bool
+GDBRemoteCommunicationServer::ReapDebugserverProcess (void *callback_baton,
+                                                      lldb::pid_t pid,
+                                                      bool exited,
+                                                      int signal,    // Zero for no signal
+                                                      int status)    // Exit value of process if signal is zero
+{
+    GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer *)callback_baton;
+    server->DebugserverProcessReaped (pid);
+    return true;
+}
+
+bool
 GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
 {
     // Spawn a local debugserver as a platform so we can then attach or launch
@@ -730,6 +756,7 @@ GDBRemoteCommunicationServer::Handle_qLa
         ConnectionFileDescriptor file_conn;
         char connect_url[PATH_MAX];
         Error error;
+        std::string hostname;
         char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";
         if (::mktemp (unix_socket_name) == NULL)
         {
@@ -737,47 +764,87 @@ GDBRemoteCommunicationServer::Handle_qLa
         }
         else
         {
+            packet.SetFilePos(::strlen ("qLaunchGDBServer:"));
+            std::string name;
+            std::string value;
+            uint16_t port = UINT16_MAX;
+            while (packet.GetNameColonValue(name, value))
+            {
+                if (name.compare ("host") == 0)
+                    hostname.swap(value);
+                else if (name.compare ("port") == 0)
+                    port = Args::StringToUInt32(value.c_str(), 0, 0);
+            }
+            if (port == UINT16_MAX)
+                port = GetAndUpdateNextPort();
+
             ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name);
             // Spawn a new thread to accept the port that gets bound after
             // binding to port 0 (zero).
-            lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name,
-                                                               AcceptPortFromInferior,
-                                                               connect_url,
-                                                               &error);
+            lldb::thread_t accept_thread = NULL;
+            
+            if (port == 0)
+            {
+                accept_thread = Host::ThreadCreate (unix_socket_name,
+                                                    AcceptPortFromInferior,
+                                                    connect_url,
+                                                    &error);
+            }
             
             if (IS_VALID_LLDB_HOST_THREAD(accept_thread))
             {
                 // Spawn a debugserver and try to get the port it listens to.
                 ProcessLaunchInfo debugserver_launch_info;
-                char host_and_port[256];
-                const int host_and_port_len = ::snprintf (host_and_port,
-                                                          sizeof(host_and_port), 
-                                                          "localhost:%u", 
-                                                          GetAndUpdateNextPort());
-                assert (host_and_port_len < sizeof(host_and_port));
-                printf("Launching debugserver with: %s...\n", host_and_port);
-                error = StartDebugserverProcess (host_and_port,
+                StreamString host_and_port;
+                if (hostname.empty())
+                    hostname = "localhost";
+                host_and_port.Printf("%s:%u", hostname.c_str(), port);
+                const char *host_and_port_cstr = host_and_port.GetString().c_str();
+                printf("Launching debugserver with: %s...\n", host_and_port_cstr);
+                error = StartDebugserverProcess (host_and_port_cstr,
                                                  unix_socket_name, 
                                                  debugserver_launch_info);
                 
                 lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
+                
+                if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
+                {
+                    {
+                        Mutex::Locker locker (m_spawned_pids_mutex);
+                        m_spawned_pids.insert(debugserver_pid);
+                    }
+                    Host::StartMonitoringChildProcess (ReapDebugserverProcess, this, debugserver_pid, false);
+                }
+
                 if (error.Success())
                 {
                     bool success = false;
                     
-                    thread_result_t accept_thread_result = NULL;
-                    if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
+                    if (accept_thread)
                     {
-                        if (accept_thread_result)
+                        thread_result_t accept_thread_result = NULL;
+                        if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
                         {
-                            uint16_t port = (intptr_t)accept_thread_result;
-                            char response[256];
-                            const int response_len = ::snprintf (response, sizeof(response), "pid:%llu;port:%u;", debugserver_pid, port);
-                            assert (response_len < sizeof(response));
-                            //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
-                            success = SendPacketNoLock (response, response_len) > 0;
+                            if (accept_thread_result)
+                            {
+                                port = (intptr_t)accept_thread_result;
+                                char response[256];
+                                const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port);
+                                assert (response_len < sizeof(response));
+                                //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
+                                success = SendPacketNoLock (response, response_len) > 0;
+                            }
                         }
                     }
+                    else
+                    {
+                        char response[256];
+                        const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port);
+                        assert (response_len < sizeof(response));
+                        //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
+                        success = SendPacketNoLock (response, response_len) > 0;
+                        
+                    }
                     ::unlink (unix_socket_name);
                     
                     if (!success)
@@ -790,7 +857,60 @@ GDBRemoteCommunicationServer::Handle_qLa
             }
         }
     }
-    return SendErrorResponse (13);
+    return SendErrorResponse (9);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
+{
+    // Spawn a local debugserver as a platform so we can then attach or launch
+    // a process...
+    
+    if (m_is_platform)
+    {
+        packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
+        
+        lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
+
+        // Scope for locker
+        {
+            Mutex::Locker locker (m_spawned_pids_mutex);
+            if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+                return SendErrorResponse (10);
+        }
+        kill (pid, SIGTERM);
+        
+        for (size_t i=0; i<10; ++i)
+        {
+            // Scope for locker
+            {
+                Mutex::Locker locker (m_spawned_pids_mutex);
+                if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+                    return true;
+            }
+            usleep (10000);
+        }
+
+        // Scope for locker
+        {
+            Mutex::Locker locker (m_spawned_pids_mutex);
+            if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+                return true;
+        }
+        kill (pid, SIGKILL);
+        
+        for (size_t i=0; i<10; ++i)
+        {
+            // Scope for locker
+            {
+                Mutex::Locker locker (m_spawned_pids_mutex);
+                if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+                    return true;
+            }
+            usleep (10000);
+        }
+    }
+    return SendErrorResponse (10);
 }
 
 bool
@@ -814,7 +934,7 @@ GDBRemoteCommunicationServer::Handle_QEn
         m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
         return SendOKResponse ();
     }
-    return SendErrorResponse (9);
+    return SendErrorResponse (11);
 }
 
 bool
@@ -829,7 +949,7 @@ GDBRemoteCommunicationServer::Handle_QLa
         m_process_launch_info.SetArchitecture(arch_spec);
         return SendOKResponse();
     }
-    return SendErrorResponse(9);
+    return SendErrorResponse(12);
 }
 
 bool
@@ -867,7 +987,7 @@ GDBRemoteCommunicationServer::Handle_QSe
         m_process_launch_info.AppendFileAction(file_action);
         return SendOKResponse ();
     }
-    return SendErrorResponse (10);
+    return SendErrorResponse (13);
 }
 
 bool
@@ -884,7 +1004,7 @@ GDBRemoteCommunicationServer::Handle_QSe
         m_process_launch_info.AppendFileAction(file_action);
         return SendOKResponse ();
     }
-    return SendErrorResponse (11);
+    return SendErrorResponse (14);
 }
 
 bool
@@ -901,7 +1021,7 @@ GDBRemoteCommunicationServer::Handle_QSe
         m_process_launch_info.AppendFileAction(file_action);
         return SendOKResponse ();
     }
-    return SendErrorResponse (12);
+    return SendErrorResponse (15);
 }
 
 bool
@@ -943,15 +1063,14 @@ GDBRemoteCommunicationServer::Handle_vFi
     if (packet.GetChar() != ',')
         return false;
     mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
-    lldb::user_id_t retcode = Host::OpenFile(FileSpec(path.c_str(), false), flags, mode);
+    Error error;
+    int fd = ::open (path.c_str(), flags, mode);
+    const int save_errno = fd == -1 ? errno : 0;
     StreamString response;
     response.PutChar('F');
-    response.PutHex64(retcode);
-    if (retcode == UINT64_MAX)
-    {
-        response.PutChar(',');
-        response.PutHex64(retcode); // TODO: replace with Host::GetSyswideErrorCode()
-    }
+    response.Printf("%i", fd);
+    if (save_errno)
+        response.Printf(",%i", save_errno);
     SendPacketNoLock(response.GetData(), response.GetSize());
     return true;
 }
@@ -960,16 +1079,24 @@ bool
 GDBRemoteCommunicationServer::Handle_vFile_Close (StringExtractorGDBRemote &packet)
 {
     packet.SetFilePos(::strlen("vFile:close:"));
-    lldb::user_id_t fd = packet.GetHexMaxU64(false, UINT64_MAX);
-    uint32_t retcode = Host::CloseFile(fd);
-    StreamString response;
-    response.PutChar('F');
-    response.PutHex32(retcode);
-    if (retcode == UINT32_MAX)
+    int fd = packet.GetS32(-1);
+    Error error;
+    int err = -1;
+    int save_errno = 0;
+    if (fd >= 0)
     {
-        response.PutChar(',');
-        response.PutHex32(retcode); // TODO: replace with Host::GetSyswideErrorCode()
+        err = close(fd);
+        save_errno = err == -1 ? errno : 0;
     }
+    else
+    {
+        save_errno = EINVAL;
+    }
+    StreamString response;
+    response.PutChar('F');
+    response.Printf("%i", err);
+    if (save_errno)
+        response.Printf(",%i", save_errno);
     SendPacketNoLock(response.GetData(), response.GetSize());
     return true;
 }
@@ -979,35 +1106,30 @@ GDBRemoteCommunicationServer::Handle_vFi
 {
     StreamGDBRemote response;
     packet.SetFilePos(::strlen("vFile:pread:"));
-    lldb::user_id_t fd = packet.GetHexMaxU64(false, UINT64_MAX);
+    int fd = packet.GetS32(-1);
     if (packet.GetChar() != ',')
         return false;
-    uint32_t count = packet.GetHexMaxU32(false, UINT32_MAX);
+    uint64_t count = packet.GetU64(UINT64_MAX);
     if (packet.GetChar() != ',')
         return false;
-    uint32_t offset = packet.GetHexMaxU32(false, UINT32_MAX);
-    if (count == UINT32_MAX) // protect yourself against allocating a 4GB buffer
+    uint64_t offset = packet.GetU64(UINT32_MAX);
+    if (count == UINT64_MAX)
     {
-        response.PutChar('F');
-        response.PutHex32(UINT32_MAX);
-        response.PutChar(',');
-        response.PutHex32(UINT32_MAX); // TODO: replace with Host::GetSyswideErrorCode()
+        response.Printf("F-1:%i", EINVAL);
         SendPacketNoLock(response.GetData(), response.GetSize());
         return true;
     }
     std::string buffer(count, 0);
-    uint32_t retcode = Host::ReadFile(fd, offset, &buffer[0], count);
+    const ssize_t bytes_read = ::pread (fd, &buffer[0], buffer.size(), offset);
+    const int save_errno = bytes_read == -1 ? errno : 0;
     response.PutChar('F');
-    response.PutHex32(retcode);
-    if (retcode == UINT32_MAX)
-    {
-        response.PutChar(',');
-        response.PutHex32(retcode); // TODO: replace with Host::GetSyswideErrorCode()
-    }
+    response.Printf("%zi", bytes_read);
+    if (save_errno)
+        response.Printf(",%i", save_errno);
     else
     {
         response.PutChar(';');
-        response.PutEscapedBytes(&buffer[0], retcode);
+        response.PutEscapedBytes(&buffer[0], bytes_read);
     }
     SendPacketNoLock(response.GetData(), response.GetSize());
     return true;
@@ -1017,23 +1139,30 @@ bool
 GDBRemoteCommunicationServer::Handle_vFile_pWrite (StringExtractorGDBRemote &packet)
 {
     packet.SetFilePos(::strlen("vFile:pwrite:"));
-    lldb::user_id_t fd = packet.GetHexMaxU64(false, UINT64_MAX);
+
+    StreamGDBRemote response;
+    response.PutChar('F');
+
+    int fd = packet.GetU32(UINT32_MAX);
     if (packet.GetChar() != ',')
         return false;
-    uint32_t offset = packet.GetHexMaxU32(false, UINT32_MAX);
+    off_t offset = packet.GetU64(UINT32_MAX);
     if (packet.GetChar() != ',')
         return false;
     std::string buffer;
-    packet.GetEscapedBinaryData(buffer);
-    uint32_t retcode = Host::WriteFile(fd, offset, &buffer[0], buffer.size());
-    StreamString response;
-    response.PutChar('F');
-    response.PutHex32(retcode);
-    if (retcode == UINT32_MAX)
+    if (packet.GetEscapedBinaryData(buffer))
     {
-        response.PutChar(',');
-        response.PutHex32(retcode); // TODO: replace with Host::GetSyswideErrorCode()
+        const ssize_t bytes_written = ::pwrite (fd, buffer.data(), buffer.size(), offset);
+        const int save_errno = bytes_written == -1 ? errno : 0;
+        response.Printf("%zi", bytes_written);
+        if (save_errno)
+            response.Printf(",%i", save_errno);
     }
+    else
+    {
+        response.Printf ("-1,%i", EINVAL);
+    }
+
     SendPacketNoLock(response.GetData(), response.GetSize());
     return true;
 }
@@ -1043,10 +1172,8 @@ GDBRemoteCommunicationServer::Handle_vFi
 {
     packet.SetFilePos(::strlen("vFile:size:"));
     std::string path;
-    packet.GetHexByteStringTerminatedBy(path,',');
-    if (path.size() == 0)
-        return false;
-    if (packet.GetChar() != ',')
+    packet.GetHexByteString(path);
+    if (path.empty())
         return false;
     lldb::user_id_t retcode = Host::GetFileSize(FileSpec(path.c_str(), false));
     StreamString response;
@@ -1062,12 +1189,30 @@ GDBRemoteCommunicationServer::Handle_vFi
 }
 
 bool
+GDBRemoteCommunicationServer::Handle_vFile_Mode (StringExtractorGDBRemote &packet)
+{
+    packet.SetFilePos(::strlen("vFile:mode:"));
+    std::string path;
+    packet.GetHexByteString(path);
+    if (path.empty())
+        return false;
+    Error error;
+    const uint32_t mode = File::GetPermissions(path.c_str(), error);
+    StreamString response;
+    response.Printf("F%u", mode);
+    if (mode == 0 || error.Fail())
+        response.Printf(",%i", (int)error.GetError());
+    SendPacketNoLock(response.GetData(), response.GetSize());
+    return true;
+}
+
+bool
 GDBRemoteCommunicationServer::Handle_vFile_Exists (StringExtractorGDBRemote &packet)
 {
     packet.SetFilePos(::strlen("vFile:exists:"));
     std::string path;
     packet.GetHexByteString(path);
-    if (path.size() == 0)
+    if (path.empty())
         return false;
     bool retcode = Host::GetFileExists(FileSpec(path.c_str(), false));
     StreamString response;

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h Thu Jun  6 19:06:43 2013
@@ -13,8 +13,10 @@
 // C Includes
 // C++ Includes
 #include <vector>
+#include <set>
 // Other libraries and framework includes
 // Project includes
+#include "lldb/Host/Mutex.h"
 #include "lldb/Target/Process.h"
 #include "GDBRemoteCommunication.h"
 
@@ -83,6 +85,8 @@ protected:
     lldb::thread_t m_async_thread;
     lldb_private::ProcessLaunchInfo m_process_launch_info;
     lldb_private::Error m_process_launch_error;
+    std::set<lldb::pid_t> m_spawned_pids;
+    lldb_private::Mutex m_spawned_pids_mutex;
     lldb_private::ProcessInstanceInfoList m_proc_infos;
     uint32_t m_proc_infos_index;
     uint16_t m_lo_port_num;
@@ -90,6 +94,7 @@ protected:
     //PortToPIDMap m_port_to_pid_map;
     uint16_t m_next_port;
     bool m_use_port_range;
+    
 
     size_t
     SendUnimplementedResponse (const char *packet);
@@ -111,6 +116,9 @@ protected:
     
     bool
     Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet);
+    
+    bool
+    Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet);
 
     bool
     Handle_qPlatform_IO_MkDir (StringExtractorGDBRemote &packet);
@@ -174,6 +182,9 @@ protected:
 
     bool
     Handle_vFile_Size (StringExtractorGDBRemote &packet);
+    
+    bool
+    Handle_vFile_Mode (StringExtractorGDBRemote &packet);
 
     bool
     Handle_vFile_Exists (StringExtractorGDBRemote &packet);
@@ -188,6 +199,16 @@ protected:
     Handle_qPlatform_RunCommand (StringExtractorGDBRemote &packet);
 
 private:
+    bool
+    DebugserverProcessReaped (lldb::pid_t pid);
+    
+    static bool
+    ReapDebugserverProcess (void *callback_baton,
+                            lldb::pid_t pid,
+                            bool exited,
+                            int signal,
+                            int status);
+
     //------------------------------------------------------------------
     // For GDBRemoteCommunicationServer only
     //------------------------------------------------------------------

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp Thu Jun  6 19:06:43 2013
@@ -85,7 +85,7 @@ GDBRemoteRegisterContext::GetRegisterCou
 }
 
 const RegisterInfo *
-GDBRemoteRegisterContext::GetRegisterInfoAtIndex (uint32_t reg)
+GDBRemoteRegisterContext::GetRegisterInfoAtIndex (size_t reg)
 {
     return m_reg_info.GetRegisterInfoAtIndex (reg);
 }
@@ -99,7 +99,7 @@ GDBRemoteRegisterContext::GetRegisterSet
 
 
 const RegisterSet *
-GDBRemoteRegisterContext::GetRegisterSet (uint32_t reg_set)
+GDBRemoteRegisterContext::GetRegisterSet (size_t reg_set)
 {
     return m_reg_info.GetRegisterSet (reg_set);
 }
@@ -134,13 +134,13 @@ GDBRemoteRegisterContext::PrivateSetRegi
     bool success = bytes_copied == reg_byte_size;
     if (success)
     {
-        m_reg_valid[reg] = true;
+        SetRegisterIsValid(reg, true);
     }
     else if (bytes_copied > 0)
     {
         // Only set register is valid to false if we copied some bytes, else
         // leave it as it was.
-        m_reg_valid[reg] = false;
+        SetRegisterIsValid(reg, false);
     }
     return success;
 }
@@ -155,7 +155,7 @@ GDBRemoteRegisterContext::GetPrimordialR
     int packet_len = 0;
     const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
     if (gdb_comm.GetThreadSuffixSupported())
-        packet_len = ::snprintf (packet, sizeof(packet), "p%x;thread:%4.4llx;", reg, m_thread.GetID());
+        packet_len = ::snprintf (packet, sizeof(packet), "p%x;thread:%4.4" PRIx64 ";", reg, m_thread.GetProtocolID());
     else
         packet_len = ::snprintf (packet, sizeof(packet), "p%x", reg);
     assert (packet_len < (sizeof(packet) - 1));
@@ -180,14 +180,14 @@ GDBRemoteRegisterContext::ReadRegisterBy
 
     const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
 
-    if (!m_reg_valid[reg])
+    if (!GetRegisterIsValid(reg))
     {
         Mutex::Locker locker;
         if (gdb_comm.GetSequenceMutex (locker, "Didn't get sequence mutex for read register."))
         {
             const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
             ProcessSP process_sp (m_thread.GetProcess());
-            if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetID()))
+            if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetProtocolID()))
             {
                 char packet[64];
                 StringExtractorGDBRemote response;
@@ -196,7 +196,7 @@ GDBRemoteRegisterContext::ReadRegisterBy
                 {
                     // Get all registers in one packet
                     if (thread_suffix_supported)
-                        packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4llx;", m_thread.GetID());
+                        packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
                     else
                         packet_len = ::snprintf (packet, sizeof(packet), "g");
                     assert (packet_len < (sizeof(packet) - 1));
@@ -207,51 +207,54 @@ GDBRemoteRegisterContext::ReadRegisterBy
                                 SetAllRegisterValid (true);
                     }
                 }
-                else if (!reg_info->value_regs)
-                {
-                    // Get each register individually
-                    GetPrimordialRegister(reg_info, gdb_comm);
-                }
-                else
+                else if (reg_info->value_regs)
                 {
                     // Process this composite register request by delegating to the constituent
                     // primordial registers.
-
+                    
                     // Index of the primordial register.
-                    uint32_t prim_reg_idx;
                     bool success = true;
-                    for (uint32_t idx = 0;
-                         (prim_reg_idx = reg_info->value_regs[idx]) != LLDB_INVALID_REGNUM;
-                         ++idx)
+                    for (uint32_t idx = 0; success; ++idx)
                     {
+                        const uint32_t prim_reg = reg_info->value_regs[idx];
+                        if (prim_reg == LLDB_INVALID_REGNUM)
+                            break;
                         // We have a valid primordial regsiter as our constituent.
                         // Grab the corresponding register info.
-                        const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg_idx);
-                        if (!GetPrimordialRegister(prim_reg_info, gdb_comm))
-                        {
+                        const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg);
+                        if (prim_reg_info == NULL)
                             success = false;
-                            // Some failure occurred.  Let's break out of the for loop.
-                            break;
+                        else
+                        {
+                            // Read the containing register if it hasn't already been read
+                            if (!GetRegisterIsValid(prim_reg))
+                                success = GetPrimordialRegister(prim_reg_info, gdb_comm);
                         }
                     }
+
                     if (success)
                     {
                         // If we reach this point, all primordial register requests have succeeded.
                         // Validate this composite register.
-                        m_reg_valid[reg_info->kinds[eRegisterKindLLDB]] = true;
+                        SetRegisterIsValid (reg_info, true);
                     }
                 }
+                else
+                {
+                    // Get each register individually
+                    GetPrimordialRegister(reg_info, gdb_comm);
+                }
             }
         }
         else
         {
-            LogSP log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
 #if LLDB_CONFIGURATION_DEBUG
             StreamString strm;
             gdb_comm.DumpHistory(strm);
             Host::SetCrashDescription (strm.GetData());
             assert (!"Didn't get sequence mutex for read register.");
 #else
+            Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
             if (log)
             {
                 if (log->GetVerbose())
@@ -269,7 +272,7 @@ GDBRemoteRegisterContext::ReadRegisterBy
         }
 
         // Make sure we got a valid register value after reading it
-        if (!m_reg_valid[reg])
+        if (!GetRegisterIsValid(reg))
             return false;
     }
 
@@ -311,10 +314,10 @@ GDBRemoteRegisterContext::SetPrimordialR
                               lldb::endian::InlHostByteOrder());
 
     if (gdb_comm.GetThreadSuffixSupported())
-        packet.Printf (";thread:%4.4llx;", m_thread.GetID());
+        packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
 
     // Invalidate just this register
-    m_reg_valid[reg] = false;
+    SetRegisterIsValid(reg, false);
     if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
                                               packet.GetString().size(),
                                               response,
@@ -337,7 +340,7 @@ GDBRemoteRegisterContext::SyncThreadStat
 
     StreamString packet;
     StringExtractorGDBRemote response;
-    packet.Printf ("QSyncThreadState:%4.4llx;", m_thread.GetID());
+    packet.Printf ("QSyncThreadState:%4.4" PRIx64 ";", m_thread.GetProtocolID());
     if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
                                               packet.GetString().size(),
                                               response,
@@ -383,10 +386,11 @@ GDBRemoteRegisterContext::WriteRegisterB
         {
             const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
             ProcessSP process_sp (m_thread.GetProcess());
-            if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetID()))
+            if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetProtocolID()))
             {
                 StreamString packet;
                 StringExtractorGDBRemote response;
+                
                 if (m_read_all_at_once)
                 {
                     // Set all registers in one packet
@@ -397,7 +401,7 @@ GDBRemoteRegisterContext::WriteRegisterB
                                               lldb::endian::InlHostByteOrder());
 
                     if (thread_suffix_supported)
-                        packet.Printf (";thread:%4.4llx;", m_thread.GetID());
+                        packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
 
                     // Invalidate all register values
                     InvalidateIfNeeded (true);
@@ -414,59 +418,57 @@ GDBRemoteRegisterContext::WriteRegisterB
                         }
                     }
                 }
-                else if (!reg_info->value_regs)
-                {
-                    // Set each register individually
-                    return SetPrimordialRegister(reg_info, gdb_comm);
-                }
                 else
                 {
-                    // Process this composite register request by delegating to the constituent
-                    // primordial registers.
-
-                    // Invalidate this composite register first.
-                    m_reg_valid[reg_info->kinds[eRegisterKindLLDB]] = false;
-
-                    // Index of the primordial register.
-                    uint32_t prim_reg_idx;
-                    // For loop index.
-                    uint32_t idx;
+                    bool success = true;
 
-                    // Invalidate the invalidate_regs, if present.
-                    if (reg_info->invalidate_regs)
+                    if (reg_info->value_regs)
                     {
-                        for (idx = 0;
-                             (prim_reg_idx = reg_info->invalidate_regs[idx]) != LLDB_INVALID_REGNUM;
-                             ++idx)
+                        // This register is part of another register. In this case we read the actual
+                        // register data for any "value_regs", and once all that data is read, we will
+                        // have enough data in our register context bytes for the value of this register
+                        
+                        // Invalidate this composite register first.
+                        
+                        for (uint32_t idx = 0; success; ++idx)
                         {
-                            // Grab the invalidate register info.
-                            const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg_idx);
-                            m_reg_valid[prim_reg_info->kinds[eRegisterKindLLDB]] = false;
+                            const uint32_t reg = reg_info->value_regs[idx];
+                            if (reg == LLDB_INVALID_REGNUM)
+                                break;
+                            // We have a valid primordial regsiter as our constituent.
+                            // Grab the corresponding register info.
+                            const RegisterInfo *value_reg_info = GetRegisterInfoAtIndex(reg);
+                            if (value_reg_info == NULL)
+                                success = false;
+                            else
+                                success = SetPrimordialRegister(value_reg_info, gdb_comm);
                         }
                     }
+                    else
+                    {
+                        // This is an actual register, write it
+                        success = SetPrimordialRegister(reg_info, gdb_comm);
+                    }
 
-                    bool success = true;
-                    for (idx = 0;
-                         (prim_reg_idx = reg_info->value_regs[idx]) != LLDB_INVALID_REGNUM;
-                         ++idx)
+                    // Check if writing this register will invalidate any other register values?
+                    // If so, invalidate them
+                    if (reg_info->invalidate_regs)
                     {
-                        // We have a valid primordial regsiter as our constituent.
-                        // Grab the corresponding register info.
-                        const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg_idx);
-                        if (!SetPrimordialRegister(prim_reg_info, gdb_comm))
+                        for (uint32_t idx = 0, reg = reg_info->invalidate_regs[0];
+                             reg != LLDB_INVALID_REGNUM;
+                             reg = reg_info->invalidate_regs[++idx])
                         {
-                            success = false;
-                            // Some failure occurred.  Let's break out of the for loop.
-                            break;
+                            SetRegisterIsValid(reg, false);
                         }
                     }
+                    
                     return success;
                 }
             }
         }
         else
         {
-            LogSP log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
+            Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
             if (log)
             {
                 if (log->GetVerbose())
@@ -506,11 +508,11 @@ GDBRemoteRegisterContext::ReadAllRegiste
         char packet[32];
         const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
         ProcessSP process_sp (m_thread.GetProcess());
-        if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetID()))
+        if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetProtocolID()))
         {
             int packet_len = 0;
             if (thread_suffix_supported)
-                packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4llx", m_thread.GetID());
+                packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4" PRIx64, m_thread.GetProtocolID());
             else
                 packet_len = ::snprintf (packet, sizeof(packet), "g");
             assert (packet_len < (sizeof(packet) - 1));
@@ -527,7 +529,7 @@ GDBRemoteRegisterContext::ReadAllRegiste
                     if (thread_suffix_supported)
                     {
                         char thread_id_cstr[64];
-                        ::snprintf (thread_id_cstr, sizeof(thread_id_cstr), ";thread:%4.4llx;", m_thread.GetID());
+                        ::snprintf (thread_id_cstr, sizeof(thread_id_cstr), ";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
                         response_str.append (thread_id_cstr);
                     }
                     data_sp.reset (new DataBufferHeap (response_str.c_str(), response_str.size()));
@@ -538,7 +540,7 @@ GDBRemoteRegisterContext::ReadAllRegiste
     }
     else
     {
-        LogSP log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
+        Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
         if (log)
         {
             if (log->GetVerbose())
@@ -577,7 +579,7 @@ GDBRemoteRegisterContext::WriteAllRegist
     {
         const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
         ProcessSP process_sp (m_thread.GetProcess());
-        if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetID()))
+        if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetProtocolID()))
         {
             // The data_sp contains the entire G response packet including the
             // G, and if the thread suffix is supported, it has the thread suffix
@@ -633,7 +635,7 @@ GDBRemoteRegisterContext::WriteAllRegist
                         const char *restore_src = (const char *)restore_data.PeekData(reg_byte_offset, reg_byte_size);
                         if (restore_src)
                         {
-                            if (m_reg_valid[reg])
+                            if (GetRegisterIsValid(reg))
                             {
                                 const char *current_src = (const char *)m_reg_data.PeekData(reg_byte_offset, reg_byte_size);
                                 if (current_src)
@@ -650,9 +652,9 @@ GDBRemoteRegisterContext::WriteAllRegist
                                                           lldb::endian::InlHostByteOrder());
 
                                 if (thread_suffix_supported)
-                                    packet.Printf (";thread:%4.4llx;", m_thread.GetID());
+                                    packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
 
-                                m_reg_valid[reg] = false;
+                                SetRegisterIsValid(reg, false);
                                 if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
                                                                           packet.GetString().size(),
                                                                           response,
@@ -671,7 +673,7 @@ GDBRemoteRegisterContext::WriteAllRegist
     }
     else
     {
-        LogSP log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
+        Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
         if (log)
         {
             if (log->GetVerbose())
@@ -855,7 +857,7 @@ GDBRemoteDynamicRegisterInfo::HardcodeAR
     static ConstString gpr_reg_set ("General Purpose Registers");
     static ConstString sfp_reg_set ("Software Floating Point Registers");
     static ConstString vfp_reg_set ("Floating Point Registers");
-    uint32_t i;
+    size_t i;
     if (from_scratch)
     {
         // Calculate the offsets of the registers
@@ -903,121 +905,67 @@ GDBRemoteDynamicRegisterInfo::HardcodeAR
     else
     {
         // Add composite registers to our primordial registers, then.
-        const uint32_t num_composites = llvm::array_lengthof(g_composites);
-        const uint32_t num_primordials = GetNumRegisters();
-        RegisterInfo *g_comp_register_infos = g_register_infos + (num_registers - num_composites);
-        for (i=0; i<num_composites; ++i)
+        const size_t num_composites = llvm::array_lengthof(g_composites);
+        const size_t num_dynamic_regs = GetNumRegisters();
+        const size_t num_common_regs = num_registers - num_composites;
+        RegisterInfo *g_comp_register_infos = g_register_infos + num_common_regs;
+
+        // First we need to validate that all registers that we already have match the non composite regs.
+        // If so, then we can add the registers, else we need to bail
+        bool match = true;
+        if (num_dynamic_regs == num_common_regs)
         {
-            ConstString name;
-            ConstString alt_name;
-            const uint32_t first_primordial_reg = g_comp_register_infos[i].value_regs[0];
-            const char *reg_name = g_register_infos[first_primordial_reg].name;
-            if (reg_name && reg_name[0])
-            {
-                for (uint32_t j = 0; j < num_primordials; ++j)
-                {
-                    const RegisterInfo *reg_info = GetRegisterInfoAtIndex(j);
-                    // Find a matching primordial register info entry.
-                    if (reg_info && reg_info->name && ::strcasecmp(reg_info->name, reg_name) == 0)
-                    {
-                        // The name matches the existing primordial entry.
-                        // Find and assign the offset, and then add this composite register entry.
-                        g_comp_register_infos[i].byte_offset = reg_info->byte_offset;
-                        name.SetCString(g_comp_register_infos[i].name);
-                        AddRegister(g_comp_register_infos[i], name, alt_name, vfp_reg_set);
+            for (i=0; match && i<num_dynamic_regs; ++i)
+            {
+                // Make sure all register names match
+                if (m_regs[i].name && g_register_infos[i].name)
+                {
+                    if (strcmp(m_regs[i].name, g_register_infos[i].name))
+                    {
+                        match = false;
+                        break;
                     }
                 }
+                
+                // Make sure all register byte sizes match
+                if (m_regs[i].byte_size != g_register_infos[i].byte_size)
+                {
+                    match = false;
+                    break;
+                }
             }
         }
-    }
-}
-
-void
-GDBRemoteDynamicRegisterInfo::Addx86_64ConvenienceRegisters()
-{
-    // For eax, ebx, ecx, edx, esi, edi, ebp, esp register mapping.
-    static const char* g_mapped_names[] = {
-        "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "rbp", "rsp",
-        "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "rbp", "rsp",
-        "rax", "rbx", "rcx", "rdx",
-        "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "rbp", "rsp"
-    };
-
-    // These value regs are to be populated with the corresponding primordial register index.
-    // For example,
-    static uint32_t g_eax_regs[] =  { 0, LLDB_INVALID_REGNUM }; // 0 is to be replaced with rax's index.
-    static uint32_t g_ebx_regs[] =  { 0, LLDB_INVALID_REGNUM };
-    static uint32_t g_ecx_regs[] =  { 0, LLDB_INVALID_REGNUM };
-    static uint32_t g_edx_regs[] =  { 0, LLDB_INVALID_REGNUM };
-    static uint32_t g_edi_regs[] =  { 0, LLDB_INVALID_REGNUM };
-    static uint32_t g_esi_regs[] =  { 0, LLDB_INVALID_REGNUM };
-    static uint32_t g_ebp_regs[] =  { 0, LLDB_INVALID_REGNUM };
-    static uint32_t g_esp_regs[] =  { 0, LLDB_INVALID_REGNUM };
-    
-    static RegisterInfo g_conv_register_infos[] = 
-    {
-//    NAME      ALT      SZ OFF ENCODING         FORMAT                COMPILER              DWARF                 GENERIC                      GDB                   LLDB NATIVE            VALUE REGS    INVALIDATE REGS
-//    ======    =======  == === =============    ============          ===================== ===================== ============================ ====================  ====================== ==========    ===============
-    { "eax"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_eax_regs,              NULL},
-    { "ebx"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_ebx_regs,              NULL},
-    { "ecx"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_ecx_regs,              NULL},
-    { "edx"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_edx_regs,              NULL},
-    { "edi"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_edi_regs,              NULL},
-    { "esi"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_esi_regs,              NULL},
-    { "ebp"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_ebp_regs,              NULL},
-    { "esp"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_esp_regs,              NULL},
-    { "ax"    , NULL,    2,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_eax_regs,              NULL},
-    { "bx"    , NULL,    2,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_ebx_regs,              NULL},
-    { "cx"    , NULL,    2,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_ecx_regs,              NULL},
-    { "dx"    , NULL,    2,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_edx_regs,              NULL},
-    { "di"    , NULL,    2,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_edi_regs,              NULL},
-    { "si"    , NULL,    2,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_esi_regs,              NULL},
-    { "bp"    , NULL,    2,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_ebp_regs,              NULL},
-    { "sp"    , NULL,    2,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_esp_regs,              NULL},
-    { "ah"    , NULL,    1,  1, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_eax_regs,              NULL},
-    { "bh"    , NULL,    1,  1, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_ebx_regs,              NULL},
-    { "ch"    , NULL,    1,  1, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_ecx_regs,              NULL},
-    { "dh"    , NULL,    1,  1, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_edx_regs,              NULL},
-    { "al"    , NULL,    1,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_eax_regs,              NULL},
-    { "bl"    , NULL,    1,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_ebx_regs,              NULL},
-    { "cl"    , NULL,    1,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_ecx_regs,              NULL},
-    { "dl"    , NULL,    1,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_edx_regs,              NULL},
-    { "dil"   , NULL,    1,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_edi_regs,              NULL},
-    { "sil"   , NULL,    1,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_esi_regs,              NULL},
-    { "bpl"   , NULL,    1,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_ebp_regs,              NULL},
-    { "spl"   , NULL,    1,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_esp_regs,              NULL}
-    };
-
-    static const uint32_t num_conv_regs = llvm::array_lengthof(g_mapped_names);
-    static ConstString gpr_reg_set ("General Purpose Registers");
-    
-    // Add convenience registers to our primordial registers.
-    const uint32_t num_primordials = GetNumRegisters();
-    uint32_t reg_kind = num_primordials;
-    for (uint32_t i=0; i<num_conv_regs; ++i)
-    {
-        ConstString name;
-        ConstString alt_name;
-        const char *prim_reg_name = g_mapped_names[i];
-        if (prim_reg_name && prim_reg_name[0])
-        {
-            for (uint32_t j = 0; j < num_primordials; ++j)
-            {
-                const RegisterInfo *reg_info = GetRegisterInfoAtIndex(j);
-                // Find a matching primordial register info entry.
-                if (reg_info && reg_info->name && ::strcasecmp(reg_info->name, prim_reg_name) == 0)
-                {
-                    // The name matches the existing primordial entry.
-                    // Find and assign the offset, and then add this composite register entry.
-                    g_conv_register_infos[i].byte_offset = reg_info->byte_offset + g_conv_register_infos[i].byte_offset;
-                    // Update the value_regs and the kinds fields in order to delegate to the primordial register.
-                    g_conv_register_infos[i].value_regs[0] = j;
-                    g_conv_register_infos[i].kinds[eRegisterKindLLDB] = ++reg_kind;
-                    name.SetCString(g_conv_register_infos[i].name);
-                    AddRegister(g_conv_register_infos[i], name, alt_name, gpr_reg_set);
+        else
+        {
+            // Wrong number of registers.
+            match = false;
+        }
+        // If "match" is true, then we can add extra registers.
+        if (match)
+        {
+            for (i=0; i<num_composites; ++i)
+            {
+                ConstString name;
+                ConstString alt_name;
+                const uint32_t first_primordial_reg = g_comp_register_infos[i].value_regs[0];
+                const char *reg_name = g_register_infos[first_primordial_reg].name;
+                if (reg_name && reg_name[0])
+                {
+                    for (uint32_t j = 0; j < num_dynamic_regs; ++j)
+                    {
+                        const RegisterInfo *reg_info = GetRegisterInfoAtIndex(j);
+                        // Find a matching primordial register info entry.
+                        if (reg_info && reg_info->name && ::strcasecmp(reg_info->name, reg_name) == 0)
+                        {
+                            // The name matches the existing primordial entry.
+                            // Find and assign the offset, and then add this composite register entry.
+                            g_comp_register_infos[i].byte_offset = reg_info->byte_offset;
+                            name.SetCString(g_comp_register_infos[i].name);
+                            AddRegister(g_comp_register_infos[i], name, alt_name, vfp_reg_set);
+                        }
+                    }
                 }
             }
         }
     }
 }
-

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h Thu Jun  6 19:06:43 2013
@@ -46,19 +46,34 @@ public:
     }
 
     void
-    AddRegister (lldb_private::RegisterInfo &reg_info, 
+    AddRegister (lldb_private::RegisterInfo reg_info, 
                  lldb_private::ConstString &reg_name, 
                  lldb_private::ConstString &reg_alt_name, 
                  lldb_private::ConstString &set_name)
     {
-        const uint32_t reg_num = m_regs.size();
+        const uint32_t reg_num = (uint32_t)m_regs.size();
         m_reg_names.push_back (reg_name);
         m_reg_alt_names.push_back (reg_alt_name);
         reg_info.name = reg_name.AsCString();
         assert (reg_info.name);
         reg_info.alt_name = reg_alt_name.AsCString(NULL);
+        uint32_t i;
+        if (reg_info.value_regs)
+        {
+            for (i=0; reg_info.value_regs[i] != LLDB_INVALID_REGNUM; ++i)
+                m_value_regs_map[reg_num].push_back(reg_info.value_regs[i]);
+            m_value_regs_map[reg_num].push_back(LLDB_INVALID_REGNUM);
+            reg_info.value_regs = m_value_regs_map[reg_num].data();
+        }
+        if (reg_info.invalidate_regs)
+        {
+            for (i=0; reg_info.invalidate_regs[i] != LLDB_INVALID_REGNUM; ++i)
+                m_invalidate_regs_map[reg_num].push_back(reg_info.invalidate_regs[i]);
+            m_invalidate_regs_map[reg_num].push_back(LLDB_INVALID_REGNUM);
+            reg_info.invalidate_regs = m_invalidate_regs_map[reg_num].data();
+        }
         m_regs.push_back (reg_info);
-        uint32_t set = GetRegisterSetIndexByName (set_name, true);
+        uint32_t set = GetRegisterSetIndexByName (set_name);
         assert (set < m_sets.size());
         assert (set < m_set_reg_nums.size());
         assert (set < m_set_names.size());
@@ -114,20 +129,20 @@ public:
     }
 
     uint32_t
-    GetRegisterSetIndexByName (lldb_private::ConstString &set_name, bool can_create)
+    GetRegisterSetIndexByName (lldb_private::ConstString &set_name)
     {
         name_collection::iterator pos, end = m_set_names.end();
         for (pos = m_set_names.begin(); pos != end; ++pos)
         {
             if (*pos == set_name)
-                return std::distance (m_set_names.begin(), pos);
+                return static_cast<uint32_t>(std::distance (m_set_names.begin(), pos));
         }
 
         m_set_names.push_back(set_name);
         m_set_reg_nums.resize(m_set_reg_nums.size()+1);
         lldb_private::RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL };
         m_sets.push_back (new_set);
-        return m_sets.size() - 1;
+        return static_cast<uint32_t>(m_sets.size() - 1);
     }
 
     uint32_t
@@ -137,7 +152,7 @@ public:
         for (pos = m_regs.begin(); pos != end; ++pos)
         {
             if (pos->kinds[kind] == num)
-                return std::distance (m_regs.begin(), pos);
+                return static_cast<uint32_t>(std::distance (m_regs.begin(), pos));
         }
 
         return LLDB_INVALID_REGNUM;
@@ -156,9 +171,6 @@ public:
     void
     HardcodeARMRegisters(bool from_scratch);
 
-    void
-    Addx86_64ConvenienceRegisters();
-
 protected:
     //------------------------------------------------------------------
     // Classes that inherit from GDBRemoteRegisterContext can see and modify these
@@ -168,6 +180,7 @@ protected:
     typedef std::vector <uint32_t> reg_num_collection;
     typedef std::vector <reg_num_collection> set_reg_num_collection;
     typedef std::vector <lldb_private::ConstString> name_collection;
+    typedef std::map<uint32_t, reg_num_collection> reg_to_regs_map;
 
     reg_collection m_regs;
     set_collection m_sets;
@@ -175,6 +188,8 @@ protected:
     name_collection m_reg_names;
     name_collection m_reg_alt_names;
     name_collection m_set_names;
+    reg_to_regs_map m_value_regs_map;
+    reg_to_regs_map m_invalidate_regs_map;
     size_t m_reg_data_byte_size;   // The number of bytes required to store all registers
 };
 
@@ -202,13 +217,13 @@ public:
     GetRegisterCount ();
 
     virtual const lldb_private::RegisterInfo *
-    GetRegisterInfoAtIndex (uint32_t reg);
+    GetRegisterInfoAtIndex (size_t reg);
 
     virtual size_t
     GetRegisterSetCount ();
 
     virtual const lldb_private::RegisterSet *
-    GetRegisterSet (uint32_t reg_set);
+    GetRegisterSet (size_t reg_set);
 
     virtual bool
     ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
@@ -243,6 +258,34 @@ protected:
     void
     SetAllRegisterValid (bool b);
 
+    bool
+    GetRegisterIsValid (uint32_t reg) const
+    {
+#if defined (LLDB_CONFIGURATION_DEBUG)
+        assert (reg < m_reg_valid.size());
+#endif
+        if (reg < m_reg_valid.size())
+            return m_reg_valid[reg];
+        return false;
+    }
+
+    void
+    SetRegisterIsValid (const lldb_private::RegisterInfo *reg_info, bool valid)
+    {
+        if (reg_info)
+            return SetRegisterIsValid (reg_info->kinds[lldb::eRegisterKindLLDB], valid);
+    }
+
+    void
+    SetRegisterIsValid (uint32_t reg, bool valid)
+    {
+#if defined (LLDB_CONFIGURATION_DEBUG)
+        assert (reg < m_reg_valid.size());
+#endif
+        if (reg < m_reg_valid.size())
+            m_reg_valid[reg] = valid;
+    }
+
     void
     SyncThreadState(lldb_private::Process *process);  // Assumes the sequence mutex has already been acquired.
     





More information about the llvm-branch-commits mailing list