diff options
Diffstat (limited to 'examples/python/jump.py')
-rw-r--r-- | examples/python/jump.py | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/examples/python/jump.py b/examples/python/jump.py new file mode 100644 index 000000000000..c904009bb405 --- /dev/null +++ b/examples/python/jump.py @@ -0,0 +1,173 @@ +import lldb, re + +def parse_linespec (linespec, frame, result): + """Handles a subset of GDB-style linespecs. Specifically: + + number - A line in the current file + +offset - The line /offset/ lines after this line + -offset - The line /offset/ lines before this line + filename:number - Line /number/ in file /filename/ + function - The start of /function/ + *address - The pointer target of /address/, which must be a literal (but see `` in LLDB) + + We explicitly do not handle filename:function because it is ambiguous in Objective-C. + + This function returns a list of addresses.""" + + breakpoint = None + target = frame.GetThread().GetProcess().GetTarget() + + matched = False + + if (not matched): + mo = re.match("^([0-9]+)$", linespec) + if (mo != None): + matched = True + #print "Matched <linenum>" + line_number = int(mo.group(1)) + line_entry = frame.GetLineEntry() + if not line_entry.IsValid(): + result.AppendMessage("Specified a line in the current file, but the current frame doesn't have line table information.") + return + breakpoint = target.BreakpointCreateByLocation (line_entry.GetFileSpec(), line_number) + + if (not matched): + mo = re.match("^\+([0-9]+)$", linespec) + if (mo != None): + matched = True + #print "Matched +<count>" + line_number = int(mo.group(1)) + line_entry = frame.GetLineEntry() + if not line_entry.IsValid(): + result.AppendMessage("Specified a line in the current file, but the current frame doesn't have line table information.") + return + breakpoint = target.BreakpointCreateByLocation(line_entry.GetFileSpec(), (line_entry.GetLine() + line_number)) + + if (not matched): + mo = re.match("^\-([0-9]+)$", linespec) + if (mo != None): + matched = True + #print "Matched -<count>" + line_number = int(mo.group(1)) + line_entry = frame.GetLineEntry() + if not line_entry.IsValid(): + result.AppendMessage("Specified a line in the current file, but the current frame doesn't have line table information.") + return + breakpoint = target.BreakpointCreateByLocation(line_entry.GetFileSpec(), (line_entry.GetLine() - line_number)) + + if (not matched): + mo = re.match("^(.*):([0-9]+)$", linespec) + if (mo != None): + matched = True + #print "Matched <filename>:<linenum>" + file_name = mo.group(1) + line_number = int(mo.group(2)) + breakpoint = target.BreakpointCreateByLocation(file_name, line_number) + + if (not matched): + mo = re.match("\*((0x)?([0-9a-f]+))$", linespec) + if (mo != None): + matched = True + #print "Matched <address-expression>" + address = long(mo.group(1), base=0) + breakpoint = target.BreakpointCreateByAddress(address) + + if (not matched): + #print "Trying <function-name>" + breakpoint = target.BreakpointCreateByName(linespec) + + num_locations = breakpoint.GetNumLocations() + + if (num_locations == 0): + result.AppendMessage("The line specification provided doesn't resolve to any addresses.") + + addr_list = [] + + for location_index in range(num_locations): + location = breakpoint.GetLocationAtIndex(location_index) + addr_list.append(location.GetAddress()) + + target.BreakpointDelete(breakpoint.GetID()) + + return addr_list + +def usage_string(): + return """ Sets the program counter to a specific address. + +Syntax: jump <linespec> [<location-id>] + +Command Options Usage: + jump <linenum> + jump +<count> + jump -<count> + jump <filename>:<linenum> + jump <function-name> + jump *<address-expression> + +<location-id> serves to disambiguate when multiple locations could be meant.""" + +def jump (debugger, command, result, internal_dict): + if (command == ""): + result.AppendMessage(usage_string()) + + args = command.split() + + if not debugger.IsValid(): + result.AppendMessage("Invalid debugger!") + return + + target = debugger.GetSelectedTarget() + if not target.IsValid(): + result.AppendMessage("jump requires a valid target.") + return + + process = target.GetProcess() + if not process.IsValid(): + result.AppendMessage("jump requires a valid process.") + return + + thread = process.GetSelectedThread() + if not thread.IsValid(): + result.AppendMessage("jump requires a valid thread.") + return + + frame = thread.GetSelectedFrame() + if not frame.IsValid(): + result.AppendMessage("jump requires a valid frame.") + return + + addresses = parse_linespec(args[0], frame, result) + + stream = lldb.SBStream() + + if len(addresses) == 0: + return + + desired_address = addresses[0] + + if len(addresses) > 1: + if len(args) == 2: + desired_index = int(args[1]) + if (desired_index >= 0) and (desired_index < len(addresses)): + desired_address = addresses[desired_index] + else: + result.AppendMessage("Desired index " + args[1] + " is not one of the options.") + return + else: + index = 0 + result.AppendMessage("The specified location resolves to multiple targets."); + for address in addresses: + stream.Clear() + address.GetDescription(stream) + result.AppendMessage(" Location ID " + str(index) + ": " + stream.GetData()) + index = index + 1 + result.AppendMessage("Please type 'jump " + command + " <location-id>' to choose one.") + return + + frame.SetPC(desired_address.GetLoadAddress(target)) + +if lldb.debugger: + # Module is being run inside the LLDB interpreter + jump.__doc__ = usage_string() + lldb.debugger.HandleCommand('command script add -f jump.jump jump') + print 'The "jump" command has been installed, type "help jump" or "jump <ENTER>" for detailed help.' |