omjavaid created this revision.
omjavaid added reviewers: labath, clayborg.
omjavaid added a subscriber: lldb-commits.
Herald added subscribers: danalbert, tberghammer, rengolin, aemerson.

This patch adds logic to make sure we can install watchpoints at 1,2 and 4 byte 
alligned addresses.

ptrace interface allows watchpoints at 8-byte alligned addresses. Therefor for 
all lower allignment levels we have to watch full 8-bytes.
We will ignore all irrelevant watchpoint trigger exceptions and will continue 
the target after stepping over the watchpoint instruction.

In worst case while watching a 8-byte array like byteArr[8] we may have to 
ignore 7 false watchpoint hits if we install watchpoint at the last byte in the 
array.

However overall advantage of this solution overwhelms this disadvantage. We now 
have all watchpoint tests passing on AArch64 Linux (HiKey board) and Arm64 
Android (Nexus9).

http://reviews.llvm.org/D21280

Files:
  source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
  source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
  source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp

Index: source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
===================================================================
--- source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -2059,7 +2059,8 @@
                             {
                                 WatchpointSP wp_sp;
                                 ArchSpec::Core core = GetTarget().GetArchitecture().GetCore();
-                                if (core >= ArchSpec::kCore_mips_first && core <= ArchSpec::kCore_mips_last)
+                                if ((core >= ArchSpec::kCore_mips_first && core <= ArchSpec::kCore_mips_last) ||
+                                    (core >= ArchSpec::eCore_arm_arm64 && core <= ArchSpec::eCore_arm_aarch64))
                                     wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_hit_addr);
                                 if (!wp_sp)
                                     wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr);
Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
===================================================================
--- source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
+++ source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
@@ -74,6 +74,9 @@
         GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) override;
 
         lldb::addr_t
+        GetWatchpointHitAddress (uint32_t wp_index) override;
+
+        lldb::addr_t
         GetWatchpointAddress (uint32_t wp_index) override;
 
         uint32_t
@@ -161,6 +164,8 @@
         struct DREG
         {
             lldb::addr_t address;  // Breakpoint/watchpoint address value.
+            lldb::addr_t hit_addr; // Address at which last watchpoint trigger exception occurred.
+            lldb::addr_t real_addr;  // Address value that should cause target to stop.
             uint32_t control;  // Breakpoint/watchpoint control value.
             uint32_t refcount;  // Serves as enable/disable and refernce counter.
         };
Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
===================================================================
--- source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -566,6 +566,7 @@
         return LLDB_INVALID_INDEX32;
 		
     uint32_t control_value = 0, wp_index = 0;
+    lldb::addr_t real_addr = addr;
 
     // Check if we are setting watchpoint other than read/write/access
     // Also update watchpoint flag to match AArch64 write-read bit configuration.
@@ -588,9 +589,23 @@
         return LLDB_INVALID_INDEX32;
 
     // Check 8-byte alignment for hardware watchpoint target address.
-    // TODO: Add support for watching un-aligned addresses
+    // Below is a hack to recalculate address and size in order to
+    // make sure we can watch non 8-byte alligned addresses as well.
     if (addr & 0x07)
-        return LLDB_INVALID_INDEX32;
+    {
+        uint8_t watch_mask = (addr & 0x07) + size;
+
+        if (watch_mask > 0x08)
+            return LLDB_INVALID_INDEX32;
+        else if (watch_mask <= 0x02)
+            size = 2;
+        else if (watch_mask <= 0x04)
+            size = 4;
+        else
+            size = 8;
+
+        addr = addr & (~0x07);
+    }
 
     // Setup control value
     control_value = watch_flags << 3;
@@ -620,6 +635,7 @@
     if ((m_hwp_regs[wp_index].control & 1) == 0)
     {
         // Update watchpoint in local cache
+        m_hwp_regs[wp_index].real_addr = real_addr;
         m_hwp_regs[wp_index].address = addr;
         m_hwp_regs[wp_index].control = control_value;
         m_hwp_regs[wp_index].refcount = 1;
@@ -801,6 +817,7 @@
         if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index)
             && trap_addr >= watch_addr && trap_addr < watch_addr + watch_size)
         {
+            m_hwp_regs[wp_index].hit_addr = trap_addr;
             return Error();
         }
     }
@@ -821,7 +838,24 @@
         return LLDB_INVALID_ADDRESS;
 
     if (WatchpointIsEnabled(wp_index))
-        return m_hwp_regs[wp_index].address;
+        return m_hwp_regs[wp_index].real_addr;
+    else
+        return LLDB_INVALID_ADDRESS;
+}
+
+lldb::addr_t
+NativeRegisterContextLinux_arm64::GetWatchpointHitAddress (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].hit_addr;
     else
         return LLDB_INVALID_ADDRESS;
 }
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to