10645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea""" 20645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel MaleaTest stepping out from a function in a multi-threaded program. 30645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea""" 40645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 50645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Maleaimport os, time 60645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Maleaimport unittest2 70645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Maleaimport lldb 80645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Maleafrom lldbtest import * 90645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Maleaimport lldbutil 100645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 110645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Maleaclass ThreadStepOutTestCase(TestBase): 120645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 130645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea mydir = os.path.join("functionalities", "thread", "step_out") 140645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 150645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea @dsym_test 160645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea def test_step_single_thread_with_dsym(self): 170645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea """Test thread step out on one thread via command interpreter. """ 180645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.buildDsym(dictionary=self.getBuildFlags()) 190645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.step_out_test(self.step_out_single_thread_with_cmd) 200645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 214edd4b4d295e07afc6a7c157f2693a110de49964Ed Maste @expectedFailureFreeBSD("llvm.org/pr16696") # threaded inferior not yet implemented on FreeBSD 220645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea @dwarf_test 230645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea def test_step_single_thread_with_dwarf(self): 240645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea """Test thread step out on one thread via command interpreter. """ 250645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.buildDwarf(dictionary=self.getBuildFlags()) 260645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.step_out_test(self.step_out_single_thread_with_cmd) 270645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 280645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea @dsym_test 290645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea def test_step_all_threads_with_dsym(self): 300645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea """Test thread step out on all threads via command interpreter. """ 310645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.buildDsym(dictionary=self.getBuildFlags()) 320645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.step_out_test(self.step_out_all_threads_with_cmd) 330645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 344edd4b4d295e07afc6a7c157f2693a110de49964Ed Maste @expectedFailureFreeBSD("llvm.org/pr16696") # threaded inferior not yet implemented on FreeBSD 350645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea @dwarf_test 360645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea def test_step_all_threads_with_dwarf(self): 370645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea """Test thread step out on all threads via command interpreter. """ 380645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.buildDwarf(dictionary=self.getBuildFlags()) 390645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.step_out_test(self.step_out_all_threads_with_cmd) 400645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 410645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea @dsym_test 420645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea def test_python_with_dsym(self): 430645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea """Test thread step out on one threads via Python API (dsym).""" 440645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.buildDsym(dictionary=self.getBuildFlags()) 450645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.step_out_test(self.step_out_with_python) 460645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 474edd4b4d295e07afc6a7c157f2693a110de49964Ed Maste @expectedFailureFreeBSD("llvm.org/pr16696") # threaded inferior not yet implemented on FreeBSD 480645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea @dwarf_test 490645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea def test_python_with_dwarf(self): 500645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea """Test thread step out on one thread via Python API (dwarf).""" 510645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.buildDwarf(dictionary=self.getBuildFlags()) 520645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.step_out_test(self.step_out_with_python) 530645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 540645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea def setUp(self): 550645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea # Call super's setUp(). 560645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea TestBase.setUp(self) 570645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea # Find the line number for our breakpoint. 580645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.breakpoint = line_number('main.cpp', '// Set breakpoint here') 59e0d9e7543b684ffedabc9b39f4e4910eb975099eDaniel Malea if "gcc" in self.getCompiler() or self.isIntelCompiler(): 609de79f93e058445afc9f8c131f9a4bb57654fe44Daniel Malea self.step_out_destination = line_number('main.cpp', '// Expect to stop here after step-out (icc and gcc)') 614a217a5a91a9575a15f494a4e08d2a09ea5adf2cAshok Thirumurthi else: 629de79f93e058445afc9f8c131f9a4bb57654fe44Daniel Malea self.step_out_destination = line_number('main.cpp', '// Expect to stop here after step-out (clang)') 630645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 640645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea def step_out_single_thread_with_cmd(self): 650645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.step_out_with_cmd("this-thread") 660645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.expect("thread backtrace all", "Thread location after step out is correct", 670645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea substrs = ["main.cpp:%d" % self.step_out_destination, 680645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea "main.cpp:%d" % self.breakpoint]) 690645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 700645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea def step_out_all_threads_with_cmd(self): 710645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.step_out_with_cmd("all-threads") 720645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.expect("thread backtrace all", "Thread location after step out is correct", 730645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea substrs = ["main.cpp:%d" % self.step_out_destination]) 740645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 750645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea def step_out_with_cmd(self, run_mode): 760645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.runCmd("thread select %d" % self.step_out_thread.GetIndexID()) 770645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.runCmd("thread step-out -m %s" % run_mode) 780645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.expect("process status", "Expected stop reason to be step-out", 790645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea substrs = ["stop reason = step out"]) 800645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 810645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.expect("thread list", "Selected thread did not change during step-out", 820645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea substrs = ["* thread #%d" % self.step_out_thread.GetIndexID()]) 830645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 840645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea def step_out_with_python(self): 850645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.step_out_thread.StepOut() 860645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 870645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea reason = self.step_out_thread.GetStopReason() 880645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.assertEqual(lldb.eStopReasonPlanComplete, reason, 890645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea "Expected thread stop reason 'plancomplete', but got '%s'" % lldbutil.stop_reason_to_str(reason)) 900645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 910645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea # Verify location after stepping out 920645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea frame = self.step_out_thread.GetFrameAtIndex(0) 930645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea desc = lldbutil.get_description(frame.GetLineEntry()) 940645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea expect = "main.cpp:%d" % self.step_out_destination 950645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.assertTrue(expect in desc, "Expected %s but thread stopped at %s" % (expect, desc)) 960645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 970645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea def step_out_test(self, step_out_func): 980645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea """Test single thread step out of a function.""" 990645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea exe = os.path.join(os.getcwd(), "a.out") 1000645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 1010645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 1020645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea # This should create a breakpoint in the main thread. 1030645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.breakpoint, num_expected_locations=1) 1040645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 1050645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea # The breakpoint list should show 1 location. 1060645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.expect("breakpoint list -f", "Breakpoint location shown correctly", 1070645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea substrs = ["1: file = 'main.cpp', line = %d, locations = 1" % self.breakpoint]) 1080645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 1090645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea # Run the program. 1100645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.runCmd("run", RUN_SUCCEEDED) 1110645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 1120645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea # Get the target process 1130645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.inferior_target = self.dbg.GetSelectedTarget() 1140645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.inferior_process = self.inferior_target.GetProcess() 1150645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 1160645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea # Get the number of threads, ensure we see all three. 1170645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea num_threads = self.inferior_process.GetNumThreads() 1180645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.assertEqual(num_threads, 3, 'Number of expected threads and actual threads do not match.') 1190645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 1200645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea (breakpoint_threads, other_threads) = ([], []) 1210645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea lldbutil.sort_stopped_threads(self.inferior_process, 1220645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea breakpoint_threads=breakpoint_threads, 1230645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea other_threads=other_threads) 1240645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 1250645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea while len(breakpoint_threads) < 2: 1260645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.runCmd("thread continue %s" % " ".join([str(x.GetIndexID()) for x in other_threads])) 1270645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea lldbutil.sort_stopped_threads(self.inferior_process, 1280645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea breakpoint_threads=breakpoint_threads, 1290645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea other_threads=other_threads) 1300645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 1310645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.step_out_thread = breakpoint_threads[0] 1320645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 1330645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea # Step out of thread stopped at breakpoint 1340645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea step_out_func() 1350645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 1360645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea # Run to completion 1370645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.runCmd("continue") 1380645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 1390645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea # At this point, the inferior process should have exited. 1400645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea self.assertTrue(self.inferior_process.GetState() == lldb.eStateExited, PROCESS_EXITED) 1410645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea 1420645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Maleaif __name__ == '__main__': 1430645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea import atexit 1440645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea lldb.SBDebugger.Initialize() 1450645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea atexit.register(lambda: lldb.SBDebugger.Terminate()) 1460645d187d2061b7b1690b2ead7aaf8f7736cf873Daniel Malea unittest2.main() 147