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

We recently committed a patch for AArch64 targets that allows us to watch any 
byte address individually in a 8 byte aligned region.

This patch implements the same for arm targets with region being watched is a 4 
byte region.

We cannot watch 8 consecutive bytes using a single watchpoint resource on Arm 
targets so maximum we can do is 4 bytes.

As a results TestWatchpointSize tests pass on arm targets which were previously 
failing.

http://reviews.llvm.org/D21516

Files:
  source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
  source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.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
@@ -2060,7 +2060,7 @@
                                 WatchpointSP wp_sp;
                                 ArchSpec::Core core = GetTarget().GetArchitecture().GetCore();
                                 if ((core >= ArchSpec::kCore_mips_first && core <= ArchSpec::kCore_mips_last) ||
-                                    (core >= ArchSpec::eCore_arm_arm64 && core <= ArchSpec::eCore_arm_aarch64))
+                                    (core >= ArchSpec::eCore_arm_generic && 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_arm.h
===================================================================
--- source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
+++ source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.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
@@ -162,6 +165,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_arm.cpp
===================================================================
--- source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
+++ source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
@@ -614,6 +614,7 @@
         return LLDB_INVALID_INDEX32;
 		
     uint32_t control_value = 0, wp_index = 0, addr_word_offset = 0, byte_mask = 0;
+    lldb::addr_t real_addr = addr;
 
     // Check if we are setting watchpoint other than read/write/access
     // Also update watchpoint flag to match Arm write-read bit configuration.
@@ -637,7 +638,24 @@
     if (size == 0 || size > 4)
         return LLDB_INVALID_INDEX32;
 
-    // We can only watch up to four bytes that follow a 4 byte aligned address
+    // Check 4-byte alignment for hardware watchpoint target address.
+    // Below is a hack to recalculate address and size in order to
+    // make sure we can watch non 4-byte alligned addresses as well.
+    if (addr & 0x03)
+    {
+        uint8_t watch_mask = (addr & 0x03) + size;
+
+        if (watch_mask > 0x04)
+            return LLDB_INVALID_INDEX32;
+        else if (watch_mask <= 0x02)
+            size = 2;
+        else if (watch_mask <= 0x04)
+            size = 4;
+
+        addr = addr & (~0x03);
+    }
+
+	// We can only watch up to four bytes that follow a 4 byte aligned address
     // per watchpoint register pair, so make sure we can properly encode this.
     addr_word_offset = addr % 4;
     byte_mask = ((1u << size) - 1u) << addr_word_offset;
@@ -682,6 +700,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;
@@ -864,6 +883,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();
         }
     }
@@ -884,7 +904,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_arm::GetWatchpointHitAddress (uint32_t wp_index)
+{
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+
+    if (log)
+        log->Printf ("NativeRegisterContextLinux_arm::%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