xref: /llvm-project/lldb/test/API/functionalities/gdb_remote_client/TestRecognizeBreakpoint.py (revision 2238dcc39358353cac21df75c3c3286ab20b8f53)
199451b44SJordan Rupprechtimport lldb
299451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import *
399451b44SJordan Rupprechtfrom lldbsuite.test.decorators import *
433c0f93fSPavel Labathfrom lldbsuite.test.gdbclientutils import *
533c0f93fSPavel Labathfrom lldbsuite.test.lldbgdbclient import GDBRemoteTestBase
699451b44SJordan Rupprecht
799451b44SJordan Rupprecht
899451b44SJordan Rupprechtclass TestRecognizeBreakpoint(GDBRemoteTestBase):
933c0f93fSPavel Labath
1099451b44SJordan Rupprecht    """This tests the case where the gdb-remote server doesn't support any
1199451b44SJordan Rupprecht    of the thread-info packets, and just tells which thread got the stop
1299451b44SJordan Rupprecht    signal with:
1399451b44SJordan Rupprecht          T05thread:01;
1499451b44SJordan Rupprecht    There was a bug in lldb that we would set the stop reason from this
1599451b44SJordan Rupprecht    packet too early - before we had updated the thread list.  So when we
1699451b44SJordan Rupprecht    later updated the thread list, we would throw away this info.  Normally
1799451b44SJordan Rupprecht    we would be able to reconstruct it from the thread info, but not if the
1899451b44SJordan Rupprecht    stub doesn't support it"""
1999451b44SJordan Rupprecht
2099451b44SJordan Rupprecht    @skipIfXmlSupportMissing
2199451b44SJordan Rupprecht    def test(self):
2299451b44SJordan Rupprecht        class MyResponder(MockGDBServerResponder):
2399451b44SJordan Rupprecht            def __init__(self):
2499451b44SJordan Rupprecht                MockGDBServerResponder.__init__(self)
2599451b44SJordan Rupprecht                self.thread_info_count = 0
2699451b44SJordan Rupprecht                self.after_cont = False
2799451b44SJordan Rupprecht                self.current_thread = 0
2899451b44SJordan Rupprecht
2999451b44SJordan Rupprecht            def cont(self):
3099451b44SJordan Rupprecht                # Simulate process stopping due to a breakpoint:
3199451b44SJordan Rupprecht                self.after_cont = True
3299451b44SJordan Rupprecht                return "T05thread:01;"
3399451b44SJordan Rupprecht
3499451b44SJordan Rupprecht            def vCont(self, packet):
3599451b44SJordan Rupprecht                self.after_cont = True
3699451b44SJordan Rupprecht                return "T05thread:01;"
3799451b44SJordan Rupprecht
3899451b44SJordan Rupprecht            def haltReason(self):
3999451b44SJordan Rupprecht                return "T02thread:01;"
4099451b44SJordan Rupprecht
4199451b44SJordan Rupprecht            def threadStopInfo(self, num):
4299451b44SJordan Rupprecht                return ""
4399451b44SJordan Rupprecht
4499451b44SJordan Rupprecht            def QThreadSuffixSupported(self):
4599451b44SJordan Rupprecht                return ""
4699451b44SJordan Rupprecht
4799451b44SJordan Rupprecht            def QListThreadsInStopReply(self):
4899451b44SJordan Rupprecht                return ""
4999451b44SJordan Rupprecht
5099451b44SJordan Rupprecht            def setBreakpoint(self, packet):
5199451b44SJordan Rupprecht                return "OK"
5299451b44SJordan Rupprecht
5399451b44SJordan Rupprecht            def qfThreadInfo(self):
5499451b44SJordan Rupprecht                return "m1"
5599451b44SJordan Rupprecht
5699451b44SJordan Rupprecht            def qsThreadInfo(self):
5799451b44SJordan Rupprecht                if (self.thread_info_count % 2) == 0:
5899451b44SJordan Rupprecht                    str = "m2"
5999451b44SJordan Rupprecht                else:
6099451b44SJordan Rupprecht                    str = "l"
6199451b44SJordan Rupprecht                self.thread_info_count += 1
6299451b44SJordan Rupprecht                return str
6399451b44SJordan Rupprecht
6499451b44SJordan Rupprecht            def readRegisters(self):
6599451b44SJordan Rupprecht                if self.after_cont and self.current_thread == 1:
6699451b44SJordan Rupprecht                    return "c01e990080ffffff"
6799451b44SJordan Rupprecht                else:
6899451b44SJordan Rupprecht                    return "badcfe10325476980"
6999451b44SJordan Rupprecht
7099451b44SJordan Rupprecht            def readRegister(self, regno):
7199451b44SJordan Rupprecht                return ""
7299451b44SJordan Rupprecht
7399451b44SJordan Rupprecht            def qXferRead(self, obj, annex, offset, length):
7499451b44SJordan Rupprecht                if annex == "target.xml":
75*2238dcc3SJonas Devlieghere                    return (
76*2238dcc3SJonas Devlieghere                        """<?xml version="1.0"?>
7799451b44SJordan Rupprecht                        <target version="1.0">
7899451b44SJordan Rupprecht                          <architecture>i386:x86-64</architecture>
7999451b44SJordan Rupprecht                          <feature name="org.gnu.gdb.i386.core">
8099451b44SJordan Rupprecht                            <reg name="rip" bitsize="64" regnum="0" type="code_ptr" group="general"/>
8199451b44SJordan Rupprecht                          </feature>
82*2238dcc3SJonas Devlieghere                        </target>""",
83*2238dcc3SJonas Devlieghere                        False,
84*2238dcc3SJonas Devlieghere                    )
8599451b44SJordan Rupprecht                else:
8699451b44SJordan Rupprecht                    return None, False
8799451b44SJordan Rupprecht
8899451b44SJordan Rupprecht            def selectThread(self, op, thread):
89*2238dcc3SJonas Devlieghere                if op != "g":
90*2238dcc3SJonas Devlieghere                    return ""
9199451b44SJordan Rupprecht
9299451b44SJordan Rupprecht                self.current_thread = thread
9399451b44SJordan Rupprecht                return "OK"
9499451b44SJordan Rupprecht
9599451b44SJordan Rupprecht            def other(self, packet):
9699451b44SJordan Rupprecht                if packet == "vCont?":
9799451b44SJordan Rupprecht                    return "vCont;c;C;s;S"
98*2238dcc3SJonas Devlieghere                return ""
9999451b44SJordan Rupprecht
100*2238dcc3SJonas Devlieghere        python_os_plugin_path = os.path.join(
101*2238dcc3SJonas Devlieghere            self.getSourceDir(), "operating_system_2.py"
102*2238dcc3SJonas Devlieghere        )
10399451b44SJordan Rupprecht        command = "settings set target.process.python-os-plugin-path '{}'".format(
104*2238dcc3SJonas Devlieghere            python_os_plugin_path
105*2238dcc3SJonas Devlieghere        )
10699451b44SJordan Rupprecht        self.runCmd(command)
10799451b44SJordan Rupprecht
10899451b44SJordan Rupprecht        self.server.responder = MyResponder()
10999451b44SJordan Rupprecht        target = self.dbg.CreateTarget("")
11099451b44SJordan Rupprecht        process = self.connect(target)
11199451b44SJordan Rupprecht
112*2238dcc3SJonas Devlieghere        bkpt = target.BreakpointCreateByAddress(0xFFFFFF8000991EC0)
11399451b44SJordan Rupprecht        self.assertEqual(bkpt.GetNumLocations(), 1, "Fake breakpoint was resolved.")
11499451b44SJordan Rupprecht
11599451b44SJordan Rupprecht        # Get the initial stop, and we should have two threads.
11699451b44SJordan Rupprecht        num_threads = len(process.threads)
11799451b44SJordan Rupprecht        self.assertEqual(num_threads, 2, "Got two threads")
11899451b44SJordan Rupprecht
11999451b44SJordan Rupprecht        thread_0 = process.threads[0]
12099451b44SJordan Rupprecht        self.assertEqual(thread_0.GetStopReason(), 1, "Thread_0 stopped for no reason")
12199451b44SJordan Rupprecht        self.assertEqual(thread_0.GetName(), "one", "Thread_0 is called one")
12299451b44SJordan Rupprecht
12399451b44SJordan Rupprecht        thread_1 = process.threads[1]
12499451b44SJordan Rupprecht        self.assertEqual(thread_1.GetStopReason(), 5, "Thread_0 stopped for SIGSTOP")
12599451b44SJordan Rupprecht        self.assertEqual(thread_1.GetName(), "two", "Thread_0 is called two")
12699451b44SJordan Rupprecht
12799451b44SJordan Rupprecht        # Now continue and we will fake hitting a breakpoint.
12899451b44SJordan Rupprecht        process.Continue()
12999451b44SJordan Rupprecht
1301b8c7352SJonas Devlieghere        self.assertState(process.GetState(), lldb.eStateStopped, "Process is stopped")
13199451b44SJordan Rupprecht        num_threads = len(process.threads)
13299451b44SJordan Rupprecht
13399451b44SJordan Rupprecht        num_threads = len(process.threads)
13499451b44SJordan Rupprecht        self.assertEqual(num_threads, 2, "Got two threads")
13599451b44SJordan Rupprecht
13699451b44SJordan Rupprecht        thread_0 = process.threads[0]
13799451b44SJordan Rupprecht        self.assertEqual(thread_0.GetStopReason(), 1, "Thread_0 stopped for no reason")
13899451b44SJordan Rupprecht        self.assertEqual(thread_0.GetName(), "one", "Thread_0 is called one")
13999451b44SJordan Rupprecht
14099451b44SJordan Rupprecht        thread_1 = process.threads[1]
14199451b44SJordan Rupprecht        self.assertEqual(thread_1.GetStopReason(), 3, "Thread_0 stopped for SIGTRAP")
14299451b44SJordan Rupprecht        self.assertEqual(thread_1.GetName(), "three", "Thread_0 is called three")
14399451b44SJordan Rupprecht
14499451b44SJordan Rupprecht        self.assertTrue(thread_1.IsValid(), "Thread_1 is valid")
145*2238dcc3SJonas Devlieghere        self.assertStopReason(
146*2238dcc3SJonas Devlieghere            thread_1.GetStopReason(),
147*2238dcc3SJonas Devlieghere            lldb.eStopReasonBreakpoint,
148*2238dcc3SJonas Devlieghere            "Stopped at breakpoint",
149*2238dcc3SJonas Devlieghere        )
150