3 A gdb-compatible frontend for lldb that implements just enough
4 commands to run the tests in the debuginfo-tests repository with lldb.
7 # ----------------------------------------------------------------------
8 # Auto-detect lldb python module.
9 import subprocess
, platform
, os
, sys
11 # Just try for LLDB in case PYTHONPATH is already correctly setup.
14 # Ask the command line driver for the path to the lldb module. Copy over
15 # the environment so that SDKROOT is propagated to xcrun.
16 command
= ['xcrun', 'lldb', '-P'] if platform
.system() == 'Darwin' else ['lldb', '-P']
17 # Extend the PYTHONPATH if the path exists and isn't already there.
18 lldb_python_path
= subprocess
.check_output(command
).decode("utf-8").strip()
19 if os
.path
.exists(lldb_python_path
) and not sys
.path
.__contains
__(lldb_python_path
):
20 sys
.path
.append(lldb_python_path
)
21 # Try importing LLDB again.
24 print('imported lldb from: "%s"'%lldb_python_path
)
26 print("error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly")
28 # ----------------------------------------------------------------------
30 # Command line option handling.
32 parser
= argparse
.ArgumentParser(description
=__doc__
)
33 parser
.add_argument('--quiet', '-q', action
="store_true", help='ignored')
34 parser
.add_argument('-batch', action
="store_true",
35 help='exit after processing comand line')
36 parser
.add_argument('-n', action
="store_true", help='ignore .lldb file')
37 parser
.add_argument('-x', dest
='script', type=argparse
.FileType('r'),
38 help='execute commands from file')
39 parser
.add_argument("target", help="the program to debug")
40 args
= parser
.parse_args()
43 # Create a new debugger instance.
44 debugger
= lldb
.SBDebugger
.Create()
45 debugger
.SkipLLDBInitFiles(args
.n
)
47 # Make sure to clean up the debugger on exit.
51 atexit
.register(on_exit
)
53 # Don't return from lldb function calls until the process stops.
54 debugger
.SetAsync(False)
56 # Create a target from a file and arch.
57 arch
= os
.popen("file "+args
.target
).read().split()[-1]
58 target
= debugger
.CreateTargetWithFileAndArch(args
.target
, arch
)
61 print("Could not create target %s"% args
.target
)
65 print("Interactive mode is not implemented.")
69 for command
in args
.script
:
70 # Strip newline and whitespaces and split into words.
71 cmd
= command
[:-1].strip().split()
75 print('> %s'% command
[:-1])
78 if re
.match('^r|(run)$', cmd
[0]):
79 error
= lldb
.SBError()
80 launchinfo
= lldb
.SBLaunchInfo([])
81 launchinfo
.SetWorkingDirectory(os
.getcwd())
82 process
= target
.Launch(launchinfo
, error
)
84 if not process
or error
.fail
:
85 state
= process
.GetState()
86 print("State = %d" % state
)
88 ERROR: Could not launch process.
89 NOTE: There are several reasons why this may happen:
90 * Root needs to run "DevToolsSecurity --enable".
91 * Older versions of lldb cannot launch more than one process simultaneously.
95 elif re
.match('^b|(break)$', cmd
[0]) and len(cmd
) == 2:
96 if re
.match('[0-9]+', cmd
[1]):
98 mainfile
= target
.FindFunctions('main')[0].compile_unit
.file
99 print(target
.BreakpointCreateByLocation(mainfile
, int(cmd
[1])))
102 file, line
= cmd
[1].split(':')
103 print(target
.BreakpointCreateByLocation(file, int(line
)))
105 elif re
.match('^ptype$', cmd
[0]) and len(cmd
) == 2:
106 # GDB's ptype has multiple incarnations depending on its
107 # argument (global variable, function, type). The definition
108 # here is for looking up the signature of a function and only
109 # if that fails it looks for a type with that name.
110 # Type lookup in LLDB would be "image lookup --type".
111 for elem
in target
.FindFunctions(cmd
[1]):
112 print(elem
.function
.type)
114 print(target
.FindFirstType(cmd
[1]))
116 elif re
.match('^po$', cmd
[0]) and len(cmd
) > 1:
118 opts
= lldb
.SBExpressionOptions()
119 opts
.SetFetchDynamicValue(True)
120 opts
.SetCoerceResultToId(True)
121 print(target
.EvaluateExpression(' '.join(cmd
[1:]), opts
))
123 # FIXME: This is a fallback path for the lab.llvm.org
124 # buildbot running OS X 10.7; it should be removed.
125 thread
= process
.GetThreadAtIndex(0)
126 frame
= thread
.GetFrameAtIndex(0)
127 print(frame
.EvaluateExpression(' '.join(cmd
[1:])))
129 elif re
.match('^p|(print)$', cmd
[0]) and len(cmd
) > 1:
130 thread
= process
.GetThreadAtIndex(0)
131 frame
= thread
.GetFrameAtIndex(0)
132 print(frame
.EvaluateExpression(' '.join(cmd
[1:])))
134 elif re
.match('^n|(next)$', cmd
[0]):
135 thread
= process
.GetThreadAtIndex(0)
138 elif re
.match('^q|(quit)$', cmd
[0]):
142 print(debugger
.HandleCommand(' '.join(cmd
)))
147 print('Could not handle the command "%s"' % ' '.join(cmd
))