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
12 # Just try for LLDB in case PYTHONPATH is already correctly setup.
15 # Ask the command line driver for the path to the lldb module. Copy over
16 # the environment so that SDKROOT is propagated to xcrun.
18 ["xcrun", "lldb", "-P"] if platform
.system() == "Darwin" else ["lldb", "-P"]
20 # Extend the PYTHONPATH if the path exists and isn't already there.
21 lldb_python_path
= subprocess
.check_output(command
).decode("utf-8").strip()
22 if os
.path
.exists(lldb_python_path
) and not sys
.path
.__contains
__(lldb_python_path
):
23 sys
.path
.append(lldb_python_path
)
24 # Try importing LLDB again.
28 print('imported lldb from: "%s"' % lldb_python_path
)
31 "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly"
34 # ----------------------------------------------------------------------
36 # Command line option handling.
39 parser
= argparse
.ArgumentParser(description
=__doc__
)
40 parser
.add_argument("--quiet", "-q", action
="store_true", help="ignored")
42 "-batch", action
="store_true", help="exit after processing comand line"
44 parser
.add_argument("-n", action
="store_true", help="ignore .lldb file")
46 "-x", dest
="script", type=argparse
.FileType("r"), help="execute commands from file"
48 parser
.add_argument("target", help="the program to debug")
49 args
= parser
.parse_args()
52 # Create a new debugger instance.
53 debugger
= lldb
.SBDebugger
.Create()
54 debugger
.SkipLLDBInitFiles(args
.n
)
56 # Make sure to clean up the debugger on exit.
64 atexit
.register(on_exit
)
66 # Don't return from lldb function calls until the process stops.
67 debugger
.SetAsync(False)
69 # Create a target from a file and arch.
70 arch
= os
.popen("file " + args
.target
).read().split()[-1]
71 target
= debugger
.CreateTargetWithFileAndArch(args
.target
, arch
)
74 print("Could not create target %s" % args
.target
)
78 print("Interactive mode is not implemented.")
83 for command
in args
.script
:
84 # Strip newline and whitespaces and split into words.
85 cmd
= command
[:-1].strip().split()
89 print("> %s" % command
[:-1])
92 if re
.match("^r|(run)$", cmd
[0]):
93 error
= lldb
.SBError()
94 launchinfo
= lldb
.SBLaunchInfo([])
95 launchinfo
.SetWorkingDirectory(os
.getcwd())
96 process
= target
.Launch(launchinfo
, error
)
98 if not process
or error
.fail
:
99 state
= process
.GetState()
100 print("State = %d" % state
)
103 ERROR: Could not launch process.
104 NOTE: There are several reasons why this may happen:
105 * Root needs to run "DevToolsSecurity --enable".
106 * Older versions of lldb cannot launch more than one process simultaneously.
111 elif re
.match("^b|(break)$", cmd
[0]) and len(cmd
) == 2:
112 if re
.match("[0-9]+", cmd
[1]):
114 mainfile
= target
.FindFunctions("main")[0].compile_unit
.file
115 print(target
.BreakpointCreateByLocation(mainfile
, int(cmd
[1])))
118 file, line
= cmd
[1].split(":")
119 print(target
.BreakpointCreateByLocation(file, int(line
)))
121 elif re
.match("^ptype$", cmd
[0]) and len(cmd
) == 2:
122 # GDB's ptype has multiple incarnations depending on its
123 # argument (global variable, function, type). The definition
124 # here is for looking up the signature of a function and only
125 # if that fails it looks for a type with that name.
126 # Type lookup in LLDB would be "image lookup --type".
127 for elem
in target
.FindFunctions(cmd
[1]):
128 print(elem
.function
.type)
130 print(target
.FindFirstType(cmd
[1]))
132 elif re
.match("^po$", cmd
[0]) and len(cmd
) > 1:
134 opts
= lldb
.SBExpressionOptions()
135 opts
.SetFetchDynamicValue(True)
136 opts
.SetCoerceResultToId(True)
137 print(target
.EvaluateExpression(" ".join(cmd
[1:]), opts
))
139 # FIXME: This is a fallback path for the lab.llvm.org
140 # buildbot running OS X 10.7; it should be removed.
141 thread
= process
.GetThreadAtIndex(0)
142 frame
= thread
.GetFrameAtIndex(0)
143 print(frame
.EvaluateExpression(" ".join(cmd
[1:])))
145 elif re
.match("^p|(print)$", cmd
[0]) and len(cmd
) > 1:
146 thread
= process
.GetThreadAtIndex(0)
147 frame
= thread
.GetFrameAtIndex(0)
148 print(frame
.EvaluateExpression(" ".join(cmd
[1:])))
150 elif re
.match("^n|(next)$", cmd
[0]):
151 thread
= process
.GetThreadAtIndex(0)
154 elif re
.match("^q|(quit)$", cmd
[0]):
158 print(debugger
.HandleCommand(" ".join(cmd
)))
163 print('Could not handle the command "%s"' % " ".join(cmd
))