1#!/usr/bin/python 2 3#---------------------------------------------------------------------- 4# This module will enable GDB remote packet logging when the 5# 'start_gdb_log' command is called with a filename to log to. When the 6# 'stop_gdb_log' command is called, it will disable the logging and 7# print out statistics about how long commands took to execute and also 8# will primnt ou 9# Be sure to add the python path that points to the LLDB shared library. 10# 11# To use this in the embedded python interpreter using "lldb" just 12# import it with the full path using the "command script import" 13# command. This can be done from the LLDB command line: 14# (lldb) command script import /path/to/gdbremote.py 15# Or it can be added to your ~/.lldbinit file so this module is always 16# available. 17#---------------------------------------------------------------------- 18 19import commands 20from __future__ import print_function 21 22import optparse 23import os 24import shlex 25import re 26import tempfile 27 28 29def start_gdb_log(debugger, command, result, dict): 30 '''Start logging GDB remote packets by enabling logging with timestamps and 31 thread safe logging. Follow a call to this function with a call to "stop_gdb_log" 32 in order to dump out the commands.''' 33 global log_file 34 if log_file: 35 result.PutCString( 36 'error: logging is already in progress with file "%s"', 37 log_file) 38 else: 39 args_len = len(args) 40 if args_len == 0: 41 log_file = tempfile.mktemp() 42 elif len(args) == 1: 43 log_file = args[0] 44 45 if log_file: 46 debugger.HandleCommand( 47 'log enable --threadsafe --timestamp --file "%s" gdb-remote packets' % 48 log_file) 49 result.PutCString( 50 "GDB packet logging enable with log file '%s'\nUse the 'stop_gdb_log' command to stop logging and show packet statistics." % 51 log_file) 52 return 53 54 result.PutCString('error: invalid log file path') 55 result.PutCString(usage) 56 57 58def parse_time_log(debugger, command, result, dict): 59 # Any commands whose names might be followed by more valid C identifier 60 # characters must be listed here 61 command_args = shlex.split(command) 62 parse_time_log_args(command_args) 63 64 65def parse_time_log_args(command_args): 66 usage = "usage: parse_time_log [options] [<LOGFILEPATH>]" 67 description = '''Parse a log file that contains timestamps and convert the timestamps to delta times between log lines.''' 68 parser = optparse.OptionParser( 69 description=description, 70 prog='parse_time_log', 71 usage=usage) 72 parser.add_option( 73 '-v', 74 '--verbose', 75 action='store_true', 76 dest='verbose', 77 help='display verbose debug info', 78 default=False) 79 try: 80 (options, args) = parser.parse_args(command_args) 81 except: 82 return 83 for log_file in args: 84 parse_log_file(log_file, options) 85 86 87def parse_log_file(file, options): 88 '''Parse a log file that was contains timestamps. These logs are typically 89 generated using: 90 (lldb) log enable --threadsafe --timestamp --file <FILE> .... 91 92 This log file will contain timestamps and this function will then normalize 93 those packets to be relative to the first value timestamp that is found and 94 show delta times between log lines and also keep track of how long it takes 95 for GDB remote commands to make a send/receive round trip. This can be 96 handy when trying to figure out why some operation in the debugger is taking 97 a long time during a preset set of debugger commands.''' 98 99 print('#----------------------------------------------------------------------') 100 print("# Log file: '%s'" % file) 101 print('#----------------------------------------------------------------------') 102 103 timestamp_regex = re.compile('(\s*)([1-9][0-9]+\.[0-9]+)([^0-9].*)$') 104 105 base_time = 0.0 106 last_time = 0.0 107 file = open(file) 108 lines = file.read().splitlines() 109 for line in lines: 110 match = timestamp_regex.match(line) 111 if match: 112 curr_time = float(match.group(2)) 113 delta = 0.0 114 if base_time: 115 delta = curr_time - last_time 116 else: 117 base_time = curr_time 118 119 print('%s%.6f %+.6f%s' % (match.group(1), curr_time - base_time, delta, match.group(3))) 120 last_time = curr_time 121 else: 122 print(line) 123 124 125if __name__ == '__main__': 126 import sys 127 parse_time_log_args(sys.argv[1:]) 128 129else: 130 import lldb 131 if lldb.debugger: 132 # This initializer is being run from LLDB in the embedded command interpreter 133 # Add any commands contained in this module to LLDB 134 lldb.debugger.HandleCommand( 135 'command script add -f delta.parse_time_log parse_time_log') 136 print('The "parse_time_log" command is now installed and ready for use, type "parse_time_log --help" for more information') 137