TestThreadAPI.py revision 21b1984e161b0cadee331d32bfd721eccfdf4b1f
1""" 2Test SBThread APIs. 3""" 4 5import os, time 6import unittest2 7import lldb 8from lldbutil import get_stopped_thread, get_caller_symbol 9from lldbtest import * 10 11class ThreadAPITestCase(TestBase): 12 13 mydir = os.path.join("python_api", "thread") 14 15 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") 16 @python_api_test 17 @dsym_test 18 def test_get_process_with_dsym(self): 19 """Test Python SBThread.GetProcess() API.""" 20 self.buildDsym() 21 self.get_process() 22 23 @python_api_test 24 @dwarf_test 25 def test_get_process_with_dwarf(self): 26 """Test Python SBThread.GetProcess() API.""" 27 self.buildDwarf() 28 self.get_process() 29 30 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") 31 @python_api_test 32 @dsym_test 33 def test_get_stop_description_with_dsym(self): 34 """Test Python SBThread.GetStopDescription() API.""" 35 self.buildDsym() 36 self.get_stop_description() 37 38 @python_api_test 39 @dwarf_test 40 def test_get_stop_description_with_dwarf(self): 41 """Test Python SBThread.GetStopDescription() API.""" 42 self.buildDwarf() 43 self.get_stop_description() 44 45 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") 46 @python_api_test 47 @dsym_test 48 def test_run_to_address_with_dsym(self): 49 """Test Python SBThread.RunToAddress() API.""" 50 # We build a different executable than the default buildDwarf() does. 51 d = {'CXX_SOURCES': 'main2.cpp', 'EXE': self.exe_name} 52 self.buildDsym(dictionary=d) 53 self.setTearDownCleanup(dictionary=d) 54 self.run_to_address(self.exe_name) 55 56 @python_api_test 57 @dwarf_test 58 def test_run_to_address_with_dwarf(self): 59 """Test Python SBThread.RunToAddress() API.""" 60 # We build a different executable than the default buildDwarf() does. 61 d = {'CXX_SOURCES': 'main2.cpp', 'EXE': self.exe_name} 62 self.buildDwarf(dictionary=d) 63 self.setTearDownCleanup(dictionary=d) 64 self.run_to_address(self.exe_name) 65 66 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") 67 @python_api_test 68 @dsym_test 69 def test_step_out_of_malloc_into_function_b_with_dsym(self): 70 """Test Python SBThread.StepOut() API to step out of a malloc call where the call site is at function b().""" 71 # We build a different executable than the default buildDsym() does. 72 d = {'CXX_SOURCES': 'main2.cpp', 'EXE': self.exe_name} 73 self.buildDsym(dictionary=d) 74 self.setTearDownCleanup(dictionary=d) 75 self.step_out_of_malloc_into_function_b(self.exe_name) 76 77 @python_api_test 78 @dwarf_test 79 def test_step_out_of_malloc_into_function_b_with_dwarf(self): 80 """Test Python SBThread.StepOut() API to step out of a malloc call where the call site is at function b().""" 81 # We build a different executable than the default buildDwarf() does. 82 d = {'CXX_SOURCES': 'main2.cpp', 'EXE': self.exe_name} 83 self.buildDwarf(dictionary=d) 84 self.setTearDownCleanup(dictionary=d) 85 self.step_out_of_malloc_into_function_b(self.exe_name) 86 87 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") 88 @python_api_test 89 @dsym_test 90 def test_step_over_3_times_with_dsym(self): 91 """Test Python SBThread.StepOver() API.""" 92 # We build a different executable than the default buildDsym() does. 93 d = {'CXX_SOURCES': 'main2.cpp', 'EXE': self.exe_name} 94 self.buildDsym(dictionary=d) 95 self.setTearDownCleanup(dictionary=d) 96 self.step_over_3_times(self.exe_name) 97 98 @python_api_test 99 @dwarf_test 100 def test_step_over_3_times_with_dwarf(self): 101 """Test Python SBThread.StepOver() API.""" 102 # We build a different executable than the default buildDwarf() does. 103 d = {'CXX_SOURCES': 'main2.cpp', 'EXE': self.exe_name} 104 self.buildDwarf(dictionary=d) 105 self.setTearDownCleanup(dictionary=d) 106 self.step_over_3_times(self.exe_name) 107 108 def setUp(self): 109 # Call super's setUp(). 110 TestBase.setUp(self) 111 # Find the line number within main.cpp to break inside main(). 112 self.break_line = line_number("main.cpp", "// Set break point at this line and check variable 'my_char'.") 113 # Find the line numbers within main2.cpp for step_out_of_malloc_into_function_b() and step_over_3_times(). 114 self.step_out_of_malloc = line_number("main2.cpp", "// thread step-out of malloc into function b.") 115 self.after_3_step_overs = line_number("main2.cpp", "// we should reach here after 3 step-over's.") 116 117 # We'll use the test method name as the exe_name for executable comppiled from main2.cpp. 118 self.exe_name = self.testMethodName 119 120 def get_process(self): 121 """Test Python SBThread.GetProcess() API.""" 122 exe = os.path.join(os.getcwd(), "a.out") 123 124 target = self.dbg.CreateTarget(exe) 125 self.assertTrue(target, VALID_TARGET) 126 127 breakpoint = target.BreakpointCreateByLocation("main.cpp", self.break_line) 128 self.assertTrue(breakpoint, VALID_BREAKPOINT) 129 self.runCmd("breakpoint list") 130 131 # Launch the process, and do not stop at the entry point. 132 process = target.LaunchSimple(None, None, os.getcwd()) 133 134 thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) 135 self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint") 136 self.runCmd("process status") 137 138 proc_of_thread = thread.GetProcess() 139 #print "proc_of_thread:", proc_of_thread 140 self.assertTrue(proc_of_thread.GetProcessID() == process.GetProcessID()) 141 142 def get_stop_description(self): 143 """Test Python SBThread.GetStopDescription() API.""" 144 exe = os.path.join(os.getcwd(), "a.out") 145 146 target = self.dbg.CreateTarget(exe) 147 self.assertTrue(target, VALID_TARGET) 148 149 breakpoint = target.BreakpointCreateByLocation("main.cpp", self.break_line) 150 self.assertTrue(breakpoint, VALID_BREAKPOINT) 151 #self.runCmd("breakpoint list") 152 153 # Launch the process, and do not stop at the entry point. 154 process = target.LaunchSimple(None, None, os.getcwd()) 155 156 thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) 157 self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint") 158 #self.runCmd("process status") 159 160 # Due to the typemap magic (see lldb.swig), we pass in an (int)length to GetStopDescription 161 # and expect to get a Python string as the return object! 162 # The 100 is just an arbitrary number specifying the buffer size. 163 stop_description = thread.GetStopDescription(100) 164 self.expect(stop_description, exe=False, 165 startstr = 'breakpoint') 166 167 def step_out_of_malloc_into_function_b(self, exe_name): 168 """Test Python SBThread.StepOut() API to step out of a malloc call where the call site is at function b().""" 169 exe = os.path.join(os.getcwd(), exe_name) 170 171 target = self.dbg.CreateTarget(exe) 172 self.assertTrue(target, VALID_TARGET) 173 174 breakpoint = target.BreakpointCreateByName('malloc') 175 self.assertTrue(breakpoint, VALID_BREAKPOINT) 176 self.runCmd("breakpoint list") 177 178 # Launch the process, and do not stop at the entry point. 179 process = target.LaunchSimple(None, None, os.getcwd()) 180 181 while True: 182 thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) 183 self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint") 184 caller_symbol = get_caller_symbol(thread) 185 #print "caller symbol of malloc:", caller_symbol 186 if not caller_symbol: 187 self.fail("Test failed: could not locate the caller symbol of malloc") 188 if caller_symbol == "b(int)": 189 break 190 #self.runCmd("thread backtrace") 191 #self.runCmd("process status") 192 process.Continue() 193 194 thread.StepOut() 195 self.runCmd("thread backtrace") 196 #self.runCmd("process status") 197 self.assertTrue(thread.GetFrameAtIndex(0).GetLineEntry().GetLine() == self.step_out_of_malloc, 198 "step out of malloc into function b is successful") 199 200 def step_over_3_times(self, exe_name): 201 """Test Python SBThread.StepOver() API.""" 202 exe = os.path.join(os.getcwd(), exe_name) 203 204 target = self.dbg.CreateTarget(exe) 205 self.assertTrue(target, VALID_TARGET) 206 207 breakpoint = target.BreakpointCreateByLocation('main2.cpp', self.step_out_of_malloc) 208 self.assertTrue(breakpoint, VALID_BREAKPOINT) 209 self.runCmd("breakpoint list") 210 211 # Launch the process, and do not stop at the entry point. 212 process = target.LaunchSimple(None, None, os.getcwd()) 213 214 self.assertTrue(process, PROCESS_IS_VALID) 215 216 # Frame #0 should be on self.step_out_of_malloc. 217 self.assertTrue(process.GetState() == lldb.eStateStopped) 218 thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) 219 self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint condition") 220 self.runCmd("thread backtrace") 221 frame0 = thread.GetFrameAtIndex(0) 222 lineEntry = frame0.GetLineEntry() 223 self.assertTrue(lineEntry.GetLine() == self.step_out_of_malloc) 224 225 thread.StepOver() 226 thread.StepOver() 227 thread.StepOver() 228 self.runCmd("thread backtrace") 229 230 # Verify that we are stopped at the correct source line number in main2.cpp. 231 frame0 = thread.GetFrameAtIndex(0) 232 lineEntry = frame0.GetLineEntry() 233 self.assertTrue(thread.GetStopReason() == lldb.eStopReasonPlanComplete) 234 # Expected failure with clang as the compiler. 235 # rdar://problem/9223880 236 # 237 # Which has been fixed on the lldb by compensating for inaccurate line 238 # table information with r140416. 239 self.assertTrue(lineEntry.GetLine() == self.after_3_step_overs) 240 241 def run_to_address(self, exe_name): 242 """Test Python SBThread.RunToAddress() API.""" 243 exe = os.path.join(os.getcwd(), exe_name) 244 245 target = self.dbg.CreateTarget(exe) 246 self.assertTrue(target, VALID_TARGET) 247 248 breakpoint = target.BreakpointCreateByLocation('main2.cpp', self.step_out_of_malloc) 249 self.assertTrue(breakpoint, VALID_BREAKPOINT) 250 self.runCmd("breakpoint list") 251 252 # Launch the process, and do not stop at the entry point. 253 process = target.LaunchSimple(None, None, os.getcwd()) 254 255 self.assertTrue(process, PROCESS_IS_VALID) 256 257 # Frame #0 should be on self.step_out_of_malloc. 258 self.assertTrue(process.GetState() == lldb.eStateStopped) 259 thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) 260 self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint condition") 261 self.runCmd("thread backtrace") 262 frame0 = thread.GetFrameAtIndex(0) 263 lineEntry = frame0.GetLineEntry() 264 self.assertTrue(lineEntry.GetLine() == self.step_out_of_malloc) 265 266 # Get the start/end addresses for this line entry. 267 start_addr = lineEntry.GetStartAddress().GetLoadAddress(target) 268 end_addr = lineEntry.GetEndAddress().GetLoadAddress(target) 269 if self.TraceOn(): 270 print "start addr:", hex(start_addr) 271 print "end addr:", hex(end_addr) 272 273 # Disable the breakpoint. 274 self.assertTrue(target.DisableAllBreakpoints()) 275 self.runCmd("breakpoint list") 276 277 thread.StepOver() 278 thread.StepOver() 279 thread.StepOver() 280 self.runCmd("thread backtrace") 281 282 # Now ask SBThread to run to the address 'start_addr' we got earlier, which 283 # corresponds to self.step_out_of_malloc line entry's start address. 284 thread.RunToAddress(start_addr) 285 self.runCmd("process status") 286 #self.runCmd("thread backtrace") 287 288 289if __name__ == '__main__': 290 import atexit 291 lldb.SBDebugger.Initialize() 292 atexit.register(lambda: lldb.SBDebugger.Terminate()) 293 unittest2.main() 294