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