|  | #!/bin/env python | 
|  | """ | 
|  | A gdb-compatible frontend for lldb that implements just enough | 
|  | commands to run the tests in the debuginfo-tests repository with lldb. | 
|  | """ | 
|  |  | 
|  | # ---------------------------------------------------------------------- | 
|  | # Auto-detect lldb python module. | 
|  | import commands, platform, os,  sys | 
|  | try: | 
|  | # Just try for LLDB in case PYTHONPATH is already correctly setup. | 
|  | import lldb | 
|  | except ImportError: | 
|  | lldb_python_dirs = list() | 
|  | # lldb is not in the PYTHONPATH, try some defaults for the current platform. | 
|  | platform_system = platform.system() | 
|  | if platform_system == 'Darwin': | 
|  | # On Darwin, try the currently selected Xcode directory | 
|  | xcode_dir = commands.getoutput("xcode-select --print-path") | 
|  | if xcode_dir: | 
|  | lldb_python_dirs.append(os.path.realpath(xcode_dir + | 
|  | '/../SharedFrameworks/LLDB.framework/Resources/Python')) | 
|  | lldb_python_dirs.append(xcode_dir + | 
|  | '/Library/PrivateFrameworks/LLDB.framework/Resources/Python') | 
|  | lldb_python_dirs.append( | 
|  | '/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python') | 
|  | success = False | 
|  | for lldb_python_dir in lldb_python_dirs: | 
|  | if os.path.exists(lldb_python_dir): | 
|  | if not (sys.path.__contains__(lldb_python_dir)): | 
|  | sys.path.append(lldb_python_dir) | 
|  | try: | 
|  | import lldb | 
|  | except ImportError: | 
|  | pass | 
|  | else: | 
|  | print 'imported lldb from: "%s"' % (lldb_python_dir) | 
|  | success = True | 
|  | break | 
|  | if not success: | 
|  | print "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly" | 
|  | sys.exit(1) | 
|  | # ---------------------------------------------------------------------- | 
|  |  | 
|  | # Command line option handling. | 
|  | import argparse | 
|  | parser = argparse.ArgumentParser(description=__doc__) | 
|  | parser.add_argument('--quiet', '-q', action="store_true", help='ignored') | 
|  | parser.add_argument('-batch', action="store_true", | 
|  | help='exit after processing comand line') | 
|  | parser.add_argument('-n', action="store_true", help='ignore .lldb file') | 
|  | parser.add_argument('-x', dest='script', type=file, help='execute commands from file') | 
|  | parser.add_argument("target", help="the program to debug") | 
|  | args = parser.parse_args() | 
|  |  | 
|  |  | 
|  | # Create a new debugger instance. | 
|  | debugger = lldb.SBDebugger.Create() | 
|  | debugger.SkipLLDBInitFiles(args.n) | 
|  |  | 
|  | # Make sure to clean up the debugger on exit. | 
|  | import atexit | 
|  | def on_exit(): | 
|  | debugger.Terminate() | 
|  | atexit.register(on_exit) | 
|  |  | 
|  | # Don't return from lldb function calls until the process stops. | 
|  | debugger.SetAsync(False) | 
|  |  | 
|  | # Create a target from a file and arch. | 
|  | arch = os.popen("file "+args.target).read().split()[-1] | 
|  | target = debugger.CreateTargetWithFileAndArch(args.target, arch) | 
|  |  | 
|  | if not target: | 
|  | print "Could not create target", args.target | 
|  | sys.exit(1) | 
|  |  | 
|  | if not args.script: | 
|  | print "Interactive mode is not implemented." | 
|  | sys.exit(1) | 
|  |  | 
|  | import re | 
|  | for command in args.script: | 
|  | # Strip newline and whitespaces and split into words. | 
|  | cmd = command[:-1].strip().split() | 
|  | if not cmd: | 
|  | continue | 
|  |  | 
|  | print '> %s'% command[:-1] | 
|  |  | 
|  | try: | 
|  | if re.match('^r|(run)$', cmd[0]): | 
|  | error = lldb.SBError() | 
|  | launchinfo = lldb.SBLaunchInfo([]) | 
|  | launchinfo.SetWorkingDirectory(os.getcwd()) | 
|  | process = target.Launch(launchinfo, error) | 
|  | print error | 
|  | if not process or error.fail: | 
|  | state = process.GetState() | 
|  | print "State = %d" % state | 
|  | print """ | 
|  | ERROR: Could not launch process. | 
|  | NOTE: There are several reasons why this may happen: | 
|  | * Root needs to run "DevToolsSecurity --enable". | 
|  | * Older versions of lldb cannot launch more than one process simultaneously. | 
|  | """ | 
|  | sys.exit(1) | 
|  |  | 
|  | elif re.match('^b|(break)$', cmd[0]) and len(cmd) == 2: | 
|  | if re.match('[0-9]+', cmd[1]): | 
|  | # b line | 
|  | mainfile = target.FindFunctions('main')[0].compile_unit.file | 
|  | print target.BreakpointCreateByLocation(mainfile, int(cmd[1])) | 
|  | else: | 
|  | # b file:line | 
|  | file, line = cmd[1].split(':') | 
|  | print target.BreakpointCreateByLocation(file, int(line)) | 
|  |  | 
|  | elif re.match('^ptype$', cmd[0]) and len(cmd) == 2: | 
|  | # GDB's ptype has multiple incarnations depending on its | 
|  | # argument (global variable, function, type).  The definition | 
|  | # here is for looking up the signature of a function and only | 
|  | # if that fails it looks for a type with that name. | 
|  | # Type lookup in LLDB would be "image lookup --type". | 
|  | for elem in target.FindFunctions(cmd[1]): | 
|  | print elem.function.type | 
|  | continue | 
|  | print target.FindFirstType(cmd[1]) | 
|  |  | 
|  | elif re.match('^po$', cmd[0]) and len(cmd) > 1: | 
|  | try: | 
|  | opts = lldb.SBExpressionOptions() | 
|  | opts.SetFetchDynamicValue(True) | 
|  | opts.SetCoerceResultToId(True) | 
|  | print target.EvaluateExpression(' '.join(cmd[1:]), opts) | 
|  | except: | 
|  | # FIXME: This is a fallback path for the lab.llvm.org | 
|  | # buildbot running OS X 10.7; it should be removed. | 
|  | thread = process.GetThreadAtIndex(0) | 
|  | frame = thread.GetFrameAtIndex(0) | 
|  | print frame.EvaluateExpression(' '.join(cmd[1:])) | 
|  |  | 
|  | elif re.match('^p|(print)$', cmd[0]) and len(cmd) > 1: | 
|  | thread = process.GetThreadAtIndex(0) | 
|  | frame = thread.GetFrameAtIndex(0) | 
|  | print frame.EvaluateExpression(' '.join(cmd[1:])) | 
|  |  | 
|  | elif re.match('^n|(next)$', cmd[0]): | 
|  | thread = process.GetThreadAtIndex(0) | 
|  | thread.StepOver() | 
|  |  | 
|  | elif re.match('^q|(quit)$', cmd[0]): | 
|  | sys.exit(0) | 
|  |  | 
|  | else: | 
|  | print debugger.HandleCommand(' '.join(cmd)) | 
|  |  | 
|  | except SystemExit: | 
|  | raise | 
|  | except: | 
|  | print 'Could not handle the command "%s"' % ' '.join(cmd) | 
|  |  |