199451b44SJordan Rupprechtfrom __future__ import print_function
299451b44SJordan Rupprechtimport lldb
399451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import *
499451b44SJordan Rupprechtfrom lldbsuite.test.decorators import *
5*33c0f93fSPavel Labathfrom lldbsuite.test.gdbclientutils import *
6*33c0f93fSPavel Labathfrom lldbsuite.test.lldbgdbclient import GDBRemoteTestBase
799451b44SJordan Rupprecht
899451b44SJordan Rupprecht
999451b44SJordan Rupprecht# This test case is testing three things:
1099451b44SJordan Rupprecht#
1199451b44SJordan Rupprecht#  1. three register values will be provided in the ? stop packet (T11) -
1299451b44SJordan Rupprecht#     registers 0 ("rax"), 1 ("rbx"), and 3 ("rip")
1399451b44SJordan Rupprecht#  2. ReadRegister packet will provide the value of register 2 ("rsi")
1499451b44SJordan Rupprecht#  3. The "g" read-all-registers packet is not supported; p must be used
1599451b44SJordan Rupprecht#     to get the value of register 2 ("rsi")
1699451b44SJordan Rupprecht#
1799451b44SJordan Rupprecht# Forcing lldb to use the expedited registers in the stop packet and
1899451b44SJordan Rupprecht# marking it an error to request that register value is to prevent
1999451b44SJordan Rupprecht# performance regressions.
2099451b44SJordan Rupprecht#
2199451b44SJordan Rupprecht# Some gdb RSP stubs only implement p/P, they do not support g/G.
2299451b44SJordan Rupprecht# lldb must be able to work with either.
2399451b44SJordan Rupprecht
2499451b44SJordan Rupprechtclass TestNoGPacketSupported(GDBRemoteTestBase):
2599451b44SJordan Rupprecht
2699451b44SJordan Rupprecht    @skipIfXmlSupportMissing
2799451b44SJordan Rupprecht    def test(self):
2899451b44SJordan Rupprecht        class MyResponder(MockGDBServerResponder):
2999451b44SJordan Rupprecht            def haltReason(self):
3099451b44SJordan Rupprecht                return "T02thread:1ff0d;threads:1ff0d;thread-pcs:000000010001bc00;00:7882773ce0ffffff;01:1122334455667788;03:00bc010001000000;"
3199451b44SJordan Rupprecht
3299451b44SJordan Rupprecht            def threadStopInfo(self, threadnum):
3399451b44SJordan Rupprecht                return "T02thread:1ff0d;threads:1ff0d;thread-pcs:000000010001bc00;00:7882773ce0ffffff;01:1122334455667788;03:00bc010001000000;"
3499451b44SJordan Rupprecht
3599451b44SJordan Rupprecht            def writeRegisters(self):
3699451b44SJordan Rupprecht                return "E02"
3799451b44SJordan Rupprecht
3899451b44SJordan Rupprecht            def readRegisters(self):
3999451b44SJordan Rupprecht                return "E01"
4099451b44SJordan Rupprecht
4199451b44SJordan Rupprecht            def readRegister(self, regnum):
4299451b44SJordan Rupprecht                # lldb will try sending "p0" to see if the p packet is supported,
4399451b44SJordan Rupprecht                # give a bogus value; in theory lldb could use this value in the
4499451b44SJordan Rupprecht                # register context and that would be valid behavior.
4599451b44SJordan Rupprecht
4699451b44SJordan Rupprecht                # notably, don't give values for registers 1 & 3 -- lldb should
4799451b44SJordan Rupprecht                # get those from the ? stop packet ("T11") and it is a pref regression
4899451b44SJordan Rupprecht                # if lldb is asking for these register values.
4999451b44SJordan Rupprecht                if regnum == 0:
5099451b44SJordan Rupprecht                    return "5555555555555555"
5199451b44SJordan Rupprecht                if regnum == 2:
5299451b44SJordan Rupprecht                    return "c04825ebfe7f0000" # 0x00007ffeeb2548c0
5399451b44SJordan Rupprecht
5499451b44SJordan Rupprecht                return "E03"
5599451b44SJordan Rupprecht
5699451b44SJordan Rupprecht            def writeRegister(self, regnum):
5799451b44SJordan Rupprecht                return "OK"
5899451b44SJordan Rupprecht
5999451b44SJordan Rupprecht            def qXferRead(self, obj, annex, offset, length):
6099451b44SJordan Rupprecht                if annex == "target.xml":
6199451b44SJordan Rupprecht                    return """<?xml version="1.0"?>
6299451b44SJordan Rupprecht                        <target version="1.0">
6399451b44SJordan Rupprecht                          <architecture>i386:x86-64</architecture>
6499451b44SJordan Rupprecht                          <feature name="org.gnu.gdb.i386.core">
6599451b44SJordan Rupprecht                            <reg name="rax" bitsize="64" regnum="0" type="code_ptr" group="general"/>
6699451b44SJordan Rupprecht                            <reg name="rbx" bitsize="64" regnum="1" type="code_ptr" group="general"/>
6799451b44SJordan Rupprecht                            <reg name="rsi" bitsize="64" regnum="2" type="code_ptr" group="general"/>
6899451b44SJordan Rupprecht                            <reg name="rip" bitsize="64" regnum="3" type="code_ptr" group="general" altname="pc" generic="pc"/>
6999451b44SJordan Rupprecht                          </feature>
7099451b44SJordan Rupprecht                        </target>""", False
7199451b44SJordan Rupprecht                else:
7299451b44SJordan Rupprecht                    return None, False
7399451b44SJordan Rupprecht
7499451b44SJordan Rupprecht        self.server.responder = MyResponder()
7599451b44SJordan Rupprecht        target = self.dbg.CreateTarget('')
7699451b44SJordan Rupprecht        if self.TraceOn():
7799451b44SJordan Rupprecht          self.runCmd("log enable gdb-remote packets")
7899451b44SJordan Rupprecht          self.addTearDownHook(
7999451b44SJordan Rupprecht                lambda: self.runCmd("log disable gdb-remote packets"))
8099451b44SJordan Rupprecht        process = self.connect(target)
8199451b44SJordan Rupprecht
8299451b44SJordan Rupprecht        thread = process.GetThreadAtIndex(0)
8399451b44SJordan Rupprecht        frame = thread.GetFrameAtIndex(0)
8499451b44SJordan Rupprecht        rax = frame.FindRegister("rax").GetValueAsUnsigned()
8599451b44SJordan Rupprecht        rbx = frame.FindRegister("rbx").GetValueAsUnsigned()
8699451b44SJordan Rupprecht        rsi = frame.FindRegister("rsi").GetValueAsUnsigned()
8799451b44SJordan Rupprecht        pc = frame.GetPC()
8899451b44SJordan Rupprecht        rip = frame.FindRegister("rip").GetValueAsUnsigned()
8999451b44SJordan Rupprecht
9099451b44SJordan Rupprecht        if self.TraceOn():
9199451b44SJordan Rupprecht            print("Register values: rax == 0x%x, rbx == 0x%x, rsi == 0x%x, pc == 0x%x, rip == 0x%x" % (rax, rbx, rsi, pc, rip))
9299451b44SJordan Rupprecht
9399451b44SJordan Rupprecht        self.assertEqual(rax, 0xffffffe03c778278)
9499451b44SJordan Rupprecht        self.assertEqual(rbx, 0x8877665544332211)
9599451b44SJordan Rupprecht        self.assertEqual(rsi, 0x00007ffeeb2548c0)
9699451b44SJordan Rupprecht        self.assertEqual(pc, 0x10001bc00)
9799451b44SJordan Rupprecht        self.assertEqual(rip, 0x10001bc00)
98