[Lldb-commits] [lldb] r149030 - in /lldb/trunk/examples/python: cmdtemplate.py gdbremote.py
Greg Clayton
gclayton at apple.com
Wed Jan 25 18:56:25 PST 2012
Author: gclayton
Date: Wed Jan 25 20:56:24 2012
New Revision: 149030
URL: http://llvm.org/viewvc/llvm-project?rev=149030&view=rev
Log:
Added a 'gdbremote' python module that adds two commands: start_gdb_log and end_gdb_log.
When this is imported into your lldb using the "command script import /path/to/gdbremote.py"
these new commands are available within LLDB. 'start_gdb_log' will enable logging with
timestamps for GDB remote packets, and 'stop_gdb_log' will then dump the details and
also a lot of packet timing data. This allows us to accurately track what packets are
taking up the most time when debugging (when using the ProcessGDBRemote debugging plug-in).
Also udpated the comments at the top of the cmdtemplate.py to show how to correctly import
the module from within LLDB.
Added:
lldb/trunk/examples/python/gdbremote.py (with props)
Modified:
lldb/trunk/examples/python/cmdtemplate.py
Modified: lldb/trunk/examples/python/cmdtemplate.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/cmdtemplate.py?rev=149030&r1=149029&r2=149030&view=diff
==============================================================================
--- lldb/trunk/examples/python/cmdtemplate.py (original)
+++ lldb/trunk/examples/python/cmdtemplate.py Wed Jan 25 20:56:24 2012
@@ -3,10 +3,10 @@
#----------------------------------------------------------------------
# Be sure to add the python path that points to the LLDB shared library.
#
-# To use this in the embedded python interpreter using "lldb":
-# % cd /path/containing/cmdtemplate.py
-# % lldb
-# (lldb) script import cmdtemplate
+# # To use this in the embedded python interpreter using "lldb" just
+# import it with the full path using the "command script import"
+# command
+# (lldb) command script import /path/to/cmdtemplate.py
#
# For the shells csh, tcsh:
# ( setenv PYTHONPATH /path/to/LLDB.framework/Resources/Python ; ./cmdtemplate.py )
Added: lldb/trunk/examples/python/gdbremote.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/gdbremote.py?rev=149030&view=auto
==============================================================================
--- lldb/trunk/examples/python/gdbremote.py (added)
+++ lldb/trunk/examples/python/gdbremote.py Wed Jan 25 20:56:24 2012
@@ -0,0 +1,184 @@
+#!/usr/bin/python
+
+#----------------------------------------------------------------------
+# This module will enable GDB remote packet logging when the
+# 'start_gdb_log' command is called with a filename to log to. When the
+# 'stop_gdb_log' command is called, it will disable the logging and
+# print out statistics about how long commands took to execute and also
+# will primnt ou
+# Be sure to add the python path that points to the LLDB shared library.
+#
+# To use this in the embedded python interpreter using "lldb" just
+# import it with the full path using the "command script import"
+# command. This can be done from the LLDB command line:
+# (lldb) command script import /path/to/gdbremote.py
+# Or it can be added to your ~/.lldbinit file so this module is always
+# available.
+#----------------------------------------------------------------------
+
+import commands
+import optparse
+import os
+import shlex
+import re
+import tempfile
+
+log_file = ''
+
+def start_gdb_log(debugger, command, result, dict):
+ '''Start logging GDB remote packets by enabling logging with timestamps and
+ thread safe logging. Follow a call to this function with a call to "stop_gdb_log"
+ in order to dump out the commands.'''
+ global log_file
+ command_args = shlex.split(command)
+ usage = "usage: start_gdb_log [options] [<LOGFILEPATH>]"
+ description='''The command enables GDB remote packet logging with timestamps. The packets will be logged to <LOGFILEPATH> if supplied, or a temporary file will be used. Logging stops when stop_gdb_log is called and the packet times will
+ be aggregated and displayed.'''
+ parser = optparse.OptionParser(description=description, prog='start_gdb_log',usage=usage)
+ parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
+ try:
+ (options, args) = parser.parse_args(command_args)
+ except:
+ return
+
+ if log_file:
+ result.PutCString ('error: logging is already in progress with file "%s"', log_file)
+ else:
+ args_len = len(args)
+ if args_len == 0:
+ log_file = tempfile.mktemp()
+ elif len(args) == 1:
+ log_file = args[0]
+
+ if log_file:
+ debugger.HandleCommand('log enable --threadsafe --timestamp --file "%s" gdb-remote packets' % log_file);
+ 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)
+ return
+
+ result.PutCString ('error: invalid log file path')
+ result.PutCString (usage)
+
+def stop_gdb_log(debugger, command, result, dict):
+ '''Stop logging GDB remote packets to the file that was specified in a call
+ to "start_gdb_log" and normalize the timestamps to be relative to the first
+ timestamp in the log file. Also print out statistics for how long each
+ command took to allow performance bottlenecks to be determined.'''
+ global log_file
+ # Any commands whose names might be followed by more valid C identifier
+ # characters must be listed here
+ command_args = shlex.split(command)
+ usage = "usage: stop_gdb_log [options]"
+ description='''The command stops a previously enabled GDB remote packet logging command. Packet logging must have been previously enabled with a call to start_gdb_log.'''
+ parser = optparse.OptionParser(description=description, prog='stop_gdb_log',usage=usage)
+ parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
+ parser.add_option('-q', '--quiet', action='store_true', dest='quiet', help='display verbose debug info', default=False)
+ try:
+ (options, args) = parser.parse_args(command_args)
+ except:
+ return
+
+ if not log_file:
+ result.PutCString ('error: logging must have been previously enabled with a call to "stop_gdb_log"')
+ elif os.path.exists (log_file):
+ if len(args) == 0:
+ debugger.HandleCommand('log disable gdb-remote packets');
+ result.PutCString ("GDB packet logging disabled. Logged packets are in '%s'" % log_file)
+ parse_gdb_log_file (log_file, options)
+ log_file = None
+ else:
+ result.PutCString (usage)
+ else:
+ print 'error: the GDB packet log file "%s" does not exist' % log_file
+
+def parse_gdb_log_file(file, options):
+ '''Parse a GDB log file that was generated by enabling logging with:
+ (lldb) log enable --threadsafe --timestamp --file <FILE> gdb-remote packets
+ This log file will contain timestamps and this fucntion will then normalize
+ those packets to be relative to the first value timestamp that is found and
+ show delta times between log lines and also keep track of how long it takes
+ for GDB remote commands to make a send/receive round trip. This can be
+ handy when trying to figure out why some operation in the debugger is taking
+ a long time during a preset set of debugger commands.'''
+
+ tricky_commands = [ 'qRegisterInfo' ]
+ timestamp_regex = re.compile('(\s*)([1-9][0-9]+\.[0-9]+)([^0-9].*)$')
+ packet_name_regex = re.compile('([A-Za-z_]+)[^a-z]')
+ base_time = 0.0
+ last_time = 0.0
+ packet_send_time = 0.0
+ packet_name = None
+ packet_total_times = {}
+ file = open(file)
+ lines = file.read().splitlines()
+ for line in lines:
+ match = timestamp_regex.match (line)
+ if match:
+ curr_time = float (match.group(2))
+ delta = 0.0
+ if base_time:
+ delta = curr_time - last_time
+ else:
+ base_time = curr_time
+ idx = line.find('send packet: $')
+ if idx >= 0:
+ packet_send_time = curr_time
+ packet_match = packet_name_regex.match (line[idx+14:])
+ if packet_match:
+ packet_name = packet_match.group(1)
+ for tricky_cmd in tricky_commands:
+ if packet_name.find (tricky_cmd) == 0:
+ packet_name = tricky_cmd
+ elif line.find('read packet: $') >= 0 and packet_name:
+ if packet_name in packet_total_times:
+ packet_total_times[packet_name] += delta
+ else:
+ packet_total_times[packet_name] = delta
+ packet_name = None
+
+ if not options or not options.quiet:
+ print '%s%.6f %+.6f%s' % (match.group(1), curr_time - base_time, delta, match.group(3))
+ last_time = curr_time
+ else:
+ print line
+ if packet_total_times:
+ total_packet_time = 0.0
+ for key, vvv in packet_total_times.items():
+ # print ' key = (%s) "%s"' % (type(key), key)
+ # print 'value = (%s) %s' % (type(vvv), vvv)
+ # if type(vvv) == 'float':
+ total_packet_time += vvv
+ print '#--------------------------------------------'
+ print '# Packet timing summary:'
+ print '#--------------------------------------------'
+ print '# Packet Time (sec) Percent'
+ print '#------------------------- ---------- -------'
+ res = sorted(packet_total_times, key=packet_total_times.__getitem__, reverse=True)
+ if last_time > 0.0:
+ for item in res:
+ packet_total_time = packet_total_times[item]
+ packet_percent = (packet_total_time / total_packet_time)*100.0
+ if packet_percent >= 10.0:
+ print " %24s %.6f %.2f%%" % (item, packet_total_time, packet_percent)
+ else:
+ print " %24s %.6f %.2f%%" % (item, packet_total_time, packet_percent)
+
+
+
+if __name__ == '__main__':
+ import sys
+ # This script is being run from the command line, create a debugger in case we are
+ # going to use any debugger functions in our function.
+ for file in sys.argv:
+ print '#----------------------------------------------------------------------'
+ print "# GDB remote log file: '%s'" % file
+ print '#----------------------------------------------------------------------'
+ parse_gdb_log_file (file, None)
+
+else:
+ import lldb
+ if lldb.debugger:
+ # This initializer is being run from LLDB in the embedded command interpreter
+ # Add any commands contained in this module to LLDB
+ lldb.debugger.HandleCommand('command script add -f gdbremote.start_gdb_log start_gdb_log')
+ lldb.debugger.HandleCommand('command script add -f gdbremote.stop_gdb_log stop_gdb_log')
+ print 'The "start_gdb_log" and "stop_gdb_log" commands are now installed and ready for use, type "start_gdb_log --help" or "stop_gdb_log --help" for more information'
Propchange: lldb/trunk/examples/python/gdbremote.py
------------------------------------------------------------------------------
svn:executable = *
More information about the lldb-commits
mailing list