Index: utils/clangdiag.py =================================================================== --- /dev/null +++ utils/clangdiag.py @@ -0,0 +1,131 @@ +#!/usr/bin/python + +#---------------------------------------------------------------------- +# 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 +# (lldb) command script import /path/to/clandiag.py +#---------------------------------------------------------------------- + +import lldb +import argparse +import commands +import shlex +import os +import subprocess + +class MyParser(argparse.ArgumentParser): + def format_help(self): + return ''' Commands for operating on clang diagnostic breakpoints + +Syntax: clangdiag enable + clangdiag disable + clangdiag diagtool + +The following subcommands are supported: + + enable -- Enable clang diagnostic breakpoints. + disable -- Disable all clang diagnostic breakpoints. + diagtool -- Set diagtool path if not in target directory. +''' + +def create_diag_options(): + parser = MyParser(prog='clangdiag') + subparsers = parser.add_subparsers( + title='subcommands', + dest='subcommands', + metavar='') + disable_parser = subparsers.add_parser('disable') + enable_parser = subparsers.add_parser('enable') + diagtool_parser = subparsers.add_parser('diagtool') + diagtool_parser.add_argument('path', nargs=1) + return parser + +def getDiagtool(target, diagtool = None): + if 'diagtool' not in getDiagtool.__dict__: + getDiagtool.diagtool = None + if diagtool: + getDiagtool.diagtool = diagtool + elif getDiagtool.diagtool is None: + exe = target.GetExecutable() + if not exe.Exists(): + print('clangdiag: Target (%s) not set.' % exe.GetFilename()) + return + diagtool = os.path.join(exe.GetDirectory(), 'diagtool') + if os.path.exists(diagtool): + getDiagtool.diagtool = diagtool + else: + print('clangdiag: diagtool not found along side %s' % exe) + return + + return getDiagtool.diagtool + +def setDiagBreakpoint(frame, bp_loc, dict): + id = frame.FindVariable("DiagID").GetValue() + if id is None: + print('clangdiag: id is None') + return False + + # Don't need to test this time, since we did that in enable. + target = frame.GetThread().GetProcess().GetTarget() + diagtool = getDiagtool(target) + name = subprocess.check_output([diagtool, "find-diagnostic-id", id]).rstrip(); + bp = target.BreakpointCreateBySourceRegex(name, lldb.SBFileSpec()) + bp.AddName("clang::Diagnostic") + + return False + +def enable(exe_ctx, args): + # Always disable existing breakpoints + disable(exe_ctx) + + target = exe_ctx.GetTarget() + # Just make sure we can find diagtool since it gets used in callbacks. + diagtool = getDiagtool(target) + bp = target.BreakpointCreateByName('DiagnosticsEngine::Report') + bp.SetScriptCallbackFunction('clangdiag.setDiagBreakpoint') + bp.AddName("clang::Diagnostic") + + return + +def disable(exe_ctx): + target = exe_ctx.GetTarget() + # Remove all diag breakpoints. + bkpts = lldb.SBBreakpointList(target) + target.FindBreakpointsByName("clang::Diagnostic", bkpts) + for i in range(bkpts.GetSize()): + target.BreakpointDelete(bkpts.GetBreakpointAtIndex(i).GetID()) + + return + +def the_diag_command(debugger, command, exe_ctx, result, dict): + # Use the Shell Lexer to properly parse up command options just like a + # shell would + command_args = shlex.split(command) + parser = create_diag_options() + try: + args = parser.parse_args(command_args) + except: + return + + if args.subcommands == 'enable': + enable(exe_ctx, args) + elif args.subcommands == 'disable': + disable(exe_ctx) + else: + getDiagtool(exe_ctx.GetTarget(), args.path[0]) + + return + +def __lldb_init_module(debugger, dict): + # This initializer is being run from LLDB in the embedded command interpreter + # Make the options so we can generate the help text for the new LLDB + # command line command prior to registering it with LLDB below + parser = create_diag_options() + the_diag_command.__doc__ = parser.format_help() + # Add any commands contained in this module to LLDB + debugger.HandleCommand( + 'command script add -f clangdiag.the_diag_command clangdiag') + print 'The "clangdiag" command has been installed, type "help clangdiag" or "clangdiag --help" for detailed help.'