blob: 6e41b4c8098f1694b089a1dc4cce9518a0c735cb [file] [log] [blame]
Kate Stoneb9c1b512016-09-06 20:57:50 +00001import lldb
2import re
Sean Callanan60e390c2013-03-12 00:08:40 +00003
Kate Stoneb9c1b512016-09-06 20:57:50 +00004
5def parse_linespec(linespec, frame, result):
Sean Callanan60e390c2013-03-12 00:08:40 +00006 """Handles a subset of GDB-style linespecs. Specifically:
Kate Stoneb9c1b512016-09-06 20:57:50 +00007
Sean Callanan60e390c2013-03-12 00:08:40 +00008 number - A line in the current file
9 +offset - The line /offset/ lines after this line
10 -offset - The line /offset/ lines before this line
11 filename:number - Line /number/ in file /filename/
12 function - The start of /function/
13 *address - The pointer target of /address/, which must be a literal (but see `` in LLDB)
14
15 We explicitly do not handle filename:function because it is ambiguous in Objective-C.
16
17 This function returns a list of addresses."""
18
19 breakpoint = None
20 target = frame.GetThread().GetProcess().GetTarget()
21
22 matched = False
23
24 if (not matched):
25 mo = re.match("^([0-9]+)$", linespec)
Kate Stoneb9c1b512016-09-06 20:57:50 +000026 if (mo is not None):
Sean Callanan60e390c2013-03-12 00:08:40 +000027 matched = True
Kate Stoneb9c1b512016-09-06 20:57:50 +000028 # print "Matched <linenum>"
Sean Callanan60e390c2013-03-12 00:08:40 +000029 line_number = int(mo.group(1))
30 line_entry = frame.GetLineEntry()
31 if not line_entry.IsValid():
Kate Stoneb9c1b512016-09-06 20:57:50 +000032 result.AppendMessage(
33 "Specified a line in the current file, but the current frame doesn't have line table information.")
Sean Callanan60e390c2013-03-12 00:08:40 +000034 return
Kate Stoneb9c1b512016-09-06 20:57:50 +000035 breakpoint = target.BreakpointCreateByLocation(
36 line_entry.GetFileSpec(), line_number)
Sean Callanan60e390c2013-03-12 00:08:40 +000037
38 if (not matched):
39 mo = re.match("^\+([0-9]+)$", linespec)
Kate Stoneb9c1b512016-09-06 20:57:50 +000040 if (mo is not None):
Sean Callanan60e390c2013-03-12 00:08:40 +000041 matched = True
Kate Stoneb9c1b512016-09-06 20:57:50 +000042 # print "Matched +<count>"
Sean Callanan60e390c2013-03-12 00:08:40 +000043 line_number = int(mo.group(1))
44 line_entry = frame.GetLineEntry()
45 if not line_entry.IsValid():
Kate Stoneb9c1b512016-09-06 20:57:50 +000046 result.AppendMessage(
47 "Specified a line in the current file, but the current frame doesn't have line table information.")
Sean Callanan60e390c2013-03-12 00:08:40 +000048 return
Kate Stoneb9c1b512016-09-06 20:57:50 +000049 breakpoint = target.BreakpointCreateByLocation(
50 line_entry.GetFileSpec(), (line_entry.GetLine() + line_number))
51
Sean Callanan60e390c2013-03-12 00:08:40 +000052 if (not matched):
53 mo = re.match("^\-([0-9]+)$", linespec)
Kate Stoneb9c1b512016-09-06 20:57:50 +000054 if (mo is not None):
Sean Callanan60e390c2013-03-12 00:08:40 +000055 matched = True
Kate Stoneb9c1b512016-09-06 20:57:50 +000056 # print "Matched -<count>"
Sean Callanan60e390c2013-03-12 00:08:40 +000057 line_number = int(mo.group(1))
58 line_entry = frame.GetLineEntry()
59 if not line_entry.IsValid():
Kate Stoneb9c1b512016-09-06 20:57:50 +000060 result.AppendMessage(
61 "Specified a line in the current file, but the current frame doesn't have line table information.")
Sean Callanan60e390c2013-03-12 00:08:40 +000062 return
Kate Stoneb9c1b512016-09-06 20:57:50 +000063 breakpoint = target.BreakpointCreateByLocation(
64 line_entry.GetFileSpec(), (line_entry.GetLine() - line_number))
Sean Callanan60e390c2013-03-12 00:08:40 +000065
66 if (not matched):
67 mo = re.match("^(.*):([0-9]+)$", linespec)
Kate Stoneb9c1b512016-09-06 20:57:50 +000068 if (mo is not None):
Sean Callanan60e390c2013-03-12 00:08:40 +000069 matched = True
Kate Stoneb9c1b512016-09-06 20:57:50 +000070 # print "Matched <filename>:<linenum>"
Sean Callanan60e390c2013-03-12 00:08:40 +000071 file_name = mo.group(1)
72 line_number = int(mo.group(2))
Kate Stoneb9c1b512016-09-06 20:57:50 +000073 breakpoint = target.BreakpointCreateByLocation(
74 file_name, line_number)
Sean Callanan60e390c2013-03-12 00:08:40 +000075
76 if (not matched):
77 mo = re.match("\*((0x)?([0-9a-f]+))$", linespec)
Kate Stoneb9c1b512016-09-06 20:57:50 +000078 if (mo is not None):
Sean Callanan60e390c2013-03-12 00:08:40 +000079 matched = True
Kate Stoneb9c1b512016-09-06 20:57:50 +000080 # print "Matched <address-expression>"
Sean Callanan60e390c2013-03-12 00:08:40 +000081 address = long(mo.group(1), base=0)
82 breakpoint = target.BreakpointCreateByAddress(address)
83
84 if (not matched):
Kate Stoneb9c1b512016-09-06 20:57:50 +000085 # print "Trying <function-name>"
Sean Callanan60e390c2013-03-12 00:08:40 +000086 breakpoint = target.BreakpointCreateByName(linespec)
87
88 num_locations = breakpoint.GetNumLocations()
89
90 if (num_locations == 0):
Kate Stoneb9c1b512016-09-06 20:57:50 +000091 result.AppendMessage(
92 "The line specification provided doesn't resolve to any addresses.")
Sean Callanan60e390c2013-03-12 00:08:40 +000093
94 addr_list = []
95
96 for location_index in range(num_locations):
97 location = breakpoint.GetLocationAtIndex(location_index)
98 addr_list.append(location.GetAddress())
99
100 target.BreakpointDelete(breakpoint.GetID())
101
102 return addr_list
103
Kate Stoneb9c1b512016-09-06 20:57:50 +0000104
Sean Callanan60e390c2013-03-12 00:08:40 +0000105def usage_string():
106 return """ Sets the program counter to a specific address.
107
108Syntax: jump <linespec> [<location-id>]
109
110Command Options Usage:
111 jump <linenum>
112 jump +<count>
113 jump -<count>
114 jump <filename>:<linenum>
115 jump <function-name>
116 jump *<address-expression>
117
118<location-id> serves to disambiguate when multiple locations could be meant."""
119
Kate Stoneb9c1b512016-09-06 20:57:50 +0000120
121def jump(debugger, command, result, internal_dict):
Sean Callanan60e390c2013-03-12 00:08:40 +0000122 if (command == ""):
123 result.AppendMessage(usage_string())
124
125 args = command.split()
126
127 if not debugger.IsValid():
128 result.AppendMessage("Invalid debugger!")
129 return
130
131 target = debugger.GetSelectedTarget()
132 if not target.IsValid():
133 result.AppendMessage("jump requires a valid target.")
134 return
135
136 process = target.GetProcess()
137 if not process.IsValid():
138 result.AppendMessage("jump requires a valid process.")
139 return
140
141 thread = process.GetSelectedThread()
142 if not thread.IsValid():
143 result.AppendMessage("jump requires a valid thread.")
144 return
145
146 frame = thread.GetSelectedFrame()
147 if not frame.IsValid():
148 result.AppendMessage("jump requires a valid frame.")
149 return
150
151 addresses = parse_linespec(args[0], frame, result)
152
153 stream = lldb.SBStream()
154
155 if len(addresses) == 0:
156 return
157
158 desired_address = addresses[0]
159
160 if len(addresses) > 1:
161 if len(args) == 2:
162 desired_index = int(args[1])
163 if (desired_index >= 0) and (desired_index < len(addresses)):
164 desired_address = addresses[desired_index]
165 else:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000166 result.AppendMessage(
167 "Desired index " +
168 args[1] +
169 " is not one of the options.")
Sean Callanan60e390c2013-03-12 00:08:40 +0000170 return
171 else:
172 index = 0
Kate Stoneb9c1b512016-09-06 20:57:50 +0000173 result.AppendMessage(
174 "The specified location resolves to multiple targets.")
Sean Callanan60e390c2013-03-12 00:08:40 +0000175 for address in addresses:
176 stream.Clear()
177 address.GetDescription(stream)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000178 result.AppendMessage(
179 " Location ID " +
180 str(index) +
181 ": " +
182 stream.GetData())
Sean Callanan60e390c2013-03-12 00:08:40 +0000183 index = index + 1
Kate Stoneb9c1b512016-09-06 20:57:50 +0000184 result.AppendMessage(
185 "Please type 'jump " +
186 command +
187 " <location-id>' to choose one.")
Sean Callanan60e390c2013-03-12 00:08:40 +0000188 return
189
190 frame.SetPC(desired_address.GetLoadAddress(target))
191
192if lldb.debugger:
193 # Module is being run inside the LLDB interpreter
194 jump.__doc__ = usage_string()
195 lldb.debugger.HandleCommand('command script add -f jump.jump jump')
196 print 'The "jump" command has been installed, type "help jump" or "jump <ENTER>" for detailed help.'