diff options
Diffstat (limited to 'examples/python/gdbremote.py')
-rwxr-xr-x | examples/python/gdbremote.py | 757 |
1 files changed, 462 insertions, 295 deletions
diff --git a/examples/python/gdbremote.py b/examples/python/gdbremote.py index 4cbfdb2ba333..7d5874e8b0c7 100755 --- a/examples/python/gdbremote.py +++ b/examples/python/gdbremote.py @@ -1,15 +1,15 @@ #!/usr/bin/python #---------------------------------------------------------------------- -# This module will enable GDB remote packet logging when the +# This module will enable GDB remote packet logging when the # 'start_gdb_log' command is called with a filename to log to. When the -# 'stop_gdb_log' command is called, it will disable the logging and +# 'stop_gdb_log' command is called, it will disable the logging and # print out statistics about how long commands took to execute and also # will primnt ou # Be sure to add the python path that points to the LLDB shared library. # # To use this in the embedded python interpreter using "lldb" just -# import it with the full path using the "command script import" +# import it with the full path using the "command script import" # command. This can be done from the LLDB command line: # (lldb) command script import /path/to/gdbremote.py # Or it can be added to your ~/.lldbinit file so this module is always @@ -37,173 +37,186 @@ g_byte_order = 'little' g_number_regex = re.compile('^(0x[0-9a-fA-F]+|[0-9]+)') g_thread_id_regex = re.compile('^(-1|[0-9a-fA-F]+|0)') + class TerminalColors: '''Simple terminal colors class''' - def __init__(self, enabled = True): + + def __init__(self, enabled=True): # TODO: discover terminal type from "file" and disable if # it can't handle the color codes self.enabled = enabled - + def reset(self): '''Reset all terminal colors and formatting.''' if self.enabled: - return "\x1b[0m"; + return "\x1b[0m" return '' - - def bold(self, on = True): + + def bold(self, on=True): '''Enable or disable bold depending on the "on" parameter.''' if self.enabled: if on: - return "\x1b[1m"; + return "\x1b[1m" else: - return "\x1b[22m"; + return "\x1b[22m" return '' - - def italics(self, on = True): + + def italics(self, on=True): '''Enable or disable italics depending on the "on" parameter.''' if self.enabled: if on: - return "\x1b[3m"; + return "\x1b[3m" else: - return "\x1b[23m"; + return "\x1b[23m" return '' - - def underline(self, on = True): + + def underline(self, on=True): '''Enable or disable underline depending on the "on" parameter.''' if self.enabled: if on: - return "\x1b[4m"; + return "\x1b[4m" else: - return "\x1b[24m"; + return "\x1b[24m" return '' - - def inverse(self, on = True): + + def inverse(self, on=True): '''Enable or disable inverse depending on the "on" parameter.''' if self.enabled: if on: - return "\x1b[7m"; + return "\x1b[7m" else: - return "\x1b[27m"; + return "\x1b[27m" return '' - - def strike(self, on = True): + + def strike(self, on=True): '''Enable or disable strike through depending on the "on" parameter.''' if self.enabled: if on: - return "\x1b[9m"; - else: - return "\x1b[29m"; + return "\x1b[9m" + else: + return "\x1b[29m" return '' - - def black(self, fg = True): - '''Set the foreground or background color to black. + + def black(self, fg=True): + '''Set the foreground or background color to black. The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[30m"; + if self.enabled: + if fg: + return "\x1b[30m" else: - return "\x1b[40m"; + return "\x1b[40m" return '' - - def red(self, fg = True): - '''Set the foreground or background color to red. + + def red(self, fg=True): + '''Set the foreground or background color to red. The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[31m"; - else: - return "\x1b[41m"; + if self.enabled: + if fg: + return "\x1b[31m" + else: + return "\x1b[41m" return '' - - def green(self, fg = True): - '''Set the foreground or background color to green. + + def green(self, fg=True): + '''Set the foreground or background color to green. The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[32m"; - else: - return "\x1b[42m"; + if self.enabled: + if fg: + return "\x1b[32m" + else: + return "\x1b[42m" return '' - - def yellow(self, fg = True): - '''Set the foreground or background color to yellow. + + def yellow(self, fg=True): + '''Set the foreground or background color to yellow. The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[33m"; - else: - return "\x1b[43m"; + if self.enabled: + if fg: + return "\x1b[33m" + else: + return "\x1b[43m" return '' - - def blue(self, fg = True): - '''Set the foreground or background color to blue. + + def blue(self, fg=True): + '''Set the foreground or background color to blue. The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[34m"; - else: - return "\x1b[44m"; + if self.enabled: + if fg: + return "\x1b[34m" + else: + return "\x1b[44m" return '' - - def magenta(self, fg = True): - '''Set the foreground or background color to magenta. + + def magenta(self, fg=True): + '''Set the foreground or background color to magenta. The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[35m"; - else: - return "\x1b[45m"; + if self.enabled: + if fg: + return "\x1b[35m" + else: + return "\x1b[45m" return '' - - def cyan(self, fg = True): - '''Set the foreground or background color to cyan. + + def cyan(self, fg=True): + '''Set the foreground or background color to cyan. The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[36m"; - else: - return "\x1b[46m"; + if self.enabled: + if fg: + return "\x1b[36m" + else: + return "\x1b[46m" return '' - - def white(self, fg = True): - '''Set the foreground or background color to white. + + def white(self, fg=True): + '''Set the foreground or background color to white. The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[37m"; - else: - return "\x1b[47m"; + if self.enabled: + if fg: + return "\x1b[37m" + else: + return "\x1b[47m" return '' - - def default(self, fg = True): - '''Set the foreground or background color to the default. + + def default(self, fg=True): + '''Set the foreground or background color to the default. The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[39m"; - else: - return "\x1b[49m"; + if self.enabled: + if fg: + return "\x1b[39m" + else: + return "\x1b[49m" return '' def start_gdb_log(debugger, command, result, dict): - '''Start logging GDB remote packets by enabling logging with timestamps and + '''Start logging GDB remote packets by enabling logging with timestamps and thread safe logging. Follow a call to this function with a call to "stop_gdb_log" in order to dump out the commands.''' global g_log_file command_args = shlex.split(command) usage = "usage: start_gdb_log [options] [<LOGFILEPATH>]" - 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 + 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 be aggregated and displayed.''' - parser = optparse.OptionParser(description=description, prog='start_gdb_log',usage=usage) - parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) + parser = optparse.OptionParser( + description=description, + prog='start_gdb_log', + usage=usage) + parser.add_option( + '-v', + '--verbose', + action='store_true', + dest='verbose', + help='display verbose debug info', + default=False) try: (options, args) = parser.parse_args(command_args) except: return if g_log_file: - result.PutCString ('error: logging is already in progress with file "%s"' % g_log_file) + result.PutCString( + 'error: logging is already in progress with file "%s"' % + g_log_file) else: args_len = len(args) if args_len == 0: @@ -212,12 +225,17 @@ def start_gdb_log(debugger, command, result, dict): g_log_file = args[0] if g_log_file: - debugger.HandleCommand('log enable --threadsafe --timestamp --file "%s" gdb-remote packets' % g_log_file); - 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) + debugger.HandleCommand( + 'log enable --threadsafe --timestamp --file "%s" gdb-remote packets' % + g_log_file) + 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) return - result.PutCString ('error: invalid log file path') - result.PutCString (usage) + result.PutCString('error: invalid log file path') + result.PutCString(usage) + def stop_gdb_log(debugger, command, result, dict): '''Stop logging GDB remote packets to the file that was specified in a call @@ -225,17 +243,50 @@ def stop_gdb_log(debugger, command, result, dict): timestamp in the log file. Also print out statistics for how long each command took to allow performance bottlenecks to be determined.''' global g_log_file - # Any commands whose names might be followed by more valid C identifier + # Any commands whose names might be followed by more valid C identifier # characters must be listed here command_args = shlex.split(command) usage = "usage: stop_gdb_log [options]" - 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.''' - parser = optparse.OptionParser(description=description, prog='stop_gdb_log',usage=usage) - parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) - parser.add_option('-q', '--quiet', action='store_true', dest='quiet', help='display verbose debug info', default=False) - parser.add_option('-C', '--color', action='store_true', dest='color', help='add terminal colors', default=False) - parser.add_option('-c', '--sort-by-count', action='store_true', dest='sort_count', help='display verbose debug info', default=False) - parser.add_option('-s', '--symbolicate', action='store_true', dest='symbolicate', help='symbolicate addresses in log using current "lldb.target"', default=False) + 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.''' + parser = optparse.OptionParser( + description=description, + prog='stop_gdb_log', + usage=usage) + parser.add_option( + '-v', + '--verbose', + action='store_true', + dest='verbose', + help='display verbose debug info', + default=False) + parser.add_option( + '-q', + '--quiet', + action='store_true', + dest='quiet', + help='display verbose debug info', + default=False) + parser.add_option( + '-C', + '--color', + action='store_true', + dest='color', + help='add terminal colors', + default=False) + parser.add_option( + '-c', + '--sort-by-count', + action='store_true', + dest='sort_count', + help='display verbose debug info', + default=False) + parser.add_option( + '-s', + '--symbolicate', + action='store_true', + dest='symbolicate', + help='symbolicate addresses in log using current "lldb.target"', + default=False) try: (options, args) = parser.parse_args(command_args) except: @@ -251,34 +302,41 @@ def stop_gdb_log(debugger, command, result, dict): print "error: can't symbolicate without a target" if not g_log_file: - result.PutCString ('error: logging must have been previously enabled with a call to "stop_gdb_log"') - elif os.path.exists (g_log_file): + result.PutCString( + 'error: logging must have been previously enabled with a call to "stop_gdb_log"') + elif os.path.exists(g_log_file): if len(args) == 0: - debugger.HandleCommand('log disable gdb-remote packets'); - result.PutCString ("GDB packet logging disabled. Logged packets are in '%s'" % g_log_file) - parse_gdb_log_file (g_log_file, options) + debugger.HandleCommand('log disable gdb-remote packets') + result.PutCString( + "GDB packet logging disabled. Logged packets are in '%s'" % + g_log_file) + parse_gdb_log_file(g_log_file, options) else: - result.PutCString (usage) + result.PutCString(usage) else: print 'error: the GDB packet log file "%s" does not exist' % g_log_file + def is_hex_byte(str): if len(str) == 2: - return str[0] in string.hexdigits and str[1] in string.hexdigits; + return str[0] in string.hexdigits and str[1] in string.hexdigits return False # global register info list g_register_infos = list() g_max_register_info_name_len = 0 + class RegisterInfo: """Class that represents register information""" + def __init__(self, kvp): self.info = dict() for kv in kvp: key = kv[0] value = kv[1] self.info[key] = value + def name(self): '''Get the name of the register.''' if self.info and 'name' in self.info: @@ -310,9 +368,9 @@ class RegisterInfo: return '0x%8.8x' % (uval) elif bit_size == 64: return '0x%16.16x' % (uval) - bytes = list(); + bytes = list() uval = packet.get_hex_uint8() - while uval != None: + while uval is not None: bytes.append(uval) uval = packet.get_hex_uint8() value_str = '0x' @@ -321,7 +379,7 @@ class RegisterInfo: for byte in bytes: value_str += '%2.2x' % byte return '%s' % (value_str) - + def __str__(self): '''Dump the register info key/value pairs''' s = '' @@ -330,25 +388,27 @@ class RegisterInfo: s += ', ' s += "%s=%s " % (key, self.info[key]) return s - + + class Packet: """Class that represents a packet that contains string data""" + def __init__(self, packet_str): self.str = packet_str - + def peek_char(self): ch = 0 if self.str: ch = self.str[0] return ch - + def get_char(self): ch = 0 if self.str: ch = self.str[0] self.str = self.str[1:] return ch - + def skip_exact_string(self, s): if self.str and self.str.startswith(s): self.str = self.str[len(s):] @@ -356,22 +416,23 @@ class Packet: else: return False - def get_thread_id(self, fail_value = -1): - match = g_number_regex.match (self.str) + def get_thread_id(self, fail_value=-1): + match = g_number_regex.match(self.str) if match: number_str = match.group(1) self.str = self.str[len(number_str):] return int(number_str, 0) else: return fail_value - + def get_hex_uint8(self): - if self.str and len(self.str) >= 2 and self.str[0] in string.hexdigits and self.str[1] in string.hexdigits: + if self.str and len(self.str) >= 2 and self.str[ + 0] in string.hexdigits and self.str[1] in string.hexdigits: uval = int(self.str[0:2], 16) self.str = self.str[2:] return uval return None - + def get_hex_uint16(self, byte_order): uval = 0 if byte_order == 'big': @@ -381,7 +442,7 @@ class Packet: uval |= self.get_hex_uint8() uval |= self.get_hex_uint8() << 8 return uval - + def get_hex_uint32(self, byte_order): uval = 0 if byte_order == 'big': @@ -395,7 +456,7 @@ class Packet: uval |= self.get_hex_uint8() << 16 uval |= self.get_hex_uint8() << 24 return uval - + def get_hex_uint64(self, byte_order): uval = 0 if byte_order == 'big': @@ -417,65 +478,64 @@ class Packet: uval |= self.get_hex_uint8() << 48 uval |= self.get_hex_uint8() << 56 return uval - + def get_number(self, fail_value=-1): '''Get a number from the packet. The number must be in big endian format and should be parsed - according to its prefix (starts with "0x" means hex, starts with "0" means octal, starts with + according to its prefix (starts with "0x" means hex, starts with "0" means octal, starts with [1-9] means decimal, etc)''' - match = g_number_regex.match (self.str) + match = g_number_regex.match(self.str) if match: number_str = match.group(1) self.str = self.str[len(number_str):] return int(number_str, 0) else: return fail_value - - + def get_hex_ascii_str(self, n=0): hex_chars = self.get_hex_chars(n) if hex_chars: return binascii.unhexlify(hex_chars) else: return None - - def get_hex_chars(self, n = 0): + + def get_hex_chars(self, n=0): str_len = len(self.str) if n == 0: - # n was zero, so we need to determine all hex chars and + # n was zero, so we need to determine all hex chars and # stop when we hit the end of the string of a non-hex character while n < str_len and self.str[n] in string.hexdigits: n = n + 1 else: if n > str_len: - return None # Not enough chars + return None # Not enough chars # Verify all chars are hex if a length was specified for i in range(n): if self.str[i] not in string.hexdigits: - return None # Not all hex digits + return None # Not all hex digits if n == 0: return None hex_str = self.str[0:n] self.str = self.str[n:] return hex_str - - def get_hex_uint(self, byte_order, n = 0): + + def get_hex_uint(self, byte_order, n=0): if byte_order == 'big': hex_str = self.get_hex_chars(n) - if hex_str == None: + if hex_str is None: return None return int(hex_str, 16) else: uval = self.get_hex_uint8() - if uval == None: + if uval is None: return None uval_result = 0 shift = 0 - while uval != None: + while uval is not None: uval_result |= (uval << shift) shift += 8 uval = self.get_hex_uint8() return uval_result - + def get_key_value_pairs(self): kvp = list() if ';' in self.str: @@ -494,36 +554,41 @@ class Packet: for str in strings: hex_values.append(Packet(str).get_hex_uint(byte_order)) return hex_values - + def __str__(self): return self.str - + def __len__(self): return len(self.str) g_thread_suffix_regex = re.compile(';thread:([0-9a-fA-F]+);') + + def get_thread_from_thread_suffix(str): if str: - match = g_thread_suffix_regex.match (str) + match = g_thread_suffix_regex.match(str) if match: return int(match.group(1), 16) return None + def cmd_qThreadStopInfo(options, cmd, args): packet = Packet(args) tid = packet.get_hex_uint('big') print "get_thread_stop_info (tid = 0x%x)" % (tid) - + + def cmd_stop_reply(options, cmd, args): print "get_last_stop_info()" return False + def rsp_stop_reply(options, cmd, cmd_args, rsp): global g_byte_order packet = Packet(rsp) stop_type = packet.get_char() if stop_type == 'T' or stop_type == 'S': - signo = packet.get_hex_uint8() + signo = packet.get_hex_uint8() key_value_pairs = packet.get_key_value_pairs() for key_value_pair in key_value_pairs: key = key_value_pair[0] @@ -532,18 +597,19 @@ def rsp_stop_reply(options, cmd, cmd_args, rsp): if reg_num < len(g_register_infos): reg_info = g_register_infos[reg_num] key_value_pair[0] = reg_info.name() - key_value_pair[1] = reg_info.get_value_from_hex_string (key_value_pair[1]) + key_value_pair[1] = reg_info.get_value_from_hex_string( + key_value_pair[1]) elif key == 'jthreads' or key == 'jstopinfo': key_value_pair[1] = binascii.unhexlify(key_value_pair[1]) key_value_pairs.insert(0, ['signal', signo]) print 'stop_reply():' - dump_key_value_pairs (key_value_pairs) + dump_key_value_pairs(key_value_pairs) elif stop_type == 'W': exit_status = packet.get_hex_uint8() print 'stop_reply(): exit (status=%i)' % exit_status elif stop_type == 'O': print 'stop_reply(): stdout = "%s"' % packet.str - + def cmd_unknown_packet(options, cmd, args): if args: @@ -552,6 +618,7 @@ def cmd_unknown_packet(options, cmd, args): print "cmd: %s", cmd return False + def cmd_qSymbol(options, cmd, args): if args == ':': print 'ready to serve symbols' @@ -571,6 +638,7 @@ def cmd_qSymbol(options, cmd, args): else: print 'error: bad command format' + def rsp_qSymbol(options, cmd, cmd_args, rsp): if len(rsp) == 0: print "Unsupported" @@ -585,11 +653,13 @@ def rsp_qSymbol(options, cmd, cmd_args, rsp): else: print 'error: response string should start with "qSymbol:": respnse is "%s"' % (rsp) + def cmd_qXfer(options, cmd, args): # $qXfer:features:read:target.xml:0,1ffff#14 print "read target special data %s" % (args) return True + def rsp_qXfer(options, cmd, cmd_args, rsp): data = string.split(cmd_args, ':') if data[0] == 'features': @@ -606,25 +676,30 @@ def rsp_qXfer(options, cmd, cmd_args, rsp): if not 'value_regnums' in reg_element.attrib: reg_info = RegisterInfo([]) if 'name' in reg_element.attrib: - reg_info.info['name'] = reg_element.attrib['name'] + reg_info.info[ + 'name'] = reg_element.attrib['name'] else: reg_info.info['name'] = 'unspecified' if 'encoding' in reg_element.attrib: - reg_info.info['encoding'] = reg_element.attrib['encoding'] + reg_info.info['encoding'] = reg_element.attrib[ + 'encoding'] else: reg_info.info['encoding'] = 'uint' if 'offset' in reg_element.attrib: - reg_info.info['offset'] = reg_element.attrib['offset'] + reg_info.info[ + 'offset'] = reg_element.attrib['offset'] if 'bitsize' in reg_element.attrib: - reg_info.info['bitsize'] = reg_element.attrib['bitsize'] + reg_info.info[ + 'bitsize'] = reg_element.attrib['bitsize'] g_register_infos.append(reg_info) print 'XML for "%s":' % (data[2]) ET.dump(xml_root) + def cmd_A(options, cmd, args): print 'launch process:' packet = Packet(args) - while 1: + while True: arg_len = packet.get_number() if arg_len == -1: break @@ -634,13 +709,15 @@ def cmd_A(options, cmd, args): if arg_idx == -1: break if not packet.skip_exact_string(','): - break; + break arg_value = packet.get_hex_ascii_str(arg_len) print 'argv[%u] = "%s"' % (arg_idx, arg_value) - + + def cmd_qC(options, cmd, args): print "query_current_thread_id()" + def rsp_qC(options, cmd, cmd_args, rsp): packet = Packet(rsp) if packet.skip_exact_string("QC"): @@ -649,16 +726,19 @@ def rsp_qC(options, cmd, cmd_args, rsp): else: print "current_thread_id = old thread ID" + def cmd_query_packet(options, cmd, args): if args: print "%s%s" % (cmd, args) else: print "%s" % (cmd) return False - + + def rsp_ok_error(rsp): print "rsp: ", rsp + def rsp_ok_means_supported(options, cmd, cmd_args, rsp): if rsp == 'OK': print "%s%s is supported" % (cmd, cmd_args) @@ -667,6 +747,7 @@ def rsp_ok_means_supported(options, cmd, cmd_args, rsp): else: print "%s%s -> %s" % (cmd, cmd_args, rsp) + def rsp_ok_means_success(options, cmd, cmd_args, rsp): if rsp == 'OK': print "success" @@ -675,17 +756,19 @@ def rsp_ok_means_success(options, cmd, cmd_args, rsp): else: print "%s%s -> %s" % (cmd, cmd_args, rsp) + def dump_key_value_pairs(key_value_pairs): max_key_len = 0 for key_value_pair in key_value_pairs: key_len = len(key_value_pair[0]) if max_key_len < key_len: - max_key_len = key_len + max_key_len = key_len for key_value_pair in key_value_pairs: key = key_value_pair[0] value = key_value_pair[1] print "%*s = %s" % (max_key_len, key, value) + def rsp_dump_key_value_pairs(options, cmd, cmd_args, rsp): if rsp: print '%s response:' % (cmd) @@ -695,14 +778,17 @@ def rsp_dump_key_value_pairs(options, cmd, cmd_args, rsp): else: print "not supported" + def cmd_c(options, cmd, args): print "continue()" return False + def cmd_s(options, cmd, args): print "step()" return False - + + def cmd_vCont(options, cmd, args): if args == '?': print "%s: get supported extended continue modes" % (cmd) @@ -735,15 +821,16 @@ def cmd_vCont(options, cmd, args): print "extended_continue (%s, other-threads: suspend)" % (s) return False + def rsp_vCont(options, cmd, cmd_args, rsp): if cmd_args == '?': # Skip the leading 'vCont;' rsp = rsp[6:] modes = string.split(rsp, ';') s = "%s: supported extended continue modes include: " % (cmd) - + for i, mode in enumerate(modes): - if i: + if i: s += ', ' if mode == 'c': s += 'continue' @@ -758,7 +845,7 @@ def rsp_vCont(options, cmd, cmd_args, rsp): print s elif rsp: if rsp[0] == 'T' or rsp[0] == 'S' or rsp[0] == 'W' or rsp[0] == 'X': - rsp_stop_reply (options, cmd, cmd_args, rsp) + rsp_stop_reply(options, cmd, cmd_args, rsp) return if rsp[0] == 'O': print "stdout: %s" % (rsp) @@ -766,6 +853,7 @@ def rsp_vCont(options, cmd, cmd_args, rsp): else: print "not supported (cmd = '%s', args = '%s', rsp = '%s')" % (cmd, cmd_args, rsp) + def cmd_vAttach(options, cmd, args): (extra_command, args) = string.split(args, ';') if extra_command: @@ -773,12 +861,13 @@ def cmd_vAttach(options, cmd, args): else: print "attach(pid = %u)" % int(args, 16) return False - + def cmd_qRegisterInfo(options, cmd, args): print 'query_register_info(reg_num=%i)' % (int(args, 16)) return False + def rsp_qRegisterInfo(options, cmd, cmd_args, rsp): global g_max_register_info_name_len print 'query_register_info(reg_num=%i):' % (int(cmd_args, 16)), @@ -796,14 +885,16 @@ def rsp_qRegisterInfo(options, cmd, cmd_args, rsp): print reg_info return False + def cmd_qThreadInfo(options, cmd, args): if cmd == 'qfThreadInfo': query_type = 'first' - else: + else: query_type = 'subsequent' print 'get_current_thread_list(type=%s)' % (query_type) return False + def rsp_qThreadInfo(options, cmd, cmd_args, rsp): packet = Packet(rsp) response_type = packet.get_char() @@ -817,11 +908,13 @@ def rsp_qThreadInfo(options, cmd, cmd_args, rsp): elif response_type == 'l': print 'END' + def rsp_hex_big_endian(options, cmd, cmd_args, rsp): packet = Packet(rsp) uval = packet.get_hex_uint('big') print '%s: 0x%x' % (cmd, uval) + def cmd_read_mem_bin(options, cmd, args): # x0x7fff5fc39200,0x200 packet = Packet(args) @@ -831,6 +924,7 @@ def cmd_read_mem_bin(options, cmd, args): print 'binary_read_memory (addr = 0x%16.16x, size = %u)' % (addr, size) return False + def rsp_mem_bin_bytes(options, cmd, cmd_args, rsp): packet = Packet(cmd_args) addr = packet.get_number() @@ -838,7 +932,8 @@ def rsp_mem_bin_bytes(options, cmd, cmd_args, rsp): size = packet.get_number() print 'memory:' if size > 0: - dump_hex_memory_buffer (addr, rsp) + dump_hex_memory_buffer(addr, rsp) + def cmd_read_memory(options, cmd, args): packet = Packet(args) @@ -848,12 +943,13 @@ def cmd_read_memory(options, cmd, args): print 'read_memory (addr = 0x%16.16x, size = %u)' % (addr, size) return False + def dump_hex_memory_buffer(addr, hex_byte_str): packet = Packet(hex_byte_str) idx = 0 ascii = '' uval = packet.get_hex_uint8() - while uval != None: + while uval is not None: if ((idx % 16) == 0): if ascii: print ' ', ascii @@ -868,8 +964,9 @@ def dump_hex_memory_buffer(addr, hex_byte_str): idx = idx + 1 if ascii: print ' ', ascii - ascii = '' - + ascii = '' + + def cmd_write_memory(options, cmd, args): packet = Packet(args) addr = packet.get_hex_uint('big') @@ -881,9 +978,10 @@ def cmd_write_memory(options, cmd, args): print 'error: invalid write memory command (missing colon after size)' return print 'write_memory (addr = 0x%16.16x, size = %u, data:' % (addr, size) - dump_hex_memory_buffer (addr, packet.str) + dump_hex_memory_buffer(addr, packet.str) return False + def cmd_alloc_memory(options, cmd, args): packet = Packet(args) byte_size = packet.get_hex_uint('big') @@ -893,11 +991,13 @@ def cmd_alloc_memory(options, cmd, args): print 'allocate_memory (byte-size = %u (0x%x), permissions = %s)' % (byte_size, byte_size, packet.str) return False + def rsp_alloc_memory(options, cmd, cmd_args, rsp): packet = Packet(rsp) addr = packet.get_hex_uint('big') print 'addr = 0x%x' % addr + def cmd_dealloc_memory(options, cmd, args): packet = Packet(args) addr = packet.get_hex_uint('big') @@ -906,17 +1006,21 @@ def cmd_dealloc_memory(options, cmd, args): else: print 'deallocate_memory (addr = 0x%x, permissions = %s)' % (addr, packet.str) return False + + def rsp_memory_bytes(options, cmd, cmd_args, rsp): addr = Packet(cmd_args).get_hex_uint('big') - dump_hex_memory_buffer (addr, rsp) + dump_hex_memory_buffer(addr, rsp) + def get_register_name_equal_value(options, reg_num, hex_value_str): if reg_num < len(g_register_infos): reg_info = g_register_infos[reg_num] - value_str = reg_info.get_value_from_hex_string (hex_value_str) + value_str = reg_info.get_value_from_hex_string(hex_value_str) s = reg_info.name() + ' = ' if options.symbolicator: - symbolicated_addresses = options.symbolicator.symbolicate (int(value_str, 0)) + symbolicated_addresses = options.symbolicator.symbolicate( + int(value_str, 0)) if symbolicated_addresses: s += options.colors.magenta() s += '%s' % symbolicated_addresses[0] @@ -928,30 +1032,33 @@ def get_register_name_equal_value(options, reg_num, hex_value_str): reg_value = Packet(hex_value_str).get_hex_uint(g_byte_order) return 'reg(%u) = 0x%x' % (reg_num, reg_value) + def cmd_read_one_reg(options, cmd, args): packet = Packet(args) reg_num = packet.get_hex_uint('big') - tid = get_thread_from_thread_suffix (packet.str) + tid = get_thread_from_thread_suffix(packet.str) name = None if reg_num < len(g_register_infos): - name = g_register_infos[reg_num].name () + name = g_register_infos[reg_num].name() if packet.str: - packet.get_char() # skip ; + packet.get_char() # skip ; thread_info = packet.get_key_value_pairs() tid = int(thread_info[0][1], 16) s = 'read_register (reg_num=%u' % reg_num if name: s += ' (%s)' % (name) - if tid != None: + if tid is not None: s += ', tid = 0x%4.4x' % (tid) s += ')' print s return False + def rsp_read_one_reg(options, cmd, cmd_args, rsp): packet = Packet(cmd_args) reg_num = packet.get_hex_uint('big') - print get_register_name_equal_value (options, reg_num, rsp) + print get_register_name_equal_value(options, reg_num, rsp) + def cmd_write_one_reg(options, cmd, args): packet = Packet(args) @@ -961,157 +1068,169 @@ def cmd_write_one_reg(options, cmd, args): else: name = None hex_value_str = packet.get_hex_chars() - tid = get_thread_from_thread_suffix (packet.str) + tid = get_thread_from_thread_suffix(packet.str) s = 'write_register (reg_num=%u' % reg_num if name: s += ' (%s)' % (name) s += ', value = ' s += get_register_name_equal_value(options, reg_num, hex_value_str) - if tid != None: + if tid is not None: s += ', tid = 0x%4.4x' % (tid) s += ')' print s return False + def dump_all_regs(packet): for reg_info in g_register_infos: nibble_size = reg_info.bit_size() / 4 hex_value_str = packet.get_hex_chars(nibble_size) - if hex_value_str != None: - value = reg_info.get_value_from_hex_string (hex_value_str) + if hex_value_str is not None: + value = reg_info.get_value_from_hex_string(hex_value_str) print '%*s = %s' % (g_max_register_info_name_len, reg_info.name(), value) else: return - + + def cmd_read_all_regs(cmd, cmd_args): packet = Packet(cmd_args) - packet.get_char() # toss the 'g' command character - tid = get_thread_from_thread_suffix (packet.str) - if tid != None: + packet.get_char() # toss the 'g' command character + tid = get_thread_from_thread_suffix(packet.str) + if tid is not None: print 'read_all_register(thread = 0x%4.4x)' % tid else: print 'read_all_register()' return False + def rsp_read_all_regs(options, cmd, cmd_args, rsp): packet = Packet(rsp) - dump_all_regs (packet) + dump_all_regs(packet) + def cmd_write_all_regs(options, cmd, args): packet = Packet(args) print 'write_all_registers()' - dump_all_regs (packet) + dump_all_regs(packet) return False - -g_bp_types = [ "software_bp", "hardware_bp", "write_wp", "read_wp", "access_wp" ] + +g_bp_types = ["software_bp", "hardware_bp", "write_wp", "read_wp", "access_wp"] + def cmd_bp(options, cmd, args): if cmd == 'Z': s = 'set_' else: s = 'clear_' - packet = Packet (args) + packet = Packet(args) bp_type = packet.get_hex_uint('big') - packet.get_char() # Skip , + packet.get_char() # Skip , bp_addr = packet.get_hex_uint('big') - packet.get_char() # Skip , + packet.get_char() # Skip , bp_size = packet.get_hex_uint('big') s += g_bp_types[bp_type] s += " (addr = 0x%x, size = %u)" % (bp_addr, bp_size) print s return False + def cmd_mem_rgn_info(options, cmd, args): packet = Packet(args) - packet.get_char() # skip ':' character + packet.get_char() # skip ':' character addr = packet.get_hex_uint('big') print 'get_memory_region_info (addr=0x%x)' % (addr) return False + def cmd_kill(options, cmd, args): print 'kill_process()' return False + def cmd_jThreadsInfo(options, cmd, args): print 'jThreadsInfo()' return False - + + def cmd_jGetLoadedDynamicLibrariesInfos(options, cmd, args): print 'jGetLoadedDynamicLibrariesInfos()' return False -def decode_packet(s, start_index = 0): - #print '\ndecode_packet("%s")' % (s[start_index:]) + +def decode_packet(s, start_index=0): + # print '\ndecode_packet("%s")' % (s[start_index:]) index = s.find('}', start_index) have_escapes = index != -1 if have_escapes: normal_s = s[start_index:index] else: normal_s = s[start_index:] - #print 'normal_s = "%s"' % (normal_s) + # print 'normal_s = "%s"' % (normal_s) if have_escapes: - escape_char = '%c' % (ord(s[index+1]) ^ 0x20) - #print 'escape_char for "%s" = %c' % (s[index:index+2], escape_char) - return normal_s + escape_char + decode_packet(s, index+2) + escape_char = '%c' % (ord(s[index + 1]) ^ 0x20) + # print 'escape_char for "%s" = %c' % (s[index:index+2], escape_char) + return normal_s + escape_char + decode_packet(s, index + 2) else: return normal_s + def rsp_json(options, cmd, cmd_args, rsp): print '%s() reply:' % (cmd) json_tree = json.loads(rsp) print json.dumps(json_tree, indent=4, separators=(',', ': ')) - - + + def rsp_jGetLoadedDynamicLibrariesInfos(options, cmd, cmd_args, rsp): if cmd_args: rsp_json(options, cmd, cmd_args, rsp) else: rsp_ok_means_supported(options, cmd, cmd_args, rsp) - + gdb_remote_commands = { - '\\?' : { 'cmd' : cmd_stop_reply , 'rsp' : rsp_stop_reply , 'name' : "stop reply pacpket"}, - 'qThreadStopInfo' : { 'cmd' : cmd_qThreadStopInfo , 'rsp' : rsp_stop_reply , 'name' : "stop reply pacpket"}, - 'QStartNoAckMode' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_supported , 'name' : "query if no ack mode is supported"}, - 'QThreadSuffixSupported' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_supported , 'name' : "query if thread suffix is supported" }, - 'QListThreadsInStopReply' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_supported , 'name' : "query if threads in stop reply packets are supported" }, - 'QSetDetachOnError' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_success , 'name' : "set if we should detach on error" }, - 'QSetDisableASLR' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_success , 'name' : "set if we should disable ASLR" }, - 'qLaunchSuccess' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_success , 'name' : "check on launch success for the A packet" }, - 'A' : { 'cmd' : cmd_A , 'rsp' : rsp_ok_means_success , 'name' : "launch process" }, - 'QLaunchArch' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_supported , 'name' : "set if we should disable ASLR" }, - 'qVAttachOrWaitSupported' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_supported , 'name' : "set the launch architecture" }, - 'qHostInfo' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_dump_key_value_pairs, 'name' : "get host information" }, - 'qC' : { 'cmd' : cmd_qC , 'rsp' : rsp_qC , 'name' : "return the current thread ID" }, - 'vCont' : { 'cmd' : cmd_vCont , 'rsp' : rsp_vCont , 'name' : "extended continue command" }, - 'vAttach' : { 'cmd' : cmd_vAttach , 'rsp' : rsp_stop_reply , 'name' : "attach to process" }, - 'c' : { 'cmd' : cmd_c , 'rsp' : rsp_stop_reply , 'name' : "continue" }, - 's' : { 'cmd' : cmd_s , 'rsp' : rsp_stop_reply , 'name' : "step" }, - 'qRegisterInfo' : { 'cmd' : cmd_qRegisterInfo , 'rsp' : rsp_qRegisterInfo , 'name' : "query register info" }, - 'qfThreadInfo' : { 'cmd' : cmd_qThreadInfo , 'rsp' : rsp_qThreadInfo , 'name' : "get current thread list" }, - 'qsThreadInfo' : { 'cmd' : cmd_qThreadInfo , 'rsp' : rsp_qThreadInfo , 'name' : "get current thread list" }, - 'qShlibInfoAddr' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_hex_big_endian , 'name' : "get shared library info address" }, - 'qMemoryRegionInfo' : { 'cmd' : cmd_mem_rgn_info , 'rsp' : rsp_dump_key_value_pairs, 'name' : "get memory region information" }, - 'qProcessInfo' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_dump_key_value_pairs, 'name' : "get process info" }, - 'qSupported' : { 'cmd' : cmd_query_packet , 'rsp' : rsp_ok_means_supported , 'name' : "query supported" }, - 'qXfer:' : { 'cmd' : cmd_qXfer , 'rsp' : rsp_qXfer , 'name' : "qXfer" }, - 'qSymbol:' : { 'cmd' : cmd_qSymbol , 'rsp' : rsp_qSymbol , 'name' : "qSymbol" }, - 'x' : { 'cmd' : cmd_read_mem_bin , 'rsp' : rsp_mem_bin_bytes , 'name' : "read memory binary" }, - 'X' : { 'cmd' : cmd_write_memory , 'rsp' : rsp_ok_means_success , 'name' : "write memory binary" }, - 'm' : { 'cmd' : cmd_read_memory , 'rsp' : rsp_memory_bytes , 'name' : "read memory" }, - 'M' : { 'cmd' : cmd_write_memory , 'rsp' : rsp_ok_means_success , 'name' : "write memory" }, - '_M' : { 'cmd' : cmd_alloc_memory , 'rsp' : rsp_alloc_memory , 'name' : "allocate memory" }, - '_m' : { 'cmd' : cmd_dealloc_memory , 'rsp' : rsp_ok_means_success , 'name' : "deallocate memory" }, - 'p' : { 'cmd' : cmd_read_one_reg , 'rsp' : rsp_read_one_reg , 'name' : "read single register" }, - 'P' : { 'cmd' : cmd_write_one_reg , 'rsp' : rsp_ok_means_success , 'name' : "write single register" }, - 'g' : { 'cmd' : cmd_read_all_regs , 'rsp' : rsp_read_all_regs , 'name' : "read all registers" }, - 'G' : { 'cmd' : cmd_write_all_regs , 'rsp' : rsp_ok_means_success , 'name' : "write all registers" }, - 'z' : { 'cmd' : cmd_bp , 'rsp' : rsp_ok_means_success , 'name' : "clear breakpoint or watchpoint" }, - 'Z' : { 'cmd' : cmd_bp , 'rsp' : rsp_ok_means_success , 'name' : "set breakpoint or watchpoint" }, - 'k' : { 'cmd' : cmd_kill , 'rsp' : rsp_stop_reply , 'name' : "kill process" }, - 'jThreadsInfo' : { 'cmd' : cmd_jThreadsInfo , 'rsp' : rsp_json , 'name' : "JSON get all threads info" }, - 'jGetLoadedDynamicLibrariesInfos:' : { 'cmd' : cmd_jGetLoadedDynamicLibrariesInfos, 'rsp' : rsp_jGetLoadedDynamicLibrariesInfos, 'name' : 'JSON get loaded dynamic libraries' }, + '\\?': {'cmd': cmd_stop_reply, 'rsp': rsp_stop_reply, 'name': "stop reply pacpket"}, + 'qThreadStopInfo': {'cmd': cmd_qThreadStopInfo, 'rsp': rsp_stop_reply, 'name': "stop reply pacpket"}, + 'QStartNoAckMode': {'cmd': cmd_query_packet, 'rsp': rsp_ok_means_supported, 'name': "query if no ack mode is supported"}, + 'QThreadSuffixSupported': {'cmd': cmd_query_packet, 'rsp': rsp_ok_means_supported, 'name': "query if thread suffix is supported"}, + 'QListThreadsInStopReply': {'cmd': cmd_query_packet, 'rsp': rsp_ok_means_supported, 'name': "query if threads in stop reply packets are supported"}, + 'QSetDetachOnError': {'cmd': cmd_query_packet, 'rsp': rsp_ok_means_success, 'name': "set if we should detach on error"}, + 'QSetDisableASLR': {'cmd': cmd_query_packet, 'rsp': rsp_ok_means_success, 'name': "set if we should disable ASLR"}, + 'qLaunchSuccess': {'cmd': cmd_query_packet, 'rsp': rsp_ok_means_success, 'name': "check on launch success for the A packet"}, + 'A': {'cmd': cmd_A, 'rsp': rsp_ok_means_success, 'name': "launch process"}, + 'QLaunchArch': {'cmd': cmd_query_packet, 'rsp': rsp_ok_means_supported, 'name': "set if we should disable ASLR"}, + 'qVAttachOrWaitSupported': {'cmd': cmd_query_packet, 'rsp': rsp_ok_means_supported, 'name': "set the launch architecture"}, + 'qHostInfo': {'cmd': cmd_query_packet, 'rsp': rsp_dump_key_value_pairs, 'name': "get host information"}, + 'qC': {'cmd': cmd_qC, 'rsp': rsp_qC, 'name': "return the current thread ID"}, + 'vCont': {'cmd': cmd_vCont, 'rsp': rsp_vCont, 'name': "extended continue command"}, + 'vAttach': {'cmd': cmd_vAttach, 'rsp': rsp_stop_reply, 'name': "attach to process"}, + 'c': {'cmd': cmd_c, 'rsp': rsp_stop_reply, 'name': "continue"}, + 's': {'cmd': cmd_s, 'rsp': rsp_stop_reply, 'name': "step"}, + 'qRegisterInfo': {'cmd': cmd_qRegisterInfo, 'rsp': rsp_qRegisterInfo, 'name': "query register info"}, + 'qfThreadInfo': {'cmd': cmd_qThreadInfo, 'rsp': rsp_qThreadInfo, 'name': "get current thread list"}, + 'qsThreadInfo': {'cmd': cmd_qThreadInfo, 'rsp': rsp_qThreadInfo, 'name': "get current thread list"}, + 'qShlibInfoAddr': {'cmd': cmd_query_packet, 'rsp': rsp_hex_big_endian, 'name': "get shared library info address"}, + 'qMemoryRegionInfo': {'cmd': cmd_mem_rgn_info, 'rsp': rsp_dump_key_value_pairs, 'name': "get memory region information"}, + 'qProcessInfo': {'cmd': cmd_query_packet, 'rsp': rsp_dump_key_value_pairs, 'name': "get process info"}, + 'qSupported': {'cmd': cmd_query_packet, 'rsp': rsp_ok_means_supported, 'name': "query supported"}, + 'qXfer:': {'cmd': cmd_qXfer, 'rsp': rsp_qXfer, 'name': "qXfer"}, + 'qSymbol:': {'cmd': cmd_qSymbol, 'rsp': rsp_qSymbol, 'name': "qSymbol"}, + 'x': {'cmd': cmd_read_mem_bin, 'rsp': rsp_mem_bin_bytes, 'name': "read memory binary"}, + 'X': {'cmd': cmd_write_memory, 'rsp': rsp_ok_means_success, 'name': "write memory binary"}, + 'm': {'cmd': cmd_read_memory, 'rsp': rsp_memory_bytes, 'name': "read memory"}, + 'M': {'cmd': cmd_write_memory, 'rsp': rsp_ok_means_success, 'name': "write memory"}, + '_M': {'cmd': cmd_alloc_memory, 'rsp': rsp_alloc_memory, 'name': "allocate memory"}, + '_m': {'cmd': cmd_dealloc_memory, 'rsp': rsp_ok_means_success, 'name': "deallocate memory"}, + 'p': {'cmd': cmd_read_one_reg, 'rsp': rsp_read_one_reg, 'name': "read single register"}, + 'P': {'cmd': cmd_write_one_reg, 'rsp': rsp_ok_means_success, 'name': "write single register"}, + 'g': {'cmd': cmd_read_all_regs, 'rsp': rsp_read_all_regs, 'name': "read all registers"}, + 'G': {'cmd': cmd_write_all_regs, 'rsp': rsp_ok_means_success, 'name': "write all registers"}, + 'z': {'cmd': cmd_bp, 'rsp': rsp_ok_means_success, 'name': "clear breakpoint or watchpoint"}, + 'Z': {'cmd': cmd_bp, 'rsp': rsp_ok_means_success, 'name': "set breakpoint or watchpoint"}, + 'k': {'cmd': cmd_kill, 'rsp': rsp_stop_reply, 'name': "kill process"}, + 'jThreadsInfo': {'cmd': cmd_jThreadsInfo, 'rsp': rsp_json, 'name': "JSON get all threads info"}, + 'jGetLoadedDynamicLibrariesInfos:': {'cmd': cmd_jGetLoadedDynamicLibrariesInfos, 'rsp': rsp_jGetLoadedDynamicLibrariesInfos, 'name': 'JSON get loaded dynamic libraries'}, } + def calculate_mean_and_standard_deviation(floats): sum = 0.0 count = len(floats) @@ -1119,20 +1238,22 @@ def calculate_mean_and_standard_deviation(floats): return (0.0, 0.0) for f in floats: sum += f - mean = sum / count + mean = sum / count accum = 0.0 for f in floats: delta = f - mean accum += delta * delta - - std_dev = math.sqrt(accum / (count-1)); + + std_dev = math.sqrt(accum / (count - 1)) return (mean, std_dev) + def parse_gdb_log_file(path, options): f = open(path) parse_gdb_log(f, options) f.close() - + + def parse_gdb_log(file, options): '''Parse a GDB log file that was generated by enabling logging with: (lldb) log enable --threadsafe --timestamp --file <FILE> gdb-remote packets @@ -1143,15 +1264,17 @@ def parse_gdb_log(file, options): handy when trying to figure out why some operation in the debugger is taking a long time during a preset set of debugger commands.''' - tricky_commands = [ 'qRegisterInfo' ] + tricky_commands = ['qRegisterInfo'] timestamp_regex = re.compile('(\s*)([1-9][0-9]+\.[0-9]+)([^0-9].*)$') packet_name_regex = re.compile('([A-Za-z_]+)[^a-z]') - packet_transmit_name_regex = re.compile('(?P<direction>send|read) packet: (?P<packet>.*)') + packet_transmit_name_regex = re.compile( + '(?P<direction>send|read) packet: (?P<packet>.*)') packet_contents_name_regex = re.compile('\$([^#]+)#[0-9a-fA-F]{2}') packet_checksum_regex = re.compile('.*#[0-9a-fA-F]{2}$') - packet_names_regex_str = '(' + '|'.join(gdb_remote_commands.keys()) + ')(.*)'; - packet_names_regex = re.compile(packet_names_regex_str); - + packet_names_regex_str = '(' + \ + '|'.join(gdb_remote_commands.keys()) + ')(.*)' + packet_names_regex = re.compile(packet_names_regex_str) + base_time = 0.0 last_time = 0.0 packet_send_time = 0.0 @@ -1181,22 +1304,24 @@ def parse_gdb_log(file, options): if not options.quiet and not hide_next_response: print '# ', line sys.stdout.write(options.colors.reset()) - - #print 'direction = "%s", packet = "%s"' % (direction, packet) - + + # print 'direction = "%s", packet = "%s"' % (direction, packet) + if packet[0] == '+': if is_command: print '-->', else: print '<--', - if not options.quiet: print 'ACK' + if not options.quiet: + print 'ACK' continue elif packet[0] == '-': if is_command: print '-->', else: print '<--', - if not options.quiet: print 'NACK' + if not options.quiet: + print 'NACK' continue elif packet[0] == '$': m = packet_contents_name_regex.match(packet) @@ -1222,7 +1347,7 @@ def parse_gdb_log(file, options): contents = decode_packet(m.group(1)) if is_command: hide_next_response = False - m = packet_names_regex.match (contents) + m = packet_names_regex.match(contents) if m: last_command = m.group(1) if last_command == '?': @@ -1230,13 +1355,14 @@ def parse_gdb_log(file, options): packet_name = last_command last_command_args = m.group(2) last_command_packet = contents - hide_next_response = gdb_remote_commands[last_command]['cmd'](options, last_command, last_command_args) + hide_next_response = gdb_remote_commands[last_command][ + 'cmd'](options, last_command, last_command_args) else: - packet_match = packet_name_regex.match (contents) + packet_match = packet_name_regex.match(contents) if packet_match: packet_name = packet_match.group(1) for tricky_cmd in tricky_commands: - if packet_name.find (tricky_cmd) == 0: + if packet_name.find(tricky_cmd) == 0: packet_name = tricky_cmd else: packet_name = contents @@ -1244,16 +1370,17 @@ def parse_gdb_log(file, options): last_command_args = None last_command_packet = None elif last_command: - gdb_remote_commands[last_command]['rsp'](options, last_command, last_command_args, contents) + gdb_remote_commands[last_command]['rsp']( + options, last_command, last_command_args, contents) else: print 'error: invalid packet: "', packet, '"' else: print '???' else: print '## ', line - match = timestamp_regex.match (line) + match = timestamp_regex.match(line) if match: - curr_time = float (match.group(2)) + curr_time = float(match.group(2)) if last_time and not is_command: delta = curr_time - last_time packet_times.append(delta) @@ -1262,7 +1389,7 @@ def parse_gdb_log(file, options): delta = curr_time - last_time else: base_time = curr_time - + if is_command: packet_send_time = curr_time elif line.find('read packet: $') >= 0 and packet_name: @@ -1300,30 +1427,68 @@ def parse_gdb_log(file, options): print '# Packet Time (sec) Percent Count ' print '#------------------------- ---------- ------- ------' if options and options.sort_count: - res = sorted(packet_count, key=packet_count.__getitem__, reverse=True) + res = sorted( + packet_count, + key=packet_count.__getitem__, + reverse=True) else: - res = sorted(packet_total_times, key=packet_total_times.__getitem__, reverse=True) + res = sorted( + packet_total_times, + key=packet_total_times.__getitem__, + reverse=True) if last_time > 0.0: for item in res: packet_total_time = packet_total_times[item] - packet_percent = (packet_total_time / total_packet_time)*100.0 + packet_percent = ( + packet_total_time / total_packet_time) * 100.0 if packet_percent >= 10.0: print " %24s %.6f %.2f%% %6d" % (item, packet_total_time, packet_percent, packet_count[item]) else: print " %24s %.6f %.2f%% %6d" % (item, packet_total_time, packet_percent, packet_count[item]) - - - + + if __name__ == '__main__': usage = "usage: gdbremote [options]" - description='''The command disassembles a GDB remote packet log.''' - parser = optparse.OptionParser(description=description, prog='gdbremote',usage=usage) - parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) - parser.add_option('-q', '--quiet', action='store_true', dest='quiet', help='display verbose debug info', default=False) - parser.add_option('-C', '--color', action='store_true', dest='color', help='add terminal colors', default=False) - parser.add_option('-c', '--sort-by-count', action='store_true', dest='sort_count', help='display verbose debug info', default=False) - parser.add_option('--crashlog', type='string', dest='crashlog', help='symbolicate using a darwin crash log file', default=False) + description = '''The command disassembles a GDB remote packet log.''' + parser = optparse.OptionParser( + description=description, + prog='gdbremote', + usage=usage) + parser.add_option( + '-v', + '--verbose', + action='store_true', + dest='verbose', + help='display verbose debug info', + default=False) + parser.add_option( + '-q', + '--quiet', + action='store_true', + dest='quiet', + help='display verbose debug info', + default=False) + parser.add_option( + '-C', + '--color', + action='store_true', + dest='color', + help='add terminal colors', + default=False) + parser.add_option( + '-c', + '--sort-by-count', + action='store_true', + dest='sort_count', + help='display verbose debug info', + default=False) + parser.add_option( + '--crashlog', + type='string', + dest='crashlog', + help='symbolicate using a darwin crash log file', + default=False) try: (options, args) = parser.parse_args(sys.argv[1:]) except: @@ -1346,17 +1511,19 @@ if __name__ == '__main__': print '#----------------------------------------------------------------------' print "# GDB remote log file: '%s'" % file print '#----------------------------------------------------------------------' - parse_gdb_log_file (file, options) + parse_gdb_log_file(file, options) if options.symbolicator: print '%s' % (options.symbolicator) else: parse_gdb_log(sys.stdin, options) - + else: import lldb - if lldb.debugger: + if lldb.debugger: # This initializer is being run from LLDB in the embedded command interpreter # Add any commands contained in this module to LLDB - lldb.debugger.HandleCommand('command script add -f gdbremote.start_gdb_log start_gdb_log') - lldb.debugger.HandleCommand('command script add -f gdbremote.stop_gdb_log stop_gdb_log') + lldb.debugger.HandleCommand( + 'command script add -f gdbremote.start_gdb_log start_gdb_log') + lldb.debugger.HandleCommand( + 'command script add -f gdbremote.stop_gdb_log stop_gdb_log') 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' |