<rdar://problem/13491977>
authorGreg Clayton <gclayton@apple.com>
Fri, 12 Apr 2013 20:07:46 +0000 (20:07 +0000)
committerGreg Clayton <gclayton@apple.com>
Fri, 12 Apr 2013 20:07:46 +0000 (20:07 +0000)
Made some fixes to the OperatingSystemPython class:
- If any thread dictionary contains any "core=N" key/value pairs then the threads obtained from the lldb_private::Process itself will be placed inside the ThreadMemory threads and will be used to get the information for a thread.
- Cleaned up all the places where a thread inside a thread was causing problems

llvm-svn: 179405

lldb/include/lldb/Target/Thread.h
lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp
lldb/source/Plugins/Process/Utility/ThreadMemory.cpp
lldb/source/Plugins/Process/Utility/ThreadMemory.h
lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp
lldb/source/Target/Process.cpp
lldb/source/Target/StackFrameList.cpp

index f517f83..84478b2 100644 (file)
@@ -416,6 +416,24 @@ public:
     virtual void
     ClearStackFrames ();
 
+    virtual bool
+    SetBackingThread (const lldb::ThreadSP &thread_sp)
+    {
+        return false;
+    }
+
+    virtual void
+    ClearBackingThread ()
+    {
+        // Subclasses can use this function if a thread is actually backed by
+        // another thread. This is currently used for the OperatingSystem plug-ins
+        // where they might have a thread that is in memory, yet its registers
+        // are available through the lldb_private::Thread subclass for the current
+        // lldb_private::Process class. Since each time the process stops the backing
+        // threads for memory threads can change, we need a way to clear the backing
+        // thread for all memory threads each time we stop.
+    }
+
     void
     DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx);
 
index c80b88c..650c713 100644 (file)
@@ -186,17 +186,40 @@ OperatingSystemPython::UpdateThreadList (ThreadList &old_thread_list, ThreadList
     if (log)
         log->Printf ("OperatingSystemPython::UpdateThreadList() fetching thread data from python for pid %" PRIu64, m_process->GetID());
 
+    // The threads that are in "new_thread_list" upon entry are the threads from the
+    // lldb_private::Process subclass, no memory threads will be in this list.
+    
     auto lock = m_interpreter->AcquireInterpreterLock(); // to make sure threads_list stays alive
     PythonList threads_list(m_interpreter->OSPlugin_ThreadsInfo(m_python_object_sp));
     if (threads_list)
     {
+        ThreadList core_thread_list(new_thread_list);
+
+        threads_list.Dump(); // REMOVE THIS
+
+        uint32_t i;
         const uint32_t num_threads = threads_list.GetSize();
-        for (uint32_t i=0; i<num_threads; ++i)
+        for (i=0; i<num_threads; ++i)
+        {
+            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, &old_thread_list, NULL));
+                ThreadSP thread_sp (CreateThreadFromThreadInfo (thread_dict, core_thread_list, old_thread_list, NULL));
                 if (thread_sp)
                     new_thread_list.AddThread(thread_sp);
             }
@@ -210,7 +233,10 @@ OperatingSystemPython::UpdateThreadList (ThreadList &old_thread_list, ThreadList
 }
 
 ThreadSP
-OperatingSystemPython::CreateThreadFromThreadInfo (PythonDictionary &thread_dict, ThreadList *old_thread_list_ptr, bool *did_create_ptr)
+OperatingSystemPython::CreateThreadFromThreadInfo (PythonDictionary &thread_dict,
+                                                   ThreadList &core_thread_list,
+                                                   ThreadList &old_thread_list,
+                                                   bool *did_create_ptr)
 {
     ThreadSP thread_sp;
     if (thread_dict)
@@ -219,20 +245,21 @@ OperatingSystemPython::CreateThreadFromThreadInfo (PythonDictionary &thread_dict
         const tid_t tid = thread_dict.GetItemForKeyAsInteger (tid_pystr, LLDB_INVALID_THREAD_ID);
         if (tid != LLDB_INVALID_THREAD_ID)
         {
+            PythonString core_pystr("core");
             PythonString name_pystr("name");
             PythonString queue_pystr("queue");
             PythonString state_pystr("state");
             PythonString stop_reason_pystr("stop_reason");
             PythonString reg_data_addr_pystr ("register_data_addr");
             
+            const uint32_t core_number = thread_dict.GetItemForKeyAsInteger (core_pystr, UINT32_MAX);
             const addr_t reg_data_addr = thread_dict.GetItemForKeyAsInteger (reg_data_addr_pystr, LLDB_INVALID_ADDRESS);
             const char *name = thread_dict.GetItemForKeyAsString (name_pystr);
             const char *queue = thread_dict.GetItemForKeyAsString (queue_pystr);
             //const char *state = thread_dict.GetItemForKeyAsString (state_pystr);
             //const char *stop_reason = thread_dict.GetItemForKeyAsString (stop_reason_pystr);
             
-            if (old_thread_list_ptr)
-                thread_sp = old_thread_list_ptr->FindThreadByID (tid, false);
+            thread_sp = old_thread_list.FindThreadByID (tid, false);
             if (!thread_sp)
             {
                 if (did_create_ptr)
@@ -242,6 +269,12 @@ OperatingSystemPython::CreateThreadFromThreadInfo (PythonDictionary &thread_dict
                                                    name,
                                                    queue,
                                                    reg_data_addr));
+                
+            }
+            
+            if (core_number < core_thread_list.GetSize(false))
+            {
+                thread_sp->SetBackingThread(core_thread_list.GetThreadAtIndex(core_number, false));
             }
         }
     }
@@ -335,9 +368,10 @@ OperatingSystemPython::CreateThread (lldb::tid_t tid, addr_t context)
         PythonDictionary thread_info_dict (m_interpreter->OSPlugin_CreateThread(m_python_object_sp, tid, context));
         if (thread_info_dict)
         {
+            ThreadList core_threads(m_process);
             ThreadList &thread_list = m_process->GetThreadList();
             bool did_create = false;
-            ThreadSP thread_sp (CreateThreadFromThreadInfo (thread_info_dict, &thread_list, &did_create));
+            ThreadSP thread_sp (CreateThreadFromThreadInfo (thread_info_dict, core_threads, thread_list, &did_create));
             if (did_create)
                 thread_list.AddThread(thread_sp);
             return thread_sp;
index 27cff90..bcc90c6 100644 (file)
@@ -93,7 +93,8 @@ protected:
     
     lldb::ThreadSP
     CreateThreadFromThreadInfo (lldb_private::PythonDictionary &thread_dict,
-                                lldb_private::ThreadList *old_thread_list_ptr,
+                                lldb_private::ThreadList &core_thread_list,
+                                lldb_private::ThreadList &old_thread_list,
                                 bool *did_create_ptr);
 
     DynamicRegisterInfo *
index 2961643..a8b1b08 100644 (file)
@@ -166,8 +166,12 @@ ThreadKDP::CreateRegisterContextForFrame (StackFrame *frame)
             }
         }
     }
-    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;
 }
 
index 7ab5db7..e7602b8 100644 (file)
@@ -21,6 +21,7 @@ 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()
@@ -34,6 +35,7 @@ ThreadMemory::ThreadMemory (Process &process,
                             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(),
@@ -65,6 +67,9 @@ ThreadMemory::WillResume (StateType resume_state)
 RegisterContextSP
 ThreadMemory::GetRegisterContext ()
 {
+    if (m_backing_thread_sp)
+        return m_backing_thread_sp->GetRegisterContext();
+
     if (!m_reg_context_sp)
     {
         ProcessSP process_sp (GetProcess());
@@ -81,6 +86,9 @@ ThreadMemory::GetRegisterContext ()
 RegisterContextSP
 ThreadMemory::CreateRegisterContextForFrame (StackFrame *frame)
 {
+    if (m_backing_thread_sp)
+        return m_backing_thread_sp->CreateRegisterContextForFrame(frame);
+
     RegisterContextSP reg_ctx_sp;
     uint32_t concrete_frame_idx = 0;
     
@@ -91,9 +99,11 @@ ThreadMemory::CreateRegisterContextForFrame (StackFrame *frame)
     {
         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;
 }
@@ -101,6 +111,9 @@ ThreadMemory::CreateRegisterContextForFrame (StackFrame *frame)
 lldb::StopInfoSP
 ThreadMemory::GetPrivateStopReason ()
 {
+    if (m_backing_thread_sp)
+        return m_backing_thread_sp->GetPrivateStopReason();
+
     ProcessSP process_sp (GetProcess());
 
     if (process_sp)
@@ -135,6 +148,10 @@ ThreadMemory::GetPrivateStopReason ()
 void
 ThreadMemory::RefreshStateAfterStop()
 {
+    if (m_backing_thread_sp)
+        return m_backing_thread_sp->RefreshStateAfterStop();
+    
+
     // Don't fetch the registers by calling Thread::GetRegisterContext() below.
     // We might not have fetched any registers yet and we don't want to fetch
     // the registers just to call invalidate on them...
index 7ee9758..0950786 100644 (file)
@@ -33,9 +33,6 @@ public:
     //------------------------------------------------------------------
     // lldb_private::Thread methods
     //------------------------------------------------------------------
-    virtual void
-    RefreshStateAfterStop();
-
     virtual lldb::RegisterContextSP
     GetRegisterContext ();
 
@@ -46,30 +43,75 @@ public:
     GetPrivateStopReason ();
 
     virtual const char *
+    GetInfo ()
+    {
+        if (m_backing_thread_sp)
+            m_backing_thread_sp->GetInfo();
+        return NULL;
+    }
+
+    virtual const char *
     GetName ()
     {
-        return m_name.c_str();
+        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 ()
     {
-        return m_queue.c_str();
+        if (!m_queue.empty())
+            return m_queue.c_str();
+        if (m_backing_thread_sp)
+            m_backing_thread_sp->GetQueueName();
+        return NULL;
     }
 
     virtual bool
     WillResume (lldb::StateType resume_state);
 
+    virtual void
+    DidResume ()
+    {
+        if (m_backing_thread_sp)
+            m_backing_thread_sp->DidResume();
+    }
+
+    virtual void
+    RefreshStateAfterStop();
+    
     lldb::ValueObjectSP &
     GetValueObject ()
     {
         return m_thread_info_valobj_sp;
     }
+    
+    virtual void
+    ClearBackingThread ()
+    {
+        m_backing_thread_sp.reset();
+    }
+
+    virtual bool
+    SetBackingThread (const lldb::ThreadSP &thread_sp)
+    {
+        m_backing_thread_sp = thread_sp;
+        return (bool)thread_sp;
+    }
 
 protected:
     //------------------------------------------------------------------
     // 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;
index 4ac3f68..f1084d6 100644 (file)
@@ -202,8 +202,12 @@ ThreadGDBRemote::CreateRegisterContextForFrame (StackFrame *frame)
             reg_ctx_sp.reset (new GDBRemoteRegisterContext (*this, concrete_frame_idx, gdb_process->m_register_info, read_all_registers_at_once));
         }
     }
-    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;
 }
 
index f88c488..81d3426 100644 (file)
@@ -118,9 +118,11 @@ ThreadMachCore::CreateRegisterContextForFrame (StackFrame *frame)
         }
         reg_ctx_sp = m_thread_reg_ctx_sp;
     }
-    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;
 }
index d60930e..6a39442 100644 (file)
@@ -1523,7 +1523,16 @@ Process::UpdateThreadListIfNeeded ()
                 {
                     OperatingSystem *os = GetOperatingSystem ();
                     if (os)
+                    {
+                        // Clear any old backing threads where memory threads might have been
+                        // backed by actual threads from the lldb_private::Process subclass
+                        size_t num_old_threads = m_thread_list.GetSize(false);
+                        for (size_t i=0; i<num_old_threads; ++i)
+                            m_thread_list.GetThreadAtIndex(i, false)->ClearBackingThread();
+
+                        // Now let the OperatingSystem plug-in update the thread list
                         os->UpdateThreadList (m_thread_list, new_thread_list);
+                    }
                     m_thread_list.Update (new_thread_list);
                     m_thread_list.SetStopID (stop_id);
                 }
index 39aa1bc..dad67dc 100644 (file)
@@ -296,27 +296,30 @@ StackFrameList::GetFramesUpTo(uint32_t end_idx)
                 // if we need to
                 if (m_frames.empty())
                 {
-                    m_thread.GetRegisterContext();
-                    assert (m_thread.m_reg_context_sp.get());
-
-                    const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
-                    // There shouldn't be any way not to get the frame info for frame 0.
-                    // But if the unwinder can't make one, lets make one by hand with the
-                    // SP as the CFA and see if that gets any further.
-                    if (!success)
+                    RegisterContextSP reg_ctx_sp (m_thread.GetRegisterContext());
+                    
+                    if (reg_ctx_sp)
                     {
-                        cfa = m_thread.GetRegisterContext()->GetSP();
-                        pc = m_thread.GetRegisterContext()->GetPC();
+
+                        const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
+                        // There shouldn't be any way not to get the frame info for frame 0.
+                        // But if the unwinder can't make one, lets make one by hand with the
+                        // SP as the CFA and see if that gets any further.
+                        if (!success)
+                        {
+                            cfa = reg_ctx_sp->GetSP();
+                            pc = reg_ctx_sp->GetPC();
+                        }
+                        
+                        unwind_frame_sp.reset (new StackFrame (m_thread.shared_from_this(),
+                                                               m_frames.size(), 
+                                                               idx,
+                                                               reg_ctx_sp,
+                                                               cfa,
+                                                               pc,
+                                                               NULL));
+                        m_frames.push_back (unwind_frame_sp);
                     }
-                    
-                    unwind_frame_sp.reset (new StackFrame (m_thread.shared_from_this(),
-                                                           m_frames.size(), 
-                                                           idx,
-                                                           m_thread.m_reg_context_sp,
-                                                           cfa,
-                                                           pc,
-                                                           NULL));
-                    m_frames.push_back (unwind_frame_sp);
                 }
                 else
                 {