[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