150 lines · python
1import lldb2from lldbsuite.test.lldbtest import *3from lldbsuite.test.decorators import *4from lldbsuite.test.gdbclientutils import *5from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase6 7 8class TestRecognizeBreakpoint(GDBRemoteTestBase):9 10 """This tests the case where the gdb-remote server doesn't support any11 of the thread-info packets, and just tells which thread got the stop12 signal with:13 T05thread:01;14 There was a bug in lldb that we would set the stop reason from this15 packet too early - before we had updated the thread list. So when we16 later updated the thread list, we would throw away this info. Normally17 we would be able to reconstruct it from the thread info, but not if the18 stub doesn't support it"""19 20 @skipIfXmlSupportMissing21 def test(self):22 class MyResponder(MockGDBServerResponder):23 def __init__(self):24 MockGDBServerResponder.__init__(self)25 self.thread_info_count = 026 self.after_cont = False27 self.current_thread = 028 29 def cont(self):30 # Simulate process stopping due to a breakpoint:31 self.after_cont = True32 return "T05thread:01;"33 34 def vCont(self, packet):35 self.after_cont = True36 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 += 162 return str63 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, False87 88 def selectThread(self, op, thread):89 if op != "g":90 return ""91 92 self.current_thread = thread93 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_path105 )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