1from __future__ import print_function
2import lldb
3from lldbsuite.test.lldbtest import *
4from lldbsuite.test.decorators import *
5from lldbsuite.test.gdbclientutils import *
6from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase
7
8
9# This test case checks for register number mismatch between lldb and gdb stub.
10# LLDB client assigns register numbers to target xml registers in increasing
11# order starting with regnum = 0, while gdb-remote may specify different regnum
12# which is stored as eRegisterKindProcessPlugin. Remote side will use its
13# register number in expedited register list, value_regs and invalidate_regnums.
14#
15# This test creates a ficticious target xml with non-sequential regnums to test
16# that correct registers are accessed in all of above mentioned cases.
17
18class TestRemoteRegNums(GDBRemoteTestBase):
19
20    mydir = TestBase.compute_mydir(__file__)
21
22    @skipIfXmlSupportMissing
23    def test(self):
24        class MyResponder(MockGDBServerResponder):
25            def haltReason(self):
26                return "T02thread:1ff0d;threads:1ff0d;thread-pcs:000000010001bc00;00:00bc010001000000;09:c04825ebfe7f0000;"
27
28            def threadStopInfo(self, threadnum):
29                return "T02thread:1ff0d;threads:1ff0d;thread-pcs:000000010001bc00;00:00bc010001000000;09:c04825ebfe7f0000;"
30
31            def writeRegisters(self):
32                return "E02"
33
34            def readRegisters(self):
35                return "E01"
36
37            rax_regnum2_val = "7882773ce0ffffff"
38            rbx_regnum4_val = "1122334455667788"
39
40            def readRegister(self, regnum):
41                # lldb will try sending "p0" to see if the p packet is supported,
42                # give a bogus value; in theory lldb could use this value in the
43                # register context and that would be valid behavior.
44
45                # notably, don't give values for registers 1 & 3 -- lldb should
46                # get those from the ? stop packet ("T11") and it is a pref regression
47                # if lldb is asking for these register values.
48                if regnum == 0:
49                    return "5555555555555555"
50                if regnum == 2:
51                    return self.rax_regnum2_val
52                if regnum == 4:
53                    return self.rbx_regnum4_val
54
55                return "E03"
56
57            def writeRegister(self, regnum, value_hex):
58                if regnum == 2:
59                    self.rax_regnum2_val = value_hex
60                if regnum == 4:
61                    self.rbx_regnum4_val = value_hex
62
63                return "OK"
64
65            def qXferRead(self, obj, annex, offset, length):
66                if annex == "target.xml":
67                    return """<?xml version="1.0"?>
68                        <target version="1.0">
69                          <architecture>i386:x86-64</architecture>
70                          <feature name="org.gnu.gdb.i386.core">
71                            <reg name="rip" bitsize="64" regnum="0" type="code_ptr" group="general" altname="pc" generic="pc"/>
72                            <reg name="rax" bitsize="64" regnum="2" type="code_ptr" group="general"/>
73                            <reg name="rbx" bitsize="64" regnum="4" type="code_ptr" group="general"/>
74                            <reg name="eax" bitsize="32" regnum="5" value_regnums="2" invalidate_regnums="2" type="code_ptr" group="general"/>
75                            <reg name="ebx" bitsize="32" regnum="7" value_regnums="4" invalidate_regnums="4" type="code_ptr" group="general"/>
76                            <reg name="rsi" bitsize="64" regnum="9" type="code_ptr" group="general"/>
77                          </feature>
78                        </target>""", False
79                else:
80                    return None, False
81
82        self.server.responder = MyResponder()
83        target = self.dbg.CreateTarget('')
84        if self.TraceOn():
85            self.runCmd("log enable gdb-remote packets")
86            self.addTearDownHook(
87                lambda: self.runCmd("log disable gdb-remote packets"))
88        process = self.connect(target)
89
90        thread = process.GetThreadAtIndex(0)
91        frame = thread.GetFrameAtIndex(0)
92        rax = frame.FindRegister("rax").GetValueAsUnsigned()
93        eax = frame.FindRegister("eax").GetValueAsUnsigned()
94        rbx = frame.FindRegister("rbx").GetValueAsUnsigned()
95        ebx = frame.FindRegister("ebx").GetValueAsUnsigned()
96        rsi = frame.FindRegister("rsi").GetValueAsUnsigned()
97        pc = frame.GetPC()
98        rip = frame.FindRegister("rip").GetValueAsUnsigned()
99
100        if self.TraceOn():
101            print("Register values: rax == 0x%x, rbx == 0x%x, rsi == 0x%x, pc == 0x%x, rip == 0x%x" % (
102                rax, rbx, rsi, pc, rip))
103
104        self.assertEqual(rax, 0xffffffe03c778278)
105        self.assertEqual(rbx, 0x8877665544332211)
106        self.assertEqual(eax, 0x3c778278)
107        self.assertEqual(ebx, 0x44332211)
108        self.assertEqual(rsi, 0x00007ffeeb2548c0)
109        self.assertEqual(pc, 0x10001bc00)
110        self.assertEqual(rip, 0x10001bc00)
111
112        frame.FindRegister("eax").SetValueFromCString("1")
113        frame.FindRegister("ebx").SetValueFromCString("0")
114        eax = frame.FindRegister("eax").GetValueAsUnsigned()
115        ebx = frame.FindRegister("ebx").GetValueAsUnsigned()
116        rax = frame.FindRegister("rax").GetValueAsUnsigned()
117        rbx = frame.FindRegister("rbx").GetValueAsUnsigned()
118
119        if self.TraceOn():
120            print("Register values: rax == 0x%x, rbx == 0x%x, rsi == 0x%x, pc == 0x%x, rip == 0x%x" % (
121                rax, rbx, rsi, pc, rip))
122
123        self.assertEqual(rax, 0xffffffe000000001)
124        self.assertEqual(rbx, 0x8877665500000000)
125        self.assertEqual(eax, 0x00000001)
126        self.assertEqual(ebx, 0x00000000)
127        self.assertEqual(rsi, 0x00007ffeeb2548c0)
128        self.assertEqual(pc, 0x10001bc00)
129        self.assertEqual(rip, 0x10001bc00)
130