diff options
Diffstat (limited to 'lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp')
| -rw-r--r-- | lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp | 661 |
1 files changed, 436 insertions, 225 deletions
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp index aef1ae995cb..ea6d6c318ca 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 <sys/socket.h> +// NT_PRSTATUS and NT_FPREGSET definition +#include <elf.h> -#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<uintptr_t>(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,120 +684,20 @@ 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<NativeProcessLinux*> (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<NativeProcessLinux*> (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 { @@ -472,79 +705,11 @@ NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const } bool -NativeRegisterContextLinux_arm64::ReadGPR() -{ - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - return false; - NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (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<NativeProcessLinux*> (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<NativeProcessLinux*> (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<NativeProcessLinux*> (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<NativeProcessLinux*> (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<NativeProcessLinux*> (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<NativeProcessLinux*> (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<NativeProcessLinux*> (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<NativeProcessLinux*>(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<NativeProcessLinux*>(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__) |

