[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