8f0ed9a4933da3b916ca27de1af5911a90614c01
[openbsd] /
1 import lldb
2 import binascii
3 from lldbsuite.test.lldbtest import *
4 from lldbsuite.test.decorators import *
5 from gdbclientutils import *
6
7
8 class TestGDBRemoteClient(GDBRemoteTestBase):
9
10     class gPacketResponder(MockGDBServerResponder):
11         def readRegisters(self):
12             return '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
13
14     def setUp(self):
15         super(TestGDBRemoteClient, self).setUp()
16         self._initial_platform = lldb.DBG.GetSelectedPlatform()
17
18     def tearDown(self):
19         lldb.DBG.SetSelectedPlatform(self._initial_platform)
20         super(TestGDBRemoteClient, self).tearDown()
21
22     def test_connect(self):
23         """Test connecting to a remote gdb server"""
24         target = self.createTarget("a.yaml")
25         process = self.connect(target)
26         self.assertPacketLogContains(["qProcessInfo", "qfThreadInfo"])
27
28     def test_attach_fail(self):
29         error_msg = "mock-error-msg"
30
31         class MyResponder(MockGDBServerResponder):
32             # Pretend we don't have any process during the initial queries.
33             def qC(self):
34                 return "E42"
35
36             def qfThreadInfo(self):
37                 return "OK" # No threads.
38
39             # Then, when we are asked to attach, error out.
40             def vAttach(self, pid):
41                 return "E42;" + binascii.hexlify(error_msg.encode()).decode()
42
43         self.server.responder = MyResponder()
44
45         target = self.dbg.CreateTarget("")
46         process = self.connect(target)
47         lldbutil.expect_state_changes(self, self.dbg.GetListener(), process, [lldb.eStateConnected])
48
49         error = lldb.SBError()
50         target.AttachToProcessWithID(lldb.SBListener(), 47, error)
51         self.assertEquals(error_msg, error.GetCString())
52
53     def test_read_registers_using_g_packets(self):
54         """Test reading registers using 'g' packets (default behavior)"""
55         self.dbg.HandleCommand(
56                 "settings set plugin.process.gdb-remote.use-g-packet-for-reading true")
57         self.addTearDownHook(lambda: 
58                 self.runCmd("settings set plugin.process.gdb-remote.use-g-packet-for-reading false"))
59         self.server.responder = self.gPacketResponder()
60         target = self.createTarget("a.yaml")
61         process = self.connect(target)
62
63         self.assertEquals(1, self.server.responder.packetLog.count("g"))
64         self.server.responder.packetLog = []
65         self.read_registers(process)
66         # Reading registers should not cause any 'p' packets to be exchanged.
67         self.assertEquals(
68                 0, len([p for p in self.server.responder.packetLog if p.startswith("p")]))
69
70     def test_read_registers_using_p_packets(self):
71         """Test reading registers using 'p' packets"""
72         self.dbg.HandleCommand(
73                 "settings set plugin.process.gdb-remote.use-g-packet-for-reading false")
74         target = self.createTarget("a.yaml")
75         process = self.connect(target)
76
77         self.read_registers(process)
78         self.assertFalse("g" in self.server.responder.packetLog)
79         self.assertGreater(
80                 len([p for p in self.server.responder.packetLog if p.startswith("p")]), 0)
81
82     def test_write_registers_using_P_packets(self):
83         """Test writing registers using 'P' packets (default behavior)"""
84         self.server.responder = self.gPacketResponder()
85         target = self.createTarget("a.yaml")
86         process = self.connect(target)
87
88         self.write_registers(process)
89         self.assertEquals(0, len(
90                 [p for p in self.server.responder.packetLog if p.startswith("G")]))
91         self.assertGreater(
92                 len([p for p in self.server.responder.packetLog if p.startswith("P")]), 0)
93
94     def test_write_registers_using_G_packets(self):
95         """Test writing registers using 'G' packets"""
96
97         class MyResponder(self.gPacketResponder):
98             def readRegister(self, register):
99                 # empty string means unsupported
100                 return ""
101
102         self.server.responder = MyResponder()
103         target = self.createTarget("a.yaml")
104         process = self.connect(target)
105
106         self.write_registers(process)
107         self.assertEquals(0, len(
108                 [p for p in self.server.responder.packetLog if p.startswith("P")]))
109         self.assertGreater(len(
110                 [p for p in self.server.responder.packetLog if p.startswith("G")]), 0)
111
112     def read_registers(self, process):
113         self.for_each_gpr(
114                 process, lambda r: self.assertEquals("0x00000000", r.GetValue()))
115
116     def write_registers(self, process):
117         self.for_each_gpr(
118                 process, lambda r: r.SetValueFromCString("0x00000000"))
119
120     def for_each_gpr(self, process, operation):
121         registers = process.GetThreadAtIndex(0).GetFrameAtIndex(0).GetRegisters()
122         self.assertGreater(registers.GetSize(), 0)
123         regSet = registers[0]
124         numChildren = regSet.GetNumChildren()
125         self.assertGreater(numChildren, 0)
126         for i in range(numChildren):
127             operation(regSet.GetChildAtIndex(i))