| //===-- 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; |
| } |