[Lldb-commits] [lldb] r141217 - in /lldb/trunk: include/lldb/Target/Target.h source/Commands/CommandObjectWatchpoint.cpp source/Commands/CommandObjectWatchpoint.h source/Target/Target.cpp test/functionalities/watchpoint/watchpoint_commands/TestWatchpointCommands.py test/functionalities/watchpoint/watchpoint_commands/main.c test/python_api/watchpoint/TestWatchpointIgnoreCount.py
Johnny Chen
johnny.chen at apple.com
Wed Oct 5 14:35:46 PDT 2011
Author: johnny
Date: Wed Oct 5 16:35:46 2011
New Revision: 141217
URL: http://llvm.org/viewvc/llvm-project?rev=141217&view=rev
Log:
Add capability to set ignore count for watchpoint on the command line:
watchpoint ignore -i <count> [<watchpt-id | watchpt-id-list>]
Add tests of watchpoint ignore_count for command line as well as API.
Added:
lldb/trunk/test/python_api/watchpoint/TestWatchpointIgnoreCount.py
Modified:
lldb/trunk/include/lldb/Target/Target.h
lldb/trunk/source/Commands/CommandObjectWatchpoint.cpp
lldb/trunk/source/Commands/CommandObjectWatchpoint.h
lldb/trunk/source/Target/Target.cpp
lldb/trunk/test/functionalities/watchpoint/watchpoint_commands/TestWatchpointCommands.py
lldb/trunk/test/functionalities/watchpoint/watchpoint_commands/main.c
Modified: lldb/trunk/include/lldb/Target/Target.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Target.h?rev=141217&r1=141216&r2=141217&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Target.h (original)
+++ lldb/trunk/include/lldb/Target/Target.h Wed Oct 5 16:35:46 2011
@@ -341,6 +341,9 @@
EnableAllWatchpointLocations (bool end_to_end = true);
bool
+ IgnoreAllWatchpointLocations (uint32_t ignore_count);
+
+ bool
DisableWatchpointLocationByID (lldb::watch_id_t watch_id);
bool
@@ -349,6 +352,9 @@
bool
RemoveWatchpointLocationByID (lldb::watch_id_t watch_id);
+ bool
+ IgnoreWatchpointLocationByID (lldb::watch_id_t watch_id, uint32_t ignore_count);
+
void
ModulesDidLoad (ModuleList &module_list);
Modified: lldb/trunk/source/Commands/CommandObjectWatchpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectWatchpoint.cpp?rev=141217&r1=141216&r2=141217&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectWatchpoint.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectWatchpoint.cpp Wed Oct 5 16:35:46 2011
@@ -155,16 +155,19 @@
CommandObjectSP enable_command_object (new CommandObjectWatchpointEnable (interpreter));
CommandObjectSP disable_command_object (new CommandObjectWatchpointDisable (interpreter));
CommandObjectSP delete_command_object (new CommandObjectWatchpointDelete (interpreter));
+ CommandObjectSP ignore_command_object (new CommandObjectWatchpointIgnore (interpreter));
list_command_object->SetCommandName ("watchpoint list");
enable_command_object->SetCommandName("watchpoint enable");
disable_command_object->SetCommandName("watchpoint disable");
delete_command_object->SetCommandName("watchpoint delete");
+ ignore_command_object->SetCommandName("watchpoint ignore");
status = LoadSubCommand ("list", list_command_object);
status = LoadSubCommand ("enable", enable_command_object);
status = LoadSubCommand ("disable", disable_command_object);
status = LoadSubCommand ("delete", delete_command_object);
+ status = LoadSubCommand ("ignore", ignore_command_object);
}
CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint()
@@ -555,3 +558,138 @@
return result.Succeeded();
}
+//-------------------------------------------------------------------------
+// CommandObjectWatchpointIgnore::CommandOptions
+//-------------------------------------------------------------------------
+#pragma mark Ignore::CommandOptions
+
+CommandObjectWatchpointIgnore::CommandOptions::CommandOptions(CommandInterpreter &interpreter) :
+ Options (interpreter),
+ m_ignore_count (0)
+{
+}
+
+CommandObjectWatchpointIgnore::CommandOptions::~CommandOptions ()
+{
+}
+
+OptionDefinition
+CommandObjectWatchpointIgnore::CommandOptions::g_option_table[] =
+{
+ { LLDB_OPT_SET_ALL, true, "ignore-count", 'i', required_argument, NULL, NULL, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping." },
+ { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL }
+};
+
+const OptionDefinition*
+CommandObjectWatchpointIgnore::CommandOptions::GetDefinitions ()
+{
+ return g_option_table;
+}
+
+Error
+CommandObjectWatchpointIgnore::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg)
+{
+ Error error;
+ char short_option = (char) m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'i':
+ {
+ m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
+ if (m_ignore_count == UINT32_MAX)
+ error.SetErrorStringWithFormat ("Invalid ignore count '%s'.\n", option_arg);
+ }
+ break;
+ default:
+ error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
+ break;
+ }
+
+ return error;
+}
+
+void
+CommandObjectWatchpointIgnore::CommandOptions::OptionParsingStarting ()
+{
+ m_ignore_count = 0;
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectWatchpointIgnore
+//-------------------------------------------------------------------------
+#pragma mark Ignore
+
+CommandObjectWatchpointIgnore::CommandObjectWatchpointIgnore(CommandInterpreter &interpreter) :
+ CommandObject(interpreter,
+ "watchpoint ignore",
+ "Set ignore count on the specified watchpoint(s). If no watchpoints are specified, set them all.",
+ NULL),
+ m_options (interpreter)
+{
+ CommandArgumentEntry arg;
+ CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange);
+ // Add the entry for the first argument for this command to the object's arguments vector.
+ m_arguments.push_back(arg);
+}
+
+CommandObjectWatchpointIgnore::~CommandObjectWatchpointIgnore()
+{
+}
+
+Options *
+CommandObjectWatchpointIgnore::GetOptions ()
+{
+ return &m_options;
+}
+
+bool
+CommandObjectWatchpointIgnore::Execute(Args& args, CommandReturnObject &result)
+{
+ Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+ if (!CheckTargetForWatchpointOperations(target, result))
+ return false;
+
+ Mutex::Locker locker;
+ target->GetWatchpointLocationList().GetListMutex(locker);
+
+ const WatchpointLocationList &watchpoints = target->GetWatchpointLocationList();
+
+ size_t num_watchpoints = watchpoints.GetSize();
+
+ if (num_watchpoints == 0)
+ {
+ result.AppendError("No watchpoints exist to be ignored.");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ if (args.GetArgumentCount() == 0)
+ {
+ target->IgnoreAllWatchpointLocations(m_options.m_ignore_count);
+ result.AppendMessageWithFormat("All watchpoints ignored. (%lu watchpoints)\n", num_watchpoints);
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ // Particular watchpoints selected; ignore them.
+ std::vector<uint32_t> wp_ids;
+ if (!VerifyWatchpointIDs(args, wp_ids))
+ {
+ result.AppendError("Invalid watchpoints specification.");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ int count = 0;
+ const size_t size = wp_ids.size();
+ for (size_t i = 0; i < size; ++i)
+ if (target->IgnoreWatchpointLocationByID(wp_ids[i], m_options.m_ignore_count))
+ ++count;
+ result.AppendMessageWithFormat("%d watchpoints ignored.\n",count);
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+
+ return result.Succeeded();
+}
+
Modified: lldb/trunk/source/Commands/CommandObjectWatchpoint.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectWatchpoint.h?rev=141217&r1=141216&r2=141217&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectWatchpoint.h (original)
+++ lldb/trunk/source/Commands/CommandObjectWatchpoint.h Wed Oct 5 16:35:46 2011
@@ -140,6 +140,56 @@
private:
};
+//-------------------------------------------------------------------------
+// CommandObjectWatchpointIgnore
+//-------------------------------------------------------------------------
+
+class CommandObjectWatchpointIgnore : public CommandObject
+{
+public:
+ CommandObjectWatchpointIgnore (CommandInterpreter &interpreter);
+
+ virtual
+ ~CommandObjectWatchpointIgnore ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandReturnObject &result);
+
+ virtual Options *
+ GetOptions ();
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions (CommandInterpreter &interpreter);
+
+ virtual
+ ~CommandOptions ();
+
+ virtual Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg);
+
+ void
+ OptionParsingStarting ();
+
+ const OptionDefinition *
+ GetDefinitions ();
+
+ // Options table: Required for subclasses of Options.
+
+ static OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+
+ uint32_t m_ignore_count;
+ };
+
+private:
+ CommandOptions m_options;
+};
+
} // namespace lldb_private
#endif // liblldb_CommandObjectWatchpoint_h_
Modified: lldb/trunk/source/Target/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=141217&r1=141216&r2=141217&view=diff
==============================================================================
--- lldb/trunk/source/Target/Target.cpp (original)
+++ lldb/trunk/source/Target/Target.cpp Wed Oct 5 16:35:46 2011
@@ -672,6 +672,30 @@
return true; // Success!
}
+// Assumption: Caller holds the list mutex lock for m_watchpoint_location_list
+// during these operations.
+bool
+Target::IgnoreAllWatchpointLocations (uint32_t ignore_count)
+{
+ LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+ if (log)
+ log->Printf ("Target::%s\n", __FUNCTION__);
+
+ if (!ProcessIsValid())
+ return false;
+
+ size_t num_watchpoints = m_watchpoint_location_list.GetSize();
+ for (size_t i = 0; i < num_watchpoints; ++i)
+ {
+ WatchpointLocationSP wp_loc_sp = m_watchpoint_location_list.GetByIndex(i);
+ if (!wp_loc_sp)
+ return false;
+
+ wp_loc_sp->SetIgnoreCount(ignore_count);
+ }
+ return true; // Success!
+}
+
// Assumption: Caller holds the list mutex lock for m_watchpoint_location_list.
bool
Target::DisableWatchpointLocationByID (lldb::watch_id_t watch_id)
@@ -734,6 +758,26 @@
return false;
}
+// Assumption: Caller holds the list mutex lock for m_watchpoint_location_list.
+bool
+Target::IgnoreWatchpointLocationByID (lldb::watch_id_t watch_id, uint32_t ignore_count)
+{
+ LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+ if (log)
+ log->Printf ("Target::%s (watch_id = %i)\n", __FUNCTION__, watch_id);
+
+ if (!ProcessIsValid())
+ return false;
+
+ WatchpointLocationSP wp_loc_sp = m_watchpoint_location_list.FindByID (watch_id);
+ if (wp_loc_sp)
+ {
+ wp_loc_sp->SetIgnoreCount(ignore_count);
+ return true;
+ }
+ return false;
+}
+
ModuleSP
Target::GetExecutableModule ()
{
Modified: lldb/trunk/test/functionalities/watchpoint/watchpoint_commands/TestWatchpointCommands.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/watchpoint/watchpoint_commands/TestWatchpointCommands.py?rev=141217&r1=141216&r2=141217&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/watchpoint/watchpoint_commands/TestWatchpointCommands.py (original)
+++ lldb/trunk/test/functionalities/watchpoint/watchpoint_commands/TestWatchpointCommands.py Wed Oct 5 16:35:46 2011
@@ -52,6 +52,19 @@
self.delete_read_write_watchpoint()
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ def test_rw_watchpoint_set_ignore_count_with_dsym(self):
+ """Test watchpoint ignore count and expect to not to stop at all."""
+ self.buildDsym(dictionary=self.d)
+ self.setTearDownCleanup(dictionary=self.d)
+ self.ignore_read_write_watchpoint()
+
+ def test_rw_watchpoint_set_ignore_count_with_dwarf(self):
+ """Test watchpoint ignore count and expect to not to stop at all."""
+ self.buildDwarf(dictionary=self.d)
+ self.setTearDownCleanup(dictionary=self.d)
+ self.ignore_read_write_watchpoint()
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
def test_rw_disable_after_first_stop_with_dsym(self):
"""Test read_write watchpoint but disable it after the first stop."""
self.buildDsym(dictionary=self.d)
@@ -175,6 +188,52 @@
self.expect("process status",
substrs = ['exited'])
+ def ignore_read_write_watchpoint(self):
+ """Test watchpoint ignore count and expect to not to stop at all."""
+ 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 read_write-type watchpoint for 'global'.
+ # There should be two watchpoint hits (see main.c).
+ self.expect("frame variable -w read_write -g -L global", WATCHPOINT_CREATED,
+ substrs = ['Watchpoint created', 'size = 4', 'type = rw',
+ '%s:%d' % (self.source, self.decl)])
+
+ # Set the ignore count of the watchpoint immediately.
+ self.expect("watchpoint ignore -i 2",
+ substrs = ['All watchpoints ignored.'])
+
+ # Use the '-v' option to do verbose listing of the watchpoint.
+ # Expect to find an ignore_count of 2.
+ self.expect("watchpoint list -v",
+ substrs = ['hit_count = 0', 'ignore_count = 2'])
+
+ self.runCmd("process continue")
+
+ # There should be no more watchpoint hit and the process status should
+ # be 'exited'.
+ self.expect("process status",
+ substrs = ['exited'])
+
+ # Use the '-v' option to do verbose listing of the watchpoint.
+ # Expect to find a hit_count of 2 as well.
+ self.expect("watchpoint list -v",
+ substrs = ['hit_count = 2', 'ignore_count = 2'])
+
def read_write_watchpoint_disable_after_first_stop(self):
"""Do read_write watchpoint but disable it after the first stop."""
exe = os.path.join(os.getcwd(), self.exe_name)
Modified: lldb/trunk/test/functionalities/watchpoint/watchpoint_commands/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/watchpoint/watchpoint_commands/main.c?rev=141217&r1=141216&r2=141217&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/watchpoint/watchpoint_commands/main.c (original)
+++ lldb/trunk/test/functionalities/watchpoint/watchpoint_commands/main.c Wed Oct 5 16:35:46 2011
@@ -15,7 +15,7 @@
int local = 0;
printf("&global=%p\n", &global);
printf("about to write to 'global'...\n"); // Set break point at this line.
- // When stopped, watch 'global' for write.
+ // When stopped, watch 'global'.
global = 20;
local += argc;
++local; // Set 2nd break point for disable_then_enable test case.
Added: lldb/trunk/test/python_api/watchpoint/TestWatchpointIgnoreCount.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/watchpoint/TestWatchpointIgnoreCount.py?rev=141217&view=auto
==============================================================================
--- lldb/trunk/test/python_api/watchpoint/TestWatchpointIgnoreCount.py (added)
+++ lldb/trunk/test/python_api/watchpoint/TestWatchpointIgnoreCount.py Wed Oct 5 16:35:46 2011
@@ -0,0 +1,102 @@
+"""
+Use lldb Python SBWatchpointLocation API to set the ignore count.
+"""
+
+import os, time
+import re
+import unittest2
+import lldb, lldbutil
+from lldbtest import *
+
+class WatchpointIgnoreCountTestCase(TestBase):
+
+ mydir = os.path.join("python_api", "watchpoint")
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+ # Our simple source filename.
+ self.source = 'main.c'
+ # Find the line number to break inside main().
+ self.line = line_number(self.source, '// Set break point at this line.')
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ @python_api_test
+ def test_set_watch_loc_ignore_count_with_dsym(self):
+ """Test SBWatchpointLocation.SetIgnoreCount() API."""
+ self.buildDsym()
+ self.do_watchpoint_location_ignore_count()
+
+ @python_api_test
+ def test_set_watch_loc_ignore_count_with_dwarf(self):
+ """Test SBWatchpointLocation.SetIgnoreCount() API."""
+ self.buildDwarf()
+ self.do_watchpoint_location_ignore_count()
+
+ def do_watchpoint_location_ignore_count(self):
+ """Test SBWatchpointLocation.SetIgnoreCount() API."""
+ exe = os.path.join(os.getcwd(), "a.out")
+
+ # Create a target by the debugger.
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target, VALID_TARGET)
+
+ # Create a breakpoint on main.c in order to set our watchpoint later.
+ breakpoint = target.BreakpointCreateByLocation(self.source, self.line)
+ self.assertTrue(breakpoint and
+ breakpoint.GetNumLocations() == 1,
+ VALID_BREAKPOINT)
+
+ # Now launch the process, and do not stop at the entry point.
+ process = target.LaunchSimple(None, None, os.getcwd())
+
+ # We should be stopped due to the breakpoint. Get frame #0.
+ process = target.GetProcess()
+ self.assertTrue(process.GetState() == lldb.eStateStopped,
+ PROCESS_STOPPED)
+ thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
+ frame0 = thread.GetFrameAtIndex(0)
+
+ # Watch 'global' for read and write.
+ value = frame0.WatchValue('global',
+ lldb.eValueTypeVariableGlobal,
+ lldb.LLDB_WATCH_TYPE_READ|lldb.LLDB_WATCH_TYPE_WRITE)
+ self.assertTrue(value, "Successfully found the variable and set a watchpoint")
+ self.DebugSBValue(value)
+
+ # Hide stdout if not running with '-t' option.
+ if not self.TraceOn():
+ self.HideStdout()
+
+ # There should be only 1 watchpoint location under the target.
+ self.assertTrue(target.GetNumWatchpointLocations() == 1)
+ wp_loc = target.GetWatchpointLocationAtIndex(0)
+ last_created = target.GetLastCreatedWatchpointLocation()
+ self.assertTrue(wp_loc == last_created)
+ self.assertTrue(wp_loc.IsEnabled())
+ self.assertTrue(wp_loc.GetIgnoreCount() == 0)
+ watch_id = wp_loc.GetID()
+ self.assertTrue(watch_id != 0)
+ print wp_loc
+
+ # Now immediately set the ignore count to 2. When we continue, expect the
+ # inferior to run to its completion without stopping due to watchpoint.
+ wp_loc.SetIgnoreCount(2)
+ print wp_loc
+ process.Continue()
+
+ # At this point, the inferior process should have exited.
+ self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED)
+
+ # Verify some vital statistics.
+ self.assertTrue(wp_loc)
+ self.assertTrue(wp_loc.GetWatchSize() == 4)
+ self.assertTrue(wp_loc.GetHitCount() == 2)
+ print wp_loc
+
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
More information about the lldb-commits
mailing list