<rdar://problem/13700260>

<rdar://problem/13723772>

Modified the lldb_private::Thread to work much better with the OperatingSystem plug-ins. Operating system plug-ins can now return have a "core" key/value pair in each thread dictionary for the OperatingSystemPython plug-ins which allows the core threads to be contained with memory threads. It also allows these memory threads to be stepped, resumed, and controlled just as if they were the actual backing threads themselves.

A few things are introduced:
- lldb_private::Thread now has a GetProtocolID() method which returns the thread protocol ID for a given thread. The protocol ID (Thread::GetProtocolID()) is usually the same as the thread id (Thread::GetID()), but it can differ when a memory thread has its own id, but is backed by an actual API thread.
- Cleaned up the Thread::WillResume() code to do the mandatory parts in Thread::ShouldResume(), and let the thread subclasses override the Thread::WillResume() which is now just a notification.
- Cleaned up ClearStackFrames() implementations so that fewer thread subclasses needed to override them
- Changed the POSIXThread class a bit since it overrode Thread::WillResume(). It is doing the wrong thing by calling "Thread::SetResumeState()" on its own, this shouldn't be done by thread subclasses, but the current code might rely on it so I left it in with a TODO comment with an explanation.

llvm-svn: 180886
This commit is contained in:
Greg Clayton 2013-05-01 21:54:04 +00:00
parent 5ed5181178
commit 160c9d81e0
25 changed files with 875 additions and 242 deletions

View File

@ -81,6 +81,10 @@ public:
{
return lldb::ThreadSP();
}
virtual bool
IsOperatingSystemPluginThread (const lldb::ThreadSP &thread_sp);
protected:
//------------------------------------------------------------------
// Member variables.

View File

@ -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;

View File

@ -40,6 +40,12 @@ public:
bool
IsValid () const;
void
SetThread (const lldb::ThreadSP &thread_sp)
{
m_thread_wp = thread_sp;
}
lldb::ThreadSP
GetThread() const
{

View File

@ -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

View File

@ -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);

View File

@ -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 */,

View File

@ -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());

View File

@ -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)

View File

@ -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)
{

View File

@ -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);

View File

@ -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

View File

@ -36,7 +36,7 @@ public:
void
RefreshStateAfterStop();
bool
virtual void
WillResume(lldb::StateType resume_state);
const char *

View File

@ -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;
}

View File

@ -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_

View File

@ -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)
return m_backing_thread_sp->WillResume(resume_state);
return true;
m_backing_thread_sp->WillResume(resume_state);
}
void
ThreadMemory::ClearStackFrames ()
{
if (m_backing_thread_sp)
m_backing_thread_sp->ClearStackFrames();
Thread::ClearStackFrames();
}
RegisterContextSP
ThreadMemory::GetRegisterContext ()
{
if (m_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);
}
}

View File

@ -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();
@ -89,6 +97,9 @@ public:
return m_thread_info_valobj_sp;
}
virtual void
ClearStackFrames ();
virtual void
ClearBackingThread ()
{
@ -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
//------------------------------------------------------------------

View File

@ -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(),

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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)
{

View File

@ -37,9 +37,6 @@ public:
virtual lldb::RegisterContextSP
CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
virtual void
ClearStackFrames ();
static bool
ThreadIDIsValid (lldb::tid_t thread);

View File

@ -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;
}

View File

@ -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.

View File

@ -131,6 +131,29 @@ ThreadList::FindThreadByID (lldb::tid_t tid, bool can_update)
return thread_sp;
}
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)
{
@ -154,6 +177,29 @@ ThreadList::RemoveThreadByID (lldb::tid_t tid, bool can_update)
return thread_sp;
}
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)
{
@ -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);
}
}