forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			197 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			197 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Python
		
	
	
	
import lldb
 | 
						|
import 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 is not 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 is not 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 is not 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 is not 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 is not 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.'
 |