diff options
-rw-r--r-- | lldb/include/lldb/API/SBWatchpointLocation.h | 10 | ||||
-rw-r--r-- | lldb/lldb.xcodeproj/project.pbxproj | 2 | ||||
-rwxr-xr-x | lldb/scripts/Python/build-swig-Python.sh | 6 | ||||
-rw-r--r-- | lldb/scripts/Python/interface/SBTarget.i | 37 | ||||
-rw-r--r-- | lldb/scripts/Python/interface/SBWatchpointLocation.i | 71 | ||||
-rw-r--r-- | lldb/scripts/Python/modify-python-lldb.py | 7 | ||||
-rw-r--r-- | lldb/scripts/Python/python-extensions.swig | 7 | ||||
-rw-r--r-- | lldb/scripts/lldb.swig | 2 | ||||
-rw-r--r-- | lldb/source/API/SBWatchpointLocation.cpp | 53 | ||||
-rw-r--r-- | lldb/source/Breakpoint/WatchpointLocation.cpp | 1 | ||||
-rw-r--r-- | lldb/test/python_api/watchpoint/TestWatchpointLocationIter.py | 118 |
11 files changed, 306 insertions, 8 deletions
diff --git a/lldb/include/lldb/API/SBWatchpointLocation.h b/lldb/include/lldb/API/SBWatchpointLocation.h index 37df01658a4..632ccd5369f 100644 --- a/lldb/include/lldb/API/SBWatchpointLocation.h +++ b/lldb/include/lldb/API/SBWatchpointLocation.h @@ -29,9 +29,16 @@ public: operator = (const lldb::SBWatchpointLocation &rhs); #endif + watch_id_t + GetID () const; + bool IsValid() const; + /// With -1 representing an invalid hardware index. + int32_t + GetHardwareIndex () const; + lldb::addr_t GetWatchAddress () const; @@ -45,6 +52,9 @@ public: IsEnabled (); uint32_t + GetHitCount () const; + + uint32_t GetIgnoreCount (); void diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index bc8aacee321..28849ca527f 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -1366,6 +1366,7 @@ B296983512C2FB2B002D92C3 /* CommandObjectVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectVersion.h; path = source/Commands/CommandObjectVersion.h; sourceTree = "<group>"; }; B2A58721143119810092BFBA /* SBWatchpointLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBWatchpointLocation.h; path = include/lldb/API/SBWatchpointLocation.h; sourceTree = "<group>"; }; B2A58723143119D50092BFBA /* SBWatchpointLocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBWatchpointLocation.cpp; path = source/API/SBWatchpointLocation.cpp; sourceTree = "<group>"; }; + B2A5872514313B480092BFBA /* SBWatchpointLocation.i */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; path = SBWatchpointLocation.i; sourceTree = "<group>"; }; B2D3033612EFA5C500F84EB3 /* InstructionUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InstructionUtils.h; path = Utility/InstructionUtils.h; sourceTree = "<group>"; }; /* End PBXFileReference section */ @@ -1727,6 +1728,7 @@ 2611FF11142D83060017FEA3 /* SBType.i */, 2611FF12142D83060017FEA3 /* SBValue.i */, 2611FF13142D83060017FEA3 /* SBValueList.i */, + B2A5872514313B480092BFBA /* SBWatchpointLocation.i */, ); name = interface; path = scripts/Python/interface; diff --git a/lldb/scripts/Python/build-swig-Python.sh b/lldb/scripts/Python/build-swig-Python.sh index 1391e81e712..69da019a0b5 100755 --- a/lldb/scripts/Python/build-swig-Python.sh +++ b/lldb/scripts/Python/build-swig-Python.sh @@ -71,7 +71,8 @@ HEADER_FILES="${SRC_ROOT}/include/lldb/lldb.h"\ " ${SRC_ROOT}/include/lldb/API/SBThread.h"\ " ${SRC_ROOT}/include/lldb/API/SBType.h"\ " ${SRC_ROOT}/include/lldb/API/SBValue.h"\ -" ${SRC_ROOT}/include/lldb/API/SBValueList.h" +" ${SRC_ROOT}/include/lldb/API/SBValueList.h"\ +" ${SRC_ROOT}/include/lldb/API/SBWatchpointLocation.h"\ INTERFACE_FILES="${SRC_ROOT}/scripts/Python/interface/SBAddress.i"\ " ${SRC_ROOT}/scripts/Python/interface/SBBlock.i"\ @@ -106,7 +107,8 @@ INTERFACE_FILES="${SRC_ROOT}/scripts/Python/interface/SBAddress.i"\ " ${SRC_ROOT}/scripts/Python/interface/SBThread.i"\ " ${SRC_ROOT}/scripts/Python/interface/SBType.i"\ " ${SRC_ROOT}/scripts/Python/interface/SBValue.i"\ -" ${SRC_ROOT}/scripts/Python/interface/SBValueList.i" +" ${SRC_ROOT}/scripts/Python/interface/SBValueList.i"\ +" ${SRC_ROOT}/scripts/Python/interface/SBWatchpointLocation.i" if [ $Debug == 1 ] then diff --git a/lldb/scripts/Python/interface/SBTarget.i b/lldb/scripts/Python/interface/SBTarget.i index acd894cb57a..3bf14b1010a 100644 --- a/lldb/scripts/Python/interface/SBTarget.i +++ b/lldb/scripts/Python/interface/SBTarget.i @@ -12,7 +12,8 @@ namespace lldb { %feature("docstring", "Represents the target program running under the debugger. -SBTarget supports module and breakpoint iterations. For example, +SBTarget supports module, breakpoint, and watchpoint_location iterations. For +example, for m in target.module_iter(): print m @@ -34,7 +35,18 @@ and, produces: SBBreakpoint: id = 1, file ='main.cpp', line = 66, locations = 1 -SBBreakpoint: id = 2, file ='main.cpp', line = 85, locations = 1" +SBBreakpoint: id = 2, file ='main.cpp', line = 85, locations = 1 + +and, + + for wp_loc in target.watchpoint_location_iter(): + print wp_loc + +produces: + +WatchpointLocation 1: addr = 0x1034ca048 size = 4 state = enabled type = rw + declare @ '/Volumes/data/lldb/svn/trunk/test/python_api/watchpoint/main.c:12' + hw_index = 0 hit_count = 2 ignore_count = 0 callback = 0x0 baton = 0x0" ) SBTarget; class SBTarget { @@ -423,6 +435,27 @@ public: bool DeleteAllBreakpoints (); + uint32_t + GetNumWatchpointLocations () const; + + lldb::SBWatchpointLocation + GetWatchpointLocationAtIndex (uint32_t idx) const; + + bool + WatchpointLocationDelete (watch_id_t watch_id); + + lldb::SBWatchpointLocation + FindWatchpointLocationByID (watch_id_t watch_id); + + bool + EnableAllWatchpointLocations (); + + bool + DisableAllWatchpointLocations (); + + bool + DeleteAllWatchpointLocations (); + lldb::SBBroadcaster GetBroadcaster () const; diff --git a/lldb/scripts/Python/interface/SBWatchpointLocation.i b/lldb/scripts/Python/interface/SBWatchpointLocation.i new file mode 100644 index 00000000000..a5e21ddb894 --- /dev/null +++ b/lldb/scripts/Python/interface/SBWatchpointLocation.i @@ -0,0 +1,71 @@ +//===-- SWIG Interface for SBWatchpointLocation -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +namespace lldb { + +%feature("docstring", +"Represents an instance of watchpoint location for a specific target program. + +A watchpoint location is determined by the address and the byte size that +resulted in this particular instantiation. Each watchpoint location has its +settable options. + +See also SBTarget.watchpoint_location_iter() for for example usage of iterating +through the watchpoint locations of the target." +) SBWatchpointLocation; +class SBWatchpointLocation +{ +public: + + SBWatchpointLocation (); + + SBWatchpointLocation (const lldb::SBWatchpointLocation &rhs); + + ~SBWatchpointLocation (); + + watch_id_t + GetID () const; + + bool + IsValid() const; + + %feature("docstring", " + //------------------------------------------------------------------ + /// With -1 representing an invalid hardware index. + //------------------------------------------------------------------ + ") GetHardwareIndex; + int32_t + GetHardwareIndex () const; + + lldb::addr_t + GetWatchAddress () const; + + size_t + GetWatchSize() const; + + void + SetEnabled(bool enabled); + + bool + IsEnabled (); + + uint32_t + GetHitCount () const; + + uint32_t + GetIgnoreCount (); + + void + SetIgnoreCount (uint32_t n); + + bool + GetDescription (lldb::SBStream &description, DescriptionLevel level); +}; + +} // namespace lldb diff --git a/lldb/scripts/Python/modify-python-lldb.py b/lldb/scripts/Python/modify-python-lldb.py index 33929c62d0e..462467734cd 100644 --- a/lldb/scripts/Python/modify-python-lldb.py +++ b/lldb/scripts/Python/modify-python-lldb.py @@ -150,6 +150,7 @@ linked_list_iter_def = ''' iter_def = " def __iter__(self): return lldb_iter(self, '%s', '%s')" module_iter = " def module_iter(self): return lldb_iter(self, '%s', '%s')" breakpoint_iter = " def breakpoint_iter(self): return lldb_iter(self, '%s', '%s')" +watchpoint_location_iter = " def watchpoint_location_iter(self): return lldb_iter(self, '%s', '%s')" section_iter = " def section_iter(self): return lldb_iter(self, '%s', '%s')" # Called to implement the built-in function len(). @@ -187,7 +188,8 @@ d = { 'SBBreakpoint': ('GetNumLocations', 'GetLocationAtIndex'), # SBTarget needs special processing, see below. 'SBTarget': {'module': ('GetNumModules', 'GetModuleAtIndex'), - 'breakpoint': ('GetNumBreakpoints', 'GetBreakpointAtIndex') + 'breakpoint': ('GetNumBreakpoints', 'GetBreakpointAtIndex'), + 'watchpoint_location': ('GetNumWatchpointLocations', 'GetWatchpointLocationAtIndex') }, # SBModule has an additional section_iter(), see below. @@ -325,10 +327,11 @@ for line in content.splitlines(): # We found the beginning of the __init__ method definition. # This is a good spot to insert the iter and/or eq-ne support. # - # But note that SBTarget has two types of iterations. + # But note that SBTarget has three types of iterations. if cls == "SBTarget": new_content.add_line(module_iter % (d[cls]['module'])) new_content.add_line(breakpoint_iter % (d[cls]['breakpoint'])) + new_content.add_line(watchpoint_location_iter % (d[cls]['watchpoint_location'])) else: if (state & DEFINING_ITERATOR): new_content.add_line(iter_def % d[cls]) diff --git a/lldb/scripts/Python/python-extensions.swig b/lldb/scripts/Python/python-extensions.swig index 246fd97982e..5c302ba6f86 100644 --- a/lldb/scripts/Python/python-extensions.swig +++ b/lldb/scripts/Python/python-extensions.swig @@ -160,4 +160,11 @@ return PyString_FromString (description.GetData()); } } +%extend lldb::SBWatchpointLocation { + PyObject *lldb::SBWatchpointLocation::__repr__ (){ + lldb::SBStream description; + $self->GetDescription (description, lldb::eDescriptionLevelVerbose); + return PyString_FromString (description.GetData()); + } +} diff --git a/lldb/scripts/lldb.swig b/lldb/scripts/lldb.swig index 3b0fab43538..1996aabb2eb 100644 --- a/lldb/scripts/lldb.swig +++ b/lldb/scripts/lldb.swig @@ -79,6 +79,7 @@ o SBLineEntry: Specifies an association with a contiguous range of instructions #include "lldb/API/SBType.h" #include "lldb/API/SBValue.h" #include "lldb/API/SBValueList.h" +#include "lldb/API/SBWatchpointLocation.h" %} /* Various liblldb typedefs that SWIG needs to know about. */ @@ -131,6 +132,7 @@ o SBLineEntry: Specifies an association with a contiguous range of instructions %include "./Python/interface/SBType.i" %include "./Python/interface/SBValue.i" %include "./Python/interface/SBValueList.i" +%include "./Python/interface/SBWatchpointLocation.i" %include "./Python/python-extensions.swig" diff --git a/lldb/source/API/SBWatchpointLocation.cpp b/lldb/source/API/SBWatchpointLocation.cpp index b0e3eb827b8..33b035ff11f 100644 --- a/lldb/source/API/SBWatchpointLocation.cpp +++ b/lldb/source/API/SBWatchpointLocation.cpp @@ -63,12 +63,46 @@ SBWatchpointLocation::~SBWatchpointLocation () { } +watch_id_t +SBWatchpointLocation::GetID () const +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + + watch_id_t watch_id = LLDB_INVALID_WATCH_ID; + if (m_opaque_sp) + watch_id = m_opaque_sp->GetID(); + + if (log) + { + if (watch_id == LLDB_INVALID_WATCH_ID) + log->Printf ("SBWatchpointLocation(%p)::GetID () => LLDB_INVALID_WATCH_ID", m_opaque_sp.get()); + else + log->Printf ("SBWatchpointLocation(%p)::GetID () => %u", m_opaque_sp.get(), watch_id); + } + + return watch_id; +} + bool SBWatchpointLocation::IsValid() const { return m_opaque_sp.get() != NULL; } +int32_t +SBWatchpointLocation::GetHardwareIndex () const +{ + int32_t hw_index = -1; + + if (m_opaque_sp) + { + Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); + hw_index = m_opaque_sp->GetHardwareIndex(); + } + + return hw_index; +} + addr_t SBWatchpointLocation::GetWatchAddress () const { @@ -103,7 +137,7 @@ SBWatchpointLocation::SetEnabled (bool enabled) if (m_opaque_sp) { Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); - m_opaque_sp->SetEnabled (enabled); + m_opaque_sp->GetTarget().DisableWatchpointLocationByID(m_opaque_sp->GetID()); } } @@ -120,6 +154,23 @@ SBWatchpointLocation::IsEnabled () } uint32_t +SBWatchpointLocation::GetHitCount () const +{ + uint32_t count = 0; + if (m_opaque_sp) + { + Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); + count = m_opaque_sp->GetHitCount(); + } + + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + if (log) + log->Printf ("SBWatchpointLocation(%p)::GetHitCount () => %u", m_opaque_sp.get(), count); + + return count; +} + +uint32_t SBWatchpointLocation::GetIgnoreCount () { if (m_opaque_sp) diff --git a/lldb/source/Breakpoint/WatchpointLocation.cpp b/lldb/source/Breakpoint/WatchpointLocation.cpp index 6b2785a22b3..01f6189821d 100644 --- a/lldb/source/Breakpoint/WatchpointLocation.cpp +++ b/lldb/source/Breakpoint/WatchpointLocation.cpp @@ -95,7 +95,6 @@ WatchpointLocation::ShouldStop (StoppointCallbackContext *context) void WatchpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level) { - s->Printf(" "); DumpWithLevel(s, level); return; } diff --git a/lldb/test/python_api/watchpoint/TestWatchpointLocationIter.py b/lldb/test/python_api/watchpoint/TestWatchpointLocationIter.py new file mode 100644 index 00000000000..d54c2105333 --- /dev/null +++ b/lldb/test/python_api/watchpoint/TestWatchpointLocationIter.py @@ -0,0 +1,118 @@ +""" +Use lldb Python SBTarget API to iterate on the watchpoint(s) for the target. +""" + +import os, time +import re +import unittest2 +import lldb, lldbutil +from lldbtest import * + +class WatchpointLocationIteratorTestCase(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_watch_loc_iter_with_dsym(self): + """Exercise SBTarget.watchpoint_location_iter() API to iterate on the available watchpoint locations.""" + self.buildDsym() + self.do_watchpoint_location_iter() + + @python_api_test + def test_watch_loc_iter_with_dwarf(self): + """Exercise SBTarget.watchpoint_location_iter() API to iterate on the available watchpoint locations.""" + self.buildDwarf() + self.do_watchpoint_location_iter() + + def do_watchpoint_location_iter(self): + """Use SBTarget.watchpoint_location_iter() to do Pythonic iteration on the available watchpoint locations.""" + 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) + + 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) + + # There should be only 1 watchpoint location under the target. + self.assertTrue(target.GetNumWatchpointLocations() == 1) + wp_loc = target.GetWatchpointLocationAtIndex(0) + self.assertTrue(wp_loc.IsEnabled()) + watch_id = wp_loc.GetID() + self.assertTrue(watch_id != 0) + + # Continue. Expect the program to stop due to the variable being written to. + process.Continue() + + # Hide stdout if not running with '-t' option. + if not self.TraceOn(): + self.HideStdout() + + # Print the stack traces. + lldbutil.print_stacktraces(process) + + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonWatchpoint) + self.assertTrue(thread, "The thread stopped due to watchpoint") + self.DebugSBValue(value) + + # We currently only support hardware watchpoint. Verify that we have a + # meaningful hardware index at this point. Exercise the printed repr of + # SBWatchpointLocation. + print wp_loc + self.assertTrue(wp_loc.GetHardwareIndex() != -1) + + # Now disable the 'rw' watchpoint. The program won't stop when it reads + # 'global' next. + wp_loc.SetEnabled(False) + self.assertTrue(wp_loc.GetHardwareIndex() == -1) + self.assertFalse(wp_loc.IsEnabled()) + + # Continue. The program does not stop again when the variable is being + # read from because the watchpoint location has been disabled. + process.Continue() + + # At this point, the inferior process should have exited. + self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED) + + # Verify some vital statistics and exercise the iterator API. + for wp_loc in target.watchpoint_location_iter(): + self.assertTrue(wp_loc) + self.assertTrue(wp_loc.GetWatchSize() == 4) + self.assertTrue(wp_loc.GetHitCount() == 1) + print wp_loc + + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() |