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 NO_DEBUG_INFO_TESTCASE = True 16 17 def setUp(self): 18 # Call super's setUp(). 19 TestBase.setUp(self) 20 # Our simple source filename. 21 self.source = 'main.cpp' 22 # Find the line number to break inside main(). 23 self.line = line_number( 24 self.source, '// Set break point at this line.') 25 # This is for verifying that watch location works. 26 self.violating_func = "do_bad_thing_with_location" 27 # Build dictionary to have unique executable names for each test 28 # method. 29 self.exe_name = self.testMethodName 30 self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name} 31 32 # on arm64 targets, lldb has incorrect hit-count / ignore-counts 33 # for watchpoints when they are hit with multiple threads at 34 # the same time. Tracked as llvm.org/pr49433 35 # or rdar://93863107 inside Apple. 36 def affected_by_radar_93863107(self): 37 return (self.getArchitecture() in ['arm64', 'arm64e']) 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 # Run the program. 57 self.runCmd("run", RUN_SUCCEEDED) 58 59 # We should be stopped again due to the breakpoint. 60 # The stop reason of the thread should be breakpoint. 61 self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, 62 substrs=['stopped', 63 'stop reason = breakpoint']) 64 65 # Now let's set a write-type watchpoint pointed to by 'g_char_ptr'. 66 self.expect( 67 "watchpoint set expression -w write -s 1 -- g_char_ptr", 68 WATCHPOINT_CREATED, 69 substrs=[ 70 'Watchpoint created', 71 'size = 1', 72 'type = w']) 73 # Get a hold of the watchpoint id just created, it is used later on to 74 # match the watchpoint id which is expected to be fired. 75 match = re.match( 76 "Watchpoint created: Watchpoint (.*):", 77 self.res.GetOutput().splitlines()[0]) 78 if match: 79 expected_wp_id = int(match.group(1), 0) 80 else: 81 self.fail("Grokking watchpoint id faailed!") 82 83 self.runCmd("expr unsigned val = *g_char_ptr; val") 84 self.expect(self.res.GetOutput().splitlines()[0], exe=False, 85 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", 92 substrs=['hit_count = 0']) 93 94 self.runCmd("process continue") 95 96 # We should be stopped again due to the watchpoint (write type), but 97 # only once. The stop reason of the thread should be watchpoint. 98 self.expect("thread list", STOPPED_DUE_TO_WATCHPOINT, 99 substrs=['stopped', 100 'stop reason = watchpoint %d' % expected_wp_id]) 101 102 # Switch to the thread stopped due to watchpoint and issue some 103 # commands. 104 self.switch_to_thread_with_stop_reason(lldb.eStopReasonWatchpoint) 105 self.runCmd("thread backtrace") 106 self.expect("frame info", 107 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 if not self.affected_by_radar_93863107(): 116 self.expect("watchpoint list -v", 117 substrs=['hit_count = %d' % len(threads)]) 118 119 self.runCmd("thread backtrace all") 120