From 068f8a7e2d7ece12cc00726bb2e6df180b217848 Mon Sep 17 00:00:00 2001 From: Tamas Berghammer Date: Tue, 26 May 2015 11:58:52 +0000 Subject: Move register reading form NativeProcessLinux to NativeRegisterContextLinux* This change reorganize the register read/write code inside lldb-server on Linux with moving the architecture independent code into a new class called NativeRegisterContextLinux and all of the architecture dependent code into the appropriate NativeRegisterContextLinux_* class. As part of it the compilation of the architecture specific register contexts are only compiled on the specific architecture because they can't be used in other cases. The purpose of this change is to remove a lot of duplicated code from the different register contexts and to remove the architecture dependent codes from the global NativeProcessLinux class. Differential revision: http://reviews.llvm.org/D9935 llvm-svn: 238196 --- .../Linux/NativeRegisterContextLinux_arm64.cpp | 661 ++++++++++++++------- 1 file changed, 436 insertions(+), 225 deletions(-) (limited to 'lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp') diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp index aef1ae995cb7..ea6d6c318ca9 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp @@ -7,19 +7,31 @@ // //===----------------------------------------------------------------------===// +#if defined (__arm64__) || defined (__aarch64__) + #include "NativeRegisterContextLinux_arm64.h" -#include "lldb/lldb-private-forward.h" +// C Includes +// C++ Includes + +// Other libraries and framework includes #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Error.h" -#include "lldb/Core/StreamString.h" +#include "lldb/Core/Log.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Host/common/NativeProcessProtocol.h" -#include "lldb/Host/common/NativeThreadProtocol.h" + #include "Plugins/Process/Linux/NativeProcessLinux.h" -#include "lldb/Core/Log.h" +#include "Plugins/Process/Linux/Procfs.h" +#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h" + +// System includes - They have to be included after framework includes because they define some +// macros which collide with variable names in other modules +#include +// NT_PRSTATUS and NT_FPREGSET definition +#include -#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof (m_fpr)) +#define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize()) using namespace lldb; using namespace lldb_private; @@ -125,13 +137,341 @@ g_reg_sets_arm64[k_num_register_sets] = { "Floating Point Registers", "fpu", k_num_fpr_registers_arm64, g_fpu_regnums_arm64 } }; -NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64 ( - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx, - RegisterInfoInterface *reg_info_interface_p) : - NativeRegisterContextRegisterInfo (native_thread, concrete_frame_idx, reg_info_interface_p) +namespace +{ + +class ReadRegOperation : public NativeProcessLinux::Operation +{ +public: + ReadRegOperation(lldb::tid_t tid, uint32_t offset, const char *reg_name, RegisterValue &value) : + m_tid(tid), + m_offset(static_cast(offset)), + m_reg_name(reg_name), + m_value(value) + { } + + void + Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + uintptr_t m_offset; + const char *m_reg_name; + RegisterValue &m_value; +}; + +class WriteRegOperation : public NativeProcessLinux::Operation +{ +public: + WriteRegOperation(lldb::tid_t tid, unsigned offset, const char *reg_name, const RegisterValue &value) : + m_tid(tid), + m_offset(offset), + m_reg_name(reg_name), + m_value(value) + { } + + void + Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + uintptr_t m_offset; + const char *m_reg_name; + const RegisterValue &m_value; +}; + +class ReadGPROperation : public NativeProcessLinux::Operation +{ +public: + ReadGPROperation(lldb::tid_t tid, void *buf, size_t buf_size) + : m_tid(tid), m_buf(buf), m_buf_size(buf_size) + { } + + void Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + void *m_buf; + size_t m_buf_size; +}; + +class WriteGPROperation : public NativeProcessLinux::Operation +{ +public: + WriteGPROperation(lldb::tid_t tid, void *buf, size_t buf_size) : + m_tid(tid), m_buf(buf), m_buf_size(buf_size) + { } + + void Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + void *m_buf; + size_t m_buf_size; +}; + +class ReadFPROperation : public NativeProcessLinux::Operation +{ +public: + ReadFPROperation(lldb::tid_t tid, void *buf, size_t buf_size) + : m_tid(tid), + m_buf(buf), + m_buf_size(buf_size) + { } + + void Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + void *m_buf; + size_t m_buf_size; +}; + +class WriteFPROperation : public NativeProcessLinux::Operation +{ +public: + WriteFPROperation(lldb::tid_t tid, void *buf, size_t buf_size) + : m_tid(tid), m_buf(buf), m_buf_size(buf_size) + { } + + void Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + void *m_buf; + size_t m_buf_size; +}; + +class ReadDBGROperation : public NativeProcessLinux::Operation +{ +public: + ReadDBGROperation(lldb::tid_t tid, unsigned int &count_wp, unsigned int &count_bp) + : m_tid(tid), + m_count_wp(count_wp), + m_count_bp(count_bp) + { } + + void Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + unsigned int &m_count_wp; + unsigned int &m_count_bp; +}; + +class WriteDBGROperation : public NativeProcessLinux::Operation +{ +public: + WriteDBGROperation(lldb::tid_t tid, lldb::addr_t *addr_buf, + uint32_t *cntrl_buf, int type, int count) + : m_tid(tid), + m_address(addr_buf), + m_control(cntrl_buf), + m_type(type), + m_count(count) + { } + + void Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + lldb::addr_t * m_address; + uint32_t * m_control; + int m_type; + int m_count; +}; + +} // end of anonymous namespace + +void +ReadRegOperation::Execute(NativeProcessLinux *monitor) +{ + if (m_offset > sizeof(struct user_pt_regs)) + { + uintptr_t offset = m_offset - sizeof(struct user_pt_regs); + if (offset > sizeof(struct user_fpsimd_state)) + { + m_error.SetErrorString("invalid offset value"); + return; + } + elf_fpregset_t regs; + int regset = NT_FPREGSET; + struct iovec ioVec; + + ioVec.iov_base = ®s; + ioVec.iov_len = sizeof regs; + NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); + if (m_error.Success()) + { + ArchSpec arch; + if (monitor->GetArchitecture(arch)) + m_value.SetBytes((void *)(((unsigned char *)(®s)) + offset), 16, arch.GetByteOrder()); + else + m_error.SetErrorString("failed to get architecture"); + } + } + else + { + elf_gregset_t regs; + int regset = NT_PRSTATUS; + struct iovec ioVec; + + ioVec.iov_base = ®s; + ioVec.iov_len = sizeof regs; + NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); + if (m_error.Success()) + { + ArchSpec arch; + if (monitor->GetArchitecture(arch)) + m_value.SetBytes((void *)(((unsigned char *)(regs)) + m_offset), 8, arch.GetByteOrder()); + else + m_error.SetErrorString("failed to get architecture"); + } + } +} + +void +WriteRegOperation::Execute(NativeProcessLinux *monitor) +{ + if (m_offset > sizeof(struct user_pt_regs)) + { + uintptr_t offset = m_offset - sizeof(struct user_pt_regs); + if (offset > sizeof(struct user_fpsimd_state)) + { + m_error.SetErrorString("invalid offset value"); + return; + } + elf_fpregset_t regs; + int regset = NT_FPREGSET; + struct iovec ioVec; + + ioVec.iov_base = ®s; + ioVec.iov_len = sizeof regs; + NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); + if (m_error.Success()) + { + ::memcpy((void *)(((unsigned char *)(®s)) + offset), m_value.GetBytes(), 16); + NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); + } + } + else + { + elf_gregset_t regs; + int regset = NT_PRSTATUS; + struct iovec ioVec; + + ioVec.iov_base = ®s; + ioVec.iov_len = sizeof regs; + NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); + if (m_error.Success()) + { + ::memcpy((void *)(((unsigned char *)(®s)) + m_offset), m_value.GetBytes(), 8); + NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); + } + } +} + +void +ReadGPROperation::Execute(NativeProcessLinux *monitor) +{ + int regset = NT_PRSTATUS; + struct iovec ioVec; + + ioVec.iov_base = m_buf; + ioVec.iov_len = m_buf_size; + NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error); +} + +void +WriteGPROperation::Execute(NativeProcessLinux *monitor) +{ + int regset = NT_PRSTATUS; + struct iovec ioVec; + + ioVec.iov_base = m_buf; + ioVec.iov_len = m_buf_size; + NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error); +} + +void +ReadFPROperation::Execute(NativeProcessLinux *monitor) +{ + int regset = NT_FPREGSET; + struct iovec ioVec; + + ioVec.iov_base = m_buf; + ioVec.iov_len = m_buf_size; + NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error); +} + +void +WriteFPROperation::Execute(NativeProcessLinux *monitor) { - switch (reg_info_interface_p->m_target_arch.GetMachine()) + int regset = NT_FPREGSET; + struct iovec ioVec; + + ioVec.iov_base = m_buf; + ioVec.iov_len = m_buf_size; + NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error); +} + +void +ReadDBGROperation::Execute(NativeProcessLinux *monitor) +{ + int regset = NT_ARM_HW_WATCH; + struct iovec ioVec; + struct user_hwdebug_state dreg_state; + + ioVec.iov_base = &dreg_state; + ioVec.iov_len = sizeof (dreg_state); + + NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len, m_error); + + m_count_wp = dreg_state.dbg_info & 0xff; + regset = NT_ARM_HW_BREAK; + + NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len, m_error); + m_count_bp = dreg_state.dbg_info & 0xff; +} + +void +WriteDBGROperation::Execute(NativeProcessLinux *monitor) +{ + struct iovec ioVec; + struct user_hwdebug_state dreg_state; + + memset (&dreg_state, 0, sizeof (dreg_state)); + ioVec.iov_base = &dreg_state; + ioVec.iov_len = sizeof (dreg_state); + + if (m_type == 0) + m_type = NT_ARM_HW_WATCH; + else + m_type = NT_ARM_HW_BREAK; + + for (int i = 0; i < m_count; i++) + { + dreg_state.dbg_regs[i].addr = m_address[i]; + dreg_state.dbg_regs[i].ctrl = m_control[i]; + } + + NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, &m_type, &ioVec, ioVec.iov_len, m_error); +} + +NativeRegisterContextLinux* +NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) +{ + return new NativeRegisterContextLinux_arm64(target_arch, native_thread, concrete_frame_idx); +} + +NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64 (const ArchSpec& target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) : + NativeRegisterContextLinux (native_thread, concrete_frame_idx, new RegisterContextLinux_arm64(target_arch)) +{ + switch (target_arch.GetMachine()) { case llvm::Triple::aarch64: m_reg_info.num_registers = k_num_registers_arm64; @@ -189,11 +529,9 @@ NativeRegisterContextLinux_arm64::ReadRegister (const RegisterInfo *reg_info, Re if (IsFPR(reg)) { - if (!ReadFPR()) - { - error.SetErrorString ("failed to read floating point register"); + error = ReadFPR(); + if (error.Fail()) return error; - } } else { @@ -279,10 +617,9 @@ NativeRegisterContextLinux_arm64::WriteRegister (const RegisterInfo *reg_info, c return Error ("unhandled register data size %" PRIu32, reg_info->byte_size); } - if (!WriteFPR()) - { - return Error ("NativeRegisterContextLinux_arm64::WriteRegister: WriteFPR failed"); - } + Error error = WriteFPR(); + if (error.Fail()) + return error; return Error (); } @@ -299,17 +636,13 @@ NativeRegisterContextLinux_arm64::ReadAllRegisterValues (lldb::DataBufferSP &dat if (!data_sp) return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE); - if (!ReadGPR ()) - { - error.SetErrorString ("ReadGPR() failed"); + error = ReadGPR(); + if (error.Fail()) return error; - } - if (!ReadFPR ()) - { - error.SetErrorString ("ReadFPR() failed"); + error = ReadFPR(); + if (error.Fail()) return error; - } uint8_t *dst = data_sp->GetBytes (); if (dst == nullptr) @@ -351,200 +684,32 @@ NativeRegisterContextLinux_arm64::WriteAllRegisterValues (const lldb::DataBuffer } ::memcpy (&m_gpr_arm64, src, GetRegisterInfoInterface ().GetGPRSize ()); - if (!WriteGPR ()) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteGPR() failed", __FUNCTION__); + error = WriteGPR(); + if (error.Fail()) return error; - } src += GetRegisterInfoInterface ().GetGPRSize (); ::memcpy (&m_fpr, src, sizeof(m_fpr)); - if (!WriteFPR ()) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteFPR() failed", __FUNCTION__); + error = WriteFPR(); + if (error.Fail()) return error; - } return error; } -Error -NativeRegisterContextLinux_arm64::WriteRegisterRaw (uint32_t reg_index, const RegisterValue ®_value) -{ - Error error; - - uint32_t reg_to_write = reg_index; - RegisterValue value_to_write = reg_value; - - // Check if this is a subregister of a full register. - const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index); - if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) - { - RegisterValue full_value; - uint32_t full_reg = reg_info->invalidate_regs[0]; - const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); - - // Read the full register. - error = ReadRegister(full_reg_info, full_value); - if (error.Fail ()) - return error; - - lldb::ByteOrder byte_order = GetByteOrder(); - uint8_t dst[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the full register. - const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info, - dst, - sizeof(dst), - byte_order, - error); - if (error.Success() && dest_size) - { - uint8_t src[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the source data. - const uint32_t src_size = reg_value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error); - if (error.Success() && src_size && (src_size < dest_size)) - { - // Copy the src bytes to the destination. - memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size); - // Set this full register as the value to write. - value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); - value_to_write.SetType(full_reg_info); - reg_to_write = full_reg; - } - } - } - - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - { - error.SetErrorString ("NativeProcessProtocol is NULL"); - return error; - } - - const RegisterInfo *const register_to_write_info_p = GetRegisterInfoAtIndex (reg_to_write); - assert (register_to_write_info_p && "register to write does not have valid RegisterInfo"); - if (!register_to_write_info_p) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_arm64::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write); - return error; - } - - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - return process_p->WriteRegisterValue(m_thread.GetID(), - register_to_write_info_p->byte_offset, - register_to_write_info_p->name, - value_to_write); -} - -Error -NativeRegisterContextLinux_arm64::ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value) -{ - Error error; - const RegisterInfo *const reg_info = GetRegisterInfoAtIndex (reg_index); - if (!reg_info) - { - error.SetErrorStringWithFormat ("register %" PRIu32 " not found", reg_index); - return error; - } - - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - { - error.SetErrorString ("NativeProcessProtocol is NULL"); - return error; - } - - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - return process_p->ReadRegisterValue(m_thread.GetID(), - reg_info->byte_offset, - reg_info->name, - reg_info->byte_size, - reg_value); -} - bool NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const { return reg <= m_reg_info.last_gpr; // GPR's come first. } -bool -NativeRegisterContextLinux_arm64::ReadGPR() -{ - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - return false; - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - - return process_p->ReadGPR (m_thread.GetID (), &m_gpr_arm64, GetRegisterInfoInterface ().GetGPRSize ()).Success(); -} - -bool -NativeRegisterContextLinux_arm64::WriteGPR() -{ - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - return false; - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - - return process_p->WriteGPR (m_thread.GetID (), &m_gpr_arm64, GetRegisterInfoInterface ().GetGPRSize ()).Success(); -} - bool NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const { return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); } -bool -NativeRegisterContextLinux_arm64::ReadFPR () -{ - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - return false; - - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - return process_p->ReadFPR (m_thread.GetID (), &m_fpr, sizeof (m_fpr)).Success(); -} - -bool -NativeRegisterContextLinux_arm64::WriteFPR () -{ - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - return false; - - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - return process_p->WriteFPR (m_thread.GetID (), &m_fpr, sizeof (m_fpr)).Success(); -} - -lldb::ByteOrder -NativeRegisterContextLinux_arm64::GetByteOrder() const -{ - // Get the target process whose privileged thread was used for the register read. - lldb::ByteOrder byte_order = lldb::eByteOrderInvalid; - - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - return byte_order; - - if (!process_sp->GetByteOrder (byte_order)) - { - // FIXME log here - } - - return byte_order; -} - -size_t -NativeRegisterContextLinux_arm64::GetGPRSize() const -{ - return GetRegisterInfoInterface().GetGPRSize(); -} - uint32_t NativeRegisterContextLinux_arm64::SetHardwareBreakpoint (lldb::addr_t addr, size_t size) { @@ -557,12 +722,10 @@ NativeRegisterContextLinux_arm64::SetHardwareBreakpoint (lldb::addr_t addr, size if (!process_sp) return false; - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); // Check if our hardware breakpoint and watchpoint information is updated. if (m_refresh_hwdebug_info) { - process_p->ReadHardwareDebugInfo (m_thread.GetID (), m_max_hwp_supported, - m_max_hbp_supported); + ReadHardwareDebugInfo (m_max_hwp_supported, m_max_hbp_supported); m_refresh_hwdebug_info = false; } @@ -668,12 +831,11 @@ NativeRegisterContextLinux_arm64::SetHardwareWatchpoint (lldb::addr_t addr, size if (!process_sp) return false; - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); + // Check if our hardware breakpoint and watchpoint information is updated. if (m_refresh_hwdebug_info) { - process_p->ReadHardwareDebugInfo (m_thread.GetID (), m_max_hwp_supported, - m_max_hbp_supported); + ReadHardwareDebugInfo (m_max_hwp_supported, m_max_hbp_supported); m_refresh_hwdebug_info = false; } @@ -724,8 +886,7 @@ NativeRegisterContextLinux_arm64::SetHardwareWatchpoint (lldb::addr_t addr, size m_hwp_regs[wp_index].refcount = 1; // PTRACE call to set corresponding watchpoint register. - process_p->WriteHardwareDebugRegs(m_thread.GetID (), &addr, - &control_value, 0, wp_index); + WriteHardwareDebugRegs(&addr, &control_value, 0, wp_index); } else m_hwp_regs[wp_index].refcount++; @@ -745,8 +906,6 @@ NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint (uint32_t wp_index) if (!process_sp) return false; - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - if (wp_index >= m_max_hwp_supported) return false; @@ -763,10 +922,7 @@ NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint (uint32_t wp_index) m_hwp_regs[wp_index].refcount = 0; //TODO: PTRACE CALL HERE for an UPDATE - process_p->WriteHardwareDebugRegs(m_thread.GetID (), - &m_hwp_regs[wp_index].address, - &m_hwp_regs[wp_index].control, - 0, wp_index); + WriteHardwareDebugRegs(&m_hwp_regs[wp_index].address, &m_hwp_regs[wp_index].control, 0, wp_index); return true; } @@ -788,8 +944,6 @@ NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints () if (!process_sp) return ml_error; - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - for (uint32_t i = 0; i < m_max_hwp_supported; i++) { if (m_hwp_regs[i].control & 0x01) @@ -798,10 +952,7 @@ NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints () m_hwp_regs[i].address = 0; m_hwp_regs[i].refcount = 0; - process_p->WriteHardwareDebugRegs(m_thread.GetID (), - &m_hwp_regs[i].address, - &m_hwp_regs[i].control, - 0, i); + WriteHardwareDebugRegs(&m_hwp_regs[i].address, &m_hwp_regs[i].control, 0, i); } } @@ -887,13 +1038,73 @@ NativeRegisterContextLinux_arm64::GetWatchpointAddress (uint32_t wp_index) return LLDB_INVALID_ADDRESS; } -bool -NativeRegisterContextLinux_arm64::HardwareSingleStep (bool enable) +Error +NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo(unsigned int &watch_count, + unsigned int &break_count) { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); + NativeProcessProtocolSP process_sp (m_thread.GetProcess()); + if (!process_sp) + return Error("NativeProcessProtocol is NULL"); + NativeProcessLinux *const process_p = reinterpret_cast(process_sp.get()); - if (log) - log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); + ReadDBGROperation op(m_thread.GetID(), watch_count, break_count); + return process_p->DoOperation(&op); +} - return false; +Error +NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(lldb::addr_t *addr_buf, + uint32_t *cntrl_buf, + int type, + int count) +{ + NativeProcessProtocolSP process_sp (m_thread.GetProcess()); + if (!process_sp) + return Error("NativeProcessProtocol is NULL"); + NativeProcessLinux *const process_p = reinterpret_cast(process_sp.get()); + + WriteDBGROperation op(m_thread.GetID(), addr_buf, cntrl_buf, type, count); + return process_p->DoOperation(&op); } + +NativeProcessLinux::OperationUP +NativeRegisterContextLinux_arm64::GetReadRegisterValueOperation(uint32_t offset, + const char* reg_name, + uint32_t size, + RegisterValue &value) +{ + return NativeProcessLinux::OperationUP(new ReadRegOperation(m_thread.GetID(), offset, reg_name, value)); +} + +NativeProcessLinux::OperationUP +NativeRegisterContextLinux_arm64::GetWriteRegisterValueOperation(uint32_t offset, + const char* reg_name, + const RegisterValue &value) +{ + return NativeProcessLinux::OperationUP(new WriteRegOperation(m_thread.GetID(), offset, reg_name, value)); +} + +NativeProcessLinux::OperationUP +NativeRegisterContextLinux_arm64::GetReadGPROperation(void *buf, size_t buf_size) +{ + return NativeProcessLinux::OperationUP(new ReadGPROperation(m_thread.GetID(), buf, buf_size)); +} + +NativeProcessLinux::OperationUP +NativeRegisterContextLinux_arm64::GetWriteGPROperation(void *buf, size_t buf_size) +{ + return NativeProcessLinux::OperationUP(new WriteGPROperation(m_thread.GetID(), buf, buf_size)); +} + +NativeProcessLinux::OperationUP +NativeRegisterContextLinux_arm64::GetReadFPROperation(void *buf, size_t buf_size) +{ + return NativeProcessLinux::OperationUP(new ReadFPROperation(m_thread.GetID(), buf, buf_size)); +} + +NativeProcessLinux::OperationUP +NativeRegisterContextLinux_arm64::GetWriteFPROperation(void *buf, size_t buf_size) +{ + return NativeProcessLinux::OperationUP(new WriteFPROperation(m_thread.GetID(), buf, buf_size)); +} + +#endif // defined (__arm64__) || defined (__aarch64__) -- cgit v1.2.3