1import lldb 2from lldbsuite.test.lldbtest import * 3from lldbsuite.test.decorators import * 4from lldbsuite.test.gdbclientutils import * 5from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase 6 7 8class TestRecognizeBreakpoint(GDBRemoteTestBase): 9 10 """ This tests the case where the gdb-remote server doesn't support any 11 of the thread-info packets, and just tells which thread got the stop 12 signal with: 13 T05thread:01; 14 There was a bug in lldb that we would set the stop reason from this 15 packet too early - before we had updated the thread list. So when we 16 later updated the thread list, we would throw away this info. Normally 17 we would be able to reconstruct it from the thread info, but not if the 18 stub doesn't support it """ 19 20 @skipIfXmlSupportMissing 21 def test(self): 22 class MyResponder(MockGDBServerResponder): 23 def __init__(self): 24 MockGDBServerResponder.__init__(self) 25 self.thread_info_count = 0 26 self.after_cont = False 27 self.current_thread = 0 28 29 def cont(self): 30 # Simulate process stopping due to a breakpoint: 31 self.after_cont = True 32 return "T05thread:01;" 33 34 def vCont(self, packet): 35 self.after_cont = True 36 return "T05thread:01;" 37 38 def haltReason(self): 39 return "T02thread:01;" 40 41 def threadStopInfo(self, num): 42 return "" 43 44 def QThreadSuffixSupported(self): 45 return "" 46 47 def QListThreadsInStopReply(self): 48 return "" 49 50 def setBreakpoint(self, packet): 51 return "OK" 52 53 def qfThreadInfo(self): 54 return "m1" 55 56 def qsThreadInfo(self): 57 if (self.thread_info_count % 2) == 0: 58 str = "m2" 59 else: 60 str = "l" 61 self.thread_info_count += 1 62 return str 63 64 def readRegisters(self): 65 if self.after_cont and self.current_thread == 1: 66 return "c01e990080ffffff" 67 else: 68 return "badcfe10325476980" 69 70 def readRegister(self, regno): 71 return "" 72 73 def qXferRead(self, obj, annex, offset, length): 74 if annex == "target.xml": 75 return """<?xml version="1.0"?> 76 <target version="1.0"> 77 <architecture>i386:x86-64</architecture> 78 <feature name="org.gnu.gdb.i386.core"> 79 <reg name="rip" bitsize="64" regnum="0" type="code_ptr" group="general"/> 80 </feature> 81 </target>""", False 82 else: 83 return None, False 84 85 def selectThread(self, op, thread): 86 if op != 'g': 87 return '' 88 89 self.current_thread = thread 90 return "OK" 91 92 def other (self, packet): 93 if packet == "vCont?": 94 return "vCont;c;C;s;S" 95 return '' 96 97 python_os_plugin_path = os.path.join(self.getSourceDir(), 98 'operating_system_2.py') 99 command ="settings set target.process.python-os-plugin-path '{}'".format( 100 python_os_plugin_path) 101 self.runCmd(command) 102 103 self.server.responder = MyResponder() 104 target = self.dbg.CreateTarget("") 105 process = self.connect(target) 106 107 bkpt = target.BreakpointCreateByAddress(0xffffff8000991ec0) 108 self.assertEqual(bkpt.GetNumLocations(), 1, "Fake breakpoint was resolved.") 109 110 # Get the initial stop, and we should have two threads. 111 num_threads = len(process.threads) 112 self.assertEqual(num_threads, 2, "Got two threads") 113 114 thread_0 = process.threads[0] 115 self.assertEqual(thread_0.GetStopReason(), 1, "Thread_0 stopped for no reason") 116 self.assertEqual(thread_0.GetName(), "one", "Thread_0 is called one") 117 118 thread_1 = process.threads[1] 119 self.assertEqual(thread_1.GetStopReason(), 5, "Thread_0 stopped for SIGSTOP") 120 self.assertEqual(thread_1.GetName(), "two", "Thread_0 is called two") 121 122 # Now continue and we will fake hitting a breakpoint. 123 process.Continue() 124 125 self.assertState(process.GetState(),lldb.eStateStopped, "Process is stopped") 126 num_threads = len(process.threads) 127 128 num_threads = len(process.threads) 129 self.assertEqual(num_threads, 2, "Got two threads") 130 131 thread_0 = process.threads[0] 132 self.assertEqual(thread_0.GetStopReason(), 1, "Thread_0 stopped for no reason") 133 self.assertEqual(thread_0.GetName(), "one", "Thread_0 is called one") 134 135 thread_1 = process.threads[1] 136 self.assertEqual(thread_1.GetStopReason(), 3, "Thread_0 stopped for SIGTRAP") 137 self.assertEqual(thread_1.GetName(), "three", "Thread_0 is called three") 138 139 self.assertTrue(thread_1.IsValid(), "Thread_1 is valid") 140 self.assertEqual(thread_1.GetStopReason(), lldb.eStopReasonBreakpoint, "Stopped at breakpoint") 141 142