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