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