]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - examples/python/jump.py
Vendor import of lldb trunk r290819:
[FreeBSD/FreeBSD.git] / examples / python / jump.py
1 import lldb
2 import re
3
4
5 def parse_linespec(linespec, frame, result):
6     """Handles a subset of GDB-style linespecs.  Specifically:
7
8        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)
26         if (mo is not None):
27             matched = True
28             # print "Matched <linenum>"
29             line_number = int(mo.group(1))
30             line_entry = frame.GetLineEntry()
31             if not line_entry.IsValid():
32                 result.AppendMessage(
33                     "Specified a line in the current file, but the current frame doesn't have line table information.")
34                 return
35             breakpoint = target.BreakpointCreateByLocation(
36                 line_entry.GetFileSpec(), line_number)
37
38     if (not matched):
39         mo = re.match("^\+([0-9]+)$", linespec)
40         if (mo is not None):
41             matched = True
42             # print "Matched +<count>"
43             line_number = int(mo.group(1))
44             line_entry = frame.GetLineEntry()
45             if not line_entry.IsValid():
46                 result.AppendMessage(
47                     "Specified a line in the current file, but the current frame doesn't have line table information.")
48                 return
49             breakpoint = target.BreakpointCreateByLocation(
50                 line_entry.GetFileSpec(), (line_entry.GetLine() + line_number))
51
52     if (not matched):
53         mo = re.match("^\-([0-9]+)$", linespec)
54         if (mo is not None):
55             matched = True
56             # print "Matched -<count>"
57             line_number = int(mo.group(1))
58             line_entry = frame.GetLineEntry()
59             if not line_entry.IsValid():
60                 result.AppendMessage(
61                     "Specified a line in the current file, but the current frame doesn't have line table information.")
62                 return
63             breakpoint = target.BreakpointCreateByLocation(
64                 line_entry.GetFileSpec(), (line_entry.GetLine() - line_number))
65
66     if (not matched):
67         mo = re.match("^(.*):([0-9]+)$", linespec)
68         if (mo is not None):
69             matched = True
70             # print "Matched <filename>:<linenum>"
71             file_name = mo.group(1)
72             line_number = int(mo.group(2))
73             breakpoint = target.BreakpointCreateByLocation(
74                 file_name, line_number)
75
76     if (not matched):
77         mo = re.match("\*((0x)?([0-9a-f]+))$", linespec)
78         if (mo is not None):
79             matched = True
80             # print "Matched <address-expression>"
81             address = long(mo.group(1), base=0)
82             breakpoint = target.BreakpointCreateByAddress(address)
83
84     if (not matched):
85         # print "Trying <function-name>"
86         breakpoint = target.BreakpointCreateByName(linespec)
87
88     num_locations = breakpoint.GetNumLocations()
89
90     if (num_locations == 0):
91         result.AppendMessage(
92             "The line specification provided doesn't resolve to any addresses.")
93
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
104
105 def usage_string():
106     return """   Sets the program counter to a specific address.
107
108 Syntax: jump <linespec> [<location-id>]
109
110 Command 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
120
121 def jump(debugger, command, result, internal_dict):
122     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:
166                 result.AppendMessage(
167                     "Desired index " +
168                     args[1] +
169                     " is not one of the options.")
170                 return
171         else:
172             index = 0
173             result.AppendMessage(
174                 "The specified location resolves to multiple targets.")
175             for address in addresses:
176                 stream.Clear()
177                 address.GetDescription(stream)
178                 result.AppendMessage(
179                     "  Location ID " +
180                     str(index) +
181                     ": " +
182                     stream.GetData())
183                 index = index + 1
184             result.AppendMessage(
185                 "Please type 'jump " +
186                 command +
187                 " <location-id>' to choose one.")
188             return
189
190     frame.SetPC(desired_address.GetLoadAddress(target))
191
192 if 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.'