diff options
25 files changed, 874 insertions, 241 deletions
diff --git a/lldb/include/lldb/Target/OperatingSystem.h b/lldb/include/lldb/Target/OperatingSystem.h index c568a40bcb6..3455333ec64 100644 --- a/lldb/include/lldb/Target/OperatingSystem.h +++ b/lldb/include/lldb/Target/OperatingSystem.h @@ -81,6 +81,10 @@ public: { return lldb::ThreadSP(); } + + virtual bool + IsOperatingSystemPluginThread (const lldb::ThreadSP &thread_sp); + protected: //------------------------------------------------------------------ // Member variables. diff --git a/lldb/include/lldb/Target/RegisterContext.h b/lldb/include/lldb/Target/RegisterContext.h index a68629d6a7f..dd0e73fc7eb 100644 --- a/lldb/include/lldb/Target/RegisterContext.h +++ b/lldb/include/lldb/Target/RegisterContext.h @@ -111,10 +111,10 @@ public: //------------------------------------------------------------------ // Subclasses should not override these //------------------------------------------------------------------ - lldb::tid_t + virtual lldb::tid_t GetThreadID() const; - Thread & + virtual Thread & GetThread () { return m_thread; diff --git a/lldb/include/lldb/Target/StopInfo.h b/lldb/include/lldb/Target/StopInfo.h index 51b54553774..c4f243ea1ad 100644 --- a/lldb/include/lldb/Target/StopInfo.h +++ b/lldb/include/lldb/Target/StopInfo.h @@ -40,6 +40,12 @@ public: bool IsValid () const; + void + SetThread (const lldb::ThreadSP &thread_sp) + { + m_thread_wp = thread_sp; + } + lldb::ThreadSP GetThread() const { diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h index e76cb88e4b6..c1cd2a75d42 100644 --- a/lldb/include/lldb/Target/Thread.h +++ b/lldb/include/lldb/Target/Thread.h @@ -255,17 +255,22 @@ public: m_resume_state = state; } - // This function is called on all the threads before "WillResume" in case - // a thread needs to change its state before the ThreadList polls all the - // threads to figure out which ones actually will get to run and how. + // This function is called on all the threads before "ShouldResume" and + // "WillResume" in case a thread needs to change its state before the + // ThreadList polls all the threads to figure out which ones actually + // will get to run and how. void SetupForResume (); - // Override this to do platform specific tasks before resume, but always - // call the Thread::WillResume at the end of your work. + // Do not override this function, it is for thread plan logic only + bool + ShouldResume (lldb::StateType resume_state); - virtual bool - WillResume (lldb::StateType resume_state); + // Override this to do platform specific tasks before resume. + virtual void + WillResume (lldb::StateType resume_state) + { + } // This clears generic thread state after a resume. If you subclass this, // be sure to call it. @@ -820,13 +825,34 @@ public: void SetTracer (lldb::ThreadPlanTracerSP &tracer_sp); - // Get the thread index ID. The index ID that is guaranteed to not be - // re-used by a process. They start at 1 and increase with each new thread. - // This allows easy command line access by a unique ID that is easier to - // type than the actual system thread ID. + //------------------------------------------------------------------ + // Get the thread index ID. The index ID that is guaranteed to not + // be re-used by a process. They start at 1 and increase with each + // new thread. This allows easy command line access by a unique ID + // that is easier to type than the actual system thread ID. + //------------------------------------------------------------------ uint32_t GetIndexID () const; + + //------------------------------------------------------------------ + // The API ID is often the same as the Thread::GetID(), but not in + // all cases. Thread::GetID() is the user visible thread ID that + // clients would want to see. The API thread ID is the thread ID + // that is used when sending data to/from the debugging protocol. + //------------------------------------------------------------------ + 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); + } + //------------------------------------------------------------------ // lldb::ExecutionContextScope pure virtual functions //------------------------------------------------------------------ @@ -881,7 +907,7 @@ public: // Gets the temporary resume state for a thread. // // This value gets set in each thread by complex debugger logic in - // Thread::WillResume() and an appropriate thread resume state will get + // Thread::ShouldResume() and an appropriate thread resume state will get // set in each thread every time the process is resumed prior to calling // Process::DoResume(). The lldb_private::Process subclass should adhere // to the thread resume state request which will be one of: @@ -898,6 +924,9 @@ public: return m_temporary_resume_state; } + void + SetStopInfo (const lldb::StopInfoSP &stop_info_sp); + protected: friend class ThreadPlan; @@ -905,6 +934,7 @@ protected: friend class ThreadEventData; friend class StackFrameList; friend class StackFrame; + friend class OperatingSystem; // This is necessary to make sure thread assets get destroyed while the thread is still in good shape // to call virtual thread methods. This must be called by classes that derive from Thread in their destructor. @@ -923,9 +953,6 @@ protected: typedef std::vector<lldb::ThreadPlanSP> plan_stack; - void - SetStopInfo (const lldb::StopInfoSP &stop_info_sp); - virtual bool SaveFrameZeroState (RegisterCheckpoint &checkpoint); @@ -943,6 +970,17 @@ protected: virtual bool IsStillAtLastBreakpointHit(); + // Some threads are threads that are made up by OperatingSystem plugins that + // are threads that exist and are context switched out into memory. The + // OperatingSystem plug-in need a ways to know if a thread is "real" or made + // up. + virtual bool + IsOperatingSystemPluginThread () const + { + return false; + } + + lldb::StackFrameListSP GetStackFrameList (); @@ -959,6 +997,7 @@ protected: 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 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. @@ -971,7 +1010,7 @@ protected: int m_resume_signal; ///< The signal that should be used when continuing this thread. lldb::StateType m_resume_state; ///< This state is used to force a thread to be suspended from outside the ThreadPlan logic. lldb::StateType m_temporary_resume_state; ///< This state records what the thread was told to do by the thread plan logic for the current resume. - /// It gets set in Thread::WillResume. + /// 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 diff --git a/lldb/include/lldb/Target/ThreadList.h b/lldb/include/lldb/Target/ThreadList.h index 345cefd008a..c219434d152 100644 --- a/lldb/include/lldb/Target/ThreadList.h +++ b/lldb/include/lldb/Target/ThreadList.h @@ -73,9 +73,15 @@ public: lldb::ThreadSP FindThreadByID (lldb::tid_t tid, bool can_update = true); + + lldb::ThreadSP + FindThreadByProtocolID (lldb::tid_t tid, bool can_update = true); lldb::ThreadSP RemoveThreadByID (lldb::tid_t tid, bool can_update = true); + + lldb::ThreadSP + RemoveThreadByProtocolID (lldb::tid_t tid, bool can_update = true); lldb::ThreadSP FindThreadByIndexID (uint32_t index_id, bool can_update = true); diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index 81c89950998..6c75fe702ea 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -440,6 +440,8 @@ 26BD407F135D2AE000237D80 /* FileLineResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BD407E135D2ADF00237D80 /* FileLineResolver.cpp */; }; 26C72C94124322890068DC16 /* SBStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 26C72C93124322890068DC16 /* SBStream.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26C72C961243229A0068DC16 /* SBStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C72C951243229A0068DC16 /* SBStream.cpp */; }; + 26CA97A1172B1FD5005DC71B /* RegisterContextThreadMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26CA979F172B1FD5005DC71B /* RegisterContextThreadMemory.cpp */; }; + 26CA97A2172B1FD5005DC71B /* RegisterContextThreadMemory.h in Headers */ = {isa = PBXBuildFile; fileRef = 26CA97A0172B1FD5005DC71B /* RegisterContextThreadMemory.h */; }; 26D1803E16CEBFD300EDFB5B /* KQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D1803C16CEBFD300EDFB5B /* KQueue.cpp */; }; 26D1804216CEDF0700EDFB5B /* TimeSpecTimeout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D1804016CEDF0700EDFB5B /* TimeSpecTimeout.cpp */; }; 26D1804516CEE12500EDFB5B /* KQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 26D1804416CEE12500EDFB5B /* KQueue.h */; }; @@ -1333,6 +1335,8 @@ 26C72C951243229A0068DC16 /* SBStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBStream.cpp; path = source/API/SBStream.cpp; sourceTree = "<group>"; }; 26C81CA411335651004BDC5A /* UUID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UUID.h; path = include/lldb/Core/UUID.h; sourceTree = "<group>"; }; 26C81CA511335651004BDC5A /* UUID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UUID.cpp; path = source/Core/UUID.cpp; sourceTree = "<group>"; }; + 26CA979F172B1FD5005DC71B /* RegisterContextThreadMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextThreadMemory.cpp; path = Utility/RegisterContextThreadMemory.cpp; sourceTree = "<group>"; }; + 26CA97A0172B1FD5005DC71B /* RegisterContextThreadMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextThreadMemory.h; path = Utility/RegisterContextThreadMemory.h; sourceTree = "<group>"; }; 26CF992414428766001E4138 /* AnsiTerminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AnsiTerminal.h; path = include/lldb/Utility/AnsiTerminal.h; sourceTree = "<group>"; }; 26D0DD5010FE554D00271C65 /* BreakpointResolverAddress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointResolverAddress.h; path = include/lldb/Breakpoint/BreakpointResolverAddress.h; sourceTree = "<group>"; }; 26D0DD5110FE554D00271C65 /* BreakpointResolverFileLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointResolverFileLine.h; path = include/lldb/Breakpoint/BreakpointResolverFileLine.h; sourceTree = "<group>"; }; @@ -2523,6 +2527,8 @@ 262D24E513FB8710002D1960 /* RegisterContextMemory.h */, 26E3EEF811A994E800FBADB6 /* RegisterContextMacOSXFrameBackchain.h */, 26E3EEF711A994E800FBADB6 /* RegisterContextMacOSXFrameBackchain.cpp */, + 26CA979F172B1FD5005DC71B /* RegisterContextThreadMemory.cpp */, + 26CA97A0172B1FD5005DC71B /* RegisterContextThreadMemory.h */, 2615DBC91208B5FC0021781D /* StopInfoMachException.h */, 2615DBC81208B5FC0021781D /* StopInfoMachException.cpp */, 26F4A21A13FBA31A0064B613 /* ThreadMemory.cpp */, @@ -3574,6 +3580,7 @@ 4C6649A014EEE7F100B0316F /* StreamCallback.h in Headers */, 26B7564F14F89356008D9CB3 /* PlatformiOSSimulator.h in Headers */, 26FFC19A14FC072100087D58 /* AuxVector.h in Headers */, + 26CA97A2172B1FD5005DC71B /* RegisterContextThreadMemory.h in Headers */, 26FFC19C14FC072100087D58 /* DYLDRendezvous.h in Headers */, 26FFC19E14FC072100087D58 /* DynamicLoaderPOSIXDYLD.h in Headers */, AF254E32170CCC33007AE5C9 /* PlatformDarwinKernel.h in Headers */, @@ -4214,6 +4221,7 @@ 2689010713353E6F00698AC0 /* ThreadPlanStepThrough.cpp in Sources */, 2689010813353E6F00698AC0 /* ThreadPlanStepUntil.cpp in Sources */, 2689010A13353E6F00698AC0 /* ThreadPlanTracer.cpp in Sources */, + 26CA97A1172B1FD5005DC71B /* RegisterContextThreadMemory.cpp in Sources */, 2689010B13353E6F00698AC0 /* ThreadSpec.cpp in Sources */, 2689010C13353E6F00698AC0 /* UnixSignals.cpp in Sources */, 2689011013353E8200698AC0 /* SharingPtr.cpp in Sources */, diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 42a1540986e..ab2f8173203 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -1964,6 +1964,11 @@ Debugger::FormatPrompt s.Printf("0x%4.4" PRIx64, thread->GetID()); var_success = true; } + else if (::strncmp (var_name_begin, "protocol_id}", strlen("protocol_id}")) == 0) + { + s.Printf("0x%4.4" PRIx64, thread->GetProtocolID()); + var_success = true; + } else if (::strncmp (var_name_begin, "index}", strlen("index}")) == 0) { s.Printf("%u", thread->GetIndexID()); diff --git a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp index a7aaedb9a0c..fc05d6e18ec 100644 --- a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp +++ b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp @@ -247,8 +247,8 @@ OperatingSystemPython::CreateThreadFromThreadInfo (PythonDictionary &thread_dict PythonString core_pystr("core"); PythonString name_pystr("name"); PythonString queue_pystr("queue"); - PythonString state_pystr("state"); - PythonString stop_reason_pystr("stop_reason"); + //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); @@ -258,7 +258,21 @@ OperatingSystemPython::CreateThreadFromThreadInfo (PythonDictionary &thread_dict //const char *state = thread_dict.GetItemForKeyAsString (state_pystr); //const char *stop_reason = thread_dict.GetItemForKeyAsString (stop_reason_pystr); + // See if a thread already exists for "tid" thread_sp = old_thread_list.FindThreadByID (tid, false); + if (thread_sp) + { + // A thread already does exist for "tid", make sure it was an operating system + // plug-in generated thread. + if (!IsOperatingSystemPluginThread(thread_sp)) + { + // We have thread ID overlap between the protocol threads and the + // operating system threads, clear the thread so we create an + // operating system thread for this. + thread_sp.reset(); + } + } + if (!thread_sp) { if (did_create_ptr) @@ -273,7 +287,19 @@ OperatingSystemPython::CreateThreadFromThreadInfo (PythonDictionary &thread_dict if (core_number < core_thread_list.GetSize(false)) { - thread_sp->SetBackingThread(core_thread_list.GetThreadAtIndex(core_number, false)); + ThreadSP core_thread_sp (core_thread_list.GetThreadAtIndex(core_number, false)); + if (core_thread_sp) + { + ThreadSP backing_core_thread_sp (core_thread_sp->GetBackingThread()); + if (backing_core_thread_sp) + { + thread_sp->SetBackingThread(backing_core_thread_sp); + } + else + { + thread_sp->SetBackingThread(core_thread_sp); + } + } } } } @@ -292,7 +318,10 @@ OperatingSystemPython::CreateRegisterContextForThread (Thread *thread, addr_t re { RegisterContextSP reg_ctx_sp; if (!m_interpreter || !m_python_object_sp || !thread) - return RegisterContextSP(); + return reg_ctx_sp; + + if (!IsOperatingSystemPluginThread(thread->shared_from_this())) + return reg_ctx_sp; // 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. @@ -308,7 +337,10 @@ OperatingSystemPython::CreateRegisterContextForThread (Thread *thread, addr_t re // The registers data is in contiguous memory, just create the register // context using the address provided if (log) - log->Printf ("OperatingSystemPython::CreateRegisterContextForThread (tid = 0x%" PRIx64 ", reg_data_addr = 0x%" PRIx64 ") creating memory register context", thread->GetID(), reg_data_addr); + log->Printf ("OperatingSystemPython::CreateRegisterContextForThread (tid = 0x%" PRIx64 ", 0x%" PRIx64 ", reg_data_addr = 0x%" PRIx64 ") creating memory register context", + thread->GetID(), + thread->GetProtocolID(), + reg_data_addr); reg_ctx_sp.reset (new RegisterContextMemory (*thread, 0, *GetDynamicRegisterInfo (), reg_data_addr)); } else @@ -316,7 +348,9 @@ OperatingSystemPython::CreateRegisterContextForThread (Thread *thread, addr_t re // No register data address is provided, query the python plug-in to let // it make up the data as it sees fit if (log) - log->Printf ("OperatingSystemPython::CreateRegisterContextForThread (tid = 0x%" PRIx64 ") fetching register data from python", thread->GetID()); + log->Printf ("OperatingSystemPython::CreateRegisterContextForThread (tid = 0x%" PRIx64 ", 0x%" PRIx64 ") fetching register data from python", + thread->GetID(), + thread->GetProtocolID()); PythonString reg_context_data(m_interpreter->OSPlugin_RegisterContextData (m_python_object_sp, thread->GetID())); if (reg_context_data) diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp index a8b1b08bcdb..6f0116e7f44 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp @@ -66,23 +66,6 @@ ThreadKDP::GetQueueName () return NULL; } -bool -ThreadKDP::WillResume (StateType resume_state) -{ - // 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); - - ClearStackFrames(); - - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP)); - if (log) - log->Printf ("Resuming thread: %4.4" PRIx64 " with state: %s.", GetID(), StateAsCString(resume_state)); - - return true; -} - void ThreadKDP::RefreshStateAfterStop() { @@ -100,16 +83,6 @@ ThreadKDP::RefreshStateAfterStop() reg_ctx_sp->InvalidateIfNeeded (force); } -void -ThreadKDP::ClearStackFrames () -{ - Unwind *unwinder = GetUnwinder (); - if (unwinder) - unwinder->Clear(); - Thread::ClearStackFrames(); -} - - bool ThreadKDP::ThreadIDIsValid (lldb::tid_t thread) { diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h b/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h index 5454f2b848d..5a980f504fc 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h @@ -26,9 +26,6 @@ public: 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); diff --git a/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp b/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp index 3b2ae03bd71..9210408fdad 100644 --- a/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp +++ b/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp @@ -150,19 +150,12 @@ POSIXThread::GetUnwinder() return m_unwinder_ap.get(); } -bool +void POSIXThread::WillResume(lldb::StateType 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); - - if (!Thread::WillResume(resume_state)) - return false; - - if (m_unwinder_ap.get()) - m_unwinder_ap->Clear(); - Thread::ClearStackFrames(); - - return true; } bool diff --git a/lldb/source/Plugins/Process/POSIX/POSIXThread.h b/lldb/source/Plugins/Process/POSIX/POSIXThread.h index 3a282042997..094e140b390 100644 --- a/lldb/source/Plugins/Process/POSIX/POSIXThread.h +++ b/lldb/source/Plugins/Process/POSIX/POSIXThread.h @@ -36,7 +36,7 @@ public: void RefreshStateAfterStop(); - bool + virtual void WillResume(lldb::StateType resume_state); const char * diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp new file mode 100644 index 00000000000..1cef63d1e22 --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp @@ -0,0 +1,256 @@ +//===-- RegisterContextThreadMemory.cpp -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/lldb-private.h" +#include "lldb/Core/Error.h" +#include "lldb/Target/OperatingSystem.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Thread.h" + +#include "RegisterContextThreadMemory.h" + +using namespace lldb; +using namespace lldb_private; + +RegisterContextThreadMemory::RegisterContextThreadMemory (Thread &thread, + lldb::addr_t register_data_addr) : + RegisterContext (thread, 0), + m_thread_wp (thread.shared_from_this()), + m_reg_ctx_sp (), + m_register_data_addr (register_data_addr), + m_stop_id(0) +{ +} + +RegisterContextThreadMemory::~RegisterContextThreadMemory() +{ +} + +void +RegisterContextThreadMemory::UpdateRegisterContext () +{ + ThreadSP thread_sp (m_thread_wp.lock()); + if (thread_sp) + { + ProcessSP process_sp (thread_sp->GetProcess()); + + if (process_sp) + { + const uint32_t stop_id = process_sp->GetModID().GetStopID(); + if (m_stop_id != stop_id) + { + m_stop_id = stop_id; + m_reg_ctx_sp.reset(); + } + if (!m_reg_ctx_sp) + { + OperatingSystem *os = process_sp->GetOperatingSystem (); + if (os->IsOperatingSystemPluginThread (thread_sp)) + m_reg_ctx_sp = os->CreateRegisterContextForThread (thread_sp.get(), LLDB_INVALID_ADDRESS); + else + { + + ThreadSP backing_thread_sp (thread_sp->GetBackingThread()); + if (backing_thread_sp) + m_reg_ctx_sp = backing_thread_sp->GetRegisterContext(); + } + } + } + } + else + { + m_reg_ctx_sp.reset(); + } +} + +//------------------------------------------------------------------ +// Subclasses must override these functions +//------------------------------------------------------------------ +void +RegisterContextThreadMemory::InvalidateAllRegisters () +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + m_reg_ctx_sp->InvalidateAllRegisters(); +} + +size_t +RegisterContextThreadMemory::GetRegisterCount () +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->GetRegisterCount(); + return 0; +} + +const RegisterInfo * +RegisterContextThreadMemory::GetRegisterInfoAtIndex (size_t reg) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->GetRegisterInfoAtIndex(reg); + return NULL; +} + +size_t +RegisterContextThreadMemory::GetRegisterSetCount () +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->GetRegisterSetCount(); + return 0; +} + +const RegisterSet * +RegisterContextThreadMemory::GetRegisterSet (size_t reg_set) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->GetRegisterSet(reg_set); + return NULL; +} + +bool +RegisterContextThreadMemory::ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->ReadRegister(reg_info, reg_value); + return false; +} + +bool +RegisterContextThreadMemory::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->WriteRegister (reg_info, reg_value); + return false; +} + +bool +RegisterContextThreadMemory::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->ReadAllRegisterValues(data_sp); + return false; +} + +bool +RegisterContextThreadMemory::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->WriteAllRegisterValues (data_sp); + return false; +} + +bool +RegisterContextThreadMemory::CopyFromRegisterContext (lldb::RegisterContextSP reg_ctx_sp) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->CopyFromRegisterContext(reg_ctx_sp); + return false; +} + +uint32_t +RegisterContextThreadMemory::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->ConvertRegisterKindToRegisterNumber(kind, num); + return false; +} + +uint32_t +RegisterContextThreadMemory::NumSupportedHardwareBreakpoints () +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->NumSupportedHardwareBreakpoints(); + return false; +} + +uint32_t +RegisterContextThreadMemory::SetHardwareBreakpoint (lldb::addr_t addr, size_t size) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->SetHardwareBreakpoint(addr, size); + return 0; +} + +bool +RegisterContextThreadMemory::ClearHardwareBreakpoint (uint32_t hw_idx) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->ClearHardwareBreakpoint (hw_idx); + return false; +} + +uint32_t +RegisterContextThreadMemory::NumSupportedHardwareWatchpoints () +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->NumSupportedHardwareWatchpoints(); + return 0; +} + +uint32_t +RegisterContextThreadMemory::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->SetHardwareWatchpoint(addr, size, read, write); + return 0; +} + +bool +RegisterContextThreadMemory::ClearHardwareWatchpoint (uint32_t hw_index) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->ClearHardwareWatchpoint(hw_index); + return false; +} + +bool +RegisterContextThreadMemory::HardwareSingleStep (bool enable) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->HardwareSingleStep(enable); + return false; +} + +Error +RegisterContextThreadMemory::ReadRegisterValueFromMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr, uint32_t src_len, RegisterValue ®_value) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->ReadRegisterValueFromMemory (reg_info, src_addr, src_len, reg_value); + Error error; + error.SetErrorString("invalid register context"); + return error; +} + +Error +RegisterContextThreadMemory::WriteRegisterValueToMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr, uint32_t dst_len, const RegisterValue ®_value) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->WriteRegisterValueToMemory (reg_info, dst_addr, dst_len, reg_value); + Error error; + error.SetErrorString("invalid register context"); + return error; +} diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h b/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h new file mode 100644 index 00000000000..8d7a4b622fe --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h @@ -0,0 +1,114 @@ +//===-- RegisterContextThreadMemory.h ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_RegisterContextThreadMemory_h_ +#define lldb_RegisterContextThreadMemory_h_ + +#include <vector> + +#include "lldb/lldb-private.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Symbol/SymbolContext.h" + +namespace lldb_private { + +class RegisterContextThreadMemory : public lldb_private::RegisterContext +{ +public: + RegisterContextThreadMemory (Thread &thread, + lldb::addr_t register_data_addr); + + virtual ~RegisterContextThreadMemory(); + //------------------------------------------------------------------ + // Subclasses must override these functions + //------------------------------------------------------------------ + virtual void + InvalidateAllRegisters (); + + virtual size_t + GetRegisterCount (); + + virtual const RegisterInfo * + GetRegisterInfoAtIndex (size_t reg); + + virtual size_t + GetRegisterSetCount (); + + virtual const RegisterSet * + GetRegisterSet (size_t reg_set); + + virtual bool + ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value); + + virtual bool + WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value); + + // These two functions are used to implement "push" and "pop" of register states. They are used primarily + // for expression evaluation, where we need to push a new state (storing the old one in data_sp) and then + // restoring the original state by passing the data_sp we got from ReadAllRegisters to WriteAllRegisterValues. + // ReadAllRegisters will do what is necessary to return a coherent set of register values for this thread, which + // may mean e.g. interrupting a thread that is sitting in a kernel trap. That is a somewhat disruptive operation, + // so these API's should only be used when this behavior is needed. + + virtual bool + ReadAllRegisterValues (lldb::DataBufferSP &data_sp); + + virtual bool + WriteAllRegisterValues (const lldb::DataBufferSP &data_sp); + + bool + CopyFromRegisterContext (lldb::RegisterContextSP context); + + virtual uint32_t + ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num); + + //------------------------------------------------------------------ + // Subclasses can override these functions if desired + //------------------------------------------------------------------ + virtual uint32_t + NumSupportedHardwareBreakpoints (); + + virtual uint32_t + SetHardwareBreakpoint (lldb::addr_t addr, size_t size); + + virtual bool + ClearHardwareBreakpoint (uint32_t hw_idx); + + virtual uint32_t + NumSupportedHardwareWatchpoints (); + + virtual uint32_t + SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write); + + virtual bool + ClearHardwareWatchpoint (uint32_t hw_index); + + virtual bool + HardwareSingleStep (bool enable); + + virtual Error + ReadRegisterValueFromMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr, uint32_t src_len, RegisterValue ®_value); + + virtual Error + WriteRegisterValueToMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr, uint32_t dst_len, const RegisterValue ®_value); + +protected: + void + UpdateRegisterContext (); + + lldb::ThreadWP m_thread_wp; + lldb::RegisterContextSP m_reg_ctx_sp; + lldb::addr_t m_register_data_addr; + uint32_t m_stop_id; +private: + DISALLOW_COPY_AND_ASSIGN (RegisterContextThreadMemory); +}; +} // namespace lldb_private + +#endif // lldb_RegisterContextThreadMemory_h_ diff --git a/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp b/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp index 62c6aeb9c75..3d08026cf98 100644 --- a/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp +++ b/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp @@ -13,6 +13,7 @@ #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; @@ -53,42 +54,32 @@ ThreadMemory::~ThreadMemory() DestroyThread(); } -bool +void ThreadMemory::WillResume (StateType resume_state) { - ClearStackFrames(); - Thread::WillResume(resume_state); + if (m_backing_thread_sp) + m_backing_thread_sp->WillResume(resume_state); +} +void +ThreadMemory::ClearStackFrames () +{ if (m_backing_thread_sp) - return m_backing_thread_sp->WillResume(resume_state); - return true; + m_backing_thread_sp->ClearStackFrames(); + Thread::ClearStackFrames(); } RegisterContextSP ThreadMemory::GetRegisterContext () { - if (m_backing_thread_sp) - return m_backing_thread_sp->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_register_data_addr); - } - } + m_reg_context_sp.reset (new RegisterContextThreadMemory (*this, m_register_data_addr)); return m_reg_context_sp; } 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; @@ -108,11 +99,179 @@ 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 () { + if (m_actual_stop_info_sp) + return m_actual_stop_info_sp; + if (m_backing_thread_sp) - return m_backing_thread_sp->GetPrivateStopReason(); + { + lldb::StopInfoSP backing_stop_info_sp (m_backing_thread_sp->GetPrivateStopReason()); + 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; + } + } ProcessSP process_sp (GetProcess()); @@ -150,15 +309,4 @@ 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... - RegisterContextSP reg_ctx_sp(m_reg_context_sp); - if (reg_ctx_sp) - { - const bool force = true; - reg_ctx_sp->InvalidateIfNeeded (force); - } } diff --git a/lldb/source/Plugins/Process/Utility/ThreadMemory.h b/lldb/source/Plugins/Process/Utility/ThreadMemory.h index 51a2486f709..2a1f7d6b67d 100644 --- a/lldb/source/Plugins/Process/Utility/ThreadMemory.h +++ b/lldb/source/Plugins/Process/Utility/ThreadMemory.h @@ -70,7 +70,7 @@ public: return NULL; } - virtual bool + virtual void WillResume (lldb::StateType resume_state); virtual void @@ -79,6 +79,14 @@ public: 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(); @@ -90,6 +98,9 @@ public: } virtual void + ClearStackFrames (); + + virtual void ClearBackingThread () { m_backing_thread_sp.reset(); @@ -98,6 +109,7 @@ public: 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; } @@ -109,6 +121,14 @@ public: } protected: + + virtual bool + IsOperatingSystemPluginThread () const + { + return true; + } + + //------------------------------------------------------------------ // For ThreadMemory and subclasses //------------------------------------------------------------------ diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index bf3dc4d8636..b17a6af4cc9 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -155,7 +155,7 @@ GDBRemoteRegisterContext::GetPrimordialRegister(const lldb_private::RegisterInfo 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.4" PRIx64 ";", 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)); @@ -187,7 +187,7 @@ GDBRemoteRegisterContext::ReadRegisterBytes (const RegisterInfo *reg_info, DataE { 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::ReadRegisterBytes (const RegisterInfo *reg_info, DataE { // Get all registers in one packet if (thread_suffix_supported) - packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4" PRIx64 ";", 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)); @@ -314,7 +314,7 @@ GDBRemoteRegisterContext::SetPrimordialRegister(const lldb_private::RegisterInfo lldb::endian::InlHostByteOrder()); if (gdb_comm.GetThreadSuffixSupported()) - packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetID()); + packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID()); // Invalidate just this register SetRegisterIsValid(reg, false); @@ -340,7 +340,7 @@ GDBRemoteRegisterContext::SyncThreadState(Process *process) StreamString packet; StringExtractorGDBRemote response; - packet.Printf ("QSyncThreadState:%4.4" PRIx64 ";", m_thread.GetID()); + packet.Printf ("QSyncThreadState:%4.4" PRIx64 ";", m_thread.GetProtocolID()); if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(), packet.GetString().size(), response, @@ -386,7 +386,7 @@ GDBRemoteRegisterContext::WriteRegisterBytes (const lldb_private::RegisterInfo * { 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; @@ -401,7 +401,7 @@ GDBRemoteRegisterContext::WriteRegisterBytes (const lldb_private::RegisterInfo * lldb::endian::InlHostByteOrder()); if (thread_suffix_supported) - packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetID()); + packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID()); // Invalidate all register values InvalidateIfNeeded (true); @@ -508,11 +508,11 @@ GDBRemoteRegisterContext::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) 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.4" PRIx64, 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)); @@ -529,7 +529,7 @@ GDBRemoteRegisterContext::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) if (thread_suffix_supported) { char thread_id_cstr[64]; - ::snprintf (thread_id_cstr, sizeof(thread_id_cstr), ";thread:%4.4" PRIx64 ";", 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())); @@ -579,7 +579,7 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data { 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 @@ -652,7 +652,7 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data lldb::endian::InlHostByteOrder()); if (thread_suffix_supported) - packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetID()); + packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID()); SetRegisterIsValid(reg, false); if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(), diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 35e455d5f24..1b4627adc55 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -1322,7 +1322,13 @@ ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new for (size_t i=0; i<num_thread_ids; ++i) { tid_t tid = m_thread_ids[i]; - ThreadSP thread_sp (old_thread_list_copy.RemoveThreadByID (tid, false)); + ThreadSP thread_sp (old_thread_list_copy.RemoveThreadByProtocolID(tid, false)); + if (thread_sp) + { + ThreadSP backing_thread_sp (thread_sp->GetBackingThread()); + if (backing_thread_sp && backing_thread_sp->GetProtocolID() == tid) + thread_sp = backing_thread_sp; + } if (!thread_sp) thread_sp.reset (new ThreadGDBRemote (*this, tid)); new_thread_list.AddThread(thread_sp); @@ -1337,7 +1343,7 @@ ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex (i, false)); if (old_thread_sp) { - lldb::tid_t old_thread_id = old_thread_sp->GetID(); + lldb::tid_t old_thread_id = old_thread_sp->GetProtocolID(); m_thread_id_to_index_id_map.erase(old_thread_id); } } @@ -1379,6 +1385,8 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) std::vector<addr_t> exc_data; addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS; ThreadSP thread_sp; + ThreadSP backing_thread_sp; + ThreadGDBRemote *gdb_thread = NULL; while (stop_packet.GetNameColonValue(name, value)) { @@ -1400,34 +1408,21 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) // hold onto the mutex between the call to m_thread_list.FindThreadByID(...) // and the m_thread_list.AddThread(...) so it doesn't change on us Mutex::Locker locker (m_thread_list.GetMutex ()); - thread_sp = m_thread_list.FindThreadByID(tid, false); - if (!thread_sp) + thread_sp = m_thread_list.FindThreadByProtocolID(tid, false); + + if (thread_sp) { - // If there is an operating system plug-in it might hiding the actual API - // thread inside a ThreadMemory... - if (GetOperatingSystem()) - { - bool found_backing_thread = false; - const uint32_t num_threads = m_thread_list.GetSize(); - for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) - { - thread_sp = m_thread_list.GetThreadAtIndex(thread_idx)->GetBackingThread(); - if (thread_sp && thread_sp->GetID() == tid) - { - found_backing_thread = true; - break; - } - } - - if (!found_backing_thread) - thread_sp.reset(); - } + backing_thread_sp = thread_sp->GetBackingThread(); + if (backing_thread_sp) + gdb_thread = static_cast<ThreadGDBRemote *> (backing_thread_sp.get()); + else + gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get()); } - - if (!thread_sp) + else { // Create the thread if we need to thread_sp.reset (new ThreadGDBRemote (*this, tid)); + gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get()); m_thread_list.AddThread(thread_sp); } } @@ -1488,7 +1483,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) // We have a register number that contains an expedited // register value. Lets supply this register to our thread // so it won't have to go and read it. - if (thread_sp) + if (gdb_thread) { uint32_t reg = Args::StringToUInt32 (name.c_str(), UINT32_MAX, 16); @@ -1497,7 +1492,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) StringExtractor reg_value_extractor; // Swap "value" over into "reg_value_extractor" reg_value_extractor.GetStringRef().swap(value); - if (!static_cast<ThreadGDBRemote *> (thread_sp.get())->PrivateSetRegisterValue (reg, reg_value_extractor)) + if (!gdb_thread->PrivateSetRegisterValue (reg, reg_value_extractor)) { Host::SetCrashDescriptionWithFormat("Setting thread register '%s' (decoded to %u (0x%x)) with value '%s' for stop packet: '%s'", name.c_str(), @@ -1513,20 +1508,18 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) if (thread_sp) { - ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get()); - gdb_thread->SetThreadDispatchQAddr (thread_dispatch_qaddr); gdb_thread->SetName (thread_name.empty() ? NULL : thread_name.c_str()); if (exc_type != 0) { const size_t exc_data_size = exc_data.size(); - gdb_thread->SetStopInfo (StopInfoMachException::CreateStopReasonWithMachException (*thread_sp, - exc_type, - exc_data_size, - exc_data_size >= 1 ? exc_data[0] : 0, - exc_data_size >= 2 ? exc_data[1] : 0, - exc_data_size >= 3 ? exc_data[2] : 0)); + thread_sp->SetStopInfo (StopInfoMachException::CreateStopReasonWithMachException (*thread_sp, + exc_type, + exc_data_size, + exc_data_size >= 1 ? exc_data[0] : 0, + exc_data_size >= 2 ? exc_data[1] : 0, + exc_data_size >= 3 ? exc_data[2] : 0)); } else { @@ -1535,27 +1528,27 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) { if (reason.compare("trace") == 0) { - gdb_thread->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp)); + thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp)); handled = true; } else if (reason.compare("breakpoint") == 0) { - addr_t pc = gdb_thread->GetRegisterContext()->GetPC(); - lldb::BreakpointSiteSP bp_site_sp = gdb_thread->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); + addr_t pc = thread_sp->GetRegisterContext()->GetPC(); + lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); if (bp_site_sp) { // 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. handled = true; - if (bp_site_sp->ValidForThisThread (gdb_thread)) + if (bp_site_sp->ValidForThisThread (thread_sp.get())) { - gdb_thread->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID())); + thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID())); } else { StopInfoSP invalid_stop_info_sp; - gdb_thread->SetStopInfo (invalid_stop_info_sp); + thread_sp->SetStopInfo (invalid_stop_info_sp); } } @@ -1568,12 +1561,12 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) { break_id_t watch_id = LLDB_INVALID_WATCH_ID; // TODO: locate the watchpoint somehow... - gdb_thread->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id)); + thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id)); handled = true; } else if (reason.compare("exception") == 0) { - gdb_thread->SetStopInfo (StopInfo::CreateStopReasonWithException(*thread_sp, description.c_str())); + thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException(*thread_sp, description.c_str())); handled = true; } } @@ -1585,22 +1578,22 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) // Currently we are going to assume SIGTRAP means we are either // hitting a breakpoint or hardware single stepping. handled = true; - addr_t pc = gdb_thread->GetRegisterContext()->GetPC(); - lldb::BreakpointSiteSP bp_site_sp = gdb_thread->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); + addr_t pc = thread_sp->GetRegisterContext()->GetPC(); + lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); if (bp_site_sp) { // 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. - if (bp_site_sp->ValidForThisThread (gdb_thread)) + if (bp_site_sp->ValidForThisThread (thread_sp.get())) { - gdb_thread->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID())); + thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID())); } else { StopInfoSP invalid_stop_info_sp; - gdb_thread->SetStopInfo (invalid_stop_info_sp); + thread_sp->SetStopInfo (invalid_stop_info_sp); } } else @@ -1608,31 +1601,31 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) // If we were stepping then assume the stop was the result of the trace. If we were // not stepping then report the SIGTRAP. // FIXME: We are still missing the case where we single step over a trap instruction. - if (gdb_thread->GetTemporaryResumeState() == eStateStepping) - gdb_thread->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp)); + if (thread_sp->GetTemporaryResumeState() == eStateStepping) + thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp)); else - gdb_thread->SetStopInfo (StopInfo::CreateStopReasonWithSignal(*thread_sp, signo)); + thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal(*thread_sp, signo)); } } if (!handled) - gdb_thread->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo)); + thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo)); } else { StopInfoSP invalid_stop_info_sp; - gdb_thread->SetStopInfo (invalid_stop_info_sp); + thread_sp->SetStopInfo (invalid_stop_info_sp); } if (!description.empty()) { - lldb::StopInfoSP stop_info_sp (gdb_thread->GetStopInfo ()); + lldb::StopInfoSP stop_info_sp (thread_sp->GetStopInfo ()); if (stop_info_sp) { stop_info_sp->SetDescription (description.c_str()); } else { - gdb_thread->SetStopInfo (StopInfo::CreateStopReasonWithException (*thread_sp, description.c_str())); + thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException (*thread_sp, description.c_str())); } } } @@ -1797,8 +1790,8 @@ ProcessGDBRemote::DoDestroy () || reason == eStopReasonException) { if (log) - log->Printf ("ProcessGDBRemote::DoDestroy() - thread: %" PRId64 " stopped with reason: %s.", - thread_sp->GetID(), + log->Printf ("ProcessGDBRemote::DoDestroy() - thread: 0x%4.4" PRIx64 " stopped with reason: %s.", + thread_sp->GetProtocolID(), stop_info_sp->GetDescription()); stop_looks_like_crash = true; break; @@ -1832,8 +1825,8 @@ ProcessGDBRemote::DoDestroy () && reason != eStopReasonException) { if (log) - log->Printf ("ProcessGDBRemote::DoDestroy() - Suspending thread: %" PRId64 " before running.", - thread_sp->GetID()); + log->Printf ("ProcessGDBRemote::DoDestroy() - Suspending thread: 0x%4.4" PRIx64 " before running.", + thread_sp->GetProtocolID()); thread_sp->SetResumeState(eStateSuspended); } } diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp index f1084d68bd4..321fe8d819a 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -80,24 +80,14 @@ ThreadGDBRemote::GetQueueName () return NULL; } -bool +void ThreadGDBRemote::WillResume (StateType resume_state) { - // 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. - // If the thread's WillResume returns false, that means that we aren't going to actually resume, - // in which case we should not do the rest of our "resume" work. - - if (!Thread::WillResume(resume_state)) - return false; - - ClearStackFrames(); - int signo = GetResumeSignal(); + const lldb::user_id_t tid = GetProtocolID(); Log *log(lldb_private::GetLogIfAnyCategoriesSet (GDBR_LOG_THREAD)); if (log) - log->Printf ("Resuming thread: %4.4" PRIx64 " with state: %s.", GetID(), StateAsCString(resume_state)); + log->Printf ("Resuming thread: %4.4" PRIx64 " with state: %s.", tid, StateAsCString(resume_state)); ProcessSP process_sp (GetProcess()); if (process_sp) @@ -112,24 +102,22 @@ ThreadGDBRemote::WillResume (StateType resume_state) case eStateRunning: if (gdb_process->GetUnixSignals().SignalIsValid (signo)) - gdb_process->m_continue_C_tids.push_back(std::make_pair(GetID(), signo)); + gdb_process->m_continue_C_tids.push_back(std::make_pair(tid, signo)); else - gdb_process->m_continue_c_tids.push_back(GetID()); + gdb_process->m_continue_c_tids.push_back(tid); break; case eStateStepping: if (gdb_process->GetUnixSignals().SignalIsValid (signo)) - gdb_process->m_continue_S_tids.push_back(std::make_pair(GetID(), signo)); + gdb_process->m_continue_S_tids.push_back(std::make_pair(tid, signo)); else - gdb_process->m_continue_s_tids.push_back(GetID()); + gdb_process->m_continue_s_tids.push_back(tid); break; default: break; } - return true; } - return false; } void @@ -147,16 +135,6 @@ ThreadGDBRemote::RefreshStateAfterStop() GetRegisterContext()->InvalidateIfNeeded (force); } -void -ThreadGDBRemote::ClearStackFrames () -{ - Unwind *unwinder = GetUnwinder (); - if (unwinder) - unwinder->Clear(); - Thread::ClearStackFrames(); -} - - bool ThreadGDBRemote::ThreadIDIsValid (lldb::tid_t thread) { @@ -245,7 +223,7 @@ ThreadGDBRemote::GetPrivateStopReason () StringExtractorGDBRemote stop_packet; ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get()); - if (gdb_process->GetGDBRemote().GetThreadStopInfo(GetID(), stop_packet)) + if (gdb_process->GetGDBRemote().GetThreadStopInfo(GetProtocolID(), stop_packet)) gdb_process->SetThreadStopInfo (stop_packet); } } diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h index 375b7a5f553..8dfc4bb78cb 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h @@ -26,7 +26,7 @@ public: virtual ~ThreadGDBRemote (); - virtual bool + virtual void WillResume (lldb::StateType resume_state); virtual void @@ -44,9 +44,6 @@ public: virtual lldb::RegisterContextSP CreateRegisterContextForFrame (lldb_private::StackFrame *frame); - virtual void - ClearStackFrames (); - void Dump (lldb_private::Log *log, uint32_t index); diff --git a/lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp index 81d3426eab5..a4e366101fa 100644 --- a/lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp +++ b/lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp @@ -73,16 +73,6 @@ ThreadMachCore::RefreshStateAfterStop() GetRegisterContext()->InvalidateIfNeeded (force); } -void -ThreadMachCore::ClearStackFrames () -{ - Unwind *unwinder = GetUnwinder (); - if (unwinder) - unwinder->Clear(); - Thread::ClearStackFrames(); -} - - bool ThreadMachCore::ThreadIDIsValid (lldb::tid_t thread) { diff --git a/lldb/source/Plugins/Process/mach-core/ThreadMachCore.h b/lldb/source/Plugins/Process/mach-core/ThreadMachCore.h index a2d3b7ad72c..cc687573c6a 100644 --- a/lldb/source/Plugins/Process/mach-core/ThreadMachCore.h +++ b/lldb/source/Plugins/Process/mach-core/ThreadMachCore.h @@ -37,9 +37,6 @@ public: virtual lldb::RegisterContextSP CreateRegisterContextForFrame (lldb_private::StackFrame *frame); - virtual void - ClearStackFrames (); - static bool ThreadIDIsValid (lldb::tid_t thread); diff --git a/lldb/source/Target/OperatingSystem.cpp b/lldb/source/Target/OperatingSystem.cpp index 33ae584f336..3fecb4a6d2c 100644 --- a/lldb/source/Target/OperatingSystem.cpp +++ b/lldb/source/Target/OperatingSystem.cpp @@ -13,7 +13,7 @@ // C++ Includes // Other libraries and framework includes #include "lldb/Core/PluginManager.h" - +#include "lldb/Target/Thread.h" using namespace lldb; using namespace lldb_private; @@ -54,3 +54,13 @@ OperatingSystem::OperatingSystem (Process *process) : OperatingSystem::~OperatingSystem() { } + + +bool +OperatingSystem::IsOperatingSystemPluginThread (const lldb::ThreadSP &thread_sp) +{ + if (thread_sp) + return thread_sp->IsOperatingSystemPluginThread(); + return false; +} + diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index 72c9a2a5b64..a7e03a2a60d 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -13,6 +13,7 @@ #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Log.h" +#include "lldb/Core/State.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/RegularExpression.h" @@ -244,6 +245,7 @@ Thread::Thread (Process &process, lldb::tid_t tid) : m_process_wp (process.shared_from_this()), m_actual_stop_info_sp (), m_index_id (process.GetNextThreadIndexID(tid)), + m_protocol_tid (tid), m_reg_context_sp (), m_state (eStateUnloaded), m_state_mutex (Mutex::eMutexTypeRecursive), @@ -517,7 +519,7 @@ Thread::SetupForResume () } bool -Thread::WillResume (StateType resume_state) +Thread::ShouldResume (StateType resume_state) { // At this point clear the completed plan stack. m_completed_plan_stack.clear(); @@ -525,6 +527,9 @@ Thread::WillResume (StateType resume_state) m_temporary_resume_state = resume_state; + // Make sure m_actual_stop_info_sp is valid + GetPrivateStopReason(); + // 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 @@ -562,6 +567,13 @@ Thread::WillResume (StateType resume_state) } } + if (need_to_resume) + { + ClearStackFrames(); + // Let Thread subclasses do any special work they need to prior to resuming + WillResume (resume_state); + } + return need_to_resume; } @@ -583,36 +595,40 @@ Thread::ShouldStop (Event* event_ptr) if (GetResumeState () == eStateSuspended) { if (log) - log->Printf ("Thread::%s for tid = 0x%4.4" PRIx64 ", should_stop = 0 (ignore since thread was suspended)", + log->Printf ("Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 ", should_stop = 0 (ignore since thread was suspended)", __FUNCTION__, - GetID ()); + GetID (), + GetProtocolID()); return false; } if (GetTemporaryResumeState () == eStateSuspended) { if (log) - log->Printf ("Thread::%s for tid = 0x%4.4" PRIx64 ", should_stop = 0 (ignore since thread was suspended)", + log->Printf ("Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 ", should_stop = 0 (ignore since thread was suspended)", __FUNCTION__, - GetID ()); + GetID (), + GetProtocolID()); return false; } if (ThreadStoppedForAReason() == false) { if (log) - log->Printf ("Thread::%s for tid = 0x%4.4" PRIx64 ", pc = 0x%16.16" PRIx64 ", should_stop = 0 (ignore since no stop reason)", + log->Printf ("Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 ", pc = 0x%16.16" PRIx64 ", should_stop = 0 (ignore since no stop reason)", __FUNCTION__, - GetID (), + GetID (), + GetProtocolID(), GetRegisterContext() ? GetRegisterContext()->GetPC() : LLDB_INVALID_ADDRESS); return false; } if (log) { - log->Printf ("Thread::%s for tid = 0x%4.4" PRIx64 ", pc = 0x%16.16" PRIx64, + log->Printf ("Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 ", pc = 0x%16.16" PRIx64, __FUNCTION__, - GetID (), + GetID (), + GetProtocolID (), GetRegisterContext() ? GetRegisterContext()->GetPC() : LLDB_INVALID_ADDRESS); log->Printf ("^^^^^^^^ Thread::ShouldStop Begin ^^^^^^^^"); StreamString s; @@ -807,21 +823,21 @@ Thread::ShouldReportStop (Event* event_ptr) if (thread_state == eStateSuspended || thread_state == eStateInvalid) { if (log) - log->Printf ("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 ": returning vote %i (state was suspended or invalid)\n", GetID(), eVoteNoOpinion); + log->Printf ("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 ": returning vote %i (state was suspended or invalid)", GetID(), eVoteNoOpinion); return eVoteNoOpinion; } if (temp_thread_state == eStateSuspended || temp_thread_state == eStateInvalid) { if (log) - log->Printf ("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 ": returning vote %i (temporary state was suspended or invalid)\n", GetID(), eVoteNoOpinion); + log->Printf ("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 ": returning vote %i (temporary state was suspended or invalid)", GetID(), eVoteNoOpinion); return eVoteNoOpinion; } if (!ThreadStoppedForAReason()) { if (log) - log->Printf ("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 ": returning vote %i (thread didn't stop for a reason.)\n", GetID(), eVoteNoOpinion); + log->Printf ("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 ": returning vote %i (thread didn't stop for a reason.)", GetID(), eVoteNoOpinion); return eVoteNoOpinion; } @@ -829,7 +845,7 @@ Thread::ShouldReportStop (Event* event_ptr) { // Don't use GetCompletedPlan here, since that suppresses private plans. if (log) - log->Printf ("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 ": returning vote for complete stack's back plan\n", GetID()); + log->Printf ("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 ": returning vote for complete stack's back plan", GetID()); return m_completed_plan_stack.back()->ShouldReportStop (event_ptr); } else @@ -849,7 +865,7 @@ Thread::ShouldReportStop (Event* event_ptr) plan_ptr = GetPreviousPlan(plan_ptr); } if (log) - log->Printf ("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 ": returning vote %i for current plan\n", GetID(), thread_vote); + log->Printf ("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 ": returning vote %i for current plan", GetID(), thread_vote); return thread_vote; } @@ -871,9 +887,10 @@ Thread::ShouldReportRun (Event* event_ptr) { // Don't use GetCompletedPlan here, since that suppresses private plans. if (log) - log->Printf ("Current Plan for thread %d (0x%4.4" PRIx64 "): %s being asked whether we should report run.", + log->Printf ("Current Plan for thread %d (0x%4.4" PRIx64 ", %s): %s being asked whether we should report run.", GetIndexID(), GetID(), + StateAsCString(GetTemporaryResumeState()), m_completed_plan_stack.back()->GetName()); return m_completed_plan_stack.back()->ShouldReportRun (event_ptr); @@ -881,9 +898,10 @@ Thread::ShouldReportRun (Event* event_ptr) else { if (log) - log->Printf ("Current Plan for thread %d (0x%4.4" PRIx64 "): %s being asked whether we should report run.", + log->Printf ("Current Plan for thread %d (0x%4.4" PRIx64 ", %s): %s being asked whether we should report run.", GetIndexID(), GetID(), + StateAsCString(GetTemporaryResumeState()), GetCurrentPlan()->GetName()); return GetCurrentPlan()->ShouldReportRun (event_ptr); @@ -1502,6 +1520,10 @@ Thread::ClearStackFrames () { Mutex::Locker locker(m_frame_mutex); + Unwind *unwinder = GetUnwinder (); + if (unwinder) + unwinder->Clear(); + // Only store away the old "reference" StackFrameList if we got all its frames: // FIXME: At some point we can try to splice in the frames we have fetched into // the new frame as we make it, but let's not try that now. diff --git a/lldb/source/Target/ThreadList.cpp b/lldb/source/Target/ThreadList.cpp index 620a7ccbd4a..d59d8059b36 100644 --- a/lldb/source/Target/ThreadList.cpp +++ b/lldb/source/Target/ThreadList.cpp @@ -132,6 +132,29 @@ ThreadList::FindThreadByID (lldb::tid_t tid, bool can_update) } ThreadSP +ThreadList::FindThreadByProtocolID (lldb::tid_t tid, bool can_update) +{ + Mutex::Locker locker(m_threads_mutex); + + if (can_update) + m_process->UpdateThreadListIfNeeded(); + + ThreadSP thread_sp; + uint32_t idx = 0; + const uint32_t num_threads = m_threads.size(); + for (idx = 0; idx < num_threads; ++idx) + { + if (m_threads[idx]->GetProtocolID() == tid) + { + thread_sp = m_threads[idx]; + break; + } + } + return thread_sp; +} + + +ThreadSP ThreadList::RemoveThreadByID (lldb::tid_t tid, bool can_update) { Mutex::Locker locker(m_threads_mutex); @@ -155,6 +178,29 @@ ThreadList::RemoveThreadByID (lldb::tid_t tid, bool can_update) } ThreadSP +ThreadList::RemoveThreadByProtocolID (lldb::tid_t tid, bool can_update) +{ + Mutex::Locker locker(m_threads_mutex); + + if (can_update) + m_process->UpdateThreadListIfNeeded(); + + ThreadSP thread_sp; + uint32_t idx = 0; + const uint32_t num_threads = m_threads.size(); + for (idx = 0; idx < num_threads; ++idx) + { + if (m_threads[idx]->GetProtocolID() == tid) + { + thread_sp = m_threads[idx]; + m_threads.erase(m_threads.begin()+idx); + break; + } + } + return thread_sp; +} + +ThreadSP ThreadList::GetThreadSPForThreadPtr (Thread *thread_ptr) { ThreadSP thread_sp; @@ -522,9 +568,9 @@ ThreadList::WillResume () { ThreadSP thread_sp(*pos); if (thread_sp.get() == immediate_thread_sp.get()) - thread_sp->WillResume(thread_sp->GetCurrentPlan()->RunState()); + thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState()); else - thread_sp->WillResume (eStateSuspended); + thread_sp->ShouldResume (eStateSuspended); } } else if (run_me_only_list.GetSize (false) == 0) @@ -538,7 +584,7 @@ ThreadList::WillResume () run_state = thread_sp->GetCurrentPlan()->RunState(); else run_state = eStateSuspended; - if (!thread_sp->WillResume(run_state)) + if (!thread_sp->ShouldResume(run_state)) need_to_resume = false; } } @@ -566,11 +612,11 @@ ThreadList::WillResume () ThreadSP thread_sp(*pos); if (thread_sp == thread_to_run) { - if (!thread_sp->WillResume(thread_sp->GetCurrentPlan()->RunState())) + if (!thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState())) need_to_resume = false; } else - thread_sp->WillResume (eStateSuspended); + thread_sp->ShouldResume (eStateSuspended); } } |

