[Lldb-commits] [lldb] r272916 - Allow installing watchpoints at less than 8-byte alligned addresses for AArch64 targets

Omair Javaid via lldb-commits lldb-commits at lists.llvm.org
Thu Jun 16 09:41:22 PDT 2016


Author: omjavaid
Date: Thu Jun 16 11:41:22 2016
New Revision: 272916

URL: http://llvm.org/viewvc/llvm-project?rev=272916&view=rev
Log:
Allow installing watchpoints at less than 8-byte alligned addresses for AArch64 targets

This patch allows LLDB for AArch64 to watch all bytes, words or double words individually on non 8-byte alligned addresses.

This patch also adds tests to verify this functionality.

Differential revision: http://reviews.llvm.org/D21280


Added:
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/Makefile
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/TestWatchpointSizes.py
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/main.c
Modified:
    lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
    lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
    lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/Makefile?rev=272916&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/Makefile (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/Makefile Thu Jun 16 11:41:22 2016
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/TestWatchpointSizes.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/TestWatchpointSizes.py?rev=272916&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/TestWatchpointSizes.py (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/TestWatchpointSizes.py Thu Jun 16 11:41:22 2016
@@ -0,0 +1,117 @@
+"""
+Test watchpoint size cases (1-byte, 2-byte, 4-byte).
+Make sure we can watch all bytes, words or double words individually
+when they are packed in a 8-byte region.
+
+"""
+
+from __future__ import print_function
+
+import os, time
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class WatchpointSizeTestCase(TestBase):
+    NO_DEBUG_INFO_TESTCASE = True
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    def setUp(self):
+        # Call super's setUp().
+        TestBase.setUp(self)
+
+        # Source filename.
+        self.source = 'main.c'
+
+        # Output filename.
+        self.exe_name = 'a.out'
+        self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name}
+
+    @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported
+    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
+    @expectedFailureAll(archs=['s390x']) # Read-write watchpoints not supported on SystemZ
+    def test_byte_size_watchpoints_with_byte_selection(self):
+        """Test to selectively watch different bytes in a 8-byte array."""
+        self.run_watchpoint_size_test('byteArray', 8, '1')
+
+    @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported
+    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
+    @expectedFailureAll(archs=['s390x']) # Read-write watchpoints not supported on SystemZ
+    def test_two_byte_watchpoints_with_word_selection(self):
+        """Test to selectively watch different words in an 8-byte word array."""
+        self.run_watchpoint_size_test('wordArray', 4, '2')
+
+    @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported
+    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
+    @expectedFailureAll(archs=['s390x']) # Read-write watchpoints not supported on SystemZ
+    def test_four_byte_watchpoints_with_dword_selection(self):
+        """Test to selectively watch two double words in an 8-byte dword array."""
+        self.run_watchpoint_size_test('dwordArray', 2, '4')
+
+    def run_watchpoint_size_test(self, arrayName, array_size, watchsize):
+        self.build(dictionary=self.d)
+        self.setTearDownCleanup(dictionary=self.d)
+
+        exe = os.path.join(os.getcwd(), self.exe_name)
+        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+        # Detect line number after which we are going to increment arrayName.
+        loc_line = line_number('main.c', '// About to write ' + arrayName)
+
+        # Set a breakpoint on the line detected above.
+        lldbutil.run_break_set_by_file_and_line (self, "main.c",loc_line,
+            num_expected_locations=1, loc_exact=True)
+
+        # Run the program.
+        self.runCmd("run", RUN_SUCCEEDED)
+
+        for i in range(array_size):
+            # We should be stopped again due to the breakpoint.
+            # The stop reason of the thread should be breakpoint.
+            self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+                substrs = ['stopped', 'stop reason = breakpoint'])
+
+            # Set a read_write type watchpoint arrayName
+            watch_loc=arrayName+"[" + str(i) + "]"
+            self.expect("watchpoint set variable -w read_write " + watch_loc,
+                WATCHPOINT_CREATED,
+            substrs = ['Watchpoint created', 'size = ' + watchsize, 'type = rw'])
+
+            # Use the '-v' option to do verbose listing of the watchpoint.
+            # The hit count should be 0 initially.
+            self.expect("watchpoint list -v", substrs = ['hit_count = 0'])
+
+            self.runCmd("process continue")
+
+            # We should be stopped due to the watchpoint.
+            # The stop reason of the thread should be watchpoint.
+            self.expect("thread list", STOPPED_DUE_TO_WATCHPOINT,
+            substrs = ['stopped', 'stop reason = watchpoint'])
+
+            # Use the '-v' option to do verbose listing of the watchpoint.
+            # The hit count should now be 1.
+            self.expect("watchpoint list -v",
+                substrs = ['hit_count = 1'])
+
+            self.runCmd("process continue")
+
+            # We should be stopped due to the watchpoint.
+            # The stop reason of the thread should be watchpoint.
+            self.expect("thread list", STOPPED_DUE_TO_WATCHPOINT,
+            substrs = ['stopped', 'stop reason = watchpoint'])
+
+            # Use the '-v' option to do verbose listing of the watchpoint.
+            # The hit count should now be 1.
+            # Verify hit_count has been updated after value has been read.
+            self.expect("watchpoint list -v",
+                substrs = ['hit_count = 2'])
+
+            # Delete the watchpoint immediately, but set auto-confirm to true first.
+            self.runCmd("settings set auto-confirm true")
+            self.expect("watchpoint delete", substrs = ['All watchpoints removed.'])
+            # Restore the original setting of auto-confirm.
+            self.runCmd("settings clear auto-confirm")
+
+            self.runCmd("process continue")

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/main.c?rev=272916&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/main.c (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/main.c Thu Jun 16 11:41:22 2016
@@ -0,0 +1,66 @@
+//===-- main.c --------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <stdio.h>
+#include <stdint.h>
+
+uint64_t pad0 = 0;
+uint8_t byteArray[8] = {0};
+uint64_t pad1 = 0;
+uint16_t wordArray[4] = {0};
+uint64_t pad2 = 0;
+uint32_t dwordArray[2] = {0};
+
+int main(int argc, char** argv) {
+
+    int i;
+    uint8_t localByte;
+    uint16_t localWord;
+    uint32_t localDword;
+
+    for (i = 0; i < 8; i++)
+    {
+        printf("About to write byteArray[%d] ...\n", i); // About to write byteArray
+        pad0++;
+        byteArray[i]++;
+        pad1++;
+        localByte = byteArray[i]; // Here onwards we should'nt be stopped in loop
+        byteArray[i]++;
+        localByte = byteArray[i];
+    }
+
+    pad0 = 0;
+    pad1 = 0;
+
+    for (i = 0; i < 4; i++)
+    {
+        printf("About to write wordArray[%d] ...\n", i); // About to write wordArray
+        pad0++;
+        wordArray[i]++;
+        pad1++;
+        localWord = wordArray[i]; // Here onwards we should'nt be stopped in loop
+        wordArray[i]++;
+        localWord = wordArray[i];
+    }
+
+    pad0 = 0;
+    pad1 = 0;
+
+    for (i = 0; i < 2; i++)
+    {
+        printf("About to write dwordArray[%d] ...\n", i); // About to write dwordArray
+        pad0++;
+        dwordArray[i]++;
+        pad1++;
+        localDword = dwordArray[i]; // Here onwards we shouldn't be stopped in loop
+        dwordArray[i]++;
+        localDword = dwordArray[i];
+    }
+
+    return 0;
+}

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=272916&r1=272915&r2=272916&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp Thu Jun 16 11:41:22 2016
@@ -566,6 +566,7 @@ NativeRegisterContextLinux_arm64::SetHar
         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 @@ NativeRegisterContextLinux_arm64::SetHar
         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 @@ NativeRegisterContextLinux_arm64::SetHar
     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 @@ NativeRegisterContextLinux_arm64::GetWat
         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 @@ NativeRegisterContextLinux_arm64::GetWat
         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;
 }

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=272916&r1=272915&r2=272916&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h Thu Jun 16 11:41:22 2016
@@ -74,6 +74,9 @@ namespace process_linux {
         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 @@ namespace process_linux {
         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.
         };

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=272916&r1=272915&r2=272916&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Thu Jun 16 11:41:22 2016
@@ -2059,7 +2059,8 @@ ProcessGDBRemote::SetThreadStopInfo (lld
                             {
                                 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);




More information about the lldb-commits mailing list