blob: 7d4fdd64fd1bb7491b0c2973cbc0b66a938b1b83 [file] [log] [blame]
Adrian Prantl888e0232013-09-06 18:10:44 +00001#!/bin/env python
2"""
3A gdb-compatible frontend for lldb that implements just enough
4commands to run the tests in the debuginfo-tests repository with lldb.
5"""
6
7# ----------------------------------------------------------------------
8# Auto-detect lldb python module.
9import commands, platform, os, sys
10try:
11 # Just try for LLDB in case PYTHONPATH is already correctly setup.
12 import lldb
13except ImportError:
14 lldb_python_dirs = list()
15 # lldb is not in the PYTHONPATH, try some defaults for the current platform.
16 platform_system = platform.system()
17 if platform_system == 'Darwin':
18 # On Darwin, try the currently selected Xcode directory
19 xcode_dir = commands.getoutput("xcode-select --print-path")
20 if xcode_dir:
21 lldb_python_dirs.append(os.path.realpath(xcode_dir +
22'/../SharedFrameworks/LLDB.framework/Resources/Python'))
23 lldb_python_dirs.append(xcode_dir +
24'/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
25 lldb_python_dirs.append(
26'/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
27 success = False
28 for lldb_python_dir in lldb_python_dirs:
29 if os.path.exists(lldb_python_dir):
30 if not (sys.path.__contains__(lldb_python_dir)):
31 sys.path.append(lldb_python_dir)
32 try:
33 import lldb
34 except ImportError:
35 pass
36 else:
37 print 'imported lldb from: "%s"' % (lldb_python_dir)
38 success = True
39 break
40 if not success:
41 print "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly"
42 sys.exit(1)
43# ----------------------------------------------------------------------
44
45# Command line option handling.
46import argparse
47parser = argparse.ArgumentParser(description=__doc__)
48parser.add_argument('--quiet', '-q', action="store_true", help='ignored')
49parser.add_argument('-batch', action="store_true",
50 help='exit after processing comand line')
51parser.add_argument('-n', action="store_true", help='ignore .lldb file')
52parser.add_argument('-x', dest='script', type=file, help='execute commands from file')
53parser.add_argument("target", help="the program to debug")
54args = parser.parse_args()
55
56
57# Create a new debugger instance.
58debugger = lldb.SBDebugger.Create()
59debugger.SkipLLDBInitFiles(args.n)
60
61# Don't return from lldb function calls until the process stops.
62debugger.SetAsync(False)
63
64# Create a target from a file and arch.
Adrian Prantlee30f632013-09-07 20:04:29 +000065arch = os.popen("file "+args.target).read().split()[-1]
Adrian Prantl002c2a82013-09-07 17:14:37 +000066target = debugger.CreateTargetWithFileAndArch(args.target, arch)
Adrian Prantl888e0232013-09-06 18:10:44 +000067
68if not target:
69 print "Could not create target", args.target
70 sys.exit(1)
71
72if not args.script:
73 print "Interactive mode is not implemented."
74 sys.exit(1)
75
76import re
77for command in args.script:
78 # Strip newline and whitespaces and split into words.
79 cmd = command[:-1].strip().split()
80 if not cmd:
81 continue
82
Adrian Prantl5ef1c862013-09-06 22:33:52 +000083 print '> %s'% command[:-1]
Adrian Prantl888e0232013-09-06 18:10:44 +000084
85 try:
86 if re.match('^r|(run)$', cmd[0]):
87 error = lldb.SBError()
88 launchinfo = lldb.SBLaunchInfo([])
89 launchinfo.SetWorkingDirectory(os.getcwd())
90 process = target.Launch(launchinfo, error)
Adrian Prantl5ef1c862013-09-06 22:33:52 +000091 print error
Adrian Prantl888e0232013-09-06 18:10:44 +000092 if not process or error.fail:
Adrian Prantl888e0232013-09-06 18:10:44 +000093 state = process.GetState()
94 print "State = %d" % state
Adrian Prantl5ef1c862013-09-06 22:33:52 +000095 print """
96ERROR: Could not launch process.
Adrian Prantl17a00112014-10-13 18:04:10 +000097NOTE: There are several reasons why this may happen:
Adrian Prantl5ef1c862013-09-06 22:33:52 +000098 * Root needs to run "DevToolsSecurity --enable".
Adrian Prantl17a00112014-10-13 18:04:10 +000099 * Older versions of lldb cannot launch more than one process simultaneously.
Adrian Prantl5ef1c862013-09-06 22:33:52 +0000100"""
Adrian Prantl888e0232013-09-06 18:10:44 +0000101 sys.exit(1)
102
103 elif re.match('^b|(break)$', cmd[0]) and len(cmd) == 2:
104 if re.match('[0-9]+', cmd[1]):
105 # b line
106 mainfile = target.FindFunctions('main')[0].compile_unit.file
107 print target.BreakpointCreateByLocation(mainfile, int(cmd[1]))
108 else:
109 # b file:line
Adrian Prantl5ef1c862013-09-06 22:33:52 +0000110 file, line = cmd[1].split(':')
Adrian Prantl888e0232013-09-06 18:10:44 +0000111 print target.BreakpointCreateByLocation(file, int(line))
112
113 elif re.match('^ptype$', cmd[0]) and len(cmd) == 2:
114 # GDB's ptype has multiple incarnations depending on its
115 # argument (global variable, function, type). The definition
116 # here is for looking up the signature of a function and only
117 # if that fails it looks for a type with that name.
118 # Type lookup in LLDB would be "image lookup --type".
119 for elem in target.FindFunctions(cmd[1]):
120 print elem.function.type
121 continue
122 print target.FindFirstType(cmd[1])
123
124 elif re.match('^po$', cmd[0]) and len(cmd) > 1:
Adrian Prantl75c47792014-02-21 00:17:02 +0000125 try:
126 opts = lldb.SBExpressionOptions()
127 opts.SetFetchDynamicValue(True)
128 opts.SetCoerceResultToId(True)
129 print target.EvaluateExpression(' '.join(cmd[1:]), opts)
130 except:
131 # FIXME: This is a fallback path for the lab.llvm.org
132 # buildbot running OS X 10.7; it should be removed.
133 thread = process.GetThreadAtIndex(0)
134 frame = thread.GetFrameAtIndex(0)
135 print frame.EvaluateExpression(' '.join(cmd[1:]))
Adrian Prantl888e0232013-09-06 18:10:44 +0000136
137 elif re.match('^p|(print)$', cmd[0]) and len(cmd) > 1:
Adrian Prantl5ef1c862013-09-06 22:33:52 +0000138 thread = process.GetThreadAtIndex(0)
139 frame = thread.GetFrameAtIndex(0)
140 print frame.EvaluateExpression(' '.join(cmd[1:]))
Adrian Prantl888e0232013-09-06 18:10:44 +0000141
Adrian Prantlc26059f2017-04-17 17:57:01 +0000142 elif re.match('^n|(next)$', cmd[0]):
143 thread = process.GetThreadAtIndex(0)
144 thread.StepOver()
145
Adrian Prantl888e0232013-09-06 18:10:44 +0000146 elif re.match('^q|(quit)$', cmd[0]):
147 sys.exit(0)
148
149 else:
150 print debugger.HandleCommand(' '.join(cmd))
151
Adrian Prantl971ad592014-10-13 16:34:31 +0000152 except SystemExit:
153 lldb.SBDebugger_Terminate()
154 raise
Adrian Prantl888e0232013-09-06 18:10:44 +0000155 except:
156 print 'Could not handle the command "%s"' % ' '.join(cmd)
157