diff options
19 files changed, 237 insertions, 397 deletions
diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h index 1856d63d5ff..fc58a6903b6 100644 --- a/lldb/include/lldb/Target/Thread.h +++ b/lldb/include/lldb/Target/Thread.h @@ -848,13 +848,7 @@ public: virtual lldb::user_id_t GetProtocolID () const { - return m_protocol_tid.GetID(); - } - - virtual void - SetProtocolID (lldb::user_id_t api_tid) - { - return m_protocol_tid.SetID(api_tid); + return GetID(); } //------------------------------------------------------------------ @@ -905,7 +899,19 @@ public: // valid. The stop info may be a "checkpointed and restored" stop info, so if it is still around it is right // even if you have not calculated this yourself, or if it disagrees with what you might have calculated. virtual lldb::StopInfoSP - GetPrivateStopReason () = 0; + GetPrivateStopInfo (); + + //---------------------------------------------------------------------- + // Ask the thread subclass to set its stop info. + // + // Thread subclasses should call Thread::SetStopInfo(...) with the + // reason the thread stopped. + // + // @return + // True if Thread::SetStopInfo(...) was called, false otherwise. + //---------------------------------------------------------------------- + virtual bool + CalculateStopInfo () = 0; //---------------------------------------------------------------------- // Gets the temporary resume state for a thread. @@ -1002,9 +1008,10 @@ protected: // Classes that inherit from Process can see and modify these //------------------------------------------------------------------ lldb::ProcessWP m_process_wp; ///< The process that owns this thread. - lldb::StopInfoSP m_actual_stop_info_sp; ///< The private stop reason for this thread + lldb::StopInfoSP m_stop_info_sp; ///< The private stop reason for this thread + uint32_t m_stop_info_stop_id; // This is the stop id for which the StopInfo is valid. Can use this so you know that + // the thread's m_stop_info_sp is current and you don't have to fetch it again const uint32_t m_index_id; ///< A unique 1 based index assigned to each thread for easy UI/command line access. - UserID m_protocol_tid; ///< The thread ID used in the system level debugging or protocol functions calls. This is usually the same as the Thread::GetID(), but not always. lldb::RegisterContextSP m_reg_context_sp; ///< The register context for this thread's current register state. lldb::StateType m_state; ///< The state of our process. mutable Mutex m_state_mutex; ///< Multithreaded protection for m_state. @@ -1020,8 +1027,6 @@ protected: /// It gets set in Thread::ShoudResume. std::unique_ptr<lldb_private::Unwind> m_unwinder_ap; bool m_destroy_called; // This is used internally to make sure derived Thread classes call DestroyThread. - uint32_t m_thread_stop_reason_stop_id; // This is the stop id for which the StopInfo is valid. Can use this so you know that - // the thread's m_actual_stop_info_sp is current and you don't have to fetch it again LazyBool m_override_should_notify; private: //------------------------------------------------------------------ diff --git a/lldb/include/lldb/Target/ThreadPlan.h b/lldb/include/lldb/Target/ThreadPlan.h index 630fee3a9f2..5e02ec74489 100644 --- a/lldb/include/lldb/Target/ThreadPlan.h +++ b/lldb/include/lldb/Target/ThreadPlan.h @@ -410,6 +410,13 @@ public: virtual bool MischiefManaged (); + virtual void + ThreadDestroyed () + { + // Any cleanup that a plan might want to do in case the thread goes away + // in the middle of the plan being queued on a thread can be done here. + } + bool GetPrivate () { @@ -537,7 +544,7 @@ protected: lldb::StopInfoSP GetPrivateStopReason() { - return m_thread.GetPrivateStopReason (); + return m_thread.GetPrivateStopInfo (); } void diff --git a/lldb/include/lldb/Target/ThreadPlanStepOverBreakpoint.h b/lldb/include/lldb/Target/ThreadPlanStepOverBreakpoint.h index c1c2a41a4d6..41cac5c9b0b 100644 --- a/lldb/include/lldb/Target/ThreadPlanStepOverBreakpoint.h +++ b/lldb/include/lldb/Target/ThreadPlanStepOverBreakpoint.h @@ -32,6 +32,7 @@ public: virtual lldb::StateType GetPlanRunState (); virtual bool WillStop (); virtual bool MischiefManaged (); + virtual void ThreadDestroyed (); void SetAutoContinue (bool do_it); virtual bool ShouldAutoContinue(Event *event_ptr); @@ -39,11 +40,13 @@ protected: virtual bool DoPlanExplainsStop (Event *event_ptr); virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan); + void ReenableBreakpointSite (); private: lldb::addr_t m_breakpoint_addr; lldb::user_id_t m_breakpoint_site_id; bool m_auto_continue; + bool m_reenabled_breakpoint_site; DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepOverBreakpoint); diff --git a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp index 0528033f3b1..1af044e00e2 100644 --- a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp +++ b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp @@ -198,36 +198,39 @@ OperatingSystemPython::UpdateThreadList (ThreadList &old_thread_list, { uint32_t i; const uint32_t num_threads = threads_list.GetSize(); - for (i=0; i<num_threads; ++i) + if (num_threads > 0) { - PythonDictionary thread_dict(threads_list.GetItemAtIndex(i)); - if (thread_dict) + for (i=0; i<num_threads; ++i) { - if (thread_dict.GetItemForKey("core")) + PythonDictionary thread_dict(threads_list.GetItemAtIndex(i)); + if (thread_dict) { - // 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; + 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) + for (i=0; i<num_threads; ++i) { - ThreadSP thread_sp (CreateThreadFromThreadInfo (thread_dict, core_thread_list, old_thread_list, NULL)); - if (thread_sp) - new_thread_list.AddThread(thread_sp); + 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); + } } } } - else - { + + if (new_thread_list.GetSize(false) == 0) new_thread_list = old_thread_list; - } + return new_thread_list.GetSize(false) > 0; } diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp index afa18dacc7d..c78aa42da20 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp @@ -385,11 +385,16 @@ ProcessKDP::DoResume () 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: @@ -398,6 +403,8 @@ ProcessKDP::DoResume () if (reg_ctx_sp) { + if (log) + log->Printf ("ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);"); reg_ctx_sp->HardwareSingleStep (true); resume = true; } @@ -412,15 +419,17 @@ ProcessKDP::DoResume () { lldb::RegisterContextSP reg_ctx_sp (kernel_thread_sp->GetRegisterContext()); - if (reg_ctx_sp) - { - reg_ctx_sp->HardwareSingleStep (false); - resume = true; - } - else - { - error.SetErrorStringWithFormat("KDP thread 0x%llx has no register context", kernel_thread_sp->GetID()); - } + 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; @@ -540,22 +549,15 @@ ProcessKDP::DoDetach(bool keep_stopped) // If we are going to keep the target stopped, then don't send the disconnect message. if (!keep_stopped && m_comm.IsConnected()) { - - bool disconnect_success = m_comm.SendRequestDisconnect(); - if (!disconnect_success) - { - if (log) - log->PutCString ("ProcessKDP::DoDetach(): send disconnect request failed"); - } - - ConnectionStatus comm_disconnect_result = m_comm.Disconnect (); + const bool success = m_comm.SendRequestDisconnect(); if (log) { - if (comm_disconnect_result == eConnectionStatusSuccess) - log->PutCString ("ProcessKDP::DoDetach() conncection channel shutdown successfully"); + if (success) + log->PutCString ("ProcessKDP::DoDetach() detach packet sent successfully"); else log->PutCString ("ProcessKDP::DoDetach() connection channel shutdown failed"); } + m_comm.Disconnect (); } } StopAsyncThread (); diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp index 6f0116e7f44..94567c87eda 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp @@ -148,26 +148,23 @@ ThreadKDP::CreateRegisterContextForFrame (StackFrame *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) { - if (IsStillAtLastBreakpointHit()) - return m_actual_stop_info_sp; - - if (m_cached_stop_info_sp) - SetStopInfo (m_cached_stop_info_sp); - else - SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, SIGSTOP)); + SetStopInfo (m_cached_stop_info_sp); + } + else + { + SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, SIGSTOP)); } + return true; } - return m_actual_stop_info_sp; + return false; } void diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h b/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h index 5a980f504fc..7dc373f0355 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h @@ -89,13 +89,10 @@ protected: 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_ diff --git a/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp b/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp index 1d43201a08d..45461c0341d 100644 --- a/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp +++ b/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp @@ -138,10 +138,11 @@ POSIXThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) return reg_ctx_sp; } -lldb::StopInfoSP -POSIXThread::GetPrivateStopReason() +bool +POSIXThread::CalculateStopInfo() { - return m_actual_stop_info_sp; + SetStopInfo (m_actual_stop_info_sp); + return true; } Unwind * diff --git a/lldb/source/Plugins/Process/POSIX/POSIXThread.h b/lldb/source/Plugins/Process/POSIX/POSIXThread.h index 69bca49839a..fc6c759f0f5 100644 --- a/lldb/source/Plugins/Process/POSIX/POSIXThread.h +++ b/lldb/source/Plugins/Process/POSIX/POSIXThread.h @@ -97,8 +97,8 @@ private: ProcessMonitor & GetMonitor(); - lldb::StopInfoSP - GetPrivateStopReason(); + virtual bool + CalculateStopInfo(); void BreakNotify(const ProcessMessage &message); void WatchNotify(const ProcessMessage &message); diff --git a/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp b/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp index 3d08026cf98..56e5a9a59fa 100644 --- a/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp +++ b/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp @@ -99,209 +99,34 @@ ThreadMemory::CreateRegisterContextForFrame (StackFrame *frame) return reg_ctx_sp; } - -//class StopInfoThreadMemory : public StopInfo -//{ -//public: -// //------------------------------------------------------------------ -// // Constructors and Destructors -// //------------------------------------------------------------------ -// StopInfoThreadMemory (Thread &thread, -// uint64_t value, -// StopInfoSP &backing_stop_info_sp) : -// StopInfo (thread, value), -// m_backing_stop_info_sp (backing_stop_info_sp) -// { -// } -// -// virtual -// ~StopInfoThreadMemory() -// { -// } -// -// virtual bool -// IsValid () const -// { -// ThreadSP backing_thread_sp (m_thread.GetBackingThread()); -// if (backing_thread_sp) -// return backing_thread_sp->IsValid(); -// return StopInfo::IsValid(); -// } -// -// virtual Thread & -// GetThread() -// { -// return m_thread; -// } -// -// virtual const Thread & -// GetThread() const -// { -// return m_thread; -// } -// -// virtual uint64_t -// GetValue() const -// { -// if (m_backing_stop_info_sp) -// return m_backing_stop_info_sp->GetValue(); -// return StopInfo::GetValue(); -// } -// -// virtual lldb::StopReason -// GetStopReason () const -// { -// if (m_backing_stop_info_sp) -// return m_backing_stop_info_sp->GetStopReason(); -// return eStopReasonNone; -// } -// -// // ShouldStopSynchronous will get called before any thread plans are consulted, and if it says we should -// // resume the target, then we will just immediately resume. This should not run any code in or resume the -// // target. -// -// virtual bool -// ShouldStopSynchronous (Event *event_ptr) -// { -// if (m_backing_stop_info_sp) -// return m_backing_stop_info_sp->ShouldStopSynchronous(event_ptr); -// return StopInfo::ShouldStopSynchronous (event_ptr); -// } -// -// // If should stop returns false, check if we should notify of this event -// virtual bool -// ShouldNotify (Event *event_ptr) -// { -// if (m_backing_stop_info_sp) -// return m_backing_stop_info_sp->ShouldNotify(event_ptr); -// return StopInfo::ShouldNotify (event_ptr); -// } -// -// virtual void -// WillResume (lldb::StateType resume_state) -// { -// if (m_backing_stop_info_sp) -// return m_backing_stop_info_sp->WillResume(resume_state); -// return StopInfo::WillResume (resume_state); -// } -// -// virtual const char * -// GetDescription () -// { -// if (m_backing_stop_info_sp) -// return m_backing_stop_info_sp->GetDescription(); -// return StopInfo::GetDescription(); -// } -// -// virtual void -// SetDescription (const char *desc_cstr) -// { -// if (m_backing_stop_info_sp) -// m_backing_stop_info_sp->SetDescription(desc_cstr); -// StopInfo::SetDescription(desc_cstr); -// } -// -// // Sometimes the thread plan logic will know that it wants a given stop to stop or not, -// // regardless of what the ordinary logic for that StopInfo would dictate. The main example -// // of this is the ThreadPlanCallFunction, which for instance knows - based on how that particular -// // expression was executed - whether it wants all breakpoints to auto-continue or not. -// // Use OverrideShouldStop on the StopInfo to implement this. -// -// virtual void -// OverrideShouldStop (bool override_value) -// { -// if (m_backing_stop_info_sp) -// m_backing_stop_info_sp->OverrideShouldStop(override_value); -// StopInfo::OverrideShouldStop (override_value); -// } -// -// virtual bool -// GetOverrideShouldStop() -// { -// if (m_backing_stop_info_sp) -// return m_backing_stop_info_sp->GetOverrideShouldStop(); -// return StopInfo::GetOverrideShouldStop(); -// } -// -// virtual bool -// GetOverriddenShouldStopValue () -// { -// if (m_backing_stop_info_sp) -// return m_backing_stop_info_sp->GetOverriddenShouldStopValue(); -// return StopInfo::GetOverriddenShouldStopValue(); -// } -// -// virtual void -// PerformAction (Event *event_ptr) -// { -// if (m_backing_stop_info_sp) -// return m_backing_stop_info_sp->PerformAction(event_ptr); -// return StopInfo::PerformAction(event_ptr); -// } -// -// virtual bool -// ShouldStop (Event *event_ptr) -// { -// if (m_backing_stop_info_sp) -// return m_backing_stop_info_sp->ShouldStop(event_ptr); -// return StopInfo::ShouldStop(event_ptr); -// } -// -// -//protected: -// StopInfoSP m_backing_stop_info_sp; -// -//private: -// DISALLOW_COPY_AND_ASSIGN (StopInfoThreadMemory); -//}; - - -lldb::StopInfoSP -ThreadMemory::GetPrivateStopReason () +bool +ThreadMemory::CalculateStopInfo () { - if (m_actual_stop_info_sp) - return m_actual_stop_info_sp; - if (m_backing_thread_sp) { - lldb::StopInfoSP backing_stop_info_sp (m_backing_thread_sp->GetPrivateStopReason()); + lldb::StopInfoSP backing_stop_info_sp (m_backing_thread_sp->GetPrivateStopInfo()); if (backing_stop_info_sp) { - m_actual_stop_info_sp = backing_stop_info_sp; - m_actual_stop_info_sp->SetThread (shared_from_this()); - return m_actual_stop_info_sp; + backing_stop_info_sp->SetThread (shared_from_this()); + SetStopInfo (backing_stop_info_sp); + return true; } } - - ProcessSP process_sp (GetProcess()); - - if (process_sp) + else { - 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 (IsStillAtLastBreakpointHit()) - return m_actual_stop_info_sp; + ProcessSP process_sp (GetProcess()); - // 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(); - + if (process_sp) + { 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 @@ -309,4 +134,7 @@ ThreadMemory::RefreshStateAfterStop() { if (m_backing_thread_sp) return m_backing_thread_sp->RefreshStateAfterStop(); + + if (m_reg_context_sp) + m_reg_context_sp->InvalidateAllRegisters(); } diff --git a/lldb/source/Plugins/Process/Utility/ThreadMemory.h b/lldb/source/Plugins/Process/Utility/ThreadMemory.h index 2a1f7d6b67d..07eb45dcb43 100644 --- a/lldb/source/Plugins/Process/Utility/ThreadMemory.h +++ b/lldb/source/Plugins/Process/Utility/ThreadMemory.h @@ -39,8 +39,8 @@ public: virtual lldb::RegisterContextSP CreateRegisterContextForFrame (lldb_private::StackFrame *frame); - virtual lldb::StopInfoSP - GetPrivateStopReason (); + virtual bool + CalculateStopInfo (); virtual const char * GetInfo () diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 0302f9312b7..0008dbfa288 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -1770,7 +1770,7 @@ ProcessGDBRemote::DoDestroy () for (size_t i = 0; i < num_threads; i++) { ThreadSP thread_sp = threads.GetThreadAtIndex(i); - StopInfoSP stop_info_sp = thread_sp->GetPrivateStopReason(); + StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo(); StopReason reason = eStopReasonInvalid; if (stop_info_sp) reason = stop_info_sp->GetStopReason(); @@ -1805,7 +1805,7 @@ ProcessGDBRemote::DoDestroy () for (size_t i = 0; i < num_threads; i++) { ThreadSP thread_sp = threads.GetThreadAtIndex(i); - StopInfoSP stop_info_sp = thread_sp->GetPrivateStopReason(); + StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo(); StopReason reason = eStopReasonInvalid; if (stop_info_sp) reason = stop_info_sp->GetStopReason(); diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp index 40b367c3993..38fb84d66ef 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -197,56 +197,18 @@ ThreadGDBRemote::PrivateSetRegisterValue (uint32_t reg, StringExtractor &respons return gdb_reg_ctx->PrivateSetRegisterValue (reg, response); } -lldb::StopInfoSP -ThreadGDBRemote::GetPrivateStopReason () +bool +ThreadGDBRemote::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) - { - // Our stop info is up to date even if it is empty... - return m_actual_stop_info_sp; - } - - if (m_actual_stop_info_sp && m_actual_stop_info_sp->IsValid()) - { - // The stop info is up to date, reset it so everything updates - SetStopInfo (m_actual_stop_info_sp); - } - else - { - if (IsStillAtLastBreakpointHit()) - { - SetStopInfo(m_actual_stop_info_sp); - } - else - { - // 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_actual_stop_info_sp.reset(); - - StringExtractorGDBRemote stop_packet; - ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get()); - if (gdb_process->GetGDBRemote().GetThreadStopInfo(GetProtocolID(), stop_packet)) - { - gdb_process->SetThreadStopInfo (stop_packet); - } - else - { - SetStopInfo (StopInfoSP()); - } - } - } + StringExtractorGDBRemote stop_packet; + ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get()); + if (gdb_process->GetGDBRemote().GetThreadStopInfo(GetProtocolID(), stop_packet)) + return gdb_process->SetThreadStopInfo (stop_packet) == eStateStopped; } - return m_actual_stop_info_sp; + return false; } diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h index 8dfc4bb78cb..50a3f19c650 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h @@ -98,8 +98,8 @@ protected: void SetStopInfoFromPacket (StringExtractor &stop_packet, uint32_t stop_id); - virtual lldb::StopInfoSP - GetPrivateStopReason (); + virtual bool + CalculateStopInfo (); }; diff --git a/lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp index a4e366101fa..85a7a20e042 100644 --- a/lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp +++ b/lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp @@ -117,39 +117,16 @@ ThreadMachCore::CreateRegisterContextForFrame (StackFrame *frame) return reg_ctx_sp; } -lldb::StopInfoSP -ThreadMachCore::GetPrivateStopReason () +bool +ThreadMachCore::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 (IsStillAtLastBreakpointHit()) - return m_actual_stop_info_sp; - - // 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(); - - } + SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, SIGSTOP)); + return true; } - return m_actual_stop_info_sp; + return false; } diff --git a/lldb/source/Plugins/Process/mach-core/ThreadMachCore.h b/lldb/source/Plugins/Process/mach-core/ThreadMachCore.h index cc687573c6a..756a04a3cbd 100644 --- a/lldb/source/Plugins/Process/mach-core/ThreadMachCore.h +++ b/lldb/source/Plugins/Process/mach-core/ThreadMachCore.h @@ -79,11 +79,10 @@ protected: lldb::addr_t m_thread_dispatch_qaddr; lldb::RegisterContextSP m_thread_reg_ctx_sp; //------------------------------------------------------------------ - // Member variables. + // Protected member functions. //------------------------------------------------------------------ - - virtual lldb::StopInfoSP - GetPrivateStopReason (); + virtual bool + CalculateStopInfo (); }; #endif // liblldb_ThreadMachCore_h_ diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index 478021ac367..c4aa2544682 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -243,9 +243,9 @@ Thread::Thread (Process &process, lldb::tid_t tid) : UserID (tid), Broadcaster(&process.GetTarget().GetDebugger(), Thread::GetStaticBroadcasterClass().AsCString()), m_process_wp (process.shared_from_this()), - m_actual_stop_info_sp (), + m_stop_info_sp (), + m_stop_info_stop_id (0), m_index_id (process.GetNextThreadIndexID(tid)), - m_protocol_tid (tid), m_reg_context_sp (), m_state (eStateUnloaded), m_state_mutex (Mutex::eMutexTypeRecursive), @@ -259,7 +259,6 @@ Thread::Thread (Process &process, lldb::tid_t tid) : m_temporary_resume_state (eStateRunning), m_unwinder_ap (), m_destroy_called (false), - m_thread_stop_reason_stop_id (0), m_override_should_notify (eLazyBoolCalculate) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); @@ -283,11 +282,17 @@ Thread::~Thread() void Thread::DestroyThread () { + // Tell any plans on the plan stack that the thread is being destroyed since + // any active plans that have a thread go away in the middle of might need + // to do cleanup. + for (auto plan : m_plan_stack) + plan->ThreadDestroyed(); + m_destroy_called = true; m_plan_stack.clear(); m_discarded_plan_stack.clear(); m_completed_plan_stack.clear(); - m_actual_stop_info_sp.reset(); + m_stop_info_sp.reset(); m_reg_context_sp.reset(); m_unwinder_ap.reset(); Mutex::Locker locker(m_frame_mutex); @@ -366,19 +371,58 @@ Thread::GetStopInfo () } else { - if ((m_thread_stop_reason_stop_id == stop_id) || // Stop info is valid, just return what we have (even if empty) - (m_actual_stop_info_sp && m_actual_stop_info_sp->IsValid())) // Stop info is valid, just return what we have + if ((m_stop_info_stop_id == stop_id) || // Stop info is valid, just return what we have (even if empty) + (m_stop_info_sp && m_stop_info_sp->IsValid())) // Stop info is valid, just return what we have { - return m_actual_stop_info_sp; + return m_stop_info_sp; } else { - GetPrivateStopReason (); - return m_actual_stop_info_sp; + GetPrivateStopInfo (); + return m_stop_info_sp; + } + } +} + +lldb::StopInfoSP +Thread::GetPrivateStopInfo () +{ + ProcessSP process_sp (GetProcess()); + if (process_sp) + { + ProcessSP process_sp (GetProcess()); + if (process_sp) + { + const uint32_t process_stop_id = process_sp->GetStopID(); + if (m_stop_info_stop_id != process_stop_id) + { + if (m_stop_info_sp) + { + if (m_stop_info_sp->IsValid()) + { + SetStopInfo (m_stop_info_sp); + } + else + { + if (IsStillAtLastBreakpointHit()) + SetStopInfo(m_stop_info_sp); + else + m_stop_info_sp.reset(); + } + } + + if (!m_stop_info_sp) + { + if (CalculateStopInfo() == false) + SetStopInfo (StopInfoSP()); + } + } } } + return m_stop_info_sp; } + lldb::StopReason Thread::GetStopReason() { @@ -393,20 +437,20 @@ Thread::GetStopReason() void Thread::SetStopInfo (const lldb::StopInfoSP &stop_info_sp) { - m_actual_stop_info_sp = stop_info_sp; - if (m_actual_stop_info_sp) + m_stop_info_sp = stop_info_sp; + if (m_stop_info_sp) { - m_actual_stop_info_sp->MakeStopInfoValid(); + m_stop_info_sp->MakeStopInfoValid(); // If we are overriding the ShouldReportStop, do that here: if (m_override_should_notify != eLazyBoolCalculate) - m_actual_stop_info_sp->OverrideShouldNotify (m_override_should_notify == eLazyBoolYes); + m_stop_info_sp->OverrideShouldNotify (m_override_should_notify == eLazyBoolYes); } ProcessSP process_sp (GetProcess()); if (process_sp) - m_thread_stop_reason_stop_id = process_sp->GetStopID(); + m_stop_info_stop_id = process_sp->GetStopID(); else - m_thread_stop_reason_stop_id = UINT32_MAX; + m_stop_info_stop_id = UINT32_MAX; } void @@ -417,8 +461,8 @@ Thread::SetShouldReportStop (Vote vote) else { m_override_should_notify = (vote == eVoteYes ? eLazyBoolYes : eLazyBoolNo); - if (m_actual_stop_info_sp) - m_actual_stop_info_sp->OverrideShouldNotify (m_override_should_notify == eLazyBoolYes); + if (m_stop_info_sp) + m_stop_info_sp->OverrideShouldNotify (m_override_should_notify == eLazyBoolYes); } } @@ -433,7 +477,7 @@ Thread::SetStopInfoToNothing() bool Thread::ThreadStoppedForAReason (void) { - return (bool) GetPrivateStopReason (); + return (bool) GetPrivateStopInfo (); } bool @@ -554,18 +598,22 @@ Thread::ShouldResume (StateType resume_state) m_temporary_resume_state = resume_state; - // Make sure m_actual_stop_info_sp is valid - GetPrivateStopReason(); + lldb::ThreadSP backing_thread_sp (GetBackingThread ()); + if (backing_thread_sp) + backing_thread_sp->m_temporary_resume_state = resume_state; + + // Make sure m_stop_info_sp is valid + GetPrivateStopInfo(); // This is a little dubious, but we are trying to limit how often we actually fetch stop info from // the target, 'cause that slows down single stepping. So assume that if we got to the point where // we're about to resume, and we haven't yet had to fetch the stop reason, then it doesn't need to know // about the fact that we are resuming... const uint32_t process_stop_id = GetProcess()->GetStopID(); - if (m_thread_stop_reason_stop_id == process_stop_id && - (m_actual_stop_info_sp && m_actual_stop_info_sp->IsValid())) + if (m_stop_info_stop_id == process_stop_id && + (m_stop_info_sp && m_stop_info_sp->IsValid())) { - StopInfo *stop_info = GetPrivateStopReason().get(); + StopInfo *stop_info = GetPrivateStopInfo().get(); if (stop_info) stop_info->WillResume (resume_state); } @@ -590,7 +638,7 @@ Thread::ShouldResume (StateType resume_state) if (need_to_resume && resume_state != eStateSuspended) { - m_actual_stop_info_sp.reset(); + m_stop_info_sp.reset(); } } @@ -676,7 +724,7 @@ Thread::ShouldStop (Event* event_ptr) // First query the stop info's ShouldStopSynchronous. This handles "synchronous" stop reasons, for example the breakpoint // command on internal breakpoints. If a synchronous stop reason says we should not stop, then we don't have to // do any more work on this stop. - StopInfoSP private_stop_info (GetPrivateStopReason()); + StopInfoSP private_stop_info (GetPrivateStopInfo()); if (private_stop_info && private_stop_info->ShouldStopSynchronous(event_ptr) == false) { if (log) @@ -1906,10 +1954,10 @@ Thread::IsStillAtLastBreakpointHit () // If we are currently stopped at a breakpoint, always return that stopinfo and don't reset it. // This allows threads to maintain their breakpoint stopinfo, such as when thread-stepping in // multithreaded programs. - if (m_actual_stop_info_sp) { - StopReason stop_reason = m_actual_stop_info_sp->GetStopReason(); + if (m_stop_info_sp) { + StopReason stop_reason = m_stop_info_sp->GetStopReason(); if (stop_reason == lldb::eStopReasonBreakpoint) { - uint64_t value = m_actual_stop_info_sp->GetValue(); + uint64_t value = m_stop_info_sp->GetValue(); lldb::RegisterContextSP reg_ctx_sp (GetRegisterContext()); if (reg_ctx_sp) { diff --git a/lldb/source/Target/ThreadList.cpp b/lldb/source/Target/ThreadList.cpp index 8db2b40d292..1f8b351100a 100644 --- a/lldb/source/Target/ThreadList.cpp +++ b/lldb/source/Target/ThreadList.cpp @@ -505,6 +505,8 @@ ThreadList::WillResume () if ((*pos)->GetResumeState() != eStateSuspended && (*pos)->GetCurrentPlan()->StopOthers()) { + if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread()) + continue; wants_solo_run = true; break; } @@ -535,6 +537,8 @@ ThreadList::WillResume () if ((*pos)->GetResumeState() != eStateSuspended && (!wants_solo_run || (*pos)->GetCurrentPlan()->StopOthers())) { + if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread()) + continue; (*pos)->SetupForResume (); } } @@ -546,7 +550,6 @@ ThreadList::WillResume () run_me_only_list.SetStopID(m_process->GetStopID()); - ThreadSP immediate_thread_sp; bool run_only_current_thread = false; for (pos = m_threads.begin(); pos != end; ++pos) @@ -555,6 +558,9 @@ ThreadList::WillResume () if (thread_sp->GetResumeState() != eStateSuspended && thread_sp->GetCurrentPlan()->StopOthers()) { + if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread()) + continue; + // You can't say "stop others" and also want yourself to be suspended. assert (thread_sp->GetCurrentPlan()->RunState() != eStateSuspended); @@ -573,18 +579,7 @@ ThreadList::WillResume () bool need_to_resume = true; - if (immediate_thread_sp) - { - for (pos = m_threads.begin(); pos != end; ++pos) - { - ThreadSP thread_sp(*pos); - if (thread_sp.get() == immediate_thread_sp.get()) - thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState()); - else - thread_sp->ShouldResume (eStateSuspended); - } - } - else if (run_me_only_list.GetSize (false) == 0) + if (run_me_only_list.GetSize (false) == 0) { // Everybody runs as they wish: for (pos = m_threads.begin(); pos != end; ++pos) diff --git a/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp b/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp index 00a19804b2c..ff4fee72a3a 100644 --- a/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp +++ b/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp @@ -34,7 +34,8 @@ ThreadPlanStepOverBreakpoint::ThreadPlanStepOverBreakpoint (Thread &thread) : // first in the thread plan stack when stepping // over a breakpoint m_breakpoint_addr (LLDB_INVALID_ADDRESS), - m_auto_continue(false) + m_auto_continue(false), + m_reenabled_breakpoint_site (false) { m_breakpoint_addr = m_thread.GetRegisterContext()->GetPC(); @@ -105,9 +106,7 @@ ThreadPlanStepOverBreakpoint::DoWillResume (StateType resume_state, bool current bool ThreadPlanStepOverBreakpoint::WillStop () { - BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress (m_breakpoint_addr)); - if (bp_site_sp) - m_thread.GetProcess()->EnableBreakpointSite (bp_site_sp.get()); + ReenableBreakpointSite (); return true; } @@ -128,13 +127,30 @@ ThreadPlanStepOverBreakpoint::MischiefManaged () if (log) log->Printf("Completed step over breakpoint plan."); // Otherwise, re-enable the breakpoint we were stepping over, and we're done. + ReenableBreakpointSite (); + ThreadPlan::MischiefManaged (); + return true; + } +} + +void +ThreadPlanStepOverBreakpoint::ReenableBreakpointSite () +{ + if (!m_reenabled_breakpoint_site) + { + m_reenabled_breakpoint_site = true; BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress (m_breakpoint_addr)); if (bp_site_sp) + { m_thread.GetProcess()->EnableBreakpointSite (bp_site_sp.get()); - ThreadPlan::MischiefManaged (); - return true; + } } } +void +ThreadPlanStepOverBreakpoint::ThreadDestroyed () +{ + ReenableBreakpointSite (); +} void ThreadPlanStepOverBreakpoint::SetAutoContinue (bool do_it) |