[Lldb-commits] [lldb] r237419 - This patch adds support for setting/clearing hardware watchpoints and breakpoints on AArch64 (Arm v8) 64-bit hardware.
Omair Javaid
omair.javaid at linaro.org
Thu May 14 23:30:00 PDT 2015
Author: omjavaid
Date: Fri May 15 01:29:58 2015
New Revision: 237419
URL: http://llvm.org/viewvc/llvm-project?rev=237419&view=rev
Log:
This patch adds support for setting/clearing hardware watchpoints and breakpoints on AArch64 (Arm v8) 64-bit hardware.
http://reviews.llvm.org/D9706
Modified:
lldb/trunk/include/lldb/Host/common/NativeRegisterContext.h
lldb/trunk/source/Host/common/NativeRegisterContext.cpp
lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h
lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp
lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h
Modified: lldb/trunk/include/lldb/Host/common/NativeRegisterContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/common/NativeRegisterContext.h?rev=237419&r1=237418&r2=237419&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/common/NativeRegisterContext.h (original)
+++ lldb/trunk/include/lldb/Host/common/NativeRegisterContext.h Fri May 15 01:29:58 2015
@@ -103,7 +103,7 @@ public:
IsWatchpointHit(uint32_t wp_index, bool &is_hit);
virtual Error
- GetWatchpointHitIndex(uint32_t &wp_index);
+ GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr);
virtual Error
IsWatchpointVacant (uint32_t wp_index, bool &is_vacant);
Modified: lldb/trunk/source/Host/common/NativeRegisterContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/NativeRegisterContext.cpp?rev=237419&r1=237418&r2=237419&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/NativeRegisterContext.cpp (original)
+++ lldb/trunk/source/Host/common/NativeRegisterContext.cpp Fri May 15 01:29:58 2015
@@ -309,7 +309,7 @@ NativeRegisterContext::IsWatchpointHit(u
}
Error
-NativeRegisterContext::GetWatchpointHitIndex(uint32_t &wp_index)
+NativeRegisterContext::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr)
{
wp_index = LLDB_INVALID_INDEX32;
return Error ("not implemented");
Modified: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp?rev=237419&r1=237418&r2=237419&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp Fri May 15 01:29:58 2015
@@ -762,6 +762,47 @@ namespace
#endif
}
+#if defined (__arm64__) || defined (__aarch64__)
+ //------------------------------------------------------------------------------
+ /// @class ReadDBGROperation
+ /// @brief Implements NativeProcessLinux::ReadDBGR.
+ class ReadDBGROperation : public 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;
+ };
+
+ 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);
+
+ PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len, m_error);
+
+ m_count_wp = dreg_state.dbg_info & 0xff;
+ regset = NT_ARM_HW_BREAK;
+
+ PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len, m_error);
+ m_count_bp = dreg_state.dbg_info & 0xff;
+ }
+#endif
+
//------------------------------------------------------------------------------
/// @class ReadRegisterSetOperation
/// @brief Implements NativeProcessLinux::ReadRegisterSet.
@@ -853,6 +894,57 @@ namespace
#endif
}
+#if defined (__arm64__) || defined (__aarch64__)
+ //------------------------------------------------------------------------------
+ /// @class WriteDBGROperation
+ /// @brief Implements NativeProcessLinux::WriteFPR.
+ class WriteDBGROperation : public 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;
+ };
+
+ void
+ WriteDBGROperation::Execute(NativeProcessLinux *monitor)
+ {
+ struct iovec ioVec;
+ struct user_hwdebug_state dreg_state;
+
+ memset (&dreg_state, 0, sizeof (dreg_state));
+ ioVec.iov_len = (__builtin_offsetof (struct user_hwdebug_state, dbg_regs[m_count - 1])
+ + sizeof (dreg_state.dbg_regs [m_count - 1]));
+
+ 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];
+ }
+
+ PTRACE(PTRACE_SETREGSET, m_tid, &m_type, &ioVec, ioVec.iov_len, m_error);
+ }
+#endif
+
//------------------------------------------------------------------------------
/// @class WriteRegisterSetOperation
/// @brief Implements NativeProcessLinux::WriteRegisterSet.
@@ -2436,7 +2528,7 @@ NativeProcessLinux::MonitorSIGTRAP(const
{
// If a watchpoint was hit, report it
uint32_t wp_index;
- Error error = thread_sp->GetRegisterContext()->GetWatchpointHitIndex(wp_index);
+ Error error = thread_sp->GetRegisterContext()->GetWatchpointHitIndex(wp_index, (lldb::addr_t)info->si_addr);
if (error.Fail() && log)
log->Printf("NativeProcessLinux::%s() "
"received error while checking for watchpoint hits, "
@@ -3841,6 +3933,26 @@ NativeProcessLinux::ReadRegisterSet(lldb
return op.GetError();
}
+#if defined (__arm64__) || defined (__aarch64__)
+
+Error
+NativeProcessLinux::ReadHardwareDebugInfo (lldb::tid_t tid, unsigned int &watch_count , unsigned int &break_count)
+{
+ ReadDBGROperation op(tid, watch_count, break_count);
+ m_monitor_up->DoOperation(&op);
+ return op.GetError();
+}
+
+Error
+NativeProcessLinux::WriteHardwareDebugRegs (lldb::tid_t tid, lldb::addr_t *addr_buf, uint32_t *cntrl_buf, int type, int count)
+{
+ WriteDBGROperation op(tid, addr_buf, cntrl_buf, type, count);
+ m_monitor_up->DoOperation(&op);
+ return op.GetError();
+}
+
+#endif
+
Error
NativeProcessLinux::WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size)
{
Modified: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h?rev=237419&r1=237418&r2=237419&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h Fri May 15 01:29:58 2015
@@ -151,6 +151,17 @@ namespace process_linux {
Error
ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size);
+#if defined (__arm64__) || defined (__aarch64__)
+ /// Reads hardware breakpoints and watchpoints capability information.
+ Error
+ ReadHardwareDebugInfo (lldb::tid_t tid, unsigned int &watch_count ,
+ unsigned int &break_count);
+
+ /// Write hardware breakpoint/watchpoint control and address registers.
+ Error
+ WriteHardwareDebugRegs (lldb::tid_t tid, lldb::addr_t *addr_buf,
+ uint32_t *cntrl_buf, int type, int count);
+#endif
/// Reads the specified register set into the specified buffer.
/// For instance, the extended floating-point register set.
Error
Modified: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp?rev=237419&r1=237418&r2=237419&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp Fri May 15 01:29:58 2015
@@ -12,10 +12,12 @@
#include "lldb/lldb-private-forward.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Error.h"
+#include "lldb/Core/StreamString.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"
#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof (m_fpr))
@@ -149,6 +151,12 @@ NativeRegisterContextLinux_arm64::Native
::memset(&m_fpr, 0, sizeof (m_fpr));
::memset(&m_gpr_arm64, 0, sizeof (m_gpr_arm64));
+ ::memset(&m_hwp_regs, 0, sizeof (m_hwp_regs));
+
+ // 16 is just a maximum value, query hardware for actual watchpoint count
+ m_max_hwp_supported = 16;
+ m_max_hbp_supported = 16;
+ m_refresh_hwdebug_info = true;
}
uint32_t
@@ -536,3 +544,356 @@ NativeRegisterContextLinux_arm64::GetGPR
{
return GetRegisterInfoInterface().GetGPRSize();
}
+
+uint32_t
+NativeRegisterContextLinux_arm64::SetHardwareBreakpoint (lldb::addr_t addr, size_t size)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+
+ if (log)
+ log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+ 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);
+ m_refresh_hwdebug_info = false;
+ }
+
+ uint32_t control_value, bp_index;
+
+ // Check if size has a valid hardware breakpoint length.
+ if (size != 4)
+ return LLDB_INVALID_INDEX32; // Invalid size for a AArch64 hardware breakpoint
+
+ // Check 4-byte alignment for hardware breakpoint target address.
+ if (addr & 0x03)
+ return LLDB_INVALID_INDEX32; // Invalid address, should be 4-byte aligned.
+
+ // Setup control value
+ control_value = 0;
+ control_value |= ((1 << size) - 1) << 5;
+ control_value |= (2 << 1) | 1;
+
+ // Iterate over stored hardware breakpoints
+ // Find a free bp_index or update reference count if duplicate.
+ bp_index = LLDB_INVALID_INDEX32;
+ for (uint32_t i = 0; i < m_max_hbp_supported; i++)
+ {
+ if ((m_hbr_regs[i].control & 1) == 0)
+ {
+ bp_index = i; // Mark last free slot
+ }
+ else if (m_hbr_regs[i].address == addr && m_hbr_regs[i].control == control_value)
+ {
+ bp_index = i; // Mark duplicate index
+ break; // Stop searching here
+ }
+ }
+
+ if (bp_index == LLDB_INVALID_INDEX32)
+ return LLDB_INVALID_INDEX32;
+
+ // Add new or update existing watchpoint
+ if ((m_hbr_regs[bp_index].control & 1) == 0)
+ {
+ m_hbr_regs[bp_index].address = addr;
+ m_hbr_regs[bp_index].control = control_value;
+ m_hbr_regs[bp_index].refcount = 1;
+
+ //TODO: PTRACE CALL HERE for an UPDATE
+ }
+ else
+ m_hbr_regs[bp_index].refcount++;
+
+ return bp_index;
+}
+
+bool
+NativeRegisterContextLinux_arm64::ClearHardwareBreakpoint (uint32_t hw_idx)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+
+ if (log)
+ log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+
+ if (hw_idx >= m_max_hbp_supported)
+ return false;
+
+ // Update reference count if multiple references.
+ if (m_hbr_regs[hw_idx].refcount > 1)
+ {
+ m_hbr_regs[hw_idx].refcount--;
+ return true;
+ }
+ else if (m_hbr_regs[hw_idx].refcount == 1)
+ {
+ m_hbr_regs[hw_idx].control &= ~1;
+ m_hbr_regs[hw_idx].address = 0;
+ m_hbr_regs[hw_idx].refcount = 0;
+
+ //TODO: PTRACE CALL HERE for an UPDATE
+ return true;
+ }
+
+ return false;
+}
+
+uint32_t
+NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints ()
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+
+ if (log)
+ log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+
+ return m_max_hwp_supported;
+}
+
+uint32_t
+NativeRegisterContextLinux_arm64::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+
+ if (log)
+ log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+ 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);
+ m_refresh_hwdebug_info = false;
+ }
+
+ uint32_t control_value, wp_index;
+
+
+ if (watch_flags != 0x1 && watch_flags != 0x2 && watch_flags != 0x3)
+ return 0;//Error ("Invalid read/write bits for watchpoint");
+
+ // Check if size has a valid hardware watchpoint length.
+ if (size != 1 && size != 2 && size != 4 && size != 8)
+ return 0;//Error ("Invalid size for watchpoint");
+
+ // Check 8-byte alignment for hardware watchpoint target address.
+ // TODO: Add support for watching un-aligned addresses
+ if (addr & 0x07)
+ return 0;//Error ("LLDB for AArch64 currently supports 8-byte alignment for hardware watchpoint target address.");
+
+ // Setup control value
+ control_value = watch_flags << 3;
+ control_value |= ((1 << size) - 1) << 5;
+ control_value |= (2 << 1) | 1;
+
+ // Iterate over stored watchpoints
+ // Find a free wp_index or update reference count if duplicate.
+ wp_index = LLDB_INVALID_INDEX32;
+ for (uint32_t i = 0; i < m_max_hwp_supported; i++)
+ {
+ if ((m_hwp_regs[i].control & 1) == 0)
+ {
+ wp_index = i; // Mark last free slot
+ }
+ else if (m_hwp_regs[i].address == addr && m_hwp_regs[i].control == control_value)
+ {
+ wp_index = i; // Mark duplicate index
+ break; // Stop searching here
+ }
+ }
+
+ if (wp_index == LLDB_INVALID_INDEX32)
+ return LLDB_INVALID_INDEX32;
+
+ // Add new or update existing watchpoint
+ if ((m_hwp_regs[wp_index].control & 1) == 0)
+ {
+ m_hwp_regs[wp_index].address = addr;
+ m_hwp_regs[wp_index].control = control_value;
+ 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);
+ }
+ else
+ m_hwp_regs[wp_index].refcount++;
+
+ return wp_index;
+}
+
+bool
+NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint (uint32_t wp_index)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+
+ if (log)
+ log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+ if (!process_sp)
+ return false;
+
+ NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
+
+ if (wp_index >= m_max_hwp_supported)
+ return false;
+
+ // Update reference count if multiple references.
+ if (m_hwp_regs[wp_index].refcount > 1)
+ {
+ m_hwp_regs[wp_index].refcount--;
+ return true;
+ }
+ else if (m_hwp_regs[wp_index].refcount == 1)
+ {
+ m_hwp_regs[wp_index].control &= ~1;
+ m_hwp_regs[wp_index].address = 0;
+ 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);
+ return true;
+ }
+
+ return false;
+}
+
+Error
+NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints ()
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+
+ if (log)
+ log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+
+ Error ml_error;
+ ml_error.SetErrorToErrno();
+ 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)
+ {
+ m_hwp_regs[i].control &= ~1;
+ 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);
+ }
+ }
+
+ return Error();
+}
+
+uint32_t
+NativeRegisterContextLinux_arm64::GetWatchpointSize(uint32_t wp_index)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+
+ if (log)
+ log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+ switch ((m_hwp_regs[wp_index].control >> 5) & 0xff)
+ {
+ case 0x01:
+ return 1;
+ case 0x03:
+ return 2;
+ case 0x0f:
+ return 4;
+ case 0xff:
+ return 8;
+ default:
+ return 0;
+ }
+}
+bool
+NativeRegisterContextLinux_arm64::WatchpointIsEnabled(uint32_t wp_index)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+
+ if (log)
+ log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+
+ if ((m_hwp_regs[wp_index].control & 0x1) == 0x1)
+ return true;
+ else
+ return false;
+}
+
+Error
+NativeRegisterContextLinux_arm64::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+
+ if (log)
+ log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+
+ uint32_t watch_size;
+ lldb::addr_t watch_addr;
+
+ for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index)
+ {
+ watch_size = GetWatchpointSize (wp_index);
+ watch_addr = m_hwp_regs[wp_index].address;
+
+ if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index)
+ && trap_addr >= watch_addr && trap_addr < watch_addr + watch_size)
+ {
+ return Error();
+ }
+ }
+
+ wp_index = LLDB_INVALID_INDEX32;
+ return Error();
+}
+
+lldb::addr_t
+NativeRegisterContextLinux_arm64::GetWatchpointAddress (uint32_t wp_index)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+
+ if (log)
+ log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+
+ if (wp_index >= m_max_hwp_supported)
+ return LLDB_INVALID_ADDRESS;
+
+ if (WatchpointIsEnabled(wp_index))
+ return m_hwp_regs[wp_index].address;
+ else
+ return LLDB_INVALID_ADDRESS;
+}
+
+bool
+NativeRegisterContextLinux_arm64::HardwareSingleStep (bool enable)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+
+ if (log)
+ log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+
+ return false;
+}
Modified: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h?rev=237419&r1=237418&r2=237419&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h Fri May 15 01:29:58 2015
@@ -44,6 +44,43 @@ namespace process_linux {
Error
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) override;
+ //------------------------------------------------------------------
+ // Hardware breakpoints/watchpoint mangement functions
+ //------------------------------------------------------------------
+
+ uint32_t
+ SetHardwareBreakpoint (lldb::addr_t addr, size_t size) override;
+
+ bool
+ ClearHardwareBreakpoint (uint32_t hw_idx) override;
+
+ uint32_t
+ NumSupportedHardwareWatchpoints () override;
+
+ uint32_t
+ SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags) override;
+
+ bool
+ ClearHardwareWatchpoint (uint32_t hw_index) override;
+
+ Error
+ ClearAllHardwareWatchpoints () override;
+
+ Error
+ GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) override;
+
+ lldb::addr_t
+ GetWatchpointAddress (uint32_t wp_index) override;
+
+ bool
+ HardwareSingleStep (bool enable) override;
+
+ uint32_t
+ GetWatchpointSize(uint32_t wp_index);
+
+ bool
+ WatchpointIsEnabled(uint32_t wp_index);
+
private:
struct RegInfo
{
@@ -79,6 +116,21 @@ namespace process_linux {
RegInfo m_reg_info;
FPU m_fpr; // floating-point registers including extended register sets.
+ // Debug register info for hardware breakpoints and watchpoints management.
+ struct DREG
+ {
+ lldb::addr_t address; // Breakpoint/watchpoint address value.
+ uint32_t control; // Breakpoint/watchpoint control value.
+ uint32_t refcount; // Serves as enable/disable and refernce counter.
+ };
+
+ struct DREG m_hbr_regs[16]; // Arm native linux hardware breakpoints
+ struct DREG m_hwp_regs[16]; // Arm native linux hardware watchpoints
+
+ uint32_t m_max_hwp_supported;
+ uint32_t m_max_hbp_supported;
+ bool m_refresh_hwdebug_info;
+
bool
IsGPR(unsigned reg) const;
Modified: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp?rev=237419&r1=237418&r2=237419&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp Fri May 15 01:29:58 2015
@@ -1069,7 +1069,7 @@ NativeRegisterContextLinux_x86_64::IsWat
}
Error
-NativeRegisterContextLinux_x86_64::GetWatchpointHitIndex(uint32_t &wp_index) {
+NativeRegisterContextLinux_x86_64::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) {
uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
for (wp_index = 0; wp_index < num_hw_wps; ++wp_index)
{
Modified: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h?rev=237419&r1=237418&r2=237419&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h Fri May 15 01:29:58 2015
@@ -50,7 +50,7 @@ namespace process_linux {
IsWatchpointHit(uint32_t wp_index, bool &is_hit) override;
Error
- GetWatchpointHitIndex(uint32_t &wp_index) override;
+ GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) override;
Error
IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override;
Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp?rev=237419&r1=237418&r2=237419&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp Fri May 15 01:29:58 2015
@@ -548,7 +548,96 @@ ReadRegOperation::Execute(ProcessMonitor
#endif
}
-//------------------------------------------------------------------------------
+#if defined (__arm64__) || defined (__aarch64__)
+ //------------------------------------------------------------------------------
+ /// @class ReadDBGROperation
+ /// @brief Implements NativeProcessLinux::ReadDBGR.
+ class ReadDBGROperation : public 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(ProcessMonitor *monitor) override;
+
+ private:
+ lldb::tid_t m_tid;
+ unsigned int &m_count_wp;
+ unsigned int &m_count_bp;
+ };
+
+ void
+ ReadDBGROperation::Execute(ProcessMonitor *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);
+
+ PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len);
+
+ m_count_wp = dreg_state.dbg_info & 0xff;
+ regset = NT_ARM_HW_BREAK;
+
+ PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len);
+ m_count_bp = dreg_state.dbg_info & 0xff;
+ }
+#endif
+
+#if defined (__arm64__) || defined (__aarch64__)
+ //------------------------------------------------------------------------------
+ /// @class WriteDBGROperation
+ /// @brief Implements NativeProcessLinux::WriteFPR.
+ class WriteDBGROperation : public Operation
+ {
+ public:
+ WriteDBGROperation(lldb::tid_t tid, lldb::addr_t *addr_buf, uint32_t *cntrl_buf, int type, int count)
+ : m_tid(tid),
+ m_addr_buf(addr_buf),
+ m_cntrl_buf(cntrl_buf),
+ m_type(type),
+ m_count(count)
+ { }
+
+ void Execute(ProcessMonitor *monitor) override;
+
+ private:
+ lldb::tid_t m_tid;
+ lldb::addr_t *m_addr_buf;
+ uint32_t *m_cntrl_buf;
+ int m_type;
+ int m_count;
+ };
+
+ void
+ WriteDBGROperation::Execute(ProcessMonitor *monitor)
+ {
+ struct iovec ioVec;
+ struct user_hwdebug_state dreg_state;
+
+ memset (&dreg_state, 0, sizeof (dreg_state));
+ ioVec.iov_len = (__builtin_offsetof (struct user_hwdebug_state, dbg_regs[m_count - 1])
+ + sizeof (dreg_state.dbg_regs [m_count - 1]));
+
+ 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_addr_buf[i];
+ dreg_state.dbg_regs[i].ctrl = m_cntrl_buf[i];
+ }
+
+ PTRACE(PTRACE_SETREGSET, m_tid, &m_type, &ioVec, ioVec.iov_len);
+ }
+#endif//------------------------------------------------------------------------------
/// @class WriteRegOperation
/// @brief Implements ProcessMonitor::WriteRegisterValue.
class WriteRegOperation : public Operation
@@ -2159,6 +2248,27 @@ ProcessMonitor::ReadRegisterValue(lldb::
return result;
}
+#if defined (__arm64__) || defined (__aarch64__)
+
+bool
+ProcessMonitor::ReadHardwareDebugInfo (lldb::tid_t tid, unsigned int &watch_count , unsigned int &break_count)
+{
+ bool result = true;
+ ReadDBGROperation op(tid, watch_count, break_count);
+ DoOperation(&op);
+ return result;
+}
+
+bool
+ProcessMonitor::WriteHardwareDebugRegs (lldb::tid_t tid, lldb::addr_t *addr_buf, uint32_t *cntrl_buf, int type, int count)
+{
+ bool result = true;
+ WriteDBGROperation op(tid, addr_buf, cntrl_buf, type, count);
+ DoOperation(&op);
+ return result;
+}
+
+#endif
bool
ProcessMonitor::WriteRegisterValue(lldb::tid_t tid, unsigned offset,
const char* reg_name, const RegisterValue &value)
Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h?rev=237419&r1=237418&r2=237419&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h Fri May 15 01:29:58 2015
@@ -138,6 +138,18 @@ public:
bool
ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size);
+#if defined (__arm64__) || defined (__aarch64__)
+ /// Reads hardware breakpoints and watchpoints capability information.
+ bool
+ ReadHardwareDebugInfo (lldb::tid_t tid, unsigned int &watch_count ,
+ unsigned int &break_count);
+
+ /// Write hardware breakpoint/watchpoint control and address registers.
+ bool
+ WriteHardwareDebugRegs (lldb::tid_t tid, lldb::addr_t *addr_buf,
+ uint32_t *cntrl_buf, int type, int count);
+#endif
+
/// Reads the specified register set into the specified buffer.
/// For instance, the extended floating-point register set.
bool
More information about the lldb-commits
mailing list