1be691f3bSpatrick#!/usr/bin/env python 2061da546Spatrick 3061da546Spatrick#---------------------------------------------------------------------- 4061da546Spatrick# This module will enable GDB remote packet logging when the 5061da546Spatrick# 'start_gdb_log' command is called with a filename to log to. When the 6061da546Spatrick# 'stop_gdb_log' command is called, it will disable the logging and 7061da546Spatrick# print out statistics about how long commands took to execute and also 8061da546Spatrick# will primnt ou 9061da546Spatrick# Be sure to add the python path that points to the LLDB shared library. 10061da546Spatrick# 11061da546Spatrick# To use this in the embedded python interpreter using "lldb" just 12061da546Spatrick# import it with the full path using the "command script import" 13061da546Spatrick# command. This can be done from the LLDB command line: 14061da546Spatrick# (lldb) command script import /path/to/gdbremote.py 15061da546Spatrick# Or it can be added to your ~/.lldbinit file so this module is always 16061da546Spatrick# available. 17061da546Spatrick#---------------------------------------------------------------------- 18061da546Spatrick 19061da546Spatrickimport optparse 20061da546Spatrickimport os 21061da546Spatrickimport shlex 22061da546Spatrickimport re 23061da546Spatrickimport tempfile 24061da546Spatrick 25061da546Spatrick 26061da546Spatrickdef start_gdb_log(debugger, command, result, dict): 27061da546Spatrick '''Start logging GDB remote packets by enabling logging with timestamps and 28061da546Spatrick thread safe logging. Follow a call to this function with a call to "stop_gdb_log" 29061da546Spatrick in order to dump out the commands.''' 30061da546Spatrick global log_file 31061da546Spatrick if log_file: 32061da546Spatrick result.PutCString( 33061da546Spatrick 'error: logging is already in progress with file "%s"', 34061da546Spatrick log_file) 35061da546Spatrick else: 36061da546Spatrick args_len = len(args) 37061da546Spatrick if args_len == 0: 38061da546Spatrick log_file = tempfile.mktemp() 39061da546Spatrick elif len(args) == 1: 40061da546Spatrick log_file = args[0] 41061da546Spatrick 42061da546Spatrick if log_file: 43061da546Spatrick debugger.HandleCommand( 44061da546Spatrick 'log enable --threadsafe --timestamp --file "%s" gdb-remote packets' % 45061da546Spatrick log_file) 46061da546Spatrick result.PutCString( 47061da546Spatrick "GDB packet logging enable with log file '%s'\nUse the 'stop_gdb_log' command to stop logging and show packet statistics." % 48061da546Spatrick log_file) 49061da546Spatrick return 50061da546Spatrick 51061da546Spatrick result.PutCString('error: invalid log file path') 52061da546Spatrick result.PutCString(usage) 53061da546Spatrick 54061da546Spatrick 55061da546Spatrickdef parse_time_log(debugger, command, result, dict): 56061da546Spatrick # Any commands whose names might be followed by more valid C identifier 57061da546Spatrick # characters must be listed here 58061da546Spatrick command_args = shlex.split(command) 59061da546Spatrick parse_time_log_args(command_args) 60061da546Spatrick 61061da546Spatrick 62061da546Spatrickdef parse_time_log_args(command_args): 63061da546Spatrick usage = "usage: parse_time_log [options] [<LOGFILEPATH>]" 64061da546Spatrick description = '''Parse a log file that contains timestamps and convert the timestamps to delta times between log lines.''' 65061da546Spatrick parser = optparse.OptionParser( 66061da546Spatrick description=description, 67061da546Spatrick prog='parse_time_log', 68061da546Spatrick usage=usage) 69061da546Spatrick parser.add_option( 70061da546Spatrick '-v', 71061da546Spatrick '--verbose', 72061da546Spatrick action='store_true', 73061da546Spatrick dest='verbose', 74061da546Spatrick help='display verbose debug info', 75061da546Spatrick default=False) 76061da546Spatrick try: 77061da546Spatrick (options, args) = parser.parse_args(command_args) 78061da546Spatrick except: 79061da546Spatrick return 80061da546Spatrick for log_file in args: 81061da546Spatrick parse_log_file(log_file, options) 82061da546Spatrick 83061da546Spatrick 84061da546Spatrickdef parse_log_file(file, options): 85061da546Spatrick '''Parse a log file that was contains timestamps. These logs are typically 86061da546Spatrick generated using: 87061da546Spatrick (lldb) log enable --threadsafe --timestamp --file <FILE> .... 88061da546Spatrick 89061da546Spatrick This log file will contain timestamps and this function will then normalize 90061da546Spatrick those packets to be relative to the first value timestamp that is found and 91061da546Spatrick show delta times between log lines and also keep track of how long it takes 92061da546Spatrick for GDB remote commands to make a send/receive round trip. This can be 93061da546Spatrick handy when trying to figure out why some operation in the debugger is taking 94061da546Spatrick a long time during a preset set of debugger commands.''' 95061da546Spatrick 96061da546Spatrick print('#----------------------------------------------------------------------') 97061da546Spatrick print("# Log file: '%s'" % file) 98061da546Spatrick print('#----------------------------------------------------------------------') 99061da546Spatrick 100061da546Spatrick timestamp_regex = re.compile('(\s*)([1-9][0-9]+\.[0-9]+)([^0-9].*)$') 101061da546Spatrick 102061da546Spatrick base_time = 0.0 103061da546Spatrick last_time = 0.0 104061da546Spatrick file = open(file) 105061da546Spatrick lines = file.read().splitlines() 106061da546Spatrick for line in lines: 107061da546Spatrick match = timestamp_regex.match(line) 108061da546Spatrick if match: 109061da546Spatrick curr_time = float(match.group(2)) 110061da546Spatrick delta = 0.0 111061da546Spatrick if base_time: 112061da546Spatrick delta = curr_time - last_time 113061da546Spatrick else: 114061da546Spatrick base_time = curr_time 115061da546Spatrick 116061da546Spatrick print('%s%.6f %+.6f%s' % (match.group(1), curr_time - base_time, delta, match.group(3))) 117061da546Spatrick last_time = curr_time 118061da546Spatrick else: 119061da546Spatrick print(line) 120061da546Spatrick 121061da546Spatrick 122061da546Spatrickif __name__ == '__main__': 123061da546Spatrick import sys 124061da546Spatrick parse_time_log_args(sys.argv[1:]) 125061da546Spatrick 126*f6aab3d8Srobert 127*f6aab3d8Srobertdef __lldb_init_module(debugger, internal_dict): 128061da546Spatrick # This initializer is being run from LLDB in the embedded command interpreter 129061da546Spatrick # Add any commands contained in this module to LLDB 130*f6aab3d8Srobert debugger.HandleCommand( 131*f6aab3d8Srobert 'command script add -o -f delta.parse_time_log parse_time_log') 132061da546Spatrick print('The "parse_time_log" command is now installed and ready for use, type "parse_time_log --help" for more information') 133