1""" 2Test that stepping works even when the OS Plugin doesn't report 3all threads at every stop. 4""" 5 6from __future__ import print_function 7 8 9import os 10import lldb 11from lldbsuite.test.decorators import * 12from lldbsuite.test.lldbtest import * 13import lldbsuite.test.lldbutil as lldbutil 14 15 16class TestOSPluginStepping(TestBase): 17 NO_DEBUG_INFO_TESTCASE = True 18 19 @skipIfWindows 20 @skipIf(oslist=["freebsd"], bugnumber="llvm.org/pr48352") 21 def test_python_os_plugin(self): 22 """Test that stepping works when the OS Plugin doesn't report all 23 threads at every stop""" 24 self.build() 25 self.main_file = lldb.SBFileSpec('main.cpp') 26 self.run_python_os_step_missing_thread(False) 27 28 @skipIfWindows 29 @skipIf(oslist=["freebsd"], bugnumber="llvm.org/pr48352") 30 def test_python_os_plugin_prune(self): 31 """Test that pruning the unreported PlanStacks works""" 32 self.build() 33 self.main_file = lldb.SBFileSpec('main.cpp') 34 self.run_python_os_step_missing_thread(True) 35 36 def get_os_thread(self): 37 return self.process.GetThreadByID(0x111111111) 38 39 def is_os_thread(self, thread): 40 id = thread.GetID() 41 return id == 0x111111111 42 43 def run_python_os_step_missing_thread(self, do_prune): 44 """Test that the Python operating system plugin works correctly""" 45 46 # Our OS plugin does NOT report all threads: 47 result = self.dbg.HandleCommand("settings set process.experimental.os-plugin-reports-all-threads false") 48 49 python_os_plugin_path = os.path.join(self.getSourceDir(), 50 "operating_system.py") 51 (target, self.process, thread, thread_bkpt) = lldbutil.run_to_source_breakpoint( 52 self, "first stop in thread - do a step out", self.main_file) 53 54 main_bkpt = target.BreakpointCreateBySourceRegex('Stop here and do not make a memory thread for thread_1', 55 self.main_file) 56 self.assertEqual(main_bkpt.GetNumLocations(), 1, "Main breakpoint has one location") 57 58 # There should not be an os thread before we load the plugin: 59 self.assertFalse(self.get_os_thread().IsValid(), "No OS thread before loading plugin") 60 61 # Now load the python OS plug-in which should update the thread list and we should have 62 # an OS plug-in thread overlaying thread_1 with id 0x111111111 63 command = "settings set target.process.python-os-plugin-path '%s'" % python_os_plugin_path 64 self.dbg.HandleCommand(command) 65 66 # Verify our OS plug-in threads showed up 67 os_thread = self.get_os_thread() 68 self.assertTrue( 69 os_thread.IsValid(), 70 "Make sure we added the thread 0x111111111 after we load the python OS plug-in") 71 72 # Now we are going to step-out. This should get interrupted by main_bkpt. We've 73 # set up the OS plugin so at this stop, we have lost the OS thread 0x111111111. 74 # Make sure both of these are true: 75 os_thread.StepOut() 76 77 stopped_threads = lldbutil.get_threads_stopped_at_breakpoint(self.process, main_bkpt) 78 self.assertEqual(len(stopped_threads), 1, "Stopped at main_bkpt") 79 thread = self.process.GetThreadByID(0x111111111) 80 self.assertFalse(thread.IsValid(), "No thread 0x111111111 on second stop.") 81 82 # Make sure we still have the thread plans for this thread: 83 # First, don't show unreported threads, that should fail: 84 command = "thread plan list -t 0x111111111" 85 result = lldb.SBCommandReturnObject() 86 interp = self.dbg.GetCommandInterpreter() 87 interp.HandleCommand(command, result) 88 self.assertFalse(result.Succeeded(), "We found no plans for the unreported thread.") 89 # Now do it again but with the -u flag: 90 command = "thread plan list -u -t 0x111111111" 91 result = lldb.SBCommandReturnObject() 92 interp.HandleCommand(command, result) 93 self.assertTrue(result.Succeeded(), "We found plans for the unreported thread.") 94 95 if do_prune: 96 # Prune the thread plan and continue, and we will run to exit. 97 interp.HandleCommand("thread plan prune 0x111111111", result) 98 self.assertTrue(result.Succeeded(), "Found the plan for 0x111111111 and pruned it") 99 100 # List again, make sure it doesn't work: 101 command = "thread plan list -u -t 0x111111111" 102 interp.HandleCommand(command, result) 103 self.assertFalse(result.Succeeded(), "We still found plans for the unreported thread.") 104 105 self.process.Continue() 106 self.assertState(self.process.GetState(), lldb.eStateExited, "We exited.") 107 else: 108 # Now we are going to continue, and when we hit the step-out breakpoint, we will 109 # put the OS plugin thread back, lldb will recover its ThreadPlanStack, and 110 # we will stop with a "step-out" reason. 111 self.process.Continue() 112 os_thread = self.get_os_thread() 113 self.assertTrue(os_thread.IsValid(), "The OS thread is back after continue") 114 self.assertIn("step out", os_thread.GetStopDescription(100), "Completed step out plan") 115