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