summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Target/OperatingSystem.h4
-rw-r--r--lldb/include/lldb/Target/RegisterContext.h4
-rw-r--r--lldb/include/lldb/Target/StopInfo.h6
-rw-r--r--lldb/include/lldb/Target/Thread.h71
-rw-r--r--lldb/include/lldb/Target/ThreadList.h6
-rw-r--r--lldb/lldb.xcodeproj/project.pbxproj8
-rw-r--r--lldb/source/Core/Debugger.cpp5
-rw-r--r--lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp46
-rw-r--r--lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp27
-rw-r--r--lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h6
-rw-r--r--lldb/source/Plugins/Process/POSIX/POSIXThread.cpp13
-rw-r--r--lldb/source/Plugins/Process/POSIX/POSIXThread.h2
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp256
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h114
-rw-r--r--lldb/source/Plugins/Process/Utility/ThreadMemory.cpp212
-rw-r--r--lldb/source/Plugins/Process/Utility/ThreadMemory.h22
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp24
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp111
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp38
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h5
-rw-r--r--lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp10
-rw-r--r--lldb/source/Plugins/Process/mach-core/ThreadMachCore.h3
-rw-r--r--lldb/source/Target/OperatingSystem.cpp12
-rw-r--r--lldb/source/Target/Thread.cpp54
-rw-r--r--lldb/source/Target/ThreadList.cpp56
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 &reg_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 &reg_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 &reg_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 &reg_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 &reg_value);
+
+ virtual bool
+ WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_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 &reg_value);
+
+ virtual Error
+ WriteRegisterValueToMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr, uint32_t dst_len, const RegisterValue &reg_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);
}
}
OpenPOWER on IntegriCloud