224 lines · python
1"""2Use lldb Python SBtarget.WatchpointCreateByAddress() API to create a watchpoint for write of '*g_char_ptr'.3"""4 5import lldb6from lldbsuite.test.decorators import *7from lldbsuite.test.lldbtest import *8from lldbsuite.test import lldbutil9 10 11class TargetWatchpointCreateByAddressPITestCase(TestBase):12 NO_DEBUG_INFO_TESTCASE = True13 14 def setUp(self):15 # Call super's setUp().16 TestBase.setUp(self)17 # Our simple source filename.18 self.source = "main.cpp"19 # Find the line number to break inside main().20 self.line = line_number(self.source, "// Set break point at this line.")21 # This is for verifying that watch location works.22 self.violating_func = "do_bad_thing_with_location"23 24 @skipIf(25 oslist=["windows"],26 archs=["x86_64"],27 bugnumber="github.com/llvm/llvm-project/issues/144777",28 )29 def test_watch_create_by_address(self):30 """Exercise SBTarget.WatchpointCreateByAddress() API to set a watchpoint."""31 self.build()32 exe = self.getBuildArtifact("a.out")33 34 # Create a target by the debugger.35 target = self.dbg.CreateTarget(exe)36 self.assertTrue(target, VALID_TARGET)37 38 # Now create a breakpoint on main.c.39 breakpoint = target.BreakpointCreateByLocation(self.source, self.line)40 self.assertTrue(41 breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT42 )43 44 # Now launch the process, and do not stop at the entry point.45 process = target.LaunchSimple(None, None, self.get_process_working_directory())46 47 # We should be stopped due to the breakpoint. Get frame #0.48 process = target.GetProcess()49 self.assertState(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)50 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)51 frame0 = thread.GetFrameAtIndex(0)52 53 value = frame0.FindValue("g_char_ptr", lldb.eValueTypeVariableGlobal)54 pointee = value.CreateValueFromAddress(55 "pointee", value.GetValueAsUnsigned(0), value.GetType().GetPointeeType()56 )57 # Watch for write to *g_char_ptr.58 error = lldb.SBError()59 wp_opts = lldb.SBWatchpointOptions()60 wp_opts.SetWatchpointTypeWrite(lldb.eWatchpointWriteTypeOnModify)61 watchpoint = target.WatchpointCreateByAddress(62 value.GetValueAsUnsigned(), 1, wp_opts, error63 )64 self.assertTrue(65 value and watchpoint, "Successfully found the pointer and set a watchpoint"66 )67 self.DebugSBValue(value)68 self.DebugSBValue(pointee)69 70 # Hide stdout if not running with '-t' option.71 if not self.TraceOn():72 self.HideStdout()73 74 print(watchpoint)75 76 # Continue. Expect the program to stop due to the variable being77 # written to.78 process.Continue()79 80 if self.TraceOn():81 lldbutil.print_stacktraces(process)82 83 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonWatchpoint)84 self.assertTrue(thread, "The thread stopped due to watchpoint")85 self.DebugSBValue(value)86 self.DebugSBValue(pointee)87 88 self.expect(89 lldbutil.print_stacktrace(thread, string_buffer=True),90 exe=False,91 substrs=[self.violating_func],92 )93 94 # This finishes our test.95 96 @skipIf(97 oslist=["windows"],98 archs=["x86_64"],99 bugnumber="github.com/llvm/llvm-project/issues/144777",100 )101 def test_watch_address(self):102 """Exercise SBTarget.WatchAddress() API to set a watchpoint.103 Same as test_watch_create_by_address, but uses the simpler API.104 """105 self.build()106 exe = self.getBuildArtifact("a.out")107 108 # Create a target by the debugger.109 target = self.dbg.CreateTarget(exe)110 self.assertTrue(target, VALID_TARGET)111 112 # Now create a breakpoint on main.c.113 breakpoint = target.BreakpointCreateByLocation(self.source, self.line)114 self.assertTrue(115 breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT116 )117 118 # Now launch the process, and do not stop at the entry point.119 process = target.LaunchSimple(None, None, self.get_process_working_directory())120 121 # We should be stopped due to the breakpoint. Get frame #0.122 process = target.GetProcess()123 self.assertState(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)124 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)125 frame0 = thread.GetFrameAtIndex(0)126 127 value = frame0.FindValue("g_char_ptr", lldb.eValueTypeVariableGlobal)128 pointee = value.CreateValueFromAddress(129 "pointee", value.GetValueAsUnsigned(0), value.GetType().GetPointeeType()130 )131 # Watch for write to *g_char_ptr.132 error = lldb.SBError()133 watch_read = False134 watch_write = True135 watchpoint = target.WatchAddress(136 value.GetValueAsUnsigned(), 1, watch_read, watch_write, error137 )138 self.assertTrue(139 value and watchpoint, "Successfully found the pointer and set a watchpoint"140 )141 self.DebugSBValue(value)142 self.DebugSBValue(pointee)143 144 # Hide stdout if not running with '-t' option.145 if not self.TraceOn():146 self.HideStdout()147 148 print(watchpoint)149 150 # Continue. Expect the program to stop due to the variable being151 # written to.152 process.Continue()153 154 if self.TraceOn():155 lldbutil.print_stacktraces(process)156 157 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonWatchpoint)158 self.assertTrue(thread, "The thread stopped due to watchpoint")159 self.DebugSBValue(value)160 self.DebugSBValue(pointee)161 162 self.expect(163 lldbutil.print_stacktrace(thread, string_buffer=True),164 exe=False,165 substrs=[self.violating_func],166 )167 168 # This finishes our test.169 170 # No size constraint on MIPS for watches171 @skipIf(archs=["mips", "mipsel", "mips64", "mips64el"])172 @skipIf(archs=["s390x"]) # Likewise on SystemZ173 @skipIf(174 oslist=["windows"],175 archs=["x86_64"],176 bugnumber="github.com/llvm/llvm-project/issues/142196",177 )178 def test_watch_address_with_invalid_watch_size(self):179 """Exercise SBTarget.WatchpointCreateByAddress() API but pass an invalid watch_size."""180 self.build()181 exe = self.getBuildArtifact("a.out")182 183 # Create a target by the debugger.184 target = self.dbg.CreateTarget(exe)185 self.assertTrue(target, VALID_TARGET)186 187 # Now create a breakpoint on main.c.188 breakpoint = target.BreakpointCreateByLocation(self.source, self.line)189 self.assertTrue(190 breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT191 )192 193 # Now launch the process, and do not stop at the entry point.194 process = target.LaunchSimple(None, None, self.get_process_working_directory())195 196 # We should be stopped due to the breakpoint. Get frame #0.197 process = target.GetProcess()198 self.assertState(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)199 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)200 frame0 = thread.GetFrameAtIndex(0)201 202 value = frame0.FindValue("g_char_ptr", lldb.eValueTypeVariableGlobal)203 pointee = value.CreateValueFromAddress(204 "pointee", value.GetValueAsUnsigned(0), value.GetType().GetPointeeType()205 )206 207 # debugserver on Darwin AArch64 systems can watch large regions208 # of memory via https://reviews.llvm.org/D149792 , don't run this209 # test there.210 if self.getArchitecture() not in ["arm64", "arm64e", "arm64_32"]:211 # Watch for write to *g_char_ptr.212 error = lldb.SBError()213 wp_opts = lldb.SBWatchpointOptions()214 wp_opts.SetWatchpointTypeWrite(lldb.eWatchpointWriteTypeOnModify)215 watchpoint = target.WatchpointCreateByAddress(216 value.GetValueAsUnsigned(), 365, wp_opts, error217 )218 self.assertFalse(watchpoint)219 self.expect(220 error.GetCString(),221 exe=False,222 substrs=["Setting one of the watchpoint resources failed"],223 )224