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