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