1""" 2Use lldb Python SBValue API to create a watchpoint for read_write of 'globl' var. 3""" 4 5import lldb 6from lldbsuite.test.decorators import * 7from lldbsuite.test.lldbtest import * 8from lldbsuite.test import lldbutil 9 10 11class SetWatchpointAPITestCase(TestBase): 12 NO_DEBUG_INFO_TESTCASE = True 13 14 def setUp(self): 15 # Call super's setUp(). 16 TestBase.setUp(self) 17 # Our simple source filename. 18 self.source = "main.c" 19 # Find the line number to break inside main(). 20 self.line = line_number(self.source, "// Set break point at this line.") 21 self.build() 22 23 # Read-write watchpoints not supported on SystemZ 24 @expectedFailureAll(archs=["s390x"]) 25 def test_watch_val(self): 26 """Exercise SBValue.Watch() API to set a watchpoint.""" 27 self._test_watch_val(variable_watchpoint=False) 28 pass 29 30 @expectedFailureAll(archs=["s390x"]) 31 def test_watch_variable(self): 32 """ 33 Exercise some watchpoint APIs when the watchpoint 34 is created as a variable watchpoint. 35 """ 36 self._test_watch_val(variable_watchpoint=True) 37 38 def _test_watch_val(self, variable_watchpoint): 39 exe = self.getBuildArtifact("a.out") 40 41 # Create a target by the debugger. 42 target = self.dbg.CreateTarget(exe) 43 self.assertTrue(target, VALID_TARGET) 44 45 # Now create a breakpoint on main.c. 46 breakpoint = target.BreakpointCreateByLocation(self.source, self.line) 47 self.assertTrue( 48 breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT 49 ) 50 51 # Now launch the process, and do not stop at the entry point. 52 process = target.LaunchSimple(None, None, self.get_process_working_directory()) 53 54 # We should be stopped due to the breakpoint. Get frame #0. 55 process = target.GetProcess() 56 self.assertState(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) 57 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) 58 frame0 = thread.GetFrameAtIndex(0) 59 60 # Watch 'global' for read and write. 61 if variable_watchpoint: 62 # FIXME: There should probably be an API to create a 63 # variable watchpoint. 64 self.runCmd("watchpoint set variable -w read_write -- global") 65 watchpoint = target.GetWatchpointAtIndex(0) 66 self.assertEqual( 67 watchpoint.GetWatchValueKind(), lldb.eWatchPointValueKindVariable 68 ) 69 self.assertEqual(watchpoint.GetWatchSpec(), "global") 70 # Synthesize an SBValue from the watchpoint 71 watchpoint_addr = lldb.SBAddress(watchpoint.GetWatchAddress(), target) 72 value = target.CreateValueFromAddress( 73 watchpoint.GetWatchSpec(), watchpoint_addr, watchpoint.GetType() 74 ) 75 else: 76 value = frame0.FindValue("global", lldb.eValueTypeVariableGlobal) 77 error = lldb.SBError() 78 watchpoint = value.Watch(True, True, True, error) 79 self.assertTrue( 80 value and watchpoint, 81 "Successfully found the variable and set a watchpoint", 82 ) 83 self.DebugSBValue(value) 84 self.assertEqual( 85 watchpoint.GetWatchValueKind(), lldb.eWatchPointValueKindExpression 86 ) 87 # FIXME: The spec should probably be '&global' given that the kind 88 # is reported as eWatchPointValueKindExpression. If the kind is 89 # actually supposed to be eWatchPointValueKindVariable then the spec 90 # should probably be 'global'. 91 self.assertEqual(watchpoint.GetWatchSpec(), None) 92 93 self.assertEqual(watchpoint.GetType().GetDisplayTypeName(), "int32_t") 94 self.assertEqual(value.GetName(), "global") 95 self.assertEqual(value.GetType(), watchpoint.GetType()) 96 self.assertTrue(watchpoint.IsWatchingReads()) 97 self.assertTrue(watchpoint.IsWatchingWrites()) 98 99 # Hide stdout if not running with '-t' option. 100 if not self.TraceOn(): 101 self.HideStdout() 102 103 print(watchpoint) 104 105 # Continue. Expect the program to stop due to the variable being 106 # written to. 107 process.Continue() 108 109 if self.TraceOn(): 110 lldbutil.print_stacktraces(process) 111 112 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonWatchpoint) 113 self.assertTrue(thread, "The thread stopped due to watchpoint") 114 self.DebugSBValue(value) 115 116 # Continue. Expect the program to stop due to the variable being read 117 # from. 118 process.Continue() 119 120 if self.TraceOn(): 121 lldbutil.print_stacktraces(process) 122 123 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonWatchpoint) 124 self.assertTrue(thread, "The thread stopped due to watchpoint") 125 self.DebugSBValue(value) 126 127 # Continue the process. We don't expect the program to be stopped 128 # again. 129 process.Continue() 130 131 # At this point, the inferior process should have exited. 132 self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED) 133 134 self.dbg.DeleteTarget(target) 135 self.assertFalse(watchpoint.IsValid()) 136