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