1515bc8c1Sserge-sans-paille#!/usr/bin/env python 2e2841639SGreg Clayton 3e2841639SGreg Clayton#---------------------------------------------------------------------- 4e2841639SGreg Clayton# This module will enable GDB remote packet logging when the 5e2841639SGreg Clayton# 'start_gdb_log' command is called with a filename to log to. When the 6e2841639SGreg Clayton# 'stop_gdb_log' command is called, it will disable the logging and 7e2841639SGreg Clayton# print out statistics about how long commands took to execute and also 8e2841639SGreg Clayton# will primnt ou 9e2841639SGreg Clayton# Be sure to add the python path that points to the LLDB shared library. 10e2841639SGreg Clayton# 11e2841639SGreg Clayton# To use this in the embedded python interpreter using "lldb" just 12e2841639SGreg Clayton# import it with the full path using the "command script import" 13e2841639SGreg Clayton# command. This can be done from the LLDB command line: 14e2841639SGreg Clayton# (lldb) command script import /path/to/gdbremote.py 15e2841639SGreg Clayton# Or it can be added to your ~/.lldbinit file so this module is always 16e2841639SGreg Clayton# available. 17e2841639SGreg Clayton#---------------------------------------------------------------------- 18e2841639SGreg Clayton 19cb6c9f73SPavel Labathfrom __future__ import print_function 20374b6714SGreg Claytonimport binascii 211a12dd70SSerge Gueltonimport subprocess 228c2afa0cSGreg Claytonimport json 2325f82aaeSGreg Claytonimport math 24e2841639SGreg Claytonimport optparse 25e2841639SGreg Claytonimport os 26e2841639SGreg Claytonimport re 278ebb9a85SGreg Claytonimport shlex 288ebb9a85SGreg Claytonimport string 298ebb9a85SGreg Claytonimport sys 30e2841639SGreg Claytonimport tempfile 31374b6714SGreg Claytonimport xml.etree.ElementTree as ET 32e2841639SGreg Clayton 33f51a23fbSGreg Clayton#---------------------------------------------------------------------- 34f51a23fbSGreg Clayton# Global variables 35f51a23fbSGreg Clayton#---------------------------------------------------------------------- 36f51a23fbSGreg Claytong_log_file = '' 37f51a23fbSGreg Claytong_byte_order = 'little' 38205d6189SGreg Claytong_number_regex = re.compile('^(0x[0-9a-fA-F]+|[0-9]+)') 39a7a5e5a6SGreg Claytong_thread_id_regex = re.compile('^(-1|[0-9a-fA-F]+|0)') 40f51a23fbSGreg Clayton 41b9c1b51eSKate Stone 428ebb9a85SGreg Claytonclass TerminalColors: 438ebb9a85SGreg Clayton '''Simple terminal colors class''' 44b9c1b51eSKate Stone 45f51a23fbSGreg Clayton def __init__(self, enabled=True): 468ebb9a85SGreg Clayton # TODO: discover terminal type from "file" and disable if 478ebb9a85SGreg Clayton # it can't handle the color codes 488ebb9a85SGreg Clayton self.enabled = enabled 498ebb9a85SGreg Clayton 508ebb9a85SGreg Clayton def reset(self): 518ebb9a85SGreg Clayton '''Reset all terminal colors and formatting.''' 528ebb9a85SGreg Clayton if self.enabled: 53b9c1b51eSKate Stone return "\x1b[0m" 54f51a23fbSGreg Clayton return '' 558ebb9a85SGreg Clayton 568ebb9a85SGreg Clayton def bold(self, on=True): 57d93c4a33SBruce Mitchener '''Enable or disable bold depending on the "on" parameter.''' 588ebb9a85SGreg Clayton if self.enabled: 598ebb9a85SGreg Clayton if on: 60b9c1b51eSKate Stone return "\x1b[1m" 618ebb9a85SGreg Clayton else: 62b9c1b51eSKate Stone return "\x1b[22m" 63f51a23fbSGreg Clayton return '' 648ebb9a85SGreg Clayton 658ebb9a85SGreg Clayton def italics(self, on=True): 66d93c4a33SBruce Mitchener '''Enable or disable italics depending on the "on" parameter.''' 678ebb9a85SGreg Clayton if self.enabled: 688ebb9a85SGreg Clayton if on: 69b9c1b51eSKate Stone return "\x1b[3m" 708ebb9a85SGreg Clayton else: 71b9c1b51eSKate Stone return "\x1b[23m" 72f51a23fbSGreg Clayton return '' 738ebb9a85SGreg Clayton 748ebb9a85SGreg Clayton def underline(self, on=True): 75d93c4a33SBruce Mitchener '''Enable or disable underline depending on the "on" parameter.''' 768ebb9a85SGreg Clayton if self.enabled: 778ebb9a85SGreg Clayton if on: 78b9c1b51eSKate Stone return "\x1b[4m" 798ebb9a85SGreg Clayton else: 80b9c1b51eSKate Stone return "\x1b[24m" 81f51a23fbSGreg Clayton return '' 82f51a23fbSGreg Clayton 838ebb9a85SGreg Clayton def inverse(self, on=True): 84d93c4a33SBruce Mitchener '''Enable or disable inverse depending on the "on" parameter.''' 858ebb9a85SGreg Clayton if self.enabled: 868ebb9a85SGreg Clayton if on: 87b9c1b51eSKate Stone return "\x1b[7m" 888ebb9a85SGreg Clayton else: 89b9c1b51eSKate Stone return "\x1b[27m" 90f51a23fbSGreg Clayton return '' 918ebb9a85SGreg Clayton 928ebb9a85SGreg Clayton def strike(self, on=True): 93d93c4a33SBruce Mitchener '''Enable or disable strike through depending on the "on" parameter.''' 948ebb9a85SGreg Clayton if self.enabled: 958ebb9a85SGreg Clayton if on: 96b9c1b51eSKate Stone return "\x1b[9m" 978ebb9a85SGreg Clayton else: 98b9c1b51eSKate Stone return "\x1b[29m" 99f51a23fbSGreg Clayton return '' 1008ebb9a85SGreg Clayton 1018ebb9a85SGreg Clayton def black(self, fg=True): 1028ebb9a85SGreg Clayton '''Set the foreground or background color to black. 1038ebb9a85SGreg Clayton The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' 1048ebb9a85SGreg Clayton if self.enabled: 1058ebb9a85SGreg Clayton if fg: 106b9c1b51eSKate Stone return "\x1b[30m" 1078ebb9a85SGreg Clayton else: 108b9c1b51eSKate Stone return "\x1b[40m" 109f51a23fbSGreg Clayton return '' 1108ebb9a85SGreg Clayton 1118ebb9a85SGreg Clayton def red(self, fg=True): 1128ebb9a85SGreg Clayton '''Set the foreground or background color to red. 1138ebb9a85SGreg Clayton The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' 1148ebb9a85SGreg Clayton if self.enabled: 1158ebb9a85SGreg Clayton if fg: 116b9c1b51eSKate Stone return "\x1b[31m" 1178ebb9a85SGreg Clayton else: 118b9c1b51eSKate Stone return "\x1b[41m" 119f51a23fbSGreg Clayton return '' 1208ebb9a85SGreg Clayton 1218ebb9a85SGreg Clayton def green(self, fg=True): 1228ebb9a85SGreg Clayton '''Set the foreground or background color to green. 1238ebb9a85SGreg Clayton The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' 1248ebb9a85SGreg Clayton if self.enabled: 1258ebb9a85SGreg Clayton if fg: 126b9c1b51eSKate Stone return "\x1b[32m" 1278ebb9a85SGreg Clayton else: 128b9c1b51eSKate Stone return "\x1b[42m" 129f51a23fbSGreg Clayton return '' 1308ebb9a85SGreg Clayton 1318ebb9a85SGreg Clayton def yellow(self, fg=True): 1328ebb9a85SGreg Clayton '''Set the foreground or background color to yellow. 1338ebb9a85SGreg Clayton The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' 1348ebb9a85SGreg Clayton if self.enabled: 1358ebb9a85SGreg Clayton if fg: 136b9c1b51eSKate Stone return "\x1b[33m" 137a542e08cSGreg Clayton else: 138b9c1b51eSKate Stone return "\x1b[43m" 139f51a23fbSGreg Clayton return '' 1408ebb9a85SGreg Clayton 1418ebb9a85SGreg Clayton def blue(self, fg=True): 1428ebb9a85SGreg Clayton '''Set the foreground or background color to blue. 1438ebb9a85SGreg Clayton The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' 1448ebb9a85SGreg Clayton if self.enabled: 1458ebb9a85SGreg Clayton if fg: 146b9c1b51eSKate Stone return "\x1b[34m" 1478ebb9a85SGreg Clayton else: 148b9c1b51eSKate Stone return "\x1b[44m" 149f51a23fbSGreg Clayton return '' 1508ebb9a85SGreg Clayton 1518ebb9a85SGreg Clayton def magenta(self, fg=True): 1528ebb9a85SGreg Clayton '''Set the foreground or background color to magenta. 1538ebb9a85SGreg Clayton The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' 1548ebb9a85SGreg Clayton if self.enabled: 1558ebb9a85SGreg Clayton if fg: 156b9c1b51eSKate Stone return "\x1b[35m" 1578ebb9a85SGreg Clayton else: 158b9c1b51eSKate Stone return "\x1b[45m" 159f51a23fbSGreg Clayton return '' 1608ebb9a85SGreg Clayton 1618ebb9a85SGreg Clayton def cyan(self, fg=True): 1628ebb9a85SGreg Clayton '''Set the foreground or background color to cyan. 1638ebb9a85SGreg Clayton The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' 1648ebb9a85SGreg Clayton if self.enabled: 1658ebb9a85SGreg Clayton if fg: 166b9c1b51eSKate Stone return "\x1b[36m" 1678ebb9a85SGreg Clayton else: 168b9c1b51eSKate Stone return "\x1b[46m" 169f51a23fbSGreg Clayton return '' 1708ebb9a85SGreg Clayton 1718ebb9a85SGreg Clayton def white(self, fg=True): 1728ebb9a85SGreg Clayton '''Set the foreground or background color to white. 1738ebb9a85SGreg Clayton The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' 1748ebb9a85SGreg Clayton if self.enabled: 1758ebb9a85SGreg Clayton if fg: 176b9c1b51eSKate Stone return "\x1b[37m" 1778ebb9a85SGreg Clayton else: 178b9c1b51eSKate Stone return "\x1b[47m" 179f51a23fbSGreg Clayton return '' 1808ebb9a85SGreg Clayton 1818ebb9a85SGreg Clayton def default(self, fg=True): 1828ebb9a85SGreg Clayton '''Set the foreground or background color to the default. 1838ebb9a85SGreg Clayton The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' 1848ebb9a85SGreg Clayton if self.enabled: 1858ebb9a85SGreg Clayton if fg: 186b9c1b51eSKate Stone return "\x1b[39m" 1878ebb9a85SGreg Clayton else: 188b9c1b51eSKate Stone return "\x1b[49m" 189f51a23fbSGreg Clayton return '' 1908ebb9a85SGreg Clayton 191e2841639SGreg Clayton 192e2841639SGreg Claytondef start_gdb_log(debugger, command, result, dict): 193e2841639SGreg Clayton '''Start logging GDB remote packets by enabling logging with timestamps and 194e2841639SGreg Clayton thread safe logging. Follow a call to this function with a call to "stop_gdb_log" 195e2841639SGreg Clayton in order to dump out the commands.''' 1968ebb9a85SGreg Clayton global g_log_file 197e2841639SGreg Clayton command_args = shlex.split(command) 198e2841639SGreg Clayton usage = "usage: start_gdb_log [options] [<LOGFILEPATH>]" 199e2841639SGreg Clayton 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 200e2841639SGreg Clayton be aggregated and displayed.''' 201b9c1b51eSKate Stone parser = optparse.OptionParser( 202b9c1b51eSKate Stone description=description, 203b9c1b51eSKate Stone prog='start_gdb_log', 204b9c1b51eSKate Stone usage=usage) 205b9c1b51eSKate Stone parser.add_option( 206b9c1b51eSKate Stone '-v', 207b9c1b51eSKate Stone '--verbose', 208b9c1b51eSKate Stone action='store_true', 209b9c1b51eSKate Stone dest='verbose', 210b9c1b51eSKate Stone help='display verbose debug info', 211b9c1b51eSKate Stone default=False) 212e2841639SGreg Clayton try: 213e2841639SGreg Clayton (options, args) = parser.parse_args(command_args) 214e2841639SGreg Clayton except: 215e2841639SGreg Clayton return 216e2841639SGreg Clayton 2178ebb9a85SGreg Clayton if g_log_file: 218b9c1b51eSKate Stone result.PutCString( 219b9c1b51eSKate Stone 'error: logging is already in progress with file "%s"' % 220b9c1b51eSKate Stone g_log_file) 221e2841639SGreg Clayton else: 222e2841639SGreg Clayton args_len = len(args) 223e2841639SGreg Clayton if args_len == 0: 2248ebb9a85SGreg Clayton g_log_file = tempfile.mktemp() 225e2841639SGreg Clayton elif len(args) == 1: 2268ebb9a85SGreg Clayton g_log_file = args[0] 227e2841639SGreg Clayton 2288ebb9a85SGreg Clayton if g_log_file: 229b9c1b51eSKate Stone debugger.HandleCommand( 230b9c1b51eSKate Stone 'log enable --threadsafe --timestamp --file "%s" gdb-remote packets' % 231b9c1b51eSKate Stone g_log_file) 232b9c1b51eSKate Stone result.PutCString( 233b9c1b51eSKate Stone "GDB packet logging enable with log file '%s'\nUse the 'stop_gdb_log' command to stop logging and show packet statistics." % 234b9c1b51eSKate Stone g_log_file) 235e2841639SGreg Clayton return 236e2841639SGreg Clayton 237e2841639SGreg Clayton result.PutCString('error: invalid log file path') 238e2841639SGreg Clayton result.PutCString(usage) 239e2841639SGreg Clayton 240b9c1b51eSKate Stone 241e2841639SGreg Claytondef stop_gdb_log(debugger, command, result, dict): 242e2841639SGreg Clayton '''Stop logging GDB remote packets to the file that was specified in a call 243e2841639SGreg Clayton to "start_gdb_log" and normalize the timestamps to be relative to the first 244e2841639SGreg Clayton timestamp in the log file. Also print out statistics for how long each 245e2841639SGreg Clayton command took to allow performance bottlenecks to be determined.''' 2468ebb9a85SGreg Clayton global g_log_file 247e2841639SGreg Clayton # Any commands whose names might be followed by more valid C identifier 248e2841639SGreg Clayton # characters must be listed here 249e2841639SGreg Clayton command_args = shlex.split(command) 250e2841639SGreg Clayton usage = "usage: stop_gdb_log [options]" 251e2841639SGreg Clayton 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.''' 252b9c1b51eSKate Stone parser = optparse.OptionParser( 253b9c1b51eSKate Stone description=description, 254b9c1b51eSKate Stone prog='stop_gdb_log', 255b9c1b51eSKate Stone usage=usage) 256b9c1b51eSKate Stone parser.add_option( 257b9c1b51eSKate Stone '-v', 258b9c1b51eSKate Stone '--verbose', 259b9c1b51eSKate Stone action='store_true', 260b9c1b51eSKate Stone dest='verbose', 261b9c1b51eSKate Stone help='display verbose debug info', 262b9c1b51eSKate Stone default=False) 263b9c1b51eSKate Stone parser.add_option( 264*cd89f94aSDominic Chen '--plot', 265*cd89f94aSDominic Chen action='store_true', 266*cd89f94aSDominic Chen dest='plot', 267*cd89f94aSDominic Chen help='plot packet latencies by packet type', 268*cd89f94aSDominic Chen default=False) 269*cd89f94aSDominic Chen parser.add_option( 270b9c1b51eSKate Stone '-q', 271b9c1b51eSKate Stone '--quiet', 272b9c1b51eSKate Stone action='store_true', 273b9c1b51eSKate Stone dest='quiet', 274b9c1b51eSKate Stone help='display verbose debug info', 275b9c1b51eSKate Stone default=False) 276b9c1b51eSKate Stone parser.add_option( 277b9c1b51eSKate Stone '-C', 278b9c1b51eSKate Stone '--color', 279b9c1b51eSKate Stone action='store_true', 280b9c1b51eSKate Stone dest='color', 281b9c1b51eSKate Stone help='add terminal colors', 282b9c1b51eSKate Stone default=False) 283b9c1b51eSKate Stone parser.add_option( 284b9c1b51eSKate Stone '-c', 285b9c1b51eSKate Stone '--sort-by-count', 286b9c1b51eSKate Stone action='store_true', 287b9c1b51eSKate Stone dest='sort_count', 288b9c1b51eSKate Stone help='display verbose debug info', 289b9c1b51eSKate Stone default=False) 290b9c1b51eSKate Stone parser.add_option( 291b9c1b51eSKate Stone '-s', 292b9c1b51eSKate Stone '--symbolicate', 293b9c1b51eSKate Stone action='store_true', 294b9c1b51eSKate Stone dest='symbolicate', 295b9c1b51eSKate Stone help='symbolicate addresses in log using current "lldb.target"', 296b9c1b51eSKate Stone default=False) 297e2841639SGreg Clayton try: 298e2841639SGreg Clayton (options, args) = parser.parse_args(command_args) 299e2841639SGreg Clayton except: 300e2841639SGreg Clayton return 301f51a23fbSGreg Clayton options.colors = TerminalColors(options.color) 302f51a23fbSGreg Clayton options.symbolicator = None 303f51a23fbSGreg Clayton if options.symbolicate: 304f51a23fbSGreg Clayton if lldb.target: 305f51a23fbSGreg Clayton import lldb.utils.symbolication 306f51a23fbSGreg Clayton options.symbolicator = lldb.utils.symbolication.Symbolicator() 307f51a23fbSGreg Clayton options.symbolicator.target = lldb.target 308f51a23fbSGreg Clayton else: 309525cd59fSSerge Guelton print("error: can't symbolicate without a target") 310e2841639SGreg Clayton 3118ebb9a85SGreg Clayton if not g_log_file: 312b9c1b51eSKate Stone result.PutCString( 313b9c1b51eSKate Stone 'error: logging must have been previously enabled with a call to "stop_gdb_log"') 3148ebb9a85SGreg Clayton elif os.path.exists(g_log_file): 315e2841639SGreg Clayton if len(args) == 0: 316b9c1b51eSKate Stone debugger.HandleCommand('log disable gdb-remote packets') 317b9c1b51eSKate Stone result.PutCString( 318b9c1b51eSKate Stone "GDB packet logging disabled. Logged packets are in '%s'" % 319b9c1b51eSKate Stone g_log_file) 3208ebb9a85SGreg Clayton parse_gdb_log_file(g_log_file, options) 321e2841639SGreg Clayton else: 322e2841639SGreg Clayton result.PutCString(usage) 323e2841639SGreg Clayton else: 324525cd59fSSerge Guelton print('error: the GDB packet log file "%s" does not exist' % g_log_file) 325e2841639SGreg Clayton 326b9c1b51eSKate Stone 3278ebb9a85SGreg Claytondef is_hex_byte(str): 3288ebb9a85SGreg Clayton if len(str) == 2: 329b9c1b51eSKate Stone return str[0] in string.hexdigits and str[1] in string.hexdigits 3308ebb9a85SGreg Clayton return False 3318ebb9a85SGreg Clayton 332db1550abSGreg Claytondef get_hex_string_if_all_printable(str): 333db1550abSGreg Clayton try: 334cb6c9f73SPavel Labath s = binascii.unhexlify(str).decode() 335db1550abSGreg Clayton if all(c in string.printable for c in s): 336db1550abSGreg Clayton return s 337cb6c9f73SPavel Labath except (TypeError, binascii.Error, UnicodeDecodeError): 338db1550abSGreg Clayton pass 339db1550abSGreg Clayton return None 340db1550abSGreg Clayton 3418ebb9a85SGreg Clayton# global register info list 3428ebb9a85SGreg Claytong_register_infos = list() 3438ebb9a85SGreg Claytong_max_register_info_name_len = 0 3448ebb9a85SGreg Clayton 345b9c1b51eSKate Stone 3468ebb9a85SGreg Claytonclass RegisterInfo: 3478ebb9a85SGreg Clayton """Class that represents register information""" 348b9c1b51eSKate Stone 3498ebb9a85SGreg Clayton def __init__(self, kvp): 3508ebb9a85SGreg Clayton self.info = dict() 3518ebb9a85SGreg Clayton for kv in kvp: 3528ebb9a85SGreg Clayton key = kv[0] 3538ebb9a85SGreg Clayton value = kv[1] 3548ebb9a85SGreg Clayton self.info[key] = value 355b9c1b51eSKate Stone 3568ebb9a85SGreg Clayton def name(self): 3578ebb9a85SGreg Clayton '''Get the name of the register.''' 3588ebb9a85SGreg Clayton if self.info and 'name' in self.info: 3598ebb9a85SGreg Clayton return self.info['name'] 3608ebb9a85SGreg Clayton return None 3618ebb9a85SGreg Clayton 3628ebb9a85SGreg Clayton def bit_size(self): 3638ebb9a85SGreg Clayton '''Get the size in bits of the register.''' 3648ebb9a85SGreg Clayton if self.info and 'bitsize' in self.info: 3658ebb9a85SGreg Clayton return int(self.info['bitsize']) 3668ebb9a85SGreg Clayton return 0 3678ebb9a85SGreg Clayton 3688ebb9a85SGreg Clayton def byte_size(self): 3698ebb9a85SGreg Clayton '''Get the size in bytes of the register.''' 3708ebb9a85SGreg Clayton return self.bit_size() / 8 3718ebb9a85SGreg Clayton 3728ebb9a85SGreg Clayton def get_value_from_hex_string(self, hex_str): 3738ebb9a85SGreg Clayton '''Dump the register value given a native byte order encoded hex ASCII byte string.''' 3748ebb9a85SGreg Clayton encoding = self.info['encoding'] 3758ebb9a85SGreg Clayton bit_size = self.bit_size() 3768ebb9a85SGreg Clayton packet = Packet(hex_str) 3778ebb9a85SGreg Clayton if encoding == 'uint': 3788ebb9a85SGreg Clayton uval = packet.get_hex_uint(g_byte_order) 3798ebb9a85SGreg Clayton if bit_size == 8: 3808ebb9a85SGreg Clayton return '0x%2.2x' % (uval) 3818ebb9a85SGreg Clayton elif bit_size == 16: 3828ebb9a85SGreg Clayton return '0x%4.4x' % (uval) 3838ebb9a85SGreg Clayton elif bit_size == 32: 3848ebb9a85SGreg Clayton return '0x%8.8x' % (uval) 3858ebb9a85SGreg Clayton elif bit_size == 64: 3868ebb9a85SGreg Clayton return '0x%16.16x' % (uval) 387b9c1b51eSKate Stone bytes = list() 3888ebb9a85SGreg Clayton uval = packet.get_hex_uint8() 389b9c1b51eSKate Stone while uval is not None: 3908ebb9a85SGreg Clayton bytes.append(uval) 3918ebb9a85SGreg Clayton uval = packet.get_hex_uint8() 3928ebb9a85SGreg Clayton value_str = '0x' 3938ebb9a85SGreg Clayton if g_byte_order == 'little': 3948ebb9a85SGreg Clayton bytes.reverse() 3958ebb9a85SGreg Clayton for byte in bytes: 3968ebb9a85SGreg Clayton value_str += '%2.2x' % byte 3978ebb9a85SGreg Clayton return '%s' % (value_str) 3988ebb9a85SGreg Clayton 3998ebb9a85SGreg Clayton def __str__(self): 4008ebb9a85SGreg Clayton '''Dump the register info key/value pairs''' 4018ebb9a85SGreg Clayton s = '' 4028ebb9a85SGreg Clayton for key in self.info.keys(): 4038ebb9a85SGreg Clayton if s: 4048ebb9a85SGreg Clayton s += ', ' 4058ebb9a85SGreg Clayton s += "%s=%s " % (key, self.info[key]) 4068ebb9a85SGreg Clayton return s 4078ebb9a85SGreg Clayton 408b9c1b51eSKate Stone 4098ebb9a85SGreg Claytonclass Packet: 4108ebb9a85SGreg Clayton """Class that represents a packet that contains string data""" 411b9c1b51eSKate Stone 4128ebb9a85SGreg Clayton def __init__(self, packet_str): 4138ebb9a85SGreg Clayton self.str = packet_str 4148ebb9a85SGreg Clayton 4158ebb9a85SGreg Clayton def peek_char(self): 4168ebb9a85SGreg Clayton ch = 0 4178ebb9a85SGreg Clayton if self.str: 4188ebb9a85SGreg Clayton ch = self.str[0] 4198ebb9a85SGreg Clayton return ch 4208ebb9a85SGreg Clayton 4218ebb9a85SGreg Clayton def get_char(self): 4228ebb9a85SGreg Clayton ch = 0 4238ebb9a85SGreg Clayton if self.str: 4248ebb9a85SGreg Clayton ch = self.str[0] 4258ebb9a85SGreg Clayton self.str = self.str[1:] 4268ebb9a85SGreg Clayton return ch 4278ebb9a85SGreg Clayton 428205d6189SGreg Clayton def skip_exact_string(self, s): 429205d6189SGreg Clayton if self.str and self.str.startswith(s): 430205d6189SGreg Clayton self.str = self.str[len(s):] 431205d6189SGreg Clayton return True 432205d6189SGreg Clayton else: 433205d6189SGreg Clayton return False 434205d6189SGreg Clayton 435a7a5e5a6SGreg Clayton def get_thread_id(self, fail_value=-1): 436a7a5e5a6SGreg Clayton match = g_number_regex.match(self.str) 437a7a5e5a6SGreg Clayton if match: 438a7a5e5a6SGreg Clayton number_str = match.group(1) 439a7a5e5a6SGreg Clayton self.str = self.str[len(number_str):] 440a7a5e5a6SGreg Clayton return int(number_str, 0) 441a7a5e5a6SGreg Clayton else: 442a7a5e5a6SGreg Clayton return fail_value 443a7a5e5a6SGreg Clayton 4448ebb9a85SGreg Clayton def get_hex_uint8(self): 445b9c1b51eSKate Stone if self.str and len(self.str) >= 2 and self.str[ 446b9c1b51eSKate Stone 0] in string.hexdigits and self.str[1] in string.hexdigits: 4478ebb9a85SGreg Clayton uval = int(self.str[0:2], 16) 4488ebb9a85SGreg Clayton self.str = self.str[2:] 4498ebb9a85SGreg Clayton return uval 4508ebb9a85SGreg Clayton return None 4518ebb9a85SGreg Clayton 4528ebb9a85SGreg Clayton def get_hex_uint16(self, byte_order): 4538ebb9a85SGreg Clayton uval = 0 4548ebb9a85SGreg Clayton if byte_order == 'big': 4558ebb9a85SGreg Clayton uval |= self.get_hex_uint8() << 8 4568ebb9a85SGreg Clayton uval |= self.get_hex_uint8() 4578ebb9a85SGreg Clayton else: 4588ebb9a85SGreg Clayton uval |= self.get_hex_uint8() 4598ebb9a85SGreg Clayton uval |= self.get_hex_uint8() << 8 4608ebb9a85SGreg Clayton return uval 4618ebb9a85SGreg Clayton 4628ebb9a85SGreg Clayton def get_hex_uint32(self, byte_order): 4638ebb9a85SGreg Clayton uval = 0 4648ebb9a85SGreg Clayton if byte_order == 'big': 4658ebb9a85SGreg Clayton uval |= self.get_hex_uint8() << 24 4668ebb9a85SGreg Clayton uval |= self.get_hex_uint8() << 16 4678ebb9a85SGreg Clayton uval |= self.get_hex_uint8() << 8 4688ebb9a85SGreg Clayton uval |= self.get_hex_uint8() 4698ebb9a85SGreg Clayton else: 4708ebb9a85SGreg Clayton uval |= self.get_hex_uint8() 4718ebb9a85SGreg Clayton uval |= self.get_hex_uint8() << 8 4728ebb9a85SGreg Clayton uval |= self.get_hex_uint8() << 16 4738ebb9a85SGreg Clayton uval |= self.get_hex_uint8() << 24 4748ebb9a85SGreg Clayton return uval 4758ebb9a85SGreg Clayton 4768ebb9a85SGreg Clayton def get_hex_uint64(self, byte_order): 4778ebb9a85SGreg Clayton uval = 0 4788ebb9a85SGreg Clayton if byte_order == 'big': 4798ebb9a85SGreg Clayton uval |= self.get_hex_uint8() << 56 4808ebb9a85SGreg Clayton uval |= self.get_hex_uint8() << 48 4818ebb9a85SGreg Clayton uval |= self.get_hex_uint8() << 40 4828ebb9a85SGreg Clayton uval |= self.get_hex_uint8() << 32 4838ebb9a85SGreg Clayton uval |= self.get_hex_uint8() << 24 4848ebb9a85SGreg Clayton uval |= self.get_hex_uint8() << 16 4858ebb9a85SGreg Clayton uval |= self.get_hex_uint8() << 8 4868ebb9a85SGreg Clayton uval |= self.get_hex_uint8() 4878ebb9a85SGreg Clayton else: 4888ebb9a85SGreg Clayton uval |= self.get_hex_uint8() 4898ebb9a85SGreg Clayton uval |= self.get_hex_uint8() << 8 4908ebb9a85SGreg Clayton uval |= self.get_hex_uint8() << 16 4918ebb9a85SGreg Clayton uval |= self.get_hex_uint8() << 24 4928ebb9a85SGreg Clayton uval |= self.get_hex_uint8() << 32 4938ebb9a85SGreg Clayton uval |= self.get_hex_uint8() << 40 4948ebb9a85SGreg Clayton uval |= self.get_hex_uint8() << 48 4958ebb9a85SGreg Clayton uval |= self.get_hex_uint8() << 56 4968ebb9a85SGreg Clayton return uval 4978ebb9a85SGreg Clayton 498205d6189SGreg Clayton def get_number(self, fail_value=-1): 499205d6189SGreg Clayton '''Get a number from the packet. The number must be in big endian format and should be parsed 500205d6189SGreg Clayton according to its prefix (starts with "0x" means hex, starts with "0" means octal, starts with 501205d6189SGreg Clayton [1-9] means decimal, etc)''' 502205d6189SGreg Clayton match = g_number_regex.match(self.str) 503205d6189SGreg Clayton if match: 504205d6189SGreg Clayton number_str = match.group(1) 505205d6189SGreg Clayton self.str = self.str[len(number_str):] 506205d6189SGreg Clayton return int(number_str, 0) 507205d6189SGreg Clayton else: 508205d6189SGreg Clayton return fail_value 509205d6189SGreg Clayton 510374b6714SGreg Clayton def get_hex_ascii_str(self, n=0): 511374b6714SGreg Clayton hex_chars = self.get_hex_chars(n) 512374b6714SGreg Clayton if hex_chars: 513374b6714SGreg Clayton return binascii.unhexlify(hex_chars) 514374b6714SGreg Clayton else: 515374b6714SGreg Clayton return None 516374b6714SGreg Clayton 5178ebb9a85SGreg Clayton def get_hex_chars(self, n=0): 5188ebb9a85SGreg Clayton str_len = len(self.str) 5198ebb9a85SGreg Clayton if n == 0: 5208ebb9a85SGreg Clayton # n was zero, so we need to determine all hex chars and 5218ebb9a85SGreg Clayton # stop when we hit the end of the string of a non-hex character 5228ebb9a85SGreg Clayton while n < str_len and self.str[n] in string.hexdigits: 5238ebb9a85SGreg Clayton n = n + 1 5248ebb9a85SGreg Clayton else: 5258ebb9a85SGreg Clayton if n > str_len: 5268ebb9a85SGreg Clayton return None # Not enough chars 5278ebb9a85SGreg Clayton # Verify all chars are hex if a length was specified 5288ebb9a85SGreg Clayton for i in range(n): 5298ebb9a85SGreg Clayton if self.str[i] not in string.hexdigits: 5308ebb9a85SGreg Clayton return None # Not all hex digits 5318ebb9a85SGreg Clayton if n == 0: 5328ebb9a85SGreg Clayton return None 5338ebb9a85SGreg Clayton hex_str = self.str[0:n] 5348ebb9a85SGreg Clayton self.str = self.str[n:] 5358ebb9a85SGreg Clayton return hex_str 5368ebb9a85SGreg Clayton 5378ebb9a85SGreg Clayton def get_hex_uint(self, byte_order, n=0): 5388ebb9a85SGreg Clayton if byte_order == 'big': 5398ebb9a85SGreg Clayton hex_str = self.get_hex_chars(n) 540b9c1b51eSKate Stone if hex_str is None: 5418ebb9a85SGreg Clayton return None 5428ebb9a85SGreg Clayton return int(hex_str, 16) 5438ebb9a85SGreg Clayton else: 5448ebb9a85SGreg Clayton uval = self.get_hex_uint8() 545b9c1b51eSKate Stone if uval is None: 5468ebb9a85SGreg Clayton return None 5478ebb9a85SGreg Clayton uval_result = 0 5488ebb9a85SGreg Clayton shift = 0 549b9c1b51eSKate Stone while uval is not None: 5508ebb9a85SGreg Clayton uval_result |= (uval << shift) 5518ebb9a85SGreg Clayton shift += 8 5528ebb9a85SGreg Clayton uval = self.get_hex_uint8() 5538ebb9a85SGreg Clayton return uval_result 5548ebb9a85SGreg Clayton 5558ebb9a85SGreg Clayton def get_key_value_pairs(self): 5568ebb9a85SGreg Clayton kvp = list() 55725f82aaeSGreg Clayton if ';' in self.str: 558cb6c9f73SPavel Labath key_value_pairs = self.str.split(';') 5598ebb9a85SGreg Clayton for key_value_pair in key_value_pairs: 5608ebb9a85SGreg Clayton if len(key_value_pair): 561cb6c9f73SPavel Labath kvp.append(key_value_pair.split(':', 1)) 5628ebb9a85SGreg Clayton return kvp 5638ebb9a85SGreg Clayton 5648ebb9a85SGreg Clayton def split(self, ch): 565*cd89f94aSDominic Chen return self.str.split(ch) 5668ebb9a85SGreg Clayton 5678ebb9a85SGreg Clayton def split_hex(self, ch, byte_order): 5688ebb9a85SGreg Clayton hex_values = list() 569*cd89f94aSDominic Chen strings = self.str.split(ch) 5708ebb9a85SGreg Clayton for str in strings: 5718ebb9a85SGreg Clayton hex_values.append(Packet(str).get_hex_uint(byte_order)) 5728ebb9a85SGreg Clayton return hex_values 5738ebb9a85SGreg Clayton 5748ebb9a85SGreg Clayton def __str__(self): 5758ebb9a85SGreg Clayton return self.str 5768ebb9a85SGreg Clayton 5778ebb9a85SGreg Clayton def __len__(self): 5788ebb9a85SGreg Clayton return len(self.str) 5798ebb9a85SGreg Clayton 5808ebb9a85SGreg Claytong_thread_suffix_regex = re.compile(';thread:([0-9a-fA-F]+);') 581b9c1b51eSKate Stone 582b9c1b51eSKate Stone 5838ebb9a85SGreg Claytondef get_thread_from_thread_suffix(str): 5848ebb9a85SGreg Clayton if str: 5858ebb9a85SGreg Clayton match = g_thread_suffix_regex.match(str) 5868ebb9a85SGreg Clayton if match: 5878ebb9a85SGreg Clayton return int(match.group(1), 16) 5888ebb9a85SGreg Clayton return None 5898ebb9a85SGreg Clayton 590b9c1b51eSKate Stone 591a7a5e5a6SGreg Claytondef cmd_qThreadStopInfo(options, cmd, args): 592a7a5e5a6SGreg Clayton packet = Packet(args) 593a7a5e5a6SGreg Clayton tid = packet.get_hex_uint('big') 594525cd59fSSerge Guelton print("get_thread_stop_info (tid = 0x%x)" % (tid)) 595a7a5e5a6SGreg Clayton 596b9c1b51eSKate Stone 597f51a23fbSGreg Claytondef cmd_stop_reply(options, cmd, args): 598525cd59fSSerge Guelton print("get_last_stop_info()") 599205d6189SGreg Clayton return False 6008ebb9a85SGreg Clayton 601b9c1b51eSKate Stone 602f51a23fbSGreg Claytondef rsp_stop_reply(options, cmd, cmd_args, rsp): 6038ebb9a85SGreg Clayton global g_byte_order 6048ebb9a85SGreg Clayton packet = Packet(rsp) 6058ebb9a85SGreg Clayton stop_type = packet.get_char() 6068ebb9a85SGreg Clayton if stop_type == 'T' or stop_type == 'S': 6078ebb9a85SGreg Clayton signo = packet.get_hex_uint8() 6088ebb9a85SGreg Clayton key_value_pairs = packet.get_key_value_pairs() 6098ebb9a85SGreg Clayton for key_value_pair in key_value_pairs: 6108ebb9a85SGreg Clayton key = key_value_pair[0] 6118ebb9a85SGreg Clayton if is_hex_byte(key): 6128ebb9a85SGreg Clayton reg_num = Packet(key).get_hex_uint8() 613374b6714SGreg Clayton if reg_num < len(g_register_infos): 614374b6714SGreg Clayton reg_info = g_register_infos[reg_num] 615374b6714SGreg Clayton key_value_pair[0] = reg_info.name() 616b9c1b51eSKate Stone key_value_pair[1] = reg_info.get_value_from_hex_string( 617b9c1b51eSKate Stone key_value_pair[1]) 618b2273bd3SGreg Clayton elif key == 'jthreads' or key == 'jstopinfo': 619b2273bd3SGreg Clayton key_value_pair[1] = binascii.unhexlify(key_value_pair[1]) 620374b6714SGreg Clayton key_value_pairs.insert(0, ['signal', signo]) 621525cd59fSSerge Guelton print('stop_reply():') 622374b6714SGreg Clayton dump_key_value_pairs(key_value_pairs) 6238ebb9a85SGreg Clayton elif stop_type == 'W': 6248ebb9a85SGreg Clayton exit_status = packet.get_hex_uint8() 625525cd59fSSerge Guelton print('stop_reply(): exit (status=%i)' % exit_status) 6268ebb9a85SGreg Clayton elif stop_type == 'O': 627525cd59fSSerge Guelton print('stop_reply(): stdout = "%s"' % packet.str) 6288ebb9a85SGreg Clayton 6298ebb9a85SGreg Clayton 630f51a23fbSGreg Claytondef cmd_unknown_packet(options, cmd, args): 6318ebb9a85SGreg Clayton if args: 632525cd59fSSerge Guelton print("cmd: %s, args: %s", cmd, args) 6338ebb9a85SGreg Clayton else: 634525cd59fSSerge Guelton print("cmd: %s", cmd) 635205d6189SGreg Clayton return False 636205d6189SGreg Clayton 637b9c1b51eSKate Stone 638205d6189SGreg Claytondef cmd_qSymbol(options, cmd, args): 639205d6189SGreg Clayton if args == ':': 640525cd59fSSerge Guelton print('ready to serve symbols') 641205d6189SGreg Clayton else: 642205d6189SGreg Clayton packet = Packet(args) 643205d6189SGreg Clayton symbol_addr = packet.get_hex_uint('big') 644205d6189SGreg Clayton if symbol_addr is None: 645205d6189SGreg Clayton if packet.skip_exact_string(':'): 646205d6189SGreg Clayton symbol_name = packet.get_hex_ascii_str() 647525cd59fSSerge Guelton print('lookup_symbol("%s") -> symbol not available yet' % (symbol_name)) 648205d6189SGreg Clayton else: 649525cd59fSSerge Guelton print('error: bad command format') 650205d6189SGreg Clayton else: 651205d6189SGreg Clayton if packet.skip_exact_string(':'): 652205d6189SGreg Clayton symbol_name = packet.get_hex_ascii_str() 653525cd59fSSerge Guelton print('lookup_symbol("%s") -> 0x%x' % (symbol_name, symbol_addr)) 654205d6189SGreg Clayton else: 655525cd59fSSerge Guelton print('error: bad command format') 656205d6189SGreg Clayton 657db1550abSGreg Claytondef cmd_QSetWithHexString(options, cmd, args): 658525cd59fSSerge Guelton print('%s("%s")' % (cmd[:-1], binascii.unhexlify(args))) 659db1550abSGreg Clayton 660db1550abSGreg Claytondef cmd_QSetWithString(options, cmd, args): 661525cd59fSSerge Guelton print('%s("%s")' % (cmd[:-1], args)) 662db1550abSGreg Clayton 663db1550abSGreg Claytondef cmd_QSetWithUnsigned(options, cmd, args): 664525cd59fSSerge Guelton print('%s(%i)' % (cmd[:-1], int(args))) 665b9c1b51eSKate Stone 666205d6189SGreg Claytondef rsp_qSymbol(options, cmd, cmd_args, rsp): 667205d6189SGreg Clayton if len(rsp) == 0: 668525cd59fSSerge Guelton print("Unsupported") 669205d6189SGreg Clayton else: 670205d6189SGreg Clayton if rsp == "OK": 671525cd59fSSerge Guelton print("No more symbols to lookup") 672205d6189SGreg Clayton else: 673205d6189SGreg Clayton packet = Packet(rsp) 674205d6189SGreg Clayton if packet.skip_exact_string("qSymbol:"): 675205d6189SGreg Clayton symbol_name = packet.get_hex_ascii_str() 676525cd59fSSerge Guelton print('lookup_symbol("%s")' % (symbol_name)) 677205d6189SGreg Clayton else: 678525cd59fSSerge Guelton print('error: response string should start with "qSymbol:": respnse is "%s"' % (rsp)) 6798ebb9a85SGreg Clayton 680b9c1b51eSKate Stone 681374b6714SGreg Claytondef cmd_qXfer(options, cmd, args): 682374b6714SGreg Clayton # $qXfer:features:read:target.xml:0,1ffff#14 683525cd59fSSerge Guelton print("read target special data %s" % (args)) 684205d6189SGreg Clayton return True 685374b6714SGreg Clayton 686b9c1b51eSKate Stone 687374b6714SGreg Claytondef rsp_qXfer(options, cmd, cmd_args, rsp): 688cb6c9f73SPavel Labath data = cmd_args.split(':') 689374b6714SGreg Clayton if data[0] == 'features': 690374b6714SGreg Clayton if data[1] == 'read': 691374b6714SGreg Clayton filename, extension = os.path.splitext(data[2]) 692374b6714SGreg Clayton if extension == '.xml': 693374b6714SGreg Clayton response = Packet(rsp) 694374b6714SGreg Clayton xml_string = response.get_hex_ascii_str() 695141f208eSGreg Clayton if xml_string: 696374b6714SGreg Clayton ch = xml_string[0] 697374b6714SGreg Clayton if ch == 'l': 698374b6714SGreg Clayton xml_string = xml_string[1:] 699374b6714SGreg Clayton xml_root = ET.fromstring(xml_string) 700374b6714SGreg Clayton for reg_element in xml_root.findall("./feature/reg"): 701374b6714SGreg Clayton if not 'value_regnums' in reg_element.attrib: 702374b6714SGreg Clayton reg_info = RegisterInfo([]) 703374b6714SGreg Clayton if 'name' in reg_element.attrib: 704b9c1b51eSKate Stone reg_info.info[ 705b9c1b51eSKate Stone 'name'] = reg_element.attrib['name'] 706374b6714SGreg Clayton else: 707374b6714SGreg Clayton reg_info.info['name'] = 'unspecified' 708374b6714SGreg Clayton if 'encoding' in reg_element.attrib: 709b9c1b51eSKate Stone reg_info.info['encoding'] = reg_element.attrib[ 710b9c1b51eSKate Stone 'encoding'] 711374b6714SGreg Clayton else: 712374b6714SGreg Clayton reg_info.info['encoding'] = 'uint' 713374b6714SGreg Clayton if 'offset' in reg_element.attrib: 714b9c1b51eSKate Stone reg_info.info[ 715b9c1b51eSKate Stone 'offset'] = reg_element.attrib['offset'] 716374b6714SGreg Clayton if 'bitsize' in reg_element.attrib: 717b9c1b51eSKate Stone reg_info.info[ 718b9c1b51eSKate Stone 'bitsize'] = reg_element.attrib['bitsize'] 719374b6714SGreg Clayton g_register_infos.append(reg_info) 720525cd59fSSerge Guelton print('XML for "%s":' % (data[2])) 721205d6189SGreg Clayton ET.dump(xml_root) 722374b6714SGreg Clayton 723b9c1b51eSKate Stone 724a7a5e5a6SGreg Claytondef cmd_A(options, cmd, args): 725525cd59fSSerge Guelton print('launch process:') 726a7a5e5a6SGreg Clayton packet = Packet(args) 727b9c1b51eSKate Stone while True: 728a7a5e5a6SGreg Clayton arg_len = packet.get_number() 729a542e08cSGreg Clayton if arg_len == -1: 730a542e08cSGreg Clayton break 731a7a5e5a6SGreg Clayton if not packet.skip_exact_string(','): 732a7a5e5a6SGreg Clayton break 733a7a5e5a6SGreg Clayton arg_idx = packet.get_number() 734a542e08cSGreg Clayton if arg_idx == -1: 735a542e08cSGreg Clayton break 736a7a5e5a6SGreg Clayton if not packet.skip_exact_string(','): 737b9c1b51eSKate Stone break 738a7a5e5a6SGreg Clayton arg_value = packet.get_hex_ascii_str(arg_len) 739525cd59fSSerge Guelton print('argv[%u] = "%s"' % (arg_idx, arg_value)) 740a7a5e5a6SGreg Clayton 741b9c1b51eSKate Stone 742a7a5e5a6SGreg Claytondef cmd_qC(options, cmd, args): 743525cd59fSSerge Guelton print("query_current_thread_id()") 744a7a5e5a6SGreg Clayton 745b9c1b51eSKate Stone 746a7a5e5a6SGreg Claytondef rsp_qC(options, cmd, cmd_args, rsp): 747a7a5e5a6SGreg Clayton packet = Packet(rsp) 748a7a5e5a6SGreg Clayton if packet.skip_exact_string("QC"): 749a7a5e5a6SGreg Clayton tid = packet.get_thread_id() 750525cd59fSSerge Guelton print("current_thread_id = %#x" % (tid)) 751a7a5e5a6SGreg Clayton else: 752525cd59fSSerge Guelton print("current_thread_id = old thread ID") 753a7a5e5a6SGreg Clayton 754b9c1b51eSKate Stone 755f51a23fbSGreg Claytondef cmd_query_packet(options, cmd, args): 7568ebb9a85SGreg Clayton if args: 757525cd59fSSerge Guelton print("%s%s" % (cmd, args)) 7588ebb9a85SGreg Clayton else: 759525cd59fSSerge Guelton print("%s" % (cmd)) 760205d6189SGreg Clayton return False 7618ebb9a85SGreg Clayton 762b9c1b51eSKate Stone 7638ebb9a85SGreg Claytondef rsp_ok_error(rsp): 764525cd59fSSerge Guelton print("rsp: ", rsp) 7658ebb9a85SGreg Clayton 766b9c1b51eSKate Stone 767f51a23fbSGreg Claytondef rsp_ok_means_supported(options, cmd, cmd_args, rsp): 7688ebb9a85SGreg Clayton if rsp == 'OK': 769525cd59fSSerge Guelton print("%s%s is supported" % (cmd, cmd_args)) 7708ebb9a85SGreg Clayton elif rsp == '': 771525cd59fSSerge Guelton print("%s%s is not supported" % (cmd, cmd_args)) 7728ebb9a85SGreg Clayton else: 773525cd59fSSerge Guelton print("%s%s -> %s" % (cmd, cmd_args, rsp)) 7748ebb9a85SGreg Clayton 775b9c1b51eSKate Stone 776f51a23fbSGreg Claytondef rsp_ok_means_success(options, cmd, cmd_args, rsp): 7778ebb9a85SGreg Clayton if rsp == 'OK': 778525cd59fSSerge Guelton print("success") 7798ebb9a85SGreg Clayton elif rsp == '': 780525cd59fSSerge Guelton print("%s%s is not supported" % (cmd, cmd_args)) 7818ebb9a85SGreg Clayton else: 782525cd59fSSerge Guelton print("%s%s -> %s" % (cmd, cmd_args, rsp)) 7838ebb9a85SGreg Clayton 784b9c1b51eSKate Stone 785374b6714SGreg Claytondef dump_key_value_pairs(key_value_pairs): 786374b6714SGreg Clayton max_key_len = 0 787374b6714SGreg Clayton for key_value_pair in key_value_pairs: 788374b6714SGreg Clayton key_len = len(key_value_pair[0]) 789374b6714SGreg Clayton if max_key_len < key_len: 790374b6714SGreg Clayton max_key_len = key_len 791374b6714SGreg Clayton for key_value_pair in key_value_pairs: 792374b6714SGreg Clayton key = key_value_pair[0] 793374b6714SGreg Clayton value = key_value_pair[1] 794db1550abSGreg Clayton unhex_value = get_hex_string_if_all_printable(value) 795db1550abSGreg Clayton if unhex_value: 796525cd59fSSerge Guelton print("%*s = %s (%s)" % (max_key_len, key, value, unhex_value)) 797db1550abSGreg Clayton else: 798525cd59fSSerge Guelton print("%*s = %s" % (max_key_len, key, value)) 799374b6714SGreg Clayton 800b9c1b51eSKate Stone 801f51a23fbSGreg Claytondef rsp_dump_key_value_pairs(options, cmd, cmd_args, rsp): 8028ebb9a85SGreg Clayton if rsp: 803525cd59fSSerge Guelton print('%s response:' % (cmd)) 8048ebb9a85SGreg Clayton packet = Packet(rsp) 8058ebb9a85SGreg Clayton key_value_pairs = packet.get_key_value_pairs() 806374b6714SGreg Clayton dump_key_value_pairs(key_value_pairs) 8078ebb9a85SGreg Clayton else: 808525cd59fSSerge Guelton print("not supported") 8098ebb9a85SGreg Clayton 810b9c1b51eSKate Stone 811b2273bd3SGreg Claytondef cmd_c(options, cmd, args): 812525cd59fSSerge Guelton print("continue()") 813205d6189SGreg Clayton return False 814b2273bd3SGreg Clayton 815b9c1b51eSKate Stone 816b2273bd3SGreg Claytondef cmd_s(options, cmd, args): 817525cd59fSSerge Guelton print("step()") 818205d6189SGreg Clayton return False 819b2273bd3SGreg Clayton 820b9c1b51eSKate Stone 821141f208eSGreg Claytondef cmd_qSpeedTest(options, cmd, args): 822525cd59fSSerge Guelton print(("qSpeedTest: cmd='%s', args='%s'" % (cmd, args))) 823141f208eSGreg Clayton 824141f208eSGreg Clayton 825141f208eSGreg Claytondef rsp_qSpeedTest(options, cmd, cmd_args, rsp): 826525cd59fSSerge Guelton print(("qSpeedTest: rsp='%s' cmd='%s', args='%s'" % (rsp, cmd, args))) 827141f208eSGreg Clayton 828141f208eSGreg Clayton 829f51a23fbSGreg Claytondef cmd_vCont(options, cmd, args): 8308ebb9a85SGreg Clayton if args == '?': 831525cd59fSSerge Guelton print("%s: get supported extended continue modes" % (cmd)) 8328ebb9a85SGreg Clayton else: 8338ebb9a85SGreg Clayton got_other_threads = 0 8348ebb9a85SGreg Clayton s = '' 835cb6c9f73SPavel Labath for thread_action in args[1:].split(';'): 836cb6c9f73SPavel Labath (short_action, thread) = thread_action.split(':', 1) 8378ebb9a85SGreg Clayton tid = int(thread, 16) 8388ebb9a85SGreg Clayton if short_action == 'c': 8398ebb9a85SGreg Clayton action = 'continue' 8408ebb9a85SGreg Clayton elif short_action == 's': 8418ebb9a85SGreg Clayton action = 'step' 8428ebb9a85SGreg Clayton elif short_action[0] == 'C': 8438ebb9a85SGreg Clayton action = 'continue with signal 0x%s' % (short_action[1:]) 8448ebb9a85SGreg Clayton elif short_action == 'S': 8458ebb9a85SGreg Clayton action = 'step with signal 0x%s' % (short_action[1:]) 8468ebb9a85SGreg Clayton else: 8478ebb9a85SGreg Clayton action = short_action 8488ebb9a85SGreg Clayton if s: 8498ebb9a85SGreg Clayton s += ', ' 8508ebb9a85SGreg Clayton if tid == -1: 8518ebb9a85SGreg Clayton got_other_threads = 1 8528ebb9a85SGreg Clayton s += 'other-threads:' 8538ebb9a85SGreg Clayton else: 8548ebb9a85SGreg Clayton s += 'thread 0x%4.4x: %s' % (tid, action) 8558ebb9a85SGreg Clayton if got_other_threads: 856525cd59fSSerge Guelton print("extended_continue (%s)" % (s)) 8578ebb9a85SGreg Clayton else: 858525cd59fSSerge Guelton print("extended_continue (%s, other-threads: suspend)" % (s)) 859205d6189SGreg Clayton return False 8608ebb9a85SGreg Clayton 861b9c1b51eSKate Stone 862f51a23fbSGreg Claytondef rsp_vCont(options, cmd, cmd_args, rsp): 8638ebb9a85SGreg Clayton if cmd_args == '?': 8648ebb9a85SGreg Clayton # Skip the leading 'vCont;' 8658ebb9a85SGreg Clayton rsp = rsp[6:] 866cb6c9f73SPavel Labath modes = rsp.split(';') 8678ebb9a85SGreg Clayton s = "%s: supported extended continue modes include: " % (cmd) 8688ebb9a85SGreg Clayton 8698ebb9a85SGreg Clayton for i, mode in enumerate(modes): 8708ebb9a85SGreg Clayton if i: 8718ebb9a85SGreg Clayton s += ', ' 8728ebb9a85SGreg Clayton if mode == 'c': 8738ebb9a85SGreg Clayton s += 'continue' 8748ebb9a85SGreg Clayton elif mode == 'C': 8758ebb9a85SGreg Clayton s += 'continue with signal' 8768ebb9a85SGreg Clayton elif mode == 's': 8778ebb9a85SGreg Clayton s += 'step' 8788ebb9a85SGreg Clayton elif mode == 'S': 8798ebb9a85SGreg Clayton s += 'step with signal' 880141f208eSGreg Clayton elif mode == 't': 881141f208eSGreg Clayton s += 'stop' 882141f208eSGreg Clayton # else: 883141f208eSGreg Clayton # s += 'unrecognized vCont mode: ', str(mode) 884525cd59fSSerge Guelton print(s) 8858ebb9a85SGreg Clayton elif rsp: 8868ebb9a85SGreg Clayton if rsp[0] == 'T' or rsp[0] == 'S' or rsp[0] == 'W' or rsp[0] == 'X': 887f51a23fbSGreg Clayton rsp_stop_reply(options, cmd, cmd_args, rsp) 8888ebb9a85SGreg Clayton return 8898ebb9a85SGreg Clayton if rsp[0] == 'O': 890525cd59fSSerge Guelton print("stdout: %s" % (rsp)) 8918ebb9a85SGreg Clayton return 8928ebb9a85SGreg Clayton else: 893525cd59fSSerge Guelton print("not supported (cmd = '%s', args = '%s', rsp = '%s')" % (cmd, cmd_args, rsp)) 8948ebb9a85SGreg Clayton 895b9c1b51eSKate Stone 896f51a23fbSGreg Claytondef cmd_vAttach(options, cmd, args): 897*cd89f94aSDominic Chen (extra_command, args) = args.split(';') 8988ebb9a85SGreg Clayton if extra_command: 899525cd59fSSerge Guelton print("%s%s(%s)" % (cmd, extra_command, args)) 9008ebb9a85SGreg Clayton else: 901525cd59fSSerge Guelton print("attach(pid = %u)" % int(args, 16)) 902205d6189SGreg Clayton return False 903205d6189SGreg Clayton 9048ebb9a85SGreg Clayton 905f51a23fbSGreg Claytondef cmd_qRegisterInfo(options, cmd, args): 906525cd59fSSerge Guelton print('query_register_info(reg_num=%i)' % (int(args, 16))) 907205d6189SGreg Clayton return False 9088ebb9a85SGreg Clayton 909b9c1b51eSKate Stone 910f51a23fbSGreg Claytondef rsp_qRegisterInfo(options, cmd, cmd_args, rsp): 9118ebb9a85SGreg Clayton global g_max_register_info_name_len 912525cd59fSSerge Guelton print('query_register_info(reg_num=%i):' % (int(cmd_args, 16)), end=' ') 9138ebb9a85SGreg Clayton if len(rsp) == 3 and rsp[0] == 'E': 9148ebb9a85SGreg Clayton g_max_register_info_name_len = 0 9158ebb9a85SGreg Clayton for reg_info in g_register_infos: 9168ebb9a85SGreg Clayton name_len = len(reg_info.name()) 9178ebb9a85SGreg Clayton if g_max_register_info_name_len < name_len: 9188ebb9a85SGreg Clayton g_max_register_info_name_len = name_len 919525cd59fSSerge Guelton print(' DONE') 9208ebb9a85SGreg Clayton else: 9218ebb9a85SGreg Clayton packet = Packet(rsp) 9228ebb9a85SGreg Clayton reg_info = RegisterInfo(packet.get_key_value_pairs()) 9238ebb9a85SGreg Clayton g_register_infos.append(reg_info) 924525cd59fSSerge Guelton print(reg_info) 925205d6189SGreg Clayton return False 9268ebb9a85SGreg Clayton 927b9c1b51eSKate Stone 928f51a23fbSGreg Claytondef cmd_qThreadInfo(options, cmd, args): 9298ebb9a85SGreg Clayton if cmd == 'qfThreadInfo': 9308ebb9a85SGreg Clayton query_type = 'first' 9318ebb9a85SGreg Clayton else: 9328ebb9a85SGreg Clayton query_type = 'subsequent' 933525cd59fSSerge Guelton print('get_current_thread_list(type=%s)' % (query_type)) 934205d6189SGreg Clayton return False 9358ebb9a85SGreg Clayton 936b9c1b51eSKate Stone 937f51a23fbSGreg Claytondef rsp_qThreadInfo(options, cmd, cmd_args, rsp): 9388ebb9a85SGreg Clayton packet = Packet(rsp) 9398ebb9a85SGreg Clayton response_type = packet.get_char() 9408ebb9a85SGreg Clayton if response_type == 'm': 9418ebb9a85SGreg Clayton tids = packet.split_hex(';', 'big') 9428ebb9a85SGreg Clayton for i, tid in enumerate(tids): 9438ebb9a85SGreg Clayton if i: 944525cd59fSSerge Guelton print(',', end=' ') 945525cd59fSSerge Guelton print('0x%x' % (tid), end=' ') 946525cd59fSSerge Guelton print() 9478ebb9a85SGreg Clayton elif response_type == 'l': 948525cd59fSSerge Guelton print('END') 9498ebb9a85SGreg Clayton 950b9c1b51eSKate Stone 951f51a23fbSGreg Claytondef rsp_hex_big_endian(options, cmd, cmd_args, rsp): 952db1550abSGreg Clayton if rsp == '': 953525cd59fSSerge Guelton print("%s%s is not supported" % (cmd, cmd_args)) 954db1550abSGreg Clayton else: 9558ebb9a85SGreg Clayton packet = Packet(rsp) 9568ebb9a85SGreg Clayton uval = packet.get_hex_uint('big') 957525cd59fSSerge Guelton print('%s: 0x%x' % (cmd, uval)) 9588ebb9a85SGreg Clayton 959b9c1b51eSKate Stone 960205d6189SGreg Claytondef cmd_read_mem_bin(options, cmd, args): 961205d6189SGreg Clayton # x0x7fff5fc39200,0x200 962205d6189SGreg Clayton packet = Packet(args) 963db1550abSGreg Clayton addr = packet.get_hex_uint('big') 964205d6189SGreg Clayton comma = packet.get_char() 965db1550abSGreg Clayton size = packet.get_hex_uint('big') 966525cd59fSSerge Guelton print('binary_read_memory (addr = 0x%16.16x, size = %u)' % (addr, size)) 967205d6189SGreg Clayton return False 968205d6189SGreg Clayton 969b9c1b51eSKate Stone 970205d6189SGreg Claytondef rsp_mem_bin_bytes(options, cmd, cmd_args, rsp): 971205d6189SGreg Clayton packet = Packet(cmd_args) 972db1550abSGreg Clayton addr = packet.get_hex_uint('big') 973205d6189SGreg Clayton comma = packet.get_char() 974db1550abSGreg Clayton size = packet.get_hex_uint('big') 975525cd59fSSerge Guelton print('memory:') 976205d6189SGreg Clayton if size > 0: 977205d6189SGreg Clayton dump_hex_memory_buffer(addr, rsp) 978205d6189SGreg Clayton 979b9c1b51eSKate Stone 980f51a23fbSGreg Claytondef cmd_read_memory(options, cmd, args): 9818ebb9a85SGreg Clayton packet = Packet(args) 9828ebb9a85SGreg Clayton addr = packet.get_hex_uint('big') 9838ebb9a85SGreg Clayton comma = packet.get_char() 9848ebb9a85SGreg Clayton size = packet.get_hex_uint('big') 985525cd59fSSerge Guelton print('read_memory (addr = 0x%16.16x, size = %u)' % (addr, size)) 986205d6189SGreg Clayton return False 9878ebb9a85SGreg Clayton 988b9c1b51eSKate Stone 9898ebb9a85SGreg Claytondef dump_hex_memory_buffer(addr, hex_byte_str): 9908ebb9a85SGreg Clayton packet = Packet(hex_byte_str) 9918ebb9a85SGreg Clayton idx = 0 9928ebb9a85SGreg Clayton ascii = '' 9938ebb9a85SGreg Clayton uval = packet.get_hex_uint8() 994b9c1b51eSKate Stone while uval is not None: 9958ebb9a85SGreg Clayton if ((idx % 16) == 0): 9968ebb9a85SGreg Clayton if ascii: 997525cd59fSSerge Guelton print(' ', ascii) 9988ebb9a85SGreg Clayton ascii = '' 999525cd59fSSerge Guelton print('0x%x:' % (addr + idx), end=' ') 1000525cd59fSSerge Guelton print('%2.2x' % (uval), end=' ') 10018ebb9a85SGreg Clayton if 0x20 <= uval and uval < 0x7f: 10028ebb9a85SGreg Clayton ascii += '%c' % uval 10038ebb9a85SGreg Clayton else: 10048ebb9a85SGreg Clayton ascii += '.' 10058ebb9a85SGreg Clayton uval = packet.get_hex_uint8() 10068ebb9a85SGreg Clayton idx = idx + 1 10078ebb9a85SGreg Clayton if ascii: 1008525cd59fSSerge Guelton print(' ', ascii) 10098ebb9a85SGreg Clayton ascii = '' 10108ebb9a85SGreg Clayton 1011b9c1b51eSKate Stone 1012f51a23fbSGreg Claytondef cmd_write_memory(options, cmd, args): 10138ebb9a85SGreg Clayton packet = Packet(args) 10148ebb9a85SGreg Clayton addr = packet.get_hex_uint('big') 10158ebb9a85SGreg Clayton if packet.get_char() != ',': 1016525cd59fSSerge Guelton print('error: invalid write memory command (missing comma after address)') 10178ebb9a85SGreg Clayton return 10188ebb9a85SGreg Clayton size = packet.get_hex_uint('big') 10198ebb9a85SGreg Clayton if packet.get_char() != ':': 1020525cd59fSSerge Guelton print('error: invalid write memory command (missing colon after size)') 10218ebb9a85SGreg Clayton return 1022525cd59fSSerge Guelton print('write_memory (addr = 0x%16.16x, size = %u, data:' % (addr, size)) 10238ebb9a85SGreg Clayton dump_hex_memory_buffer(addr, packet.str) 1024205d6189SGreg Clayton return False 10258ebb9a85SGreg Clayton 1026b9c1b51eSKate Stone 1027f51a23fbSGreg Claytondef cmd_alloc_memory(options, cmd, args): 10288ebb9a85SGreg Clayton packet = Packet(args) 10298ebb9a85SGreg Clayton byte_size = packet.get_hex_uint('big') 10308ebb9a85SGreg Clayton if packet.get_char() != ',': 1031525cd59fSSerge Guelton print('error: invalid allocate memory command (missing comma after address)') 10328ebb9a85SGreg Clayton return 1033525cd59fSSerge Guelton print('allocate_memory (byte-size = %u (0x%x), permissions = %s)' % (byte_size, byte_size, packet.str)) 1034205d6189SGreg Clayton return False 10358ebb9a85SGreg Clayton 1036b9c1b51eSKate Stone 1037f51a23fbSGreg Claytondef rsp_alloc_memory(options, cmd, cmd_args, rsp): 10388ebb9a85SGreg Clayton packet = Packet(rsp) 10398ebb9a85SGreg Clayton addr = packet.get_hex_uint('big') 1040525cd59fSSerge Guelton print('addr = 0x%x' % addr) 10418ebb9a85SGreg Clayton 1042b9c1b51eSKate Stone 1043f51a23fbSGreg Claytondef cmd_dealloc_memory(options, cmd, args): 10448ebb9a85SGreg Clayton packet = Packet(args) 10458ebb9a85SGreg Clayton addr = packet.get_hex_uint('big') 10468ebb9a85SGreg Clayton if packet.get_char() != ',': 1047525cd59fSSerge Guelton print('error: invalid allocate memory command (missing comma after address)') 1048205d6189SGreg Clayton else: 1049525cd59fSSerge Guelton print('deallocate_memory (addr = 0x%x, permissions = %s)' % (addr, packet.str)) 1050205d6189SGreg Clayton return False 1051b9c1b51eSKate Stone 1052b9c1b51eSKate Stone 1053f51a23fbSGreg Claytondef rsp_memory_bytes(options, cmd, cmd_args, rsp): 10548ebb9a85SGreg Clayton addr = Packet(cmd_args).get_hex_uint('big') 10558ebb9a85SGreg Clayton dump_hex_memory_buffer(addr, rsp) 10568ebb9a85SGreg Clayton 1057b9c1b51eSKate Stone 1058f51a23fbSGreg Claytondef get_register_name_equal_value(options, reg_num, hex_value_str): 10598ebb9a85SGreg Clayton if reg_num < len(g_register_infos): 10608ebb9a85SGreg Clayton reg_info = g_register_infos[reg_num] 1061f51a23fbSGreg Clayton value_str = reg_info.get_value_from_hex_string(hex_value_str) 1062f51a23fbSGreg Clayton s = reg_info.name() + ' = ' 1063f51a23fbSGreg Clayton if options.symbolicator: 1064b9c1b51eSKate Stone symbolicated_addresses = options.symbolicator.symbolicate( 1065b9c1b51eSKate Stone int(value_str, 0)) 1066f51a23fbSGreg Clayton if symbolicated_addresses: 1067f51a23fbSGreg Clayton s += options.colors.magenta() 1068f51a23fbSGreg Clayton s += '%s' % symbolicated_addresses[0] 1069f51a23fbSGreg Clayton s += options.colors.reset() 1070f51a23fbSGreg Clayton return s 1071f51a23fbSGreg Clayton s += value_str 1072f51a23fbSGreg Clayton return s 10738ebb9a85SGreg Clayton else: 10748ebb9a85SGreg Clayton reg_value = Packet(hex_value_str).get_hex_uint(g_byte_order) 10758ebb9a85SGreg Clayton return 'reg(%u) = 0x%x' % (reg_num, reg_value) 10768ebb9a85SGreg Clayton 1077b9c1b51eSKate Stone 1078f51a23fbSGreg Claytondef cmd_read_one_reg(options, cmd, args): 10798ebb9a85SGreg Clayton packet = Packet(args) 10808ebb9a85SGreg Clayton reg_num = packet.get_hex_uint('big') 10818ebb9a85SGreg Clayton tid = get_thread_from_thread_suffix(packet.str) 10828ebb9a85SGreg Clayton name = None 10838ebb9a85SGreg Clayton if reg_num < len(g_register_infos): 10848ebb9a85SGreg Clayton name = g_register_infos[reg_num].name() 10858ebb9a85SGreg Clayton if packet.str: 10868ebb9a85SGreg Clayton packet.get_char() # skip ; 10878ebb9a85SGreg Clayton thread_info = packet.get_key_value_pairs() 10888ebb9a85SGreg Clayton tid = int(thread_info[0][1], 16) 10898ebb9a85SGreg Clayton s = 'read_register (reg_num=%u' % reg_num 10908ebb9a85SGreg Clayton if name: 10918ebb9a85SGreg Clayton s += ' (%s)' % (name) 1092b9c1b51eSKate Stone if tid is not None: 10938ebb9a85SGreg Clayton s += ', tid = 0x%4.4x' % (tid) 10948ebb9a85SGreg Clayton s += ')' 1095525cd59fSSerge Guelton print(s) 1096205d6189SGreg Clayton return False 10978ebb9a85SGreg Clayton 1098b9c1b51eSKate Stone 1099f51a23fbSGreg Claytondef rsp_read_one_reg(options, cmd, cmd_args, rsp): 11008ebb9a85SGreg Clayton packet = Packet(cmd_args) 11018ebb9a85SGreg Clayton reg_num = packet.get_hex_uint('big') 1102525cd59fSSerge Guelton print(get_register_name_equal_value(options, reg_num, rsp)) 11038ebb9a85SGreg Clayton 1104b9c1b51eSKate Stone 1105f51a23fbSGreg Claytondef cmd_write_one_reg(options, cmd, args): 11068ebb9a85SGreg Clayton packet = Packet(args) 11078ebb9a85SGreg Clayton reg_num = packet.get_hex_uint('big') 11088ebb9a85SGreg Clayton if packet.get_char() != '=': 1109525cd59fSSerge Guelton print('error: invalid register write packet') 11108ebb9a85SGreg Clayton else: 11118ebb9a85SGreg Clayton name = None 11128ebb9a85SGreg Clayton hex_value_str = packet.get_hex_chars() 11138ebb9a85SGreg Clayton tid = get_thread_from_thread_suffix(packet.str) 11148ebb9a85SGreg Clayton s = 'write_register (reg_num=%u' % reg_num 11158ebb9a85SGreg Clayton if name: 11168ebb9a85SGreg Clayton s += ' (%s)' % (name) 11178ebb9a85SGreg Clayton s += ', value = ' 1118f51a23fbSGreg Clayton s += get_register_name_equal_value(options, reg_num, hex_value_str) 1119b9c1b51eSKate Stone if tid is not None: 11208ebb9a85SGreg Clayton s += ', tid = 0x%4.4x' % (tid) 11218ebb9a85SGreg Clayton s += ')' 1122525cd59fSSerge Guelton print(s) 1123205d6189SGreg Clayton return False 11248ebb9a85SGreg Clayton 1125b9c1b51eSKate Stone 11268ebb9a85SGreg Claytondef dump_all_regs(packet): 11278ebb9a85SGreg Clayton for reg_info in g_register_infos: 11288ebb9a85SGreg Clayton nibble_size = reg_info.bit_size() / 4 11298ebb9a85SGreg Clayton hex_value_str = packet.get_hex_chars(nibble_size) 1130b9c1b51eSKate Stone if hex_value_str is not None: 11318ebb9a85SGreg Clayton value = reg_info.get_value_from_hex_string(hex_value_str) 1132525cd59fSSerge Guelton print('%*s = %s' % (g_max_register_info_name_len, reg_info.name(), value)) 11338ebb9a85SGreg Clayton else: 11348ebb9a85SGreg Clayton return 11358ebb9a85SGreg Clayton 1136b9c1b51eSKate Stone 11378ebb9a85SGreg Claytondef cmd_read_all_regs(cmd, cmd_args): 11388ebb9a85SGreg Clayton packet = Packet(cmd_args) 11398ebb9a85SGreg Clayton packet.get_char() # toss the 'g' command character 11408ebb9a85SGreg Clayton tid = get_thread_from_thread_suffix(packet.str) 1141b9c1b51eSKate Stone if tid is not None: 1142525cd59fSSerge Guelton print('read_all_register(thread = 0x%4.4x)' % tid) 11438ebb9a85SGreg Clayton else: 1144525cd59fSSerge Guelton print('read_all_register()') 1145205d6189SGreg Clayton return False 11468ebb9a85SGreg Clayton 1147b9c1b51eSKate Stone 1148f51a23fbSGreg Claytondef rsp_read_all_regs(options, cmd, cmd_args, rsp): 11498ebb9a85SGreg Clayton packet = Packet(rsp) 11508ebb9a85SGreg Clayton dump_all_regs(packet) 11518ebb9a85SGreg Clayton 1152b9c1b51eSKate Stone 1153f51a23fbSGreg Claytondef cmd_write_all_regs(options, cmd, args): 11548ebb9a85SGreg Clayton packet = Packet(args) 1155525cd59fSSerge Guelton print('write_all_registers()') 11568ebb9a85SGreg Clayton dump_all_regs(packet) 1157205d6189SGreg Clayton return False 11588ebb9a85SGreg Clayton 11598ebb9a85SGreg Claytong_bp_types = ["software_bp", "hardware_bp", "write_wp", "read_wp", "access_wp"] 11608ebb9a85SGreg Clayton 1161b9c1b51eSKate Stone 1162f51a23fbSGreg Claytondef cmd_bp(options, cmd, args): 11638ebb9a85SGreg Clayton if cmd == 'Z': 11648ebb9a85SGreg Clayton s = 'set_' 11658ebb9a85SGreg Clayton else: 11668ebb9a85SGreg Clayton s = 'clear_' 11678ebb9a85SGreg Clayton packet = Packet(args) 11688ebb9a85SGreg Clayton bp_type = packet.get_hex_uint('big') 11698ebb9a85SGreg Clayton packet.get_char() # Skip , 11708ebb9a85SGreg Clayton bp_addr = packet.get_hex_uint('big') 11718ebb9a85SGreg Clayton packet.get_char() # Skip , 11728ebb9a85SGreg Clayton bp_size = packet.get_hex_uint('big') 11738ebb9a85SGreg Clayton s += g_bp_types[bp_type] 11748ebb9a85SGreg Clayton s += " (addr = 0x%x, size = %u)" % (bp_addr, bp_size) 1175525cd59fSSerge Guelton print(s) 1176205d6189SGreg Clayton return False 11778ebb9a85SGreg Clayton 1178b9c1b51eSKate Stone 1179f51a23fbSGreg Claytondef cmd_mem_rgn_info(options, cmd, args): 11808ebb9a85SGreg Clayton packet = Packet(args) 11818ebb9a85SGreg Clayton packet.get_char() # skip ':' character 11828ebb9a85SGreg Clayton addr = packet.get_hex_uint('big') 1183525cd59fSSerge Guelton print('get_memory_region_info (addr=0x%x)' % (addr)) 1184205d6189SGreg Clayton return False 11858ebb9a85SGreg Clayton 1186b9c1b51eSKate Stone 1187f51a23fbSGreg Claytondef cmd_kill(options, cmd, args): 1188525cd59fSSerge Guelton print('kill_process()') 1189205d6189SGreg Clayton return False 11908ebb9a85SGreg Clayton 1191b9c1b51eSKate Stone 11928c2afa0cSGreg Claytondef cmd_jThreadsInfo(options, cmd, args): 1193525cd59fSSerge Guelton print('jThreadsInfo()') 11948c2afa0cSGreg Clayton return False 11958c2afa0cSGreg Clayton 1196b9c1b51eSKate Stone 11978c2afa0cSGreg Claytondef cmd_jGetLoadedDynamicLibrariesInfos(options, cmd, args): 1198525cd59fSSerge Guelton print('jGetLoadedDynamicLibrariesInfos()') 11998c2afa0cSGreg Clayton return False 12008c2afa0cSGreg Clayton 1201b9c1b51eSKate Stone 12028c2afa0cSGreg Claytondef decode_packet(s, start_index=0): 12038c2afa0cSGreg Clayton # print '\ndecode_packet("%s")' % (s[start_index:]) 12048c2afa0cSGreg Clayton index = s.find('}', start_index) 12058c2afa0cSGreg Clayton have_escapes = index != -1 12068c2afa0cSGreg Clayton if have_escapes: 12078c2afa0cSGreg Clayton normal_s = s[start_index:index] 12088c2afa0cSGreg Clayton else: 12098c2afa0cSGreg Clayton normal_s = s[start_index:] 12108c2afa0cSGreg Clayton # print 'normal_s = "%s"' % (normal_s) 12118c2afa0cSGreg Clayton if have_escapes: 12128c2afa0cSGreg Clayton escape_char = '%c' % (ord(s[index + 1]) ^ 0x20) 12138c2afa0cSGreg Clayton # print 'escape_char for "%s" = %c' % (s[index:index+2], escape_char) 12148c2afa0cSGreg Clayton return normal_s + escape_char + decode_packet(s, index + 2) 12158c2afa0cSGreg Clayton else: 12168c2afa0cSGreg Clayton return normal_s 12178c2afa0cSGreg Clayton 1218b9c1b51eSKate Stone 12198c2afa0cSGreg Claytondef rsp_json(options, cmd, cmd_args, rsp): 1220525cd59fSSerge Guelton print('%s() reply:' % (cmd)) 1221*cd89f94aSDominic Chen if not rsp: 1222*cd89f94aSDominic Chen return 1223*cd89f94aSDominic Chen try: 12248c2afa0cSGreg Clayton json_tree = json.loads(rsp) 1225525cd59fSSerge Guelton print(json.dumps(json_tree, indent=4, separators=(',', ': '))) 1226*cd89f94aSDominic Chen except json.JSONDecodeError: 1227*cd89f94aSDominic Chen return 12288c2afa0cSGreg Clayton 12298c2afa0cSGreg Claytondef rsp_jGetLoadedDynamicLibrariesInfos(options, cmd, cmd_args, rsp): 12308c2afa0cSGreg Clayton if cmd_args: 12318c2afa0cSGreg Clayton rsp_json(options, cmd, cmd_args, rsp) 12328c2afa0cSGreg Clayton else: 12338c2afa0cSGreg Clayton rsp_ok_means_supported(options, cmd, cmd_args, rsp) 12348c2afa0cSGreg Clayton 12358ebb9a85SGreg Claytongdb_remote_commands = { 12368ebb9a85SGreg Clayton '\\?': {'cmd': cmd_stop_reply, 'rsp': rsp_stop_reply, 'name': "stop reply pacpket"}, 1237a7a5e5a6SGreg Clayton 'qThreadStopInfo': {'cmd': cmd_qThreadStopInfo, 'rsp': rsp_stop_reply, 'name': "stop reply pacpket"}, 12388ebb9a85SGreg Clayton 'QStartNoAckMode': {'cmd': cmd_query_packet, 'rsp': rsp_ok_means_supported, 'name': "query if no ack mode is supported"}, 12398ebb9a85SGreg Clayton 'QThreadSuffixSupported': {'cmd': cmd_query_packet, 'rsp': rsp_ok_means_supported, 'name': "query if thread suffix is supported"}, 12408ebb9a85SGreg Clayton 'QListThreadsInStopReply': {'cmd': cmd_query_packet, 'rsp': rsp_ok_means_supported, 'name': "query if threads in stop reply packets are supported"}, 1241db1550abSGreg Clayton 'QSetDetachOnError:': {'cmd': cmd_QSetWithUnsigned, 'rsp': rsp_ok_means_success, 'name': "set if we should detach on error"}, 1242db1550abSGreg Clayton 'QSetDisableASLR:': {'cmd': cmd_QSetWithUnsigned, 'rsp': rsp_ok_means_success, 'name': "set if we should disable ASLR"}, 1243a7a5e5a6SGreg Clayton 'qLaunchSuccess': {'cmd': cmd_query_packet, 'rsp': rsp_ok_means_success, 'name': "check on launch success for the A packet"}, 1244a7a5e5a6SGreg Clayton 'A': {'cmd': cmd_A, 'rsp': rsp_ok_means_success, 'name': "launch process"}, 1245db1550abSGreg Clayton 'QLaunchArch:': {'cmd': cmd_QSetWithString, 'rsp': rsp_ok_means_supported, 'name': "set the arch to launch in case the file contains multiple architectures"}, 1246a7a5e5a6SGreg Clayton 'qVAttachOrWaitSupported': {'cmd': cmd_query_packet, 'rsp': rsp_ok_means_supported, 'name': "set the launch architecture"}, 12478ebb9a85SGreg Clayton 'qHostInfo': {'cmd': cmd_query_packet, 'rsp': rsp_dump_key_value_pairs, 'name': "get host information"}, 1248a7a5e5a6SGreg Clayton 'qC': {'cmd': cmd_qC, 'rsp': rsp_qC, 'name': "return the current thread ID"}, 12498ebb9a85SGreg Clayton 'vCont': {'cmd': cmd_vCont, 'rsp': rsp_vCont, 'name': "extended continue command"}, 1250141f208eSGreg Clayton 'qSpeedTest': {'cmd':cmd_qSpeedTest, 'rsp': rsp_qSpeedTest, 'name': 'speed test packdet'}, 12518ebb9a85SGreg Clayton 'vAttach': {'cmd': cmd_vAttach, 'rsp': rsp_stop_reply, 'name': "attach to process"}, 1252b2273bd3SGreg Clayton 'c': {'cmd': cmd_c, 'rsp': rsp_stop_reply, 'name': "continue"}, 1253b2273bd3SGreg Clayton 's': {'cmd': cmd_s, 'rsp': rsp_stop_reply, 'name': "step"}, 12548ebb9a85SGreg Clayton 'qRegisterInfo': {'cmd': cmd_qRegisterInfo, 'rsp': rsp_qRegisterInfo, 'name': "query register info"}, 12558ebb9a85SGreg Clayton 'qfThreadInfo': {'cmd': cmd_qThreadInfo, 'rsp': rsp_qThreadInfo, 'name': "get current thread list"}, 12568ebb9a85SGreg Clayton 'qsThreadInfo': {'cmd': cmd_qThreadInfo, 'rsp': rsp_qThreadInfo, 'name': "get current thread list"}, 12578ebb9a85SGreg Clayton 'qShlibInfoAddr': {'cmd': cmd_query_packet, 'rsp': rsp_hex_big_endian, 'name': "get shared library info address"}, 12588ebb9a85SGreg Clayton 'qMemoryRegionInfo': {'cmd': cmd_mem_rgn_info, 'rsp': rsp_dump_key_value_pairs, 'name': "get memory region information"}, 125925f82aaeSGreg Clayton 'qProcessInfo': {'cmd': cmd_query_packet, 'rsp': rsp_dump_key_value_pairs, 'name': "get process info"}, 126025f82aaeSGreg Clayton 'qSupported': {'cmd': cmd_query_packet, 'rsp': rsp_ok_means_supported, 'name': "query supported"}, 1261374b6714SGreg Clayton 'qXfer:': {'cmd': cmd_qXfer, 'rsp': rsp_qXfer, 'name': "qXfer"}, 1262205d6189SGreg Clayton 'qSymbol:': {'cmd': cmd_qSymbol, 'rsp': rsp_qSymbol, 'name': "qSymbol"}, 1263db1550abSGreg Clayton 'QSetSTDIN:' : {'cmd' : cmd_QSetWithHexString, 'rsp' : rsp_ok_means_success, 'name': "set STDIN prior to launching with A packet"}, 1264db1550abSGreg Clayton 'QSetSTDOUT:' : {'cmd' : cmd_QSetWithHexString, 'rsp' : rsp_ok_means_success, 'name': "set STDOUT prior to launching with A packet"}, 1265db1550abSGreg Clayton 'QSetSTDERR:' : {'cmd' : cmd_QSetWithHexString, 'rsp' : rsp_ok_means_success, 'name': "set STDERR prior to launching with A packet"}, 1266db1550abSGreg Clayton 'QEnvironment:' : {'cmd' : cmd_QSetWithString, 'rsp' : rsp_ok_means_success, 'name': "set an environment variable prior to launching with A packet"}, 1267db1550abSGreg Clayton 'QEnvironmentHexEncoded:' : {'cmd' : cmd_QSetWithHexString, 'rsp' : rsp_ok_means_success, 'name': "set an environment variable prior to launching with A packet"}, 1268205d6189SGreg Clayton 'x': {'cmd': cmd_read_mem_bin, 'rsp': rsp_mem_bin_bytes, 'name': "read memory binary"}, 1269205d6189SGreg Clayton 'X': {'cmd': cmd_write_memory, 'rsp': rsp_ok_means_success, 'name': "write memory binary"}, 12708ebb9a85SGreg Clayton 'm': {'cmd': cmd_read_memory, 'rsp': rsp_memory_bytes, 'name': "read memory"}, 12718ebb9a85SGreg Clayton 'M': {'cmd': cmd_write_memory, 'rsp': rsp_ok_means_success, 'name': "write memory"}, 12728ebb9a85SGreg Clayton '_M': {'cmd': cmd_alloc_memory, 'rsp': rsp_alloc_memory, 'name': "allocate memory"}, 12738ebb9a85SGreg Clayton '_m': {'cmd': cmd_dealloc_memory, 'rsp': rsp_ok_means_success, 'name': "deallocate memory"}, 12748ebb9a85SGreg Clayton 'p': {'cmd': cmd_read_one_reg, 'rsp': rsp_read_one_reg, 'name': "read single register"}, 12758ebb9a85SGreg Clayton 'P': {'cmd': cmd_write_one_reg, 'rsp': rsp_ok_means_success, 'name': "write single register"}, 12768ebb9a85SGreg Clayton 'g': {'cmd': cmd_read_all_regs, 'rsp': rsp_read_all_regs, 'name': "read all registers"}, 12778ebb9a85SGreg Clayton 'G': {'cmd': cmd_write_all_regs, 'rsp': rsp_ok_means_success, 'name': "write all registers"}, 12788ebb9a85SGreg Clayton 'z': {'cmd': cmd_bp, 'rsp': rsp_ok_means_success, 'name': "clear breakpoint or watchpoint"}, 12798ebb9a85SGreg Clayton 'Z': {'cmd': cmd_bp, 'rsp': rsp_ok_means_success, 'name': "set breakpoint or watchpoint"}, 12808ebb9a85SGreg Clayton 'k': {'cmd': cmd_kill, 'rsp': rsp_stop_reply, 'name': "kill process"}, 12818c2afa0cSGreg Clayton 'jThreadsInfo': {'cmd': cmd_jThreadsInfo, 'rsp': rsp_json, 'name': "JSON get all threads info"}, 12828c2afa0cSGreg Clayton 'jGetLoadedDynamicLibrariesInfos:': {'cmd': cmd_jGetLoadedDynamicLibrariesInfos, 'rsp': rsp_jGetLoadedDynamicLibrariesInfos, 'name': 'JSON get loaded dynamic libraries'}, 12838ebb9a85SGreg Clayton} 128425f82aaeSGreg Clayton 1285b9c1b51eSKate Stone 128625f82aaeSGreg Claytondef calculate_mean_and_standard_deviation(floats): 128725f82aaeSGreg Clayton sum = 0.0 128825f82aaeSGreg Clayton count = len(floats) 1289b2273bd3SGreg Clayton if count == 0: 1290b2273bd3SGreg Clayton return (0.0, 0.0) 129125f82aaeSGreg Clayton for f in floats: 129225f82aaeSGreg Clayton sum += f 129325f82aaeSGreg Clayton mean = sum / count 129425f82aaeSGreg Clayton accum = 0.0 129525f82aaeSGreg Clayton for f in floats: 129625f82aaeSGreg Clayton delta = f - mean 129725f82aaeSGreg Clayton accum += delta * delta 129825f82aaeSGreg Clayton 1299b9c1b51eSKate Stone std_dev = math.sqrt(accum / (count - 1)) 130025f82aaeSGreg Clayton return (mean, std_dev) 130125f82aaeSGreg Clayton 1302b9c1b51eSKate Stone 1303b2273bd3SGreg Claytondef parse_gdb_log_file(path, options): 1304b2273bd3SGreg Clayton f = open(path) 1305205d6189SGreg Clayton parse_gdb_log(f, options) 1306b2273bd3SGreg Clayton f.close() 1307b2273bd3SGreg Clayton 1308b9c1b51eSKate Stone 1309141f208eSGreg Claytondef round_up(n, incr): 1310141f208eSGreg Clayton return float(((int(n) + incr) / incr) * incr) 1311141f208eSGreg Clayton 1312141f208eSGreg Clayton 1313141f208eSGreg Claytondef plot_latencies(sec_times): 1314141f208eSGreg Clayton # import numpy as np 1315141f208eSGreg Clayton import matplotlib.pyplot as plt 1316141f208eSGreg Clayton 1317141f208eSGreg Clayton for (i, name) in enumerate(sec_times.keys()): 1318141f208eSGreg Clayton times = sec_times[name] 1319141f208eSGreg Clayton if len(times) <= 1: 1320141f208eSGreg Clayton continue 1321141f208eSGreg Clayton plt.subplot(2, 1, 1) 1322141f208eSGreg Clayton plt.title('Packet "%s" Times' % (name)) 1323141f208eSGreg Clayton plt.xlabel('Packet') 1324141f208eSGreg Clayton units = 'ms' 1325141f208eSGreg Clayton adj_times = [] 1326141f208eSGreg Clayton max_time = 0.0 1327141f208eSGreg Clayton for time in times: 1328141f208eSGreg Clayton time = time * 1000.0 1329141f208eSGreg Clayton adj_times.append(time) 1330141f208eSGreg Clayton if time > max_time: 1331141f208eSGreg Clayton max_time = time 1332141f208eSGreg Clayton if max_time < 1.0: 1333141f208eSGreg Clayton units = 'us' 1334141f208eSGreg Clayton max_time = 0.0 1335141f208eSGreg Clayton for i in range(len(adj_times)): 1336141f208eSGreg Clayton adj_times[i] *= 1000.0 1337141f208eSGreg Clayton if adj_times[i] > max_time: 1338141f208eSGreg Clayton max_time = adj_times[i] 1339141f208eSGreg Clayton plt.ylabel('Time (%s)' % (units)) 1340141f208eSGreg Clayton max_y = None 1341141f208eSGreg Clayton for i in [5.0, 10.0, 25.0, 50.0]: 1342141f208eSGreg Clayton if max_time < i: 1343141f208eSGreg Clayton max_y = round_up(max_time, i) 1344141f208eSGreg Clayton break 1345141f208eSGreg Clayton if max_y is None: 1346141f208eSGreg Clayton max_y = round_up(max_time, 100.0) 1347141f208eSGreg Clayton plt.ylim(0.0, max_y) 1348141f208eSGreg Clayton plt.plot(adj_times, 'o-') 1349141f208eSGreg Clayton plt.show() 1350141f208eSGreg Clayton 1351141f208eSGreg Clayton 1352b2273bd3SGreg Claytondef parse_gdb_log(file, options): 1353e2841639SGreg Clayton '''Parse a GDB log file that was generated by enabling logging with: 1354e2841639SGreg Clayton (lldb) log enable --threadsafe --timestamp --file <FILE> gdb-remote packets 1355d93c4a33SBruce Mitchener This log file will contain timestamps and this function will then normalize 1356e2841639SGreg Clayton those packets to be relative to the first value timestamp that is found and 1357e2841639SGreg Clayton show delta times between log lines and also keep track of how long it takes 1358e2841639SGreg Clayton for GDB remote commands to make a send/receive round trip. This can be 1359e2841639SGreg Clayton handy when trying to figure out why some operation in the debugger is taking 1360e2841639SGreg Clayton a long time during a preset set of debugger commands.''' 1361e2841639SGreg Clayton 1362e2841639SGreg Clayton tricky_commands = ['qRegisterInfo'] 1363e2841639SGreg Clayton timestamp_regex = re.compile('(\s*)([1-9][0-9]+\.[0-9]+)([^0-9].*)$') 1364e2841639SGreg Clayton packet_name_regex = re.compile('([A-Za-z_]+)[^a-z]') 1365b9c1b51eSKate Stone packet_transmit_name_regex = re.compile( 1366b9c1b51eSKate Stone '(?P<direction>send|read) packet: (?P<packet>.*)') 1367db1550abSGreg Clayton packet_contents_name_regex = re.compile('\$([^#]*)#[0-9a-fA-F]{2}') 13688c2afa0cSGreg Clayton packet_checksum_regex = re.compile('.*#[0-9a-fA-F]{2}$') 1369b9c1b51eSKate Stone packet_names_regex_str = '(' + \ 1370b9c1b51eSKate Stone '|'.join(gdb_remote_commands.keys()) + ')(.*)' 1371b9c1b51eSKate Stone packet_names_regex = re.compile(packet_names_regex_str) 13728ebb9a85SGreg Clayton 1373e2841639SGreg Clayton base_time = 0.0 1374e2841639SGreg Clayton last_time = 0.0 1375141f208eSGreg Clayton min_time = 100000000.0 1376e2841639SGreg Clayton packet_total_times = {} 1377141f208eSGreg Clayton all_packet_times = [] 1378141f208eSGreg Clayton packet_times = {} 1379141f208eSGreg Clayton packet_counts = {} 1380e2841639SGreg Clayton lines = file.read().splitlines() 13818ebb9a85SGreg Clayton last_command = None 13828ebb9a85SGreg Clayton last_command_args = None 13838ebb9a85SGreg Clayton last_command_packet = None 1384205d6189SGreg Clayton hide_next_response = False 13858c2afa0cSGreg Clayton num_lines = len(lines) 13868c2afa0cSGreg Clayton skip_count = 0 13878c2afa0cSGreg Clayton for (line_index, line) in enumerate(lines): 13888c2afa0cSGreg Clayton # See if we need to skip any lines 13898c2afa0cSGreg Clayton if skip_count > 0: 13908c2afa0cSGreg Clayton skip_count -= 1 13918c2afa0cSGreg Clayton continue 13928ebb9a85SGreg Clayton m = packet_transmit_name_regex.search(line) 1393f51a23fbSGreg Clayton is_command = False 139425f82aaeSGreg Clayton direction = None 13958ebb9a85SGreg Clayton if m: 13968ebb9a85SGreg Clayton direction = m.group('direction') 13978ebb9a85SGreg Clayton is_command = direction == 'send' 13988ebb9a85SGreg Clayton packet = m.group('packet') 1399f51a23fbSGreg Clayton sys.stdout.write(options.colors.green()) 1400205d6189SGreg Clayton if not options.quiet and not hide_next_response: 1401525cd59fSSerge Guelton print('# ', line) 1402f51a23fbSGreg Clayton sys.stdout.write(options.colors.reset()) 14038ebb9a85SGreg Clayton 14048ebb9a85SGreg Clayton # print 'direction = "%s", packet = "%s"' % (direction, packet) 14058ebb9a85SGreg Clayton 14068c2afa0cSGreg Clayton if packet[0] == '+': 1407205d6189SGreg Clayton if is_command: 1408525cd59fSSerge Guelton print('-->', end=' ') 1409205d6189SGreg Clayton else: 1410525cd59fSSerge Guelton print('<--', end=' ') 1411b9c1b51eSKate Stone if not options.quiet: 1412525cd59fSSerge Guelton print('ACK') 141325f82aaeSGreg Clayton continue 14148ebb9a85SGreg Clayton elif packet[0] == '-': 14158c2afa0cSGreg Clayton if is_command: 1416525cd59fSSerge Guelton print('-->', end=' ') 14178c2afa0cSGreg Clayton else: 1418525cd59fSSerge Guelton print('<--', end=' ') 1419b9c1b51eSKate Stone if not options.quiet: 1420525cd59fSSerge Guelton print('NACK') 142125f82aaeSGreg Clayton continue 14228ebb9a85SGreg Clayton elif packet[0] == '$': 14238ebb9a85SGreg Clayton m = packet_contents_name_regex.match(packet) 14248c2afa0cSGreg Clayton if not m and packet[0] == '$': 14258c2afa0cSGreg Clayton multiline_packet = packet 14268c2afa0cSGreg Clayton idx = line_index + 1 14278c2afa0cSGreg Clayton while idx < num_lines: 14288c2afa0cSGreg Clayton if not options.quiet and not hide_next_response: 1429525cd59fSSerge Guelton print('# ', lines[idx]) 14308c2afa0cSGreg Clayton multiline_packet += lines[idx] 14318c2afa0cSGreg Clayton m = packet_contents_name_regex.match(multiline_packet) 14328ebb9a85SGreg Clayton if m: 14338c2afa0cSGreg Clayton packet = multiline_packet 14348c2afa0cSGreg Clayton skip_count = idx - line_index 14358c2afa0cSGreg Clayton break 14368c2afa0cSGreg Clayton else: 14378c2afa0cSGreg Clayton idx += 1 14388c2afa0cSGreg Clayton if m: 14398c2afa0cSGreg Clayton if is_command: 1440525cd59fSSerge Guelton print('-->', end=' ') 14418c2afa0cSGreg Clayton else: 1442525cd59fSSerge Guelton print('<--', end=' ') 14438c2afa0cSGreg Clayton contents = decode_packet(m.group(1)) 14448ebb9a85SGreg Clayton if is_command: 1445205d6189SGreg Clayton hide_next_response = False 14468ebb9a85SGreg Clayton m = packet_names_regex.match(contents) 14478ebb9a85SGreg Clayton if m: 14488ebb9a85SGreg Clayton last_command = m.group(1) 1449a7a5e5a6SGreg Clayton if last_command == '?': 1450a7a5e5a6SGreg Clayton last_command = '\\?' 1451f51a23fbSGreg Clayton packet_name = last_command 14528ebb9a85SGreg Clayton last_command_args = m.group(2) 14538ebb9a85SGreg Clayton last_command_packet = contents 1454b9c1b51eSKate Stone hide_next_response = gdb_remote_commands[last_command][ 1455b9c1b51eSKate Stone 'cmd'](options, last_command, last_command_args) 14568ebb9a85SGreg Clayton else: 145725f82aaeSGreg Clayton packet_match = packet_name_regex.match(contents) 1458f51a23fbSGreg Clayton if packet_match: 1459f51a23fbSGreg Clayton packet_name = packet_match.group(1) 1460f51a23fbSGreg Clayton for tricky_cmd in tricky_commands: 1461f51a23fbSGreg Clayton if packet_name.find(tricky_cmd) == 0: 1462f51a23fbSGreg Clayton packet_name = tricky_cmd 1463f51a23fbSGreg Clayton else: 1464f51a23fbSGreg Clayton packet_name = contents 14658ebb9a85SGreg Clayton last_command = None 14668ebb9a85SGreg Clayton last_command_args = None 14678ebb9a85SGreg Clayton last_command_packet = None 14688ebb9a85SGreg Clayton elif last_command: 1469b9c1b51eSKate Stone gdb_remote_commands[last_command]['rsp']( 1470b9c1b51eSKate Stone options, last_command, last_command_args, contents) 14718ebb9a85SGreg Clayton else: 1472525cd59fSSerge Guelton print('error: invalid packet: "', packet, '"') 14738ebb9a85SGreg Clayton else: 1474525cd59fSSerge Guelton print('???') 14758ebb9a85SGreg Clayton else: 1476525cd59fSSerge Guelton print('## ', line) 1477e2841639SGreg Clayton match = timestamp_regex.match(line) 1478e2841639SGreg Clayton if match: 1479e2841639SGreg Clayton curr_time = float(match.group(2)) 148025f82aaeSGreg Clayton if last_time and not is_command: 148125f82aaeSGreg Clayton delta = curr_time - last_time 1482141f208eSGreg Clayton all_packet_times.append(delta) 1483e2841639SGreg Clayton delta = 0.0 1484e2841639SGreg Clayton if base_time: 1485e2841639SGreg Clayton delta = curr_time - last_time 1486e2841639SGreg Clayton else: 1487e2841639SGreg Clayton base_time = curr_time 1488f51a23fbSGreg Clayton 1489141f208eSGreg Clayton if not is_command: 1490141f208eSGreg Clayton if line.find('read packet: $') >= 0 and packet_name: 1491e2841639SGreg Clayton if packet_name in packet_total_times: 1492e2841639SGreg Clayton packet_total_times[packet_name] += delta 1493141f208eSGreg Clayton packet_counts[packet_name] += 1 1494e2841639SGreg Clayton else: 1495e2841639SGreg Clayton packet_total_times[packet_name] = delta 1496141f208eSGreg Clayton packet_counts[packet_name] = 1 1497141f208eSGreg Clayton if packet_name not in packet_times: 1498141f208eSGreg Clayton packet_times[packet_name] = [] 1499141f208eSGreg Clayton packet_times[packet_name].append(delta) 1500e2841639SGreg Clayton packet_name = None 1501141f208eSGreg Clayton if min_time > delta: 1502141f208eSGreg Clayton min_time = delta 1503e2841639SGreg Clayton 1504e2841639SGreg Clayton if not options or not options.quiet: 1505525cd59fSSerge Guelton print('%s%.6f %+.6f%s' % (match.group(1), 1506141f208eSGreg Clayton curr_time - base_time, 1507141f208eSGreg Clayton delta, 1508525cd59fSSerge Guelton match.group(3))) 1509e2841639SGreg Clayton last_time = curr_time 15108ebb9a85SGreg Clayton # else: 15118ebb9a85SGreg Clayton # print line 1512141f208eSGreg Clayton (average, std_dev) = calculate_mean_and_standard_deviation(all_packet_times) 1513205d6189SGreg Clayton if average and std_dev: 1514525cd59fSSerge Guelton print('%u packets with average packet time of %f and standard deviation of %f' % (len(all_packet_times), average, std_dev)) 1515e2841639SGreg Clayton if packet_total_times: 1516e2841639SGreg Clayton total_packet_time = 0.0 1517d95752f2SJim Ingham total_packet_count = 0 1518e2841639SGreg Clayton for key, vvv in packet_total_times.items(): 1519e2841639SGreg Clayton # print ' key = (%s) "%s"' % (type(key), key) 1520e2841639SGreg Clayton # print 'value = (%s) %s' % (type(vvv), vvv) 1521e2841639SGreg Clayton # if type(vvv) == 'float': 1522e2841639SGreg Clayton total_packet_time += vvv 1523141f208eSGreg Clayton for key, vvv in packet_counts.items(): 1524d95752f2SJim Ingham total_packet_count += vvv 1525d95752f2SJim Ingham 1526525cd59fSSerge Guelton print('#------------------------------------------------------------') 1527525cd59fSSerge Guelton print('# Packet timing summary:') 1528525cd59fSSerge Guelton print('# Totals: time = %6f, count = %6d' % (total_packet_time, 1529525cd59fSSerge Guelton total_packet_count)) 1530525cd59fSSerge Guelton print('# Min packet time: time = %6f' % (min_time)) 1531525cd59fSSerge Guelton print('#------------------------------------------------------------') 1532525cd59fSSerge Guelton print('# Packet Time (sec) Percent Count Latency') 1533525cd59fSSerge Guelton print('#------------------------- ----------- ------- ------ -------') 1534d95752f2SJim Ingham if options and options.sort_count: 1535b9c1b51eSKate Stone res = sorted( 1536141f208eSGreg Clayton packet_counts, 1537141f208eSGreg Clayton key=packet_counts.__getitem__, 1538b9c1b51eSKate Stone reverse=True) 1539d95752f2SJim Ingham else: 1540b9c1b51eSKate Stone res = sorted( 1541b9c1b51eSKate Stone packet_total_times, 1542b9c1b51eSKate Stone key=packet_total_times.__getitem__, 1543b9c1b51eSKate Stone reverse=True) 1544d95752f2SJim Ingham 1545e2841639SGreg Clayton if last_time > 0.0: 1546e2841639SGreg Clayton for item in res: 1547e2841639SGreg Clayton packet_total_time = packet_total_times[item] 1548b9c1b51eSKate Stone packet_percent = ( 1549b9c1b51eSKate Stone packet_total_time / total_packet_time) * 100.0 1550141f208eSGreg Clayton packet_count = packet_counts[item] 1551525cd59fSSerge Guelton print(" %24s %11.6f %5.2f%% %6d %9.6f" % ( 1552141f208eSGreg Clayton item, packet_total_time, packet_percent, packet_count, 1553525cd59fSSerge Guelton float(packet_total_time) / float(packet_count))) 1554*cd89f94aSDominic Chen if options and options.plot: 1555141f208eSGreg Clayton plot_latencies(packet_times) 1556e2841639SGreg Clayton 1557e2841639SGreg Claytonif __name__ == '__main__': 15588ebb9a85SGreg Clayton usage = "usage: gdbremote [options]" 15598ebb9a85SGreg Clayton description = '''The command disassembles a GDB remote packet log.''' 1560b9c1b51eSKate Stone parser = optparse.OptionParser( 1561b9c1b51eSKate Stone description=description, 1562b9c1b51eSKate Stone prog='gdbremote', 1563b9c1b51eSKate Stone usage=usage) 1564b9c1b51eSKate Stone parser.add_option( 1565b9c1b51eSKate Stone '-v', 1566b9c1b51eSKate Stone '--verbose', 1567b9c1b51eSKate Stone action='store_true', 1568b9c1b51eSKate Stone dest='verbose', 1569b9c1b51eSKate Stone help='display verbose debug info', 1570b9c1b51eSKate Stone default=False) 1571b9c1b51eSKate Stone parser.add_option( 1572b9c1b51eSKate Stone '-q', 1573b9c1b51eSKate Stone '--quiet', 1574b9c1b51eSKate Stone action='store_true', 1575b9c1b51eSKate Stone dest='quiet', 1576b9c1b51eSKate Stone help='display verbose debug info', 1577b9c1b51eSKate Stone default=False) 1578b9c1b51eSKate Stone parser.add_option( 1579b9c1b51eSKate Stone '-C', 1580b9c1b51eSKate Stone '--color', 1581b9c1b51eSKate Stone action='store_true', 1582b9c1b51eSKate Stone dest='color', 1583b9c1b51eSKate Stone help='add terminal colors', 1584b9c1b51eSKate Stone default=False) 1585b9c1b51eSKate Stone parser.add_option( 1586b9c1b51eSKate Stone '-c', 1587b9c1b51eSKate Stone '--sort-by-count', 1588b9c1b51eSKate Stone action='store_true', 1589b9c1b51eSKate Stone dest='sort_count', 1590b9c1b51eSKate Stone help='display verbose debug info', 1591b9c1b51eSKate Stone default=False) 1592b9c1b51eSKate Stone parser.add_option( 1593b9c1b51eSKate Stone '--crashlog', 1594b9c1b51eSKate Stone type='string', 1595b9c1b51eSKate Stone dest='crashlog', 1596b9c1b51eSKate Stone help='symbolicate using a darwin crash log file', 1597b9c1b51eSKate Stone default=False) 15988ebb9a85SGreg Clayton try: 15998ebb9a85SGreg Clayton (options, args) = parser.parse_args(sys.argv[1:]) 16008ebb9a85SGreg Clayton except: 1601525cd59fSSerge Guelton print('error: argument error') 16028ebb9a85SGreg Clayton sys.exit(1) 16038ebb9a85SGreg Clayton 1604f51a23fbSGreg Clayton options.colors = TerminalColors(options.color) 1605f51a23fbSGreg Clayton options.symbolicator = None 1606f51a23fbSGreg Clayton if options.crashlog: 1607f51a23fbSGreg Clayton import lldb 1608f51a23fbSGreg Clayton lldb.debugger = lldb.SBDebugger.Create() 1609f51a23fbSGreg Clayton import lldb.macosx.crashlog 1610f51a23fbSGreg Clayton options.symbolicator = lldb.macosx.crashlog.CrashLog(options.crashlog) 1611525cd59fSSerge Guelton print('%s' % (options.symbolicator)) 16128ebb9a85SGreg Clayton 1613e2841639SGreg Clayton # This script is being run from the command line, create a debugger in case we are 1614e2841639SGreg Clayton # going to use any debugger functions in our function. 1615b2273bd3SGreg Clayton if len(args): 16168ebb9a85SGreg Clayton for file in args: 1617525cd59fSSerge Guelton print('#----------------------------------------------------------------------') 1618525cd59fSSerge Guelton print("# GDB remote log file: '%s'" % file) 1619525cd59fSSerge Guelton print('#----------------------------------------------------------------------') 16208ebb9a85SGreg Clayton parse_gdb_log_file(file, options) 1621f51a23fbSGreg Clayton if options.symbolicator: 1622525cd59fSSerge Guelton print('%s' % (options.symbolicator)) 1623b2273bd3SGreg Clayton else: 1624b2273bd3SGreg Clayton parse_gdb_log(sys.stdin, options) 1625f51a23fbSGreg Clayton 16261441ffe6SDave Leedef __lldb_init_module(debugger, internal_dict): 1627e2841639SGreg Clayton # This initializer is being run from LLDB in the embedded command interpreter 1628e2841639SGreg Clayton # Add any commands contained in this module to LLDB 16291441ffe6SDave Lee debugger.HandleCommand( 1630b9c1b51eSKate Stone 'command script add -f gdbremote.start_gdb_log start_gdb_log') 16311441ffe6SDave Lee debugger.HandleCommand( 1632b9c1b51eSKate Stone 'command script add -f gdbremote.stop_gdb_log stop_gdb_log') 1633525cd59fSSerge Guelton 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') 1634