44e2cfa891a4e984a33d0d93a436f4631d7fc625
[openbsd] /
1 import lldb
2 from lldbsuite.test.lldbtest import *
3 from lldbsuite.test.decorators import *
4 from gdbclientutils import *
5
6
7 class 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