blob: 773ddede94a157fb3939e5c216ff9d445839f853 [file] [log] [blame]
Todd Fialae50b2e42014-06-13 19:11:33 +00001"""
2Base class for gdb-remote test cases.
3"""
4
Todd Fiala8aae4f42014-06-13 23:34:17 +00005import errno
Todd Fiala24189d42014-07-14 06:24:44 +00006import os
7import os.path
Todd Fialae50b2e42014-06-13 19:11:33 +00008import platform
Todd Fiala9e2d3292014-07-09 23:10:43 +00009import random
Todd Fialae2202002014-06-27 22:11:56 +000010import re
Todd Fiala31bde322014-07-26 20:39:17 +000011import select
Todd Fialae50b2e42014-06-13 19:11:33 +000012import sets
13import signal
14import socket
15import subprocess
16import sys
Todd Fiala24189d42014-07-14 06:24:44 +000017import tempfile
Todd Fialae50b2e42014-06-13 19:11:33 +000018import time
Todd Fiala24189d42014-07-14 06:24:44 +000019import unittest2
Todd Fialae50b2e42014-06-13 19:11:33 +000020from lldbtest import *
21from lldbgdbserverutils import *
22import logging
Todd Fialae50b2e42014-06-13 19:11:33 +000023
24class GdbRemoteTestCaseBase(TestBase):
25
Todd Fialae50b2e42014-06-13 19:11:33 +000026 _TIMEOUT_SECONDS = 5
27
28 _GDBREMOTE_KILL_PACKET = "$k#6b"
29
30 _LOGGING_LEVEL = logging.WARNING
31 # _LOGGING_LEVEL = logging.DEBUG
32
Todd Fiala7306cf32014-07-29 22:30:01 +000033 # Start the inferior separately, attach to the inferior on the stub command line.
Todd Fialae50b2e42014-06-13 19:11:33 +000034 _STARTUP_ATTACH = "attach"
Todd Fiala7306cf32014-07-29 22:30:01 +000035 # Start the inferior separately, start the stub without attaching, allow the test to attach to the inferior however it wants (e.g. $vAttach;pid).
36 _STARTUP_ATTACH_MANUALLY = "attach_manually"
37 # Start the stub, and launch the inferior with an $A packet via the initial packet stream.
Todd Fialae50b2e42014-06-13 19:11:33 +000038 _STARTUP_LAUNCH = "launch"
39
40 # GDB Signal numbers that are not target-specific used for common exceptions
41 TARGET_EXC_BAD_ACCESS = 0x91
42 TARGET_EXC_BAD_INSTRUCTION = 0x92
43 TARGET_EXC_ARITHMETIC = 0x93
44 TARGET_EXC_EMULATION = 0x94
45 TARGET_EXC_SOFTWARE = 0x95
46 TARGET_EXC_BREAKPOINT = 0x96
47
48 def setUp(self):
49 TestBase.setUp(self)
50 FORMAT = '%(asctime)-15s %(levelname)-8s %(message)s'
51 logging.basicConfig(format=FORMAT)
52 self.logger = logging.getLogger(__name__)
53 self.logger.setLevel(self._LOGGING_LEVEL)
54 self.test_sequence = GdbRemoteTestSequence(self.logger)
55 self.set_inferior_startup_launch()
Todd Fiala9e2d3292014-07-09 23:10:43 +000056 self.port = self.get_next_port()
Todd Fiala67041192014-07-11 22:50:13 +000057 self.named_pipe_path = None
Todd Fiala24189d42014-07-14 06:24:44 +000058 self.named_pipe = None
59 self.named_pipe_fd = None
Todd Fialaf9ad21d2014-07-16 16:15:42 +000060 self.stub_sends_two_stop_notifications_on_kill = False
Chaoren Linf62b7fc2015-05-05 20:34:36 +000061 if lldb.platform_url:
Chaoren Linf9c4c422015-05-06 01:28:04 +000062 scheme, host = re.match('(.+)://(.+):\d+', lldb.platform_url).groups()
Chaoren Lin28b8ea12015-05-07 01:42:53 +000063 if scheme == 'adb':
64 self.stub_device = host
65 self.stub_hostname = 'localhost'
66 else:
67 self.stub_device = None
68 self.stub_hostname = host
Tamas Berghammerde786792015-03-30 10:52:32 +000069 else:
70 self.stub_hostname = "localhost"
Todd Fialae50b2e42014-06-13 19:11:33 +000071
Todd Fiala9e2d3292014-07-09 23:10:43 +000072 def get_next_port(self):
73 return 12000 + random.randint(0,3999)
Todd Fialae50b2e42014-06-13 19:11:33 +000074
75 def reset_test_sequence(self):
76 self.test_sequence = GdbRemoteTestSequence(self.logger)
77
Todd Fiala24189d42014-07-14 06:24:44 +000078 def create_named_pipe(self):
79 # Create a temp dir and name for a pipe.
80 temp_dir = tempfile.mkdtemp()
81 named_pipe_path = os.path.join(temp_dir, "stub_port_number")
82
83 # Create the named pipe.
84 os.mkfifo(named_pipe_path)
85
86 # Open the read side of the pipe in non-blocking mode. This will return right away, ready or not.
87 named_pipe_fd = os.open(named_pipe_path, os.O_RDONLY | os.O_NONBLOCK)
88
89 # Create the file for the named pipe. Note this will follow semantics of
90 # a non-blocking read side of a named pipe, which has different semantics
91 # than a named pipe opened for read in non-blocking mode.
92 named_pipe = os.fdopen(named_pipe_fd, "r")
93 self.assertIsNotNone(named_pipe)
94
95 def shutdown_named_pipe():
96 # Close the pipe.
97 try:
98 named_pipe.close()
99 except:
100 print "failed to close named pipe"
101 None
102
103 # Delete the pipe.
104 try:
105 os.remove(named_pipe_path)
106 except:
107 print "failed to delete named pipe: {}".format(named_pipe_path)
108 None
109
110 # Delete the temp directory.
111 try:
112 os.rmdir(temp_dir)
113 except:
114 print "failed to delete temp dir: {}, directory contents: '{}'".format(temp_dir, os.listdir(temp_dir))
115 None
116
117 # Add the shutdown hook to clean up the named pipe.
118 self.addTearDownHook(shutdown_named_pipe)
119
120 # Clear the port so the stub selects a port number.
121 self.port = 0
122
123 return (named_pipe_path, named_pipe, named_pipe_fd)
124
125 def get_stub_port_from_named_socket(self, read_timeout_seconds=5):
126 # Wait for something to read with a max timeout.
127 (ready_readers, _, _) = select.select([self.named_pipe_fd], [], [], read_timeout_seconds)
128 self.assertIsNotNone(ready_readers, "write side of pipe has not written anything - stub isn't writing to pipe.")
129 self.assertNotEqual(len(ready_readers), 0, "write side of pipe has not written anything - stub isn't writing to pipe.")
130
131 # Read the port from the named pipe.
132 stub_port_raw = self.named_pipe.read()
133 self.assertIsNotNone(stub_port_raw)
134 self.assertNotEqual(len(stub_port_raw), 0, "no content to read on pipe")
135
136 # Trim null byte, convert to int.
137 stub_port_raw = stub_port_raw[:-1]
138 stub_port = int(stub_port_raw)
139 self.assertTrue(stub_port > 0)
140
141 return stub_port
142
143 def init_llgs_test(self, use_named_pipe=True):
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000144 if lldb.remote_platform:
145 # Remote platforms don't support named pipe based port negotiation
146 use_named_pipe = False
147
148 platform = self.dbg.GetSelectedPlatform()
149
150 shell_command = lldb.SBPlatformShellCommand("echo $PPID")
151 err = platform.Run(shell_command)
152 if err.Fail():
153 raise Exception("remote_platform.RunShellCommand('echo $PPID') failed: %s" % err)
154 pid = shell_command.GetOutput().strip()
155
156 shell_command = lldb.SBPlatformShellCommand("readlink /proc/%s/exe" % pid)
157 err = platform.Run(shell_command)
158 if err.Fail():
159 raise Exception("remote_platform.RunShellCommand('readlink /proc/%d/exe') failed: %s" % (pid, err))
Ying Chencd819142015-05-08 01:47:17 +0000160 # If the binary has been deleted, the link name has " (deleted)" appended.
161 # Remove if it's there.
Ying Chenc5430522015-05-08 01:25:10 +0000162 self.debug_monitor_exe = re.sub(r' \(deleted\)$', '', shell_command.GetOutput().strip())
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000163 else:
164 self.debug_monitor_exe = get_lldb_server_exe()
165 if not self.debug_monitor_exe:
166 self.skipTest("lldb-server exe not found")
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000167
Vince Harronf1ff3c12015-05-10 18:02:53 +0000168 self.debug_monitor_extra_args = ["gdbserver"]
Vince Harron1f160372015-05-21 18:51:20 +0000169
170 if len(lldbtest_config.channels) > 0:
171 self.debug_monitor_extra_args.append("--log-file={}-server.log".format(self.log_basename))
172 self.debug_monitor_extra_args.append("--log-channels={}".format(":".join(lldbtest_config.channels)))
173
Todd Fiala24189d42014-07-14 06:24:44 +0000174 if use_named_pipe:
175 (self.named_pipe_path, self.named_pipe, self.named_pipe_fd) = self.create_named_pipe()
Todd Fialae50b2e42014-06-13 19:11:33 +0000176
Todd Fiala24189d42014-07-14 06:24:44 +0000177 def init_debugserver_test(self, use_named_pipe=True):
Todd Fialae50b2e42014-06-13 19:11:33 +0000178 self.debug_monitor_exe = get_debugserver_exe()
179 if not self.debug_monitor_exe:
180 self.skipTest("debugserver exe not found")
Vince Harron1f160372015-05-21 18:51:20 +0000181 self.debug_monitor_extra_args = ["--log-file={}-server.log".format(self.log_basename), "--log-flags=0x800000"]
Todd Fiala24189d42014-07-14 06:24:44 +0000182 if use_named_pipe:
183 (self.named_pipe_path, self.named_pipe, self.named_pipe_fd) = self.create_named_pipe()
Todd Fialaf9ad21d2014-07-16 16:15:42 +0000184 # The debugserver stub has a race on handling the 'k' command, so it sends an X09 right away, then sends the real X notification
185 # when the process truly dies.
186 self.stub_sends_two_stop_notifications_on_kill = True
Todd Fialae50b2e42014-06-13 19:11:33 +0000187
Chaoren Lin28b8ea12015-05-07 01:42:53 +0000188 def forward_adb_port(self, source, target, direction, device):
189 adb = [ 'adb' ] + ([ '-s', device ] if device else []) + [ direction ]
Tamas Berghammer27c8d362015-03-13 14:32:25 +0000190 def remove_port_forward():
Chaoren Lin28b8ea12015-05-07 01:42:53 +0000191 subprocess.call(adb + [ "--remove", "tcp:%d" % source])
192
193 subprocess.call(adb + [ "tcp:%d" % source, "tcp:%d" % target])
Tamas Berghammer27c8d362015-03-13 14:32:25 +0000194 self.addTearDownHook(remove_port_forward)
195
Todd Fialae50b2e42014-06-13 19:11:33 +0000196 def create_socket(self):
197 sock = socket.socket()
198 logger = self.logger
199
Tamas Berghammerde786792015-03-30 10:52:32 +0000200 triple = self.dbg.GetSelectedPlatform().GetTriple()
201 if re.match(".*-.*-.*-android", triple):
Chaoren Lin28b8ea12015-05-07 01:42:53 +0000202 self.forward_adb_port(self.port, self.port, "forward", self.stub_device)
Tamas Berghammerde786792015-03-30 10:52:32 +0000203
204 connect_info = (self.stub_hostname, self.port)
205 sock.connect(connect_info)
206
Todd Fialae50b2e42014-06-13 19:11:33 +0000207 def shutdown_socket():
208 if sock:
209 try:
Robert Flack8cc4cf12015-03-06 14:36:33 +0000210 # send the kill packet so lldb-server shuts down gracefully
Todd Fialae50b2e42014-06-13 19:11:33 +0000211 sock.sendall(GdbRemoteTestCaseBase._GDBREMOTE_KILL_PACKET)
212 except:
213 logger.warning("failed to send kill packet to debug monitor: {}; ignoring".format(sys.exc_info()[0]))
214
215 try:
216 sock.close()
217 except:
218 logger.warning("failed to close socket to debug monitor: {}; ignoring".format(sys.exc_info()[0]))
219
220 self.addTearDownHook(shutdown_socket)
221
Todd Fialae50b2e42014-06-13 19:11:33 +0000222 return sock
223
224 def set_inferior_startup_launch(self):
225 self._inferior_startup = self._STARTUP_LAUNCH
226
227 def set_inferior_startup_attach(self):
228 self._inferior_startup = self._STARTUP_ATTACH
229
Todd Fiala7306cf32014-07-29 22:30:01 +0000230 def set_inferior_startup_attach_manually(self):
231 self._inferior_startup = self._STARTUP_ATTACH_MANUALLY
232
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000233 def get_debug_monitor_command_line_args(self, attach_pid=None):
Tamas Berghammerde786792015-03-30 10:52:32 +0000234 if lldb.remote_platform:
235 commandline_args = self.debug_monitor_extra_args + ["*:{}".format(self.port)]
236 else:
237 commandline_args = self.debug_monitor_extra_args + ["localhost:{}".format(self.port)]
238
Todd Fialae50b2e42014-06-13 19:11:33 +0000239 if attach_pid:
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000240 commandline_args += ["--attach=%d" % attach_pid]
Todd Fiala67041192014-07-11 22:50:13 +0000241 if self.named_pipe_path:
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000242 commandline_args += ["--named-pipe", self.named_pipe_path]
243 return commandline_args
244
245 def run_platform_command(self, cmd):
246 platform = self.dbg.GetSelectedPlatform()
247 shell_command = lldb.SBPlatformShellCommand(cmd)
248 err = platform.Run(shell_command)
249 return (err, shell_command.GetOutput())
Todd Fiala31bde322014-07-26 20:39:17 +0000250
251 def launch_debug_monitor(self, attach_pid=None, logfile=None):
252 # Create the command line.
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000253 commandline_args = self.get_debug_monitor_command_line_args(attach_pid=attach_pid)
Todd Fialae50b2e42014-06-13 19:11:33 +0000254
Todd Fiala8aae4f42014-06-13 23:34:17 +0000255 # Start the server.
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000256 server = self.spawnSubprocess(self.debug_monitor_exe, commandline_args, install_remote=False)
257 self.addTearDownHook(self.cleanupSubprocesses)
Todd Fiala24189d42014-07-14 06:24:44 +0000258 self.assertIsNotNone(server)
Todd Fiala24189d42014-07-14 06:24:44 +0000259
260 # If we're receiving the stub's listening port from the named pipe, do that here.
261 if self.named_pipe:
262 self.port = self.get_stub_port_from_named_socket()
Todd Fialae50b2e42014-06-13 19:11:33 +0000263
Todd Fiala8aae4f42014-06-13 23:34:17 +0000264 return server
265
266 def connect_to_debug_monitor(self, attach_pid=None):
Todd Fiala24189d42014-07-14 06:24:44 +0000267 if self.named_pipe:
268 # Create the stub.
269 server = self.launch_debug_monitor(attach_pid=attach_pid)
270 self.assertIsNotNone(server)
271
272 def shutdown_debug_monitor():
273 try:
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000274 server.terminate()
Todd Fiala24189d42014-07-14 06:24:44 +0000275 except:
Ilia K7c1d91d2015-04-15 13:08:35 +0000276 logger.warning("failed to terminate server for debug monitor: {}; ignoring".format(sys.exc_info()[0]))
Todd Fiala24189d42014-07-14 06:24:44 +0000277 self.addTearDownHook(shutdown_debug_monitor)
278
279 # Schedule debug monitor to be shut down during teardown.
280 logger = self.logger
281
282 # Attach to the stub and return a socket opened to it.
283 self.sock = self.create_socket()
284 return server
285
286 # We're using a random port algorithm to try not to collide with other ports,
287 # and retry a max # times.
Todd Fiala8aae4f42014-06-13 23:34:17 +0000288 attempts = 0
289 MAX_ATTEMPTS = 20
Todd Fialae50b2e42014-06-13 19:11:33 +0000290
Todd Fiala8aae4f42014-06-13 23:34:17 +0000291 while attempts < MAX_ATTEMPTS:
Todd Fiala9e2d3292014-07-09 23:10:43 +0000292 server = self.launch_debug_monitor(attach_pid=attach_pid)
293
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000294 # Schedule debug monitor to be shut down during teardown.
295 logger = self.logger
296 def shutdown_debug_monitor():
Todd Fiala9e2d3292014-07-09 23:10:43 +0000297 try:
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000298 server.terminate()
299 except:
300 logger.warning("failed to terminate server for debug monitor: {}; ignoring".format(sys.exc_info()[0]))
301 self.addTearDownHook(shutdown_debug_monitor)
302
Tamas Berghammerde786792015-03-30 10:52:32 +0000303 connect_attemps = 0
304 MAX_CONNECT_ATTEMPTS = 10
305
306 while connect_attemps < MAX_CONNECT_ATTEMPTS:
307 # Create a socket to talk to the server
308 try:
309 self.sock = self.create_socket()
310 return server
311 except socket.error as serr:
312 # We're only trying to handle connection refused.
313 if serr.errno != errno.ECONNREFUSED:
314 raise serr
315 time.sleep(0.5)
316 connect_attemps += 1
317
318 # We should close the server here to be safe.
319 server.terminate()
Todd Fiala9e2d3292014-07-09 23:10:43 +0000320
321 # Increment attempts.
322 print("connect to debug monitor on port %d failed, attempt #%d of %d" % (self.port, attempts + 1, MAX_ATTEMPTS))
323 attempts += 1
324
325 # And wait a random length of time before next attempt, to avoid collisions.
326 time.sleep(random.randint(1,5))
327
328 # Now grab a new port number.
329 self.port = self.get_next_port()
Todd Fiala8aae4f42014-06-13 23:34:17 +0000330
331 raise Exception("failed to create a socket to the launched debug monitor after %d tries" % attempts)
Todd Fialae50b2e42014-06-13 19:11:33 +0000332
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000333 def launch_process_for_attach(self, inferior_args=None, sleep_seconds=3, exe_path=None):
Todd Fialae50b2e42014-06-13 19:11:33 +0000334 # We're going to start a child process that the debug monitor stub can later attach to.
335 # This process needs to be started so that it just hangs around for a while. We'll
336 # have it sleep.
Todd Fiala58a2f662014-08-12 17:02:07 +0000337 if not exe_path:
338 exe_path = os.path.abspath("a.out")
Todd Fialae50b2e42014-06-13 19:11:33 +0000339
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000340 args = []
Todd Fialae50b2e42014-06-13 19:11:33 +0000341 if inferior_args:
342 args.extend(inferior_args)
343 if sleep_seconds:
344 args.append("sleep:%d" % sleep_seconds)
345
Ilia K7c1d91d2015-04-15 13:08:35 +0000346 inferior = self.spawnSubprocess(exe_path, args)
347 def shutdown_process_for_attach():
348 try:
349 inferior.terminate()
350 except:
351 logger.warning("failed to terminate inferior process for attach: {}; ignoring".format(sys.exc_info()[0]))
352 self.addTearDownHook(shutdown_process_for_attach)
353 return inferior
Todd Fialae50b2e42014-06-13 19:11:33 +0000354
Todd Fiala58a2f662014-08-12 17:02:07 +0000355 def prep_debug_monitor_and_inferior(self, inferior_args=None, inferior_sleep_seconds=3, inferior_exe_path=None):
Todd Fialae50b2e42014-06-13 19:11:33 +0000356 """Prep the debug monitor, the inferior, and the expected packet stream.
357
358 Handle the separate cases of using the debug monitor in attach-to-inferior mode
359 and in launch-inferior mode.
360
361 For attach-to-inferior mode, the inferior process is first started, then
362 the debug monitor is started in attach to pid mode (using --attach on the
363 stub command line), and the no-ack-mode setup is appended to the packet
364 stream. The packet stream is not yet executed, ready to have more expected
365 packet entries added to it.
366
367 For launch-inferior mode, the stub is first started, then no ack mode is
368 setup on the expected packet stream, then the verified launch packets are added
369 to the expected socket stream. The packet stream is not yet executed, ready
370 to have more expected packet entries added to it.
371
372 The return value is:
373 {inferior:<inferior>, server:<server>}
374 """
375 inferior = None
376 attach_pid = None
377
Todd Fiala7306cf32014-07-29 22:30:01 +0000378 if self._inferior_startup == self._STARTUP_ATTACH or self._inferior_startup == self._STARTUP_ATTACH_MANUALLY:
Todd Fialae50b2e42014-06-13 19:11:33 +0000379 # Launch the process that we'll use as the inferior.
Todd Fiala58a2f662014-08-12 17:02:07 +0000380 inferior = self.launch_process_for_attach(inferior_args=inferior_args, sleep_seconds=inferior_sleep_seconds, exe_path=inferior_exe_path)
Todd Fialae50b2e42014-06-13 19:11:33 +0000381 self.assertIsNotNone(inferior)
382 self.assertTrue(inferior.pid > 0)
Todd Fiala7306cf32014-07-29 22:30:01 +0000383 if self._inferior_startup == self._STARTUP_ATTACH:
384 # In this case, we want the stub to attach via the command line, so set the command line attach pid here.
385 attach_pid = inferior.pid
Todd Fialae50b2e42014-06-13 19:11:33 +0000386
Todd Fialae50b2e42014-06-13 19:11:33 +0000387 if self._inferior_startup == self._STARTUP_LAUNCH:
388 # Build launch args
Todd Fiala58a2f662014-08-12 17:02:07 +0000389 if not inferior_exe_path:
390 inferior_exe_path = os.path.abspath("a.out")
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000391
392 if lldb.remote_platform:
Chaoren Lin3e2bdb42015-05-11 17:53:39 +0000393 remote_path = lldbutil.append_to_remote_wd(os.path.basename(inferior_exe_path))
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000394 remote_file_spec = lldb.SBFileSpec(remote_path, False)
395 err = lldb.remote_platform.Install(lldb.SBFileSpec(inferior_exe_path, True), remote_file_spec)
396 if err.Fail():
397 raise Exception("remote_platform.Install('%s', '%s') failed: %s" % (inferior_exe_path, remote_path, err))
398 inferior_exe_path = remote_path
399
Todd Fiala58a2f662014-08-12 17:02:07 +0000400 launch_args = [inferior_exe_path]
Todd Fialae50b2e42014-06-13 19:11:33 +0000401 if inferior_args:
402 launch_args.extend(inferior_args)
403
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000404 # Launch the debug monitor stub, attaching to the inferior.
405 server = self.connect_to_debug_monitor(attach_pid=attach_pid)
406 self.assertIsNotNone(server)
407
Todd Fialae50b2e42014-06-13 19:11:33 +0000408 # Build the expected protocol stream
409 self.add_no_ack_remote_stream()
410 if self._inferior_startup == self._STARTUP_LAUNCH:
411 self.add_verified_launch_packets(launch_args)
412
413 return {"inferior":inferior, "server":server}
414
Todd Fiala31bde322014-07-26 20:39:17 +0000415 def expect_socket_recv(self, sock, expected_content_regex, timeout_seconds):
416 response = ""
417 timeout_time = time.time() + timeout_seconds
418
419 while not expected_content_regex.match(response) and time.time() < timeout_time:
420 can_read, _, _ = select.select([sock], [], [], timeout_seconds)
421 if can_read and sock in can_read:
422 recv_bytes = sock.recv(4096)
423 if recv_bytes:
424 response += recv_bytes
425
426 self.assertTrue(expected_content_regex.match(response))
427
428 def expect_socket_send(self, sock, content, timeout_seconds):
429 request_bytes_remaining = content
430 timeout_time = time.time() + timeout_seconds
431
432 while len(request_bytes_remaining) > 0 and time.time() < timeout_time:
433 _, can_write, _ = select.select([], [sock], [], timeout_seconds)
434 if can_write and sock in can_write:
435 written_byte_count = sock.send(request_bytes_remaining)
436 request_bytes_remaining = request_bytes_remaining[written_byte_count:]
437 self.assertEquals(len(request_bytes_remaining), 0)
438
439 def do_handshake(self, stub_socket, timeout_seconds=5):
440 # Write the ack.
441 self.expect_socket_send(stub_socket, "+", timeout_seconds)
442
443 # Send the start no ack mode packet.
444 NO_ACK_MODE_REQUEST = "$QStartNoAckMode#b0"
445 bytes_sent = stub_socket.send(NO_ACK_MODE_REQUEST)
446 self.assertEquals(bytes_sent, len(NO_ACK_MODE_REQUEST))
447
448 # Receive the ack and "OK"
449 self.expect_socket_recv(stub_socket, re.compile(r"^\+\$OK#[0-9a-fA-F]{2}$"), timeout_seconds)
450
451 # Send the final ack.
452 self.expect_socket_send(stub_socket, "+", timeout_seconds)
453
Todd Fialae50b2e42014-06-13 19:11:33 +0000454 def add_no_ack_remote_stream(self):
455 self.test_sequence.add_log_lines(
456 ["read packet: +",
457 "read packet: $QStartNoAckMode#b0",
458 "send packet: +",
459 "send packet: $OK#9a",
460 "read packet: +"],
461 True)
462
463 def add_verified_launch_packets(self, launch_args):
464 self.test_sequence.add_log_lines(
465 ["read packet: %s" % build_gdbremote_A_packet(launch_args),
466 "send packet: $OK#00",
467 "read packet: $qLaunchSuccess#a5",
468 "send packet: $OK#00"],
469 True)
470
471 def add_thread_suffix_request_packets(self):
472 self.test_sequence.add_log_lines(
Stephane Sezer22ed42e2014-11-13 21:39:24 +0000473 ["read packet: $QThreadSuffixSupported#e4",
Todd Fialae50b2e42014-06-13 19:11:33 +0000474 "send packet: $OK#00",
475 ], True)
476
477 def add_process_info_collection_packets(self):
478 self.test_sequence.add_log_lines(
Stephane Sezer22ed42e2014-11-13 21:39:24 +0000479 ["read packet: $qProcessInfo#dc",
Todd Fiala8aae4f42014-06-13 23:34:17 +0000480 { "direction":"send", "regex":r"^\$(.+)#[0-9a-fA-F]{2}$", "capture":{1:"process_info_raw"} }],
Todd Fialae50b2e42014-06-13 19:11:33 +0000481 True)
482
483 _KNOWN_PROCESS_INFO_KEYS = [
484 "pid",
485 "parent-pid",
486 "real-uid",
487 "real-gid",
488 "effective-uid",
489 "effective-gid",
490 "cputype",
491 "cpusubtype",
492 "ostype",
Todd Fialac540dd02014-08-26 18:21:02 +0000493 "triple",
Todd Fialae50b2e42014-06-13 19:11:33 +0000494 "vendor",
495 "endian",
496 "ptrsize"
497 ]
498
499 def parse_process_info_response(self, context):
500 # Ensure we have a process info response.
501 self.assertIsNotNone(context)
502 process_info_raw = context.get("process_info_raw")
503 self.assertIsNotNone(process_info_raw)
504
505 # Pull out key:value; pairs.
506 process_info_dict = { match.group(1):match.group(2) for match in re.finditer(r"([^:]+):([^;]+);", process_info_raw) }
507
508 # Validate keys are known.
509 for (key, val) in process_info_dict.items():
510 self.assertTrue(key in self._KNOWN_PROCESS_INFO_KEYS)
511 self.assertIsNotNone(val)
512
513 return process_info_dict
514
515 def add_register_info_collection_packets(self):
516 self.test_sequence.add_log_lines(
517 [ { "type":"multi_response", "query":"qRegisterInfo", "append_iteration_suffix":True,
518 "end_regex":re.compile(r"^\$(E\d+)?#[0-9a-fA-F]{2}$"),
519 "save_key":"reg_info_responses" } ],
520 True)
521
522 def parse_register_info_packets(self, context):
523 """Return an array of register info dictionaries, one per register info."""
524 reg_info_responses = context.get("reg_info_responses")
525 self.assertIsNotNone(reg_info_responses)
526
527 # Parse register infos.
528 return [parse_reg_info_response(reg_info_response) for reg_info_response in reg_info_responses]
529
Todd Fiala50a211b2014-06-14 22:00:36 +0000530 def expect_gdbremote_sequence(self, timeout_seconds=None):
Todd Fiala8aae4f42014-06-13 23:34:17 +0000531 if not timeout_seconds:
532 timeout_seconds = self._TIMEOUT_SECONDS
533 return expect_lldb_gdbserver_replay(self, self.sock, self.test_sequence, timeout_seconds, self.logger)
Todd Fialae50b2e42014-06-13 19:11:33 +0000534
535 _KNOWN_REGINFO_KEYS = [
536 "name",
537 "alt-name",
538 "bitsize",
539 "offset",
540 "encoding",
541 "format",
542 "set",
543 "gcc",
544 "dwarf",
545 "generic",
546 "container-regs",
547 "invalidate-regs"
548 ]
549
550 def assert_valid_reg_info(self, reg_info):
551 # Assert we know about all the reginfo keys parsed.
552 for key in reg_info:
553 self.assertTrue(key in self._KNOWN_REGINFO_KEYS)
554
555 # Check the bare-minimum expected set of register info keys.
556 self.assertTrue("name" in reg_info)
557 self.assertTrue("bitsize" in reg_info)
558 self.assertTrue("offset" in reg_info)
559 self.assertTrue("encoding" in reg_info)
560 self.assertTrue("format" in reg_info)
561
562 def find_pc_reg_info(self, reg_infos):
563 lldb_reg_index = 0
564 for reg_info in reg_infos:
565 if ("generic" in reg_info) and (reg_info["generic"] == "pc"):
566 return (lldb_reg_index, reg_info)
567 lldb_reg_index += 1
568
569 return (None, None)
570
571 def add_lldb_register_index(self, reg_infos):
572 """Add a "lldb_register_index" key containing the 0-baed index of each reg_infos entry.
573
574 We'll use this when we want to call packets like P/p with a register index but do so
575 on only a subset of the full register info set.
576 """
577 self.assertIsNotNone(reg_infos)
578
579 reg_index = 0
580 for reg_info in reg_infos:
581 reg_info["lldb_register_index"] = reg_index
582 reg_index += 1
583
584 def add_query_memory_region_packets(self, address):
585 self.test_sequence.add_log_lines(
586 ["read packet: $qMemoryRegionInfo:{0:x}#00".format(address),
587 {"direction":"send", "regex":r"^\$(.+)#[0-9a-fA-F]{2}$", "capture":{1:"memory_region_response"} }],
588 True)
589
Todd Fialac30281a2014-06-14 03:03:23 +0000590 def parse_key_val_dict(self, key_val_text, allow_dupes=True):
Todd Fialae50b2e42014-06-13 19:11:33 +0000591 self.assertIsNotNone(key_val_text)
592 kv_dict = {}
593 for match in re.finditer(r";?([^:]+):([^;]+)", key_val_text):
Todd Fialac30281a2014-06-14 03:03:23 +0000594 key = match.group(1)
595 val = match.group(2)
596 if key in kv_dict:
597 if allow_dupes:
598 if type(kv_dict[key]) == list:
599 kv_dict[key].append(val)
600 else:
601 # Promote to list
602 kv_dict[key] = [kv_dict[key], val]
603 else:
604 self.fail("key '{}' already present when attempting to add value '{}' (text='{}', dict={})".format(key, val, key_val_text, kv_dict))
605 else:
606 kv_dict[key] = val
Todd Fialae50b2e42014-06-13 19:11:33 +0000607 return kv_dict
608
609 def parse_memory_region_packet(self, context):
610 # Ensure we have a context.
611 self.assertIsNotNone(context.get("memory_region_response"))
612
613 # Pull out key:value; pairs.
614 mem_region_dict = self.parse_key_val_dict(context.get("memory_region_response"))
615
616 # Validate keys are known.
617 for (key, val) in mem_region_dict.items():
618 self.assertTrue(key in ["start", "size", "permissions", "error"])
619 self.assertIsNotNone(val)
620
621 # Return the dictionary of key-value pairs for the memory region.
622 return mem_region_dict
623
624 def assert_address_within_memory_region(self, test_address, mem_region_dict):
625 self.assertIsNotNone(mem_region_dict)
626 self.assertTrue("start" in mem_region_dict)
627 self.assertTrue("size" in mem_region_dict)
628
629 range_start = int(mem_region_dict["start"], 16)
630 range_size = int(mem_region_dict["size"], 16)
631 range_end = range_start + range_size
632
633 if test_address < range_start:
634 self.fail("address 0x{0:x} comes before range 0x{1:x} - 0x{2:x} (size 0x{3:x})".format(test_address, range_start, range_end, range_size))
635 elif test_address >= range_end:
636 self.fail("address 0x{0:x} comes after range 0x{1:x} - 0x{2:x} (size 0x{3:x})".format(test_address, range_start, range_end, range_size))
637
638 def add_threadinfo_collection_packets(self):
639 self.test_sequence.add_log_lines(
640 [ { "type":"multi_response", "first_query":"qfThreadInfo", "next_query":"qsThreadInfo",
641 "append_iteration_suffix":False, "end_regex":re.compile(r"^\$(l)?#[0-9a-fA-F]{2}$"),
642 "save_key":"threadinfo_responses" } ],
643 True)
644
645 def parse_threadinfo_packets(self, context):
646 """Return an array of thread ids (decimal ints), one per thread."""
647 threadinfo_responses = context.get("threadinfo_responses")
648 self.assertIsNotNone(threadinfo_responses)
649
650 thread_ids = []
651 for threadinfo_response in threadinfo_responses:
652 new_thread_infos = parse_threadinfo_response(threadinfo_response)
653 thread_ids.extend(new_thread_infos)
654 return thread_ids
655
656 def wait_for_thread_count(self, thread_count, timeout_seconds=3):
657 start_time = time.time()
658 timeout_time = start_time + timeout_seconds
659
660 actual_thread_count = 0
661 while actual_thread_count < thread_count:
662 self.reset_test_sequence()
663 self.add_threadinfo_collection_packets()
664
665 context = self.expect_gdbremote_sequence()
666 self.assertIsNotNone(context)
667
668 threads = self.parse_threadinfo_packets(context)
669 self.assertIsNotNone(threads)
670
671 actual_thread_count = len(threads)
672
673 if time.time() > timeout_time:
674 raise Exception(
675 'timed out after {} seconds while waiting for theads: waiting for at least {} threads, found {}'.format(
676 timeout_seconds, thread_count, actual_thread_count))
677
678 return threads
679
680 def add_set_breakpoint_packets(self, address, do_continue=True, breakpoint_kind=1):
681 self.test_sequence.add_log_lines(
682 [# Set the breakpoint.
683 "read packet: $Z0,{0:x},{1}#00".format(address, breakpoint_kind),
684 # Verify the stub could set it.
685 "send packet: $OK#00",
686 ], True)
687
688 if (do_continue):
689 self.test_sequence.add_log_lines(
690 [# Continue the inferior.
Stephane Sezer22ed42e2014-11-13 21:39:24 +0000691 "read packet: $c#63",
Todd Fialae50b2e42014-06-13 19:11:33 +0000692 # Expect a breakpoint stop report.
693 {"direction":"send", "regex":r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);", "capture":{1:"stop_signo", 2:"stop_thread_id"} },
694 ], True)
695
696 def add_remove_breakpoint_packets(self, address, breakpoint_kind=1):
697 self.test_sequence.add_log_lines(
698 [# Remove the breakpoint.
699 "read packet: $z0,{0:x},{1}#00".format(address, breakpoint_kind),
700 # Verify the stub could unset it.
701 "send packet: $OK#00",
702 ], True)
703
704 def add_qSupported_packets(self):
705 self.test_sequence.add_log_lines(
706 ["read packet: $qSupported#00",
707 {"direction":"send", "regex":r"^\$(.*)#[0-9a-fA-F]{2}", "capture":{1: "qSupported_response"}},
708 ], True)
709
710 _KNOWN_QSUPPORTED_STUB_FEATURES = [
711 "augmented-libraries-svr4-read",
712 "PacketSize",
713 "QStartNoAckMode",
Todd Fiala8aae4f42014-06-13 23:34:17 +0000714 "QThreadSuffixSupported",
Todd Fiala43ab82c2014-06-15 23:33:09 +0000715 "QListThreadsInStopReply",
Todd Fialae50b2e42014-06-13 19:11:33 +0000716 "qXfer:auxv:read",
717 "qXfer:libraries:read",
718 "qXfer:libraries-svr4:read",
Ying Chen294c9262015-05-26 23:08:09 +0000719 "qXfer:features:read",
Todd Fialae50b2e42014-06-13 19:11:33 +0000720 ]
721
722 def parse_qSupported_response(self, context):
723 self.assertIsNotNone(context)
724
725 raw_response = context.get("qSupported_response")
726 self.assertIsNotNone(raw_response)
727
728 # For values with key=val, the dict key and vals are set as expected. For feature+, feature- and feature?, the
729 # +,-,? is stripped from the key and set as the value.
730 supported_dict = {}
731 for match in re.finditer(r";?([^=;]+)(=([^;]+))?", raw_response):
732 key = match.group(1)
733 val = match.group(3)
734
735 # key=val: store as is
736 if val and len(val) > 0:
737 supported_dict[key] = val
738 else:
739 if len(key) < 2:
740 raise Exception("singular stub feature is too short: must be stub_feature{+,-,?}")
741 supported_type = key[-1]
742 key = key[:-1]
743 if not supported_type in ["+", "-", "?"]:
744 raise Exception("malformed stub feature: final character {} not in expected set (+,-,?)".format(supported_type))
745 supported_dict[key] = supported_type
746 # Ensure we know the supported element
747 if not key in self._KNOWN_QSUPPORTED_STUB_FEATURES:
748 raise Exception("unknown qSupported stub feature reported: %s" % key)
749
750 return supported_dict
751
752 def run_process_then_stop(self, run_seconds=1):
753 # Tell the stub to continue.
754 self.test_sequence.add_log_lines(
Stephane Sezerb6e81922014-11-20 18:50:46 +0000755 ["read packet: $vCont;c#a8"],
Todd Fialae50b2e42014-06-13 19:11:33 +0000756 True)
757 context = self.expect_gdbremote_sequence()
758
759 # Wait for run_seconds.
760 time.sleep(run_seconds)
761
762 # Send an interrupt, capture a T response.
763 self.reset_test_sequence()
764 self.test_sequence.add_log_lines(
765 ["read packet: {}".format(chr(03)),
766 {"direction":"send", "regex":r"^\$T([0-9a-fA-F]+)([^#]+)#[0-9a-fA-F]{2}$", "capture":{1:"stop_result"} }],
767 True)
768 context = self.expect_gdbremote_sequence()
769 self.assertIsNotNone(context)
770 self.assertIsNotNone(context.get("stop_result"))
771
772 return context
773
774 def select_modifiable_register(self, reg_infos):
775 """Find a register that can be read/written freely."""
776 PREFERRED_REGISTER_NAMES = sets.Set(["rax",])
777
778 # First check for the first register from the preferred register name set.
779 alternative_register_index = None
780
781 self.assertIsNotNone(reg_infos)
782 for reg_info in reg_infos:
783 if ("name" in reg_info) and (reg_info["name"] in PREFERRED_REGISTER_NAMES):
784 # We found a preferred register. Use it.
785 return reg_info["lldb_register_index"]
786 if ("generic" in reg_info) and (reg_info["generic"] == "fp"):
787 # A frame pointer register will do as a register to modify temporarily.
788 alternative_register_index = reg_info["lldb_register_index"]
789
790 # We didn't find a preferred register. Return whatever alternative register
791 # we found, if any.
792 return alternative_register_index
793
794 def extract_registers_from_stop_notification(self, stop_key_vals_text):
795 self.assertIsNotNone(stop_key_vals_text)
796 kv_dict = self.parse_key_val_dict(stop_key_vals_text)
797
798 registers = {}
799 for (key, val) in kv_dict.items():
Stephane Sezer5109a792014-11-14 09:46:21 +0000800 if re.match(r"^[0-9a-fA-F]+$", key):
Todd Fialae50b2e42014-06-13 19:11:33 +0000801 registers[int(key, 16)] = val
802 return registers
803
804 def gather_register_infos(self):
805 self.reset_test_sequence()
806 self.add_register_info_collection_packets()
807
808 context = self.expect_gdbremote_sequence()
809 self.assertIsNotNone(context)
810
811 reg_infos = self.parse_register_info_packets(context)
812 self.assertIsNotNone(reg_infos)
813 self.add_lldb_register_index(reg_infos)
814
815 return reg_infos
816
817 def find_generic_register_with_name(self, reg_infos, generic_name):
818 self.assertIsNotNone(reg_infos)
819 for reg_info in reg_infos:
820 if ("generic" in reg_info) and (reg_info["generic"] == generic_name):
821 return reg_info
822 return None
823
Todd Fiala8d7ab8c2014-06-17 16:04:45 +0000824 def decode_gdbremote_binary(self, encoded_bytes):
825 decoded_bytes = ""
826 i = 0
827 while i < len(encoded_bytes):
828 if encoded_bytes[i] == "}":
829 # Handle escaped char.
830 self.assertTrue(i + 1 < len(encoded_bytes))
831 decoded_bytes += chr(ord(encoded_bytes[i+1]) ^ 0x20)
832 i +=2
833 elif encoded_bytes[i] == "*":
834 # Handle run length encoding.
835 self.assertTrue(len(decoded_bytes) > 0)
836 self.assertTrue(i + 1 < len(encoded_bytes))
837 repeat_count = ord(encoded_bytes[i+1]) - 29
838 decoded_bytes += decoded_bytes[-1] * repeat_count
839 i += 2
840 else:
841 decoded_bytes += encoded_bytes[i]
842 i += 1
843 return decoded_bytes
844
845 def build_auxv_dict(self, endian, word_size, auxv_data):
846 self.assertIsNotNone(endian)
847 self.assertIsNotNone(word_size)
848 self.assertIsNotNone(auxv_data)
849
850 auxv_dict = {}
851
852 while len(auxv_data) > 0:
853 # Chop off key.
854 raw_key = auxv_data[:word_size]
855 auxv_data = auxv_data[word_size:]
856
857 # Chop of value.
858 raw_value = auxv_data[:word_size]
859 auxv_data = auxv_data[word_size:]
860
861 # Convert raw text from target endian.
862 key = unpack_endian_binary_string(endian, raw_key)
863 value = unpack_endian_binary_string(endian, raw_value)
864
865 # Handle ending entry.
866 if key == 0:
867 self.assertEquals(value, 0)
868 return auxv_dict
869
870 # The key should not already be present.
871 self.assertFalse(key in auxv_dict)
872 auxv_dict[key] = value
873
874 self.fail("should not reach here - implies required double zero entry not found")
875 return auxv_dict
Todd Fiala51886732014-06-17 22:01:27 +0000876
877 def read_binary_data_in_chunks(self, command_prefix, chunk_length):
878 """Collect command_prefix{offset:x},{chunk_length:x} until a single 'l' or 'l' with data is returned."""
879 offset = 0
880 done = False
881 decoded_data = ""
882
883 while not done:
884 # Grab the next iteration of data.
885 self.reset_test_sequence()
886 self.test_sequence.add_log_lines([
887 "read packet: ${}{:x},{:x}:#00".format(command_prefix, offset, chunk_length),
Todd Fiala4c24eba2014-06-19 17:35:40 +0000888 {"direction":"send", "regex":re.compile(r"^\$([^E])(.*)#[0-9a-fA-F]{2}$", re.MULTILINE|re.DOTALL), "capture":{1:"response_type", 2:"content_raw"} }
Todd Fiala51886732014-06-17 22:01:27 +0000889 ], True)
890
891 context = self.expect_gdbremote_sequence()
892 self.assertIsNotNone(context)
893
894 response_type = context.get("response_type")
895 self.assertIsNotNone(response_type)
896 self.assertTrue(response_type in ["l", "m"])
897
898 # Move offset along.
899 offset += chunk_length
900
901 # Figure out if we're done. We're done if the response type is l.
902 done = response_type == "l"
903
904 # Decode binary data.
905 content_raw = context.get("content_raw")
906 if content_raw and len(content_raw) > 0:
907 self.assertIsNotNone(content_raw)
908 decoded_data += self.decode_gdbremote_binary(content_raw)
909 return decoded_data
Todd Fiala4c24eba2014-06-19 17:35:40 +0000910
911 def add_interrupt_packets(self):
912 self.test_sequence.add_log_lines([
913 # Send the intterupt.
914 "read packet: {}".format(chr(03)),
915 # And wait for the stop notification.
916 {"direction":"send", "regex":r"^\$T([0-9a-fA-F]{2})(.*)#[0-9a-fA-F]{2}$", "capture":{1:"stop_signo", 2:"stop_key_val_text" } },
917 ], True)
918
919 def parse_interrupt_packets(self, context):
920 self.assertIsNotNone(context.get("stop_signo"))
921 self.assertIsNotNone(context.get("stop_key_val_text"))
Todd Fiala9846d452014-06-20 17:39:24 +0000922 return (int(context["stop_signo"], 16), self.parse_key_val_dict(context["stop_key_val_text"]))
923
924 def add_QSaveRegisterState_packets(self, thread_id):
925 if thread_id:
926 # Use the thread suffix form.
927 request = "read packet: $QSaveRegisterState;thread:{:x}#00".format(thread_id)
928 else:
929 request = "read packet: $QSaveRegisterState#00"
930
931 self.test_sequence.add_log_lines([
932 request,
933 {"direction":"send", "regex":r"^\$(E?.*)#[0-9a-fA-F]{2}$", "capture":{1:"save_response" } },
934 ], True)
935
936 def parse_QSaveRegisterState_response(self, context):
937 self.assertIsNotNone(context)
938
939 save_response = context.get("save_response")
940 self.assertIsNotNone(save_response)
941
942 if len(save_response) < 1 or save_response[0] == "E":
943 # error received
944 return (False, None)
945 else:
946 return (True, int(save_response))
947
948 def add_QRestoreRegisterState_packets(self, save_id, thread_id=None):
949 if thread_id:
950 # Use the thread suffix form.
951 request = "read packet: $QRestoreRegisterState:{};thread:{:x}#00".format(save_id, thread_id)
952 else:
953 request = "read packet: $QRestoreRegisterState:{}#00".format(save_id)
954
955 self.test_sequence.add_log_lines([
956 request,
957 "send packet: $OK#00"
958 ], True)
959
960 def flip_all_bits_in_each_register_value(self, reg_infos, endian, thread_id=None):
961 self.assertIsNotNone(reg_infos)
962
963 successful_writes = 0
964 failed_writes = 0
965
966 for reg_info in reg_infos:
967 # Use the lldb register index added to the reg info. We're not necessarily
968 # working off a full set of register infos, so an inferred register index could be wrong.
969 reg_index = reg_info["lldb_register_index"]
970 self.assertIsNotNone(reg_index)
971
972 reg_byte_size = int(reg_info["bitsize"])/8
973 self.assertTrue(reg_byte_size > 0)
974
975 # Handle thread suffix.
976 if thread_id:
977 p_request = "read packet: $p{:x};thread:{:x}#00".format(reg_index, thread_id)
978 else:
979 p_request = "read packet: $p{:x}#00".format(reg_index)
980
981 # Read the existing value.
982 self.reset_test_sequence()
983 self.test_sequence.add_log_lines([
984 p_request,
985 { "direction":"send", "regex":r"^\$([0-9a-fA-F]+)#", "capture":{1:"p_response"} },
986 ], True)
987 context = self.expect_gdbremote_sequence()
988 self.assertIsNotNone(context)
989
990 # Verify the response length.
991 p_response = context.get("p_response")
992 self.assertIsNotNone(p_response)
993 initial_reg_value = unpack_register_hex_unsigned(endian, p_response)
994
995 # Flip the value by xoring with all 1s
996 all_one_bits_raw = "ff" * (int(reg_info["bitsize"]) / 8)
997 flipped_bits_int = initial_reg_value ^ int(all_one_bits_raw, 16)
998 # print "reg (index={}, name={}): val={}, flipped bits (int={}, hex={:x})".format(reg_index, reg_info["name"], initial_reg_value, flipped_bits_int, flipped_bits_int)
999
1000 # Handle thread suffix for P.
1001 if thread_id:
1002 P_request = "read packet: $P{:x}={};thread:{:x}#00".format(reg_index, pack_register_hex(endian, flipped_bits_int, byte_size=reg_byte_size), thread_id)
1003 else:
1004 P_request = "read packet: $P{:x}={}#00".format(reg_index, pack_register_hex(endian, flipped_bits_int, byte_size=reg_byte_size))
1005
1006 # Write the flipped value to the register.
1007 self.reset_test_sequence()
1008 self.test_sequence.add_log_lines([
1009 P_request,
1010 { "direction":"send", "regex":r"^\$(OK|E[0-9a-fA-F]+)#[0-9a-fA-F]{2}", "capture":{1:"P_response"} },
1011 ], True)
1012 context = self.expect_gdbremote_sequence()
1013 self.assertIsNotNone(context)
1014
1015 # Determine if the write succeeded. There are a handful of registers that can fail, or partially fail
1016 # (e.g. flags, segment selectors, etc.) due to register value restrictions. Don't worry about them
1017 # all flipping perfectly.
1018 P_response = context.get("P_response")
1019 self.assertIsNotNone(P_response)
1020 if P_response == "OK":
1021 successful_writes += 1
1022 else:
1023 failed_writes += 1
1024 # print "reg (index={}, name={}) write FAILED (error: {})".format(reg_index, reg_info["name"], P_response)
1025
1026 # Read back the register value, ensure it matches the flipped value.
1027 if P_response == "OK":
1028 self.reset_test_sequence()
1029 self.test_sequence.add_log_lines([
1030 p_request,
1031 { "direction":"send", "regex":r"^\$([0-9a-fA-F]+)#", "capture":{1:"p_response"} },
1032 ], True)
1033 context = self.expect_gdbremote_sequence()
1034 self.assertIsNotNone(context)
1035
1036 verify_p_response_raw = context.get("p_response")
1037 self.assertIsNotNone(verify_p_response_raw)
1038 verify_bits = unpack_register_hex_unsigned(endian, verify_p_response_raw)
1039
1040 if verify_bits != flipped_bits_int:
1041 # Some registers, like mxcsrmask and others, will permute what's written. Adjust succeed/fail counts.
1042 # print "reg (index={}, name={}): read verify FAILED: wrote {:x}, verify read back {:x}".format(reg_index, reg_info["name"], flipped_bits_int, verify_bits)
1043 successful_writes -= 1
1044 failed_writes +=1
1045
1046 return (successful_writes, failed_writes)
1047
1048 def is_bit_flippable_register(self, reg_info):
1049 if not reg_info:
1050 return False
1051 if not "set" in reg_info:
1052 return False
1053 if reg_info["set"] != "General Purpose Registers":
1054 return False
1055 if ("container-regs" in reg_info) and (len(reg_info["container-regs"]) > 0):
1056 # Don't try to bit flip registers contained in another register.
1057 return False
1058 if re.match("^.s$", reg_info["name"]):
1059 # This is a 2-letter register name that ends in "s", like a segment register.
1060 # Don't try to bit flip these.
1061 return False
1062 # Okay, this looks fine-enough.
1063 return True
1064
1065 def read_register_values(self, reg_infos, endian, thread_id=None):
1066 self.assertIsNotNone(reg_infos)
1067 values = {}
1068
1069 for reg_info in reg_infos:
1070 # We append a register index when load reg infos so we can work with subsets.
1071 reg_index = reg_info.get("lldb_register_index")
1072 self.assertIsNotNone(reg_index)
1073
1074 # Handle thread suffix.
1075 if thread_id:
1076 p_request = "read packet: $p{:x};thread:{:x}#00".format(reg_index, thread_id)
1077 else:
1078 p_request = "read packet: $p{:x}#00".format(reg_index)
1079
1080 # Read it with p.
1081 self.reset_test_sequence()
1082 self.test_sequence.add_log_lines([
1083 p_request,
1084 { "direction":"send", "regex":r"^\$([0-9a-fA-F]+)#", "capture":{1:"p_response"} },
1085 ], True)
1086 context = self.expect_gdbremote_sequence()
1087 self.assertIsNotNone(context)
1088
1089 # Convert value from target endian to integral.
1090 p_response = context.get("p_response")
1091 self.assertIsNotNone(p_response)
1092 self.assertTrue(len(p_response) > 0)
1093 self.assertFalse(p_response[0] == "E")
1094
1095 values[reg_index] = unpack_register_hex_unsigned(endian, p_response)
1096
Todd Fialae2202002014-06-27 22:11:56 +00001097 return values
1098
1099 def add_vCont_query_packets(self):
1100 self.test_sequence.add_log_lines([
Stephane Sezer22ed42e2014-11-13 21:39:24 +00001101 "read packet: $vCont?#49",
Todd Fialae2202002014-06-27 22:11:56 +00001102 {"direction":"send", "regex":r"^\$(vCont)?(.*)#[0-9a-fA-F]{2}$", "capture":{2:"vCont_query_response" } },
1103 ], True)
1104
1105 def parse_vCont_query_response(self, context):
1106 self.assertIsNotNone(context)
1107 vCont_query_response = context.get("vCont_query_response")
1108
1109 # Handle case of no vCont support at all - in which case the capture group will be none or zero length.
1110 if not vCont_query_response or len(vCont_query_response) == 0:
1111 return {}
1112
1113 return {key:1 for key in vCont_query_response.split(";") if key and len(key) > 0}
1114
1115 def count_single_steps_until_true(self, thread_id, predicate, args, max_step_count=100, use_Hc_packet=True, step_instruction="s"):
1116 """Used by single step test that appears in a few different contexts."""
1117 single_step_count = 0
1118
1119 while single_step_count < max_step_count:
1120 self.assertIsNotNone(thread_id)
1121
1122 # Build the packet for the single step instruction. We replace {thread}, if present, with the thread_id.
1123 step_packet = "read packet: ${}#00".format(re.sub(r"{thread}", "{:x}".format(thread_id), step_instruction))
1124 # print "\nstep_packet created: {}\n".format(step_packet)
1125
1126 # Single step.
1127 self.reset_test_sequence()
1128 if use_Hc_packet:
1129 self.test_sequence.add_log_lines(
1130 [# Set the continue thread.
1131 "read packet: $Hc{0:x}#00".format(thread_id),
1132 "send packet: $OK#00",
1133 ], True)
1134 self.test_sequence.add_log_lines([
1135 # Single step.
1136 step_packet,
1137 # "read packet: $vCont;s:{0:x}#00".format(thread_id),
1138 # Expect a breakpoint stop report.
1139 {"direction":"send", "regex":r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);", "capture":{1:"stop_signo", 2:"stop_thread_id"} },
1140 ], True)
1141 context = self.expect_gdbremote_sequence()
1142 self.assertIsNotNone(context)
1143 self.assertIsNotNone(context.get("stop_signo"))
1144 self.assertEquals(int(context.get("stop_signo"), 16), signal.SIGTRAP)
1145
1146 single_step_count += 1
1147
1148 # See if the predicate is true. If so, we're done.
1149 if predicate(args):
1150 return (True, single_step_count)
1151
1152 # The predicate didn't return true within the runaway step count.
1153 return (False, single_step_count)
1154
1155 def g_c1_c2_contents_are(self, args):
1156 """Used by single step test that appears in a few different contexts."""
1157 g_c1_address = args["g_c1_address"]
1158 g_c2_address = args["g_c2_address"]
1159 expected_g_c1 = args["expected_g_c1"]
1160 expected_g_c2 = args["expected_g_c2"]
1161
1162 # Read g_c1 and g_c2 contents.
1163 self.reset_test_sequence()
1164 self.test_sequence.add_log_lines(
1165 ["read packet: $m{0:x},{1:x}#00".format(g_c1_address, 1),
1166 {"direction":"send", "regex":r"^\$(.+)#[0-9a-fA-F]{2}$", "capture":{1:"g_c1_contents"} },
1167 "read packet: $m{0:x},{1:x}#00".format(g_c2_address, 1),
1168 {"direction":"send", "regex":r"^\$(.+)#[0-9a-fA-F]{2}$", "capture":{1:"g_c2_contents"} }],
1169 True)
1170
1171 # Run the packet stream.
1172 context = self.expect_gdbremote_sequence()
1173 self.assertIsNotNone(context)
1174
1175 # Check if what we read from inferior memory is what we are expecting.
1176 self.assertIsNotNone(context.get("g_c1_contents"))
1177 self.assertIsNotNone(context.get("g_c2_contents"))
1178
1179 return (context.get("g_c1_contents").decode("hex") == expected_g_c1) and (context.get("g_c2_contents").decode("hex") == expected_g_c2)
1180
1181 def single_step_only_steps_one_instruction(self, use_Hc_packet=True, step_instruction="s"):
1182 """Used by single step test that appears in a few different contexts."""
1183 # Start up the inferior.
1184 procs = self.prep_debug_monitor_and_inferior(
1185 inferior_args=["get-code-address-hex:swap_chars", "get-data-address-hex:g_c1", "get-data-address-hex:g_c2", "sleep:1", "call-function:swap_chars", "sleep:5"])
1186
1187 # Run the process
1188 self.test_sequence.add_log_lines(
1189 [# Start running after initial stop.
Stephane Sezer22ed42e2014-11-13 21:39:24 +00001190 "read packet: $c#63",
Todd Fialae2202002014-06-27 22:11:56 +00001191 # Match output line that prints the memory address of the function call entry point.
1192 # Note we require launch-only testing so we can get inferior otuput.
1193 { "type":"output_match", "regex":r"^code address: 0x([0-9a-fA-F]+)\r\ndata address: 0x([0-9a-fA-F]+)\r\ndata address: 0x([0-9a-fA-F]+)\r\n$",
1194 "capture":{ 1:"function_address", 2:"g_c1_address", 3:"g_c2_address"} },
1195 # Now stop the inferior.
1196 "read packet: {}".format(chr(03)),
1197 # And wait for the stop notification.
1198 {"direction":"send", "regex":r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);", "capture":{1:"stop_signo", 2:"stop_thread_id"} }],
1199 True)
1200
1201 # Run the packet stream.
1202 context = self.expect_gdbremote_sequence()
1203 self.assertIsNotNone(context)
1204
1205 # Grab the main thread id.
1206 self.assertIsNotNone(context.get("stop_thread_id"))
1207 main_thread_id = int(context.get("stop_thread_id"), 16)
1208
1209 # Grab the function address.
1210 self.assertIsNotNone(context.get("function_address"))
1211 function_address = int(context.get("function_address"), 16)
1212
1213 # Grab the data addresses.
1214 self.assertIsNotNone(context.get("g_c1_address"))
1215 g_c1_address = int(context.get("g_c1_address"), 16)
1216
1217 self.assertIsNotNone(context.get("g_c2_address"))
1218 g_c2_address = int(context.get("g_c2_address"), 16)
1219
1220 # Set a breakpoint at the given address.
Tamas Berghammer157e84f2015-05-28 10:55:01 +00001221 if self.getArchitecture() == "arm":
1222 # TODO: Handle case when setting breakpoint in thumb code
1223 BREAKPOINT_KIND = 4
1224 else:
1225 BREAKPOINT_KIND = 1
Todd Fialae2202002014-06-27 22:11:56 +00001226 self.reset_test_sequence()
1227 self.add_set_breakpoint_packets(function_address, do_continue=True, breakpoint_kind=BREAKPOINT_KIND)
1228 context = self.expect_gdbremote_sequence()
1229 self.assertIsNotNone(context)
1230
1231 # Remove the breakpoint.
1232 self.reset_test_sequence()
1233 self.add_remove_breakpoint_packets(function_address, breakpoint_kind=BREAKPOINT_KIND)
1234 context = self.expect_gdbremote_sequence()
1235 self.assertIsNotNone(context)
1236
1237 # Verify g_c1 and g_c2 match expected initial state.
1238 args = {}
1239 args["g_c1_address"] = g_c1_address
1240 args["g_c2_address"] = g_c2_address
1241 args["expected_g_c1"] = "0"
1242 args["expected_g_c2"] = "1"
1243
1244 self.assertTrue(self.g_c1_c2_contents_are(args))
1245
1246 # Verify we take only a small number of steps to hit the first state. Might need to work through function entry prologue code.
1247 args["expected_g_c1"] = "1"
1248 args["expected_g_c2"] = "1"
1249 (state_reached, step_count) = self.count_single_steps_until_true(main_thread_id, self.g_c1_c2_contents_are, args, max_step_count=25, use_Hc_packet=use_Hc_packet, step_instruction=step_instruction)
1250 self.assertTrue(state_reached)
1251
1252 # Verify we hit the next state.
1253 args["expected_g_c1"] = "1"
1254 args["expected_g_c2"] = "0"
1255 (state_reached, step_count) = self.count_single_steps_until_true(main_thread_id, self.g_c1_c2_contents_are, args, max_step_count=5, use_Hc_packet=use_Hc_packet, step_instruction=step_instruction)
1256 self.assertTrue(state_reached)
1257 self.assertEquals(step_count, 1)
1258
1259 # Verify we hit the next state.
1260 args["expected_g_c1"] = "0"
1261 args["expected_g_c2"] = "0"
1262 (state_reached, step_count) = self.count_single_steps_until_true(main_thread_id, self.g_c1_c2_contents_are, args, max_step_count=5, use_Hc_packet=use_Hc_packet, step_instruction=step_instruction)
1263 self.assertTrue(state_reached)
1264 self.assertEquals(step_count, 1)
1265
1266 # Verify we hit the next state.
1267 args["expected_g_c1"] = "0"
1268 args["expected_g_c2"] = "1"
1269 (state_reached, step_count) = self.count_single_steps_until_true(main_thread_id, self.g_c1_c2_contents_are, args, max_step_count=5, use_Hc_packet=use_Hc_packet, step_instruction=step_instruction)
1270 self.assertTrue(state_reached)
1271 self.assertEquals(step_count, 1)
Todd Fialaaf245d12014-06-30 21:05:18 +00001272