1""" 2Use lldb Python SBTarget API to iterate on the watchpoint(s) for the target. 3""" 4 5import lldb 6from lldbsuite.test.decorators import * 7from lldbsuite.test.lldbtest import * 8from lldbsuite.test import lldbutil 9 10 11class WatchpointIteratorTestCase(TestBase): 12 NO_DEBUG_INFO_TESTCASE = True 13 14 # hardware watchpoints are not reported with a hardware index # on armv7 on ios devices 15 def affected_by_radar_34564183(self): 16 return ( 17 self.getArchitecture() in ["armv7", "armv7k", "arm64_32"] 18 ) and self.platformIsDarwin() 19 20 def setUp(self): 21 # Call super's setUp(). 22 TestBase.setUp(self) 23 # Our simple source filename. 24 self.source = "main.c" 25 # Find the line number to break inside main(). 26 self.line = line_number(self.source, "// Set break point at this line.") 27 28 def test_watch_iter(self): 29 """Exercise SBTarget.watchpoint_iter() API to iterate on the available watchpoints.""" 30 self.build() 31 exe = self.getBuildArtifact("a.out") 32 33 # Create a target by the debugger. 34 target = self.dbg.CreateTarget(exe) 35 self.assertTrue(target, VALID_TARGET) 36 37 # Create a breakpoint on main.c in order to set our watchpoint later. 38 breakpoint = target.BreakpointCreateByLocation(self.source, self.line) 39 self.assertTrue( 40 breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT 41 ) 42 43 # Now launch the process, and do not stop at the entry point. 44 process = target.LaunchSimple(None, None, self.get_process_working_directory()) 45 46 # We should be stopped due to the breakpoint. Get frame #0. 47 process = target.GetProcess() 48 self.assertState(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) 49 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) 50 frame0 = thread.GetFrameAtIndex(0) 51 52 # Watch 'global' for read and write. 53 value = frame0.FindValue("global", lldb.eValueTypeVariableGlobal) 54 error = lldb.SBError() 55 watchpoint = value.Watch(True, False, True, error) 56 self.assertTrue( 57 value and watchpoint, "Successfully found the variable and set a watchpoint" 58 ) 59 self.DebugSBValue(value) 60 61 # Hide stdout if not running with '-t' option. 62 if not self.TraceOn(): 63 self.HideStdout() 64 65 # There should be only 1 watchpoint location under the target. 66 self.assertEqual(target.GetNumWatchpoints(), 1) 67 self.assertTrue(watchpoint.IsEnabled()) 68 watch_id = watchpoint.GetID() 69 self.assertNotEqual(watch_id, 0) 70 71 # Continue. Expect the program to stop due to the variable being 72 # written to. 73 process.Continue() 74 75 # Hide stdout if not running with '-t' option. 76 if not self.TraceOn(): 77 self.HideStdout() 78 79 # Print the stack traces. 80 lldbutil.print_stacktraces(process) 81 82 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonWatchpoint) 83 self.assertTrue(thread, "The thread stopped due to watchpoint") 84 self.DebugSBValue(value) 85 86 # SBWatchpoint.GetDescription() takes a description level arg. 87 print(lldbutil.get_description(watchpoint, lldb.eDescriptionLevelFull)) 88 89 # Now disable the 'rw' watchpoint. The program won't stop when it reads 90 # 'global' next. 91 watchpoint.SetEnabled(False) 92 self.assertFalse(watchpoint.IsEnabled()) 93 94 # Continue. The program does not stop again when the variable is being 95 # read from because the watchpoint location has been disabled. 96 process.Continue() 97 98 # At this point, the inferior process should have exited. 99 self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED) 100 101 # Verify some vital statistics and exercise the iterator API. 102 for watchpoint in target.watchpoint_iter(): 103 self.assertTrue(watchpoint) 104 self.assertEqual(watchpoint.GetWatchSize(), 4) 105 self.assertEqual(watchpoint.GetHitCount(), 1) 106 print(watchpoint) 107