blob: 512162ab5936b2cbadef6e9d17cd63f502610b3d [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
20import optparse
21import os
Greg Claytone2841632012-01-26 02:56:24 +000022import re
Greg Clayton8ebb9a82012-06-01 20:23:54 +000023import shlex
24import string
25import sys
Greg Claytone2841632012-01-26 02:56:24 +000026import tempfile
27
Greg Claytonf51a23f2012-06-04 23:22:17 +000028#----------------------------------------------------------------------
29# Global variables
30#----------------------------------------------------------------------
31g_log_file = ''
32g_byte_order = 'little'
33
Greg Clayton8ebb9a82012-06-01 20:23:54 +000034class TerminalColors:
35 '''Simple terminal colors class'''
Greg Claytonf51a23f2012-06-04 23:22:17 +000036 def __init__(self, enabled = True):
Greg Clayton8ebb9a82012-06-01 20:23:54 +000037 # TODO: discover terminal type from "file" and disable if
38 # it can't handle the color codes
39 self.enabled = enabled
40
41 def reset(self):
42 '''Reset all terminal colors and formatting.'''
43 if self.enabled:
Greg Claytonf51a23f2012-06-04 23:22:17 +000044 return "\x1b[0m";
45 return ''
Greg Clayton8ebb9a82012-06-01 20:23:54 +000046
47 def bold(self, on = True):
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000048 '''Enable or disable bold depending on the "on" parameter.'''
Greg Clayton8ebb9a82012-06-01 20:23:54 +000049 if self.enabled:
50 if on:
Greg Claytonf51a23f2012-06-04 23:22:17 +000051 return "\x1b[1m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +000052 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +000053 return "\x1b[22m";
54 return ''
55
Greg Clayton8ebb9a82012-06-01 20:23:54 +000056 def italics(self, on = True):
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000057 '''Enable or disable italics depending on the "on" parameter.'''
Greg Clayton8ebb9a82012-06-01 20:23:54 +000058 if self.enabled:
59 if on:
Greg Claytonf51a23f2012-06-04 23:22:17 +000060 return "\x1b[3m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +000061 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +000062 return "\x1b[23m";
63 return ''
64
Greg Clayton8ebb9a82012-06-01 20:23:54 +000065 def underline(self, on = True):
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000066 '''Enable or disable underline depending on the "on" parameter.'''
Greg Clayton8ebb9a82012-06-01 20:23:54 +000067 if self.enabled:
68 if on:
Greg Claytonf51a23f2012-06-04 23:22:17 +000069 return "\x1b[4m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +000070 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +000071 return "\x1b[24m";
72 return ''
73
Greg Clayton8ebb9a82012-06-01 20:23:54 +000074 def inverse(self, on = True):
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000075 '''Enable or disable inverse depending on the "on" parameter.'''
Greg Clayton8ebb9a82012-06-01 20:23:54 +000076 if self.enabled:
77 if on:
Greg Claytonf51a23f2012-06-04 23:22:17 +000078 return "\x1b[7m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +000079 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +000080 return "\x1b[27m";
81 return ''
82
Greg Clayton8ebb9a82012-06-01 20:23:54 +000083 def strike(self, on = True):
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000084 '''Enable or disable strike through depending on the "on" parameter.'''
Greg Clayton8ebb9a82012-06-01 20:23:54 +000085 if self.enabled:
86 if on:
Greg Claytonf51a23f2012-06-04 23:22:17 +000087 return "\x1b[9m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +000088 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +000089 return "\x1b[29m";
90 return ''
91
Greg Clayton8ebb9a82012-06-01 20:23:54 +000092 def black(self, fg = True):
93 '''Set the foreground or background color to black.
94 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
95 if self.enabled:
96 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +000097 return "\x1b[30m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +000098 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +000099 return "\x1b[40m";
100 return ''
101
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000102 def red(self, fg = True):
103 '''Set the foreground or background color to red.
104 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
105 if self.enabled:
106 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000107 return "\x1b[31m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000108 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000109 return "\x1b[41m";
110 return ''
111
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000112 def green(self, fg = True):
113 '''Set the foreground or background color to green.
114 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
115 if self.enabled:
116 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000117 return "\x1b[32m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000118 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000119 return "\x1b[42m";
120 return ''
121
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000122 def yellow(self, fg = True):
123 '''Set the foreground or background color to yellow.
124 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
125 if self.enabled:
126 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000127 return "\x1b[43m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000128 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000129 return "\x1b[33m";
130 return ''
131
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000132 def blue(self, fg = True):
133 '''Set the foreground or background color to blue.
134 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
135 if self.enabled:
136 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000137 return "\x1b[34m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000138 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000139 return "\x1b[44m";
140 return ''
141
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000142 def magenta(self, fg = True):
143 '''Set the foreground or background color to magenta.
144 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
145 if self.enabled:
146 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000147 return "\x1b[35m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000148 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000149 return "\x1b[45m";
150 return ''
151
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000152 def cyan(self, fg = True):
153 '''Set the foreground or background color to cyan.
154 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
155 if self.enabled:
156 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000157 return "\x1b[36m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000158 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000159 return "\x1b[46m";
160 return ''
161
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000162 def white(self, fg = True):
163 '''Set the foreground or background color to white.
164 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
165 if self.enabled:
166 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000167 return "\x1b[37m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000168 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000169 return "\x1b[47m";
170 return ''
171
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000172 def default(self, fg = True):
173 '''Set the foreground or background color to the default.
174 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
175 if self.enabled:
176 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000177 return "\x1b[39m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000178 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000179 return "\x1b[49m";
180 return ''
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000181
Greg Claytone2841632012-01-26 02:56:24 +0000182
183def start_gdb_log(debugger, command, result, dict):
184 '''Start logging GDB remote packets by enabling logging with timestamps and
185 thread safe logging. Follow a call to this function with a call to "stop_gdb_log"
186 in order to dump out the commands.'''
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000187 global g_log_file
Greg Claytone2841632012-01-26 02:56:24 +0000188 command_args = shlex.split(command)
189 usage = "usage: start_gdb_log [options] [<LOGFILEPATH>]"
190 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
191 be aggregated and displayed.'''
192 parser = optparse.OptionParser(description=description, prog='start_gdb_log',usage=usage)
193 parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
194 try:
195 (options, args) = parser.parse_args(command_args)
196 except:
197 return
198
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000199 if g_log_file:
200 result.PutCString ('error: logging is already in progress with file "%s"', g_log_file)
Greg Claytone2841632012-01-26 02:56:24 +0000201 else:
202 args_len = len(args)
203 if args_len == 0:
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000204 g_log_file = tempfile.mktemp()
Greg Claytone2841632012-01-26 02:56:24 +0000205 elif len(args) == 1:
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000206 g_log_file = args[0]
Greg Claytone2841632012-01-26 02:56:24 +0000207
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000208 if g_log_file:
209 debugger.HandleCommand('log enable --threadsafe --timestamp --file "%s" gdb-remote packets' % g_log_file);
210 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 +0000211 return
212
213 result.PutCString ('error: invalid log file path')
214 result.PutCString (usage)
215
216def stop_gdb_log(debugger, command, result, dict):
217 '''Stop logging GDB remote packets to the file that was specified in a call
218 to "start_gdb_log" and normalize the timestamps to be relative to the first
219 timestamp in the log file. Also print out statistics for how long each
220 command took to allow performance bottlenecks to be determined.'''
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000221 global g_log_file
Greg Claytone2841632012-01-26 02:56:24 +0000222 # Any commands whose names might be followed by more valid C identifier
223 # characters must be listed here
224 command_args = shlex.split(command)
225 usage = "usage: stop_gdb_log [options]"
226 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.'''
227 parser = optparse.OptionParser(description=description, prog='stop_gdb_log',usage=usage)
228 parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
229 parser.add_option('-q', '--quiet', action='store_true', dest='quiet', help='display verbose debug info', default=False)
Greg Claytonf51a23f2012-06-04 23:22:17 +0000230 parser.add_option('-C', '--color', action='store_true', dest='color', help='add terminal colors', default=False)
Jim Inghamd95752f2012-03-01 18:57:51 +0000231 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 +0000232 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 +0000233 try:
234 (options, args) = parser.parse_args(command_args)
235 except:
236 return
Greg Claytonf51a23f2012-06-04 23:22:17 +0000237 options.colors = TerminalColors(options.color)
238 options.symbolicator = None
239 if options.symbolicate:
240 if lldb.target:
241 import lldb.utils.symbolication
242 options.symbolicator = lldb.utils.symbolication.Symbolicator()
243 options.symbolicator.target = lldb.target
244 else:
245 print "error: can't symbolicate without a target"
Greg Claytone2841632012-01-26 02:56:24 +0000246
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000247 if not g_log_file:
Greg Claytone2841632012-01-26 02:56:24 +0000248 result.PutCString ('error: logging must have been previously enabled with a call to "stop_gdb_log"')
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000249 elif os.path.exists (g_log_file):
Greg Claytone2841632012-01-26 02:56:24 +0000250 if len(args) == 0:
251 debugger.HandleCommand('log disable gdb-remote packets');
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000252 result.PutCString ("GDB packet logging disabled. Logged packets are in '%s'" % g_log_file)
253 parse_gdb_log_file (g_log_file, options)
Greg Claytone2841632012-01-26 02:56:24 +0000254 else:
255 result.PutCString (usage)
256 else:
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000257 print 'error: the GDB packet log file "%s" does not exist' % g_log_file
Greg Claytone2841632012-01-26 02:56:24 +0000258
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000259def is_hex_byte(str):
260 if len(str) == 2:
261 return str[0] in string.hexdigits and str[1] in string.hexdigits;
262 return False
263
264# global register info list
265g_register_infos = list()
266g_max_register_info_name_len = 0
267
268class RegisterInfo:
269 """Class that represents register information"""
270 def __init__(self, kvp):
271 self.info = dict()
272 for kv in kvp:
273 key = kv[0]
274 value = kv[1]
275 self.info[key] = value
276 def name(self):
277 '''Get the name of the register.'''
278 if self.info and 'name' in self.info:
279 return self.info['name']
280 return None
281
282 def bit_size(self):
283 '''Get the size in bits of the register.'''
284 if self.info and 'bitsize' in self.info:
285 return int(self.info['bitsize'])
286 return 0
287
288 def byte_size(self):
289 '''Get the size in bytes of the register.'''
290 return self.bit_size() / 8
291
292 def get_value_from_hex_string(self, hex_str):
293 '''Dump the register value given a native byte order encoded hex ASCII byte string.'''
294 encoding = self.info['encoding']
295 bit_size = self.bit_size()
296 packet = Packet(hex_str)
297 if encoding == 'uint':
298 uval = packet.get_hex_uint(g_byte_order)
299 if bit_size == 8:
300 return '0x%2.2x' % (uval)
301 elif bit_size == 16:
302 return '0x%4.4x' % (uval)
303 elif bit_size == 32:
304 return '0x%8.8x' % (uval)
305 elif bit_size == 64:
306 return '0x%16.16x' % (uval)
307 bytes = list();
308 uval = packet.get_hex_uint8()
309 while uval != None:
310 bytes.append(uval)
311 uval = packet.get_hex_uint8()
312 value_str = '0x'
313 if g_byte_order == 'little':
314 bytes.reverse()
315 for byte in bytes:
316 value_str += '%2.2x' % byte
317 return '%s' % (value_str)
318
319 def __str__(self):
320 '''Dump the register info key/value pairs'''
321 s = ''
322 for key in self.info.keys():
323 if s:
324 s += ', '
325 s += "%s=%s " % (key, self.info[key])
326 return s
327
328class Packet:
329 """Class that represents a packet that contains string data"""
330 def __init__(self, packet_str):
331 self.str = packet_str
332
333 def peek_char(self):
334 ch = 0
335 if self.str:
336 ch = self.str[0]
337 return ch
338
339 def get_char(self):
340 ch = 0
341 if self.str:
342 ch = self.str[0]
343 self.str = self.str[1:]
344 return ch
345
346 def get_hex_uint8(self):
347 if self.str and len(self.str) >= 2 and self.str[0] in string.hexdigits and self.str[1] in string.hexdigits:
348 uval = int(self.str[0:2], 16)
349 self.str = self.str[2:]
350 return uval
351 return None
352
353 def get_hex_uint16(self, byte_order):
354 uval = 0
355 if byte_order == 'big':
356 uval |= self.get_hex_uint8() << 8
357 uval |= self.get_hex_uint8()
358 else:
359 uval |= self.get_hex_uint8()
360 uval |= self.get_hex_uint8() << 8
361 return uval
362
363 def get_hex_uint32(self, byte_order):
364 uval = 0
365 if byte_order == 'big':
366 uval |= self.get_hex_uint8() << 24
367 uval |= self.get_hex_uint8() << 16
368 uval |= self.get_hex_uint8() << 8
369 uval |= self.get_hex_uint8()
370 else:
371 uval |= self.get_hex_uint8()
372 uval |= self.get_hex_uint8() << 8
373 uval |= self.get_hex_uint8() << 16
374 uval |= self.get_hex_uint8() << 24
375 return uval
376
377 def get_hex_uint64(self, byte_order):
378 uval = 0
379 if byte_order == 'big':
380 uval |= self.get_hex_uint8() << 56
381 uval |= self.get_hex_uint8() << 48
382 uval |= self.get_hex_uint8() << 40
383 uval |= self.get_hex_uint8() << 32
384 uval |= self.get_hex_uint8() << 24
385 uval |= self.get_hex_uint8() << 16
386 uval |= self.get_hex_uint8() << 8
387 uval |= self.get_hex_uint8()
388 else:
389 uval |= self.get_hex_uint8()
390 uval |= self.get_hex_uint8() << 8
391 uval |= self.get_hex_uint8() << 16
392 uval |= self.get_hex_uint8() << 24
393 uval |= self.get_hex_uint8() << 32
394 uval |= self.get_hex_uint8() << 40
395 uval |= self.get_hex_uint8() << 48
396 uval |= self.get_hex_uint8() << 56
397 return uval
398
399 def get_hex_chars(self, n = 0):
400 str_len = len(self.str)
401 if n == 0:
402 # n was zero, so we need to determine all hex chars and
403 # stop when we hit the end of the string of a non-hex character
404 while n < str_len and self.str[n] in string.hexdigits:
405 n = n + 1
406 else:
407 if n > str_len:
408 return None # Not enough chars
409 # Verify all chars are hex if a length was specified
410 for i in range(n):
411 if self.str[i] not in string.hexdigits:
412 return None # Not all hex digits
413 if n == 0:
414 return None
415 hex_str = self.str[0:n]
416 self.str = self.str[n:]
417 return hex_str
418
419 def get_hex_uint(self, byte_order, n = 0):
420 if byte_order == 'big':
421 hex_str = self.get_hex_chars(n)
422 if hex_str == None:
423 return None
424 return int(hex_str, 16)
425 else:
426 uval = self.get_hex_uint8()
427 if uval == None:
428 return None
429 uval_result = 0
430 shift = 0
431 while uval != None:
432 uval_result |= (uval << shift)
433 shift += 8
434 uval = self.get_hex_uint8()
435 return uval_result
436
437 def get_key_value_pairs(self):
438 kvp = list()
439 key_value_pairs = string.split(self.str, ';')
440 for key_value_pair in key_value_pairs:
441 if len(key_value_pair):
442 kvp.append(string.split(key_value_pair, ':'))
443 return kvp
444
445 def split(self, ch):
446 return string.split(self.str, ch)
447
448 def split_hex(self, ch, byte_order):
449 hex_values = list()
450 strings = string.split(self.str, ch)
451 for str in strings:
452 hex_values.append(Packet(str).get_hex_uint(byte_order))
453 return hex_values
454
455 def __str__(self):
456 return self.str
457
458 def __len__(self):
459 return len(self.str)
460
461g_thread_suffix_regex = re.compile(';thread:([0-9a-fA-F]+);')
462def get_thread_from_thread_suffix(str):
463 if str:
464 match = g_thread_suffix_regex.match (str)
465 if match:
466 return int(match.group(1), 16)
467 return None
468
Greg Claytonf51a23f2012-06-04 23:22:17 +0000469def cmd_stop_reply(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000470 print "get_last_stop_info()"
471
Greg Claytonf51a23f2012-06-04 23:22:17 +0000472def rsp_stop_reply(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000473 global g_byte_order
474 packet = Packet(rsp)
475 stop_type = packet.get_char()
476 if stop_type == 'T' or stop_type == 'S':
477 signo = packet.get_hex_uint8()
478 print ' signal = %i' % signo
479 key_value_pairs = packet.get_key_value_pairs()
480 for key_value_pair in key_value_pairs:
481 key = key_value_pair[0]
482 value = key_value_pair[1]
483 if is_hex_byte(key):
484 reg_num = Packet(key).get_hex_uint8()
Greg Claytonf51a23f2012-06-04 23:22:17 +0000485 print ' ' + get_register_name_equal_value (options, reg_num, value)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000486 else:
487 print ' %s = %s' % (key, value)
488 elif stop_type == 'W':
489 exit_status = packet.get_hex_uint8()
490 print 'exit (status=%i)' % exit_status
491 elif stop_type == 'O':
492 print 'stdout = %s' % packet.str
493
494
Greg Claytonf51a23f2012-06-04 23:22:17 +0000495def cmd_unknown_packet(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000496 if args:
497 print "cmd: %s, args: %s", cmd, args
498 else:
499 print "cmd: %s", cmd
500
Greg Claytonf51a23f2012-06-04 23:22:17 +0000501def cmd_query_packet(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000502 if args:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000503 print "query: %s, args: %s" % (cmd, args)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000504 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000505 print "query: %s" % (cmd)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000506
507def rsp_ok_error(rsp):
508 print "rsp: ", rsp
509
Greg Claytonf51a23f2012-06-04 23:22:17 +0000510def rsp_ok_means_supported(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000511 if rsp == 'OK':
512 print "%s%s is supported" % (cmd, cmd_args)
513 elif rsp == '':
514 print "%s%s is not supported" % (cmd, cmd_args)
515 else:
516 print "%s%s -> %s" % (cmd, cmd_args, rsp)
517
Greg Claytonf51a23f2012-06-04 23:22:17 +0000518def rsp_ok_means_success(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000519 if rsp == 'OK':
520 print "success"
521 elif rsp == '':
522 print "%s%s is not supported" % (cmd, cmd_args)
523 else:
524 print "%s%s -> %s" % (cmd, cmd_args, rsp)
525
Greg Claytonf51a23f2012-06-04 23:22:17 +0000526def rsp_dump_key_value_pairs(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000527 if rsp:
528 packet = Packet(rsp)
529 key_value_pairs = packet.get_key_value_pairs()
530 for key_value_pair in key_value_pairs:
531 key = key_value_pair[0]
532 value = key_value_pair[1]
533 print " %s = %s" % (key, value)
534 else:
535 print "not supported"
536
Greg Claytonf51a23f2012-06-04 23:22:17 +0000537def cmd_vCont(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000538 if args == '?':
539 print "%s: get supported extended continue modes" % (cmd)
540 else:
541 got_other_threads = 0
542 s = ''
543 for thread_action in string.split(args[1:], ';'):
544 (short_action, thread) = string.split(thread_action, ':')
545 tid = int(thread, 16)
546 if short_action == 'c':
547 action = 'continue'
548 elif short_action == 's':
549 action = 'step'
550 elif short_action[0] == 'C':
551 action = 'continue with signal 0x%s' % (short_action[1:])
552 elif short_action == 'S':
553 action = 'step with signal 0x%s' % (short_action[1:])
554 else:
555 action = short_action
556 if s:
557 s += ', '
558 if tid == -1:
559 got_other_threads = 1
560 s += 'other-threads:'
561 else:
562 s += 'thread 0x%4.4x: %s' % (tid, action)
563 if got_other_threads:
564 print "extended_continue (%s)" % (s)
565 else:
566 print "extended_continue (%s, other-threads: suspend)" % (s)
567
Greg Claytonf51a23f2012-06-04 23:22:17 +0000568def rsp_vCont(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000569 if cmd_args == '?':
570 # Skip the leading 'vCont;'
571 rsp = rsp[6:]
572 modes = string.split(rsp, ';')
573 s = "%s: supported extended continue modes include: " % (cmd)
574
575 for i, mode in enumerate(modes):
576 if i:
577 s += ', '
578 if mode == 'c':
579 s += 'continue'
580 elif mode == 'C':
581 s += 'continue with signal'
582 elif mode == 's':
583 s += 'step'
584 elif mode == 'S':
585 s += 'step with signal'
586 else:
587 s += 'unrecognized vCont mode: ', mode
588 print s
589 elif rsp:
590 if rsp[0] == 'T' or rsp[0] == 'S' or rsp[0] == 'W' or rsp[0] == 'X':
Greg Claytonf51a23f2012-06-04 23:22:17 +0000591 rsp_stop_reply (options, cmd, cmd_args, rsp)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000592 return
593 if rsp[0] == 'O':
594 print "stdout: %s" % (rsp)
595 return
596 else:
597 print "not supported (cmd = '%s', args = '%s', rsp = '%s')" % (cmd, cmd_args, rsp)
598
Greg Claytonf51a23f2012-06-04 23:22:17 +0000599def cmd_vAttach(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000600 (extra_command, args) = string.split(args, ';')
601 if extra_command:
602 print "%s%s(%s)" % (cmd, extra_command, args)
603 else:
604 print "attach_pid(%s)" % args
605
Greg Claytonf51a23f2012-06-04 23:22:17 +0000606def cmd_qRegisterInfo(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000607 print 'query_register_info(reg_num=%i)' % (int(args, 16))
608
Greg Claytonf51a23f2012-06-04 23:22:17 +0000609def rsp_qRegisterInfo(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000610 global g_max_register_info_name_len
611 print 'query_register_info(reg_num=%i):' % (int(cmd_args, 16)),
612 if len(rsp) == 3 and rsp[0] == 'E':
613 g_max_register_info_name_len = 0
614 for reg_info in g_register_infos:
615 name_len = len(reg_info.name())
616 if g_max_register_info_name_len < name_len:
617 g_max_register_info_name_len = name_len
618 print' DONE'
619 else:
620 packet = Packet(rsp)
621 reg_info = RegisterInfo(packet.get_key_value_pairs())
622 g_register_infos.append(reg_info)
623 print reg_info
624
625
Greg Claytonf51a23f2012-06-04 23:22:17 +0000626def cmd_qThreadInfo(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000627 if cmd == 'qfThreadInfo':
628 query_type = 'first'
629 else:
630 query_type = 'subsequent'
631 print 'get_current_thread_list(type=%s)' % (query_type)
632
Greg Claytonf51a23f2012-06-04 23:22:17 +0000633def rsp_qThreadInfo(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000634 packet = Packet(rsp)
635 response_type = packet.get_char()
636 if response_type == 'm':
637 tids = packet.split_hex(';', 'big')
638 for i, tid in enumerate(tids):
639 if i:
640 print ',',
641 print '0x%x' % (tid),
642 print
643 elif response_type == 'l':
644 print 'END'
645
Greg Claytonf51a23f2012-06-04 23:22:17 +0000646def rsp_hex_big_endian(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000647 packet = Packet(rsp)
648 uval = packet.get_hex_uint('big')
649 print '%s: 0x%x' % (cmd, uval)
650
Greg Claytonf51a23f2012-06-04 23:22:17 +0000651def cmd_read_memory(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000652 packet = Packet(args)
653 addr = packet.get_hex_uint('big')
654 comma = packet.get_char()
655 size = packet.get_hex_uint('big')
656 print 'read_memory (addr = 0x%x, size = %u)' % (addr, size)
657
658def dump_hex_memory_buffer(addr, hex_byte_str):
659 packet = Packet(hex_byte_str)
660 idx = 0
661 ascii = ''
662 uval = packet.get_hex_uint8()
663 while uval != None:
664 if ((idx % 16) == 0):
665 if ascii:
666 print ' ', ascii
667 ascii = ''
668 print '0x%x:' % (addr + idx),
669 print '%2.2x' % (uval),
670 if 0x20 <= uval and uval < 0x7f:
671 ascii += '%c' % uval
672 else:
673 ascii += '.'
674 uval = packet.get_hex_uint8()
675 idx = idx + 1
676 if ascii:
677 print ' ', ascii
678 ascii = ''
679
Greg Claytonf51a23f2012-06-04 23:22:17 +0000680def cmd_write_memory(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000681 packet = Packet(args)
682 addr = packet.get_hex_uint('big')
683 if packet.get_char() != ',':
684 print 'error: invalid write memory command (missing comma after address)'
685 return
686 size = packet.get_hex_uint('big')
687 if packet.get_char() != ':':
688 print 'error: invalid write memory command (missing colon after size)'
689 return
690 print 'write_memory (addr = 0x%x, size = %u, data:' % (addr, size)
691 dump_hex_memory_buffer (addr, packet.str)
692
Greg Claytonf51a23f2012-06-04 23:22:17 +0000693def cmd_alloc_memory(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000694 packet = Packet(args)
695 byte_size = packet.get_hex_uint('big')
696 if packet.get_char() != ',':
697 print 'error: invalid allocate memory command (missing comma after address)'
698 return
699 print 'allocate_memory (byte-size = %u (0x%x), permissions = %s)' % (byte_size, byte_size, packet.str)
700
Greg Claytonf51a23f2012-06-04 23:22:17 +0000701def rsp_alloc_memory(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000702 packet = Packet(rsp)
703 addr = packet.get_hex_uint('big')
704 print 'addr = 0x%x' % addr
705
Greg Claytonf51a23f2012-06-04 23:22:17 +0000706def cmd_dealloc_memory(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000707 packet = Packet(args)
708 addr = packet.get_hex_uint('big')
709 if packet.get_char() != ',':
710 print 'error: invalid allocate memory command (missing comma after address)'
711 return
712 print 'deallocate_memory (addr = 0x%x, permissions = %s)' % (addr, packet.str)
713
Greg Claytonf51a23f2012-06-04 23:22:17 +0000714def rsp_memory_bytes(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000715 addr = Packet(cmd_args).get_hex_uint('big')
716 dump_hex_memory_buffer (addr, rsp)
717
Greg Claytonf51a23f2012-06-04 23:22:17 +0000718def get_register_name_equal_value(options, reg_num, hex_value_str):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000719 if reg_num < len(g_register_infos):
720 reg_info = g_register_infos[reg_num]
Greg Claytonf51a23f2012-06-04 23:22:17 +0000721 value_str = reg_info.get_value_from_hex_string (hex_value_str)
722 s = reg_info.name() + ' = '
723 if options.symbolicator:
724 symbolicated_addresses = options.symbolicator.symbolicate (int(value_str, 0))
725 if symbolicated_addresses:
726 s += options.colors.magenta()
727 s += '%s' % symbolicated_addresses[0]
728 s += options.colors.reset()
729 return s
730 s += value_str
731 return s
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000732 else:
733 reg_value = Packet(hex_value_str).get_hex_uint(g_byte_order)
734 return 'reg(%u) = 0x%x' % (reg_num, reg_value)
735
Greg Claytonf51a23f2012-06-04 23:22:17 +0000736def cmd_read_one_reg(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000737 packet = Packet(args)
738 reg_num = packet.get_hex_uint('big')
739 tid = get_thread_from_thread_suffix (packet.str)
740 name = None
741 if reg_num < len(g_register_infos):
742 name = g_register_infos[reg_num].name ()
743 if packet.str:
744 packet.get_char() # skip ;
745 thread_info = packet.get_key_value_pairs()
746 tid = int(thread_info[0][1], 16)
747 s = 'read_register (reg_num=%u' % reg_num
748 if name:
749 s += ' (%s)' % (name)
750 if tid != None:
751 s += ', tid = 0x%4.4x' % (tid)
752 s += ')'
753 print s
754
Greg Claytonf51a23f2012-06-04 23:22:17 +0000755def rsp_read_one_reg(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000756 packet = Packet(cmd_args)
757 reg_num = packet.get_hex_uint('big')
Greg Claytonf51a23f2012-06-04 23:22:17 +0000758 print get_register_name_equal_value (options, reg_num, rsp)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000759
Greg Claytonf51a23f2012-06-04 23:22:17 +0000760def cmd_write_one_reg(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000761 packet = Packet(args)
762 reg_num = packet.get_hex_uint('big')
763 if packet.get_char() != '=':
764 print 'error: invalid register write packet'
765 else:
766 name = None
767 hex_value_str = packet.get_hex_chars()
768 tid = get_thread_from_thread_suffix (packet.str)
769 s = 'write_register (reg_num=%u' % reg_num
770 if name:
771 s += ' (%s)' % (name)
772 s += ', value = '
Greg Claytonf51a23f2012-06-04 23:22:17 +0000773 s += get_register_name_equal_value(options, reg_num, hex_value_str)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000774 if tid != None:
775 s += ', tid = 0x%4.4x' % (tid)
776 s += ')'
777 print s
778
779def dump_all_regs(packet):
780 for reg_info in g_register_infos:
781 nibble_size = reg_info.bit_size() / 4
782 hex_value_str = packet.get_hex_chars(nibble_size)
783 if hex_value_str != None:
784 value = reg_info.get_value_from_hex_string (hex_value_str)
785 print '%*s = %s' % (g_max_register_info_name_len, reg_info.name(), value)
786 else:
787 return
788
789def cmd_read_all_regs(cmd, cmd_args):
790 packet = Packet(cmd_args)
791 packet.get_char() # toss the 'g' command character
792 tid = get_thread_from_thread_suffix (packet.str)
793 if tid != None:
794 print 'read_all_register(thread = 0x%4.4x)' % tid
795 else:
796 print 'read_all_register()'
797
Greg Claytonf51a23f2012-06-04 23:22:17 +0000798def rsp_read_all_regs(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000799 packet = Packet(rsp)
800 dump_all_regs (packet)
801
Greg Claytonf51a23f2012-06-04 23:22:17 +0000802def cmd_write_all_regs(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000803 packet = Packet(args)
804 print 'write_all_registers()'
805 dump_all_regs (packet)
806
807g_bp_types = [ "software_bp", "hardware_bp", "write_wp", "read_wp", "access_wp" ]
808
Greg Claytonf51a23f2012-06-04 23:22:17 +0000809def cmd_bp(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000810 if cmd == 'Z':
811 s = 'set_'
812 else:
813 s = 'clear_'
814 packet = Packet (args)
815 bp_type = packet.get_hex_uint('big')
816 packet.get_char() # Skip ,
817 bp_addr = packet.get_hex_uint('big')
818 packet.get_char() # Skip ,
819 bp_size = packet.get_hex_uint('big')
820 s += g_bp_types[bp_type]
821 s += " (addr = 0x%x, size = %u)" % (bp_addr, bp_size)
822 print s
823
Greg Claytonf51a23f2012-06-04 23:22:17 +0000824def cmd_mem_rgn_info(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000825 packet = Packet(args)
826 packet.get_char() # skip ':' character
827 addr = packet.get_hex_uint('big')
828 print 'get_memory_region_info (addr=0x%x)' % (addr)
829
Greg Claytonf51a23f2012-06-04 23:22:17 +0000830def cmd_kill(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000831 print 'kill_process()'
832
833gdb_remote_commands = {
834 '\\?' : { 'cmd' : cmd_stop_reply , 'rsp' : rsp_stop_reply , 'name' : "stop reply pacpket"},
835 'QStartNoAckMode' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_supported , 'name' : "query if no ack mode is supported"},
836 'QThreadSuffixSupported' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_supported , 'name' : "query if thread suffix is supported" },
837 'QListThreadsInStopReply' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_supported , 'name' : "query if threads in stop reply packets are supported" },
Greg Clayton48629002012-08-20 16:50:43 +0000838 '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 +0000839 'qHostInfo' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_dump_key_value_pairs, 'name' : "get host information" },
840 'vCont' : { 'cmd' : cmd_vCont , 'rsp' : rsp_vCont , 'name' : "extended continue command" },
841 'vAttach' : { 'cmd' : cmd_vAttach , 'rsp' : rsp_stop_reply , 'name' : "attach to process" },
842 'qRegisterInfo' : { 'cmd' : cmd_qRegisterInfo , 'rsp' : rsp_qRegisterInfo , 'name' : "query register info" },
843 'qfThreadInfo' : { 'cmd' : cmd_qThreadInfo , 'rsp' : rsp_qThreadInfo , 'name' : "get current thread list" },
844 'qsThreadInfo' : { 'cmd' : cmd_qThreadInfo , 'rsp' : rsp_qThreadInfo , 'name' : "get current thread list" },
845 'qShlibInfoAddr' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_hex_big_endian , 'name' : "get shared library info address" },
846 'qMemoryRegionInfo' : { 'cmd' : cmd_mem_rgn_info , 'rsp' : rsp_dump_key_value_pairs, 'name' : "get memory region information" },
847 'm' : { 'cmd' : cmd_read_memory , 'rsp' : rsp_memory_bytes , 'name' : "read memory" },
848 'M' : { 'cmd' : cmd_write_memory , 'rsp' : rsp_ok_means_success , 'name' : "write memory" },
849 '_M' : { 'cmd' : cmd_alloc_memory , 'rsp' : rsp_alloc_memory , 'name' : "allocate memory" },
850 '_m' : { 'cmd' : cmd_dealloc_memory, 'rsp' : rsp_ok_means_success , 'name' : "deallocate memory" },
851 'p' : { 'cmd' : cmd_read_one_reg , 'rsp' : rsp_read_one_reg , 'name' : "read single register" },
852 'P' : { 'cmd' : cmd_write_one_reg , 'rsp' : rsp_ok_means_success , 'name' : "write single register" },
853 'g' : { 'cmd' : cmd_read_all_regs , 'rsp' : rsp_read_all_regs , 'name' : "read all registers" },
854 'G' : { 'cmd' : cmd_write_all_regs, 'rsp' : rsp_ok_means_success , 'name' : "write all registers" },
855 'z' : { 'cmd' : cmd_bp , 'rsp' : rsp_ok_means_success , 'name' : "clear breakpoint or watchpoint" },
856 'Z' : { 'cmd' : cmd_bp , 'rsp' : rsp_ok_means_success , 'name' : "set breakpoint or watchpoint" },
857 'k' : { 'cmd' : cmd_kill , 'rsp' : rsp_stop_reply , 'name' : "kill process" },
858}
Greg Claytone2841632012-01-26 02:56:24 +0000859def parse_gdb_log_file(file, options):
860 '''Parse a GDB log file that was generated by enabling logging with:
861 (lldb) log enable --threadsafe --timestamp --file <FILE> gdb-remote packets
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +0000862 This log file will contain timestamps and this function will then normalize
Greg Claytone2841632012-01-26 02:56:24 +0000863 those packets to be relative to the first value timestamp that is found and
864 show delta times between log lines and also keep track of how long it takes
865 for GDB remote commands to make a send/receive round trip. This can be
866 handy when trying to figure out why some operation in the debugger is taking
867 a long time during a preset set of debugger commands.'''
868
869 tricky_commands = [ 'qRegisterInfo' ]
870 timestamp_regex = re.compile('(\s*)([1-9][0-9]+\.[0-9]+)([^0-9].*)$')
871 packet_name_regex = re.compile('([A-Za-z_]+)[^a-z]')
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000872 packet_transmit_name_regex = re.compile('(?P<direction>send|read) packet: (?P<packet>.*)')
873 packet_contents_name_regex = re.compile('\$([^#]+)#[0-9a-fA-F]{2}')
874 packet_names_regex_str = '(' + '|'.join(gdb_remote_commands.keys()) + ')(.*)';
875 packet_names_regex = re.compile(packet_names_regex_str);
876
Greg Claytone2841632012-01-26 02:56:24 +0000877 base_time = 0.0
878 last_time = 0.0
879 packet_send_time = 0.0
Greg Claytone2841632012-01-26 02:56:24 +0000880 packet_total_times = {}
Jim Inghamd95752f2012-03-01 18:57:51 +0000881 packet_count = {}
Greg Claytone2841632012-01-26 02:56:24 +0000882 file = open(file)
883 lines = file.read().splitlines()
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000884 last_command = None
885 last_command_args = None
886 last_command_packet = None
Greg Claytone2841632012-01-26 02:56:24 +0000887 for line in lines:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000888 packet_name = None
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000889 m = packet_transmit_name_regex.search(line)
Greg Claytonf51a23f2012-06-04 23:22:17 +0000890 is_command = False
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000891 if m:
892 direction = m.group('direction')
893 is_command = direction == 'send'
894 packet = m.group('packet')
Greg Claytonf51a23f2012-06-04 23:22:17 +0000895 sys.stdout.write(options.colors.green())
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000896 if options.quiet:
897 if is_command:
898 print '-->', packet
899 else:
900 print '<--', packet
901 else:
902 print '# ', line
Greg Claytonf51a23f2012-06-04 23:22:17 +0000903 sys.stdout.write(options.colors.reset())
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000904
905 #print 'direction = "%s", packet = "%s"' % (direction, packet)
906
907 if packet[0] == '+':
908 print 'ACK'
909 elif packet[0] == '-':
910 print 'NACK'
911 elif packet[0] == '$':
912 m = packet_contents_name_regex.match(packet)
913 if m:
914 contents = m.group(1)
915 if is_command:
916 m = packet_names_regex.match (contents)
917 if m:
918 last_command = m.group(1)
Greg Claytonf51a23f2012-06-04 23:22:17 +0000919 packet_name = last_command
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000920 last_command_args = m.group(2)
921 last_command_packet = contents
Greg Claytonf51a23f2012-06-04 23:22:17 +0000922 gdb_remote_commands[last_command]['cmd'](options, last_command, last_command_args)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000923 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000924 packet_match = packet_name_regex.match (line[idx+14:])
925 if packet_match:
926 packet_name = packet_match.group(1)
927 for tricky_cmd in tricky_commands:
928 if packet_name.find (tricky_cmd) == 0:
929 packet_name = tricky_cmd
930 else:
931 packet_name = contents
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000932 last_command = None
933 last_command_args = None
934 last_command_packet = None
935 elif last_command:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000936 gdb_remote_commands[last_command]['rsp'](options, last_command, last_command_args, contents)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000937 else:
938 print 'error: invalid packet: "', packet, '"'
939 else:
940 print '???'
941 else:
942 print '## ', line
Greg Claytone2841632012-01-26 02:56:24 +0000943 match = timestamp_regex.match (line)
944 if match:
945 curr_time = float (match.group(2))
946 delta = 0.0
947 if base_time:
948 delta = curr_time - last_time
949 else:
950 base_time = curr_time
Greg Claytonf51a23f2012-06-04 23:22:17 +0000951
952 if is_command:
Greg Claytone2841632012-01-26 02:56:24 +0000953 packet_send_time = curr_time
Greg Claytone2841632012-01-26 02:56:24 +0000954 elif line.find('read packet: $') >= 0 and packet_name:
955 if packet_name in packet_total_times:
956 packet_total_times[packet_name] += delta
Jim Inghamd95752f2012-03-01 18:57:51 +0000957 packet_count[packet_name] += 1
Greg Claytone2841632012-01-26 02:56:24 +0000958 else:
959 packet_total_times[packet_name] = delta
Jim Inghamd95752f2012-03-01 18:57:51 +0000960 packet_count[packet_name] = 1
Greg Claytone2841632012-01-26 02:56:24 +0000961 packet_name = None
962
963 if not options or not options.quiet:
964 print '%s%.6f %+.6f%s' % (match.group(1), curr_time - base_time, delta, match.group(3))
965 last_time = curr_time
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000966 # else:
967 # print line
Greg Claytone2841632012-01-26 02:56:24 +0000968 if packet_total_times:
969 total_packet_time = 0.0
Jim Inghamd95752f2012-03-01 18:57:51 +0000970 total_packet_count = 0
Greg Claytone2841632012-01-26 02:56:24 +0000971 for key, vvv in packet_total_times.items():
972 # print ' key = (%s) "%s"' % (type(key), key)
973 # print 'value = (%s) %s' % (type(vvv), vvv)
974 # if type(vvv) == 'float':
975 total_packet_time += vvv
Jim Inghamd95752f2012-03-01 18:57:51 +0000976 for key, vvv in packet_count.items():
977 total_packet_count += vvv
978
979 print '#---------------------------------------------------'
Greg Claytone2841632012-01-26 02:56:24 +0000980 print '# Packet timing summary:'
Jim Inghamd95752f2012-03-01 18:57:51 +0000981 print '# Totals: time - %6f count %6d' % (total_packet_time, total_packet_count)
982 print '#---------------------------------------------------'
983 print '# Packet Time (sec) Percent Count '
984 print '#------------------------- ---------- ------- ------'
985 if options and options.sort_count:
986 res = sorted(packet_count, key=packet_count.__getitem__, reverse=True)
987 else:
988 res = sorted(packet_total_times, key=packet_total_times.__getitem__, reverse=True)
989
Greg Claytone2841632012-01-26 02:56:24 +0000990 if last_time > 0.0:
991 for item in res:
992 packet_total_time = packet_total_times[item]
993 packet_percent = (packet_total_time / total_packet_time)*100.0
994 if packet_percent >= 10.0:
Jim Inghamd95752f2012-03-01 18:57:51 +0000995 print " %24s %.6f %.2f%% %6d" % (item, packet_total_time, packet_percent, packet_count[item])
Greg Claytone2841632012-01-26 02:56:24 +0000996 else:
Jim Inghamd95752f2012-03-01 18:57:51 +0000997 print " %24s %.6f %.2f%% %6d" % (item, packet_total_time, packet_percent, packet_count[item])
Greg Claytone2841632012-01-26 02:56:24 +0000998
999
1000
1001if __name__ == '__main__':
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001002 usage = "usage: gdbremote [options]"
1003 description='''The command disassembles a GDB remote packet log.'''
1004 parser = optparse.OptionParser(description=description, prog='gdbremote',usage=usage)
1005 parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
1006 parser.add_option('-q', '--quiet', action='store_true', dest='quiet', help='display verbose debug info', default=False)
1007 parser.add_option('-C', '--color', action='store_true', dest='color', help='add terminal colors', default=False)
1008 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 +00001009 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 +00001010 try:
1011 (options, args) = parser.parse_args(sys.argv[1:])
1012 except:
1013 print 'error: argument error'
1014 sys.exit(1)
1015
Greg Claytonf51a23f2012-06-04 23:22:17 +00001016 options.colors = TerminalColors(options.color)
1017 options.symbolicator = None
1018 if options.crashlog:
1019 import lldb
1020 lldb.debugger = lldb.SBDebugger.Create()
1021 import lldb.macosx.crashlog
1022 options.symbolicator = lldb.macosx.crashlog.CrashLog(options.crashlog)
1023 print '%s' % (options.symbolicator)
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001024
Greg Claytone2841632012-01-26 02:56:24 +00001025 # This script is being run from the command line, create a debugger in case we are
1026 # going to use any debugger functions in our function.
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001027 for file in args:
Greg Claytone2841632012-01-26 02:56:24 +00001028 print '#----------------------------------------------------------------------'
1029 print "# GDB remote log file: '%s'" % file
1030 print '#----------------------------------------------------------------------'
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001031 parse_gdb_log_file (file, options)
Greg Claytonf51a23f2012-06-04 23:22:17 +00001032 if options.symbolicator:
1033 print '%s' % (options.symbolicator)
1034
Greg Claytone2841632012-01-26 02:56:24 +00001035else:
1036 import lldb
1037 if lldb.debugger:
1038 # This initializer is being run from LLDB in the embedded command interpreter
1039 # Add any commands contained in this module to LLDB
1040 lldb.debugger.HandleCommand('command script add -f gdbremote.start_gdb_log start_gdb_log')
1041 lldb.debugger.HandleCommand('command script add -f gdbremote.stop_gdb_log stop_gdb_log')
1042 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'