<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, &regset, &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, &regset, &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, &regset, &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, &regset, &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>