[Lldb-commits] [lldb] r153273 - in /lldb/trunk/tools/debugserver/source/MacOSX/arm: DNBArchImpl.cpp DNBArchImpl.h

Johnny Chen johnny.chen at apple.com
Thu Mar 22 13:04:07 PDT 2012


Author: johnny
Date: Thu Mar 22 15:04:07 2012
New Revision: 153273

URL: http://llvm.org/viewvc/llvm-project?rev=153273&view=rev
Log:
Previous check-ins allow to hit the arm hardware watchpoint, with a workaound to handle the issue
that the inferior cannot execute past the watchpoint-triggering instruction.

The solution is disable the watchpoint before resuming the inferior and make it hardware single step;
when the inferior stops again due to single step, re-enable the watchpoint and disable the single step
to make the inferior able to continue again without obstacle.

rdar://problem/9667960

Modified:
    lldb/trunk/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp
    lldb/trunk/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h

Modified: lldb/trunk/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp?rev=153273&r1=153272&r2=153273&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp Thu Mar 22 15:04:07 2012
@@ -275,11 +275,6 @@
         DNBLogThreadedIf(LOG_STEP, "BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { 0x%8.8x, 0x%8.8x }",
             i, i, dbg.__bvr[i], dbg.__bcr[i],
             i, i, dbg.__wvr[i], dbg.__wcr[i]);
-        /*
-        printf("BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { 0x%8.8x, 0x%8.8x }\n",
-               i, i, dbg.__bvr[i], dbg.__bcr[i],
-               i, i, dbg.__wvr[i], dbg.__wcr[i]);
-        */
     }
 }
 
@@ -365,20 +360,30 @@
         }
     }
 
-    // Disable the triggered watchpoint temporarily because we resume.
+    // Disable the triggered watchpoint temporarily before we resume.
+    // Plus, we try to enable hardware single step to execute past the instruction which triggered our watchpoint.
     if (m_watchpoint_did_occur)
     {
-        if (m_watchpoint_hw_index >= 0) {
+        if (m_watchpoint_hw_index >= 0)
+        {
             DisableHardwareWatchpoint(m_watchpoint_hw_index);
             DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() DisableHardwareWatchpoint(%d) called",
                              m_watchpoint_hw_index);
-            // Reset the two watchpoint member variables.
-            m_watchpoint_did_occur = false;
-            m_watchpoint_hw_index = -1;
-            /*
-            printf("DNBArchMachARM::ThreadWillResume() DisableHardwareWatchpoint(%d) called",
-                   m_watchpoint_hw_index);
-            */
+
+            // Enable hardware single step to move past the watchpoint-triggering instruction.
+            m_watchpoint_resume_single_step_enabled = (EnableHardwareSingleStep(true) == KERN_SUCCESS);
+
+            // If we are not able to enable single step to move past the watchpoint-triggering instruction,
+            // at least we should reset the two watchpoint member variables so that the next time around
+            // this callback function is invoked, the enclosing logical branch is skipped.
+            if (!m_watchpoint_resume_single_step_enabled) {
+                // Reset the two watchpoint member variables.
+                m_watchpoint_did_occur = false;
+                m_watchpoint_hw_index = -1;
+                DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() failed to enable single step");
+            }
+            else
+                DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() succeeded to enable single step");
         }
     }
 }
@@ -390,6 +395,30 @@
 
     m_state.InvalidateRegisterSetState (e_regSetALL);
 
+    if (m_watchpoint_resume_single_step_enabled)
+    {
+        // Great!  We now disable the hardware single step as well as re-enable the hardware watchpoint.
+        // See also ThreadWillResume().
+        if (EnableHardwareSingleStep(false) == KERN_SUCCESS)
+        {
+            if (m_watchpoint_did_occur && m_watchpoint_hw_index >= 0)
+            {
+                EnableHardwareWatchpoint(m_watchpoint_hw_index);
+                m_watchpoint_resume_single_step_enabled = false;
+                m_watchpoint_did_occur = false;
+                m_watchpoint_hw_index = -1;
+            }
+            else
+            {
+                DNBLogError("internal error detected: m_watchpoint_resume_step_enabled is true but (m_watchpoint_did_occur && m_watchpoint_hw_index >= 0) does not hold!");
+            }
+        }
+        else
+        {
+            DNBLogError("internal error detected: m_watchpoint_resume_step_enabled is true but unable to disable single step!");
+        }
+    }
+
     // Are we stepping a single instruction?
     if (GetGPRState(true) == KERN_SUCCESS)
     {
@@ -489,16 +518,11 @@
 bool
 DNBArchMachARM::NotifyException(MachException::Data& exc)
 {
-    //printf("exc.ex_type=%d\n", exc.exc_type);
     switch (exc.exc_type)
     {
         default:
             break;
         case EXC_BREAKPOINT:
-            /*
-            for (size_t i = 0; i < exc.exc_data.size(); ++i)
-                printf("exc.exc_data[%lu]=%llu\n", i, exc.exc_data[i]);
-            */
             if (exc.exc_data.size() == 2 && exc.exc_data[0] == EXC_ARM_DA_DEBUG)
             {
                 // exc_code = EXC_ARM_DA_DEBUG
@@ -507,11 +531,9 @@
                 // If yes, retrieve the exc_sub_code as the data break address.
                 if (!HasWatchpointOccurred())
                     break;
-                //printf("Info -- Debug Status and Control Register indicates hardware watchpoint occurred!\n");
 
                 // The data break address is passed as exc_data[1].
                 nub_addr_t addr = exc.exc_data[1];
-                //printf("Info -- from mach exception: exc.exc_data[1]=0x%x\n", addr);
                 // Find the hardware index with the side effect of possibly massaging the
                 // addr to return the starting address as seen from the debugger side.
                 uint32_t hw_index = GetHardwareWatchpointHit(addr);
@@ -519,10 +541,8 @@
                 {
                     m_watchpoint_did_occur = true;
                     m_watchpoint_hw_index = hw_index;
-                    //printf("Setting exc.exc_data[1] to %u\n", addr);
                     exc.exc_data[1] = addr;
                     // Piggyback the hw_index in the exc.data.
-                    //printf("Setting exc.exc_data[2] to %u\n", hw_index);
                     exc.exc_data.push_back(hw_index);
                 }
 
@@ -2258,7 +2278,6 @@
             }
         }
     }
-    //printf("g_num_supported_hw_watchpoints=%u\n", g_num_supported_hw_watchpoints);
     return g_num_supported_hw_watchpoints;
 }
 
@@ -2367,7 +2386,6 @@
 uint32_t
 DNBArchMachARM::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write)
 {
-    //printf("DNBArchMachARM::EnableHardwareWatchpoint(addr = 0x%8.8llx, size = %zu, read = %u, write = %u)\n", (uint64_t)addr, size, read, write);
     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint(addr = 0x%8.8llx, size = %zu, read = %u, write = %u)", (uint64_t)addr, size, read, write);
 
     const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
@@ -2428,7 +2446,6 @@
         // See if we found an available hw watchpoint slot above
         if (i < num_hw_watchpoints)
         {
-            //printf("Found an available watchpoint slot: %u\nBefore setting WRP...\n", i);
             //DumpDBGState(m_state.dbg);
 
             // Make the byte_mask into a valid Byte Address Select mask
@@ -2442,7 +2459,6 @@
                                     WCR_ENABLE;                 // Enable this watchpoint;
 
             kret = SetDBGState();
-            //printf("After setting WRP for slot: %u ...\n", i);
             //DumpDBGState(m_state.dbg);
 
             DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() SetDBGState() => 0x%8.8x.", kret);
@@ -2468,7 +2484,7 @@
     {
         if (hw_index < num_hw_points)
         {
-            m_state.dbg.__wcr[hw_index] &= ~((nub_addr_t)0x1);
+            m_state.dbg.__wcr[hw_index] |= (nub_addr_t)WCR_ENABLE;
             DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x  WCR%u = 0x%8.8x",
                     hw_index,
                     hw_index,
@@ -2495,7 +2511,7 @@
     {
         if (hw_index < num_hw_points)
         {
-            m_state.dbg.__wcr[hw_index] &= ~((nub_addr_t)0x1);
+            m_state.dbg.__wcr[hw_index] &= ~((nub_addr_t)WCR_ENABLE);
             DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::DisableHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x  WCR%u = 0x%8.8x",
                     hw_index,
                     hw_index,
@@ -2532,16 +2548,9 @@
 int32_t
 LowestBitSet(uint32_t val)
 {
-    //printf("LowestBitSet(): val=0x%x)\n", val);
-    /*
-    for (unsigned i = 0; i < 4; ++i)
-        printf("bit %u = %u\n", i, bit(val, i));
-    */
     for (unsigned i = 0; i < 4; ++i) {
-        if (bit(val, i)) {
-            //printf("LowestBitSet() returning %d\n", i);
+        if (bit(val, i))
             return i;
-        }
     }
     return -1;
 }
@@ -2554,7 +2563,6 @@
 {
     // Read the debug state
     kern_return_t kret = GetDBGState(true);
-    //printf("GetHardwareWatchpointHit: dumping the debug state....\n");
     //DumpDBGState(m_state.dbg);
     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", kret);
     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::GetHardwareWatchpointHit() addr = 0x%llx", (uint64_t)addr);
@@ -2568,10 +2576,6 @@
         for (i = 0; i < num; ++i)
         {
             nub_addr_t wp_addr = GetWatchAddress(debug_state, i);
-            /*
-            printf("DNBArchMachARM::GetHardwareWatchpointHit() slot: %u (addr = 0x%llx).\n",
-                   i, (uint64_t)wp_addr);
-            */
             DNBLogThreadedIf(LOG_WATCHPOINTS,
                              "DNBArchMachARM::GetHardwareWatchpointHit() slot: %u (addr = 0x%llx).",
                              i, (uint64_t)wp_addr);
@@ -2584,10 +2588,6 @@
 
                 // Compute the starting address (from the point of view of the debugger).
                 addr = wp_addr + LowestBitSet(byte_mask);
-                /*
-                printf("DNBArchMachARM::GetHardwareWatchpointHit() found => %u (wp_addr = 0x%llx, addr = 0x%llx).\n",
-                       i, (uint64_t)wp_addr, (uint64_t)addr);
-                */
                 return i;
             }
         }
@@ -2605,13 +2605,11 @@
 {
     uint32_t register_DBGDSCR;
     asm("mrc p14, 0, %0, c0, c1, 0" : "=r" (register_DBGDSCR));
-    //printf("ClearWatchpointOccurred: register_DBGDSCR: 0x%x, bits(5, 2): 0x%x\n", register_DBGDSCR, bits(register_DBGDSCR, 5, 2));
     if (bits(register_DBGDSCR, 5, 2) == WATCHPOINT_OCCURRED)
     {
         uint32_t mask = ~(0xF << 2);
         register_DBGDSCR &= mask;
         asm("mcr p14, 0, %0, c0, c1, 0" : "=r" (register_DBGDSCR));
-        //printf("ClearWatchpointOccurred: cleared bits(5,2) of register_DBGDSCR\n");
     }
     return;
 }
@@ -2626,14 +2624,11 @@
 {
     uint32_t register_DBGDSCR;
     asm("mrc p14, 0, %0, c0, c1, 0" : "=r" (register_DBGDSCR));
-    //printf("HasWatchpointOccurred: register_DBGDSCR: 0x%x, bits(5, 2): 0x%x\n", register_DBGDSCR, bits(register_DBGDSCR, 5, 2));
     return (bits(register_DBGDSCR, 5, 2) == WATCHPOINT_OCCURRED);
 }
 
-// FIXME: IsWatchpointHit() currently returns the first enabled watchpoint,
-//        instead of finding the watchpoint that actually triggered.
 bool
-DNBArchMachARM::IsWatchpointHit(const DBG &debug_state, uint32_t hw_index)
+DNBArchMachARM::IsWatchpointEnabled(const DBG &debug_state, uint32_t hw_index)
 {
     // Watchpoint Control Registers, bitfield definitions
     // ...

Modified: lldb/trunk/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h?rev=153273&r1=153272&r2=153273&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h Thu Mar 22 15:04:07 2012
@@ -37,7 +37,8 @@
         m_sw_single_step_itblock_break_count(0),
         m_last_decode_pc(INVALID_NUB_ADDRESS),
         m_watchpoint_hw_index(-1),
-        m_watchpoint_did_occur(false)
+        m_watchpoint_did_occur(false),
+        m_watchpoint_resume_single_step_enabled(false)
     {
         memset(&m_dbg_save, 0, sizeof(m_dbg_save));
 #if defined (USE_ARM_DISASSEMBLER_FRAMEWORK)
@@ -242,7 +243,7 @@
     // Helper functions for watchpoint implementaions.
     static void ClearWatchpointOccurred();
     static bool HasWatchpointOccurred();
-    static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index);
+    static bool IsWatchpointEnabled(const DBG &debug_state, uint32_t hw_index);
     static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index);
 
 protected:
@@ -262,10 +263,10 @@
 #endif
     nub_addr_t      m_last_decode_pc;
 
-    // The following two member variables should be updated atomically.
+    // The following member variables should be updated atomically.
     int32_t         m_watchpoint_hw_index;
     bool            m_watchpoint_did_occur;
-
+    bool            m_watchpoint_resume_single_step_enabled;
 };
 
 #endif    // #if defined (__arm__)





More information about the lldb-commits mailing list