xref: /openbsd-src/gnu/llvm/lldb/examples/python/delta.py (revision 46035553bfdd96e63c94e32da0210227ec2e3cf1)
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
19from __future__ import print_function
20
21import optparse
22import os
23import shlex
24import re
25import tempfile
26
27
28def start_gdb_log(debugger, command, result, dict):
29    '''Start logging GDB remote packets by enabling logging with timestamps and
30    thread safe logging. Follow a call to this function with a call to "stop_gdb_log"
31    in order to dump out the commands.'''
32    global log_file
33    if log_file:
34        result.PutCString(
35            'error: logging is already in progress with file "%s"',
36            log_file)
37    else:
38        args_len = len(args)
39        if args_len == 0:
40            log_file = tempfile.mktemp()
41        elif len(args) == 1:
42            log_file = args[0]
43
44        if log_file:
45            debugger.HandleCommand(
46                'log enable --threadsafe --timestamp --file "%s" gdb-remote packets' %
47                log_file)
48            result.PutCString(
49                "GDB packet logging enable with log file '%s'\nUse the 'stop_gdb_log' command to stop logging and show packet statistics." %
50                log_file)
51            return
52
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 identifier
59    # characters must be listed here
60    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,
69        prog='parse_time_log',
70        usage=usage)
71    parser.add_option(
72        '-v',
73        '--verbose',
74        action='store_true',
75        dest='verbose',
76        help='display verbose debug info',
77        default=False)
78    try:
79        (options, args) = parser.parse_args(command_args)
80    except:
81        return
82    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 typically
88    generated using:
89    (lldb) log enable --threadsafe --timestamp --file <FILE> ....
90
91    This log file will contain timestamps and this function will then normalize
92    those packets to be relative to the first value timestamp that is found and
93    show delta times between log lines and also keep track of how long it takes
94    for GDB remote commands to make a send/receive round trip. This can be
95    handy when trying to figure out why some operation in the debugger is taking
96    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('(\s*)([1-9][0-9]+\.[0-9]+)([^0-9].*)$')
103
104    base_time = 0.0
105    last_time = 0.0
106    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.0
113            if base_time:
114                delta = curr_time - last_time
115            else:
116                base_time = curr_time
117
118            print('%s%.6f %+.6f%s' % (match.group(1), curr_time - base_time, delta, match.group(3)))
119            last_time = curr_time
120        else:
121            print(line)
122
123
124if __name__ == '__main__':
125    import sys
126    parse_time_log_args(sys.argv[1:])
127
128else:
129    import lldb
130    if lldb.debugger:
131        # This initializer is being run from LLDB in the embedded command interpreter
132        # Add any commands contained in this module to LLDB
133        lldb.debugger.HandleCommand(
134            'command script add -f delta.parse_time_log parse_time_log')
135        print('The "parse_time_log" command is now installed and ready for use, type "parse_time_log --help" for more information')
136