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