blob: 2ea0db920d119dba0aca69d42111f6e05d3c1063 [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
26 mydir = TestBase.compute_mydir(__file__)
27
Todd Fialae50b2e42014-06-13 19:11:33 +000028 _TIMEOUT_SECONDS = 5
29
30 _GDBREMOTE_KILL_PACKET = "$k#6b"
31
32 _LOGGING_LEVEL = logging.WARNING
33 # _LOGGING_LEVEL = logging.DEBUG
34
Todd Fiala7306cf32014-07-29 22:30:01 +000035 # Start the inferior separately, attach to the inferior on the stub command line.
Todd Fialae50b2e42014-06-13 19:11:33 +000036 _STARTUP_ATTACH = "attach"
Todd Fiala7306cf32014-07-29 22:30:01 +000037 # Start the inferior separately, start the stub without attaching, allow the test to attach to the inferior however it wants (e.g. $vAttach;pid).
38 _STARTUP_ATTACH_MANUALLY = "attach_manually"
39 # Start the stub, and launch the inferior with an $A packet via the initial packet stream.
Todd Fialae50b2e42014-06-13 19:11:33 +000040 _STARTUP_LAUNCH = "launch"
41
42 # GDB Signal numbers that are not target-specific used for common exceptions
43 TARGET_EXC_BAD_ACCESS = 0x91
44 TARGET_EXC_BAD_INSTRUCTION = 0x92
45 TARGET_EXC_ARITHMETIC = 0x93
46 TARGET_EXC_EMULATION = 0x94
47 TARGET_EXC_SOFTWARE = 0x95
48 TARGET_EXC_BREAKPOINT = 0x96
49
50 def setUp(self):
51 TestBase.setUp(self)
52 FORMAT = '%(asctime)-15s %(levelname)-8s %(message)s'
53 logging.basicConfig(format=FORMAT)
54 self.logger = logging.getLogger(__name__)
55 self.logger.setLevel(self._LOGGING_LEVEL)
56 self.test_sequence = GdbRemoteTestSequence(self.logger)
57 self.set_inferior_startup_launch()
Todd Fiala9e2d3292014-07-09 23:10:43 +000058 self.port = self.get_next_port()
Todd Fiala67041192014-07-11 22:50:13 +000059 self.named_pipe_path = None
Todd Fiala24189d42014-07-14 06:24:44 +000060 self.named_pipe = None
61 self.named_pipe_fd = None
Todd Fialaf9ad21d2014-07-16 16:15:42 +000062 self.stub_sends_two_stop_notifications_on_kill = False
Todd Fiala31bde322014-07-26 20:39:17 +000063 self.stub_hostname = "localhost"
Todd Fialae50b2e42014-06-13 19:11:33 +000064
Todd Fiala9e2d3292014-07-09 23:10:43 +000065 def get_next_port(self):
66 return 12000 + random.randint(0,3999)
Todd Fialae50b2e42014-06-13 19:11:33 +000067
68 def reset_test_sequence(self):
69 self.test_sequence = GdbRemoteTestSequence(self.logger)
70
Todd Fiala24189d42014-07-14 06:24:44 +000071 def create_named_pipe(self):
72 # Create a temp dir and name for a pipe.
73 temp_dir = tempfile.mkdtemp()
74 named_pipe_path = os.path.join(temp_dir, "stub_port_number")
75
76 # Create the named pipe.
77 os.mkfifo(named_pipe_path)
78
79 # Open the read side of the pipe in non-blocking mode. This will return right away, ready or not.
80 named_pipe_fd = os.open(named_pipe_path, os.O_RDONLY | os.O_NONBLOCK)
81
82 # Create the file for the named pipe. Note this will follow semantics of
83 # a non-blocking read side of a named pipe, which has different semantics
84 # than a named pipe opened for read in non-blocking mode.
85 named_pipe = os.fdopen(named_pipe_fd, "r")
86 self.assertIsNotNone(named_pipe)
87
88 def shutdown_named_pipe():
89 # Close the pipe.
90 try:
91 named_pipe.close()
92 except:
93 print "failed to close named pipe"
94 None
95
96 # Delete the pipe.
97 try:
98 os.remove(named_pipe_path)
99 except:
100 print "failed to delete named pipe: {}".format(named_pipe_path)
101 None
102
103 # Delete the temp directory.
104 try:
105 os.rmdir(temp_dir)
106 except:
107 print "failed to delete temp dir: {}, directory contents: '{}'".format(temp_dir, os.listdir(temp_dir))
108 None
109
110 # Add the shutdown hook to clean up the named pipe.
111 self.addTearDownHook(shutdown_named_pipe)
112
113 # Clear the port so the stub selects a port number.
114 self.port = 0
115
116 return (named_pipe_path, named_pipe, named_pipe_fd)
117
118 def get_stub_port_from_named_socket(self, read_timeout_seconds=5):
119 # Wait for something to read with a max timeout.
120 (ready_readers, _, _) = select.select([self.named_pipe_fd], [], [], read_timeout_seconds)
121 self.assertIsNotNone(ready_readers, "write side of pipe has not written anything - stub isn't writing to pipe.")
122 self.assertNotEqual(len(ready_readers), 0, "write side of pipe has not written anything - stub isn't writing to pipe.")
123
124 # Read the port from the named pipe.
125 stub_port_raw = self.named_pipe.read()
126 self.assertIsNotNone(stub_port_raw)
127 self.assertNotEqual(len(stub_port_raw), 0, "no content to read on pipe")
128
129 # Trim null byte, convert to int.
130 stub_port_raw = stub_port_raw[:-1]
131 stub_port = int(stub_port_raw)
132 self.assertTrue(stub_port > 0)
133
134 return stub_port
135
136 def init_llgs_test(self, use_named_pipe=True):
Robert Flack8cc4cf12015-03-06 14:36:33 +0000137 self.debug_monitor_exe = get_lldb_server_exe()
Todd Fialae50b2e42014-06-13 19:11:33 +0000138 if not self.debug_monitor_exe:
Robert Flack8cc4cf12015-03-06 14:36:33 +0000139 self.skipTest("lldb-server exe not found")
Pavel Labath9180f962015-02-04 10:48:29 +0000140 dname = os.path.join(os.environ["LLDB_TEST"],
141 os.environ["LLDB_SESSION_DIRNAME"])
Tamas Berghammerc2c3d712015-02-18 15:39:41 +0000142 self.debug_monitor_extra_args = " gdbserver -c 'log enable -T -f {}/process-{}.log lldb break process thread' -c 'log enable -T -f {}/packets-{}.log gdb-remote packets'".format(dname, self.id(), dname, self.id())
Todd Fiala24189d42014-07-14 06:24:44 +0000143 if use_named_pipe:
144 (self.named_pipe_path, self.named_pipe, self.named_pipe_fd) = self.create_named_pipe()
Todd Fialae50b2e42014-06-13 19:11:33 +0000145
Todd Fiala24189d42014-07-14 06:24:44 +0000146 def init_debugserver_test(self, use_named_pipe=True):
Todd Fialae50b2e42014-06-13 19:11:33 +0000147 self.debug_monitor_exe = get_debugserver_exe()
148 if not self.debug_monitor_exe:
149 self.skipTest("debugserver exe not found")
150 self.debug_monitor_extra_args = " --log-file=/tmp/packets-{}.log --log-flags=0x800000".format(self._testMethodName)
Todd Fiala24189d42014-07-14 06:24:44 +0000151 if use_named_pipe:
152 (self.named_pipe_path, self.named_pipe, self.named_pipe_fd) = self.create_named_pipe()
Todd Fialaf9ad21d2014-07-16 16:15:42 +0000153 # The debugserver stub has a race on handling the 'k' command, so it sends an X09 right away, then sends the real X notification
154 # when the process truly dies.
155 self.stub_sends_two_stop_notifications_on_kill = True
Todd Fialae50b2e42014-06-13 19:11:33 +0000156
157 def create_socket(self):
158 sock = socket.socket()
159 logger = self.logger
160
161 def shutdown_socket():
162 if sock:
163 try:
Robert Flack8cc4cf12015-03-06 14:36:33 +0000164 # send the kill packet so lldb-server shuts down gracefully
Todd Fialae50b2e42014-06-13 19:11:33 +0000165 sock.sendall(GdbRemoteTestCaseBase._GDBREMOTE_KILL_PACKET)
166 except:
167 logger.warning("failed to send kill packet to debug monitor: {}; ignoring".format(sys.exc_info()[0]))
168
169 try:
170 sock.close()
171 except:
172 logger.warning("failed to close socket to debug monitor: {}; ignoring".format(sys.exc_info()[0]))
173
174 self.addTearDownHook(shutdown_socket)
175
Todd Fiala31bde322014-07-26 20:39:17 +0000176 connect_info = (self.stub_hostname, self.port)
Todd Fiala24189d42014-07-14 06:24:44 +0000177 # print "connecting to stub on {}:{}".format(connect_info[0], connect_info[1])
178 sock.connect(connect_info)
179
Todd Fialae50b2e42014-06-13 19:11:33 +0000180 return sock
181
182 def set_inferior_startup_launch(self):
183 self._inferior_startup = self._STARTUP_LAUNCH
184
185 def set_inferior_startup_attach(self):
186 self._inferior_startup = self._STARTUP_ATTACH
187
Todd Fiala7306cf32014-07-29 22:30:01 +0000188 def set_inferior_startup_attach_manually(self):
189 self._inferior_startup = self._STARTUP_ATTACH_MANUALLY
190
Todd Fiala31bde322014-07-26 20:39:17 +0000191 def get_debug_monitor_command_line(self, attach_pid=None):
Todd Fialae50b2e42014-06-13 19:11:33 +0000192 commandline = "{}{} localhost:{}".format(self.debug_monitor_exe, self.debug_monitor_extra_args, self.port)
193 if attach_pid:
194 commandline += " --attach=%d" % attach_pid
Todd Fiala67041192014-07-11 22:50:13 +0000195 if self.named_pipe_path:
196 commandline += " --named-pipe %s" % self.named_pipe_path
Todd Fiala31bde322014-07-26 20:39:17 +0000197 return commandline
198
199 def launch_debug_monitor(self, attach_pid=None, logfile=None):
200 # Create the command line.
201 import pexpect
202 commandline = self.get_debug_monitor_command_line(attach_pid=attach_pid)
Todd Fialae50b2e42014-06-13 19:11:33 +0000203
Todd Fiala8aae4f42014-06-13 23:34:17 +0000204 # Start the server.
Todd Fiala31bde322014-07-26 20:39:17 +0000205 server = pexpect.spawn(commandline, logfile=logfile)
Todd Fiala24189d42014-07-14 06:24:44 +0000206 self.assertIsNotNone(server)
Robert Flack8cc4cf12015-03-06 14:36:33 +0000207 server.expect(r"(debugserver|lldb-server)", timeout=10)
Todd Fiala24189d42014-07-14 06:24:44 +0000208
209 # If we're receiving the stub's listening port from the named pipe, do that here.
210 if self.named_pipe:
211 self.port = self.get_stub_port_from_named_socket()
212 # print "debug server listening on {}".format(self.port)
Todd Fialae50b2e42014-06-13 19:11:33 +0000213
214 # Turn on logging for what the child sends back.
215 if self.TraceOn():
216 server.logfile_read = sys.stdout
217
Todd Fiala8aae4f42014-06-13 23:34:17 +0000218 return server
219
220 def connect_to_debug_monitor(self, attach_pid=None):
Todd Fiala24189d42014-07-14 06:24:44 +0000221 if self.named_pipe:
222 # Create the stub.
223 server = self.launch_debug_monitor(attach_pid=attach_pid)
224 self.assertIsNotNone(server)
225
226 def shutdown_debug_monitor():
227 try:
228 server.close()
229 except:
230 logger.warning("failed to close pexpect server for debug monitor: {}; ignoring".format(sys.exc_info()[0]))
231 self.addTearDownHook(shutdown_debug_monitor)
232
233 # Schedule debug monitor to be shut down during teardown.
234 logger = self.logger
235
236 # Attach to the stub and return a socket opened to it.
237 self.sock = self.create_socket()
238 return server
239
240 # We're using a random port algorithm to try not to collide with other ports,
241 # and retry a max # times.
Todd Fiala8aae4f42014-06-13 23:34:17 +0000242 attempts = 0
243 MAX_ATTEMPTS = 20
Todd Fialae50b2e42014-06-13 19:11:33 +0000244
Todd Fiala8aae4f42014-06-13 23:34:17 +0000245 while attempts < MAX_ATTEMPTS:
Todd Fiala9e2d3292014-07-09 23:10:43 +0000246 server = self.launch_debug_monitor(attach_pid=attach_pid)
247
248 # Wait until we receive the server ready message before continuing.
249 port_good = True
Todd Fiala8aae4f42014-06-13 23:34:17 +0000250 try:
Todd Fiala9e2d3292014-07-09 23:10:43 +0000251 server.expect_exact('Listening to port {} for a connection from localhost'.format(self.port))
252 except:
253 port_good = False
254 server.close()
Todd Fialae50b2e42014-06-13 19:11:33 +0000255
Todd Fiala9e2d3292014-07-09 23:10:43 +0000256 if port_good:
257 # Schedule debug monitor to be shut down during teardown.
258 logger = self.logger
259 def shutdown_debug_monitor():
260 try:
261 server.close()
262 except:
263 logger.warning("failed to close pexpect server for debug monitor: {}; ignoring".format(sys.exc_info()[0]))
264 self.addTearDownHook(shutdown_debug_monitor)
Todd Fiala8aae4f42014-06-13 23:34:17 +0000265
Todd Fiala9e2d3292014-07-09 23:10:43 +0000266 # Create a socket to talk to the server
267 try:
268 self.sock = self.create_socket()
269 return server
270 except socket.error as serr:
271 # We're only trying to handle connection refused.
272 if serr.errno != errno.ECONNREFUSED:
273 raise serr
274 # We should close the server here to be safe.
275 server.close()
276
277 # Increment attempts.
278 print("connect to debug monitor on port %d failed, attempt #%d of %d" % (self.port, attempts + 1, MAX_ATTEMPTS))
279 attempts += 1
280
281 # And wait a random length of time before next attempt, to avoid collisions.
282 time.sleep(random.randint(1,5))
283
284 # Now grab a new port number.
285 self.port = self.get_next_port()
Todd Fiala8aae4f42014-06-13 23:34:17 +0000286
287 raise Exception("failed to create a socket to the launched debug monitor after %d tries" % attempts)
Todd Fialae50b2e42014-06-13 19:11:33 +0000288
Todd Fiala58a2f662014-08-12 17:02:07 +0000289 def launch_process_for_attach(self,inferior_args=None, sleep_seconds=3, exe_path=None):
Todd Fialae50b2e42014-06-13 19:11:33 +0000290 # We're going to start a child process that the debug monitor stub can later attach to.
291 # This process needs to be started so that it just hangs around for a while. We'll
292 # have it sleep.
Todd Fiala58a2f662014-08-12 17:02:07 +0000293 if not exe_path:
294 exe_path = os.path.abspath("a.out")
Todd Fialae50b2e42014-06-13 19:11:33 +0000295
296 args = [exe_path]
297 if inferior_args:
298 args.extend(inferior_args)
299 if sleep_seconds:
300 args.append("sleep:%d" % sleep_seconds)
301
302 return subprocess.Popen(args)
303
Todd Fiala58a2f662014-08-12 17:02:07 +0000304 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 +0000305 """Prep the debug monitor, the inferior, and the expected packet stream.
306
307 Handle the separate cases of using the debug monitor in attach-to-inferior mode
308 and in launch-inferior mode.
309
310 For attach-to-inferior mode, the inferior process is first started, then
311 the debug monitor is started in attach to pid mode (using --attach on the
312 stub command line), and the no-ack-mode setup is appended to the packet
313 stream. The packet stream is not yet executed, ready to have more expected
314 packet entries added to it.
315
316 For launch-inferior mode, the stub is first started, then no ack mode is
317 setup on the expected packet stream, then the verified launch packets are added
318 to the expected socket stream. The packet stream is not yet executed, ready
319 to have more expected packet entries added to it.
320
321 The return value is:
322 {inferior:<inferior>, server:<server>}
323 """
324 inferior = None
325 attach_pid = None
326
Todd Fiala7306cf32014-07-29 22:30:01 +0000327 if self._inferior_startup == self._STARTUP_ATTACH or self._inferior_startup == self._STARTUP_ATTACH_MANUALLY:
Todd Fialae50b2e42014-06-13 19:11:33 +0000328 # Launch the process that we'll use as the inferior.
Todd Fiala58a2f662014-08-12 17:02:07 +0000329 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 +0000330 self.assertIsNotNone(inferior)
331 self.assertTrue(inferior.pid > 0)
Todd Fiala7306cf32014-07-29 22:30:01 +0000332 if self._inferior_startup == self._STARTUP_ATTACH:
333 # In this case, we want the stub to attach via the command line, so set the command line attach pid here.
334 attach_pid = inferior.pid
Todd Fialae50b2e42014-06-13 19:11:33 +0000335
336 # Launch the debug monitor stub, attaching to the inferior.
Todd Fiala8aae4f42014-06-13 23:34:17 +0000337 server = self.connect_to_debug_monitor(attach_pid=attach_pid)
Todd Fialae50b2e42014-06-13 19:11:33 +0000338 self.assertIsNotNone(server)
339
340 if self._inferior_startup == self._STARTUP_LAUNCH:
341 # Build launch args
Todd Fiala58a2f662014-08-12 17:02:07 +0000342 if not inferior_exe_path:
343 inferior_exe_path = os.path.abspath("a.out")
344 launch_args = [inferior_exe_path]
Todd Fialae50b2e42014-06-13 19:11:33 +0000345 if inferior_args:
346 launch_args.extend(inferior_args)
347
348 # Build the expected protocol stream
349 self.add_no_ack_remote_stream()
350 if self._inferior_startup == self._STARTUP_LAUNCH:
351 self.add_verified_launch_packets(launch_args)
352
353 return {"inferior":inferior, "server":server}
354
Todd Fiala31bde322014-07-26 20:39:17 +0000355 def expect_socket_recv(self, sock, expected_content_regex, timeout_seconds):
356 response = ""
357 timeout_time = time.time() + timeout_seconds
358
359 while not expected_content_regex.match(response) and time.time() < timeout_time:
360 can_read, _, _ = select.select([sock], [], [], timeout_seconds)
361 if can_read and sock in can_read:
362 recv_bytes = sock.recv(4096)
363 if recv_bytes:
364 response += recv_bytes
365
366 self.assertTrue(expected_content_regex.match(response))
367
368 def expect_socket_send(self, sock, content, timeout_seconds):
369 request_bytes_remaining = content
370 timeout_time = time.time() + timeout_seconds
371
372 while len(request_bytes_remaining) > 0 and time.time() < timeout_time:
373 _, can_write, _ = select.select([], [sock], [], timeout_seconds)
374 if can_write and sock in can_write:
375 written_byte_count = sock.send(request_bytes_remaining)
376 request_bytes_remaining = request_bytes_remaining[written_byte_count:]
377 self.assertEquals(len(request_bytes_remaining), 0)
378
379 def do_handshake(self, stub_socket, timeout_seconds=5):
380 # Write the ack.
381 self.expect_socket_send(stub_socket, "+", timeout_seconds)
382
383 # Send the start no ack mode packet.
384 NO_ACK_MODE_REQUEST = "$QStartNoAckMode#b0"
385 bytes_sent = stub_socket.send(NO_ACK_MODE_REQUEST)
386 self.assertEquals(bytes_sent, len(NO_ACK_MODE_REQUEST))
387
388 # Receive the ack and "OK"
389 self.expect_socket_recv(stub_socket, re.compile(r"^\+\$OK#[0-9a-fA-F]{2}$"), timeout_seconds)
390
391 # Send the final ack.
392 self.expect_socket_send(stub_socket, "+", timeout_seconds)
393
Todd Fialae50b2e42014-06-13 19:11:33 +0000394 def add_no_ack_remote_stream(self):
395 self.test_sequence.add_log_lines(
396 ["read packet: +",
397 "read packet: $QStartNoAckMode#b0",
398 "send packet: +",
399 "send packet: $OK#9a",
400 "read packet: +"],
401 True)
402
403 def add_verified_launch_packets(self, launch_args):
404 self.test_sequence.add_log_lines(
405 ["read packet: %s" % build_gdbremote_A_packet(launch_args),
406 "send packet: $OK#00",
407 "read packet: $qLaunchSuccess#a5",
408 "send packet: $OK#00"],
409 True)
410
411 def add_thread_suffix_request_packets(self):
412 self.test_sequence.add_log_lines(
Stephane Sezer22ed42e2014-11-13 21:39:24 +0000413 ["read packet: $QThreadSuffixSupported#e4",
Todd Fialae50b2e42014-06-13 19:11:33 +0000414 "send packet: $OK#00",
415 ], True)
416
417 def add_process_info_collection_packets(self):
418 self.test_sequence.add_log_lines(
Stephane Sezer22ed42e2014-11-13 21:39:24 +0000419 ["read packet: $qProcessInfo#dc",
Todd Fiala8aae4f42014-06-13 23:34:17 +0000420 { "direction":"send", "regex":r"^\$(.+)#[0-9a-fA-F]{2}$", "capture":{1:"process_info_raw"} }],
Todd Fialae50b2e42014-06-13 19:11:33 +0000421 True)
422
423 _KNOWN_PROCESS_INFO_KEYS = [
424 "pid",
425 "parent-pid",
426 "real-uid",
427 "real-gid",
428 "effective-uid",
429 "effective-gid",
430 "cputype",
431 "cpusubtype",
432 "ostype",
Todd Fialac540dd02014-08-26 18:21:02 +0000433 "triple",
Todd Fialae50b2e42014-06-13 19:11:33 +0000434 "vendor",
435 "endian",
436 "ptrsize"
437 ]
438
439 def parse_process_info_response(self, context):
440 # Ensure we have a process info response.
441 self.assertIsNotNone(context)
442 process_info_raw = context.get("process_info_raw")
443 self.assertIsNotNone(process_info_raw)
444
445 # Pull out key:value; pairs.
446 process_info_dict = { match.group(1):match.group(2) for match in re.finditer(r"([^:]+):([^;]+);", process_info_raw) }
447
448 # Validate keys are known.
449 for (key, val) in process_info_dict.items():
450 self.assertTrue(key in self._KNOWN_PROCESS_INFO_KEYS)
451 self.assertIsNotNone(val)
452
453 return process_info_dict
454
455 def add_register_info_collection_packets(self):
456 self.test_sequence.add_log_lines(
457 [ { "type":"multi_response", "query":"qRegisterInfo", "append_iteration_suffix":True,
458 "end_regex":re.compile(r"^\$(E\d+)?#[0-9a-fA-F]{2}$"),
459 "save_key":"reg_info_responses" } ],
460 True)
461
462 def parse_register_info_packets(self, context):
463 """Return an array of register info dictionaries, one per register info."""
464 reg_info_responses = context.get("reg_info_responses")
465 self.assertIsNotNone(reg_info_responses)
466
467 # Parse register infos.
468 return [parse_reg_info_response(reg_info_response) for reg_info_response in reg_info_responses]
469
Todd Fiala50a211b2014-06-14 22:00:36 +0000470 def expect_gdbremote_sequence(self, timeout_seconds=None):
Todd Fiala8aae4f42014-06-13 23:34:17 +0000471 if not timeout_seconds:
472 timeout_seconds = self._TIMEOUT_SECONDS
473 return expect_lldb_gdbserver_replay(self, self.sock, self.test_sequence, timeout_seconds, self.logger)
Todd Fialae50b2e42014-06-13 19:11:33 +0000474
475 _KNOWN_REGINFO_KEYS = [
476 "name",
477 "alt-name",
478 "bitsize",
479 "offset",
480 "encoding",
481 "format",
482 "set",
483 "gcc",
484 "dwarf",
485 "generic",
486 "container-regs",
487 "invalidate-regs"
488 ]
489
490 def assert_valid_reg_info(self, reg_info):
491 # Assert we know about all the reginfo keys parsed.
492 for key in reg_info:
493 self.assertTrue(key in self._KNOWN_REGINFO_KEYS)
494
495 # Check the bare-minimum expected set of register info keys.
496 self.assertTrue("name" in reg_info)
497 self.assertTrue("bitsize" in reg_info)
498 self.assertTrue("offset" in reg_info)
499 self.assertTrue("encoding" in reg_info)
500 self.assertTrue("format" in reg_info)
501
502 def find_pc_reg_info(self, reg_infos):
503 lldb_reg_index = 0
504 for reg_info in reg_infos:
505 if ("generic" in reg_info) and (reg_info["generic"] == "pc"):
506 return (lldb_reg_index, reg_info)
507 lldb_reg_index += 1
508
509 return (None, None)
510
511 def add_lldb_register_index(self, reg_infos):
512 """Add a "lldb_register_index" key containing the 0-baed index of each reg_infos entry.
513
514 We'll use this when we want to call packets like P/p with a register index but do so
515 on only a subset of the full register info set.
516 """
517 self.assertIsNotNone(reg_infos)
518
519 reg_index = 0
520 for reg_info in reg_infos:
521 reg_info["lldb_register_index"] = reg_index
522 reg_index += 1
523
524 def add_query_memory_region_packets(self, address):
525 self.test_sequence.add_log_lines(
526 ["read packet: $qMemoryRegionInfo:{0:x}#00".format(address),
527 {"direction":"send", "regex":r"^\$(.+)#[0-9a-fA-F]{2}$", "capture":{1:"memory_region_response"} }],
528 True)
529
Todd Fialac30281a2014-06-14 03:03:23 +0000530 def parse_key_val_dict(self, key_val_text, allow_dupes=True):
Todd Fialae50b2e42014-06-13 19:11:33 +0000531 self.assertIsNotNone(key_val_text)
532 kv_dict = {}
533 for match in re.finditer(r";?([^:]+):([^;]+)", key_val_text):
Todd Fialac30281a2014-06-14 03:03:23 +0000534 key = match.group(1)
535 val = match.group(2)
536 if key in kv_dict:
537 if allow_dupes:
538 if type(kv_dict[key]) == list:
539 kv_dict[key].append(val)
540 else:
541 # Promote to list
542 kv_dict[key] = [kv_dict[key], val]
543 else:
544 self.fail("key '{}' already present when attempting to add value '{}' (text='{}', dict={})".format(key, val, key_val_text, kv_dict))
545 else:
546 kv_dict[key] = val
Todd Fialae50b2e42014-06-13 19:11:33 +0000547 return kv_dict
548
549 def parse_memory_region_packet(self, context):
550 # Ensure we have a context.
551 self.assertIsNotNone(context.get("memory_region_response"))
552
553 # Pull out key:value; pairs.
554 mem_region_dict = self.parse_key_val_dict(context.get("memory_region_response"))
555
556 # Validate keys are known.
557 for (key, val) in mem_region_dict.items():
558 self.assertTrue(key in ["start", "size", "permissions", "error"])
559 self.assertIsNotNone(val)
560
561 # Return the dictionary of key-value pairs for the memory region.
562 return mem_region_dict
563
564 def assert_address_within_memory_region(self, test_address, mem_region_dict):
565 self.assertIsNotNone(mem_region_dict)
566 self.assertTrue("start" in mem_region_dict)
567 self.assertTrue("size" in mem_region_dict)
568
569 range_start = int(mem_region_dict["start"], 16)
570 range_size = int(mem_region_dict["size"], 16)
571 range_end = range_start + range_size
572
573 if test_address < range_start:
574 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))
575 elif test_address >= range_end:
576 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))
577
578 def add_threadinfo_collection_packets(self):
579 self.test_sequence.add_log_lines(
580 [ { "type":"multi_response", "first_query":"qfThreadInfo", "next_query":"qsThreadInfo",
581 "append_iteration_suffix":False, "end_regex":re.compile(r"^\$(l)?#[0-9a-fA-F]{2}$"),
582 "save_key":"threadinfo_responses" } ],
583 True)
584
585 def parse_threadinfo_packets(self, context):
586 """Return an array of thread ids (decimal ints), one per thread."""
587 threadinfo_responses = context.get("threadinfo_responses")
588 self.assertIsNotNone(threadinfo_responses)
589
590 thread_ids = []
591 for threadinfo_response in threadinfo_responses:
592 new_thread_infos = parse_threadinfo_response(threadinfo_response)
593 thread_ids.extend(new_thread_infos)
594 return thread_ids
595
596 def wait_for_thread_count(self, thread_count, timeout_seconds=3):
597 start_time = time.time()
598 timeout_time = start_time + timeout_seconds
599
600 actual_thread_count = 0
601 while actual_thread_count < thread_count:
602 self.reset_test_sequence()
603 self.add_threadinfo_collection_packets()
604
605 context = self.expect_gdbremote_sequence()
606 self.assertIsNotNone(context)
607
608 threads = self.parse_threadinfo_packets(context)
609 self.assertIsNotNone(threads)
610
611 actual_thread_count = len(threads)
612
613 if time.time() > timeout_time:
614 raise Exception(
615 'timed out after {} seconds while waiting for theads: waiting for at least {} threads, found {}'.format(
616 timeout_seconds, thread_count, actual_thread_count))
617
618 return threads
619
620 def add_set_breakpoint_packets(self, address, do_continue=True, breakpoint_kind=1):
621 self.test_sequence.add_log_lines(
622 [# Set the breakpoint.
623 "read packet: $Z0,{0:x},{1}#00".format(address, breakpoint_kind),
624 # Verify the stub could set it.
625 "send packet: $OK#00",
626 ], True)
627
628 if (do_continue):
629 self.test_sequence.add_log_lines(
630 [# Continue the inferior.
Stephane Sezer22ed42e2014-11-13 21:39:24 +0000631 "read packet: $c#63",
Todd Fialae50b2e42014-06-13 19:11:33 +0000632 # Expect a breakpoint stop report.
633 {"direction":"send", "regex":r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);", "capture":{1:"stop_signo", 2:"stop_thread_id"} },
634 ], True)
635
636 def add_remove_breakpoint_packets(self, address, breakpoint_kind=1):
637 self.test_sequence.add_log_lines(
638 [# Remove the breakpoint.
639 "read packet: $z0,{0:x},{1}#00".format(address, breakpoint_kind),
640 # Verify the stub could unset it.
641 "send packet: $OK#00",
642 ], True)
643
644 def add_qSupported_packets(self):
645 self.test_sequence.add_log_lines(
646 ["read packet: $qSupported#00",
647 {"direction":"send", "regex":r"^\$(.*)#[0-9a-fA-F]{2}", "capture":{1: "qSupported_response"}},
648 ], True)
649
650 _KNOWN_QSUPPORTED_STUB_FEATURES = [
651 "augmented-libraries-svr4-read",
652 "PacketSize",
653 "QStartNoAckMode",
Todd Fiala8aae4f42014-06-13 23:34:17 +0000654 "QThreadSuffixSupported",
Todd Fiala43ab82c2014-06-15 23:33:09 +0000655 "QListThreadsInStopReply",
Todd Fialae50b2e42014-06-13 19:11:33 +0000656 "qXfer:auxv:read",
657 "qXfer:libraries:read",
658 "qXfer:libraries-svr4:read",
659 ]
660
661 def parse_qSupported_response(self, context):
662 self.assertIsNotNone(context)
663
664 raw_response = context.get("qSupported_response")
665 self.assertIsNotNone(raw_response)
666
667 # For values with key=val, the dict key and vals are set as expected. For feature+, feature- and feature?, the
668 # +,-,? is stripped from the key and set as the value.
669 supported_dict = {}
670 for match in re.finditer(r";?([^=;]+)(=([^;]+))?", raw_response):
671 key = match.group(1)
672 val = match.group(3)
673
674 # key=val: store as is
675 if val and len(val) > 0:
676 supported_dict[key] = val
677 else:
678 if len(key) < 2:
679 raise Exception("singular stub feature is too short: must be stub_feature{+,-,?}")
680 supported_type = key[-1]
681 key = key[:-1]
682 if not supported_type in ["+", "-", "?"]:
683 raise Exception("malformed stub feature: final character {} not in expected set (+,-,?)".format(supported_type))
684 supported_dict[key] = supported_type
685 # Ensure we know the supported element
686 if not key in self._KNOWN_QSUPPORTED_STUB_FEATURES:
687 raise Exception("unknown qSupported stub feature reported: %s" % key)
688
689 return supported_dict
690
691 def run_process_then_stop(self, run_seconds=1):
692 # Tell the stub to continue.
693 self.test_sequence.add_log_lines(
Stephane Sezerb6e81922014-11-20 18:50:46 +0000694 ["read packet: $vCont;c#a8"],
Todd Fialae50b2e42014-06-13 19:11:33 +0000695 True)
696 context = self.expect_gdbremote_sequence()
697
698 # Wait for run_seconds.
699 time.sleep(run_seconds)
700
701 # Send an interrupt, capture a T response.
702 self.reset_test_sequence()
703 self.test_sequence.add_log_lines(
704 ["read packet: {}".format(chr(03)),
705 {"direction":"send", "regex":r"^\$T([0-9a-fA-F]+)([^#]+)#[0-9a-fA-F]{2}$", "capture":{1:"stop_result"} }],
706 True)
707 context = self.expect_gdbremote_sequence()
708 self.assertIsNotNone(context)
709 self.assertIsNotNone(context.get("stop_result"))
710
711 return context
712
713 def select_modifiable_register(self, reg_infos):
714 """Find a register that can be read/written freely."""
715 PREFERRED_REGISTER_NAMES = sets.Set(["rax",])
716
717 # First check for the first register from the preferred register name set.
718 alternative_register_index = None
719
720 self.assertIsNotNone(reg_infos)
721 for reg_info in reg_infos:
722 if ("name" in reg_info) and (reg_info["name"] in PREFERRED_REGISTER_NAMES):
723 # We found a preferred register. Use it.
724 return reg_info["lldb_register_index"]
725 if ("generic" in reg_info) and (reg_info["generic"] == "fp"):
726 # A frame pointer register will do as a register to modify temporarily.
727 alternative_register_index = reg_info["lldb_register_index"]
728
729 # We didn't find a preferred register. Return whatever alternative register
730 # we found, if any.
731 return alternative_register_index
732
733 def extract_registers_from_stop_notification(self, stop_key_vals_text):
734 self.assertIsNotNone(stop_key_vals_text)
735 kv_dict = self.parse_key_val_dict(stop_key_vals_text)
736
737 registers = {}
738 for (key, val) in kv_dict.items():
Stephane Sezer5109a792014-11-14 09:46:21 +0000739 if re.match(r"^[0-9a-fA-F]+$", key):
Todd Fialae50b2e42014-06-13 19:11:33 +0000740 registers[int(key, 16)] = val
741 return registers
742
743 def gather_register_infos(self):
744 self.reset_test_sequence()
745 self.add_register_info_collection_packets()
746
747 context = self.expect_gdbremote_sequence()
748 self.assertIsNotNone(context)
749
750 reg_infos = self.parse_register_info_packets(context)
751 self.assertIsNotNone(reg_infos)
752 self.add_lldb_register_index(reg_infos)
753
754 return reg_infos
755
756 def find_generic_register_with_name(self, reg_infos, generic_name):
757 self.assertIsNotNone(reg_infos)
758 for reg_info in reg_infos:
759 if ("generic" in reg_info) and (reg_info["generic"] == generic_name):
760 return reg_info
761 return None
762
Todd Fiala8d7ab8c2014-06-17 16:04:45 +0000763 def decode_gdbremote_binary(self, encoded_bytes):
764 decoded_bytes = ""
765 i = 0
766 while i < len(encoded_bytes):
767 if encoded_bytes[i] == "}":
768 # Handle escaped char.
769 self.assertTrue(i + 1 < len(encoded_bytes))
770 decoded_bytes += chr(ord(encoded_bytes[i+1]) ^ 0x20)
771 i +=2
772 elif encoded_bytes[i] == "*":
773 # Handle run length encoding.
774 self.assertTrue(len(decoded_bytes) > 0)
775 self.assertTrue(i + 1 < len(encoded_bytes))
776 repeat_count = ord(encoded_bytes[i+1]) - 29
777 decoded_bytes += decoded_bytes[-1] * repeat_count
778 i += 2
779 else:
780 decoded_bytes += encoded_bytes[i]
781 i += 1
782 return decoded_bytes
783
784 def build_auxv_dict(self, endian, word_size, auxv_data):
785 self.assertIsNotNone(endian)
786 self.assertIsNotNone(word_size)
787 self.assertIsNotNone(auxv_data)
788
789 auxv_dict = {}
790
791 while len(auxv_data) > 0:
792 # Chop off key.
793 raw_key = auxv_data[:word_size]
794 auxv_data = auxv_data[word_size:]
795
796 # Chop of value.
797 raw_value = auxv_data[:word_size]
798 auxv_data = auxv_data[word_size:]
799
800 # Convert raw text from target endian.
801 key = unpack_endian_binary_string(endian, raw_key)
802 value = unpack_endian_binary_string(endian, raw_value)
803
804 # Handle ending entry.
805 if key == 0:
806 self.assertEquals(value, 0)
807 return auxv_dict
808
809 # The key should not already be present.
810 self.assertFalse(key in auxv_dict)
811 auxv_dict[key] = value
812
813 self.fail("should not reach here - implies required double zero entry not found")
814 return auxv_dict
Todd Fiala51886732014-06-17 22:01:27 +0000815
816 def read_binary_data_in_chunks(self, command_prefix, chunk_length):
817 """Collect command_prefix{offset:x},{chunk_length:x} until a single 'l' or 'l' with data is returned."""
818 offset = 0
819 done = False
820 decoded_data = ""
821
822 while not done:
823 # Grab the next iteration of data.
824 self.reset_test_sequence()
825 self.test_sequence.add_log_lines([
826 "read packet: ${}{:x},{:x}:#00".format(command_prefix, offset, chunk_length),
Todd Fiala4c24eba2014-06-19 17:35:40 +0000827 {"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 +0000828 ], True)
829
830 context = self.expect_gdbremote_sequence()
831 self.assertIsNotNone(context)
832
833 response_type = context.get("response_type")
834 self.assertIsNotNone(response_type)
835 self.assertTrue(response_type in ["l", "m"])
836
837 # Move offset along.
838 offset += chunk_length
839
840 # Figure out if we're done. We're done if the response type is l.
841 done = response_type == "l"
842
843 # Decode binary data.
844 content_raw = context.get("content_raw")
845 if content_raw and len(content_raw) > 0:
846 self.assertIsNotNone(content_raw)
847 decoded_data += self.decode_gdbremote_binary(content_raw)
848 return decoded_data
Todd Fiala4c24eba2014-06-19 17:35:40 +0000849
850 def add_interrupt_packets(self):
851 self.test_sequence.add_log_lines([
852 # Send the intterupt.
853 "read packet: {}".format(chr(03)),
854 # And wait for the stop notification.
855 {"direction":"send", "regex":r"^\$T([0-9a-fA-F]{2})(.*)#[0-9a-fA-F]{2}$", "capture":{1:"stop_signo", 2:"stop_key_val_text" } },
856 ], True)
857
858 def parse_interrupt_packets(self, context):
859 self.assertIsNotNone(context.get("stop_signo"))
860 self.assertIsNotNone(context.get("stop_key_val_text"))
Todd Fiala9846d452014-06-20 17:39:24 +0000861 return (int(context["stop_signo"], 16), self.parse_key_val_dict(context["stop_key_val_text"]))
862
863 def add_QSaveRegisterState_packets(self, thread_id):
864 if thread_id:
865 # Use the thread suffix form.
866 request = "read packet: $QSaveRegisterState;thread:{:x}#00".format(thread_id)
867 else:
868 request = "read packet: $QSaveRegisterState#00"
869
870 self.test_sequence.add_log_lines([
871 request,
872 {"direction":"send", "regex":r"^\$(E?.*)#[0-9a-fA-F]{2}$", "capture":{1:"save_response" } },
873 ], True)
874
875 def parse_QSaveRegisterState_response(self, context):
876 self.assertIsNotNone(context)
877
878 save_response = context.get("save_response")
879 self.assertIsNotNone(save_response)
880
881 if len(save_response) < 1 or save_response[0] == "E":
882 # error received
883 return (False, None)
884 else:
885 return (True, int(save_response))
886
887 def add_QRestoreRegisterState_packets(self, save_id, thread_id=None):
888 if thread_id:
889 # Use the thread suffix form.
890 request = "read packet: $QRestoreRegisterState:{};thread:{:x}#00".format(save_id, thread_id)
891 else:
892 request = "read packet: $QRestoreRegisterState:{}#00".format(save_id)
893
894 self.test_sequence.add_log_lines([
895 request,
896 "send packet: $OK#00"
897 ], True)
898
899 def flip_all_bits_in_each_register_value(self, reg_infos, endian, thread_id=None):
900 self.assertIsNotNone(reg_infos)
901
902 successful_writes = 0
903 failed_writes = 0
904
905 for reg_info in reg_infos:
906 # Use the lldb register index added to the reg info. We're not necessarily
907 # working off a full set of register infos, so an inferred register index could be wrong.
908 reg_index = reg_info["lldb_register_index"]
909 self.assertIsNotNone(reg_index)
910
911 reg_byte_size = int(reg_info["bitsize"])/8
912 self.assertTrue(reg_byte_size > 0)
913
914 # Handle thread suffix.
915 if thread_id:
916 p_request = "read packet: $p{:x};thread:{:x}#00".format(reg_index, thread_id)
917 else:
918 p_request = "read packet: $p{:x}#00".format(reg_index)
919
920 # Read the existing value.
921 self.reset_test_sequence()
922 self.test_sequence.add_log_lines([
923 p_request,
924 { "direction":"send", "regex":r"^\$([0-9a-fA-F]+)#", "capture":{1:"p_response"} },
925 ], True)
926 context = self.expect_gdbremote_sequence()
927 self.assertIsNotNone(context)
928
929 # Verify the response length.
930 p_response = context.get("p_response")
931 self.assertIsNotNone(p_response)
932 initial_reg_value = unpack_register_hex_unsigned(endian, p_response)
933
934 # Flip the value by xoring with all 1s
935 all_one_bits_raw = "ff" * (int(reg_info["bitsize"]) / 8)
936 flipped_bits_int = initial_reg_value ^ int(all_one_bits_raw, 16)
937 # 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)
938
939 # Handle thread suffix for P.
940 if thread_id:
941 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)
942 else:
943 P_request = "read packet: $P{:x}={}#00".format(reg_index, pack_register_hex(endian, flipped_bits_int, byte_size=reg_byte_size))
944
945 # Write the flipped value to the register.
946 self.reset_test_sequence()
947 self.test_sequence.add_log_lines([
948 P_request,
949 { "direction":"send", "regex":r"^\$(OK|E[0-9a-fA-F]+)#[0-9a-fA-F]{2}", "capture":{1:"P_response"} },
950 ], True)
951 context = self.expect_gdbremote_sequence()
952 self.assertIsNotNone(context)
953
954 # Determine if the write succeeded. There are a handful of registers that can fail, or partially fail
955 # (e.g. flags, segment selectors, etc.) due to register value restrictions. Don't worry about them
956 # all flipping perfectly.
957 P_response = context.get("P_response")
958 self.assertIsNotNone(P_response)
959 if P_response == "OK":
960 successful_writes += 1
961 else:
962 failed_writes += 1
963 # print "reg (index={}, name={}) write FAILED (error: {})".format(reg_index, reg_info["name"], P_response)
964
965 # Read back the register value, ensure it matches the flipped value.
966 if P_response == "OK":
967 self.reset_test_sequence()
968 self.test_sequence.add_log_lines([
969 p_request,
970 { "direction":"send", "regex":r"^\$([0-9a-fA-F]+)#", "capture":{1:"p_response"} },
971 ], True)
972 context = self.expect_gdbremote_sequence()
973 self.assertIsNotNone(context)
974
975 verify_p_response_raw = context.get("p_response")
976 self.assertIsNotNone(verify_p_response_raw)
977 verify_bits = unpack_register_hex_unsigned(endian, verify_p_response_raw)
978
979 if verify_bits != flipped_bits_int:
980 # Some registers, like mxcsrmask and others, will permute what's written. Adjust succeed/fail counts.
981 # print "reg (index={}, name={}): read verify FAILED: wrote {:x}, verify read back {:x}".format(reg_index, reg_info["name"], flipped_bits_int, verify_bits)
982 successful_writes -= 1
983 failed_writes +=1
984
985 return (successful_writes, failed_writes)
986
987 def is_bit_flippable_register(self, reg_info):
988 if not reg_info:
989 return False
990 if not "set" in reg_info:
991 return False
992 if reg_info["set"] != "General Purpose Registers":
993 return False
994 if ("container-regs" in reg_info) and (len(reg_info["container-regs"]) > 0):
995 # Don't try to bit flip registers contained in another register.
996 return False
997 if re.match("^.s$", reg_info["name"]):
998 # This is a 2-letter register name that ends in "s", like a segment register.
999 # Don't try to bit flip these.
1000 return False
1001 # Okay, this looks fine-enough.
1002 return True
1003
1004 def read_register_values(self, reg_infos, endian, thread_id=None):
1005 self.assertIsNotNone(reg_infos)
1006 values = {}
1007
1008 for reg_info in reg_infos:
1009 # We append a register index when load reg infos so we can work with subsets.
1010 reg_index = reg_info.get("lldb_register_index")
1011 self.assertIsNotNone(reg_index)
1012
1013 # Handle thread suffix.
1014 if thread_id:
1015 p_request = "read packet: $p{:x};thread:{:x}#00".format(reg_index, thread_id)
1016 else:
1017 p_request = "read packet: $p{:x}#00".format(reg_index)
1018
1019 # Read it with p.
1020 self.reset_test_sequence()
1021 self.test_sequence.add_log_lines([
1022 p_request,
1023 { "direction":"send", "regex":r"^\$([0-9a-fA-F]+)#", "capture":{1:"p_response"} },
1024 ], True)
1025 context = self.expect_gdbremote_sequence()
1026 self.assertIsNotNone(context)
1027
1028 # Convert value from target endian to integral.
1029 p_response = context.get("p_response")
1030 self.assertIsNotNone(p_response)
1031 self.assertTrue(len(p_response) > 0)
1032 self.assertFalse(p_response[0] == "E")
1033
1034 values[reg_index] = unpack_register_hex_unsigned(endian, p_response)
1035
Todd Fialae2202002014-06-27 22:11:56 +00001036 return values
1037
1038 def add_vCont_query_packets(self):
1039 self.test_sequence.add_log_lines([
Stephane Sezer22ed42e2014-11-13 21:39:24 +00001040 "read packet: $vCont?#49",
Todd Fialae2202002014-06-27 22:11:56 +00001041 {"direction":"send", "regex":r"^\$(vCont)?(.*)#[0-9a-fA-F]{2}$", "capture":{2:"vCont_query_response" } },
1042 ], True)
1043
1044 def parse_vCont_query_response(self, context):
1045 self.assertIsNotNone(context)
1046 vCont_query_response = context.get("vCont_query_response")
1047
1048 # Handle case of no vCont support at all - in which case the capture group will be none or zero length.
1049 if not vCont_query_response or len(vCont_query_response) == 0:
1050 return {}
1051
1052 return {key:1 for key in vCont_query_response.split(";") if key and len(key) > 0}
1053
1054 def count_single_steps_until_true(self, thread_id, predicate, args, max_step_count=100, use_Hc_packet=True, step_instruction="s"):
1055 """Used by single step test that appears in a few different contexts."""
1056 single_step_count = 0
1057
1058 while single_step_count < max_step_count:
1059 self.assertIsNotNone(thread_id)
1060
1061 # Build the packet for the single step instruction. We replace {thread}, if present, with the thread_id.
1062 step_packet = "read packet: ${}#00".format(re.sub(r"{thread}", "{:x}".format(thread_id), step_instruction))
1063 # print "\nstep_packet created: {}\n".format(step_packet)
1064
1065 # Single step.
1066 self.reset_test_sequence()
1067 if use_Hc_packet:
1068 self.test_sequence.add_log_lines(
1069 [# Set the continue thread.
1070 "read packet: $Hc{0:x}#00".format(thread_id),
1071 "send packet: $OK#00",
1072 ], True)
1073 self.test_sequence.add_log_lines([
1074 # Single step.
1075 step_packet,
1076 # "read packet: $vCont;s:{0:x}#00".format(thread_id),
1077 # Expect a breakpoint stop report.
1078 {"direction":"send", "regex":r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);", "capture":{1:"stop_signo", 2:"stop_thread_id"} },
1079 ], True)
1080 context = self.expect_gdbremote_sequence()
1081 self.assertIsNotNone(context)
1082 self.assertIsNotNone(context.get("stop_signo"))
1083 self.assertEquals(int(context.get("stop_signo"), 16), signal.SIGTRAP)
1084
1085 single_step_count += 1
1086
1087 # See if the predicate is true. If so, we're done.
1088 if predicate(args):
1089 return (True, single_step_count)
1090
1091 # The predicate didn't return true within the runaway step count.
1092 return (False, single_step_count)
1093
1094 def g_c1_c2_contents_are(self, args):
1095 """Used by single step test that appears in a few different contexts."""
1096 g_c1_address = args["g_c1_address"]
1097 g_c2_address = args["g_c2_address"]
1098 expected_g_c1 = args["expected_g_c1"]
1099 expected_g_c2 = args["expected_g_c2"]
1100
1101 # Read g_c1 and g_c2 contents.
1102 self.reset_test_sequence()
1103 self.test_sequence.add_log_lines(
1104 ["read packet: $m{0:x},{1:x}#00".format(g_c1_address, 1),
1105 {"direction":"send", "regex":r"^\$(.+)#[0-9a-fA-F]{2}$", "capture":{1:"g_c1_contents"} },
1106 "read packet: $m{0:x},{1:x}#00".format(g_c2_address, 1),
1107 {"direction":"send", "regex":r"^\$(.+)#[0-9a-fA-F]{2}$", "capture":{1:"g_c2_contents"} }],
1108 True)
1109
1110 # Run the packet stream.
1111 context = self.expect_gdbremote_sequence()
1112 self.assertIsNotNone(context)
1113
1114 # Check if what we read from inferior memory is what we are expecting.
1115 self.assertIsNotNone(context.get("g_c1_contents"))
1116 self.assertIsNotNone(context.get("g_c2_contents"))
1117
1118 return (context.get("g_c1_contents").decode("hex") == expected_g_c1) and (context.get("g_c2_contents").decode("hex") == expected_g_c2)
1119
1120 def single_step_only_steps_one_instruction(self, use_Hc_packet=True, step_instruction="s"):
1121 """Used by single step test that appears in a few different contexts."""
1122 # Start up the inferior.
1123 procs = self.prep_debug_monitor_and_inferior(
1124 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"])
1125
1126 # Run the process
1127 self.test_sequence.add_log_lines(
1128 [# Start running after initial stop.
Stephane Sezer22ed42e2014-11-13 21:39:24 +00001129 "read packet: $c#63",
Todd Fialae2202002014-06-27 22:11:56 +00001130 # Match output line that prints the memory address of the function call entry point.
1131 # Note we require launch-only testing so we can get inferior otuput.
1132 { "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$",
1133 "capture":{ 1:"function_address", 2:"g_c1_address", 3:"g_c2_address"} },
1134 # Now stop the inferior.
1135 "read packet: {}".format(chr(03)),
1136 # And wait for the stop notification.
1137 {"direction":"send", "regex":r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);", "capture":{1:"stop_signo", 2:"stop_thread_id"} }],
1138 True)
1139
1140 # Run the packet stream.
1141 context = self.expect_gdbremote_sequence()
1142 self.assertIsNotNone(context)
1143
1144 # Grab the main thread id.
1145 self.assertIsNotNone(context.get("stop_thread_id"))
1146 main_thread_id = int(context.get("stop_thread_id"), 16)
1147
1148 # Grab the function address.
1149 self.assertIsNotNone(context.get("function_address"))
1150 function_address = int(context.get("function_address"), 16)
1151
1152 # Grab the data addresses.
1153 self.assertIsNotNone(context.get("g_c1_address"))
1154 g_c1_address = int(context.get("g_c1_address"), 16)
1155
1156 self.assertIsNotNone(context.get("g_c2_address"))
1157 g_c2_address = int(context.get("g_c2_address"), 16)
1158
1159 # Set a breakpoint at the given address.
1160 # Note this might need to be switched per platform (ARM, mips, etc.).
1161 BREAKPOINT_KIND = 1
1162 self.reset_test_sequence()
1163 self.add_set_breakpoint_packets(function_address, do_continue=True, breakpoint_kind=BREAKPOINT_KIND)
1164 context = self.expect_gdbremote_sequence()
1165 self.assertIsNotNone(context)
1166
1167 # Remove the breakpoint.
1168 self.reset_test_sequence()
1169 self.add_remove_breakpoint_packets(function_address, breakpoint_kind=BREAKPOINT_KIND)
1170 context = self.expect_gdbremote_sequence()
1171 self.assertIsNotNone(context)
1172
1173 # Verify g_c1 and g_c2 match expected initial state.
1174 args = {}
1175 args["g_c1_address"] = g_c1_address
1176 args["g_c2_address"] = g_c2_address
1177 args["expected_g_c1"] = "0"
1178 args["expected_g_c2"] = "1"
1179
1180 self.assertTrue(self.g_c1_c2_contents_are(args))
1181
1182 # Verify we take only a small number of steps to hit the first state. Might need to work through function entry prologue code.
1183 args["expected_g_c1"] = "1"
1184 args["expected_g_c2"] = "1"
1185 (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)
1186 self.assertTrue(state_reached)
1187
1188 # Verify we hit the next state.
1189 args["expected_g_c1"] = "1"
1190 args["expected_g_c2"] = "0"
1191 (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)
1192 self.assertTrue(state_reached)
1193 self.assertEquals(step_count, 1)
1194
1195 # Verify we hit the next state.
1196 args["expected_g_c1"] = "0"
1197 args["expected_g_c2"] = "0"
1198 (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)
1199 self.assertTrue(state_reached)
1200 self.assertEquals(step_count, 1)
1201
1202 # Verify we hit the next state.
1203 args["expected_g_c1"] = "0"
1204 args["expected_g_c2"] = "1"
1205 (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)
1206 self.assertTrue(state_reached)
1207 self.assertEquals(step_count, 1)
Todd Fialaaf245d12014-06-30 21:05:18 +00001208