262 lines · python
1"""2Test that the Python operating system plugin works correctly3"""4 5 6import os7import lldb8from lldbsuite.test.decorators import *9from lldbsuite.test.lldbtest import *10import lldbsuite.test.lldbutil as lldbutil11 12 13class PluginPythonOSPlugin(TestBase):14 NO_DEBUG_INFO_TESTCASE = True15 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 Windows22 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() + 131 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 + 138 39 def run_python_os_funcionality(self):40 """Test that the Python operating system plugin works correctly"""41 42 # Set debugger into synchronous mode43 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 the52 # 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 get56 # automatically uploaded57 arguments = None58 environment = None59 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 stop67 # at our breakpoint in main68 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 have85 # OS plug-in created threads with the IDs: 0x111111111, 0x222222222,86 # 0x33333333387 command = (88 "settings set target.process.python-os-plugin-path '%s'"89 % python_os_plugin_path90 )91 self.dbg.HandleCommand(command)92 93 # Verify our OS plug-in threads showed up94 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 threads114 # disappear115 self.dbg.HandleCommand("settings clear target.process.python-os-plugin-path")116 117 # Verify the threads are gone after unloading the python OS plug-in118 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 tid_regex = re.compile(r"tid = ((0x)?[0-9a-fA-F]+)")135 136 def get_tid_from_thread_info_command(self, thread, use_backing_thread):137 interp = self.dbg.GetCommandInterpreter()138 result = lldb.SBCommandReturnObject()139 140 backing_thread_arg = ""141 if use_backing_thread:142 backing_thread_arg = "--backing-thread"143 144 interp.HandleCommand(145 "thread info {0} {1}".format(thread.GetIndexID(), backing_thread_arg),146 result,147 True,148 )149 self.assertTrue(result.Succeeded(), "failed to run thread info")150 match = self.tid_regex.search(result.GetOutput())151 self.assertNotEqual(match, None)152 return int(match.group(1), 0)153 154 def run_python_os_step(self):155 """Test that the Python operating system plugin works correctly and allows single stepping of a virtual thread that is backed by a real thread"""156 157 # Set debugger into synchronous mode158 self.dbg.SetAsync(False)159 160 # Create a target by the debugger.161 exe = self.getBuildArtifact("a.out")162 python_os_plugin_path = os.path.join(163 self.getSourceDir(), "operating_system2.py"164 )165 target = self.dbg.CreateTarget(exe)166 self.assertTrue(target, VALID_TARGET)167 168 # Set breakpoints inside and outside methods that take pointers to the169 # containing struct.170 lldbutil.run_break_set_by_source_regexp(self, "// Set breakpoint here")171 172 # Register our shared libraries for remote targets so they get173 # automatically uploaded174 arguments = None175 environment = None176 177 # Now launch the process, and do not stop at entry point.178 process = target.LaunchSimple(179 arguments, environment, self.get_process_working_directory()180 )181 self.assertTrue(process, PROCESS_IS_VALID)182 183 core_thread_zero = process.GetThreadAtIndex(0)184 185 # Make sure there are no OS plug-in created thread when we first stop186 # at our breakpoint in main187 thread = process.GetThreadByID(0x111111111)188 self.assertFalse(189 thread.IsValid(),190 "Make sure there is no thread 0x111111111 before we load the python OS plug-in",191 )192 193 # Now load the python OS plug-in which should update the thread list and we should have194 # OS plug-in created threads with the IDs: 0x111111111, 0x222222222,195 # 0x333333333196 command = (197 "settings set target.process.python-os-plugin-path '%s'"198 % python_os_plugin_path199 )200 self.dbg.HandleCommand(command)201 202 # Verify our OS plug-in threads showed up203 thread = process.GetThreadByID(0x111111111)204 self.assertTrue(205 thread.IsValid(),206 "Make sure there is a thread 0x111111111 after we load the python OS plug-in",207 )208 # This OS plugin does not set thread names / queue names, so it should209 # inherit the core thread's name.210 self.assertEqual(core_thread_zero.GetName(), thread.GetName())211 self.assertEqual(core_thread_zero.GetQueueName(), thread.GetQueueName())212 213 frame = thread.GetFrameAtIndex(0)214 self.assertTrue(215 frame.IsValid(), "Make sure we get a frame from thread 0x111111111"216 )217 line_entry = frame.GetLineEntry()218 219 self.assertEqual(220 line_entry.GetFileSpec().GetFilename(),221 "main.c",222 "Make sure we stopped on line 5 in main.c",223 )224 self.assertEqual(225 line_entry.GetLine(), 5, "Make sure we stopped on line 5 in main.c"226 )227 228 # Now single step thread 0x111111111 and make sure it does what we need229 # it to230 thread.StepOver()231 232 tid_os = self.get_tid_from_thread_info_command(thread, False)233 self.assertEqual(tid_os, 0x111111111)234 tid_real = self.get_tid_from_thread_info_command(thread, True)235 self.assertNotEqual(tid_os, tid_real)236 237 frame = thread.GetFrameAtIndex(0)238 self.assertTrue(239 frame.IsValid(), "Make sure we get a frame from thread 0x111111111"240 )241 line_entry = frame.GetLineEntry()242 243 self.assertEqual(244 line_entry.GetFileSpec().GetFilename(),245 "main.c",246 "Make sure we stepped from line 5 to line 6 in main.c",247 )248 self.assertEqual(249 line_entry.GetLine(),250 6,251 "Make sure we stepped from line 5 to line 6 in main.c",252 )253 254 thread_bp_number = lldbutil.run_break_set_by_source_regexp(255 self, "Set tid-specific breakpoint here", num_expected_locations=1256 )257 breakpoint = target.FindBreakpointByID(thread_bp_number)258 # This breakpoint should not be hit.259 breakpoint.SetThreadID(123)260 process.Continue()261 self.assertState(process.GetState(), lldb.eStateExited)262