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