blob: 83af78124fc8066819dc8707ea9fa17342008a13 [file] [log] [blame]
Greg Claytone2841632012-01-26 02:56:24 +00001#!/usr/bin/python
2
3#----------------------------------------------------------------------
4# This module will enable GDB remote packet logging when the
5# 'start_gdb_log' command is called with a filename to log to. When the
6# 'stop_gdb_log' command is called, it will disable the logging and
7# print out statistics about how long commands took to execute and also
8# will primnt ou
9# Be sure to add the python path that points to the LLDB shared library.
10#
11# To use this in the embedded python interpreter using "lldb" just
12# import it with the full path using the "command script import"
13# command. This can be done from the LLDB command line:
14# (lldb) command script import /path/to/gdbremote.py
15# Or it can be added to your ~/.lldbinit file so this module is always
16# available.
17#----------------------------------------------------------------------
18
19import commands
Greg Clayton25f82aa2015-05-22 23:00:59 +000020import math
Greg Claytone2841632012-01-26 02:56:24 +000021import optparse
22import os
Greg Claytone2841632012-01-26 02:56:24 +000023import re
Greg Clayton8ebb9a82012-06-01 20:23:54 +000024import shlex
25import string
26import sys
Greg Claytone2841632012-01-26 02:56:24 +000027import tempfile
28
Greg Claytonf51a23f2012-06-04 23:22:17 +000029#----------------------------------------------------------------------
30# Global variables
31#----------------------------------------------------------------------
32g_log_file = ''
33g_byte_order = 'little'
34
Greg Clayton8ebb9a82012-06-01 20:23:54 +000035class TerminalColors:
36 '''Simple terminal colors class'''
Greg Claytonf51a23f2012-06-04 23:22:17 +000037 def __init__(self, enabled = True):
Greg Clayton8ebb9a82012-06-01 20:23:54 +000038 # TODO: discover terminal type from "file" and disable if
39 # it can't handle the color codes
40 self.enabled = enabled
41
42 def reset(self):
43 '''Reset all terminal colors and formatting.'''
44 if self.enabled:
Greg Claytonf51a23f2012-06-04 23:22:17 +000045 return "\x1b[0m";
46 return ''
Greg Clayton8ebb9a82012-06-01 20:23:54 +000047
48 def bold(self, on = True):
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000049 '''Enable or disable bold depending on the "on" parameter.'''
Greg Clayton8ebb9a82012-06-01 20:23:54 +000050 if self.enabled:
51 if on:
Greg Claytonf51a23f2012-06-04 23:22:17 +000052 return "\x1b[1m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +000053 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +000054 return "\x1b[22m";
55 return ''
56
Greg Clayton8ebb9a82012-06-01 20:23:54 +000057 def italics(self, on = True):
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000058 '''Enable or disable italics depending on the "on" parameter.'''
Greg Clayton8ebb9a82012-06-01 20:23:54 +000059 if self.enabled:
60 if on:
Greg Claytonf51a23f2012-06-04 23:22:17 +000061 return "\x1b[3m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +000062 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +000063 return "\x1b[23m";
64 return ''
65
Greg Clayton8ebb9a82012-06-01 20:23:54 +000066 def underline(self, on = True):
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000067 '''Enable or disable underline depending on the "on" parameter.'''
Greg Clayton8ebb9a82012-06-01 20:23:54 +000068 if self.enabled:
69 if on:
Greg Claytonf51a23f2012-06-04 23:22:17 +000070 return "\x1b[4m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +000071 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +000072 return "\x1b[24m";
73 return ''
74
Greg Clayton8ebb9a82012-06-01 20:23:54 +000075 def inverse(self, on = True):
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000076 '''Enable or disable inverse depending on the "on" parameter.'''
Greg Clayton8ebb9a82012-06-01 20:23:54 +000077 if self.enabled:
78 if on:
Greg Claytonf51a23f2012-06-04 23:22:17 +000079 return "\x1b[7m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +000080 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +000081 return "\x1b[27m";
82 return ''
83
Greg Clayton8ebb9a82012-06-01 20:23:54 +000084 def strike(self, on = True):
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000085 '''Enable or disable strike through depending on the "on" parameter.'''
Greg Clayton8ebb9a82012-06-01 20:23:54 +000086 if self.enabled:
87 if on:
Greg Claytonf51a23f2012-06-04 23:22:17 +000088 return "\x1b[9m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +000089 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +000090 return "\x1b[29m";
91 return ''
92
Greg Clayton8ebb9a82012-06-01 20:23:54 +000093 def black(self, fg = True):
94 '''Set the foreground or background color to black.
95 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
96 if self.enabled:
97 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +000098 return "\x1b[30m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +000099 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000100 return "\x1b[40m";
101 return ''
102
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000103 def red(self, fg = True):
104 '''Set the foreground or background color to red.
105 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
106 if self.enabled:
107 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000108 return "\x1b[31m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000109 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000110 return "\x1b[41m";
111 return ''
112
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000113 def green(self, fg = True):
114 '''Set the foreground or background color to green.
115 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
116 if self.enabled:
117 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000118 return "\x1b[32m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000119 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000120 return "\x1b[42m";
121 return ''
122
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000123 def yellow(self, fg = True):
124 '''Set the foreground or background color to yellow.
125 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
126 if self.enabled:
127 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000128 return "\x1b[43m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000129 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000130 return "\x1b[33m";
131 return ''
132
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000133 def blue(self, fg = True):
134 '''Set the foreground or background color to blue.
135 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
136 if self.enabled:
137 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000138 return "\x1b[34m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000139 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000140 return "\x1b[44m";
141 return ''
142
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000143 def magenta(self, fg = True):
144 '''Set the foreground or background color to magenta.
145 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
146 if self.enabled:
147 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000148 return "\x1b[35m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000149 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000150 return "\x1b[45m";
151 return ''
152
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000153 def cyan(self, fg = True):
154 '''Set the foreground or background color to cyan.
155 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
156 if self.enabled:
157 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000158 return "\x1b[36m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000159 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000160 return "\x1b[46m";
161 return ''
162
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000163 def white(self, fg = True):
164 '''Set the foreground or background color to white.
165 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
166 if self.enabled:
167 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000168 return "\x1b[37m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000169 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000170 return "\x1b[47m";
171 return ''
172
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000173 def default(self, fg = True):
174 '''Set the foreground or background color to the default.
175 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
176 if self.enabled:
177 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000178 return "\x1b[39m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000179 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000180 return "\x1b[49m";
181 return ''
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000182
Greg Claytone2841632012-01-26 02:56:24 +0000183
184def start_gdb_log(debugger, command, result, dict):
185 '''Start logging GDB remote packets by enabling logging with timestamps and
186 thread safe logging. Follow a call to this function with a call to "stop_gdb_log"
187 in order to dump out the commands.'''
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000188 global g_log_file
Greg Claytone2841632012-01-26 02:56:24 +0000189 command_args = shlex.split(command)
190 usage = "usage: start_gdb_log [options] [<LOGFILEPATH>]"
191 description='''The command enables GDB remote packet logging with timestamps. The packets will be logged to <LOGFILEPATH> if supplied, or a temporary file will be used. Logging stops when stop_gdb_log is called and the packet times will
192 be aggregated and displayed.'''
193 parser = optparse.OptionParser(description=description, prog='start_gdb_log',usage=usage)
194 parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
195 try:
196 (options, args) = parser.parse_args(command_args)
197 except:
198 return
199
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000200 if g_log_file:
201 result.PutCString ('error: logging is already in progress with file "%s"', g_log_file)
Greg Claytone2841632012-01-26 02:56:24 +0000202 else:
203 args_len = len(args)
204 if args_len == 0:
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000205 g_log_file = tempfile.mktemp()
Greg Claytone2841632012-01-26 02:56:24 +0000206 elif len(args) == 1:
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000207 g_log_file = args[0]
Greg Claytone2841632012-01-26 02:56:24 +0000208
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000209 if g_log_file:
210 debugger.HandleCommand('log enable --threadsafe --timestamp --file "%s" gdb-remote packets' % g_log_file);
211 result.PutCString ("GDB packet logging enable with log file '%s'\nUse the 'stop_gdb_log' command to stop logging and show packet statistics." % g_log_file)
Greg Claytone2841632012-01-26 02:56:24 +0000212 return
213
214 result.PutCString ('error: invalid log file path')
215 result.PutCString (usage)
216
217def stop_gdb_log(debugger, command, result, dict):
218 '''Stop logging GDB remote packets to the file that was specified in a call
219 to "start_gdb_log" and normalize the timestamps to be relative to the first
220 timestamp in the log file. Also print out statistics for how long each
221 command took to allow performance bottlenecks to be determined.'''
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000222 global g_log_file
Greg Claytone2841632012-01-26 02:56:24 +0000223 # Any commands whose names might be followed by more valid C identifier
224 # characters must be listed here
225 command_args = shlex.split(command)
226 usage = "usage: stop_gdb_log [options]"
227 description='''The command stops a previously enabled GDB remote packet logging command. Packet logging must have been previously enabled with a call to start_gdb_log.'''
228 parser = optparse.OptionParser(description=description, prog='stop_gdb_log',usage=usage)
229 parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
230 parser.add_option('-q', '--quiet', action='store_true', dest='quiet', help='display verbose debug info', default=False)
Greg Claytonf51a23f2012-06-04 23:22:17 +0000231 parser.add_option('-C', '--color', action='store_true', dest='color', help='add terminal colors', default=False)
Jim Inghamd95752f2012-03-01 18:57:51 +0000232 parser.add_option('-c', '--sort-by-count', action='store_true', dest='sort_count', help='display verbose debug info', default=False)
Greg Claytonf51a23f2012-06-04 23:22:17 +0000233 parser.add_option('-s', '--symbolicate', action='store_true', dest='symbolicate', help='symbolicate addresses in log using current "lldb.target"', default=False)
Greg Claytone2841632012-01-26 02:56:24 +0000234 try:
235 (options, args) = parser.parse_args(command_args)
236 except:
237 return
Greg Claytonf51a23f2012-06-04 23:22:17 +0000238 options.colors = TerminalColors(options.color)
239 options.symbolicator = None
240 if options.symbolicate:
241 if lldb.target:
242 import lldb.utils.symbolication
243 options.symbolicator = lldb.utils.symbolication.Symbolicator()
244 options.symbolicator.target = lldb.target
245 else:
246 print "error: can't symbolicate without a target"
Greg Claytone2841632012-01-26 02:56:24 +0000247
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000248 if not g_log_file:
Greg Claytone2841632012-01-26 02:56:24 +0000249 result.PutCString ('error: logging must have been previously enabled with a call to "stop_gdb_log"')
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000250 elif os.path.exists (g_log_file):
Greg Claytone2841632012-01-26 02:56:24 +0000251 if len(args) == 0:
252 debugger.HandleCommand('log disable gdb-remote packets');
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000253 result.PutCString ("GDB packet logging disabled. Logged packets are in '%s'" % g_log_file)
254 parse_gdb_log_file (g_log_file, options)
Greg Claytone2841632012-01-26 02:56:24 +0000255 else:
256 result.PutCString (usage)
257 else:
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000258 print 'error: the GDB packet log file "%s" does not exist' % g_log_file
Greg Claytone2841632012-01-26 02:56:24 +0000259
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000260def is_hex_byte(str):
261 if len(str) == 2:
262 return str[0] in string.hexdigits and str[1] in string.hexdigits;
263 return False
264
265# global register info list
266g_register_infos = list()
267g_max_register_info_name_len = 0
268
269class RegisterInfo:
270 """Class that represents register information"""
271 def __init__(self, kvp):
272 self.info = dict()
273 for kv in kvp:
274 key = kv[0]
275 value = kv[1]
276 self.info[key] = value
277 def name(self):
278 '''Get the name of the register.'''
279 if self.info and 'name' in self.info:
280 return self.info['name']
281 return None
282
283 def bit_size(self):
284 '''Get the size in bits of the register.'''
285 if self.info and 'bitsize' in self.info:
286 return int(self.info['bitsize'])
287 return 0
288
289 def byte_size(self):
290 '''Get the size in bytes of the register.'''
291 return self.bit_size() / 8
292
293 def get_value_from_hex_string(self, hex_str):
294 '''Dump the register value given a native byte order encoded hex ASCII byte string.'''
295 encoding = self.info['encoding']
296 bit_size = self.bit_size()
297 packet = Packet(hex_str)
298 if encoding == 'uint':
299 uval = packet.get_hex_uint(g_byte_order)
300 if bit_size == 8:
301 return '0x%2.2x' % (uval)
302 elif bit_size == 16:
303 return '0x%4.4x' % (uval)
304 elif bit_size == 32:
305 return '0x%8.8x' % (uval)
306 elif bit_size == 64:
307 return '0x%16.16x' % (uval)
308 bytes = list();
309 uval = packet.get_hex_uint8()
310 while uval != None:
311 bytes.append(uval)
312 uval = packet.get_hex_uint8()
313 value_str = '0x'
314 if g_byte_order == 'little':
315 bytes.reverse()
316 for byte in bytes:
317 value_str += '%2.2x' % byte
318 return '%s' % (value_str)
319
320 def __str__(self):
321 '''Dump the register info key/value pairs'''
322 s = ''
323 for key in self.info.keys():
324 if s:
325 s += ', '
326 s += "%s=%s " % (key, self.info[key])
327 return s
328
329class Packet:
330 """Class that represents a packet that contains string data"""
331 def __init__(self, packet_str):
332 self.str = packet_str
333
334 def peek_char(self):
335 ch = 0
336 if self.str:
337 ch = self.str[0]
338 return ch
339
340 def get_char(self):
341 ch = 0
342 if self.str:
343 ch = self.str[0]
344 self.str = self.str[1:]
345 return ch
346
347 def get_hex_uint8(self):
348 if self.str and len(self.str) >= 2 and self.str[0] in string.hexdigits and self.str[1] in string.hexdigits:
349 uval = int(self.str[0:2], 16)
350 self.str = self.str[2:]
351 return uval
352 return None
353
354 def get_hex_uint16(self, byte_order):
355 uval = 0
356 if byte_order == 'big':
357 uval |= self.get_hex_uint8() << 8
358 uval |= self.get_hex_uint8()
359 else:
360 uval |= self.get_hex_uint8()
361 uval |= self.get_hex_uint8() << 8
362 return uval
363
364 def get_hex_uint32(self, byte_order):
365 uval = 0
366 if byte_order == 'big':
367 uval |= self.get_hex_uint8() << 24
368 uval |= self.get_hex_uint8() << 16
369 uval |= self.get_hex_uint8() << 8
370 uval |= self.get_hex_uint8()
371 else:
372 uval |= self.get_hex_uint8()
373 uval |= self.get_hex_uint8() << 8
374 uval |= self.get_hex_uint8() << 16
375 uval |= self.get_hex_uint8() << 24
376 return uval
377
378 def get_hex_uint64(self, byte_order):
379 uval = 0
380 if byte_order == 'big':
381 uval |= self.get_hex_uint8() << 56
382 uval |= self.get_hex_uint8() << 48
383 uval |= self.get_hex_uint8() << 40
384 uval |= self.get_hex_uint8() << 32
385 uval |= self.get_hex_uint8() << 24
386 uval |= self.get_hex_uint8() << 16
387 uval |= self.get_hex_uint8() << 8
388 uval |= self.get_hex_uint8()
389 else:
390 uval |= self.get_hex_uint8()
391 uval |= self.get_hex_uint8() << 8
392 uval |= self.get_hex_uint8() << 16
393 uval |= self.get_hex_uint8() << 24
394 uval |= self.get_hex_uint8() << 32
395 uval |= self.get_hex_uint8() << 40
396 uval |= self.get_hex_uint8() << 48
397 uval |= self.get_hex_uint8() << 56
398 return uval
399
400 def get_hex_chars(self, n = 0):
401 str_len = len(self.str)
402 if n == 0:
403 # n was zero, so we need to determine all hex chars and
404 # stop when we hit the end of the string of a non-hex character
405 while n < str_len and self.str[n] in string.hexdigits:
406 n = n + 1
407 else:
408 if n > str_len:
409 return None # Not enough chars
410 # Verify all chars are hex if a length was specified
411 for i in range(n):
412 if self.str[i] not in string.hexdigits:
413 return None # Not all hex digits
414 if n == 0:
415 return None
416 hex_str = self.str[0:n]
417 self.str = self.str[n:]
418 return hex_str
419
420 def get_hex_uint(self, byte_order, n = 0):
421 if byte_order == 'big':
422 hex_str = self.get_hex_chars(n)
423 if hex_str == None:
424 return None
425 return int(hex_str, 16)
426 else:
427 uval = self.get_hex_uint8()
428 if uval == None:
429 return None
430 uval_result = 0
431 shift = 0
432 while uval != None:
433 uval_result |= (uval << shift)
434 shift += 8
435 uval = self.get_hex_uint8()
436 return uval_result
437
438 def get_key_value_pairs(self):
439 kvp = list()
Greg Clayton25f82aa2015-05-22 23:00:59 +0000440 if ';' in self.str:
441 key_value_pairs = string.split(self.str, ';')
442 for key_value_pair in key_value_pairs:
443 if len(key_value_pair):
444 kvp.append(string.split(key_value_pair, ':'))
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000445 return kvp
446
447 def split(self, ch):
448 return string.split(self.str, ch)
449
450 def split_hex(self, ch, byte_order):
451 hex_values = list()
452 strings = string.split(self.str, ch)
453 for str in strings:
454 hex_values.append(Packet(str).get_hex_uint(byte_order))
455 return hex_values
456
457 def __str__(self):
458 return self.str
459
460 def __len__(self):
461 return len(self.str)
462
463g_thread_suffix_regex = re.compile(';thread:([0-9a-fA-F]+);')
464def get_thread_from_thread_suffix(str):
465 if str:
466 match = g_thread_suffix_regex.match (str)
467 if match:
468 return int(match.group(1), 16)
469 return None
470
Greg Claytonf51a23f2012-06-04 23:22:17 +0000471def cmd_stop_reply(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000472 print "get_last_stop_info()"
473
Greg Claytonf51a23f2012-06-04 23:22:17 +0000474def rsp_stop_reply(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000475 global g_byte_order
476 packet = Packet(rsp)
477 stop_type = packet.get_char()
478 if stop_type == 'T' or stop_type == 'S':
479 signo = packet.get_hex_uint8()
480 print ' signal = %i' % signo
481 key_value_pairs = packet.get_key_value_pairs()
482 for key_value_pair in key_value_pairs:
483 key = key_value_pair[0]
484 value = key_value_pair[1]
485 if is_hex_byte(key):
486 reg_num = Packet(key).get_hex_uint8()
Greg Claytonf51a23f2012-06-04 23:22:17 +0000487 print ' ' + get_register_name_equal_value (options, reg_num, value)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000488 else:
489 print ' %s = %s' % (key, value)
490 elif stop_type == 'W':
491 exit_status = packet.get_hex_uint8()
492 print 'exit (status=%i)' % exit_status
493 elif stop_type == 'O':
494 print 'stdout = %s' % packet.str
495
496
Greg Claytonf51a23f2012-06-04 23:22:17 +0000497def cmd_unknown_packet(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000498 if args:
499 print "cmd: %s, args: %s", cmd, args
500 else:
501 print "cmd: %s", cmd
502
Greg Claytonf51a23f2012-06-04 23:22:17 +0000503def cmd_query_packet(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000504 if args:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000505 print "query: %s, args: %s" % (cmd, args)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000506 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000507 print "query: %s" % (cmd)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000508
509def rsp_ok_error(rsp):
510 print "rsp: ", rsp
511
Greg Claytonf51a23f2012-06-04 23:22:17 +0000512def rsp_ok_means_supported(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000513 if rsp == 'OK':
514 print "%s%s is supported" % (cmd, cmd_args)
515 elif rsp == '':
516 print "%s%s is not supported" % (cmd, cmd_args)
517 else:
518 print "%s%s -> %s" % (cmd, cmd_args, rsp)
519
Greg Claytonf51a23f2012-06-04 23:22:17 +0000520def rsp_ok_means_success(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000521 if rsp == 'OK':
522 print "success"
523 elif rsp == '':
524 print "%s%s is not supported" % (cmd, cmd_args)
525 else:
526 print "%s%s -> %s" % (cmd, cmd_args, rsp)
527
Greg Claytonf51a23f2012-06-04 23:22:17 +0000528def rsp_dump_key_value_pairs(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000529 if rsp:
530 packet = Packet(rsp)
531 key_value_pairs = packet.get_key_value_pairs()
532 for key_value_pair in key_value_pairs:
Greg Clayton25f82aa2015-05-22 23:00:59 +0000533 print key_value_pair
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000534 key = key_value_pair[0]
535 value = key_value_pair[1]
536 print " %s = %s" % (key, value)
537 else:
538 print "not supported"
539
Greg Claytonf51a23f2012-06-04 23:22:17 +0000540def cmd_vCont(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000541 if args == '?':
542 print "%s: get supported extended continue modes" % (cmd)
543 else:
544 got_other_threads = 0
545 s = ''
546 for thread_action in string.split(args[1:], ';'):
547 (short_action, thread) = string.split(thread_action, ':')
548 tid = int(thread, 16)
549 if short_action == 'c':
550 action = 'continue'
551 elif short_action == 's':
552 action = 'step'
553 elif short_action[0] == 'C':
554 action = 'continue with signal 0x%s' % (short_action[1:])
555 elif short_action == 'S':
556 action = 'step with signal 0x%s' % (short_action[1:])
557 else:
558 action = short_action
559 if s:
560 s += ', '
561 if tid == -1:
562 got_other_threads = 1
563 s += 'other-threads:'
564 else:
565 s += 'thread 0x%4.4x: %s' % (tid, action)
566 if got_other_threads:
567 print "extended_continue (%s)" % (s)
568 else:
569 print "extended_continue (%s, other-threads: suspend)" % (s)
570
Greg Claytonf51a23f2012-06-04 23:22:17 +0000571def rsp_vCont(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000572 if cmd_args == '?':
573 # Skip the leading 'vCont;'
574 rsp = rsp[6:]
575 modes = string.split(rsp, ';')
576 s = "%s: supported extended continue modes include: " % (cmd)
577
578 for i, mode in enumerate(modes):
579 if i:
580 s += ', '
581 if mode == 'c':
582 s += 'continue'
583 elif mode == 'C':
584 s += 'continue with signal'
585 elif mode == 's':
586 s += 'step'
587 elif mode == 'S':
588 s += 'step with signal'
589 else:
590 s += 'unrecognized vCont mode: ', mode
591 print s
592 elif rsp:
593 if rsp[0] == 'T' or rsp[0] == 'S' or rsp[0] == 'W' or rsp[0] == 'X':
Greg Claytonf51a23f2012-06-04 23:22:17 +0000594 rsp_stop_reply (options, cmd, cmd_args, rsp)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000595 return
596 if rsp[0] == 'O':
597 print "stdout: %s" % (rsp)
598 return
599 else:
600 print "not supported (cmd = '%s', args = '%s', rsp = '%s')" % (cmd, cmd_args, rsp)
601
Greg Claytonf51a23f2012-06-04 23:22:17 +0000602def cmd_vAttach(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000603 (extra_command, args) = string.split(args, ';')
604 if extra_command:
605 print "%s%s(%s)" % (cmd, extra_command, args)
606 else:
607 print "attach_pid(%s)" % args
608
Greg Claytonf51a23f2012-06-04 23:22:17 +0000609def cmd_qRegisterInfo(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000610 print 'query_register_info(reg_num=%i)' % (int(args, 16))
611
Greg Claytonf51a23f2012-06-04 23:22:17 +0000612def rsp_qRegisterInfo(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000613 global g_max_register_info_name_len
614 print 'query_register_info(reg_num=%i):' % (int(cmd_args, 16)),
615 if len(rsp) == 3 and rsp[0] == 'E':
616 g_max_register_info_name_len = 0
617 for reg_info in g_register_infos:
618 name_len = len(reg_info.name())
619 if g_max_register_info_name_len < name_len:
620 g_max_register_info_name_len = name_len
621 print' DONE'
622 else:
623 packet = Packet(rsp)
624 reg_info = RegisterInfo(packet.get_key_value_pairs())
625 g_register_infos.append(reg_info)
626 print reg_info
627
628
Greg Claytonf51a23f2012-06-04 23:22:17 +0000629def cmd_qThreadInfo(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000630 if cmd == 'qfThreadInfo':
631 query_type = 'first'
632 else:
633 query_type = 'subsequent'
634 print 'get_current_thread_list(type=%s)' % (query_type)
635
Greg Claytonf51a23f2012-06-04 23:22:17 +0000636def rsp_qThreadInfo(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000637 packet = Packet(rsp)
638 response_type = packet.get_char()
639 if response_type == 'm':
640 tids = packet.split_hex(';', 'big')
641 for i, tid in enumerate(tids):
642 if i:
643 print ',',
644 print '0x%x' % (tid),
645 print
646 elif response_type == 'l':
647 print 'END'
648
Greg Claytonf51a23f2012-06-04 23:22:17 +0000649def rsp_hex_big_endian(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000650 packet = Packet(rsp)
651 uval = packet.get_hex_uint('big')
652 print '%s: 0x%x' % (cmd, uval)
653
Greg Claytonf51a23f2012-06-04 23:22:17 +0000654def cmd_read_memory(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000655 packet = Packet(args)
656 addr = packet.get_hex_uint('big')
657 comma = packet.get_char()
658 size = packet.get_hex_uint('big')
659 print 'read_memory (addr = 0x%x, size = %u)' % (addr, size)
660
661def dump_hex_memory_buffer(addr, hex_byte_str):
662 packet = Packet(hex_byte_str)
663 idx = 0
664 ascii = ''
665 uval = packet.get_hex_uint8()
666 while uval != None:
667 if ((idx % 16) == 0):
668 if ascii:
669 print ' ', ascii
670 ascii = ''
671 print '0x%x:' % (addr + idx),
672 print '%2.2x' % (uval),
673 if 0x20 <= uval and uval < 0x7f:
674 ascii += '%c' % uval
675 else:
676 ascii += '.'
677 uval = packet.get_hex_uint8()
678 idx = idx + 1
679 if ascii:
680 print ' ', ascii
681 ascii = ''
682
Greg Claytonf51a23f2012-06-04 23:22:17 +0000683def cmd_write_memory(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000684 packet = Packet(args)
685 addr = packet.get_hex_uint('big')
686 if packet.get_char() != ',':
687 print 'error: invalid write memory command (missing comma after address)'
688 return
689 size = packet.get_hex_uint('big')
690 if packet.get_char() != ':':
691 print 'error: invalid write memory command (missing colon after size)'
692 return
693 print 'write_memory (addr = 0x%x, size = %u, data:' % (addr, size)
694 dump_hex_memory_buffer (addr, packet.str)
695
Greg Claytonf51a23f2012-06-04 23:22:17 +0000696def cmd_alloc_memory(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000697 packet = Packet(args)
698 byte_size = packet.get_hex_uint('big')
699 if packet.get_char() != ',':
700 print 'error: invalid allocate memory command (missing comma after address)'
701 return
702 print 'allocate_memory (byte-size = %u (0x%x), permissions = %s)' % (byte_size, byte_size, packet.str)
703
Greg Claytonf51a23f2012-06-04 23:22:17 +0000704def rsp_alloc_memory(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000705 packet = Packet(rsp)
706 addr = packet.get_hex_uint('big')
707 print 'addr = 0x%x' % addr
708
Greg Claytonf51a23f2012-06-04 23:22:17 +0000709def cmd_dealloc_memory(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000710 packet = Packet(args)
711 addr = packet.get_hex_uint('big')
712 if packet.get_char() != ',':
713 print 'error: invalid allocate memory command (missing comma after address)'
714 return
715 print 'deallocate_memory (addr = 0x%x, permissions = %s)' % (addr, packet.str)
716
Greg Claytonf51a23f2012-06-04 23:22:17 +0000717def rsp_memory_bytes(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000718 addr = Packet(cmd_args).get_hex_uint('big')
719 dump_hex_memory_buffer (addr, rsp)
720
Greg Claytonf51a23f2012-06-04 23:22:17 +0000721def get_register_name_equal_value(options, reg_num, hex_value_str):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000722 if reg_num < len(g_register_infos):
723 reg_info = g_register_infos[reg_num]
Greg Claytonf51a23f2012-06-04 23:22:17 +0000724 value_str = reg_info.get_value_from_hex_string (hex_value_str)
725 s = reg_info.name() + ' = '
726 if options.symbolicator:
727 symbolicated_addresses = options.symbolicator.symbolicate (int(value_str, 0))
728 if symbolicated_addresses:
729 s += options.colors.magenta()
730 s += '%s' % symbolicated_addresses[0]
731 s += options.colors.reset()
732 return s
733 s += value_str
734 return s
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000735 else:
736 reg_value = Packet(hex_value_str).get_hex_uint(g_byte_order)
737 return 'reg(%u) = 0x%x' % (reg_num, reg_value)
738
Greg Claytonf51a23f2012-06-04 23:22:17 +0000739def cmd_read_one_reg(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000740 packet = Packet(args)
741 reg_num = packet.get_hex_uint('big')
742 tid = get_thread_from_thread_suffix (packet.str)
743 name = None
744 if reg_num < len(g_register_infos):
745 name = g_register_infos[reg_num].name ()
746 if packet.str:
747 packet.get_char() # skip ;
748 thread_info = packet.get_key_value_pairs()
749 tid = int(thread_info[0][1], 16)
750 s = 'read_register (reg_num=%u' % reg_num
751 if name:
752 s += ' (%s)' % (name)
753 if tid != None:
754 s += ', tid = 0x%4.4x' % (tid)
755 s += ')'
756 print s
757
Greg Claytonf51a23f2012-06-04 23:22:17 +0000758def rsp_read_one_reg(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000759 packet = Packet(cmd_args)
760 reg_num = packet.get_hex_uint('big')
Greg Claytonf51a23f2012-06-04 23:22:17 +0000761 print get_register_name_equal_value (options, reg_num, rsp)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000762
Greg Claytonf51a23f2012-06-04 23:22:17 +0000763def cmd_write_one_reg(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000764 packet = Packet(args)
765 reg_num = packet.get_hex_uint('big')
766 if packet.get_char() != '=':
767 print 'error: invalid register write packet'
768 else:
769 name = None
770 hex_value_str = packet.get_hex_chars()
771 tid = get_thread_from_thread_suffix (packet.str)
772 s = 'write_register (reg_num=%u' % reg_num
773 if name:
774 s += ' (%s)' % (name)
775 s += ', value = '
Greg Claytonf51a23f2012-06-04 23:22:17 +0000776 s += get_register_name_equal_value(options, reg_num, hex_value_str)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000777 if tid != None:
778 s += ', tid = 0x%4.4x' % (tid)
779 s += ')'
780 print s
781
782def dump_all_regs(packet):
783 for reg_info in g_register_infos:
784 nibble_size = reg_info.bit_size() / 4
785 hex_value_str = packet.get_hex_chars(nibble_size)
786 if hex_value_str != None:
787 value = reg_info.get_value_from_hex_string (hex_value_str)
788 print '%*s = %s' % (g_max_register_info_name_len, reg_info.name(), value)
789 else:
790 return
791
792def cmd_read_all_regs(cmd, cmd_args):
793 packet = Packet(cmd_args)
794 packet.get_char() # toss the 'g' command character
795 tid = get_thread_from_thread_suffix (packet.str)
796 if tid != None:
797 print 'read_all_register(thread = 0x%4.4x)' % tid
798 else:
799 print 'read_all_register()'
800
Greg Claytonf51a23f2012-06-04 23:22:17 +0000801def rsp_read_all_regs(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000802 packet = Packet(rsp)
803 dump_all_regs (packet)
804
Greg Claytonf51a23f2012-06-04 23:22:17 +0000805def cmd_write_all_regs(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000806 packet = Packet(args)
807 print 'write_all_registers()'
808 dump_all_regs (packet)
809
810g_bp_types = [ "software_bp", "hardware_bp", "write_wp", "read_wp", "access_wp" ]
811
Greg Claytonf51a23f2012-06-04 23:22:17 +0000812def cmd_bp(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000813 if cmd == 'Z':
814 s = 'set_'
815 else:
816 s = 'clear_'
817 packet = Packet (args)
818 bp_type = packet.get_hex_uint('big')
819 packet.get_char() # Skip ,
820 bp_addr = packet.get_hex_uint('big')
821 packet.get_char() # Skip ,
822 bp_size = packet.get_hex_uint('big')
823 s += g_bp_types[bp_type]
824 s += " (addr = 0x%x, size = %u)" % (bp_addr, bp_size)
825 print s
826
Greg Claytonf51a23f2012-06-04 23:22:17 +0000827def cmd_mem_rgn_info(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000828 packet = Packet(args)
829 packet.get_char() # skip ':' character
830 addr = packet.get_hex_uint('big')
831 print 'get_memory_region_info (addr=0x%x)' % (addr)
832
Greg Claytonf51a23f2012-06-04 23:22:17 +0000833def cmd_kill(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000834 print 'kill_process()'
835
836gdb_remote_commands = {
837 '\\?' : { 'cmd' : cmd_stop_reply , 'rsp' : rsp_stop_reply , 'name' : "stop reply pacpket"},
838 'QStartNoAckMode' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_supported , 'name' : "query if no ack mode is supported"},
839 'QThreadSuffixSupported' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_supported , 'name' : "query if thread suffix is supported" },
840 'QListThreadsInStopReply' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_supported , 'name' : "query if threads in stop reply packets are supported" },
Greg Clayton25f82aa2015-05-22 23:00:59 +0000841 'QSetDetachOnError' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_supported , 'name' : "query if we should detach on error" },
Greg Clayton48629002012-08-20 16:50:43 +0000842 'qVAttachOrWaitSupported' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_supported , 'name' : "query if threads attach with optional wait is supported" },
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000843 'qHostInfo' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_dump_key_value_pairs, 'name' : "get host information" },
844 'vCont' : { 'cmd' : cmd_vCont , 'rsp' : rsp_vCont , 'name' : "extended continue command" },
845 'vAttach' : { 'cmd' : cmd_vAttach , 'rsp' : rsp_stop_reply , 'name' : "attach to process" },
846 'qRegisterInfo' : { 'cmd' : cmd_qRegisterInfo , 'rsp' : rsp_qRegisterInfo , 'name' : "query register info" },
847 'qfThreadInfo' : { 'cmd' : cmd_qThreadInfo , 'rsp' : rsp_qThreadInfo , 'name' : "get current thread list" },
848 'qsThreadInfo' : { 'cmd' : cmd_qThreadInfo , 'rsp' : rsp_qThreadInfo , 'name' : "get current thread list" },
849 'qShlibInfoAddr' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_hex_big_endian , 'name' : "get shared library info address" },
850 'qMemoryRegionInfo' : { 'cmd' : cmd_mem_rgn_info , 'rsp' : rsp_dump_key_value_pairs, 'name' : "get memory region information" },
Greg Clayton25f82aa2015-05-22 23:00:59 +0000851 'qProcessInfo' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_dump_key_value_pairs, 'name' : "get process info" },
852 'qSupported' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_supported , 'name' : "query supported" },
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000853 'm' : { 'cmd' : cmd_read_memory , 'rsp' : rsp_memory_bytes , 'name' : "read memory" },
854 'M' : { 'cmd' : cmd_write_memory , 'rsp' : rsp_ok_means_success , 'name' : "write memory" },
855 '_M' : { 'cmd' : cmd_alloc_memory , 'rsp' : rsp_alloc_memory , 'name' : "allocate memory" },
856 '_m' : { 'cmd' : cmd_dealloc_memory, 'rsp' : rsp_ok_means_success , 'name' : "deallocate memory" },
857 'p' : { 'cmd' : cmd_read_one_reg , 'rsp' : rsp_read_one_reg , 'name' : "read single register" },
858 'P' : { 'cmd' : cmd_write_one_reg , 'rsp' : rsp_ok_means_success , 'name' : "write single register" },
859 'g' : { 'cmd' : cmd_read_all_regs , 'rsp' : rsp_read_all_regs , 'name' : "read all registers" },
860 'G' : { 'cmd' : cmd_write_all_regs, 'rsp' : rsp_ok_means_success , 'name' : "write all registers" },
861 'z' : { 'cmd' : cmd_bp , 'rsp' : rsp_ok_means_success , 'name' : "clear breakpoint or watchpoint" },
862 'Z' : { 'cmd' : cmd_bp , 'rsp' : rsp_ok_means_success , 'name' : "set breakpoint or watchpoint" },
863 'k' : { 'cmd' : cmd_kill , 'rsp' : rsp_stop_reply , 'name' : "kill process" },
864}
Greg Clayton25f82aa2015-05-22 23:00:59 +0000865
866def calculate_mean_and_standard_deviation(floats):
867 sum = 0.0
868 count = len(floats)
869 for f in floats:
870 sum += f
871 mean = sum / count
872 accum = 0.0
873 for f in floats:
874 delta = f - mean
875 accum += delta * delta
876
877 std_dev = math.sqrt(accum / (count-1));
878 return (mean, std_dev)
879
Greg Claytone2841632012-01-26 02:56:24 +0000880def parse_gdb_log_file(file, options):
881 '''Parse a GDB log file that was generated by enabling logging with:
882 (lldb) log enable --threadsafe --timestamp --file <FILE> gdb-remote packets
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +0000883 This log file will contain timestamps and this function will then normalize
Greg Claytone2841632012-01-26 02:56:24 +0000884 those packets to be relative to the first value timestamp that is found and
885 show delta times between log lines and also keep track of how long it takes
886 for GDB remote commands to make a send/receive round trip. This can be
887 handy when trying to figure out why some operation in the debugger is taking
888 a long time during a preset set of debugger commands.'''
889
890 tricky_commands = [ 'qRegisterInfo' ]
891 timestamp_regex = re.compile('(\s*)([1-9][0-9]+\.[0-9]+)([^0-9].*)$')
892 packet_name_regex = re.compile('([A-Za-z_]+)[^a-z]')
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000893 packet_transmit_name_regex = re.compile('(?P<direction>send|read) packet: (?P<packet>.*)')
894 packet_contents_name_regex = re.compile('\$([^#]+)#[0-9a-fA-F]{2}')
895 packet_names_regex_str = '(' + '|'.join(gdb_remote_commands.keys()) + ')(.*)';
896 packet_names_regex = re.compile(packet_names_regex_str);
897
Greg Claytone2841632012-01-26 02:56:24 +0000898 base_time = 0.0
899 last_time = 0.0
900 packet_send_time = 0.0
Greg Claytone2841632012-01-26 02:56:24 +0000901 packet_total_times = {}
Greg Clayton25f82aa2015-05-22 23:00:59 +0000902 packet_times = []
Jim Inghamd95752f2012-03-01 18:57:51 +0000903 packet_count = {}
Greg Claytone2841632012-01-26 02:56:24 +0000904 file = open(file)
905 lines = file.read().splitlines()
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000906 last_command = None
907 last_command_args = None
908 last_command_packet = None
Greg Claytone2841632012-01-26 02:56:24 +0000909 for line in lines:
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000910 m = packet_transmit_name_regex.search(line)
Greg Claytonf51a23f2012-06-04 23:22:17 +0000911 is_command = False
Greg Clayton25f82aa2015-05-22 23:00:59 +0000912 direction = None
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000913 if m:
914 direction = m.group('direction')
915 is_command = direction == 'send'
916 packet = m.group('packet')
Greg Claytonf51a23f2012-06-04 23:22:17 +0000917 sys.stdout.write(options.colors.green())
Greg Clayton25f82aa2015-05-22 23:00:59 +0000918 if not options.quiet:
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000919 print '# ', line
Greg Claytonf51a23f2012-06-04 23:22:17 +0000920 sys.stdout.write(options.colors.reset())
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000921
922 #print 'direction = "%s", packet = "%s"' % (direction, packet)
923
924 if packet[0] == '+':
Greg Clayton25f82aa2015-05-22 23:00:59 +0000925 if not options.quiet: print 'ACK'
926 continue
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000927 elif packet[0] == '-':
Greg Clayton25f82aa2015-05-22 23:00:59 +0000928 if not options.quiet: print 'NACK'
929 continue
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000930 elif packet[0] == '$':
931 m = packet_contents_name_regex.match(packet)
932 if m:
933 contents = m.group(1)
934 if is_command:
935 m = packet_names_regex.match (contents)
936 if m:
937 last_command = m.group(1)
Greg Claytonf51a23f2012-06-04 23:22:17 +0000938 packet_name = last_command
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000939 last_command_args = m.group(2)
940 last_command_packet = contents
Greg Claytonf51a23f2012-06-04 23:22:17 +0000941 gdb_remote_commands[last_command]['cmd'](options, last_command, last_command_args)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000942 else:
Greg Clayton25f82aa2015-05-22 23:00:59 +0000943 packet_match = packet_name_regex.match (contents)
Greg Claytonf51a23f2012-06-04 23:22:17 +0000944 if packet_match:
945 packet_name = packet_match.group(1)
946 for tricky_cmd in tricky_commands:
947 if packet_name.find (tricky_cmd) == 0:
948 packet_name = tricky_cmd
949 else:
950 packet_name = contents
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000951 last_command = None
952 last_command_args = None
953 last_command_packet = None
954 elif last_command:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000955 gdb_remote_commands[last_command]['rsp'](options, last_command, last_command_args, contents)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000956 else:
957 print 'error: invalid packet: "', packet, '"'
958 else:
959 print '???'
960 else:
961 print '## ', line
Greg Claytone2841632012-01-26 02:56:24 +0000962 match = timestamp_regex.match (line)
963 if match:
964 curr_time = float (match.group(2))
Greg Clayton25f82aa2015-05-22 23:00:59 +0000965 if last_time and not is_command:
966 delta = curr_time - last_time
967 packet_times.append(delta)
Greg Claytone2841632012-01-26 02:56:24 +0000968 delta = 0.0
969 if base_time:
970 delta = curr_time - last_time
971 else:
972 base_time = curr_time
Greg Claytonf51a23f2012-06-04 23:22:17 +0000973
974 if is_command:
Greg Claytone2841632012-01-26 02:56:24 +0000975 packet_send_time = curr_time
Greg Claytone2841632012-01-26 02:56:24 +0000976 elif line.find('read packet: $') >= 0 and packet_name:
977 if packet_name in packet_total_times:
978 packet_total_times[packet_name] += delta
Jim Inghamd95752f2012-03-01 18:57:51 +0000979 packet_count[packet_name] += 1
Greg Claytone2841632012-01-26 02:56:24 +0000980 else:
981 packet_total_times[packet_name] = delta
Jim Inghamd95752f2012-03-01 18:57:51 +0000982 packet_count[packet_name] = 1
Greg Claytone2841632012-01-26 02:56:24 +0000983 packet_name = None
984
985 if not options or not options.quiet:
986 print '%s%.6f %+.6f%s' % (match.group(1), curr_time - base_time, delta, match.group(3))
987 last_time = curr_time
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000988 # else:
989 # print line
Greg Clayton25f82aa2015-05-22 23:00:59 +0000990 (average, std_dev) = calculate_mean_and_standard_deviation(packet_times)
991 print '%u packets with average packet time of %f and standard deviation of %f' % (len(packet_times), average, std_dev)
Greg Claytone2841632012-01-26 02:56:24 +0000992 if packet_total_times:
993 total_packet_time = 0.0
Jim Inghamd95752f2012-03-01 18:57:51 +0000994 total_packet_count = 0
Greg Claytone2841632012-01-26 02:56:24 +0000995 for key, vvv in packet_total_times.items():
996 # print ' key = (%s) "%s"' % (type(key), key)
997 # print 'value = (%s) %s' % (type(vvv), vvv)
998 # if type(vvv) == 'float':
999 total_packet_time += vvv
Jim Inghamd95752f2012-03-01 18:57:51 +00001000 for key, vvv in packet_count.items():
1001 total_packet_count += vvv
1002
1003 print '#---------------------------------------------------'
Greg Claytone2841632012-01-26 02:56:24 +00001004 print '# Packet timing summary:'
Greg Clayton25f82aa2015-05-22 23:00:59 +00001005 print '# Totals: time = %6f, count = %6d' % (total_packet_time, total_packet_count)
Jim Inghamd95752f2012-03-01 18:57:51 +00001006 print '#---------------------------------------------------'
1007 print '# Packet Time (sec) Percent Count '
1008 print '#------------------------- ---------- ------- ------'
1009 if options and options.sort_count:
1010 res = sorted(packet_count, key=packet_count.__getitem__, reverse=True)
1011 else:
1012 res = sorted(packet_total_times, key=packet_total_times.__getitem__, reverse=True)
1013
Greg Claytone2841632012-01-26 02:56:24 +00001014 if last_time > 0.0:
1015 for item in res:
1016 packet_total_time = packet_total_times[item]
1017 packet_percent = (packet_total_time / total_packet_time)*100.0
1018 if packet_percent >= 10.0:
Jim Inghamd95752f2012-03-01 18:57:51 +00001019 print " %24s %.6f %.2f%% %6d" % (item, packet_total_time, packet_percent, packet_count[item])
Greg Claytone2841632012-01-26 02:56:24 +00001020 else:
Jim Inghamd95752f2012-03-01 18:57:51 +00001021 print " %24s %.6f %.2f%% %6d" % (item, packet_total_time, packet_percent, packet_count[item])
Greg Claytone2841632012-01-26 02:56:24 +00001022
1023
1024
1025if __name__ == '__main__':
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001026 usage = "usage: gdbremote [options]"
1027 description='''The command disassembles a GDB remote packet log.'''
1028 parser = optparse.OptionParser(description=description, prog='gdbremote',usage=usage)
1029 parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
1030 parser.add_option('-q', '--quiet', action='store_true', dest='quiet', help='display verbose debug info', default=False)
1031 parser.add_option('-C', '--color', action='store_true', dest='color', help='add terminal colors', default=False)
1032 parser.add_option('-c', '--sort-by-count', action='store_true', dest='sort_count', help='display verbose debug info', default=False)
Greg Claytonf51a23f2012-06-04 23:22:17 +00001033 parser.add_option('--crashlog', type='string', dest='crashlog', help='symbolicate using a darwin crash log file', default=False)
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001034 try:
1035 (options, args) = parser.parse_args(sys.argv[1:])
1036 except:
1037 print 'error: argument error'
1038 sys.exit(1)
1039
Greg Claytonf51a23f2012-06-04 23:22:17 +00001040 options.colors = TerminalColors(options.color)
1041 options.symbolicator = None
1042 if options.crashlog:
1043 import lldb
1044 lldb.debugger = lldb.SBDebugger.Create()
1045 import lldb.macosx.crashlog
1046 options.symbolicator = lldb.macosx.crashlog.CrashLog(options.crashlog)
1047 print '%s' % (options.symbolicator)
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001048
Greg Claytone2841632012-01-26 02:56:24 +00001049 # This script is being run from the command line, create a debugger in case we are
1050 # going to use any debugger functions in our function.
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001051 for file in args:
Greg Claytone2841632012-01-26 02:56:24 +00001052 print '#----------------------------------------------------------------------'
1053 print "# GDB remote log file: '%s'" % file
1054 print '#----------------------------------------------------------------------'
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001055 parse_gdb_log_file (file, options)
Greg Claytonf51a23f2012-06-04 23:22:17 +00001056 if options.symbolicator:
1057 print '%s' % (options.symbolicator)
1058
Greg Claytone2841632012-01-26 02:56:24 +00001059else:
1060 import lldb
1061 if lldb.debugger:
1062 # This initializer is being run from LLDB in the embedded command interpreter
1063 # Add any commands contained in this module to LLDB
1064 lldb.debugger.HandleCommand('command script add -f gdbremote.start_gdb_log start_gdb_log')
1065 lldb.debugger.HandleCommand('command script add -f gdbremote.stop_gdb_log stop_gdb_log')
1066 print 'The "start_gdb_log" and "stop_gdb_log" commands are now installed and ready for use, type "start_gdb_log --help" or "stop_gdb_log --help" for more information'