blob: 159a5172cf9e8b075f39a0331dd12ea8dda74804 [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:
Siva Chandrade4c5982015-05-29 00:14:16 +0000145 def run_shell_cmd(cmd):
146 platform = self.dbg.GetSelectedPlatform()
147 shell_cmd = lldb.SBPlatformShellCommand(cmd)
148 err = platform.Run(shell_cmd)
149 if err.Fail() or shell_cmd.GetStatus():
150 m = "remote_platform.RunShellCommand('%s') failed:\n" % cmd
151 m += ">>> return code: %d\n" % shell_cmd.GetStatus()
152 if err.Fail():
153 m += ">>> %s\n" % str(err).strip()
154 m += ">>> %s\n" % (shell_cmd.GetOutput() or
155 "Command generated no output.")
156 raise Exception(m)
157 return shell_cmd.GetOutput().strip()
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000158 # Remote platforms don't support named pipe based port negotiation
159 use_named_pipe = False
160
Chaoren Linbfa848c2015-07-06 18:56:04 +0000161 # Grab the ppid from /proc/[shell pid]/stat
162 shell_stat = run_shell_cmd("cat /proc/$$/stat")
163 # [pid] ([executable]) [state] [*ppid*]
164 pid = re.match(r"^\d+ \(.+\) . (\d+)", shell_stat).group(1)
Siva Chandrade4c5982015-05-29 00:14:16 +0000165 ls_output = run_shell_cmd("ls -l /proc/%s/exe" % pid)
166 exe = ls_output.split()[-1]
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000167
Ying Chencd819142015-05-08 01:47:17 +0000168 # If the binary has been deleted, the link name has " (deleted)" appended.
169 # Remove if it's there.
Siva Chandrade4c5982015-05-29 00:14:16 +0000170 self.debug_monitor_exe = re.sub(r' \(deleted\)$', '', exe)
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000171 else:
172 self.debug_monitor_exe = get_lldb_server_exe()
173 if not self.debug_monitor_exe:
174 self.skipTest("lldb-server exe not found")
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000175
Vince Harronf1ff3c12015-05-10 18:02:53 +0000176 self.debug_monitor_extra_args = ["gdbserver"]
Vince Harron1f160372015-05-21 18:51:20 +0000177
178 if len(lldbtest_config.channels) > 0:
179 self.debug_monitor_extra_args.append("--log-file={}-server.log".format(self.log_basename))
180 self.debug_monitor_extra_args.append("--log-channels={}".format(":".join(lldbtest_config.channels)))
181
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 Fialae50b2e42014-06-13 19:11:33 +0000184
Todd Fiala24189d42014-07-14 06:24:44 +0000185 def init_debugserver_test(self, use_named_pipe=True):
Todd Fialae50b2e42014-06-13 19:11:33 +0000186 self.debug_monitor_exe = get_debugserver_exe()
187 if not self.debug_monitor_exe:
188 self.skipTest("debugserver exe not found")
Vince Harron1f160372015-05-21 18:51:20 +0000189 self.debug_monitor_extra_args = ["--log-file={}-server.log".format(self.log_basename), "--log-flags=0x800000"]
Todd Fiala24189d42014-07-14 06:24:44 +0000190 if use_named_pipe:
191 (self.named_pipe_path, self.named_pipe, self.named_pipe_fd) = self.create_named_pipe()
Todd Fialaf9ad21d2014-07-16 16:15:42 +0000192 # The debugserver stub has a race on handling the 'k' command, so it sends an X09 right away, then sends the real X notification
193 # when the process truly dies.
194 self.stub_sends_two_stop_notifications_on_kill = True
Todd Fialae50b2e42014-06-13 19:11:33 +0000195
Chaoren Lin28b8ea12015-05-07 01:42:53 +0000196 def forward_adb_port(self, source, target, direction, device):
197 adb = [ 'adb' ] + ([ '-s', device ] if device else []) + [ direction ]
Tamas Berghammer27c8d362015-03-13 14:32:25 +0000198 def remove_port_forward():
Chaoren Lin28b8ea12015-05-07 01:42:53 +0000199 subprocess.call(adb + [ "--remove", "tcp:%d" % source])
200
201 subprocess.call(adb + [ "tcp:%d" % source, "tcp:%d" % target])
Tamas Berghammer27c8d362015-03-13 14:32:25 +0000202 self.addTearDownHook(remove_port_forward)
203
Todd Fialae50b2e42014-06-13 19:11:33 +0000204 def create_socket(self):
205 sock = socket.socket()
206 logger = self.logger
207
Tamas Berghammerde786792015-03-30 10:52:32 +0000208 triple = self.dbg.GetSelectedPlatform().GetTriple()
209 if re.match(".*-.*-.*-android", triple):
Chaoren Lin28b8ea12015-05-07 01:42:53 +0000210 self.forward_adb_port(self.port, self.port, "forward", self.stub_device)
Tamas Berghammerde786792015-03-30 10:52:32 +0000211
212 connect_info = (self.stub_hostname, self.port)
213 sock.connect(connect_info)
214
Todd Fialae50b2e42014-06-13 19:11:33 +0000215 def shutdown_socket():
216 if sock:
217 try:
Robert Flack8cc4cf12015-03-06 14:36:33 +0000218 # send the kill packet so lldb-server shuts down gracefully
Todd Fialae50b2e42014-06-13 19:11:33 +0000219 sock.sendall(GdbRemoteTestCaseBase._GDBREMOTE_KILL_PACKET)
220 except:
221 logger.warning("failed to send kill packet to debug monitor: {}; ignoring".format(sys.exc_info()[0]))
222
223 try:
224 sock.close()
225 except:
226 logger.warning("failed to close socket to debug monitor: {}; ignoring".format(sys.exc_info()[0]))
227
228 self.addTearDownHook(shutdown_socket)
229
Todd Fialae50b2e42014-06-13 19:11:33 +0000230 return sock
231
232 def set_inferior_startup_launch(self):
233 self._inferior_startup = self._STARTUP_LAUNCH
234
235 def set_inferior_startup_attach(self):
236 self._inferior_startup = self._STARTUP_ATTACH
237
Todd Fiala7306cf32014-07-29 22:30:01 +0000238 def set_inferior_startup_attach_manually(self):
239 self._inferior_startup = self._STARTUP_ATTACH_MANUALLY
240
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000241 def get_debug_monitor_command_line_args(self, attach_pid=None):
Tamas Berghammerde786792015-03-30 10:52:32 +0000242 if lldb.remote_platform:
243 commandline_args = self.debug_monitor_extra_args + ["*:{}".format(self.port)]
244 else:
245 commandline_args = self.debug_monitor_extra_args + ["localhost:{}".format(self.port)]
246
Todd Fialae50b2e42014-06-13 19:11:33 +0000247 if attach_pid:
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000248 commandline_args += ["--attach=%d" % attach_pid]
Todd Fiala67041192014-07-11 22:50:13 +0000249 if self.named_pipe_path:
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000250 commandline_args += ["--named-pipe", self.named_pipe_path]
251 return commandline_args
252
253 def run_platform_command(self, cmd):
254 platform = self.dbg.GetSelectedPlatform()
255 shell_command = lldb.SBPlatformShellCommand(cmd)
256 err = platform.Run(shell_command)
257 return (err, shell_command.GetOutput())
Todd Fiala31bde322014-07-26 20:39:17 +0000258
259 def launch_debug_monitor(self, attach_pid=None, logfile=None):
260 # Create the command line.
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000261 commandline_args = self.get_debug_monitor_command_line_args(attach_pid=attach_pid)
Todd Fialae50b2e42014-06-13 19:11:33 +0000262
Todd Fiala8aae4f42014-06-13 23:34:17 +0000263 # Start the server.
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000264 server = self.spawnSubprocess(self.debug_monitor_exe, commandline_args, install_remote=False)
265 self.addTearDownHook(self.cleanupSubprocesses)
Todd Fiala24189d42014-07-14 06:24:44 +0000266 self.assertIsNotNone(server)
Todd Fiala24189d42014-07-14 06:24:44 +0000267
268 # If we're receiving the stub's listening port from the named pipe, do that here.
269 if self.named_pipe:
270 self.port = self.get_stub_port_from_named_socket()
Todd Fialae50b2e42014-06-13 19:11:33 +0000271
Todd Fiala8aae4f42014-06-13 23:34:17 +0000272 return server
273
274 def connect_to_debug_monitor(self, attach_pid=None):
Todd Fiala24189d42014-07-14 06:24:44 +0000275 if self.named_pipe:
276 # Create the stub.
277 server = self.launch_debug_monitor(attach_pid=attach_pid)
278 self.assertIsNotNone(server)
279
280 def shutdown_debug_monitor():
281 try:
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000282 server.terminate()
Todd Fiala24189d42014-07-14 06:24:44 +0000283 except:
Ilia K7c1d91d2015-04-15 13:08:35 +0000284 logger.warning("failed to terminate server for debug monitor: {}; ignoring".format(sys.exc_info()[0]))
Todd Fiala24189d42014-07-14 06:24:44 +0000285 self.addTearDownHook(shutdown_debug_monitor)
286
287 # Schedule debug monitor to be shut down during teardown.
288 logger = self.logger
289
290 # Attach to the stub and return a socket opened to it.
291 self.sock = self.create_socket()
292 return server
293
294 # We're using a random port algorithm to try not to collide with other ports,
295 # and retry a max # times.
Todd Fiala8aae4f42014-06-13 23:34:17 +0000296 attempts = 0
297 MAX_ATTEMPTS = 20
Todd Fialae50b2e42014-06-13 19:11:33 +0000298
Todd Fiala8aae4f42014-06-13 23:34:17 +0000299 while attempts < MAX_ATTEMPTS:
Todd Fiala9e2d3292014-07-09 23:10:43 +0000300 server = self.launch_debug_monitor(attach_pid=attach_pid)
301
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000302 # Schedule debug monitor to be shut down during teardown.
303 logger = self.logger
304 def shutdown_debug_monitor():
Todd Fiala9e2d3292014-07-09 23:10:43 +0000305 try:
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000306 server.terminate()
307 except:
308 logger.warning("failed to terminate server for debug monitor: {}; ignoring".format(sys.exc_info()[0]))
309 self.addTearDownHook(shutdown_debug_monitor)
310
Tamas Berghammerde786792015-03-30 10:52:32 +0000311 connect_attemps = 0
312 MAX_CONNECT_ATTEMPTS = 10
313
314 while connect_attemps < MAX_CONNECT_ATTEMPTS:
315 # Create a socket to talk to the server
316 try:
317 self.sock = self.create_socket()
318 return server
319 except socket.error as serr:
320 # We're only trying to handle connection refused.
321 if serr.errno != errno.ECONNREFUSED:
322 raise serr
323 time.sleep(0.5)
324 connect_attemps += 1
325
326 # We should close the server here to be safe.
327 server.terminate()
Todd Fiala9e2d3292014-07-09 23:10:43 +0000328
329 # Increment attempts.
330 print("connect to debug monitor on port %d failed, attempt #%d of %d" % (self.port, attempts + 1, MAX_ATTEMPTS))
331 attempts += 1
332
333 # And wait a random length of time before next attempt, to avoid collisions.
334 time.sleep(random.randint(1,5))
335
336 # Now grab a new port number.
337 self.port = self.get_next_port()
Todd Fiala8aae4f42014-06-13 23:34:17 +0000338
339 raise Exception("failed to create a socket to the launched debug monitor after %d tries" % attempts)
Todd Fialae50b2e42014-06-13 19:11:33 +0000340
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000341 def launch_process_for_attach(self, inferior_args=None, sleep_seconds=3, exe_path=None):
Todd Fialae50b2e42014-06-13 19:11:33 +0000342 # We're going to start a child process that the debug monitor stub can later attach to.
343 # This process needs to be started so that it just hangs around for a while. We'll
344 # have it sleep.
Todd Fiala58a2f662014-08-12 17:02:07 +0000345 if not exe_path:
346 exe_path = os.path.abspath("a.out")
Todd Fialae50b2e42014-06-13 19:11:33 +0000347
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000348 args = []
Todd Fialae50b2e42014-06-13 19:11:33 +0000349 if inferior_args:
350 args.extend(inferior_args)
351 if sleep_seconds:
352 args.append("sleep:%d" % sleep_seconds)
353
Ilia K7c1d91d2015-04-15 13:08:35 +0000354 inferior = self.spawnSubprocess(exe_path, args)
355 def shutdown_process_for_attach():
356 try:
357 inferior.terminate()
358 except:
359 logger.warning("failed to terminate inferior process for attach: {}; ignoring".format(sys.exc_info()[0]))
360 self.addTearDownHook(shutdown_process_for_attach)
361 return inferior
Todd Fialae50b2e42014-06-13 19:11:33 +0000362
Todd Fiala58a2f662014-08-12 17:02:07 +0000363 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 +0000364 """Prep the debug monitor, the inferior, and the expected packet stream.
365
366 Handle the separate cases of using the debug monitor in attach-to-inferior mode
367 and in launch-inferior mode.
368
369 For attach-to-inferior mode, the inferior process is first started, then
370 the debug monitor is started in attach to pid mode (using --attach on the
371 stub command line), and the no-ack-mode setup is appended to the packet
372 stream. The packet stream is not yet executed, ready to have more expected
373 packet entries added to it.
374
375 For launch-inferior mode, the stub is first started, then no ack mode is
376 setup on the expected packet stream, then the verified launch packets are added
377 to the expected socket stream. The packet stream is not yet executed, ready
378 to have more expected packet entries added to it.
379
380 The return value is:
381 {inferior:<inferior>, server:<server>}
382 """
383 inferior = None
384 attach_pid = None
385
Todd Fiala7306cf32014-07-29 22:30:01 +0000386 if self._inferior_startup == self._STARTUP_ATTACH or self._inferior_startup == self._STARTUP_ATTACH_MANUALLY:
Todd Fialae50b2e42014-06-13 19:11:33 +0000387 # Launch the process that we'll use as the inferior.
Todd Fiala58a2f662014-08-12 17:02:07 +0000388 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 +0000389 self.assertIsNotNone(inferior)
390 self.assertTrue(inferior.pid > 0)
Todd Fiala7306cf32014-07-29 22:30:01 +0000391 if self._inferior_startup == self._STARTUP_ATTACH:
392 # In this case, we want the stub to attach via the command line, so set the command line attach pid here.
393 attach_pid = inferior.pid
Todd Fialae50b2e42014-06-13 19:11:33 +0000394
Todd Fialae50b2e42014-06-13 19:11:33 +0000395 if self._inferior_startup == self._STARTUP_LAUNCH:
396 # Build launch args
Todd Fiala58a2f662014-08-12 17:02:07 +0000397 if not inferior_exe_path:
398 inferior_exe_path = os.path.abspath("a.out")
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000399
400 if lldb.remote_platform:
Chaoren Lin5d76b1b2015-06-06 00:25:50 +0000401 remote_path = lldbutil.append_to_process_working_directory(os.path.basename(inferior_exe_path))
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000402 remote_file_spec = lldb.SBFileSpec(remote_path, False)
403 err = lldb.remote_platform.Install(lldb.SBFileSpec(inferior_exe_path, True), remote_file_spec)
404 if err.Fail():
405 raise Exception("remote_platform.Install('%s', '%s') failed: %s" % (inferior_exe_path, remote_path, err))
406 inferior_exe_path = remote_path
407
Todd Fiala58a2f662014-08-12 17:02:07 +0000408 launch_args = [inferior_exe_path]
Todd Fialae50b2e42014-06-13 19:11:33 +0000409 if inferior_args:
410 launch_args.extend(inferior_args)
411
Tamas Berghammer04f51d12015-03-11 13:51:07 +0000412 # Launch the debug monitor stub, attaching to the inferior.
413 server = self.connect_to_debug_monitor(attach_pid=attach_pid)
414 self.assertIsNotNone(server)
415
Todd Fialae50b2e42014-06-13 19:11:33 +0000416 # Build the expected protocol stream
417 self.add_no_ack_remote_stream()
418 if self._inferior_startup == self._STARTUP_LAUNCH:
419 self.add_verified_launch_packets(launch_args)
420
421 return {"inferior":inferior, "server":server}
422
Todd Fiala31bde322014-07-26 20:39:17 +0000423 def expect_socket_recv(self, sock, expected_content_regex, timeout_seconds):
424 response = ""
425 timeout_time = time.time() + timeout_seconds
426
427 while not expected_content_regex.match(response) and time.time() < timeout_time:
428 can_read, _, _ = select.select([sock], [], [], timeout_seconds)
429 if can_read and sock in can_read:
430 recv_bytes = sock.recv(4096)
431 if recv_bytes:
432 response += recv_bytes
433
434 self.assertTrue(expected_content_regex.match(response))
435
436 def expect_socket_send(self, sock, content, timeout_seconds):
437 request_bytes_remaining = content
438 timeout_time = time.time() + timeout_seconds
439
440 while len(request_bytes_remaining) > 0 and time.time() < timeout_time:
441 _, can_write, _ = select.select([], [sock], [], timeout_seconds)
442 if can_write and sock in can_write:
443 written_byte_count = sock.send(request_bytes_remaining)
444 request_bytes_remaining = request_bytes_remaining[written_byte_count:]
445 self.assertEquals(len(request_bytes_remaining), 0)
446
447 def do_handshake(self, stub_socket, timeout_seconds=5):
448 # Write the ack.
449 self.expect_socket_send(stub_socket, "+", timeout_seconds)
450
451 # Send the start no ack mode packet.
452 NO_ACK_MODE_REQUEST = "$QStartNoAckMode#b0"
453 bytes_sent = stub_socket.send(NO_ACK_MODE_REQUEST)
454 self.assertEquals(bytes_sent, len(NO_ACK_MODE_REQUEST))
455
456 # Receive the ack and "OK"
457 self.expect_socket_recv(stub_socket, re.compile(r"^\+\$OK#[0-9a-fA-F]{2}$"), timeout_seconds)
458
459 # Send the final ack.
460 self.expect_socket_send(stub_socket, "+", timeout_seconds)
461
Todd Fialae50b2e42014-06-13 19:11:33 +0000462 def add_no_ack_remote_stream(self):
463 self.test_sequence.add_log_lines(
464 ["read packet: +",
465 "read packet: $QStartNoAckMode#b0",
466 "send packet: +",
467 "send packet: $OK#9a",
468 "read packet: +"],
469 True)
470
471 def add_verified_launch_packets(self, launch_args):
472 self.test_sequence.add_log_lines(
473 ["read packet: %s" % build_gdbremote_A_packet(launch_args),
474 "send packet: $OK#00",
475 "read packet: $qLaunchSuccess#a5",
476 "send packet: $OK#00"],
477 True)
478
479 def add_thread_suffix_request_packets(self):
480 self.test_sequence.add_log_lines(
Stephane Sezer22ed42e2014-11-13 21:39:24 +0000481 ["read packet: $QThreadSuffixSupported#e4",
Todd Fialae50b2e42014-06-13 19:11:33 +0000482 "send packet: $OK#00",
483 ], True)
484
485 def add_process_info_collection_packets(self):
486 self.test_sequence.add_log_lines(
Stephane Sezer22ed42e2014-11-13 21:39:24 +0000487 ["read packet: $qProcessInfo#dc",
Todd Fiala8aae4f42014-06-13 23:34:17 +0000488 { "direction":"send", "regex":r"^\$(.+)#[0-9a-fA-F]{2}$", "capture":{1:"process_info_raw"} }],
Todd Fialae50b2e42014-06-13 19:11:33 +0000489 True)
490
491 _KNOWN_PROCESS_INFO_KEYS = [
492 "pid",
493 "parent-pid",
494 "real-uid",
495 "real-gid",
496 "effective-uid",
497 "effective-gid",
498 "cputype",
499 "cpusubtype",
500 "ostype",
Todd Fialac540dd02014-08-26 18:21:02 +0000501 "triple",
Todd Fialae50b2e42014-06-13 19:11:33 +0000502 "vendor",
503 "endian",
504 "ptrsize"
505 ]
506
507 def parse_process_info_response(self, context):
508 # Ensure we have a process info response.
509 self.assertIsNotNone(context)
510 process_info_raw = context.get("process_info_raw")
511 self.assertIsNotNone(process_info_raw)
512
513 # Pull out key:value; pairs.
514 process_info_dict = { match.group(1):match.group(2) for match in re.finditer(r"([^:]+):([^;]+);", process_info_raw) }
515
516 # Validate keys are known.
517 for (key, val) in process_info_dict.items():
518 self.assertTrue(key in self._KNOWN_PROCESS_INFO_KEYS)
519 self.assertIsNotNone(val)
520
521 return process_info_dict
522
523 def add_register_info_collection_packets(self):
524 self.test_sequence.add_log_lines(
525 [ { "type":"multi_response", "query":"qRegisterInfo", "append_iteration_suffix":True,
526 "end_regex":re.compile(r"^\$(E\d+)?#[0-9a-fA-F]{2}$"),
527 "save_key":"reg_info_responses" } ],
528 True)
529
530 def parse_register_info_packets(self, context):
531 """Return an array of register info dictionaries, one per register info."""
532 reg_info_responses = context.get("reg_info_responses")
533 self.assertIsNotNone(reg_info_responses)
534
535 # Parse register infos.
536 return [parse_reg_info_response(reg_info_response) for reg_info_response in reg_info_responses]
537
Todd Fiala50a211b2014-06-14 22:00:36 +0000538 def expect_gdbremote_sequence(self, timeout_seconds=None):
Todd Fiala8aae4f42014-06-13 23:34:17 +0000539 if not timeout_seconds:
540 timeout_seconds = self._TIMEOUT_SECONDS
541 return expect_lldb_gdbserver_replay(self, self.sock, self.test_sequence, timeout_seconds, self.logger)
Todd Fialae50b2e42014-06-13 19:11:33 +0000542
543 _KNOWN_REGINFO_KEYS = [
544 "name",
545 "alt-name",
546 "bitsize",
547 "offset",
548 "encoding",
549 "format",
550 "set",
Jason Molenda63bd0db2015-09-15 23:20:34 +0000551 "ehframe",
Todd Fialae50b2e42014-06-13 19:11:33 +0000552 "dwarf",
553 "generic",
554 "container-regs",
555 "invalidate-regs"
556 ]
557
558 def assert_valid_reg_info(self, reg_info):
559 # Assert we know about all the reginfo keys parsed.
560 for key in reg_info:
561 self.assertTrue(key in self._KNOWN_REGINFO_KEYS)
562
563 # Check the bare-minimum expected set of register info keys.
564 self.assertTrue("name" in reg_info)
565 self.assertTrue("bitsize" in reg_info)
566 self.assertTrue("offset" in reg_info)
567 self.assertTrue("encoding" in reg_info)
568 self.assertTrue("format" in reg_info)
569
570 def find_pc_reg_info(self, reg_infos):
571 lldb_reg_index = 0
572 for reg_info in reg_infos:
573 if ("generic" in reg_info) and (reg_info["generic"] == "pc"):
574 return (lldb_reg_index, reg_info)
575 lldb_reg_index += 1
576
577 return (None, None)
578
579 def add_lldb_register_index(self, reg_infos):
580 """Add a "lldb_register_index" key containing the 0-baed index of each reg_infos entry.
581
582 We'll use this when we want to call packets like P/p with a register index but do so
583 on only a subset of the full register info set.
584 """
585 self.assertIsNotNone(reg_infos)
586
587 reg_index = 0
588 for reg_info in reg_infos:
589 reg_info["lldb_register_index"] = reg_index
590 reg_index += 1
591
592 def add_query_memory_region_packets(self, address):
593 self.test_sequence.add_log_lines(
594 ["read packet: $qMemoryRegionInfo:{0:x}#00".format(address),
595 {"direction":"send", "regex":r"^\$(.+)#[0-9a-fA-F]{2}$", "capture":{1:"memory_region_response"} }],
596 True)
597
Todd Fialac30281a2014-06-14 03:03:23 +0000598 def parse_key_val_dict(self, key_val_text, allow_dupes=True):
Todd Fialae50b2e42014-06-13 19:11:33 +0000599 self.assertIsNotNone(key_val_text)
600 kv_dict = {}
601 for match in re.finditer(r";?([^:]+):([^;]+)", key_val_text):
Todd Fialac30281a2014-06-14 03:03:23 +0000602 key = match.group(1)
603 val = match.group(2)
604 if key in kv_dict:
605 if allow_dupes:
606 if type(kv_dict[key]) == list:
607 kv_dict[key].append(val)
608 else:
609 # Promote to list
610 kv_dict[key] = [kv_dict[key], val]
611 else:
612 self.fail("key '{}' already present when attempting to add value '{}' (text='{}', dict={})".format(key, val, key_val_text, kv_dict))
613 else:
614 kv_dict[key] = val
Todd Fialae50b2e42014-06-13 19:11:33 +0000615 return kv_dict
616
617 def parse_memory_region_packet(self, context):
618 # Ensure we have a context.
619 self.assertIsNotNone(context.get("memory_region_response"))
620
621 # Pull out key:value; pairs.
622 mem_region_dict = self.parse_key_val_dict(context.get("memory_region_response"))
623
624 # Validate keys are known.
625 for (key, val) in mem_region_dict.items():
626 self.assertTrue(key in ["start", "size", "permissions", "error"])
627 self.assertIsNotNone(val)
628
629 # Return the dictionary of key-value pairs for the memory region.
630 return mem_region_dict
631
632 def assert_address_within_memory_region(self, test_address, mem_region_dict):
633 self.assertIsNotNone(mem_region_dict)
634 self.assertTrue("start" in mem_region_dict)
635 self.assertTrue("size" in mem_region_dict)
636
637 range_start = int(mem_region_dict["start"], 16)
638 range_size = int(mem_region_dict["size"], 16)
639 range_end = range_start + range_size
640
641 if test_address < range_start:
642 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))
643 elif test_address >= range_end:
644 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))
645
646 def add_threadinfo_collection_packets(self):
647 self.test_sequence.add_log_lines(
648 [ { "type":"multi_response", "first_query":"qfThreadInfo", "next_query":"qsThreadInfo",
649 "append_iteration_suffix":False, "end_regex":re.compile(r"^\$(l)?#[0-9a-fA-F]{2}$"),
650 "save_key":"threadinfo_responses" } ],
651 True)
652
653 def parse_threadinfo_packets(self, context):
654 """Return an array of thread ids (decimal ints), one per thread."""
655 threadinfo_responses = context.get("threadinfo_responses")
656 self.assertIsNotNone(threadinfo_responses)
657
658 thread_ids = []
659 for threadinfo_response in threadinfo_responses:
660 new_thread_infos = parse_threadinfo_response(threadinfo_response)
661 thread_ids.extend(new_thread_infos)
662 return thread_ids
663
664 def wait_for_thread_count(self, thread_count, timeout_seconds=3):
665 start_time = time.time()
666 timeout_time = start_time + timeout_seconds
667
668 actual_thread_count = 0
669 while actual_thread_count < thread_count:
670 self.reset_test_sequence()
671 self.add_threadinfo_collection_packets()
672
673 context = self.expect_gdbremote_sequence()
674 self.assertIsNotNone(context)
675
676 threads = self.parse_threadinfo_packets(context)
677 self.assertIsNotNone(threads)
678
679 actual_thread_count = len(threads)
680
681 if time.time() > timeout_time:
682 raise Exception(
683 'timed out after {} seconds while waiting for theads: waiting for at least {} threads, found {}'.format(
684 timeout_seconds, thread_count, actual_thread_count))
685
686 return threads
687
688 def add_set_breakpoint_packets(self, address, do_continue=True, breakpoint_kind=1):
689 self.test_sequence.add_log_lines(
690 [# Set the breakpoint.
691 "read packet: $Z0,{0:x},{1}#00".format(address, breakpoint_kind),
692 # Verify the stub could set it.
693 "send packet: $OK#00",
694 ], True)
695
696 if (do_continue):
697 self.test_sequence.add_log_lines(
698 [# Continue the inferior.
Stephane Sezer22ed42e2014-11-13 21:39:24 +0000699 "read packet: $c#63",
Todd Fialae50b2e42014-06-13 19:11:33 +0000700 # Expect a breakpoint stop report.
701 {"direction":"send", "regex":r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);", "capture":{1:"stop_signo", 2:"stop_thread_id"} },
702 ], True)
703
704 def add_remove_breakpoint_packets(self, address, breakpoint_kind=1):
705 self.test_sequence.add_log_lines(
706 [# Remove the breakpoint.
707 "read packet: $z0,{0:x},{1}#00".format(address, breakpoint_kind),
708 # Verify the stub could unset it.
709 "send packet: $OK#00",
710 ], True)
711
712 def add_qSupported_packets(self):
713 self.test_sequence.add_log_lines(
714 ["read packet: $qSupported#00",
715 {"direction":"send", "regex":r"^\$(.*)#[0-9a-fA-F]{2}", "capture":{1: "qSupported_response"}},
716 ], True)
717
718 _KNOWN_QSUPPORTED_STUB_FEATURES = [
719 "augmented-libraries-svr4-read",
720 "PacketSize",
721 "QStartNoAckMode",
Todd Fiala8aae4f42014-06-13 23:34:17 +0000722 "QThreadSuffixSupported",
Todd Fiala43ab82c2014-06-15 23:33:09 +0000723 "QListThreadsInStopReply",
Todd Fialae50b2e42014-06-13 19:11:33 +0000724 "qXfer:auxv:read",
725 "qXfer:libraries:read",
726 "qXfer:libraries-svr4:read",
Ying Chen294c9262015-05-26 23:08:09 +0000727 "qXfer:features:read",
Greg Claytonb30c50c2015-05-29 00:01:55 +0000728 "qEcho"
Todd Fialae50b2e42014-06-13 19:11:33 +0000729 ]
730
731 def parse_qSupported_response(self, context):
732 self.assertIsNotNone(context)
733
734 raw_response = context.get("qSupported_response")
735 self.assertIsNotNone(raw_response)
736
737 # For values with key=val, the dict key and vals are set as expected. For feature+, feature- and feature?, the
738 # +,-,? is stripped from the key and set as the value.
739 supported_dict = {}
740 for match in re.finditer(r";?([^=;]+)(=([^;]+))?", raw_response):
741 key = match.group(1)
742 val = match.group(3)
743
744 # key=val: store as is
745 if val and len(val) > 0:
746 supported_dict[key] = val
747 else:
748 if len(key) < 2:
749 raise Exception("singular stub feature is too short: must be stub_feature{+,-,?}")
750 supported_type = key[-1]
751 key = key[:-1]
752 if not supported_type in ["+", "-", "?"]:
753 raise Exception("malformed stub feature: final character {} not in expected set (+,-,?)".format(supported_type))
754 supported_dict[key] = supported_type
755 # Ensure we know the supported element
756 if not key in self._KNOWN_QSUPPORTED_STUB_FEATURES:
757 raise Exception("unknown qSupported stub feature reported: %s" % key)
758
759 return supported_dict
760
761 def run_process_then_stop(self, run_seconds=1):
762 # Tell the stub to continue.
763 self.test_sequence.add_log_lines(
Stephane Sezerb6e81922014-11-20 18:50:46 +0000764 ["read packet: $vCont;c#a8"],
Todd Fialae50b2e42014-06-13 19:11:33 +0000765 True)
766 context = self.expect_gdbremote_sequence()
767
768 # Wait for run_seconds.
769 time.sleep(run_seconds)
770
771 # Send an interrupt, capture a T response.
772 self.reset_test_sequence()
773 self.test_sequence.add_log_lines(
774 ["read packet: {}".format(chr(03)),
775 {"direction":"send", "regex":r"^\$T([0-9a-fA-F]+)([^#]+)#[0-9a-fA-F]{2}$", "capture":{1:"stop_result"} }],
776 True)
777 context = self.expect_gdbremote_sequence()
778 self.assertIsNotNone(context)
779 self.assertIsNotNone(context.get("stop_result"))
780
781 return context
782
783 def select_modifiable_register(self, reg_infos):
784 """Find a register that can be read/written freely."""
785 PREFERRED_REGISTER_NAMES = sets.Set(["rax",])
786
787 # First check for the first register from the preferred register name set.
788 alternative_register_index = None
789
790 self.assertIsNotNone(reg_infos)
791 for reg_info in reg_infos:
792 if ("name" in reg_info) and (reg_info["name"] in PREFERRED_REGISTER_NAMES):
793 # We found a preferred register. Use it.
794 return reg_info["lldb_register_index"]
795 if ("generic" in reg_info) and (reg_info["generic"] == "fp"):
796 # A frame pointer register will do as a register to modify temporarily.
797 alternative_register_index = reg_info["lldb_register_index"]
798
799 # We didn't find a preferred register. Return whatever alternative register
800 # we found, if any.
801 return alternative_register_index
802
803 def extract_registers_from_stop_notification(self, stop_key_vals_text):
804 self.assertIsNotNone(stop_key_vals_text)
805 kv_dict = self.parse_key_val_dict(stop_key_vals_text)
806
807 registers = {}
808 for (key, val) in kv_dict.items():
Stephane Sezer5109a792014-11-14 09:46:21 +0000809 if re.match(r"^[0-9a-fA-F]+$", key):
Todd Fialae50b2e42014-06-13 19:11:33 +0000810 registers[int(key, 16)] = val
811 return registers
812
813 def gather_register_infos(self):
814 self.reset_test_sequence()
815 self.add_register_info_collection_packets()
816
817 context = self.expect_gdbremote_sequence()
818 self.assertIsNotNone(context)
819
820 reg_infos = self.parse_register_info_packets(context)
821 self.assertIsNotNone(reg_infos)
822 self.add_lldb_register_index(reg_infos)
823
824 return reg_infos
825
826 def find_generic_register_with_name(self, reg_infos, generic_name):
827 self.assertIsNotNone(reg_infos)
828 for reg_info in reg_infos:
829 if ("generic" in reg_info) and (reg_info["generic"] == generic_name):
830 return reg_info
831 return None
832
Todd Fiala8d7ab8c2014-06-17 16:04:45 +0000833 def decode_gdbremote_binary(self, encoded_bytes):
834 decoded_bytes = ""
835 i = 0
836 while i < len(encoded_bytes):
837 if encoded_bytes[i] == "}":
838 # Handle escaped char.
839 self.assertTrue(i + 1 < len(encoded_bytes))
840 decoded_bytes += chr(ord(encoded_bytes[i+1]) ^ 0x20)
841 i +=2
842 elif encoded_bytes[i] == "*":
843 # Handle run length encoding.
844 self.assertTrue(len(decoded_bytes) > 0)
845 self.assertTrue(i + 1 < len(encoded_bytes))
846 repeat_count = ord(encoded_bytes[i+1]) - 29
847 decoded_bytes += decoded_bytes[-1] * repeat_count
848 i += 2
849 else:
850 decoded_bytes += encoded_bytes[i]
851 i += 1
852 return decoded_bytes
853
854 def build_auxv_dict(self, endian, word_size, auxv_data):
855 self.assertIsNotNone(endian)
856 self.assertIsNotNone(word_size)
857 self.assertIsNotNone(auxv_data)
858
859 auxv_dict = {}
860
861 while len(auxv_data) > 0:
862 # Chop off key.
863 raw_key = auxv_data[:word_size]
864 auxv_data = auxv_data[word_size:]
865
866 # Chop of value.
867 raw_value = auxv_data[:word_size]
868 auxv_data = auxv_data[word_size:]
869
870 # Convert raw text from target endian.
871 key = unpack_endian_binary_string(endian, raw_key)
872 value = unpack_endian_binary_string(endian, raw_value)
873
874 # Handle ending entry.
875 if key == 0:
876 self.assertEquals(value, 0)
877 return auxv_dict
878
879 # The key should not already be present.
880 self.assertFalse(key in auxv_dict)
881 auxv_dict[key] = value
882
883 self.fail("should not reach here - implies required double zero entry not found")
884 return auxv_dict
Todd Fiala51886732014-06-17 22:01:27 +0000885
886 def read_binary_data_in_chunks(self, command_prefix, chunk_length):
887 """Collect command_prefix{offset:x},{chunk_length:x} until a single 'l' or 'l' with data is returned."""
888 offset = 0
889 done = False
890 decoded_data = ""
891
892 while not done:
893 # Grab the next iteration of data.
894 self.reset_test_sequence()
895 self.test_sequence.add_log_lines([
896 "read packet: ${}{:x},{:x}:#00".format(command_prefix, offset, chunk_length),
Todd Fiala4c24eba2014-06-19 17:35:40 +0000897 {"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 +0000898 ], True)
899
900 context = self.expect_gdbremote_sequence()
901 self.assertIsNotNone(context)
902
903 response_type = context.get("response_type")
904 self.assertIsNotNone(response_type)
905 self.assertTrue(response_type in ["l", "m"])
906
907 # Move offset along.
908 offset += chunk_length
909
910 # Figure out if we're done. We're done if the response type is l.
911 done = response_type == "l"
912
913 # Decode binary data.
914 content_raw = context.get("content_raw")
915 if content_raw and len(content_raw) > 0:
916 self.assertIsNotNone(content_raw)
917 decoded_data += self.decode_gdbremote_binary(content_raw)
918 return decoded_data
Todd Fiala4c24eba2014-06-19 17:35:40 +0000919
920 def add_interrupt_packets(self):
921 self.test_sequence.add_log_lines([
922 # Send the intterupt.
923 "read packet: {}".format(chr(03)),
924 # And wait for the stop notification.
925 {"direction":"send", "regex":r"^\$T([0-9a-fA-F]{2})(.*)#[0-9a-fA-F]{2}$", "capture":{1:"stop_signo", 2:"stop_key_val_text" } },
926 ], True)
927
928 def parse_interrupt_packets(self, context):
929 self.assertIsNotNone(context.get("stop_signo"))
930 self.assertIsNotNone(context.get("stop_key_val_text"))
Todd Fiala9846d452014-06-20 17:39:24 +0000931 return (int(context["stop_signo"], 16), self.parse_key_val_dict(context["stop_key_val_text"]))
932
933 def add_QSaveRegisterState_packets(self, thread_id):
934 if thread_id:
935 # Use the thread suffix form.
936 request = "read packet: $QSaveRegisterState;thread:{:x}#00".format(thread_id)
937 else:
938 request = "read packet: $QSaveRegisterState#00"
939
940 self.test_sequence.add_log_lines([
941 request,
942 {"direction":"send", "regex":r"^\$(E?.*)#[0-9a-fA-F]{2}$", "capture":{1:"save_response" } },
943 ], True)
944
945 def parse_QSaveRegisterState_response(self, context):
946 self.assertIsNotNone(context)
947
948 save_response = context.get("save_response")
949 self.assertIsNotNone(save_response)
950
951 if len(save_response) < 1 or save_response[0] == "E":
952 # error received
953 return (False, None)
954 else:
955 return (True, int(save_response))
956
957 def add_QRestoreRegisterState_packets(self, save_id, thread_id=None):
958 if thread_id:
959 # Use the thread suffix form.
960 request = "read packet: $QRestoreRegisterState:{};thread:{:x}#00".format(save_id, thread_id)
961 else:
962 request = "read packet: $QRestoreRegisterState:{}#00".format(save_id)
963
964 self.test_sequence.add_log_lines([
965 request,
966 "send packet: $OK#00"
967 ], True)
968
969 def flip_all_bits_in_each_register_value(self, reg_infos, endian, thread_id=None):
970 self.assertIsNotNone(reg_infos)
971
972 successful_writes = 0
973 failed_writes = 0
974
975 for reg_info in reg_infos:
976 # Use the lldb register index added to the reg info. We're not necessarily
977 # working off a full set of register infos, so an inferred register index could be wrong.
978 reg_index = reg_info["lldb_register_index"]
979 self.assertIsNotNone(reg_index)
980
981 reg_byte_size = int(reg_info["bitsize"])/8
982 self.assertTrue(reg_byte_size > 0)
983
984 # Handle thread suffix.
985 if thread_id:
986 p_request = "read packet: $p{:x};thread:{:x}#00".format(reg_index, thread_id)
987 else:
988 p_request = "read packet: $p{:x}#00".format(reg_index)
989
990 # Read the existing value.
991 self.reset_test_sequence()
992 self.test_sequence.add_log_lines([
993 p_request,
994 { "direction":"send", "regex":r"^\$([0-9a-fA-F]+)#", "capture":{1:"p_response"} },
995 ], True)
996 context = self.expect_gdbremote_sequence()
997 self.assertIsNotNone(context)
998
999 # Verify the response length.
1000 p_response = context.get("p_response")
1001 self.assertIsNotNone(p_response)
1002 initial_reg_value = unpack_register_hex_unsigned(endian, p_response)
1003
1004 # Flip the value by xoring with all 1s
1005 all_one_bits_raw = "ff" * (int(reg_info["bitsize"]) / 8)
1006 flipped_bits_int = initial_reg_value ^ int(all_one_bits_raw, 16)
1007 # 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)
1008
1009 # Handle thread suffix for P.
1010 if thread_id:
1011 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)
1012 else:
1013 P_request = "read packet: $P{:x}={}#00".format(reg_index, pack_register_hex(endian, flipped_bits_int, byte_size=reg_byte_size))
1014
1015 # Write the flipped value to the register.
1016 self.reset_test_sequence()
1017 self.test_sequence.add_log_lines([
1018 P_request,
1019 { "direction":"send", "regex":r"^\$(OK|E[0-9a-fA-F]+)#[0-9a-fA-F]{2}", "capture":{1:"P_response"} },
1020 ], True)
1021 context = self.expect_gdbremote_sequence()
1022 self.assertIsNotNone(context)
1023
1024 # Determine if the write succeeded. There are a handful of registers that can fail, or partially fail
1025 # (e.g. flags, segment selectors, etc.) due to register value restrictions. Don't worry about them
1026 # all flipping perfectly.
1027 P_response = context.get("P_response")
1028 self.assertIsNotNone(P_response)
1029 if P_response == "OK":
1030 successful_writes += 1
1031 else:
1032 failed_writes += 1
1033 # print "reg (index={}, name={}) write FAILED (error: {})".format(reg_index, reg_info["name"], P_response)
1034
1035 # Read back the register value, ensure it matches the flipped value.
1036 if P_response == "OK":
1037 self.reset_test_sequence()
1038 self.test_sequence.add_log_lines([
1039 p_request,
1040 { "direction":"send", "regex":r"^\$([0-9a-fA-F]+)#", "capture":{1:"p_response"} },
1041 ], True)
1042 context = self.expect_gdbremote_sequence()
1043 self.assertIsNotNone(context)
1044
1045 verify_p_response_raw = context.get("p_response")
1046 self.assertIsNotNone(verify_p_response_raw)
1047 verify_bits = unpack_register_hex_unsigned(endian, verify_p_response_raw)
1048
1049 if verify_bits != flipped_bits_int:
1050 # Some registers, like mxcsrmask and others, will permute what's written. Adjust succeed/fail counts.
1051 # print "reg (index={}, name={}): read verify FAILED: wrote {:x}, verify read back {:x}".format(reg_index, reg_info["name"], flipped_bits_int, verify_bits)
1052 successful_writes -= 1
1053 failed_writes +=1
1054
1055 return (successful_writes, failed_writes)
1056
1057 def is_bit_flippable_register(self, reg_info):
1058 if not reg_info:
1059 return False
1060 if not "set" in reg_info:
1061 return False
1062 if reg_info["set"] != "General Purpose Registers":
1063 return False
1064 if ("container-regs" in reg_info) and (len(reg_info["container-regs"]) > 0):
1065 # Don't try to bit flip registers contained in another register.
1066 return False
1067 if re.match("^.s$", reg_info["name"]):
1068 # This is a 2-letter register name that ends in "s", like a segment register.
1069 # Don't try to bit flip these.
1070 return False
Siva Chandrad772ef32015-06-04 22:04:04 +00001071 if re.match("^(c|)psr$", reg_info["name"]):
1072 # This is an ARM program status register; don't flip it.
1073 return False
Todd Fiala9846d452014-06-20 17:39:24 +00001074 # Okay, this looks fine-enough.
1075 return True
1076
1077 def read_register_values(self, reg_infos, endian, thread_id=None):
1078 self.assertIsNotNone(reg_infos)
1079 values = {}
1080
1081 for reg_info in reg_infos:
1082 # We append a register index when load reg infos so we can work with subsets.
1083 reg_index = reg_info.get("lldb_register_index")
1084 self.assertIsNotNone(reg_index)
1085
1086 # Handle thread suffix.
1087 if thread_id:
1088 p_request = "read packet: $p{:x};thread:{:x}#00".format(reg_index, thread_id)
1089 else:
1090 p_request = "read packet: $p{:x}#00".format(reg_index)
1091
1092 # Read it with p.
1093 self.reset_test_sequence()
1094 self.test_sequence.add_log_lines([
1095 p_request,
1096 { "direction":"send", "regex":r"^\$([0-9a-fA-F]+)#", "capture":{1:"p_response"} },
1097 ], True)
1098 context = self.expect_gdbremote_sequence()
1099 self.assertIsNotNone(context)
1100
1101 # Convert value from target endian to integral.
1102 p_response = context.get("p_response")
1103 self.assertIsNotNone(p_response)
1104 self.assertTrue(len(p_response) > 0)
1105 self.assertFalse(p_response[0] == "E")
1106
1107 values[reg_index] = unpack_register_hex_unsigned(endian, p_response)
1108
Todd Fialae2202002014-06-27 22:11:56 +00001109 return values
1110
1111 def add_vCont_query_packets(self):
1112 self.test_sequence.add_log_lines([
Stephane Sezer22ed42e2014-11-13 21:39:24 +00001113 "read packet: $vCont?#49",
Todd Fialae2202002014-06-27 22:11:56 +00001114 {"direction":"send", "regex":r"^\$(vCont)?(.*)#[0-9a-fA-F]{2}$", "capture":{2:"vCont_query_response" } },
1115 ], True)
1116
1117 def parse_vCont_query_response(self, context):
1118 self.assertIsNotNone(context)
1119 vCont_query_response = context.get("vCont_query_response")
1120
1121 # Handle case of no vCont support at all - in which case the capture group will be none or zero length.
1122 if not vCont_query_response or len(vCont_query_response) == 0:
1123 return {}
1124
1125 return {key:1 for key in vCont_query_response.split(";") if key and len(key) > 0}
1126
1127 def count_single_steps_until_true(self, thread_id, predicate, args, max_step_count=100, use_Hc_packet=True, step_instruction="s"):
1128 """Used by single step test that appears in a few different contexts."""
1129 single_step_count = 0
1130
1131 while single_step_count < max_step_count:
1132 self.assertIsNotNone(thread_id)
1133
1134 # Build the packet for the single step instruction. We replace {thread}, if present, with the thread_id.
1135 step_packet = "read packet: ${}#00".format(re.sub(r"{thread}", "{:x}".format(thread_id), step_instruction))
1136 # print "\nstep_packet created: {}\n".format(step_packet)
1137
1138 # Single step.
1139 self.reset_test_sequence()
1140 if use_Hc_packet:
1141 self.test_sequence.add_log_lines(
1142 [# Set the continue thread.
1143 "read packet: $Hc{0:x}#00".format(thread_id),
1144 "send packet: $OK#00",
1145 ], True)
1146 self.test_sequence.add_log_lines([
1147 # Single step.
1148 step_packet,
1149 # "read packet: $vCont;s:{0:x}#00".format(thread_id),
1150 # Expect a breakpoint stop report.
1151 {"direction":"send", "regex":r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);", "capture":{1:"stop_signo", 2:"stop_thread_id"} },
1152 ], True)
1153 context = self.expect_gdbremote_sequence()
1154 self.assertIsNotNone(context)
1155 self.assertIsNotNone(context.get("stop_signo"))
Chaoren Lin677acee2015-06-02 17:01:13 +00001156 self.assertEquals(int(context.get("stop_signo"), 16),
1157 lldbutil.get_signal_number('SIGTRAP'))
Todd Fialae2202002014-06-27 22:11:56 +00001158
1159 single_step_count += 1
1160
1161 # See if the predicate is true. If so, we're done.
1162 if predicate(args):
1163 return (True, single_step_count)
1164
1165 # The predicate didn't return true within the runaway step count.
1166 return (False, single_step_count)
1167
1168 def g_c1_c2_contents_are(self, args):
1169 """Used by single step test that appears in a few different contexts."""
1170 g_c1_address = args["g_c1_address"]
1171 g_c2_address = args["g_c2_address"]
1172 expected_g_c1 = args["expected_g_c1"]
1173 expected_g_c2 = args["expected_g_c2"]
1174
1175 # Read g_c1 and g_c2 contents.
1176 self.reset_test_sequence()
1177 self.test_sequence.add_log_lines(
1178 ["read packet: $m{0:x},{1:x}#00".format(g_c1_address, 1),
1179 {"direction":"send", "regex":r"^\$(.+)#[0-9a-fA-F]{2}$", "capture":{1:"g_c1_contents"} },
1180 "read packet: $m{0:x},{1:x}#00".format(g_c2_address, 1),
1181 {"direction":"send", "regex":r"^\$(.+)#[0-9a-fA-F]{2}$", "capture":{1:"g_c2_contents"} }],
1182 True)
1183
1184 # Run the packet stream.
1185 context = self.expect_gdbremote_sequence()
1186 self.assertIsNotNone(context)
1187
1188 # Check if what we read from inferior memory is what we are expecting.
1189 self.assertIsNotNone(context.get("g_c1_contents"))
1190 self.assertIsNotNone(context.get("g_c2_contents"))
1191
1192 return (context.get("g_c1_contents").decode("hex") == expected_g_c1) and (context.get("g_c2_contents").decode("hex") == expected_g_c2)
1193
1194 def single_step_only_steps_one_instruction(self, use_Hc_packet=True, step_instruction="s"):
1195 """Used by single step test that appears in a few different contexts."""
1196 # Start up the inferior.
1197 procs = self.prep_debug_monitor_and_inferior(
1198 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"])
1199
1200 # Run the process
1201 self.test_sequence.add_log_lines(
1202 [# Start running after initial stop.
Stephane Sezer22ed42e2014-11-13 21:39:24 +00001203 "read packet: $c#63",
Todd Fialae2202002014-06-27 22:11:56 +00001204 # Match output line that prints the memory address of the function call entry point.
1205 # Note we require launch-only testing so we can get inferior otuput.
1206 { "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$",
1207 "capture":{ 1:"function_address", 2:"g_c1_address", 3:"g_c2_address"} },
1208 # Now stop the inferior.
1209 "read packet: {}".format(chr(03)),
1210 # And wait for the stop notification.
1211 {"direction":"send", "regex":r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);", "capture":{1:"stop_signo", 2:"stop_thread_id"} }],
1212 True)
1213
1214 # Run the packet stream.
1215 context = self.expect_gdbremote_sequence()
1216 self.assertIsNotNone(context)
1217
1218 # Grab the main thread id.
1219 self.assertIsNotNone(context.get("stop_thread_id"))
1220 main_thread_id = int(context.get("stop_thread_id"), 16)
1221
1222 # Grab the function address.
1223 self.assertIsNotNone(context.get("function_address"))
1224 function_address = int(context.get("function_address"), 16)
1225
1226 # Grab the data addresses.
1227 self.assertIsNotNone(context.get("g_c1_address"))
1228 g_c1_address = int(context.get("g_c1_address"), 16)
1229
1230 self.assertIsNotNone(context.get("g_c2_address"))
1231 g_c2_address = int(context.get("g_c2_address"), 16)
1232
1233 # Set a breakpoint at the given address.
Tamas Berghammer157e84f2015-05-28 10:55:01 +00001234 if self.getArchitecture() == "arm":
1235 # TODO: Handle case when setting breakpoint in thumb code
1236 BREAKPOINT_KIND = 4
1237 else:
1238 BREAKPOINT_KIND = 1
Todd Fialae2202002014-06-27 22:11:56 +00001239 self.reset_test_sequence()
1240 self.add_set_breakpoint_packets(function_address, do_continue=True, breakpoint_kind=BREAKPOINT_KIND)
1241 context = self.expect_gdbremote_sequence()
1242 self.assertIsNotNone(context)
1243
1244 # Remove the breakpoint.
1245 self.reset_test_sequence()
1246 self.add_remove_breakpoint_packets(function_address, breakpoint_kind=BREAKPOINT_KIND)
1247 context = self.expect_gdbremote_sequence()
1248 self.assertIsNotNone(context)
1249
1250 # Verify g_c1 and g_c2 match expected initial state.
1251 args = {}
1252 args["g_c1_address"] = g_c1_address
1253 args["g_c2_address"] = g_c2_address
1254 args["expected_g_c1"] = "0"
1255 args["expected_g_c2"] = "1"
1256
1257 self.assertTrue(self.g_c1_c2_contents_are(args))
1258
1259 # Verify we take only a small number of steps to hit the first state. Might need to work through function entry prologue code.
1260 args["expected_g_c1"] = "1"
1261 args["expected_g_c2"] = "1"
1262 (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)
1263 self.assertTrue(state_reached)
1264
1265 # Verify we hit the next state.
1266 args["expected_g_c1"] = "1"
1267 args["expected_g_c2"] = "0"
1268 (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)
1269 self.assertTrue(state_reached)
1270 self.assertEquals(step_count, 1)
1271
1272 # Verify we hit the next state.
1273 args["expected_g_c1"] = "0"
1274 args["expected_g_c2"] = "0"
1275 (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)
1276 self.assertTrue(state_reached)
1277 self.assertEquals(step_count, 1)
1278
1279 # Verify we hit the next state.
1280 args["expected_g_c1"] = "0"
1281 args["expected_g_c2"] = "1"
1282 (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)
1283 self.assertTrue(state_reached)
1284 self.assertEquals(step_count, 1)
Todd Fialaaf245d12014-06-30 21:05:18 +00001285