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