1""" 2Test that the Python operating system plugin works correctly 3""" 4 5 6import os 7import lldb 8from lldbsuite.test.decorators import * 9from lldbsuite.test.lldbtest import * 10import lldbsuite.test.lldbutil as lldbutil 11 12 13class PluginPythonOSPlugin(TestBase): 14 NO_DEBUG_INFO_TESTCASE = True 15 16 def test_python_os_plugin(self): 17 """Test that the Python operating system plugin works correctly""" 18 self.build() 19 self.run_python_os_funcionality() 20 21 @skipIfWindows # This is flaky on Windows 22 def test_run_python_os_step(self): 23 """Test that the Python operating system plugin works correctly when single stepping a virtual thread""" 24 self.build() 25 self.run_python_os_step() 26 27 def verify_os_thread_registers(self, thread): 28 frame = thread.GetFrameAtIndex(0) 29 registers = frame.GetRegisters().GetValueAtIndex(0) 30 reg_value = thread.GetThreadID() + 1 31 for reg in registers: 32 self.assertEqual( 33 reg.GetValueAsUnsigned(), 34 reg_value, 35 "Verify the registers contains the correct value", 36 ) 37 reg_value = reg_value + 1 38 39 def run_python_os_funcionality(self): 40 """Test that the Python operating system plugin works correctly""" 41 42 # Set debugger into synchronous mode 43 self.dbg.SetAsync(False) 44 45 # Create a target by the debugger. 46 exe = self.getBuildArtifact("a.out") 47 python_os_plugin_path = os.path.join(self.getSourceDir(), "operating_system.py") 48 target = self.dbg.CreateTarget(exe) 49 self.assertTrue(target, VALID_TARGET) 50 51 # Set breakpoints inside and outside methods that take pointers to the 52 # containing struct. 53 lldbutil.run_break_set_by_source_regexp(self, "// Set breakpoint here") 54 55 # Register our shared libraries for remote targets so they get 56 # automatically uploaded 57 arguments = None 58 environment = None 59 60 # Now launch the process, and do not stop at entry point. 61 process = target.LaunchSimple( 62 arguments, environment, self.get_process_working_directory() 63 ) 64 self.assertTrue(process, PROCESS_IS_VALID) 65 66 # Make sure there are no OS plug-in created thread when we first stop 67 # at our breakpoint in main 68 thread = process.GetThreadByID(0x111111111) 69 self.assertFalse( 70 thread.IsValid(), 71 "Make sure there is no thread 0x111111111 before we load the python OS plug-in", 72 ) 73 thread = process.GetThreadByID(0x222222222) 74 self.assertFalse( 75 thread.IsValid(), 76 "Make sure there is no thread 0x222222222 before we load the python OS plug-in", 77 ) 78 thread = process.GetThreadByID(0x333333333) 79 self.assertFalse( 80 thread.IsValid(), 81 "Make sure there is no thread 0x333333333 before we load the python OS plug-in", 82 ) 83 84 # Now load the python OS plug-in which should update the thread list and we should have 85 # OS plug-in created threads with the IDs: 0x111111111, 0x222222222, 86 # 0x333333333 87 command = ( 88 "settings set target.process.python-os-plugin-path '%s'" 89 % python_os_plugin_path 90 ) 91 self.dbg.HandleCommand(command) 92 93 # Verify our OS plug-in threads showed up 94 thread = process.GetThreadByID(0x111111111) 95 self.assertTrue( 96 thread.IsValid(), 97 "Make sure there is a thread 0x111111111 after we load the python OS plug-in", 98 ) 99 self.verify_os_thread_registers(thread) 100 thread = process.GetThreadByID(0x222222222) 101 self.assertTrue( 102 thread.IsValid(), 103 "Make sure there is a thread 0x222222222 after we load the python OS plug-in", 104 ) 105 self.verify_os_thread_registers(thread) 106 thread = process.GetThreadByID(0x333333333) 107 self.assertTrue( 108 thread.IsValid(), 109 "Make sure there is a thread 0x333333333 after we load the python OS plug-in", 110 ) 111 self.verify_os_thread_registers(thread) 112 113 # Now clear the OS plug-in path to make the OS plug-in created threads 114 # disappear 115 self.dbg.HandleCommand("settings clear target.process.python-os-plugin-path") 116 117 # Verify the threads are gone after unloading the python OS plug-in 118 thread = process.GetThreadByID(0x111111111) 119 self.assertFalse( 120 thread.IsValid(), 121 "Make sure there is no thread 0x111111111 after we unload the python OS plug-in", 122 ) 123 thread = process.GetThreadByID(0x222222222) 124 self.assertFalse( 125 thread.IsValid(), 126 "Make sure there is no thread 0x222222222 after we unload the python OS plug-in", 127 ) 128 thread = process.GetThreadByID(0x333333333) 129 self.assertFalse( 130 thread.IsValid(), 131 "Make sure there is no thread 0x333333333 after we unload the python OS plug-in", 132 ) 133 134 def run_python_os_step(self): 135 """Test that the Python operating system plugin works correctly and allows single stepping of a virtual thread that is backed by a real thread""" 136 137 # Set debugger into synchronous mode 138 self.dbg.SetAsync(False) 139 140 # Create a target by the debugger. 141 exe = self.getBuildArtifact("a.out") 142 python_os_plugin_path = os.path.join( 143 self.getSourceDir(), "operating_system2.py" 144 ) 145 target = self.dbg.CreateTarget(exe) 146 self.assertTrue(target, VALID_TARGET) 147 148 # Set breakpoints inside and outside methods that take pointers to the 149 # containing struct. 150 lldbutil.run_break_set_by_source_regexp(self, "// Set breakpoint here") 151 152 # Register our shared libraries for remote targets so they get 153 # automatically uploaded 154 arguments = None 155 environment = None 156 157 # Now launch the process, and do not stop at entry point. 158 process = target.LaunchSimple( 159 arguments, environment, self.get_process_working_directory() 160 ) 161 self.assertTrue(process, PROCESS_IS_VALID) 162 163 # Make sure there are no OS plug-in created thread when we first stop 164 # at our breakpoint in main 165 thread = process.GetThreadByID(0x111111111) 166 self.assertFalse( 167 thread.IsValid(), 168 "Make sure there is no thread 0x111111111 before we load the python OS plug-in", 169 ) 170 171 # Now load the python OS plug-in which should update the thread list and we should have 172 # OS plug-in created threads with the IDs: 0x111111111, 0x222222222, 173 # 0x333333333 174 command = ( 175 "settings set target.process.python-os-plugin-path '%s'" 176 % python_os_plugin_path 177 ) 178 self.dbg.HandleCommand(command) 179 180 # Verify our OS plug-in threads showed up 181 thread = process.GetThreadByID(0x111111111) 182 self.assertTrue( 183 thread.IsValid(), 184 "Make sure there is a thread 0x111111111 after we load the python OS plug-in", 185 ) 186 187 frame = thread.GetFrameAtIndex(0) 188 self.assertTrue( 189 frame.IsValid(), "Make sure we get a frame from thread 0x111111111" 190 ) 191 line_entry = frame.GetLineEntry() 192 193 self.assertEqual( 194 line_entry.GetFileSpec().GetFilename(), 195 "main.c", 196 "Make sure we stopped on line 5 in main.c", 197 ) 198 self.assertEqual( 199 line_entry.GetLine(), 5, "Make sure we stopped on line 5 in main.c" 200 ) 201 202 # Now single step thread 0x111111111 and make sure it does what we need 203 # it to 204 thread.StepOver() 205 206 frame = thread.GetFrameAtIndex(0) 207 self.assertTrue( 208 frame.IsValid(), "Make sure we get a frame from thread 0x111111111" 209 ) 210 line_entry = frame.GetLineEntry() 211 212 self.assertEqual( 213 line_entry.GetFileSpec().GetFilename(), 214 "main.c", 215 "Make sure we stepped from line 5 to line 6 in main.c", 216 ) 217 self.assertEqual( 218 line_entry.GetLine(), 219 6, 220 "Make sure we stepped from line 5 to line 6 in main.c", 221 ) 222 223 thread_bp_number = lldbutil.run_break_set_by_source_regexp( 224 self, "Set tid-specific breakpoint here", num_expected_locations=1 225 ) 226 breakpoint = target.FindBreakpointByID(thread_bp_number) 227 # This breakpoint should not be hit. 228 breakpoint.SetThreadID(123) 229 process.Continue() 230 self.assertState(process.GetState(), lldb.eStateExited) 231