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