116 lines · python
1"""2Test lldb watchpoint that uses 'watchpoint set -w write -s size' to watch a pointed location with size.3"""4 5 6import lldb7from lldbsuite.test.decorators import *8from lldbsuite.test.lldbtest import *9from lldbsuite.test import lldbutil10 11 12class WatchLocationUsingWatchpointSetTestCase(TestBase):13 NO_DEBUG_INFO_TESTCASE = True14 15 # on arm64 targets, lldb has incorrect hit-count / ignore-counts16 # for watchpoints when they are hit with multiple threads at17 # the same time. Tracked as llvm.org/pr4943318 # or rdar://93863107 inside Apple.19 def affected_by_radar_93863107(self):20 return (21 self.getArchitecture() in ["arm64", "arm64e"]22 ) and self.platformIsDarwin()23 24 def setUp(self):25 # Call super's setUp().26 TestBase.setUp(self)27 # Our simple source filename.28 self.source = "main.cpp"29 # Find the line number to break inside main().30 self.line = line_number(self.source, "// Set break point at this line.")31 # This is for verifying that watch location works.32 self.violating_func = "do_bad_thing_with_location"33 # Build dictionary to have unique executable names for each test34 # method.35 36 @skipIf(oslist=["linux"], archs=["aarch64", "arm$"], bugnumber="llvm.org/pr26031")37 @skipIfWindows # This test is flaky on Windows38 def test_watchlocation_using_watchpoint_set(self):39 """Test watching a location with 'watchpoint set expression -w write -s size' option."""40 self.build()41 self.setTearDownCleanup()42 43 exe = self.getBuildArtifact("a.out")44 target = self.dbg.CreateTarget(exe)45 46 # Add a breakpoint to set a watchpoint when stopped on the breakpoint.47 lldbutil.run_break_set_by_file_and_line(48 self, None, self.line, num_expected_locations=149 )50 51 # Run the program.52 self.runCmd("run", RUN_SUCCEEDED)53 54 # We should be stopped again due to the breakpoint.55 # The stop reason of the thread should be breakpoint.56 self.expect(57 "thread list",58 STOPPED_DUE_TO_BREAKPOINT,59 substrs=["stopped", "stop reason = breakpoint"],60 )61 62 # Now let's set a write-type watchpoint pointed to by 'g_char_ptr' and63 # with offset as 7.64 # The main.cpp, by design, misbehaves by not following the agreed upon65 # protocol of only accessing the allowable index range of [0, 6].66 self.expect(67 "watchpoint set expression -w write -s 1 -- g_char_ptr + 7",68 WATCHPOINT_CREATED,69 substrs=["Watchpoint created", "size = 1", "type = w"],70 )71 self.runCmd("expr unsigned val = g_char_ptr[7]; val")72 self.expect(self.res.GetOutput().splitlines()[0], exe=False, endstr=" = 0")73 74 # Use the '-v' option to do verbose listing of the watchpoint.75 # The hit count should be 0 initially.76 self.expect("watchpoint list -v", substrs=["hit_count = 0"])77 78 # Check the underlying SBWatchpoint.79 watchpoint = target.GetWatchpointAtIndex(0)80 self.assertEqual(watchpoint.GetWatchSize(), 1)81 self.assertEqual(watchpoint.GetHitCount(), 0)82 self.assertEqual(watchpoint.GetWatchSpec(), "g_char_ptr + 7")83 84 self.runCmd("process continue")85 86 # We should be stopped again due to the watchpoint (write type), but87 # only once. The stop reason of the thread should be watchpoint.88 self.expect(89 "thread list",90 STOPPED_DUE_TO_WATCHPOINT,91 substrs=[92 "stopped",93 self.violating_func,94 "stop reason = watchpoint",95 ],96 )97 98 # Switch to the thread stopped due to watchpoint and issue some99 # commands.100 self.switch_to_thread_with_stop_reason(lldb.eStopReasonWatchpoint)101 self.runCmd("thread backtrace")102 self.runCmd("expr unsigned val = g_char_ptr[7]; val")103 self.expect(self.res.GetOutput().splitlines()[0], exe=False, endstr=" = 99")104 105 # Use the '-v' option to do verbose listing of the watchpoint.106 # The hit count should now be the same as the number of threads that107 # stopped on a watchpoint.108 threads = lldbutil.get_stopped_threads(109 self.process(), lldb.eStopReasonWatchpoint110 )111 112 if not self.affected_by_radar_93863107():113 self.expect("watchpoint list -v", substrs=["hit_count = %d" % len(threads)])114 115 self.runCmd("thread backtrace all")116