[Lldb-commits] [lldb] r140836 - in /lldb/trunk: include/lldb/Interpreter/OptionGroupWatchpoint.h source/Commands/CommandObjectFrame.cpp source/Interpreter/OptionGroupWatchpoint.cpp test/functionalities/watchpoint/hello_watchlocation/ test/functionalities/watchpoint/hello_watchlocation/Makefile test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py test/functionalities/watchpoint/hello_watchlocation/main.cpp

Johnny Chen johnny.chen at apple.com
Thu Sep 29 18:08:48 PDT 2011


Author: johnny
Date: Thu Sep 29 20:08:48 2011
New Revision: 140836

URL: http://llvm.org/viewvc/llvm-project?rev=140836&view=rev
Log:
Add an accompanying option to the 'frame variable -w' command to, instead of watching the variable,
watch the location pointed to by the variable.  An example,

(lldb) frame variable -w write -x 1 -g g_char_ptr
(char *) g_char_ptr = 0x0000000100100860 ""...
Watchpoint created: WatchpointLocation 1: addr = 0x100100860 size = 1 state = enabled type = w
    declare @ '/Volumes/data/lldb/svn/trunk/test/functionalities/watchpoint/hello_watchlocation/main.cpp:21'

...

(lldb) c
Process 3936 resuming

...

rocess 3936 stopped
* thread #2: tid = 0x3403, 0x00000001000009b7 a.out`do_bad_thing_with_location(char*, char) + 23 at main.cpp:27, stop reason = watchpoint 1
    frame #0: 0x00000001000009b7 a.out`do_bad_thing_with_location(char*, char) + 23 at main.cpp:27
   24  	do_bad_thing_with_location(char *char_ptr, char new_val)
   25  	{
   26  	    *char_ptr = new_val;
-> 27  	}
   28  	
   29  	uint32_t access_pool (uint32_t flag = 0);
   30  	
(lldb) 

Also add TestWatchLocation.py test to exercise this functionality.

Added:
    lldb/trunk/test/functionalities/watchpoint/hello_watchlocation/
    lldb/trunk/test/functionalities/watchpoint/hello_watchlocation/Makefile
    lldb/trunk/test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py
    lldb/trunk/test/functionalities/watchpoint/hello_watchlocation/main.cpp
Modified:
    lldb/trunk/include/lldb/Interpreter/OptionGroupWatchpoint.h
    lldb/trunk/source/Commands/CommandObjectFrame.cpp
    lldb/trunk/source/Interpreter/OptionGroupWatchpoint.cpp

Modified: lldb/trunk/include/lldb/Interpreter/OptionGroupWatchpoint.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/OptionGroupWatchpoint.h?rev=140836&r1=140835&r2=140836&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/OptionGroupWatchpoint.h (original)
+++ lldb/trunk/include/lldb/Interpreter/OptionGroupWatchpoint.h Thu Sep 29 20:08:48 2011
@@ -55,8 +55,9 @@
             eWatchReadWrite
         } WatchType;
 
-        bool watch_variable;
         WatchType watch_type;
+        uint32_t watch_size;
+        bool watch_variable;
 
     private:
         DISALLOW_COPY_AND_ASSIGN(OptionGroupWatchpoint);

Modified: lldb/trunk/source/Commands/CommandObjectFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectFrame.cpp?rev=140836&r1=140835&r2=140836&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectFrame.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectFrame.cpp Thu Sep 29 20:08:48 2011
@@ -436,7 +436,7 @@
                 }
 
                 // Things have checked out ok...
-                // m_option_watchpoint.watch_mode specifies the mode for watching.
+                // m_option_watchpoint.watch_type specifies the type of watching.
             }
             if (command.GetArgumentCount() > 0)
             {
@@ -532,12 +532,20 @@
                             if (m_option_watchpoint.watch_variable)
                             {
                                 AddressType addr_type;
-                                lldb::addr_t addr = valobj_sp->GetAddressOf(false, &addr_type);
+                                lldb::addr_t addr = 0;
                                 size_t size = 0;
-                                if (addr_type == eAddressTypeLoad) {
-                                    // We're in business.
-                                    // Find out the size of this variable.
-                                    size = valobj_sp->GetByteSize();
+                                if (m_option_watchpoint.watch_size == 0) {
+                                    addr = valobj_sp->GetAddressOf(false, &addr_type);
+                                    if (addr_type == eAddressTypeLoad) {
+                                        // We're in business.
+                                        // Find out the size of this variable.
+                                        size = valobj_sp->GetByteSize();
+                                    }
+                                } else {
+                                    // The '-xsize'/'-x' option means to treat the value object as
+                                    // a pointer and to watch the pointee with the specified size.
+                                    addr = valobj_sp->GetValueAsUnsigned(0);
+                                    size = m_option_watchpoint.watch_size;
                                 }
                                 uint32_t watch_type = m_option_watchpoint.watch_type;
                                 WatchpointLocation *wp_loc = exe_ctx.GetTargetRef().CreateWatchpointLocation(addr, size, watch_type).get();

Modified: lldb/trunk/source/Interpreter/OptionGroupWatchpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionGroupWatchpoint.cpp?rev=140836&r1=140835&r2=140836&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionGroupWatchpoint.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionGroupWatchpoint.cpp Thu Sep 29 20:08:48 2011
@@ -28,11 +28,21 @@
     { 0, NULL, NULL }
 };
 
+static OptionEnumValueElement g_watch_size[] =
+{
+    { 1, "1", "Watch for byte size of 1"},
+    { 2, "2", "Watch for byte size of 2"},
+    { 4, "4", "Watch for byte size of 4"},
+    { 8, "8", "Watch for byte size of 8"},
+    { 0, NULL, NULL }
+};
+
 // if you add any options here, remember to update the counters in OptionGroupWatchpoint::GetNumDefinitions()
 static OptionDefinition
 g_option_table[] =
 {
-    { LLDB_OPT_SET_1, false, "watch", 'w', required_argument, g_watch_type, 0, eArgTypeWatchType, "Determine how to watch a memory location (read, write, or read/write)."}
+    { LLDB_OPT_SET_1, false, "watch", 'w', required_argument, g_watch_type, 0, eArgTypeWatchType, "Determine how to watch a variable (read, write, or read/write)."},
+    { LLDB_OPT_SET_1, false, "xsize", 'x', required_argument, g_watch_size, 0, eArgTypeByteSize, "Number of bytes to use to watch a location (1, 2, 4, or 8)."}
 };
 
 
@@ -61,6 +71,14 @@
                 error.SetErrorStringWithFormat("Invalid option arg for '-w': '%s'.\n", option_arg);
             break;
         }
+        case 'x': {
+            bool success = false;
+            OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
+            watch_size = (WatchType) Args::StringToOptionEnum(option_arg, enum_values, 0, &success);
+            if (!success)
+                error.SetErrorStringWithFormat("Invalid option arg for '-x': '%s'.\n", option_arg);
+            break;
+        }
         default:
             error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
             break;
@@ -74,6 +92,7 @@
 {
     watch_variable = false;
     watch_type     = eWatchInvalid;
+    watch_size     = 0;
 }
 
 

Added: lldb/trunk/test/functionalities/watchpoint/hello_watchlocation/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/watchpoint/hello_watchlocation/Makefile?rev=140836&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/watchpoint/hello_watchlocation/Makefile (added)
+++ lldb/trunk/test/functionalities/watchpoint/hello_watchlocation/Makefile Thu Sep 29 20:08:48 2011
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py?rev=140836&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py (added)
+++ lldb/trunk/test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py Thu Sep 29 20:08:48 2011
@@ -0,0 +1,92 @@
+"""
+Test lldb watchpoint that uses '-x size' to watch a pointed location with size.
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+
+class HelloWatchLocationTestCase(TestBase):
+
+    mydir = os.path.join("functionalities", "watchpoint", "hello_watchlocation")
+
+    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+    def test_hello_watchlocation_with_dsym(self):
+        """Test watching a location with '-x size' option."""
+        self.buildDsym(dictionary=self.d)
+        self.setTearDownCleanup(dictionary=self.d)
+        self.hello_watchlocation()
+
+    def test_hello_watchlocation_with_dwarf(self):
+        """Test watching a location with '-x size' option."""
+        self.buildDwarf(dictionary=self.d)
+        self.setTearDownCleanup(dictionary=self.d)
+        self.hello_watchlocation()
+
+    def setUp(self):
+        # Call super's setUp().
+        TestBase.setUp(self)
+        # Our simple source filename.
+        self.source = 'main.cpp'
+        # Find the line number to break inside main().
+        self.line = line_number(self.source, '// Set break point at this line.')
+        # This is for verifying that watch location works.
+        self.violating_func = "do_bad_thing_with_location";
+        # Build dictionary to have unique executable names for each test method.
+        self.exe_name = self.testMethodName
+        self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name}
+
+    def hello_watchlocation(self):
+        """Test watching a location with '-x size' option."""
+        exe = os.path.join(os.getcwd(), self.exe_name)
+        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+        # Add a breakpoint to set a watchpoint when stopped on the breakpoint.
+        self.expect("breakpoint set -l %d" % self.line, BREAKPOINT_CREATED,
+            startstr = "Breakpoint created: 1: file ='%s', line = %d, locations = 1" %
+                       (self.source, self.line))
+
+        # Run the program.
+        self.runCmd("run", RUN_SUCCEEDED)
+
+        # 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'])
+
+        # Now let's set a write-type watchpoint pointed to by 'g_char_ptr'.
+        # The main.cpp, by design, misbehaves by not following the agreed upon
+        # protocol of using a mutex while accessing the global pool and by not
+        # incrmenting the global pool by 2.
+        self.expect("frame variable -w write -x 1 -g g_char_ptr", WATCHPOINT_CREATED,
+            substrs = ['Watchpoint created', 'size = 1', 'type = w'])
+
+        # 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 again due to the watchpoint (write type), but
+        # only once.  The stop reason of the thread should be watchpoint.
+        self.expect("thread list", STOPPED_DUE_TO_WATCHPOINT,
+            substrs = ['stopped',
+                       'stop reason = watchpoint',
+                       self.violating_func])
+
+        # 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("thread backtrace all")
+
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()

Added: lldb/trunk/test/functionalities/watchpoint/hello_watchlocation/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/watchpoint/hello_watchlocation/main.cpp?rev=140836&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/watchpoint/hello_watchlocation/main.cpp (added)
+++ lldb/trunk/test/functionalities/watchpoint/hello_watchlocation/main.cpp Thu Sep 29 20:08:48 2011
@@ -0,0 +1,98 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C includes
+#include <pthread.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+pthread_t g_thread_1 = NULL;
+pthread_t g_thread_2 = NULL;
+pthread_t g_thread_3 = NULL;
+
+char *g_char_ptr = NULL;
+
+void
+do_bad_thing_with_location(char *char_ptr, char new_val)
+{
+    *char_ptr = new_val;
+}
+
+uint32_t access_pool (uint32_t flag = 0);
+
+uint32_t
+access_pool (uint32_t flag)
+{
+    static pthread_mutex_t g_access_mutex = PTHREAD_MUTEX_INITIALIZER;
+    if (flag == 0)
+        ::pthread_mutex_lock (&g_access_mutex);
+
+    char old_val = *g_char_ptr;
+    if (flag != 0)
+        do_bad_thing_with_location(g_char_ptr, old_val + 1);
+
+    if (flag == 0)
+        ::pthread_mutex_unlock (&g_access_mutex);
+    return *g_char_ptr;
+}
+
+void *
+thread_func (void *arg)
+{
+    uint32_t thread_index = *((uint32_t *)arg);
+    printf ("%s (thread index = %u) startng...\n", __FUNCTION__, thread_index);
+
+    uint32_t count = 0;
+    uint32_t val;
+    while (count++ < 15)
+    {
+        // random micro second sleep from zero to 3 seconds
+        int usec = ::rand() % 3000000;
+        printf ("%s (thread = %u) doing a usleep (%d)...\n", __FUNCTION__, thread_index, usec);
+        ::usleep (usec);
+        
+        if (count < 7)
+            val = access_pool ();
+        else
+            val = access_pool (1);
+                
+        printf ("%s (thread = %u) after usleep access_pool returns %d (count=%d)...\n", __FUNCTION__, thread_index, val, count);
+    }
+    printf ("%s (thread index = %u) exiting...\n", __FUNCTION__, thread_index);
+    return NULL;
+}
+
+
+int main (int argc, char const *argv[])
+{
+    int err;
+    void *thread_result = NULL;
+    uint32_t thread_index_1 = 1;
+    uint32_t thread_index_2 = 2;
+    uint32_t thread_index_3 = 3;
+
+    g_char_ptr = (char *)malloc (1);
+    *g_char_ptr = 0;
+
+    // Create 3 threads
+    err = ::pthread_create (&g_thread_1, NULL, thread_func, &thread_index_1);
+    err = ::pthread_create (&g_thread_2, NULL, thread_func, &thread_index_2);
+    err = ::pthread_create (&g_thread_3, NULL, thread_func, &thread_index_3);
+
+    printf ("Before turning all three threads loose...\n"); // Set break point at this line.
+
+    // Join all of our threads
+    err = ::pthread_join (g_thread_1, &thread_result);
+    err = ::pthread_join (g_thread_2, &thread_result);
+    err = ::pthread_join (g_thread_3, &thread_result);
+
+    return 0;
+}





More information about the lldb-commits mailing list