1*99451b44SJordan Rupprecht""" 2*99451b44SJordan RupprechtTest SBThread APIs. 3*99451b44SJordan Rupprecht""" 4*99451b44SJordan Rupprecht 5*99451b44SJordan Rupprechtfrom __future__ import print_function 6*99451b44SJordan Rupprecht 7*99451b44SJordan Rupprecht 8*99451b44SJordan Rupprechtimport lldb 9*99451b44SJordan Rupprechtfrom lldbsuite.test.decorators import * 10*99451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import * 11*99451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil 12*99451b44SJordan Rupprechtfrom lldbsuite.test.lldbutil import get_stopped_thread, get_caller_symbol 13*99451b44SJordan Rupprecht 14*99451b44SJordan Rupprecht 15*99451b44SJordan Rupprechtclass ThreadAPITestCase(TestBase): 16*99451b44SJordan Rupprecht 17*99451b44SJordan Rupprecht mydir = TestBase.compute_mydir(__file__) 18*99451b44SJordan Rupprecht 19*99451b44SJordan Rupprecht @add_test_categories(['pyapi']) 20*99451b44SJordan Rupprecht def test_get_process(self): 21*99451b44SJordan Rupprecht """Test Python SBThread.GetProcess() API.""" 22*99451b44SJordan Rupprecht self.build() 23*99451b44SJordan Rupprecht self.get_process() 24*99451b44SJordan Rupprecht 25*99451b44SJordan Rupprecht @add_test_categories(['pyapi']) 26*99451b44SJordan Rupprecht def test_get_stop_description(self): 27*99451b44SJordan Rupprecht """Test Python SBThread.GetStopDescription() API.""" 28*99451b44SJordan Rupprecht self.build() 29*99451b44SJordan Rupprecht self.get_stop_description() 30*99451b44SJordan Rupprecht 31*99451b44SJordan Rupprecht @add_test_categories(['pyapi']) 32*99451b44SJordan Rupprecht def test_run_to_address(self): 33*99451b44SJordan Rupprecht """Test Python SBThread.RunToAddress() API.""" 34*99451b44SJordan Rupprecht # We build a different executable than the default build() does. 35*99451b44SJordan Rupprecht d = {'CXX_SOURCES': 'main2.cpp', 'EXE': self.exe_name} 36*99451b44SJordan Rupprecht self.build(dictionary=d) 37*99451b44SJordan Rupprecht self.setTearDownCleanup(dictionary=d) 38*99451b44SJordan Rupprecht self.run_to_address(self.exe_name) 39*99451b44SJordan Rupprecht 40*99451b44SJordan Rupprecht @add_test_categories(['pyapi']) 41*99451b44SJordan Rupprecht @expectedFailureAll(oslist=['freebsd'], bugnumber='llvm.org/pr20476') 42*99451b44SJordan Rupprecht @expectedFailureAll(oslist=["windows"]) 43*99451b44SJordan Rupprecht @expectedFailureNetBSD 44*99451b44SJordan Rupprecht def test_step_out_of_malloc_into_function_b(self): 45*99451b44SJordan Rupprecht """Test Python SBThread.StepOut() API to step out of a malloc call where the call site is at function b().""" 46*99451b44SJordan Rupprecht # We build a different executable than the default build() does. 47*99451b44SJordan Rupprecht d = {'CXX_SOURCES': 'main2.cpp', 'EXE': self.exe_name} 48*99451b44SJordan Rupprecht self.build(dictionary=d) 49*99451b44SJordan Rupprecht self.setTearDownCleanup(dictionary=d) 50*99451b44SJordan Rupprecht self.step_out_of_malloc_into_function_b(self.exe_name) 51*99451b44SJordan Rupprecht 52*99451b44SJordan Rupprecht @add_test_categories(['pyapi']) 53*99451b44SJordan Rupprecht def test_step_over_3_times(self): 54*99451b44SJordan Rupprecht """Test Python SBThread.StepOver() API.""" 55*99451b44SJordan Rupprecht # We build a different executable than the default build() does. 56*99451b44SJordan Rupprecht d = {'CXX_SOURCES': 'main2.cpp', 'EXE': self.exe_name} 57*99451b44SJordan Rupprecht self.build(dictionary=d) 58*99451b44SJordan Rupprecht self.setTearDownCleanup(dictionary=d) 59*99451b44SJordan Rupprecht self.step_over_3_times(self.exe_name) 60*99451b44SJordan Rupprecht 61*99451b44SJordan Rupprecht def setUp(self): 62*99451b44SJordan Rupprecht # Call super's setUp(). 63*99451b44SJordan Rupprecht TestBase.setUp(self) 64*99451b44SJordan Rupprecht # Find the line number within main.cpp to break inside main(). 65*99451b44SJordan Rupprecht self.break_line = line_number( 66*99451b44SJordan Rupprecht "main.cpp", "// Set break point at this line and check variable 'my_char'.") 67*99451b44SJordan Rupprecht # Find the line numbers within main2.cpp for 68*99451b44SJordan Rupprecht # step_out_of_malloc_into_function_b() and step_over_3_times(). 69*99451b44SJordan Rupprecht self.step_out_of_malloc = line_number( 70*99451b44SJordan Rupprecht "main2.cpp", "// thread step-out of malloc into function b.") 71*99451b44SJordan Rupprecht self.after_3_step_overs = line_number( 72*99451b44SJordan Rupprecht "main2.cpp", "// we should reach here after 3 step-over's.") 73*99451b44SJordan Rupprecht 74*99451b44SJordan Rupprecht # We'll use the test method name as the exe_name for executable 75*99451b44SJordan Rupprecht # comppiled from main2.cpp. 76*99451b44SJordan Rupprecht self.exe_name = self.testMethodName 77*99451b44SJordan Rupprecht 78*99451b44SJordan Rupprecht def get_process(self): 79*99451b44SJordan Rupprecht """Test Python SBThread.GetProcess() API.""" 80*99451b44SJordan Rupprecht exe = self.getBuildArtifact("a.out") 81*99451b44SJordan Rupprecht 82*99451b44SJordan Rupprecht target = self.dbg.CreateTarget(exe) 83*99451b44SJordan Rupprecht self.assertTrue(target, VALID_TARGET) 84*99451b44SJordan Rupprecht 85*99451b44SJordan Rupprecht breakpoint = target.BreakpointCreateByLocation( 86*99451b44SJordan Rupprecht "main.cpp", self.break_line) 87*99451b44SJordan Rupprecht self.assertTrue(breakpoint, VALID_BREAKPOINT) 88*99451b44SJordan Rupprecht self.runCmd("breakpoint list") 89*99451b44SJordan Rupprecht 90*99451b44SJordan Rupprecht # Launch the process, and do not stop at the entry point. 91*99451b44SJordan Rupprecht process = target.LaunchSimple( 92*99451b44SJordan Rupprecht None, None, self.get_process_working_directory()) 93*99451b44SJordan Rupprecht 94*99451b44SJordan Rupprecht thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) 95*99451b44SJordan Rupprecht self.assertTrue( 96*99451b44SJordan Rupprecht thread.IsValid(), 97*99451b44SJordan Rupprecht "There should be a thread stopped due to breakpoint") 98*99451b44SJordan Rupprecht self.runCmd("process status") 99*99451b44SJordan Rupprecht 100*99451b44SJordan Rupprecht proc_of_thread = thread.GetProcess() 101*99451b44SJordan Rupprecht #print("proc_of_thread:", proc_of_thread) 102*99451b44SJordan Rupprecht self.assertTrue(proc_of_thread.GetProcessID() 103*99451b44SJordan Rupprecht == process.GetProcessID()) 104*99451b44SJordan Rupprecht 105*99451b44SJordan Rupprecht def get_stop_description(self): 106*99451b44SJordan Rupprecht """Test Python SBThread.GetStopDescription() API.""" 107*99451b44SJordan Rupprecht exe = self.getBuildArtifact("a.out") 108*99451b44SJordan Rupprecht 109*99451b44SJordan Rupprecht target = self.dbg.CreateTarget(exe) 110*99451b44SJordan Rupprecht self.assertTrue(target, VALID_TARGET) 111*99451b44SJordan Rupprecht 112*99451b44SJordan Rupprecht breakpoint = target.BreakpointCreateByLocation( 113*99451b44SJordan Rupprecht "main.cpp", self.break_line) 114*99451b44SJordan Rupprecht self.assertTrue(breakpoint, VALID_BREAKPOINT) 115*99451b44SJordan Rupprecht #self.runCmd("breakpoint list") 116*99451b44SJordan Rupprecht 117*99451b44SJordan Rupprecht # Launch the process, and do not stop at the entry point. 118*99451b44SJordan Rupprecht process = target.LaunchSimple( 119*99451b44SJordan Rupprecht None, None, self.get_process_working_directory()) 120*99451b44SJordan Rupprecht 121*99451b44SJordan Rupprecht thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) 122*99451b44SJordan Rupprecht self.assertTrue( 123*99451b44SJordan Rupprecht thread.IsValid(), 124*99451b44SJordan Rupprecht "There should be a thread stopped due to breakpoint") 125*99451b44SJordan Rupprecht 126*99451b44SJordan Rupprecht # Get the stop reason. GetStopDescription expects that we pass in the size of the description 127*99451b44SJordan Rupprecht # we expect plus an additional byte for the null terminator. 128*99451b44SJordan Rupprecht 129*99451b44SJordan Rupprecht # Test with a buffer that is exactly as large as the expected stop reason. 130*99451b44SJordan Rupprecht self.assertEqual("breakpoint 1.1", thread.GetStopDescription(len('breakpoint 1.1') + 1)) 131*99451b44SJordan Rupprecht 132*99451b44SJordan Rupprecht # Test some smaller buffer sizes. 133*99451b44SJordan Rupprecht self.assertEqual("breakpoint", thread.GetStopDescription(len('breakpoint') + 1)) 134*99451b44SJordan Rupprecht self.assertEqual("break", thread.GetStopDescription(len('break') + 1)) 135*99451b44SJordan Rupprecht self.assertEqual("b", thread.GetStopDescription(len('b') + 1)) 136*99451b44SJordan Rupprecht 137*99451b44SJordan Rupprecht # Test that we can pass in a much larger size and still get the right output. 138*99451b44SJordan Rupprecht self.assertEqual("breakpoint 1.1", thread.GetStopDescription(len('breakpoint 1.1') + 100)) 139*99451b44SJordan Rupprecht 140*99451b44SJordan Rupprecht def step_out_of_malloc_into_function_b(self, exe_name): 141*99451b44SJordan Rupprecht """Test Python SBThread.StepOut() API to step out of a malloc call where the call site is at function b().""" 142*99451b44SJordan Rupprecht exe = self.getBuildArtifact(exe_name) 143*99451b44SJordan Rupprecht 144*99451b44SJordan Rupprecht target = self.dbg.CreateTarget(exe) 145*99451b44SJordan Rupprecht self.assertTrue(target, VALID_TARGET) 146*99451b44SJordan Rupprecht 147*99451b44SJordan Rupprecht breakpoint = target.BreakpointCreateByName('malloc') 148*99451b44SJordan Rupprecht self.assertTrue(breakpoint, VALID_BREAKPOINT) 149*99451b44SJordan Rupprecht 150*99451b44SJordan Rupprecht # Launch the process, and do not stop at the entry point. 151*99451b44SJordan Rupprecht process = target.LaunchSimple( 152*99451b44SJordan Rupprecht None, None, self.get_process_working_directory()) 153*99451b44SJordan Rupprecht 154*99451b44SJordan Rupprecht while True: 155*99451b44SJordan Rupprecht thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) 156*99451b44SJordan Rupprecht self.assertTrue( 157*99451b44SJordan Rupprecht thread.IsValid(), 158*99451b44SJordan Rupprecht "There should be a thread stopped due to breakpoint") 159*99451b44SJordan Rupprecht caller_symbol = get_caller_symbol(thread) 160*99451b44SJordan Rupprecht if not caller_symbol: 161*99451b44SJordan Rupprecht self.fail( 162*99451b44SJordan Rupprecht "Test failed: could not locate the caller symbol of malloc") 163*99451b44SJordan Rupprecht 164*99451b44SJordan Rupprecht # Our top frame may be an inlined function in malloc() (e.g., on 165*99451b44SJordan Rupprecht # FreeBSD). Apply a simple heuristic of stepping out until we find 166*99451b44SJordan Rupprecht # a non-malloc caller 167*99451b44SJordan Rupprecht while caller_symbol.startswith("malloc"): 168*99451b44SJordan Rupprecht thread.StepOut() 169*99451b44SJordan Rupprecht self.assertTrue(thread.IsValid(), 170*99451b44SJordan Rupprecht "Thread valid after stepping to outer malloc") 171*99451b44SJordan Rupprecht caller_symbol = get_caller_symbol(thread) 172*99451b44SJordan Rupprecht 173*99451b44SJordan Rupprecht if caller_symbol == "b(int)": 174*99451b44SJordan Rupprecht break 175*99451b44SJordan Rupprecht process.Continue() 176*99451b44SJordan Rupprecht 177*99451b44SJordan Rupprecht # On Linux malloc calls itself in some case. Remove the breakpoint because we don't want 178*99451b44SJordan Rupprecht # to hit it during step-out. 179*99451b44SJordan Rupprecht target.BreakpointDelete(breakpoint.GetID()) 180*99451b44SJordan Rupprecht 181*99451b44SJordan Rupprecht thread.StepOut() 182*99451b44SJordan Rupprecht self.runCmd("thread backtrace") 183*99451b44SJordan Rupprecht self.assertTrue( 184*99451b44SJordan Rupprecht thread.GetFrameAtIndex(0).GetLineEntry().GetLine() == self.step_out_of_malloc, 185*99451b44SJordan Rupprecht "step out of malloc into function b is successful") 186*99451b44SJordan Rupprecht 187*99451b44SJordan Rupprecht def step_over_3_times(self, exe_name): 188*99451b44SJordan Rupprecht """Test Python SBThread.StepOver() API.""" 189*99451b44SJordan Rupprecht exe = self.getBuildArtifact(exe_name) 190*99451b44SJordan Rupprecht 191*99451b44SJordan Rupprecht target = self.dbg.CreateTarget(exe) 192*99451b44SJordan Rupprecht self.assertTrue(target, VALID_TARGET) 193*99451b44SJordan Rupprecht 194*99451b44SJordan Rupprecht breakpoint = target.BreakpointCreateByLocation( 195*99451b44SJordan Rupprecht 'main2.cpp', self.step_out_of_malloc) 196*99451b44SJordan Rupprecht self.assertTrue(breakpoint, VALID_BREAKPOINT) 197*99451b44SJordan Rupprecht self.runCmd("breakpoint list") 198*99451b44SJordan Rupprecht 199*99451b44SJordan Rupprecht # Launch the process, and do not stop at the entry point. 200*99451b44SJordan Rupprecht process = target.LaunchSimple( 201*99451b44SJordan Rupprecht None, None, self.get_process_working_directory()) 202*99451b44SJordan Rupprecht 203*99451b44SJordan Rupprecht self.assertTrue(process, PROCESS_IS_VALID) 204*99451b44SJordan Rupprecht 205*99451b44SJordan Rupprecht # Frame #0 should be on self.step_out_of_malloc. 206*99451b44SJordan Rupprecht self.assertTrue(process.GetState() == lldb.eStateStopped) 207*99451b44SJordan Rupprecht thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) 208*99451b44SJordan Rupprecht self.assertTrue( 209*99451b44SJordan Rupprecht thread.IsValid(), 210*99451b44SJordan Rupprecht "There should be a thread stopped due to breakpoint condition") 211*99451b44SJordan Rupprecht self.runCmd("thread backtrace") 212*99451b44SJordan Rupprecht frame0 = thread.GetFrameAtIndex(0) 213*99451b44SJordan Rupprecht lineEntry = frame0.GetLineEntry() 214*99451b44SJordan Rupprecht self.assertTrue(lineEntry.GetLine() == self.step_out_of_malloc) 215*99451b44SJordan Rupprecht 216*99451b44SJordan Rupprecht thread.StepOver() 217*99451b44SJordan Rupprecht thread.StepOver() 218*99451b44SJordan Rupprecht thread.StepOver() 219*99451b44SJordan Rupprecht self.runCmd("thread backtrace") 220*99451b44SJordan Rupprecht 221*99451b44SJordan Rupprecht # Verify that we are stopped at the correct source line number in 222*99451b44SJordan Rupprecht # main2.cpp. 223*99451b44SJordan Rupprecht frame0 = thread.GetFrameAtIndex(0) 224*99451b44SJordan Rupprecht lineEntry = frame0.GetLineEntry() 225*99451b44SJordan Rupprecht self.assertTrue(thread.GetStopReason() == lldb.eStopReasonPlanComplete) 226*99451b44SJordan Rupprecht # Expected failure with clang as the compiler. 227*99451b44SJordan Rupprecht # rdar://problem/9223880 228*99451b44SJordan Rupprecht # 229*99451b44SJordan Rupprecht # Which has been fixed on the lldb by compensating for inaccurate line 230*99451b44SJordan Rupprecht # table information with r140416. 231*99451b44SJordan Rupprecht self.assertTrue(lineEntry.GetLine() == self.after_3_step_overs) 232*99451b44SJordan Rupprecht 233*99451b44SJordan Rupprecht def run_to_address(self, exe_name): 234*99451b44SJordan Rupprecht """Test Python SBThread.RunToAddress() API.""" 235*99451b44SJordan Rupprecht exe = self.getBuildArtifact(exe_name) 236*99451b44SJordan Rupprecht 237*99451b44SJordan Rupprecht target = self.dbg.CreateTarget(exe) 238*99451b44SJordan Rupprecht self.assertTrue(target, VALID_TARGET) 239*99451b44SJordan Rupprecht 240*99451b44SJordan Rupprecht breakpoint = target.BreakpointCreateByLocation( 241*99451b44SJordan Rupprecht 'main2.cpp', self.step_out_of_malloc) 242*99451b44SJordan Rupprecht self.assertTrue(breakpoint, VALID_BREAKPOINT) 243*99451b44SJordan Rupprecht self.runCmd("breakpoint list") 244*99451b44SJordan Rupprecht 245*99451b44SJordan Rupprecht # Launch the process, and do not stop at the entry point. 246*99451b44SJordan Rupprecht process = target.LaunchSimple( 247*99451b44SJordan Rupprecht None, None, self.get_process_working_directory()) 248*99451b44SJordan Rupprecht 249*99451b44SJordan Rupprecht self.assertTrue(process, PROCESS_IS_VALID) 250*99451b44SJordan Rupprecht 251*99451b44SJordan Rupprecht # Frame #0 should be on self.step_out_of_malloc. 252*99451b44SJordan Rupprecht self.assertTrue(process.GetState() == lldb.eStateStopped) 253*99451b44SJordan Rupprecht thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) 254*99451b44SJordan Rupprecht self.assertTrue( 255*99451b44SJordan Rupprecht thread.IsValid(), 256*99451b44SJordan Rupprecht "There should be a thread stopped due to breakpoint condition") 257*99451b44SJordan Rupprecht self.runCmd("thread backtrace") 258*99451b44SJordan Rupprecht frame0 = thread.GetFrameAtIndex(0) 259*99451b44SJordan Rupprecht lineEntry = frame0.GetLineEntry() 260*99451b44SJordan Rupprecht self.assertTrue(lineEntry.GetLine() == self.step_out_of_malloc) 261*99451b44SJordan Rupprecht 262*99451b44SJordan Rupprecht # Get the start/end addresses for this line entry. 263*99451b44SJordan Rupprecht start_addr = lineEntry.GetStartAddress().GetLoadAddress(target) 264*99451b44SJordan Rupprecht end_addr = lineEntry.GetEndAddress().GetLoadAddress(target) 265*99451b44SJordan Rupprecht if self.TraceOn(): 266*99451b44SJordan Rupprecht print("start addr:", hex(start_addr)) 267*99451b44SJordan Rupprecht print("end addr:", hex(end_addr)) 268*99451b44SJordan Rupprecht 269*99451b44SJordan Rupprecht # Disable the breakpoint. 270*99451b44SJordan Rupprecht self.assertTrue(target.DisableAllBreakpoints()) 271*99451b44SJordan Rupprecht self.runCmd("breakpoint list") 272*99451b44SJordan Rupprecht 273*99451b44SJordan Rupprecht thread.StepOver() 274*99451b44SJordan Rupprecht thread.StepOver() 275*99451b44SJordan Rupprecht thread.StepOver() 276*99451b44SJordan Rupprecht self.runCmd("thread backtrace") 277*99451b44SJordan Rupprecht 278*99451b44SJordan Rupprecht # Now ask SBThread to run to the address 'start_addr' we got earlier, which 279*99451b44SJordan Rupprecht # corresponds to self.step_out_of_malloc line entry's start address. 280*99451b44SJordan Rupprecht thread.RunToAddress(start_addr) 281*99451b44SJordan Rupprecht self.runCmd("process status") 282*99451b44SJordan Rupprecht #self.runCmd("thread backtrace") 283