diff options
Diffstat (limited to 'lldb/source/Plugins/Process/Utility')
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 ®_value) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->ReadRegister(reg_info, reg_value); + return false; +} + +bool +RegisterContextThreadMemory::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->WriteRegister (reg_info, reg_value); + return false; +} + +bool +RegisterContextThreadMemory::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->ReadAllRegisterValues(data_sp); + return false; +} + +bool +RegisterContextThreadMemory::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->WriteAllRegisterValues (data_sp); + return false; +} + +bool +RegisterContextThreadMemory::CopyFromRegisterContext (lldb::RegisterContextSP reg_ctx_sp) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->CopyFromRegisterContext(reg_ctx_sp); + return false; +} + +uint32_t +RegisterContextThreadMemory::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->ConvertRegisterKindToRegisterNumber(kind, num); + return false; +} + +uint32_t +RegisterContextThreadMemory::NumSupportedHardwareBreakpoints () +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->NumSupportedHardwareBreakpoints(); + return false; +} + +uint32_t +RegisterContextThreadMemory::SetHardwareBreakpoint (lldb::addr_t addr, size_t size) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->SetHardwareBreakpoint(addr, size); + return 0; +} + +bool +RegisterContextThreadMemory::ClearHardwareBreakpoint (uint32_t hw_idx) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->ClearHardwareBreakpoint (hw_idx); + return false; +} + +uint32_t +RegisterContextThreadMemory::NumSupportedHardwareWatchpoints () +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->NumSupportedHardwareWatchpoints(); + return 0; +} + +uint32_t +RegisterContextThreadMemory::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->SetHardwareWatchpoint(addr, size, read, write); + return 0; +} + +bool +RegisterContextThreadMemory::ClearHardwareWatchpoint (uint32_t hw_index) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->ClearHardwareWatchpoint(hw_index); + return false; +} + +bool +RegisterContextThreadMemory::HardwareSingleStep (bool enable) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->HardwareSingleStep(enable); + return false; +} + +Error +RegisterContextThreadMemory::ReadRegisterValueFromMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr, uint32_t src_len, RegisterValue ®_value) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->ReadRegisterValueFromMemory (reg_info, src_addr, src_len, reg_value); + Error error; + error.SetErrorString("invalid register context"); + return error; +} + +Error +RegisterContextThreadMemory::WriteRegisterValueToMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr, uint32_t dst_len, const RegisterValue ®_value) +{ + UpdateRegisterContext (); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->WriteRegisterValueToMemory (reg_info, dst_addr, dst_len, reg_value); + Error error; + error.SetErrorString("invalid register context"); + return error; +} diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h b/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h new file mode 100644 index 00000000000..8d7a4b622fe --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h @@ -0,0 +1,114 @@ +//===-- RegisterContextThreadMemory.h ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_RegisterContextThreadMemory_h_ +#define lldb_RegisterContextThreadMemory_h_ + +#include <vector> + +#include "lldb/lldb-private.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Symbol/SymbolContext.h" + +namespace lldb_private { + +class RegisterContextThreadMemory : public lldb_private::RegisterContext +{ +public: + RegisterContextThreadMemory (Thread &thread, + lldb::addr_t register_data_addr); + + virtual ~RegisterContextThreadMemory(); + //------------------------------------------------------------------ + // Subclasses must override these functions + //------------------------------------------------------------------ + virtual void + InvalidateAllRegisters (); + + virtual size_t + GetRegisterCount (); + + virtual const RegisterInfo * + GetRegisterInfoAtIndex (size_t reg); + + virtual size_t + GetRegisterSetCount (); + + virtual const RegisterSet * + GetRegisterSet (size_t reg_set); + + virtual bool + ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value); + + virtual bool + WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value); + + // These two functions are used to implement "push" and "pop" of register states. They are used primarily + // for expression evaluation, where we need to push a new state (storing the old one in data_sp) and then + // restoring the original state by passing the data_sp we got from ReadAllRegisters to WriteAllRegisterValues. + // ReadAllRegisters will do what is necessary to return a coherent set of register values for this thread, which + // may mean e.g. interrupting a thread that is sitting in a kernel trap. That is a somewhat disruptive operation, + // so these API's should only be used when this behavior is needed. + + virtual bool + ReadAllRegisterValues (lldb::DataBufferSP &data_sp); + + virtual bool + WriteAllRegisterValues (const lldb::DataBufferSP &data_sp); + + bool + CopyFromRegisterContext (lldb::RegisterContextSP context); + + virtual uint32_t + ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num); + + //------------------------------------------------------------------ + // Subclasses can override these functions if desired + //------------------------------------------------------------------ + virtual uint32_t + NumSupportedHardwareBreakpoints (); + + virtual uint32_t + SetHardwareBreakpoint (lldb::addr_t addr, size_t size); + + virtual bool + ClearHardwareBreakpoint (uint32_t hw_idx); + + virtual uint32_t + NumSupportedHardwareWatchpoints (); + + virtual uint32_t + SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write); + + virtual bool + ClearHardwareWatchpoint (uint32_t hw_index); + + virtual bool + HardwareSingleStep (bool enable); + + virtual Error + ReadRegisterValueFromMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr, uint32_t src_len, RegisterValue ®_value); + + virtual Error + WriteRegisterValueToMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr, uint32_t dst_len, const RegisterValue ®_value); + +protected: + void + UpdateRegisterContext (); + + lldb::ThreadWP m_thread_wp; + lldb::RegisterContextSP m_reg_ctx_sp; + lldb::addr_t m_register_data_addr; + uint32_t m_stop_id; +private: + DISALLOW_COPY_AND_ASSIGN (RegisterContextThreadMemory); +}; +} // namespace lldb_private + +#endif // lldb_RegisterContextThreadMemory_h_ diff --git a/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp b/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp index 62c6aeb9c75..3d08026cf98 100644 --- a/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp +++ b/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp @@ -13,6 +13,7 @@ #include "lldb/Target/Process.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/Unwind.h" +#include "Plugins/Process/Utility/RegisterContextThreadMemory.h" using namespace lldb; using namespace lldb_private; @@ -53,42 +54,32 @@ ThreadMemory::~ThreadMemory() DestroyThread(); } -bool +void ThreadMemory::WillResume (StateType resume_state) { - ClearStackFrames(); - Thread::WillResume(resume_state); + if (m_backing_thread_sp) + m_backing_thread_sp->WillResume(resume_state); +} +void +ThreadMemory::ClearStackFrames () +{ if (m_backing_thread_sp) - return m_backing_thread_sp->WillResume(resume_state); - return true; + m_backing_thread_sp->ClearStackFrames(); + Thread::ClearStackFrames(); } RegisterContextSP ThreadMemory::GetRegisterContext () { - if (m_backing_thread_sp) - return m_backing_thread_sp->GetRegisterContext(); - if (!m_reg_context_sp) - { - ProcessSP process_sp (GetProcess()); - if (process_sp) - { - OperatingSystem *os = process_sp->GetOperatingSystem (); - if (os) - m_reg_context_sp = os->CreateRegisterContextForThread (this, m_register_data_addr); - } - } + m_reg_context_sp.reset (new RegisterContextThreadMemory (*this, m_register_data_addr)); return m_reg_context_sp; } RegisterContextSP ThreadMemory::CreateRegisterContextForFrame (StackFrame *frame) { - if (m_backing_thread_sp) - return m_backing_thread_sp->CreateRegisterContextForFrame(frame); - RegisterContextSP reg_ctx_sp; uint32_t concrete_frame_idx = 0; @@ -108,11 +99,179 @@ ThreadMemory::CreateRegisterContextForFrame (StackFrame *frame) return reg_ctx_sp; } + +//class StopInfoThreadMemory : public StopInfo +//{ +//public: +// //------------------------------------------------------------------ +// // Constructors and Destructors +// //------------------------------------------------------------------ +// StopInfoThreadMemory (Thread &thread, +// uint64_t value, +// StopInfoSP &backing_stop_info_sp) : +// StopInfo (thread, value), +// m_backing_stop_info_sp (backing_stop_info_sp) +// { +// } +// +// virtual +// ~StopInfoThreadMemory() +// { +// } +// +// virtual bool +// IsValid () const +// { +// ThreadSP backing_thread_sp (m_thread.GetBackingThread()); +// if (backing_thread_sp) +// return backing_thread_sp->IsValid(); +// return StopInfo::IsValid(); +// } +// +// virtual Thread & +// GetThread() +// { +// return m_thread; +// } +// +// virtual const Thread & +// GetThread() const +// { +// return m_thread; +// } +// +// virtual uint64_t +// GetValue() const +// { +// if (m_backing_stop_info_sp) +// return m_backing_stop_info_sp->GetValue(); +// return StopInfo::GetValue(); +// } +// +// virtual lldb::StopReason +// GetStopReason () const +// { +// if (m_backing_stop_info_sp) +// return m_backing_stop_info_sp->GetStopReason(); +// return eStopReasonNone; +// } +// +// // ShouldStopSynchronous will get called before any thread plans are consulted, and if it says we should +// // resume the target, then we will just immediately resume. This should not run any code in or resume the +// // target. +// +// virtual bool +// ShouldStopSynchronous (Event *event_ptr) +// { +// if (m_backing_stop_info_sp) +// return m_backing_stop_info_sp->ShouldStopSynchronous(event_ptr); +// return StopInfo::ShouldStopSynchronous (event_ptr); +// } +// +// // If should stop returns false, check if we should notify of this event +// virtual bool +// ShouldNotify (Event *event_ptr) +// { +// if (m_backing_stop_info_sp) +// return m_backing_stop_info_sp->ShouldNotify(event_ptr); +// return StopInfo::ShouldNotify (event_ptr); +// } +// +// virtual void +// WillResume (lldb::StateType resume_state) +// { +// if (m_backing_stop_info_sp) +// return m_backing_stop_info_sp->WillResume(resume_state); +// return StopInfo::WillResume (resume_state); +// } +// +// virtual const char * +// GetDescription () +// { +// if (m_backing_stop_info_sp) +// return m_backing_stop_info_sp->GetDescription(); +// return StopInfo::GetDescription(); +// } +// +// virtual void +// SetDescription (const char *desc_cstr) +// { +// if (m_backing_stop_info_sp) +// m_backing_stop_info_sp->SetDescription(desc_cstr); +// StopInfo::SetDescription(desc_cstr); +// } +// +// // Sometimes the thread plan logic will know that it wants a given stop to stop or not, +// // regardless of what the ordinary logic for that StopInfo would dictate. The main example +// // of this is the ThreadPlanCallFunction, which for instance knows - based on how that particular +// // expression was executed - whether it wants all breakpoints to auto-continue or not. +// // Use OverrideShouldStop on the StopInfo to implement this. +// +// virtual void +// OverrideShouldStop (bool override_value) +// { +// if (m_backing_stop_info_sp) +// m_backing_stop_info_sp->OverrideShouldStop(override_value); +// StopInfo::OverrideShouldStop (override_value); +// } +// +// virtual bool +// GetOverrideShouldStop() +// { +// if (m_backing_stop_info_sp) +// return m_backing_stop_info_sp->GetOverrideShouldStop(); +// return StopInfo::GetOverrideShouldStop(); +// } +// +// virtual bool +// GetOverriddenShouldStopValue () +// { +// if (m_backing_stop_info_sp) +// return m_backing_stop_info_sp->GetOverriddenShouldStopValue(); +// return StopInfo::GetOverriddenShouldStopValue(); +// } +// +// virtual void +// PerformAction (Event *event_ptr) +// { +// if (m_backing_stop_info_sp) +// return m_backing_stop_info_sp->PerformAction(event_ptr); +// return StopInfo::PerformAction(event_ptr); +// } +// +// virtual bool +// ShouldStop (Event *event_ptr) +// { +// if (m_backing_stop_info_sp) +// return m_backing_stop_info_sp->ShouldStop(event_ptr); +// return StopInfo::ShouldStop(event_ptr); +// } +// +// +//protected: +// StopInfoSP m_backing_stop_info_sp; +// +//private: +// DISALLOW_COPY_AND_ASSIGN (StopInfoThreadMemory); +//}; + + lldb::StopInfoSP ThreadMemory::GetPrivateStopReason () { + if (m_actual_stop_info_sp) + return m_actual_stop_info_sp; + if (m_backing_thread_sp) - return m_backing_thread_sp->GetPrivateStopReason(); + { + lldb::StopInfoSP backing_stop_info_sp (m_backing_thread_sp->GetPrivateStopReason()); + if (backing_stop_info_sp) + { + m_actual_stop_info_sp = backing_stop_info_sp; + m_actual_stop_info_sp->SetThread (shared_from_this()); + return m_actual_stop_info_sp; + } + } ProcessSP process_sp (GetProcess()); @@ -150,15 +309,4 @@ ThreadMemory::RefreshStateAfterStop() { if (m_backing_thread_sp) return m_backing_thread_sp->RefreshStateAfterStop(); - - - // Don't fetch the registers by calling Thread::GetRegisterContext() below. - // We might not have fetched any registers yet and we don't want to fetch - // the registers just to call invalidate on them... - RegisterContextSP reg_ctx_sp(m_reg_context_sp); - if (reg_ctx_sp) - { - const bool force = true; - reg_ctx_sp->InvalidateIfNeeded (force); - } } diff --git a/lldb/source/Plugins/Process/Utility/ThreadMemory.h b/lldb/source/Plugins/Process/Utility/ThreadMemory.h index 51a2486f709..2a1f7d6b67d 100644 --- a/lldb/source/Plugins/Process/Utility/ThreadMemory.h +++ b/lldb/source/Plugins/Process/Utility/ThreadMemory.h @@ -70,7 +70,7 @@ public: return NULL; } - virtual bool + virtual void WillResume (lldb::StateType resume_state); virtual void @@ -79,6 +79,14 @@ public: if (m_backing_thread_sp) m_backing_thread_sp->DidResume(); } + + virtual lldb::user_id_t + GetProtocolID () const + { + if (m_backing_thread_sp) + return m_backing_thread_sp->GetProtocolID(); + return Thread::GetProtocolID(); + } virtual void RefreshStateAfterStop(); @@ -90,6 +98,9 @@ public: } virtual void + ClearStackFrames (); + + virtual void ClearBackingThread () { m_backing_thread_sp.reset(); @@ -98,6 +109,7 @@ public: virtual bool SetBackingThread (const lldb::ThreadSP &thread_sp) { + //printf ("Thread 0x%llx is being backed by thread 0x%llx\n", GetID(), thread_sp->GetID()); m_backing_thread_sp = thread_sp; return (bool)thread_sp; } @@ -109,6 +121,14 @@ public: } protected: + + virtual bool + IsOperatingSystemPluginThread () const + { + return true; + } + + //------------------------------------------------------------------ // For ThreadMemory and subclasses //------------------------------------------------------------------ |