142 lines · python
1#!/usr/bin/env python2 3# ----------------------------------------------------------------------4# This module will enable GDB remote packet logging when the5# 'start_gdb_log' command is called with a filename to log to. When the6# 'stop_gdb_log' command is called, it will disable the logging and7# print out statistics about how long commands took to execute and also8# will primnt ou9# 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" just12# 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.py15# Or it can be added to your ~/.lldbinit file so this module is always16# available.17# ----------------------------------------------------------------------18 19import optparse20import os21import shlex22import re23import tempfile24 25 26def start_gdb_log(debugger, command, result, dict):27 """Start logging GDB remote packets by enabling logging with timestamps and28 thread safe logging. Follow a call to this function with a call to "stop_gdb_log"29 in order to dump out the commands."""30 global log_file31 if log_file:32 result.PutCString(33 'error: logging is already in progress with file "%s"', log_file34 )35 else:36 args_len = len(args)37 if args_len == 0:38 log_file = tempfile.mktemp()39 elif len(args) == 1:40 log_file = args[0]41 42 if log_file:43 debugger.HandleCommand(44 'log enable --threadsafe --timestamp --file "%s" gdb-remote packets'45 % log_file46 )47 result.PutCString(48 "GDB packet logging enable with log file '%s'\nUse the 'stop_gdb_log' command to stop logging and show packet statistics."49 % log_file50 )51 return52 53 result.PutCString("error: invalid log file path")54 result.PutCString(usage)55 56 57def parse_time_log(debugger, command, result, dict):58 # Any commands whose names might be followed by more valid C identifier59 # characters must be listed here60 command_args = shlex.split(command)61 parse_time_log_args(command_args)62 63 64def parse_time_log_args(command_args):65 usage = "usage: parse_time_log [options] [<LOGFILEPATH>]"66 description = """Parse a log file that contains timestamps and convert the timestamps to delta times between log lines."""67 parser = optparse.OptionParser(68 description=description, prog="parse_time_log", usage=usage69 )70 parser.add_option(71 "-v",72 "--verbose",73 action="store_true",74 dest="verbose",75 help="display verbose debug info",76 default=False,77 )78 try:79 (options, args) = parser.parse_args(command_args)80 except:81 return82 for log_file in args:83 parse_log_file(log_file, options)84 85 86def parse_log_file(file, options):87 """Parse a log file that was contains timestamps. These logs are typically88 generated using:89 (lldb) log enable --threadsafe --timestamp --file <FILE> ....90 91 This log file will contain timestamps and this function will then normalize92 those packets to be relative to the first value timestamp that is found and93 show delta times between log lines and also keep track of how long it takes94 for GDB remote commands to make a send/receive round trip. This can be95 handy when trying to figure out why some operation in the debugger is taking96 a long time during a preset set of debugger commands."""97 98 print("#----------------------------------------------------------------------")99 print("# Log file: '%s'" % file)100 print("#----------------------------------------------------------------------")101 102 timestamp_regex = re.compile(r"(\s*)([1-9][0-9]+\.[0-9]+)([^0-9].*)$")103 104 base_time = 0.0105 last_time = 0.0106 file = open(file)107 lines = file.read().splitlines()108 for line in lines:109 match = timestamp_regex.match(line)110 if match:111 curr_time = float(match.group(2))112 delta = 0.0113 if base_time:114 delta = curr_time - last_time115 else:116 base_time = curr_time117 118 print(119 "%s%.6f %+.6f%s"120 % (match.group(1), curr_time - base_time, delta, match.group(3))121 )122 last_time = curr_time123 else:124 print(line)125 126 127if __name__ == "__main__":128 import sys129 130 parse_time_log_args(sys.argv[1:])131 132 133def __lldb_init_module(debugger, internal_dict):134 # This initializer is being run from LLDB in the embedded command interpreter135 # Add any commands contained in this module to LLDB136 debugger.HandleCommand(137 "command script add -o -f delta.parse_time_log parse_time_log"138 )139 print(140 'The "parse_time_log" command is now installed and ready for use, type "parse_time_log --help" for more information'141 )142