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 ( 76 """<?xml version="1.0"?> 77 <target version="1.0"> 78 <architecture>i386:x86-64</architecture> 79 <feature name="org.gnu.gdb.i386.core"> 80 <reg name="rip" bitsize="64" regnum="0" type="code_ptr" group="general"/> 81 </feature> 82 </target>""", 83 False, 84 ) 85 else: 86 return None, False 87 88 def selectThread(self, op, thread): 89 if op != "g": 90 return "" 91 92 self.current_thread = thread 93 return "OK" 94 95 def other(self, packet): 96 if packet == "vCont?": 97 return "vCont;c;C;s;S" 98 return "" 99 100 python_os_plugin_path = os.path.join( 101 self.getSourceDir(), "operating_system_2.py" 102 ) 103 command = "settings set target.process.python-os-plugin-path '{}'".format( 104 python_os_plugin_path 105 ) 106 self.runCmd(command) 107 108 self.server.responder = MyResponder() 109 target = self.dbg.CreateTarget("") 110 process = self.connect(target) 111 112 bkpt = target.BreakpointCreateByAddress(0xFFFFFF8000991EC0) 113 self.assertEqual(bkpt.GetNumLocations(), 1, "Fake breakpoint was resolved.") 114 115 # Get the initial stop, and we should have two threads. 116 num_threads = len(process.threads) 117 self.assertEqual(num_threads, 2, "Got two threads") 118 119 thread_0 = process.threads[0] 120 self.assertEqual(thread_0.GetStopReason(), 1, "Thread_0 stopped for no reason") 121 self.assertEqual(thread_0.GetName(), "one", "Thread_0 is called one") 122 123 thread_1 = process.threads[1] 124 self.assertEqual(thread_1.GetStopReason(), 5, "Thread_0 stopped for SIGSTOP") 125 self.assertEqual(thread_1.GetName(), "two", "Thread_0 is called two") 126 127 # Now continue and we will fake hitting a breakpoint. 128 process.Continue() 129 130 self.assertState(process.GetState(), lldb.eStateStopped, "Process is stopped") 131 num_threads = len(process.threads) 132 133 num_threads = len(process.threads) 134 self.assertEqual(num_threads, 2, "Got two threads") 135 136 thread_0 = process.threads[0] 137 self.assertEqual(thread_0.GetStopReason(), 1, "Thread_0 stopped for no reason") 138 self.assertEqual(thread_0.GetName(), "one", "Thread_0 is called one") 139 140 thread_1 = process.threads[1] 141 self.assertEqual(thread_1.GetStopReason(), 3, "Thread_0 stopped for SIGTRAP") 142 self.assertEqual(thread_1.GetName(), "three", "Thread_0 is called three") 143 144 self.assertTrue(thread_1.IsValid(), "Thread_1 is valid") 145 self.assertStopReason( 146 thread_1.GetStopReason(), 147 lldb.eStopReasonBreakpoint, 148 "Stopped at breakpoint", 149 ) 150