199451b44SJordan Rupprechtimport lldb 299451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import * 399451b44SJordan Rupprechtfrom lldbsuite.test.decorators import * 433c0f93fSPavel Labathfrom lldbsuite.test.gdbclientutils import * 533c0f93fSPavel Labathfrom lldbsuite.test.lldbgdbclient import GDBRemoteTestBase 699451b44SJordan Rupprecht 799451b44SJordan Rupprecht 899451b44SJordan Rupprechtclass TestRecognizeBreakpoint(GDBRemoteTestBase): 933c0f93fSPavel Labath 1099451b44SJordan Rupprecht """This tests the case where the gdb-remote server doesn't support any 1199451b44SJordan Rupprecht of the thread-info packets, and just tells which thread got the stop 1299451b44SJordan Rupprecht signal with: 1399451b44SJordan Rupprecht T05thread:01; 1499451b44SJordan Rupprecht There was a bug in lldb that we would set the stop reason from this 1599451b44SJordan Rupprecht packet too early - before we had updated the thread list. So when we 1699451b44SJordan Rupprecht later updated the thread list, we would throw away this info. Normally 1799451b44SJordan Rupprecht we would be able to reconstruct it from the thread info, but not if the 1899451b44SJordan Rupprecht stub doesn't support it""" 1999451b44SJordan Rupprecht 2099451b44SJordan Rupprecht @skipIfXmlSupportMissing 2199451b44SJordan Rupprecht def test(self): 2299451b44SJordan Rupprecht class MyResponder(MockGDBServerResponder): 2399451b44SJordan Rupprecht def __init__(self): 2499451b44SJordan Rupprecht MockGDBServerResponder.__init__(self) 2599451b44SJordan Rupprecht self.thread_info_count = 0 2699451b44SJordan Rupprecht self.after_cont = False 2799451b44SJordan Rupprecht self.current_thread = 0 2899451b44SJordan Rupprecht 2999451b44SJordan Rupprecht def cont(self): 3099451b44SJordan Rupprecht # Simulate process stopping due to a breakpoint: 3199451b44SJordan Rupprecht self.after_cont = True 3299451b44SJordan Rupprecht return "T05thread:01;" 3399451b44SJordan Rupprecht 3499451b44SJordan Rupprecht def vCont(self, packet): 3599451b44SJordan Rupprecht self.after_cont = True 3699451b44SJordan Rupprecht return "T05thread:01;" 3799451b44SJordan Rupprecht 3899451b44SJordan Rupprecht def haltReason(self): 3999451b44SJordan Rupprecht return "T02thread:01;" 4099451b44SJordan Rupprecht 4199451b44SJordan Rupprecht def threadStopInfo(self, num): 4299451b44SJordan Rupprecht return "" 4399451b44SJordan Rupprecht 4499451b44SJordan Rupprecht def QThreadSuffixSupported(self): 4599451b44SJordan Rupprecht return "" 4699451b44SJordan Rupprecht 4799451b44SJordan Rupprecht def QListThreadsInStopReply(self): 4899451b44SJordan Rupprecht return "" 4999451b44SJordan Rupprecht 5099451b44SJordan Rupprecht def setBreakpoint(self, packet): 5199451b44SJordan Rupprecht return "OK" 5299451b44SJordan Rupprecht 5399451b44SJordan Rupprecht def qfThreadInfo(self): 5499451b44SJordan Rupprecht return "m1" 5599451b44SJordan Rupprecht 5699451b44SJordan Rupprecht def qsThreadInfo(self): 5799451b44SJordan Rupprecht if (self.thread_info_count % 2) == 0: 5899451b44SJordan Rupprecht str = "m2" 5999451b44SJordan Rupprecht else: 6099451b44SJordan Rupprecht str = "l" 6199451b44SJordan Rupprecht self.thread_info_count += 1 6299451b44SJordan Rupprecht return str 6399451b44SJordan Rupprecht 6499451b44SJordan Rupprecht def readRegisters(self): 6599451b44SJordan Rupprecht if self.after_cont and self.current_thread == 1: 6699451b44SJordan Rupprecht return "c01e990080ffffff" 6799451b44SJordan Rupprecht else: 6899451b44SJordan Rupprecht return "badcfe10325476980" 6999451b44SJordan Rupprecht 7099451b44SJordan Rupprecht def readRegister(self, regno): 7199451b44SJordan Rupprecht return "" 7299451b44SJordan Rupprecht 7399451b44SJordan Rupprecht def qXferRead(self, obj, annex, offset, length): 7499451b44SJordan Rupprecht if annex == "target.xml": 75*2238dcc3SJonas Devlieghere return ( 76*2238dcc3SJonas Devlieghere """<?xml version="1.0"?> 7799451b44SJordan Rupprecht <target version="1.0"> 7899451b44SJordan Rupprecht <architecture>i386:x86-64</architecture> 7999451b44SJordan Rupprecht <feature name="org.gnu.gdb.i386.core"> 8099451b44SJordan Rupprecht <reg name="rip" bitsize="64" regnum="0" type="code_ptr" group="general"/> 8199451b44SJordan Rupprecht </feature> 82*2238dcc3SJonas Devlieghere </target>""", 83*2238dcc3SJonas Devlieghere False, 84*2238dcc3SJonas Devlieghere ) 8599451b44SJordan Rupprecht else: 8699451b44SJordan Rupprecht return None, False 8799451b44SJordan Rupprecht 8899451b44SJordan Rupprecht def selectThread(self, op, thread): 89*2238dcc3SJonas Devlieghere if op != "g": 90*2238dcc3SJonas Devlieghere return "" 9199451b44SJordan Rupprecht 9299451b44SJordan Rupprecht self.current_thread = thread 9399451b44SJordan Rupprecht return "OK" 9499451b44SJordan Rupprecht 9599451b44SJordan Rupprecht def other(self, packet): 9699451b44SJordan Rupprecht if packet == "vCont?": 9799451b44SJordan Rupprecht return "vCont;c;C;s;S" 98*2238dcc3SJonas Devlieghere return "" 9999451b44SJordan Rupprecht 100*2238dcc3SJonas Devlieghere python_os_plugin_path = os.path.join( 101*2238dcc3SJonas Devlieghere self.getSourceDir(), "operating_system_2.py" 102*2238dcc3SJonas Devlieghere ) 10399451b44SJordan Rupprecht command = "settings set target.process.python-os-plugin-path '{}'".format( 104*2238dcc3SJonas Devlieghere python_os_plugin_path 105*2238dcc3SJonas Devlieghere ) 10699451b44SJordan Rupprecht self.runCmd(command) 10799451b44SJordan Rupprecht 10899451b44SJordan Rupprecht self.server.responder = MyResponder() 10999451b44SJordan Rupprecht target = self.dbg.CreateTarget("") 11099451b44SJordan Rupprecht process = self.connect(target) 11199451b44SJordan Rupprecht 112*2238dcc3SJonas Devlieghere bkpt = target.BreakpointCreateByAddress(0xFFFFFF8000991EC0) 11399451b44SJordan Rupprecht self.assertEqual(bkpt.GetNumLocations(), 1, "Fake breakpoint was resolved.") 11499451b44SJordan Rupprecht 11599451b44SJordan Rupprecht # Get the initial stop, and we should have two threads. 11699451b44SJordan Rupprecht num_threads = len(process.threads) 11799451b44SJordan Rupprecht self.assertEqual(num_threads, 2, "Got two threads") 11899451b44SJordan Rupprecht 11999451b44SJordan Rupprecht thread_0 = process.threads[0] 12099451b44SJordan Rupprecht self.assertEqual(thread_0.GetStopReason(), 1, "Thread_0 stopped for no reason") 12199451b44SJordan Rupprecht self.assertEqual(thread_0.GetName(), "one", "Thread_0 is called one") 12299451b44SJordan Rupprecht 12399451b44SJordan Rupprecht thread_1 = process.threads[1] 12499451b44SJordan Rupprecht self.assertEqual(thread_1.GetStopReason(), 5, "Thread_0 stopped for SIGSTOP") 12599451b44SJordan Rupprecht self.assertEqual(thread_1.GetName(), "two", "Thread_0 is called two") 12699451b44SJordan Rupprecht 12799451b44SJordan Rupprecht # Now continue and we will fake hitting a breakpoint. 12899451b44SJordan Rupprecht process.Continue() 12999451b44SJordan Rupprecht 1301b8c7352SJonas Devlieghere self.assertState(process.GetState(), lldb.eStateStopped, "Process is stopped") 13199451b44SJordan Rupprecht num_threads = len(process.threads) 13299451b44SJordan Rupprecht 13399451b44SJordan Rupprecht num_threads = len(process.threads) 13499451b44SJordan Rupprecht self.assertEqual(num_threads, 2, "Got two threads") 13599451b44SJordan Rupprecht 13699451b44SJordan Rupprecht thread_0 = process.threads[0] 13799451b44SJordan Rupprecht self.assertEqual(thread_0.GetStopReason(), 1, "Thread_0 stopped for no reason") 13899451b44SJordan Rupprecht self.assertEqual(thread_0.GetName(), "one", "Thread_0 is called one") 13999451b44SJordan Rupprecht 14099451b44SJordan Rupprecht thread_1 = process.threads[1] 14199451b44SJordan Rupprecht self.assertEqual(thread_1.GetStopReason(), 3, "Thread_0 stopped for SIGTRAP") 14299451b44SJordan Rupprecht self.assertEqual(thread_1.GetName(), "three", "Thread_0 is called three") 14399451b44SJordan Rupprecht 14499451b44SJordan Rupprecht self.assertTrue(thread_1.IsValid(), "Thread_1 is valid") 145*2238dcc3SJonas Devlieghere self.assertStopReason( 146*2238dcc3SJonas Devlieghere thread_1.GetStopReason(), 147*2238dcc3SJonas Devlieghere lldb.eStopReasonBreakpoint, 148*2238dcc3SJonas Devlieghere "Stopped at breakpoint", 149*2238dcc3SJonas Devlieghere ) 150