1 """ 2 Use lldb Python SBtarget.WatchAddress() API to create a watchpoint for write of '*g_char_ptr'. 3 """ 4 5 import os, time 6 import re 7 import unittest2 8 import lldb, lldbutil 9 from lldbtest import * 10 11 class TargetWatchAddressAPITestCase(TestBase): 12 13 mydir = os.path.join("python_api", "watchpoint", "watchlocation") 14 15 def setUp(self): 16 # Call super's setUp(). 17 TestBase.setUp(self) 18 # Our simple source filename. 19 self.source = 'main.cpp' 20 # Find the line number to break inside main(). 21 self.line = line_number(self.source, '// Set break point at this line.') 22 # This is for verifying that watch location works. 23 self.violating_func = "do_bad_thing_with_location"; 24 25 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") 26 @python_api_test 27 @dsym_test 28 def test_watch_address_with_dsym(self): 29 """Exercise SBTarget.WatchAddress() API to set a watchpoint.""" 30 self.buildDsym() 31 self.do_set_watchaddress() 32 33 @expectedFailureFreeBSD('llvm.org/pr16706') # Watchpoints fail on FreeBSD 34 @skipIfLinux # llvm.org/pr14323 - skip due to incomplete multi-threaded debug support 35 @python_api_test 36 @dwarf_test 37 def test_watch_address_with_dwarf(self): 38 """Exercise SBTarget.WatchAddress() API to set a watchpoint.""" 39 self.buildDwarf() 40 self.do_set_watchaddress() 41 42 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") 43 @python_api_test 44 @dsym_test 45 def test_watch_address_with_invalid_watch_size_with_dsym(self): 46 """Exercise SBTarget.WatchAddress() API but pass an invalid watch_size.""" 47 self.buildDsym() 48 self.do_set_watchaddress_with_invalid_watch_size() 49 50 @python_api_test 51 @dwarf_test 52 def test_watch_address_with_invalid_watch_size_with_dwarf(self): 53 """Exercise SBTarget.WatchAddress() API but pass an invalid watch_size.""" 54 self.buildDwarf() 55 self.do_set_watchaddress_with_invalid_watch_size() 56 57 def do_set_watchaddress(self): 58 """Use SBTarget.WatchAddress() to set a watchpoint and verify that the program stops later due to the watchpoint.""" 59 exe = os.path.join(os.getcwd(), "a.out") 60 61 # Create a target by the debugger. 62 target = self.dbg.CreateTarget(exe) 63 self.assertTrue(target, VALID_TARGET) 64 65 # Now create a breakpoint on main.c. 66 breakpoint = target.BreakpointCreateByLocation(self.source, self.line) 67 self.assertTrue(breakpoint and 68 breakpoint.GetNumLocations() == 1, 69 VALID_BREAKPOINT) 70 71 # Now launch the process, and do not stop at the entry point. 72 process = target.LaunchSimple(None, None, os.getcwd()) 73 74 # We should be stopped due to the breakpoint. Get frame #0. 75 process = target.GetProcess() 76 self.assertTrue(process.GetState() == lldb.eStateStopped, 77 PROCESS_STOPPED) 78 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) 79 frame0 = thread.GetFrameAtIndex(0) 80 81 value = frame0.FindValue('g_char_ptr', 82 lldb.eValueTypeVariableGlobal) 83 pointee = value.CreateValueFromAddress("pointee", 84 value.GetValueAsUnsigned(0), 85 value.GetType().GetPointeeType()) 86 # Watch for write to *g_char_ptr. 87 error = lldb.SBError(); 88 watchpoint = target.WatchAddress(value.GetValueAsUnsigned(), 1, False, True, error) 89 self.assertTrue(value and watchpoint, 90 "Successfully found the pointer and set a watchpoint") 91 self.DebugSBValue(value) 92 self.DebugSBValue(pointee) 93 94 # Hide stdout if not running with '-t' option. 95 if not self.TraceOn(): 96 self.HideStdout() 97 98 print watchpoint 99 100 # Continue. Expect the program to stop due to the variable being written to. 101 process.Continue() 102 103 if (self.TraceOn()): 104 lldbutil.print_stacktraces(process) 105 106 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonWatchpoint) 107 self.assertTrue(thread, "The thread stopped due to watchpoint") 108 self.DebugSBValue(value) 109 self.DebugSBValue(pointee) 110 111 self.expect(lldbutil.print_stacktrace(thread, string_buffer=True), exe=False, 112 substrs = [self.violating_func]) 113 114 # This finishes our test. 115 116 def do_set_watchaddress_with_invalid_watch_size(self): 117 """Use SBTarget.WatchAddress() to set a watchpoint with invalid watch_size and verify we get a meaningful error message.""" 118 exe = os.path.join(os.getcwd(), "a.out") 119 120 # Create a target by the debugger. 121 target = self.dbg.CreateTarget(exe) 122 self.assertTrue(target, VALID_TARGET) 123 124 # Now create a breakpoint on main.c. 125 breakpoint = target.BreakpointCreateByLocation(self.source, self.line) 126 self.assertTrue(breakpoint and 127 breakpoint.GetNumLocations() == 1, 128 VALID_BREAKPOINT) 129 130 # Now launch the process, and do not stop at the entry point. 131 process = target.LaunchSimple(None, None, os.getcwd()) 132 133 # We should be stopped due to the breakpoint. Get frame #0. 134 process = target.GetProcess() 135 self.assertTrue(process.GetState() == lldb.eStateStopped, 136 PROCESS_STOPPED) 137 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) 138 frame0 = thread.GetFrameAtIndex(0) 139 140 value = frame0.FindValue('g_char_ptr', 141 lldb.eValueTypeVariableGlobal) 142 pointee = value.CreateValueFromAddress("pointee", 143 value.GetValueAsUnsigned(0), 144 value.GetType().GetPointeeType()) 145 # Watch for write to *g_char_ptr. 146 error = lldb.SBError(); 147 watchpoint = target.WatchAddress(value.GetValueAsUnsigned(), 365, False, True, error) 148 self.assertFalse(watchpoint) 149 self.expect(error.GetCString(), exe=False, 150 substrs = ['watch size of %d is not supported' % 365]) 151 152 153 if __name__ == '__main__': 154 import atexit 155 lldb.SBDebugger.Initialize() 156 atexit.register(lambda: lldb.SBDebugger.Terminate()) 157 unittest2.main() 158