def test_with_python_api(self): """Test function call thread safety.""" self.build() exe = os.path.join(os.getcwd(), "a.out") target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) self.main_source_spec = lldb.SBFileSpec(self.main_source) break1 = target.BreakpointCreateByName("stopper", 'a.out') self.assertTrue(break1, VALID_BREAKPOINT) process = target.LaunchSimple(None, None, self.get_process_working_directory()) self.assertTrue(process, PROCESS_IS_VALID) threads = lldbutil.get_threads_stopped_at_breakpoint(process, break1) if len(threads) != 1: self.fail("Failed to stop at breakpoint 1.") self.check_number_of_threads(process) main_thread = lldb.SBThread() select_thread = lldb.SBThread() for idx in range(0, process.GetNumThreads()): t = process.GetThreadAtIndex(idx) if t.GetName() == "main thread": main_thread = t if t.GetName() == "select thread": select_thread = t self.assertTrue(main_thread.IsValid() and select_thread.IsValid(), "Got both expected threads") self.safe_to_call_func_on_main_thread(main_thread) self.safe_to_call_func_on_select_thread(select_thread)
def test_with_python_api(self): """Test that we get thread names when interrupting a process.""" self.build() exe = os.path.join(os.getcwd(), "a.out") target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) launch_info = lldb.SBLaunchInfo(None) error = lldb.SBError() lldb.debugger.SetAsync(True) process = target.Launch(launch_info, error) self.assertTrue(process, PROCESS_IS_VALID) listener = lldb.debugger.GetListener() broadcaster = process.GetBroadcaster() rc = broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged) self.assertTrue(rc != 0, "Unable to add listener to process") self.assertTrue(self.wait_for_running(process, listener), "Check that process is up and running") inferior_set_up = self.wait_until_program_setup_complete( process, listener) self.assertTrue( inferior_set_up.IsValid() and inferior_set_up.GetValueAsSigned() == 1, "Check that the program was able to create its threads within the allotted time" ) self.check_number_of_threads(process) main_thread = lldb.SBThread() second_thread = lldb.SBThread() third_thread = lldb.SBThread() for idx in range(0, process.GetNumThreads()): t = process.GetThreadAtIndex(idx) if t.GetName() == "main thread": main_thread = t if t.GetName() == "second thread": second_thread = t if t.GetName() == "third thread": third_thread = t self.check_expected_threads_present(main_thread, second_thread, third_thread) process.Kill()
def test_SBThread(self): obj = lldb.SBThread() if self.TraceOn(): print obj self.assertFalse(obj) # Do fuzz testing on the invalid obj, it should not crash lldb. import sb_thread sb_thread.fuzz_obj(obj)
def test_with_python_api(self): """Test function call thread safety.""" self.build() exe = self.getBuildArtifact("a.out") target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) self.main_source_spec = lldb.SBFileSpec("main.c") break1 = target.BreakpointCreateByName("stopper", 'a.out') self.assertTrue(break1, VALID_BREAKPOINT) process = target.LaunchSimple(None, None, self.get_process_working_directory()) self.assertTrue(process, PROCESS_IS_VALID) threads = lldbutil.get_threads_stopped_at_breakpoint(process, break1) self.assertEqual(len(threads), 1, "Failed to stop at breakpoint 1.") self.assertEqual( process.GetNumThreads(), 2, "Check that the process has two threads when sitting at the stopper() breakpoint" ) main_thread = lldb.SBThread() select_thread = lldb.SBThread() for idx in range(0, process.GetNumThreads()): t = process.GetThreadAtIndex(idx) if t.GetName() == "main thread": main_thread = t if t.GetName() == "select thread": select_thread = t self.assertTrue(main_thread.IsValid() and select_thread.IsValid(), "Got both expected threads") self.assertTrue(main_thread.SafeToCallFunctions(), "It is safe to call functions on the main thread") self.assertTrue( select_thread.SafeToCallFunctions() == False, "It is not safe to call functions on the select thread")
def fuzz_obj(obj): obj.GetTarget() obj.GetByteOrder() obj.PutSTDIN("my data") obj.GetSTDOUT(6) obj.GetSTDERR(6) event = lldb.SBEvent() try: obj.ReportEventState(event, None) except Exception: pass obj.AppendEventStateReport(event, lldb.SBCommandReturnObject()) error = lldb.SBError() obj.RemoteAttachToProcessWithID(123, error) obj.RemoteLaunch(None, None, None, None, None, None, 0, False, error) obj.GetNumThreads() obj.GetThreadAtIndex(0) obj.GetThreadByID(0) obj.GetSelectedThread() obj.SetSelectedThread(lldb.SBThread()) obj.SetSelectedThreadByID(0) obj.GetState() obj.GetExitStatus() obj.GetExitDescription() obj.GetProcessID() obj.GetAddressByteSize() obj.Destroy() obj.Continue() obj.Stop() obj.Kill() obj.Detach() obj.Signal(7) obj.ReadMemory(0x0000ffff, 10, error) obj.WriteMemory(0x0000ffff, "hi data", error) obj.ReadCStringFromMemory(0x0, 128, error) obj.ReadUnsignedFromMemory(0xff, 4, error) obj.ReadPointerFromMemory(0xff, error) obj.GetBroadcaster() obj.GetDescription(lldb.SBStream()) obj.LoadImage(lldb.SBFileSpec(), error) obj.UnloadImage(0) obj.Clear() obj.GetNumSupportedHardwareWatchpoints(error) for thread in obj: s = str(thread) len(obj)
def queues(self): """Test queues inspection SB APIs without libBacktraceRecording.""" exe = self.getBuildArtifact("a.out") target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) self.main_source_spec = lldb.SBFileSpec(self.main_source) break1 = target.BreakpointCreateByName("stopper", 'a.out') self.assertTrue(break1, VALID_BREAKPOINT) self.remove_token(exe) process = target.LaunchSimple([exe + '.token.'], None, self.get_process_working_directory()) self.assertTrue(process, PROCESS_IS_VALID) threads = lldbutil.get_threads_stopped_at_breakpoint(process, break1) if len(threads) != 1: self.fail("Failed to stop at breakpoint 1.") self.await_token(exe) queue_submittor_1 = lldb.SBQueue() queue_performer_1 = lldb.SBQueue() queue_performer_2 = lldb.SBQueue() queue_performer_3 = lldb.SBQueue() for idx in range(0, process.GetNumQueues()): q = process.GetQueueAtIndex(idx) if q.GetName() == "com.apple.work_submittor_1": queue_submittor_1 = q if q.GetName() == "com.apple.work_performer_1": queue_performer_1 = q if q.GetName() == "com.apple.work_performer_2": queue_performer_2 = q if q.GetName() == "com.apple.work_performer_3": queue_performer_3 = q self.assertTrue( queue_submittor_1.IsValid() and queue_performer_1.IsValid() and queue_performer_2.IsValid() and queue_performer_3.IsValid(), "Got all four expected queues: %s %s %s %s" % (queue_submittor_1.IsValid(), queue_performer_1.IsValid(), queue_performer_2.IsValid(), queue_performer_3.IsValid())) self.check_queue_for_valid_queue_id(queue_submittor_1) self.check_queue_for_valid_queue_id(queue_performer_1) self.check_queue_for_valid_queue_id(queue_performer_2) self.check_queue_for_valid_queue_id(queue_performer_3) self.check_number_of_threads_owned_by_queue(queue_submittor_1, 1) self.check_number_of_threads_owned_by_queue(queue_performer_1, 1) self.check_number_of_threads_owned_by_queue(queue_performer_2, 1) self.check_number_of_threads_owned_by_queue(queue_performer_3, 4) self.check_queue_kind(queue_submittor_1, lldb.eQueueKindSerial) self.check_queue_kind(queue_performer_1, lldb.eQueueKindSerial) self.check_queue_kind(queue_performer_2, lldb.eQueueKindSerial) self.check_queue_kind(queue_performer_3, lldb.eQueueKindConcurrent) self.check_queues_threads_match_queue(queue_submittor_1) self.check_queues_threads_match_queue(queue_performer_1) self.check_queues_threads_match_queue(queue_performer_2) self.check_queues_threads_match_queue(queue_performer_3) # We have threads running with all the different dispatch QoS service # levels - find those threads and check that we can get the correct # QoS name for each of them. user_initiated_thread = lldb.SBThread() user_interactive_thread = lldb.SBThread() utility_thread = lldb.SBThread() unspecified_thread = lldb.SBThread() background_thread = lldb.SBThread() for th in process.threads: if th.GetName() == "user initiated QoS": user_initiated_thread = th if th.GetName() == "user interactive QoS": user_interactive_thread = th if th.GetName() == "utility QoS": utility_thread = th if th.GetName() == "unspecified QoS": unspecified_thread = th if th.GetName() == "background QoS": background_thread = th self.assertTrue(user_initiated_thread.IsValid(), "Found user initiated QoS thread") self.assertTrue(user_interactive_thread.IsValid(), "Found user interactive QoS thread") self.assertTrue(utility_thread.IsValid(), "Found utility QoS thread") self.assertTrue(unspecified_thread.IsValid(), "Found unspecified QoS thread") self.assertTrue(background_thread.IsValid(), "Found background QoS thread") stream = lldb.SBStream() self.assertTrue( user_initiated_thread.GetInfoItemByPathAsString( "requested_qos.printable_name", stream), "Get QoS printable string for user initiated QoS thread") self.assertTrue(stream.GetData() == "User Initiated", "user initiated QoS thread name is valid") stream.Clear() self.assertTrue( user_interactive_thread.GetInfoItemByPathAsString( "requested_qos.printable_name", stream), "Get QoS printable string for user interactive QoS thread") self.assertTrue(stream.GetData() == "User Interactive", "user interactive QoS thread name is valid") stream.Clear() self.assertTrue( utility_thread.GetInfoItemByPathAsString( "requested_qos.printable_name", stream), "Get QoS printable string for utility QoS thread") self.assertTrue(stream.GetData() == "Utility", "utility QoS thread name is valid") stream.Clear() self.assertTrue( unspecified_thread.GetInfoItemByPathAsString( "requested_qos.printable_name", stream), "Get QoS printable string for unspecified QoS thread") qosName = stream.GetData() self.assertTrue(qosName == "User Initiated" or qosName == "Default", "unspecified QoS thread name is valid") stream.Clear() self.assertTrue( background_thread.GetInfoItemByPathAsString( "requested_qos.printable_name", stream), "Get QoS printable string for background QoS thread") self.assertTrue(stream.GetData() == "Background", "background QoS thread name is valid")
def suspended_thread_test(self): (self.target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( self, "Stop here to get things going", self.main_source_file) # Make in the running thread, so the we will have to stop a number of times # while handling breakpoints. The first couple of times we hit it we will # run expressions as well. Make sure we don't let the suspended thread run # during those operations. rt_bp = self.make_bkpt("Break here to show we can handle breakpoints") # Make a breakpoint that we will hit when the running thread exits: rt_exit_bp = self.make_bkpt("Break here after thread_join") # Make a breakpoint in the suspended thread. We should not hit this till we # resume it after joining the running thread. st_bp = self.make_bkpt("We allowed the suspend thread to run") # Make a breakpoint after pthread_join of the suspend thread to ensure # that we didn't keep the thread from exiting normally st_exit_bp = self.make_bkpt( " Break here to make sure the thread exited normally") threads = lldbutil.continue_to_breakpoint(process, rt_bp) self.assertEqual(len(threads), 1, "Hit the running_func breakpoint") # Make sure we didn't hit the suspend thread breakpoint: self.assertEqual(st_bp.GetHitCount(), 0, "Continue allowed the suspend thread to run") # Now try an expression on the running thread: self.try_an_expression(threads[0], 0, st_bp) # Continue, and check the same things: threads = lldbutil.continue_to_breakpoint(process, rt_bp) self.assertEqual(len(threads), 1, "We didn't hit running breakpoint") # Try an expression on the suspended thread: thread = lldb.SBThread() for thread in process.threads: th_name = thread.GetName() if th_name == None: continue if "Look for me" in th_name: break self.assertTrue(thread.IsValid(), "We found the suspend thread.") self.try_an_expression(thread, 1, st_bp) # Now set the running thread breakpoint to auto-continue and let it # run a bit to make sure we still don't let the suspend thread run. rt_bp.SetAutoContinue(True) threads = lldbutil.continue_to_breakpoint(process, rt_exit_bp) self.assertEqual(len(threads), 1) self.assertEqual(st_bp.GetHitCount(), 0, "Continue again let suspended thread run") # Now continue and we SHOULD hit the suspend_func breakpoint: threads = lldbutil.continue_to_breakpoint(process, st_bp) self.assertEqual(len(threads), 1, "The thread resumed successfully") # Finally, continue again and we should get out of the last pthread_join # and the process should be about to exit threads = lldbutil.continue_to_breakpoint(process, st_exit_bp) self.assertEqual(len(threads), 1, "pthread_join exited successfully")