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