Revert "[clang-repl] Implement partial translation units and error recovery."
[llvm-project.git] / lldb / examples / python / jump.py
blobdc4cc48b14447c92c7b89a794057e7982b3ca24f
1 from __future__ import print_function
3 import lldb
4 import re
7 def parse_linespec(linespec, frame, result):
8 """Handles a subset of GDB-style linespecs. Specifically:
10 number - A line in the current file
11 +offset - The line /offset/ lines after this line
12 -offset - The line /offset/ lines before this line
13 filename:number - Line /number/ in file /filename/
14 function - The start of /function/
15 *address - The pointer target of /address/, which must be a literal (but see `` in LLDB)
17 We explicitly do not handle filename:function because it is ambiguous in Objective-C.
19 This function returns a list of addresses."""
21 breakpoint = None
22 target = frame.GetThread().GetProcess().GetTarget()
24 matched = False
26 if (not matched):
27 mo = re.match("^([0-9]+)$", linespec)
28 if (mo is not None):
29 matched = True
30 # print "Matched <linenum>"
31 line_number = int(mo.group(1))
32 line_entry = frame.GetLineEntry()
33 if not line_entry.IsValid():
34 result.AppendMessage(
35 "Specified a line in the current file, but the current frame doesn't have line table information.")
36 return
37 breakpoint = target.BreakpointCreateByLocation(
38 line_entry.GetFileSpec(), line_number)
40 if (not matched):
41 mo = re.match("^\+([0-9]+)$", linespec)
42 if (mo is not None):
43 matched = True
44 # print "Matched +<count>"
45 line_number = int(mo.group(1))
46 line_entry = frame.GetLineEntry()
47 if not line_entry.IsValid():
48 result.AppendMessage(
49 "Specified a line in the current file, but the current frame doesn't have line table information.")
50 return
51 breakpoint = target.BreakpointCreateByLocation(
52 line_entry.GetFileSpec(), (line_entry.GetLine() + line_number))
54 if (not matched):
55 mo = re.match("^\-([0-9]+)$", linespec)
56 if (mo is not None):
57 matched = True
58 # print "Matched -<count>"
59 line_number = int(mo.group(1))
60 line_entry = frame.GetLineEntry()
61 if not line_entry.IsValid():
62 result.AppendMessage(
63 "Specified a line in the current file, but the current frame doesn't have line table information.")
64 return
65 breakpoint = target.BreakpointCreateByLocation(
66 line_entry.GetFileSpec(), (line_entry.GetLine() - line_number))
68 if (not matched):
69 mo = re.match("^(.*):([0-9]+)$", linespec)
70 if (mo is not None):
71 matched = True
72 # print "Matched <filename>:<linenum>"
73 file_name = mo.group(1)
74 line_number = int(mo.group(2))
75 breakpoint = target.BreakpointCreateByLocation(
76 file_name, line_number)
78 if (not matched):
79 mo = re.match("\*((0x)?([0-9a-f]+))$", linespec)
80 if (mo is not None):
81 matched = True
82 # print "Matched <address-expression>"
83 address = int(mo.group(1), base=0)
84 breakpoint = target.BreakpointCreateByAddress(address)
86 if (not matched):
87 # print "Trying <function-name>"
88 breakpoint = target.BreakpointCreateByName(linespec)
90 num_locations = breakpoint.GetNumLocations()
92 if (num_locations == 0):
93 result.AppendMessage(
94 "The line specification provided doesn't resolve to any addresses.")
96 addr_list = []
98 for location_index in range(num_locations):
99 location = breakpoint.GetLocationAtIndex(location_index)
100 addr_list.append(location.GetAddress())
102 target.BreakpointDelete(breakpoint.GetID())
104 return addr_list
107 def usage_string():
108 return """ Sets the program counter to a specific address.
110 Syntax: jump <linespec> [<location-id>]
112 Command Options Usage:
113 jump <linenum>
114 jump +<count>
115 jump -<count>
116 jump <filename>:<linenum>
117 jump <function-name>
118 jump *<address-expression>
120 <location-id> serves to disambiguate when multiple locations could be meant."""
123 def jump(debugger, command, result, internal_dict):
124 if (command == ""):
125 result.AppendMessage(usage_string())
127 args = command.split()
129 if not debugger.IsValid():
130 result.AppendMessage("Invalid debugger!")
131 return
133 target = debugger.GetSelectedTarget()
134 if not target.IsValid():
135 result.AppendMessage("jump requires a valid target.")
136 return
138 process = target.GetProcess()
139 if not process.IsValid():
140 result.AppendMessage("jump requires a valid process.")
141 return
143 thread = process.GetSelectedThread()
144 if not thread.IsValid():
145 result.AppendMessage("jump requires a valid thread.")
146 return
148 frame = thread.GetSelectedFrame()
149 if not frame.IsValid():
150 result.AppendMessage("jump requires a valid frame.")
151 return
153 addresses = parse_linespec(args[0], frame, result)
155 stream = lldb.SBStream()
157 if len(addresses) == 0:
158 return
160 desired_address = addresses[0]
162 if len(addresses) > 1:
163 if len(args) == 2:
164 desired_index = int(args[1])
165 if (desired_index >= 0) and (desired_index < len(addresses)):
166 desired_address = addresses[desired_index]
167 else:
168 result.AppendMessage(
169 "Desired index " +
170 args[1] +
171 " is not one of the options.")
172 return
173 else:
174 index = 0
175 result.AppendMessage(
176 "The specified location resolves to multiple targets.")
177 for address in addresses:
178 stream.Clear()
179 address.GetDescription(stream)
180 result.AppendMessage(
181 " Location ID " +
182 str(index) +
183 ": " +
184 stream.GetData())
185 index = index + 1
186 result.AppendMessage(
187 "Please type 'jump " +
188 command +
189 " <location-id>' to choose one.")
190 return
192 frame.SetPC(desired_address.GetLoadAddress(target))
194 if lldb.debugger:
195 # Module is being run inside the LLDB interpreter
196 jump.__doc__ = usage_string()
197 lldb.debugger.HandleCommand('command script add -f jump.jump jump')
198 print('The "jump" command has been installed, type "help jump" or "jump <ENTER>" for detailed help.')