summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/Utility
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process/Utility')
-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
4 files changed, 571 insertions, 33 deletions
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
//------------------------------------------------------------------
OpenPOWER on IntegriCloud