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