TestThreadAPI.py revision 650fef9e5ac3ea99091b14b12ef5e4b7b73de7b0
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_stop_description_with_dsym(self): 18 """Test Python SBThread.GetStopDescription() API.""" 19 self.buildDsym() 20 self.get_stop_description() 21 22 @python_api_test 23 def test_get_stop_description_with_dwarf(self): 24 """Test Python SBThread.GetStopDescription() API.""" 25 self.buildDwarf() 26 self.get_stop_description() 27 28 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") 29 @python_api_test 30 def test_step_out_of_malloc_into_function_b_with_dsym(self): 31 """Test Python SBThread.StepOut() API to step out of a malloc call where the call site is at function b().""" 32 # We build a different executable than the default buildDsym() does. 33 d = {'CXX_SOURCES': 'main2.cpp'} 34 self.buildDsym(dictionary=d) 35 self.setTearDownCleanup(dictionary=d) 36 self.step_out_of_malloc_into_function_b() 37 38 @python_api_test 39 def test_step_out_of_malloc_into_function_b_with_dwarf(self): 40 """Test Python SBThread.StepOut() API to step out of a malloc call where the call site is at function b().""" 41 # We build a different executable than the default buildDwarf() does. 42 d = {'CXX_SOURCES': 'main2.cpp'} 43 self.buildDwarf(dictionary=d) 44 self.setTearDownCleanup(dictionary=d) 45 self.step_out_of_malloc_into_function_b() 46 47 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") 48 @python_api_test 49 def test_step_over_3_times_with_dsym(self): 50 """Test Python SBThread.StepOver() API.""" 51 # We build a different executable than the default buildDsym() does. 52 d = {'CXX_SOURCES': 'main2.cpp'} 53 self.buildDsym(dictionary=d) 54 self.setTearDownCleanup(dictionary=d) 55 self.step_over_3_times() 56 57 @python_api_test 58 def test_step_over_3_times_with_dwarf(self): 59 """Test Python SBThread.StepOver() API.""" 60 # We build a different executable than the default buildDwarf() does. 61 d = {'CXX_SOURCES': 'main2.cpp'} 62 self.buildDwarf(dictionary=d) 63 self.setTearDownCleanup(dictionary=d) 64 self.step_over_3_times() 65 66 def setUp(self): 67 # Call super's setUp(). 68 TestBase.setUp(self) 69 # Find the line number to break inside main(). 70 self.line = line_number("main.cpp", "// Set break point at this line and check variable 'my_char'.") 71 # Find the line numbers within main2.cpp for step_over_3_times() and step_out_of_malloc_into_function_b(). 72 self.line2 = line_number("main2.cpp", "// thread step-out of malloc into function b.") 73 self.line3 = line_number("main2.cpp", "// we should reach here after 3 step-over's.") 74 75 def get_stop_description(self): 76 """Test Python SBProcess.ReadMemory() API.""" 77 exe = os.path.join(os.getcwd(), "a.out") 78 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 79 80 target = self.dbg.CreateTarget(exe) 81 self.assertTrue(target.IsValid(), VALID_TARGET) 82 83 breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line) 84 self.assertTrue(breakpoint.IsValid(), VALID_BREAKPOINT) 85 #self.runCmd("breakpoint list") 86 87 # Launch the process, and do not stop at the entry point. 88 error = lldb.SBError() 89 self.process = target.Launch (self.dbg.GetListener(), None, None, os.ctermid(), os.ctermid(), os.ctermid(), None, 0, False, error) 90 91 thread = get_stopped_thread(self.process, lldb.eStopReasonBreakpoint) 92 self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint") 93 #self.runCmd("process status") 94 95 # Due to the typemap magic (see lldb.swig), we pass in an (int)length to GetStopDescription 96 # and expect to get a Python string as the result object! 97 # The 100 is just an arbitrary number specifying the buffer size. 98 stop_description = thread.GetStopDescription(100) 99 self.expect(stop_description, exe=False, 100 startstr = 'breakpoint') 101 102 def step_out_of_malloc_into_function_b(self): 103 """Test Python SBThread.StepOut() API to step out of a malloc call where the call site is at function b().""" 104 exe = os.path.join(os.getcwd(), "a.out") 105 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 106 107 target = self.dbg.CreateTarget(exe) 108 self.assertTrue(target.IsValid(), VALID_TARGET) 109 110 breakpoint = target.BreakpointCreateByName('malloc') 111 self.assertTrue(breakpoint.IsValid(), VALID_BREAKPOINT) 112 self.runCmd("breakpoint list") 113 114 # Launch the process, and do not stop at the entry point. 115 error = lldb.SBError() 116 self.process = target.Launch (self.dbg.GetListener(), None, None, os.ctermid(), os.ctermid(), os.ctermid(), None, 0, False, error) 117 118 while True: 119 thread = get_stopped_thread(self.process, lldb.eStopReasonBreakpoint) 120 self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint") 121 caller_symbol = get_caller_symbol(thread) 122 #print "caller symbol of malloc:", caller_symbol 123 if not caller_symbol: 124 self.fail("Test failed: could not locate the caller symbol of malloc") 125 if caller_symbol == "b(int)": 126 break 127 #self.runCmd("thread backtrace") 128 #self.runCmd("process status") 129 self.process.Continue() 130 131 thread.StepOut() 132 self.runCmd("thread backtrace") 133 #self.runCmd("process status") 134 self.assertTrue(thread.GetFrameAtIndex(0).GetLineEntry().GetLine() == self.line2, 135 "step out of malloc into function b is successful") 136 137 def step_over_3_times(self): 138 """Test Python SBThread.StepOver() API.""" 139 exe = os.path.join(os.getcwd(), "a.out") 140 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 141 142 target = self.dbg.CreateTarget(exe) 143 self.assertTrue(target.IsValid(), VALID_TARGET) 144 145 breakpoint = target.BreakpointCreateByLocation('main2.cpp', self.line2) 146 self.assertTrue(breakpoint.IsValid(), VALID_BREAKPOINT) 147 self.runCmd("breakpoint list") 148 149 # Launch the process, and do not stop at the entry point. 150 error = lldb.SBError() 151 self.process = target.Launch (self.dbg.GetListener(), None, None, os.ctermid(), os.ctermid(), os.ctermid(), None, 0, False, error) 152 153 self.assertTrue(self.process.IsValid(), PROCESS_IS_VALID) 154 155 # Frame #0 should be on self.line2. 156 self.assertTrue(self.process.GetState() == lldb.eStateStopped) 157 thread = get_stopped_thread(self.process, lldb.eStopReasonBreakpoint) 158 self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint condition") 159 self.runCmd("thread backtrace") 160 frame0 = thread.GetFrameAtIndex(0) 161 lineEntry = frame0.GetLineEntry() 162 self.assertTrue(lineEntry.GetLine() == self.line2) 163 164 thread.StepOver() 165 thread.StepOver() 166 thread.StepOver() 167 self.runCmd("thread backtrace") 168 169 # Verify that we are stopped at the correct source line number in main2.cpp. 170 frame0 = thread.GetFrameAtIndex(0) 171 lineEntry = frame0.GetLineEntry() 172 self.assertTrue(thread.GetStopReason() == lldb.eStopReasonPlanComplete) 173 self.assertTrue(lineEntry.GetLine() == self.line3) 174 175 176if __name__ == '__main__': 177 import atexit 178 lldb.SBDebugger.Initialize() 179 atexit.register(lambda: lldb.SBDebugger.Terminate()) 180 unittest2.main() 181