blob: 4cbfdb2ba333a6a0312e0a6319184ac82fba8ccf [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
Greg Clayton374b6712015-07-02 22:22:45 +000019import binascii
Greg Claytone2841632012-01-26 02:56:24 +000020import commands
Greg Clayton8c2afa02015-07-22 20:12:58 +000021import json
Greg Clayton25f82aa2015-05-22 23:00:59 +000022import math
Greg Claytone2841632012-01-26 02:56:24 +000023import optparse
24import os
Greg Claytone2841632012-01-26 02:56:24 +000025import re
Greg Clayton8ebb9a82012-06-01 20:23:54 +000026import shlex
27import string
28import sys
Greg Claytone2841632012-01-26 02:56:24 +000029import tempfile
Greg Clayton374b6712015-07-02 22:22:45 +000030import xml.etree.ElementTree as ET
Greg Claytone2841632012-01-26 02:56:24 +000031
Greg Claytonf51a23f2012-06-04 23:22:17 +000032#----------------------------------------------------------------------
33# Global variables
34#----------------------------------------------------------------------
35g_log_file = ''
36g_byte_order = 'little'
Greg Clayton205d6182015-07-17 20:16:50 +000037g_number_regex = re.compile('^(0x[0-9a-fA-F]+|[0-9]+)')
Greg Claytona7a5e5a2015-07-17 23:08:14 +000038g_thread_id_regex = re.compile('^(-1|[0-9a-fA-F]+|0)')
Greg Claytonf51a23f2012-06-04 23:22:17 +000039
Greg Clayton8ebb9a82012-06-01 20:23:54 +000040class TerminalColors:
41 '''Simple terminal colors class'''
Greg Claytonf51a23f2012-06-04 23:22:17 +000042 def __init__(self, enabled = True):
Greg Clayton8ebb9a82012-06-01 20:23:54 +000043 # TODO: discover terminal type from "file" and disable if
44 # it can't handle the color codes
45 self.enabled = enabled
46
47 def reset(self):
48 '''Reset all terminal colors and formatting.'''
49 if self.enabled:
Greg Claytonf51a23f2012-06-04 23:22:17 +000050 return "\x1b[0m";
51 return ''
Greg Clayton8ebb9a82012-06-01 20:23:54 +000052
53 def bold(self, on = True):
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000054 '''Enable or disable bold depending on the "on" parameter.'''
Greg Clayton8ebb9a82012-06-01 20:23:54 +000055 if self.enabled:
56 if on:
Greg Claytonf51a23f2012-06-04 23:22:17 +000057 return "\x1b[1m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +000058 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +000059 return "\x1b[22m";
60 return ''
61
Greg Clayton8ebb9a82012-06-01 20:23:54 +000062 def italics(self, on = True):
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000063 '''Enable or disable italics depending on the "on" parameter.'''
Greg Clayton8ebb9a82012-06-01 20:23:54 +000064 if self.enabled:
65 if on:
Greg Claytonf51a23f2012-06-04 23:22:17 +000066 return "\x1b[3m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +000067 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +000068 return "\x1b[23m";
69 return ''
70
Greg Clayton8ebb9a82012-06-01 20:23:54 +000071 def underline(self, on = True):
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000072 '''Enable or disable underline depending on the "on" parameter.'''
Greg Clayton8ebb9a82012-06-01 20:23:54 +000073 if self.enabled:
74 if on:
Greg Claytonf51a23f2012-06-04 23:22:17 +000075 return "\x1b[4m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +000076 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +000077 return "\x1b[24m";
78 return ''
79
Greg Clayton8ebb9a82012-06-01 20:23:54 +000080 def inverse(self, on = True):
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000081 '''Enable or disable inverse depending on the "on" parameter.'''
Greg Clayton8ebb9a82012-06-01 20:23:54 +000082 if self.enabled:
83 if on:
Greg Claytonf51a23f2012-06-04 23:22:17 +000084 return "\x1b[7m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +000085 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +000086 return "\x1b[27m";
87 return ''
88
Greg Clayton8ebb9a82012-06-01 20:23:54 +000089 def strike(self, on = True):
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000090 '''Enable or disable strike through depending on the "on" parameter.'''
Greg Clayton8ebb9a82012-06-01 20:23:54 +000091 if self.enabled:
92 if on:
Greg Claytonf51a23f2012-06-04 23:22:17 +000093 return "\x1b[9m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +000094 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +000095 return "\x1b[29m";
96 return ''
97
Greg Clayton8ebb9a82012-06-01 20:23:54 +000098 def black(self, fg = True):
99 '''Set the foreground or background color to black.
100 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
101 if self.enabled:
102 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000103 return "\x1b[30m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000104 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000105 return "\x1b[40m";
106 return ''
107
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000108 def red(self, fg = True):
109 '''Set the foreground or background color to red.
110 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
111 if self.enabled:
112 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000113 return "\x1b[31m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000114 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000115 return "\x1b[41m";
116 return ''
117
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000118 def green(self, fg = True):
119 '''Set the foreground or background color to green.
120 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
121 if self.enabled:
122 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000123 return "\x1b[32m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000124 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000125 return "\x1b[42m";
126 return ''
127
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000128 def yellow(self, fg = True):
129 '''Set the foreground or background color to yellow.
130 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
131 if self.enabled:
132 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000133 return "\x1b[33m";
Greg Claytona542e082015-07-20 21:22:18 +0000134 else:
135 return "\x1b[43m";
Greg Claytonf51a23f2012-06-04 23:22:17 +0000136 return ''
137
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000138 def blue(self, fg = True):
139 '''Set the foreground or background color to blue.
140 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
141 if self.enabled:
142 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000143 return "\x1b[34m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000144 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000145 return "\x1b[44m";
146 return ''
147
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000148 def magenta(self, fg = True):
149 '''Set the foreground or background color to magenta.
150 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
151 if self.enabled:
152 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000153 return "\x1b[35m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000154 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000155 return "\x1b[45m";
156 return ''
157
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000158 def cyan(self, fg = True):
159 '''Set the foreground or background color to cyan.
160 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
161 if self.enabled:
162 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000163 return "\x1b[36m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000164 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000165 return "\x1b[46m";
166 return ''
167
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000168 def white(self, fg = True):
169 '''Set the foreground or background color to white.
170 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
171 if self.enabled:
172 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000173 return "\x1b[37m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000174 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000175 return "\x1b[47m";
176 return ''
177
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000178 def default(self, fg = True):
179 '''Set the foreground or background color to the default.
180 The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
181 if self.enabled:
182 if fg:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000183 return "\x1b[39m";
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000184 else:
Greg Claytonf51a23f2012-06-04 23:22:17 +0000185 return "\x1b[49m";
186 return ''
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000187
Greg Claytone2841632012-01-26 02:56:24 +0000188
189def start_gdb_log(debugger, command, result, dict):
190 '''Start logging GDB remote packets by enabling logging with timestamps and
191 thread safe logging. Follow a call to this function with a call to "stop_gdb_log"
192 in order to dump out the commands.'''
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000193 global g_log_file
Greg Claytone2841632012-01-26 02:56:24 +0000194 command_args = shlex.split(command)
195 usage = "usage: start_gdb_log [options] [<LOGFILEPATH>]"
196 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
197 be aggregated and displayed.'''
198 parser = optparse.OptionParser(description=description, prog='start_gdb_log',usage=usage)
199 parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
200 try:
201 (options, args) = parser.parse_args(command_args)
202 except:
203 return
204
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000205 if g_log_file:
Pavel Labath4b7dc292015-07-28 15:13:23 +0000206 result.PutCString ('error: logging is already in progress with file "%s"' % g_log_file)
Greg Claytone2841632012-01-26 02:56:24 +0000207 else:
208 args_len = len(args)
209 if args_len == 0:
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000210 g_log_file = tempfile.mktemp()
Greg Claytone2841632012-01-26 02:56:24 +0000211 elif len(args) == 1:
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000212 g_log_file = args[0]
Greg Claytone2841632012-01-26 02:56:24 +0000213
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000214 if g_log_file:
215 debugger.HandleCommand('log enable --threadsafe --timestamp --file "%s" gdb-remote packets' % g_log_file);
216 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 +0000217 return
218
219 result.PutCString ('error: invalid log file path')
220 result.PutCString (usage)
221
222def stop_gdb_log(debugger, command, result, dict):
223 '''Stop logging GDB remote packets to the file that was specified in a call
224 to "start_gdb_log" and normalize the timestamps to be relative to the first
225 timestamp in the log file. Also print out statistics for how long each
226 command took to allow performance bottlenecks to be determined.'''
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000227 global g_log_file
Greg Claytone2841632012-01-26 02:56:24 +0000228 # Any commands whose names might be followed by more valid C identifier
229 # characters must be listed here
230 command_args = shlex.split(command)
231 usage = "usage: stop_gdb_log [options]"
232 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.'''
233 parser = optparse.OptionParser(description=description, prog='stop_gdb_log',usage=usage)
234 parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
235 parser.add_option('-q', '--quiet', action='store_true', dest='quiet', help='display verbose debug info', default=False)
Greg Claytonf51a23f2012-06-04 23:22:17 +0000236 parser.add_option('-C', '--color', action='store_true', dest='color', help='add terminal colors', default=False)
Jim Inghamd95752f2012-03-01 18:57:51 +0000237 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 +0000238 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 +0000239 try:
240 (options, args) = parser.parse_args(command_args)
241 except:
242 return
Greg Claytonf51a23f2012-06-04 23:22:17 +0000243 options.colors = TerminalColors(options.color)
244 options.symbolicator = None
245 if options.symbolicate:
246 if lldb.target:
247 import lldb.utils.symbolication
248 options.symbolicator = lldb.utils.symbolication.Symbolicator()
249 options.symbolicator.target = lldb.target
250 else:
251 print "error: can't symbolicate without a target"
Greg Claytone2841632012-01-26 02:56:24 +0000252
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000253 if not g_log_file:
Greg Claytone2841632012-01-26 02:56:24 +0000254 result.PutCString ('error: logging must have been previously enabled with a call to "stop_gdb_log"')
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000255 elif os.path.exists (g_log_file):
Greg Claytone2841632012-01-26 02:56:24 +0000256 if len(args) == 0:
257 debugger.HandleCommand('log disable gdb-remote packets');
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000258 result.PutCString ("GDB packet logging disabled. Logged packets are in '%s'" % g_log_file)
259 parse_gdb_log_file (g_log_file, options)
Greg Claytone2841632012-01-26 02:56:24 +0000260 else:
261 result.PutCString (usage)
262 else:
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000263 print 'error: the GDB packet log file "%s" does not exist' % g_log_file
Greg Claytone2841632012-01-26 02:56:24 +0000264
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000265def is_hex_byte(str):
266 if len(str) == 2:
267 return str[0] in string.hexdigits and str[1] in string.hexdigits;
268 return False
269
270# global register info list
271g_register_infos = list()
272g_max_register_info_name_len = 0
273
274class RegisterInfo:
275 """Class that represents register information"""
276 def __init__(self, kvp):
277 self.info = dict()
278 for kv in kvp:
279 key = kv[0]
280 value = kv[1]
281 self.info[key] = value
282 def name(self):
283 '''Get the name of the register.'''
284 if self.info and 'name' in self.info:
285 return self.info['name']
286 return None
287
288 def bit_size(self):
289 '''Get the size in bits of the register.'''
290 if self.info and 'bitsize' in self.info:
291 return int(self.info['bitsize'])
292 return 0
293
294 def byte_size(self):
295 '''Get the size in bytes of the register.'''
296 return self.bit_size() / 8
297
298 def get_value_from_hex_string(self, hex_str):
299 '''Dump the register value given a native byte order encoded hex ASCII byte string.'''
300 encoding = self.info['encoding']
301 bit_size = self.bit_size()
302 packet = Packet(hex_str)
303 if encoding == 'uint':
304 uval = packet.get_hex_uint(g_byte_order)
305 if bit_size == 8:
306 return '0x%2.2x' % (uval)
307 elif bit_size == 16:
308 return '0x%4.4x' % (uval)
309 elif bit_size == 32:
310 return '0x%8.8x' % (uval)
311 elif bit_size == 64:
312 return '0x%16.16x' % (uval)
313 bytes = list();
314 uval = packet.get_hex_uint8()
315 while uval != None:
316 bytes.append(uval)
317 uval = packet.get_hex_uint8()
318 value_str = '0x'
319 if g_byte_order == 'little':
320 bytes.reverse()
321 for byte in bytes:
322 value_str += '%2.2x' % byte
323 return '%s' % (value_str)
324
325 def __str__(self):
326 '''Dump the register info key/value pairs'''
327 s = ''
328 for key in self.info.keys():
329 if s:
330 s += ', '
331 s += "%s=%s " % (key, self.info[key])
332 return s
333
334class Packet:
335 """Class that represents a packet that contains string data"""
336 def __init__(self, packet_str):
337 self.str = packet_str
338
339 def peek_char(self):
340 ch = 0
341 if self.str:
342 ch = self.str[0]
343 return ch
344
345 def get_char(self):
346 ch = 0
347 if self.str:
348 ch = self.str[0]
349 self.str = self.str[1:]
350 return ch
351
Greg Clayton205d6182015-07-17 20:16:50 +0000352 def skip_exact_string(self, s):
353 if self.str and self.str.startswith(s):
354 self.str = self.str[len(s):]
355 return True
356 else:
357 return False
358
Greg Claytona7a5e5a2015-07-17 23:08:14 +0000359 def get_thread_id(self, fail_value = -1):
360 match = g_number_regex.match (self.str)
361 if match:
362 number_str = match.group(1)
363 self.str = self.str[len(number_str):]
364 return int(number_str, 0)
365 else:
366 return fail_value
367
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000368 def get_hex_uint8(self):
369 if self.str and len(self.str) >= 2 and self.str[0] in string.hexdigits and self.str[1] in string.hexdigits:
370 uval = int(self.str[0:2], 16)
371 self.str = self.str[2:]
372 return uval
373 return None
374
375 def get_hex_uint16(self, byte_order):
376 uval = 0
377 if byte_order == 'big':
378 uval |= self.get_hex_uint8() << 8
379 uval |= self.get_hex_uint8()
380 else:
381 uval |= self.get_hex_uint8()
382 uval |= self.get_hex_uint8() << 8
383 return uval
384
385 def get_hex_uint32(self, byte_order):
386 uval = 0
387 if byte_order == 'big':
388 uval |= self.get_hex_uint8() << 24
389 uval |= self.get_hex_uint8() << 16
390 uval |= self.get_hex_uint8() << 8
391 uval |= self.get_hex_uint8()
392 else:
393 uval |= self.get_hex_uint8()
394 uval |= self.get_hex_uint8() << 8
395 uval |= self.get_hex_uint8() << 16
396 uval |= self.get_hex_uint8() << 24
397 return uval
398
399 def get_hex_uint64(self, byte_order):
400 uval = 0
401 if byte_order == 'big':
402 uval |= self.get_hex_uint8() << 56
403 uval |= self.get_hex_uint8() << 48
404 uval |= self.get_hex_uint8() << 40
405 uval |= self.get_hex_uint8() << 32
406 uval |= self.get_hex_uint8() << 24
407 uval |= self.get_hex_uint8() << 16
408 uval |= self.get_hex_uint8() << 8
409 uval |= self.get_hex_uint8()
410 else:
411 uval |= self.get_hex_uint8()
412 uval |= self.get_hex_uint8() << 8
413 uval |= self.get_hex_uint8() << 16
414 uval |= self.get_hex_uint8() << 24
415 uval |= self.get_hex_uint8() << 32
416 uval |= self.get_hex_uint8() << 40
417 uval |= self.get_hex_uint8() << 48
418 uval |= self.get_hex_uint8() << 56
419 return uval
420
Greg Clayton205d6182015-07-17 20:16:50 +0000421 def get_number(self, fail_value=-1):
422 '''Get a number from the packet. The number must be in big endian format and should be parsed
423 according to its prefix (starts with "0x" means hex, starts with "0" means octal, starts with
424 [1-9] means decimal, etc)'''
425 match = g_number_regex.match (self.str)
426 if match:
427 number_str = match.group(1)
428 self.str = self.str[len(number_str):]
429 return int(number_str, 0)
430 else:
431 return fail_value
432
433
Greg Clayton374b6712015-07-02 22:22:45 +0000434 def get_hex_ascii_str(self, n=0):
435 hex_chars = self.get_hex_chars(n)
436 if hex_chars:
437 return binascii.unhexlify(hex_chars)
438 else:
439 return None
440
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000441 def get_hex_chars(self, n = 0):
442 str_len = len(self.str)
443 if n == 0:
444 # n was zero, so we need to determine all hex chars and
445 # stop when we hit the end of the string of a non-hex character
446 while n < str_len and self.str[n] in string.hexdigits:
447 n = n + 1
448 else:
449 if n > str_len:
450 return None # Not enough chars
451 # Verify all chars are hex if a length was specified
452 for i in range(n):
453 if self.str[i] not in string.hexdigits:
454 return None # Not all hex digits
455 if n == 0:
456 return None
457 hex_str = self.str[0:n]
458 self.str = self.str[n:]
459 return hex_str
460
461 def get_hex_uint(self, byte_order, n = 0):
462 if byte_order == 'big':
463 hex_str = self.get_hex_chars(n)
464 if hex_str == None:
465 return None
466 return int(hex_str, 16)
467 else:
468 uval = self.get_hex_uint8()
469 if uval == None:
470 return None
471 uval_result = 0
472 shift = 0
473 while uval != None:
474 uval_result |= (uval << shift)
475 shift += 8
476 uval = self.get_hex_uint8()
477 return uval_result
478
479 def get_key_value_pairs(self):
480 kvp = list()
Greg Clayton25f82aa2015-05-22 23:00:59 +0000481 if ';' in self.str:
482 key_value_pairs = string.split(self.str, ';')
483 for key_value_pair in key_value_pairs:
484 if len(key_value_pair):
485 kvp.append(string.split(key_value_pair, ':'))
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000486 return kvp
487
488 def split(self, ch):
489 return string.split(self.str, ch)
490
491 def split_hex(self, ch, byte_order):
492 hex_values = list()
493 strings = string.split(self.str, ch)
494 for str in strings:
495 hex_values.append(Packet(str).get_hex_uint(byte_order))
496 return hex_values
497
498 def __str__(self):
499 return self.str
500
501 def __len__(self):
502 return len(self.str)
503
504g_thread_suffix_regex = re.compile(';thread:([0-9a-fA-F]+);')
505def get_thread_from_thread_suffix(str):
506 if str:
507 match = g_thread_suffix_regex.match (str)
508 if match:
509 return int(match.group(1), 16)
510 return None
511
Greg Claytona7a5e5a2015-07-17 23:08:14 +0000512def cmd_qThreadStopInfo(options, cmd, args):
513 packet = Packet(args)
514 tid = packet.get_hex_uint('big')
515 print "get_thread_stop_info (tid = 0x%x)" % (tid)
516
Greg Claytonf51a23f2012-06-04 23:22:17 +0000517def cmd_stop_reply(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000518 print "get_last_stop_info()"
Greg Clayton205d6182015-07-17 20:16:50 +0000519 return False
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000520
Greg Claytonf51a23f2012-06-04 23:22:17 +0000521def rsp_stop_reply(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000522 global g_byte_order
523 packet = Packet(rsp)
524 stop_type = packet.get_char()
525 if stop_type == 'T' or stop_type == 'S':
526 signo = packet.get_hex_uint8()
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000527 key_value_pairs = packet.get_key_value_pairs()
528 for key_value_pair in key_value_pairs:
529 key = key_value_pair[0]
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000530 if is_hex_byte(key):
531 reg_num = Packet(key).get_hex_uint8()
Greg Clayton374b6712015-07-02 22:22:45 +0000532 if reg_num < len(g_register_infos):
533 reg_info = g_register_infos[reg_num]
534 key_value_pair[0] = reg_info.name()
535 key_value_pair[1] = reg_info.get_value_from_hex_string (key_value_pair[1])
Greg Claytonb2273bd2015-07-17 00:19:31 +0000536 elif key == 'jthreads' or key == 'jstopinfo':
537 key_value_pair[1] = binascii.unhexlify(key_value_pair[1])
Greg Clayton374b6712015-07-02 22:22:45 +0000538 key_value_pairs.insert(0, ['signal', signo])
Greg Clayton8c2afa02015-07-22 20:12:58 +0000539 print 'stop_reply():'
Greg Clayton374b6712015-07-02 22:22:45 +0000540 dump_key_value_pairs (key_value_pairs)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000541 elif stop_type == 'W':
542 exit_status = packet.get_hex_uint8()
Greg Clayton8c2afa02015-07-22 20:12:58 +0000543 print 'stop_reply(): exit (status=%i)' % exit_status
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000544 elif stop_type == 'O':
Greg Clayton8c2afa02015-07-22 20:12:58 +0000545 print 'stop_reply(): stdout = "%s"' % packet.str
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000546
547
Greg Claytonf51a23f2012-06-04 23:22:17 +0000548def cmd_unknown_packet(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000549 if args:
550 print "cmd: %s, args: %s", cmd, args
551 else:
552 print "cmd: %s", cmd
Greg Clayton205d6182015-07-17 20:16:50 +0000553 return False
554
555def cmd_qSymbol(options, cmd, args):
556 if args == ':':
557 print 'ready to serve symbols'
558 else:
559 packet = Packet(args)
560 symbol_addr = packet.get_hex_uint('big')
561 if symbol_addr is None:
562 if packet.skip_exact_string(':'):
563 symbol_name = packet.get_hex_ascii_str()
564 print 'lookup_symbol("%s") -> symbol not available yet' % (symbol_name)
565 else:
566 print 'error: bad command format'
567 else:
568 if packet.skip_exact_string(':'):
569 symbol_name = packet.get_hex_ascii_str()
570 print 'lookup_symbol("%s") -> 0x%x' % (symbol_name, symbol_addr)
571 else:
572 print 'error: bad command format'
573
574def rsp_qSymbol(options, cmd, cmd_args, rsp):
575 if len(rsp) == 0:
576 print "Unsupported"
577 else:
578 if rsp == "OK":
579 print "No more symbols to lookup"
580 else:
581 packet = Packet(rsp)
582 if packet.skip_exact_string("qSymbol:"):
583 symbol_name = packet.get_hex_ascii_str()
584 print 'lookup_symbol("%s")' % (symbol_name)
585 else:
586 print 'error: response string should start with "qSymbol:": respnse is "%s"' % (rsp)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000587
Greg Clayton374b6712015-07-02 22:22:45 +0000588def cmd_qXfer(options, cmd, args):
589 # $qXfer:features:read:target.xml:0,1ffff#14
590 print "read target special data %s" % (args)
Greg Clayton205d6182015-07-17 20:16:50 +0000591 return True
Greg Clayton374b6712015-07-02 22:22:45 +0000592
593def rsp_qXfer(options, cmd, cmd_args, rsp):
594 data = string.split(cmd_args, ':')
595 if data[0] == 'features':
596 if data[1] == 'read':
597 filename, extension = os.path.splitext(data[2])
598 if extension == '.xml':
599 response = Packet(rsp)
600 xml_string = response.get_hex_ascii_str()
601 ch = xml_string[0]
602 if ch == 'l':
603 xml_string = xml_string[1:]
604 xml_root = ET.fromstring(xml_string)
605 for reg_element in xml_root.findall("./feature/reg"):
606 if not 'value_regnums' in reg_element.attrib:
607 reg_info = RegisterInfo([])
608 if 'name' in reg_element.attrib:
609 reg_info.info['name'] = reg_element.attrib['name']
610 else:
611 reg_info.info['name'] = 'unspecified'
612 if 'encoding' in reg_element.attrib:
613 reg_info.info['encoding'] = reg_element.attrib['encoding']
614 else:
615 reg_info.info['encoding'] = 'uint'
616 if 'offset' in reg_element.attrib:
617 reg_info.info['offset'] = reg_element.attrib['offset']
618 if 'bitsize' in reg_element.attrib:
619 reg_info.info['bitsize'] = reg_element.attrib['bitsize']
620 g_register_infos.append(reg_info)
Greg Clayton205d6182015-07-17 20:16:50 +0000621 print 'XML for "%s":' % (data[2])
622 ET.dump(xml_root)
Greg Claytona7a5e5a2015-07-17 23:08:14 +0000623
624def cmd_A(options, cmd, args):
625 print 'launch process:'
626 packet = Packet(args)
627 while 1:
628 arg_len = packet.get_number()
Greg Claytona542e082015-07-20 21:22:18 +0000629 if arg_len == -1:
630 break
Greg Claytona7a5e5a2015-07-17 23:08:14 +0000631 if not packet.skip_exact_string(','):
632 break
633 arg_idx = packet.get_number()
Greg Claytona542e082015-07-20 21:22:18 +0000634 if arg_idx == -1:
635 break
Greg Claytona7a5e5a2015-07-17 23:08:14 +0000636 if not packet.skip_exact_string(','):
637 break;
638 arg_value = packet.get_hex_ascii_str(arg_len)
639 print 'argv[%u] = "%s"' % (arg_idx, arg_value)
640
641def cmd_qC(options, cmd, args):
642 print "query_current_thread_id()"
643
644def rsp_qC(options, cmd, cmd_args, rsp):
645 packet = Packet(rsp)
646 if packet.skip_exact_string("QC"):
647 tid = packet.get_thread_id()
648 print "current_thread_id = %#x" % (tid)
649 else:
650 print "current_thread_id = old thread ID"
651
Greg Claytonf51a23f2012-06-04 23:22:17 +0000652def cmd_query_packet(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000653 if args:
Greg Clayton205d6182015-07-17 20:16:50 +0000654 print "%s%s" % (cmd, args)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000655 else:
Greg Clayton205d6182015-07-17 20:16:50 +0000656 print "%s" % (cmd)
657 return False
658
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000659def rsp_ok_error(rsp):
660 print "rsp: ", rsp
661
Greg Claytonf51a23f2012-06-04 23:22:17 +0000662def rsp_ok_means_supported(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000663 if rsp == 'OK':
664 print "%s%s is supported" % (cmd, cmd_args)
665 elif rsp == '':
666 print "%s%s is not supported" % (cmd, cmd_args)
667 else:
668 print "%s%s -> %s" % (cmd, cmd_args, rsp)
669
Greg Claytonf51a23f2012-06-04 23:22:17 +0000670def rsp_ok_means_success(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000671 if rsp == 'OK':
672 print "success"
673 elif rsp == '':
674 print "%s%s is not supported" % (cmd, cmd_args)
675 else:
676 print "%s%s -> %s" % (cmd, cmd_args, rsp)
677
Greg Clayton374b6712015-07-02 22:22:45 +0000678def dump_key_value_pairs(key_value_pairs):
679 max_key_len = 0
680 for key_value_pair in key_value_pairs:
681 key_len = len(key_value_pair[0])
682 if max_key_len < key_len:
683 max_key_len = key_len
684 for key_value_pair in key_value_pairs:
685 key = key_value_pair[0]
686 value = key_value_pair[1]
687 print "%*s = %s" % (max_key_len, key, value)
688
Greg Claytonf51a23f2012-06-04 23:22:17 +0000689def rsp_dump_key_value_pairs(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000690 if rsp:
Greg Clayton205d6182015-07-17 20:16:50 +0000691 print '%s response:' % (cmd)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000692 packet = Packet(rsp)
693 key_value_pairs = packet.get_key_value_pairs()
Greg Clayton374b6712015-07-02 22:22:45 +0000694 dump_key_value_pairs(key_value_pairs)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000695 else:
696 print "not supported"
697
Greg Claytonb2273bd2015-07-17 00:19:31 +0000698def cmd_c(options, cmd, args):
699 print "continue()"
Greg Clayton205d6182015-07-17 20:16:50 +0000700 return False
Greg Claytonb2273bd2015-07-17 00:19:31 +0000701
702def cmd_s(options, cmd, args):
703 print "step()"
Greg Clayton205d6182015-07-17 20:16:50 +0000704 return False
Greg Claytonb2273bd2015-07-17 00:19:31 +0000705
Greg Claytonf51a23f2012-06-04 23:22:17 +0000706def cmd_vCont(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000707 if args == '?':
708 print "%s: get supported extended continue modes" % (cmd)
709 else:
710 got_other_threads = 0
711 s = ''
712 for thread_action in string.split(args[1:], ';'):
713 (short_action, thread) = string.split(thread_action, ':')
714 tid = int(thread, 16)
715 if short_action == 'c':
716 action = 'continue'
717 elif short_action == 's':
718 action = 'step'
719 elif short_action[0] == 'C':
720 action = 'continue with signal 0x%s' % (short_action[1:])
721 elif short_action == 'S':
722 action = 'step with signal 0x%s' % (short_action[1:])
723 else:
724 action = short_action
725 if s:
726 s += ', '
727 if tid == -1:
728 got_other_threads = 1
729 s += 'other-threads:'
730 else:
731 s += 'thread 0x%4.4x: %s' % (tid, action)
732 if got_other_threads:
733 print "extended_continue (%s)" % (s)
734 else:
735 print "extended_continue (%s, other-threads: suspend)" % (s)
Greg Clayton205d6182015-07-17 20:16:50 +0000736 return False
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000737
Greg Claytonf51a23f2012-06-04 23:22:17 +0000738def rsp_vCont(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000739 if cmd_args == '?':
740 # Skip the leading 'vCont;'
741 rsp = rsp[6:]
742 modes = string.split(rsp, ';')
743 s = "%s: supported extended continue modes include: " % (cmd)
744
745 for i, mode in enumerate(modes):
746 if i:
747 s += ', '
748 if mode == 'c':
749 s += 'continue'
750 elif mode == 'C':
751 s += 'continue with signal'
752 elif mode == 's':
753 s += 'step'
754 elif mode == 'S':
755 s += 'step with signal'
756 else:
757 s += 'unrecognized vCont mode: ', mode
758 print s
759 elif rsp:
760 if rsp[0] == 'T' or rsp[0] == 'S' or rsp[0] == 'W' or rsp[0] == 'X':
Greg Claytonf51a23f2012-06-04 23:22:17 +0000761 rsp_stop_reply (options, cmd, cmd_args, rsp)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000762 return
763 if rsp[0] == 'O':
764 print "stdout: %s" % (rsp)
765 return
766 else:
767 print "not supported (cmd = '%s', args = '%s', rsp = '%s')" % (cmd, cmd_args, rsp)
768
Greg Claytonf51a23f2012-06-04 23:22:17 +0000769def cmd_vAttach(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000770 (extra_command, args) = string.split(args, ';')
771 if extra_command:
772 print "%s%s(%s)" % (cmd, extra_command, args)
773 else:
Greg Clayton205d6182015-07-17 20:16:50 +0000774 print "attach(pid = %u)" % int(args, 16)
775 return False
776
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000777
Greg Claytonf51a23f2012-06-04 23:22:17 +0000778def cmd_qRegisterInfo(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000779 print 'query_register_info(reg_num=%i)' % (int(args, 16))
Greg Clayton205d6182015-07-17 20:16:50 +0000780 return False
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000781
Greg Claytonf51a23f2012-06-04 23:22:17 +0000782def rsp_qRegisterInfo(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000783 global g_max_register_info_name_len
784 print 'query_register_info(reg_num=%i):' % (int(cmd_args, 16)),
785 if len(rsp) == 3 and rsp[0] == 'E':
786 g_max_register_info_name_len = 0
787 for reg_info in g_register_infos:
788 name_len = len(reg_info.name())
789 if g_max_register_info_name_len < name_len:
790 g_max_register_info_name_len = name_len
791 print' DONE'
792 else:
793 packet = Packet(rsp)
794 reg_info = RegisterInfo(packet.get_key_value_pairs())
795 g_register_infos.append(reg_info)
796 print reg_info
Greg Clayton205d6182015-07-17 20:16:50 +0000797 return False
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000798
Greg Claytonf51a23f2012-06-04 23:22:17 +0000799def cmd_qThreadInfo(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000800 if cmd == 'qfThreadInfo':
801 query_type = 'first'
802 else:
803 query_type = 'subsequent'
804 print 'get_current_thread_list(type=%s)' % (query_type)
Greg Clayton205d6182015-07-17 20:16:50 +0000805 return False
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000806
Greg Claytonf51a23f2012-06-04 23:22:17 +0000807def rsp_qThreadInfo(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000808 packet = Packet(rsp)
809 response_type = packet.get_char()
810 if response_type == 'm':
811 tids = packet.split_hex(';', 'big')
812 for i, tid in enumerate(tids):
813 if i:
814 print ',',
815 print '0x%x' % (tid),
816 print
817 elif response_type == 'l':
818 print 'END'
819
Greg Claytonf51a23f2012-06-04 23:22:17 +0000820def rsp_hex_big_endian(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000821 packet = Packet(rsp)
822 uval = packet.get_hex_uint('big')
823 print '%s: 0x%x' % (cmd, uval)
824
Greg Clayton205d6182015-07-17 20:16:50 +0000825def cmd_read_mem_bin(options, cmd, args):
826 # x0x7fff5fc39200,0x200
827 packet = Packet(args)
828 addr = packet.get_number()
829 comma = packet.get_char()
830 size = packet.get_number()
831 print 'binary_read_memory (addr = 0x%16.16x, size = %u)' % (addr, size)
832 return False
833
834def rsp_mem_bin_bytes(options, cmd, cmd_args, rsp):
835 packet = Packet(cmd_args)
836 addr = packet.get_number()
837 comma = packet.get_char()
838 size = packet.get_number()
839 print 'memory:'
840 if size > 0:
841 dump_hex_memory_buffer (addr, rsp)
842
Greg Claytonf51a23f2012-06-04 23:22:17 +0000843def cmd_read_memory(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000844 packet = Packet(args)
845 addr = packet.get_hex_uint('big')
846 comma = packet.get_char()
847 size = packet.get_hex_uint('big')
Greg Clayton205d6182015-07-17 20:16:50 +0000848 print 'read_memory (addr = 0x%16.16x, size = %u)' % (addr, size)
849 return False
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000850
851def dump_hex_memory_buffer(addr, hex_byte_str):
852 packet = Packet(hex_byte_str)
853 idx = 0
854 ascii = ''
855 uval = packet.get_hex_uint8()
856 while uval != None:
857 if ((idx % 16) == 0):
858 if ascii:
859 print ' ', ascii
860 ascii = ''
861 print '0x%x:' % (addr + idx),
862 print '%2.2x' % (uval),
863 if 0x20 <= uval and uval < 0x7f:
864 ascii += '%c' % uval
865 else:
866 ascii += '.'
867 uval = packet.get_hex_uint8()
868 idx = idx + 1
869 if ascii:
870 print ' ', ascii
871 ascii = ''
872
Greg Claytonf51a23f2012-06-04 23:22:17 +0000873def cmd_write_memory(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000874 packet = Packet(args)
875 addr = packet.get_hex_uint('big')
876 if packet.get_char() != ',':
877 print 'error: invalid write memory command (missing comma after address)'
878 return
879 size = packet.get_hex_uint('big')
880 if packet.get_char() != ':':
881 print 'error: invalid write memory command (missing colon after size)'
882 return
Greg Clayton205d6182015-07-17 20:16:50 +0000883 print 'write_memory (addr = 0x%16.16x, size = %u, data:' % (addr, size)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000884 dump_hex_memory_buffer (addr, packet.str)
Greg Clayton205d6182015-07-17 20:16:50 +0000885 return False
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000886
Greg Claytonf51a23f2012-06-04 23:22:17 +0000887def cmd_alloc_memory(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000888 packet = Packet(args)
889 byte_size = packet.get_hex_uint('big')
890 if packet.get_char() != ',':
891 print 'error: invalid allocate memory command (missing comma after address)'
892 return
893 print 'allocate_memory (byte-size = %u (0x%x), permissions = %s)' % (byte_size, byte_size, packet.str)
Greg Clayton205d6182015-07-17 20:16:50 +0000894 return False
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000895
Greg Claytonf51a23f2012-06-04 23:22:17 +0000896def rsp_alloc_memory(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000897 packet = Packet(rsp)
898 addr = packet.get_hex_uint('big')
899 print 'addr = 0x%x' % addr
900
Greg Claytonf51a23f2012-06-04 23:22:17 +0000901def cmd_dealloc_memory(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000902 packet = Packet(args)
903 addr = packet.get_hex_uint('big')
904 if packet.get_char() != ',':
905 print 'error: invalid allocate memory command (missing comma after address)'
Greg Clayton205d6182015-07-17 20:16:50 +0000906 else:
907 print 'deallocate_memory (addr = 0x%x, permissions = %s)' % (addr, packet.str)
908 return False
Greg Claytonf51a23f2012-06-04 23:22:17 +0000909def rsp_memory_bytes(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000910 addr = Packet(cmd_args).get_hex_uint('big')
911 dump_hex_memory_buffer (addr, rsp)
912
Greg Claytonf51a23f2012-06-04 23:22:17 +0000913def get_register_name_equal_value(options, reg_num, hex_value_str):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000914 if reg_num < len(g_register_infos):
915 reg_info = g_register_infos[reg_num]
Greg Claytonf51a23f2012-06-04 23:22:17 +0000916 value_str = reg_info.get_value_from_hex_string (hex_value_str)
917 s = reg_info.name() + ' = '
918 if options.symbolicator:
919 symbolicated_addresses = options.symbolicator.symbolicate (int(value_str, 0))
920 if symbolicated_addresses:
921 s += options.colors.magenta()
922 s += '%s' % symbolicated_addresses[0]
923 s += options.colors.reset()
924 return s
925 s += value_str
926 return s
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000927 else:
928 reg_value = Packet(hex_value_str).get_hex_uint(g_byte_order)
929 return 'reg(%u) = 0x%x' % (reg_num, reg_value)
930
Greg Claytonf51a23f2012-06-04 23:22:17 +0000931def cmd_read_one_reg(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000932 packet = Packet(args)
933 reg_num = packet.get_hex_uint('big')
934 tid = get_thread_from_thread_suffix (packet.str)
935 name = None
936 if reg_num < len(g_register_infos):
937 name = g_register_infos[reg_num].name ()
938 if packet.str:
939 packet.get_char() # skip ;
940 thread_info = packet.get_key_value_pairs()
941 tid = int(thread_info[0][1], 16)
942 s = 'read_register (reg_num=%u' % reg_num
943 if name:
944 s += ' (%s)' % (name)
945 if tid != None:
946 s += ', tid = 0x%4.4x' % (tid)
947 s += ')'
948 print s
Greg Clayton205d6182015-07-17 20:16:50 +0000949 return False
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000950
Greg Claytonf51a23f2012-06-04 23:22:17 +0000951def rsp_read_one_reg(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000952 packet = Packet(cmd_args)
953 reg_num = packet.get_hex_uint('big')
Greg Claytonf51a23f2012-06-04 23:22:17 +0000954 print get_register_name_equal_value (options, reg_num, rsp)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000955
Greg Claytonf51a23f2012-06-04 23:22:17 +0000956def cmd_write_one_reg(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000957 packet = Packet(args)
958 reg_num = packet.get_hex_uint('big')
959 if packet.get_char() != '=':
960 print 'error: invalid register write packet'
961 else:
962 name = None
963 hex_value_str = packet.get_hex_chars()
964 tid = get_thread_from_thread_suffix (packet.str)
965 s = 'write_register (reg_num=%u' % reg_num
966 if name:
967 s += ' (%s)' % (name)
968 s += ', value = '
Greg Claytonf51a23f2012-06-04 23:22:17 +0000969 s += get_register_name_equal_value(options, reg_num, hex_value_str)
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000970 if tid != None:
971 s += ', tid = 0x%4.4x' % (tid)
972 s += ')'
973 print s
Greg Clayton205d6182015-07-17 20:16:50 +0000974 return False
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000975
976def dump_all_regs(packet):
977 for reg_info in g_register_infos:
978 nibble_size = reg_info.bit_size() / 4
979 hex_value_str = packet.get_hex_chars(nibble_size)
980 if hex_value_str != None:
981 value = reg_info.get_value_from_hex_string (hex_value_str)
982 print '%*s = %s' % (g_max_register_info_name_len, reg_info.name(), value)
983 else:
984 return
985
986def cmd_read_all_regs(cmd, cmd_args):
987 packet = Packet(cmd_args)
988 packet.get_char() # toss the 'g' command character
989 tid = get_thread_from_thread_suffix (packet.str)
990 if tid != None:
991 print 'read_all_register(thread = 0x%4.4x)' % tid
992 else:
993 print 'read_all_register()'
Greg Clayton205d6182015-07-17 20:16:50 +0000994 return False
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000995
Greg Claytonf51a23f2012-06-04 23:22:17 +0000996def rsp_read_all_regs(options, cmd, cmd_args, rsp):
Greg Clayton8ebb9a82012-06-01 20:23:54 +0000997 packet = Packet(rsp)
998 dump_all_regs (packet)
999
Greg Claytonf51a23f2012-06-04 23:22:17 +00001000def cmd_write_all_regs(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001001 packet = Packet(args)
1002 print 'write_all_registers()'
1003 dump_all_regs (packet)
Greg Clayton205d6182015-07-17 20:16:50 +00001004 return False
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001005
1006g_bp_types = [ "software_bp", "hardware_bp", "write_wp", "read_wp", "access_wp" ]
1007
Greg Claytonf51a23f2012-06-04 23:22:17 +00001008def cmd_bp(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001009 if cmd == 'Z':
1010 s = 'set_'
1011 else:
1012 s = 'clear_'
1013 packet = Packet (args)
1014 bp_type = packet.get_hex_uint('big')
1015 packet.get_char() # Skip ,
1016 bp_addr = packet.get_hex_uint('big')
1017 packet.get_char() # Skip ,
1018 bp_size = packet.get_hex_uint('big')
1019 s += g_bp_types[bp_type]
1020 s += " (addr = 0x%x, size = %u)" % (bp_addr, bp_size)
1021 print s
Greg Clayton205d6182015-07-17 20:16:50 +00001022 return False
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001023
Greg Claytonf51a23f2012-06-04 23:22:17 +00001024def cmd_mem_rgn_info(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001025 packet = Packet(args)
1026 packet.get_char() # skip ':' character
1027 addr = packet.get_hex_uint('big')
1028 print 'get_memory_region_info (addr=0x%x)' % (addr)
Greg Clayton205d6182015-07-17 20:16:50 +00001029 return False
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001030
Greg Claytonf51a23f2012-06-04 23:22:17 +00001031def cmd_kill(options, cmd, args):
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001032 print 'kill_process()'
Greg Clayton205d6182015-07-17 20:16:50 +00001033 return False
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001034
Greg Clayton8c2afa02015-07-22 20:12:58 +00001035def cmd_jThreadsInfo(options, cmd, args):
1036 print 'jThreadsInfo()'
1037 return False
1038
1039def cmd_jGetLoadedDynamicLibrariesInfos(options, cmd, args):
1040 print 'jGetLoadedDynamicLibrariesInfos()'
1041 return False
1042
1043def decode_packet(s, start_index = 0):
1044 #print '\ndecode_packet("%s")' % (s[start_index:])
1045 index = s.find('}', start_index)
1046 have_escapes = index != -1
1047 if have_escapes:
1048 normal_s = s[start_index:index]
1049 else:
1050 normal_s = s[start_index:]
1051 #print 'normal_s = "%s"' % (normal_s)
1052 if have_escapes:
1053 escape_char = '%c' % (ord(s[index+1]) ^ 0x20)
1054 #print 'escape_char for "%s" = %c' % (s[index:index+2], escape_char)
1055 return normal_s + escape_char + decode_packet(s, index+2)
1056 else:
1057 return normal_s
1058
1059def rsp_json(options, cmd, cmd_args, rsp):
1060 print '%s() reply:' % (cmd)
1061 json_tree = json.loads(rsp)
1062 print json.dumps(json_tree, indent=4, separators=(',', ': '))
1063
1064
1065def rsp_jGetLoadedDynamicLibrariesInfos(options, cmd, cmd_args, rsp):
1066 if cmd_args:
1067 rsp_json(options, cmd, cmd_args, rsp)
1068 else:
1069 rsp_ok_means_supported(options, cmd, cmd_args, rsp)
1070
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001071gdb_remote_commands = {
Greg Claytona7a5e5a2015-07-17 23:08:14 +00001072 '\\?' : { 'cmd' : cmd_stop_reply , 'rsp' : rsp_stop_reply , 'name' : "stop reply pacpket"},
1073 'qThreadStopInfo' : { 'cmd' : cmd_qThreadStopInfo , 'rsp' : rsp_stop_reply , 'name' : "stop reply pacpket"},
1074 'QStartNoAckMode' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_supported , 'name' : "query if no ack mode is supported"},
1075 'QThreadSuffixSupported' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_supported , 'name' : "query if thread suffix is supported" },
1076 'QListThreadsInStopReply' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_supported , 'name' : "query if threads in stop reply packets are supported" },
1077 'QSetDetachOnError' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_success , 'name' : "set if we should detach on error" },
1078 'QSetDisableASLR' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_success , 'name' : "set if we should disable ASLR" },
1079 'qLaunchSuccess' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_success , 'name' : "check on launch success for the A packet" },
1080 'A' : { 'cmd' : cmd_A , 'rsp' : rsp_ok_means_success , 'name' : "launch process" },
1081 'QLaunchArch' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_supported , 'name' : "set if we should disable ASLR" },
1082 'qVAttachOrWaitSupported' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_supported , 'name' : "set the launch architecture" },
1083 'qHostInfo' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_dump_key_value_pairs, 'name' : "get host information" },
1084 'qC' : { 'cmd' : cmd_qC , 'rsp' : rsp_qC , 'name' : "return the current thread ID" },
1085 'vCont' : { 'cmd' : cmd_vCont , 'rsp' : rsp_vCont , 'name' : "extended continue command" },
1086 'vAttach' : { 'cmd' : cmd_vAttach , 'rsp' : rsp_stop_reply , 'name' : "attach to process" },
1087 'c' : { 'cmd' : cmd_c , 'rsp' : rsp_stop_reply , 'name' : "continue" },
1088 's' : { 'cmd' : cmd_s , 'rsp' : rsp_stop_reply , 'name' : "step" },
1089 'qRegisterInfo' : { 'cmd' : cmd_qRegisterInfo , 'rsp' : rsp_qRegisterInfo , 'name' : "query register info" },
1090 'qfThreadInfo' : { 'cmd' : cmd_qThreadInfo , 'rsp' : rsp_qThreadInfo , 'name' : "get current thread list" },
1091 'qsThreadInfo' : { 'cmd' : cmd_qThreadInfo , 'rsp' : rsp_qThreadInfo , 'name' : "get current thread list" },
1092 'qShlibInfoAddr' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_hex_big_endian , 'name' : "get shared library info address" },
1093 'qMemoryRegionInfo' : { 'cmd' : cmd_mem_rgn_info , 'rsp' : rsp_dump_key_value_pairs, 'name' : "get memory region information" },
1094 'qProcessInfo' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_dump_key_value_pairs, 'name' : "get process info" },
1095 'qSupported' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_supported , 'name' : "query supported" },
1096 'qXfer:' : { 'cmd' : cmd_qXfer , 'rsp' : rsp_qXfer , 'name' : "qXfer" },
1097 'qSymbol:' : { 'cmd' : cmd_qSymbol , 'rsp' : rsp_qSymbol , 'name' : "qSymbol" },
1098 'x' : { 'cmd' : cmd_read_mem_bin , 'rsp' : rsp_mem_bin_bytes , 'name' : "read memory binary" },
1099 'X' : { 'cmd' : cmd_write_memory , 'rsp' : rsp_ok_means_success , 'name' : "write memory binary" },
1100 'm' : { 'cmd' : cmd_read_memory , 'rsp' : rsp_memory_bytes , 'name' : "read memory" },
1101 'M' : { 'cmd' : cmd_write_memory , 'rsp' : rsp_ok_means_success , 'name' : "write memory" },
1102 '_M' : { 'cmd' : cmd_alloc_memory , 'rsp' : rsp_alloc_memory , 'name' : "allocate memory" },
1103 '_m' : { 'cmd' : cmd_dealloc_memory , 'rsp' : rsp_ok_means_success , 'name' : "deallocate memory" },
1104 'p' : { 'cmd' : cmd_read_one_reg , 'rsp' : rsp_read_one_reg , 'name' : "read single register" },
1105 'P' : { 'cmd' : cmd_write_one_reg , 'rsp' : rsp_ok_means_success , 'name' : "write single register" },
1106 'g' : { 'cmd' : cmd_read_all_regs , 'rsp' : rsp_read_all_regs , 'name' : "read all registers" },
1107 'G' : { 'cmd' : cmd_write_all_regs , 'rsp' : rsp_ok_means_success , 'name' : "write all registers" },
1108 'z' : { 'cmd' : cmd_bp , 'rsp' : rsp_ok_means_success , 'name' : "clear breakpoint or watchpoint" },
1109 'Z' : { 'cmd' : cmd_bp , 'rsp' : rsp_ok_means_success , 'name' : "set breakpoint or watchpoint" },
1110 'k' : { 'cmd' : cmd_kill , 'rsp' : rsp_stop_reply , 'name' : "kill process" },
Greg Clayton8c2afa02015-07-22 20:12:58 +00001111 'jThreadsInfo' : { 'cmd' : cmd_jThreadsInfo , 'rsp' : rsp_json , 'name' : "JSON get all threads info" },
1112 'jGetLoadedDynamicLibrariesInfos:' : { 'cmd' : cmd_jGetLoadedDynamicLibrariesInfos, 'rsp' : rsp_jGetLoadedDynamicLibrariesInfos, 'name' : 'JSON get loaded dynamic libraries' },
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001113}
Greg Clayton25f82aa2015-05-22 23:00:59 +00001114
1115def calculate_mean_and_standard_deviation(floats):
1116 sum = 0.0
1117 count = len(floats)
Greg Claytonb2273bd2015-07-17 00:19:31 +00001118 if count == 0:
1119 return (0.0, 0.0)
Greg Clayton25f82aa2015-05-22 23:00:59 +00001120 for f in floats:
1121 sum += f
1122 mean = sum / count
1123 accum = 0.0
1124 for f in floats:
1125 delta = f - mean
1126 accum += delta * delta
1127
1128 std_dev = math.sqrt(accum / (count-1));
1129 return (mean, std_dev)
Greg Claytonb2273bd2015-07-17 00:19:31 +00001130
1131def parse_gdb_log_file(path, options):
1132 f = open(path)
Greg Clayton205d6182015-07-17 20:16:50 +00001133 parse_gdb_log(f, options)
Greg Claytonb2273bd2015-07-17 00:19:31 +00001134 f.close()
Greg Clayton25f82aa2015-05-22 23:00:59 +00001135
Greg Claytonb2273bd2015-07-17 00:19:31 +00001136def parse_gdb_log(file, options):
Greg Claytone2841632012-01-26 02:56:24 +00001137 '''Parse a GDB log file that was generated by enabling logging with:
1138 (lldb) log enable --threadsafe --timestamp --file <FILE> gdb-remote packets
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +00001139 This log file will contain timestamps and this function will then normalize
Greg Claytone2841632012-01-26 02:56:24 +00001140 those packets to be relative to the first value timestamp that is found and
1141 show delta times between log lines and also keep track of how long it takes
1142 for GDB remote commands to make a send/receive round trip. This can be
1143 handy when trying to figure out why some operation in the debugger is taking
1144 a long time during a preset set of debugger commands.'''
1145
1146 tricky_commands = [ 'qRegisterInfo' ]
1147 timestamp_regex = re.compile('(\s*)([1-9][0-9]+\.[0-9]+)([^0-9].*)$')
1148 packet_name_regex = re.compile('([A-Za-z_]+)[^a-z]')
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001149 packet_transmit_name_regex = re.compile('(?P<direction>send|read) packet: (?P<packet>.*)')
1150 packet_contents_name_regex = re.compile('\$([^#]+)#[0-9a-fA-F]{2}')
Greg Clayton8c2afa02015-07-22 20:12:58 +00001151 packet_checksum_regex = re.compile('.*#[0-9a-fA-F]{2}$')
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001152 packet_names_regex_str = '(' + '|'.join(gdb_remote_commands.keys()) + ')(.*)';
1153 packet_names_regex = re.compile(packet_names_regex_str);
1154
Greg Claytone2841632012-01-26 02:56:24 +00001155 base_time = 0.0
1156 last_time = 0.0
1157 packet_send_time = 0.0
Greg Claytone2841632012-01-26 02:56:24 +00001158 packet_total_times = {}
Greg Clayton25f82aa2015-05-22 23:00:59 +00001159 packet_times = []
Jim Inghamd95752f2012-03-01 18:57:51 +00001160 packet_count = {}
Greg Claytone2841632012-01-26 02:56:24 +00001161 lines = file.read().splitlines()
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001162 last_command = None
1163 last_command_args = None
1164 last_command_packet = None
Greg Clayton205d6182015-07-17 20:16:50 +00001165 hide_next_response = False
Greg Clayton8c2afa02015-07-22 20:12:58 +00001166 num_lines = len(lines)
1167 skip_count = 0
1168 for (line_index, line) in enumerate(lines):
1169 # See if we need to skip any lines
1170 if skip_count > 0:
1171 skip_count -= 1
1172 continue
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001173 m = packet_transmit_name_regex.search(line)
Greg Claytonf51a23f2012-06-04 23:22:17 +00001174 is_command = False
Greg Clayton25f82aa2015-05-22 23:00:59 +00001175 direction = None
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001176 if m:
1177 direction = m.group('direction')
1178 is_command = direction == 'send'
1179 packet = m.group('packet')
Greg Claytonf51a23f2012-06-04 23:22:17 +00001180 sys.stdout.write(options.colors.green())
Greg Clayton205d6182015-07-17 20:16:50 +00001181 if not options.quiet and not hide_next_response:
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001182 print '# ', line
Greg Claytonf51a23f2012-06-04 23:22:17 +00001183 sys.stdout.write(options.colors.reset())
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001184
1185 #print 'direction = "%s", packet = "%s"' % (direction, packet)
1186
1187 if packet[0] == '+':
Greg Clayton8c2afa02015-07-22 20:12:58 +00001188 if is_command:
1189 print '-->',
1190 else:
1191 print '<--',
Greg Clayton25f82aa2015-05-22 23:00:59 +00001192 if not options.quiet: print 'ACK'
1193 continue
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001194 elif packet[0] == '-':
Greg Clayton8c2afa02015-07-22 20:12:58 +00001195 if is_command:
1196 print '-->',
1197 else:
1198 print '<--',
Greg Clayton25f82aa2015-05-22 23:00:59 +00001199 if not options.quiet: print 'NACK'
1200 continue
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001201 elif packet[0] == '$':
1202 m = packet_contents_name_regex.match(packet)
Greg Clayton8c2afa02015-07-22 20:12:58 +00001203 if not m and packet[0] == '$':
1204 multiline_packet = packet
1205 idx = line_index + 1
1206 while idx < num_lines:
1207 if not options.quiet and not hide_next_response:
1208 print '# ', lines[idx]
1209 multiline_packet += lines[idx]
1210 m = packet_contents_name_regex.match(multiline_packet)
1211 if m:
1212 packet = multiline_packet
1213 skip_count = idx - line_index
1214 break
1215 else:
1216 idx += 1
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001217 if m:
Greg Clayton8c2afa02015-07-22 20:12:58 +00001218 if is_command:
1219 print '-->',
1220 else:
1221 print '<--',
1222 contents = decode_packet(m.group(1))
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001223 if is_command:
Greg Clayton205d6182015-07-17 20:16:50 +00001224 hide_next_response = False
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001225 m = packet_names_regex.match (contents)
1226 if m:
1227 last_command = m.group(1)
Greg Claytona7a5e5a2015-07-17 23:08:14 +00001228 if last_command == '?':
1229 last_command = '\\?'
Greg Claytonf51a23f2012-06-04 23:22:17 +00001230 packet_name = last_command
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001231 last_command_args = m.group(2)
1232 last_command_packet = contents
Greg Clayton205d6182015-07-17 20:16:50 +00001233 hide_next_response = gdb_remote_commands[last_command]['cmd'](options, last_command, last_command_args)
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001234 else:
Greg Clayton25f82aa2015-05-22 23:00:59 +00001235 packet_match = packet_name_regex.match (contents)
Greg Claytonf51a23f2012-06-04 23:22:17 +00001236 if packet_match:
1237 packet_name = packet_match.group(1)
1238 for tricky_cmd in tricky_commands:
1239 if packet_name.find (tricky_cmd) == 0:
1240 packet_name = tricky_cmd
1241 else:
1242 packet_name = contents
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001243 last_command = None
1244 last_command_args = None
1245 last_command_packet = None
1246 elif last_command:
Greg Claytonf51a23f2012-06-04 23:22:17 +00001247 gdb_remote_commands[last_command]['rsp'](options, last_command, last_command_args, contents)
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001248 else:
1249 print 'error: invalid packet: "', packet, '"'
1250 else:
1251 print '???'
1252 else:
1253 print '## ', line
Greg Claytone2841632012-01-26 02:56:24 +00001254 match = timestamp_regex.match (line)
1255 if match:
1256 curr_time = float (match.group(2))
Greg Clayton25f82aa2015-05-22 23:00:59 +00001257 if last_time and not is_command:
1258 delta = curr_time - last_time
1259 packet_times.append(delta)
Greg Claytone2841632012-01-26 02:56:24 +00001260 delta = 0.0
1261 if base_time:
1262 delta = curr_time - last_time
1263 else:
1264 base_time = curr_time
Greg Claytonf51a23f2012-06-04 23:22:17 +00001265
1266 if is_command:
Greg Claytone2841632012-01-26 02:56:24 +00001267 packet_send_time = curr_time
Greg Claytone2841632012-01-26 02:56:24 +00001268 elif line.find('read packet: $') >= 0 and packet_name:
1269 if packet_name in packet_total_times:
1270 packet_total_times[packet_name] += delta
Jim Inghamd95752f2012-03-01 18:57:51 +00001271 packet_count[packet_name] += 1
Greg Claytone2841632012-01-26 02:56:24 +00001272 else:
1273 packet_total_times[packet_name] = delta
Jim Inghamd95752f2012-03-01 18:57:51 +00001274 packet_count[packet_name] = 1
Greg Claytone2841632012-01-26 02:56:24 +00001275 packet_name = None
1276
1277 if not options or not options.quiet:
1278 print '%s%.6f %+.6f%s' % (match.group(1), curr_time - base_time, delta, match.group(3))
1279 last_time = curr_time
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001280 # else:
1281 # print line
Greg Clayton25f82aa2015-05-22 23:00:59 +00001282 (average, std_dev) = calculate_mean_and_standard_deviation(packet_times)
Greg Clayton205d6182015-07-17 20:16:50 +00001283 if average and std_dev:
1284 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 +00001285 if packet_total_times:
1286 total_packet_time = 0.0
Jim Inghamd95752f2012-03-01 18:57:51 +00001287 total_packet_count = 0
Greg Claytone2841632012-01-26 02:56:24 +00001288 for key, vvv in packet_total_times.items():
1289 # print ' key = (%s) "%s"' % (type(key), key)
1290 # print 'value = (%s) %s' % (type(vvv), vvv)
1291 # if type(vvv) == 'float':
1292 total_packet_time += vvv
Jim Inghamd95752f2012-03-01 18:57:51 +00001293 for key, vvv in packet_count.items():
1294 total_packet_count += vvv
1295
1296 print '#---------------------------------------------------'
Greg Claytone2841632012-01-26 02:56:24 +00001297 print '# Packet timing summary:'
Greg Clayton25f82aa2015-05-22 23:00:59 +00001298 print '# Totals: time = %6f, count = %6d' % (total_packet_time, total_packet_count)
Jim Inghamd95752f2012-03-01 18:57:51 +00001299 print '#---------------------------------------------------'
1300 print '# Packet Time (sec) Percent Count '
1301 print '#------------------------- ---------- ------- ------'
1302 if options and options.sort_count:
1303 res = sorted(packet_count, key=packet_count.__getitem__, reverse=True)
1304 else:
1305 res = sorted(packet_total_times, key=packet_total_times.__getitem__, reverse=True)
1306
Greg Claytone2841632012-01-26 02:56:24 +00001307 if last_time > 0.0:
1308 for item in res:
1309 packet_total_time = packet_total_times[item]
1310 packet_percent = (packet_total_time / total_packet_time)*100.0
1311 if packet_percent >= 10.0:
Jim Inghamd95752f2012-03-01 18:57:51 +00001312 print " %24s %.6f %.2f%% %6d" % (item, packet_total_time, packet_percent, packet_count[item])
Greg Claytone2841632012-01-26 02:56:24 +00001313 else:
Jim Inghamd95752f2012-03-01 18:57:51 +00001314 print " %24s %.6f %.2f%% %6d" % (item, packet_total_time, packet_percent, packet_count[item])
Greg Claytone2841632012-01-26 02:56:24 +00001315
1316
1317
1318if __name__ == '__main__':
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001319 usage = "usage: gdbremote [options]"
1320 description='''The command disassembles a GDB remote packet log.'''
1321 parser = optparse.OptionParser(description=description, prog='gdbremote',usage=usage)
1322 parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
1323 parser.add_option('-q', '--quiet', action='store_true', dest='quiet', help='display verbose debug info', default=False)
1324 parser.add_option('-C', '--color', action='store_true', dest='color', help='add terminal colors', default=False)
1325 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 +00001326 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 +00001327 try:
1328 (options, args) = parser.parse_args(sys.argv[1:])
1329 except:
1330 print 'error: argument error'
1331 sys.exit(1)
1332
Greg Claytonf51a23f2012-06-04 23:22:17 +00001333 options.colors = TerminalColors(options.color)
1334 options.symbolicator = None
1335 if options.crashlog:
1336 import lldb
1337 lldb.debugger = lldb.SBDebugger.Create()
1338 import lldb.macosx.crashlog
1339 options.symbolicator = lldb.macosx.crashlog.CrashLog(options.crashlog)
1340 print '%s' % (options.symbolicator)
Greg Clayton8ebb9a82012-06-01 20:23:54 +00001341
Greg Claytone2841632012-01-26 02:56:24 +00001342 # This script is being run from the command line, create a debugger in case we are
1343 # going to use any debugger functions in our function.
Greg Claytonb2273bd2015-07-17 00:19:31 +00001344 if len(args):
1345 for file in args:
1346 print '#----------------------------------------------------------------------'
1347 print "# GDB remote log file: '%s'" % file
1348 print '#----------------------------------------------------------------------'
1349 parse_gdb_log_file (file, options)
1350 if options.symbolicator:
1351 print '%s' % (options.symbolicator)
1352 else:
1353 parse_gdb_log(sys.stdin, options)
Greg Claytonf51a23f2012-06-04 23:22:17 +00001354
Greg Claytone2841632012-01-26 02:56:24 +00001355else:
1356 import lldb
1357 if lldb.debugger:
1358 # This initializer is being run from LLDB in the embedded command interpreter
1359 # Add any commands contained in this module to LLDB
1360 lldb.debugger.HandleCommand('command script add -f gdbremote.start_gdb_log start_gdb_log')
1361 lldb.debugger.HandleCommand('command script add -f gdbremote.stop_gdb_log stop_gdb_log')
1362 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'