1525cd59fSSerge Gueltonfrom __future__ import print_function 2525cd59fSSerge Guelton 3b9c1b51eSKate Stoneimport lldb 4b9c1b51eSKate Stoneimport re 5b9c1b51eSKate Stone 660e390cbSSean Callanan 760e390cbSSean Callanandef parse_linespec(linespec, frame, result): 860e390cbSSean Callanan """Handles a subset of GDB-style linespecs. Specifically: 960e390cbSSean Callanan 1060e390cbSSean Callanan number - A line in the current file 1160e390cbSSean Callanan +offset - The line /offset/ lines after this line 1260e390cbSSean Callanan -offset - The line /offset/ lines before this line 1360e390cbSSean Callanan filename:number - Line /number/ in file /filename/ 1460e390cbSSean Callanan function - The start of /function/ 1560e390cbSSean Callanan *address - The pointer target of /address/, which must be a literal (but see `` in LLDB) 1660e390cbSSean Callanan 1760e390cbSSean Callanan We explicitly do not handle filename:function because it is ambiguous in Objective-C. 1860e390cbSSean Callanan 1960e390cbSSean Callanan This function returns a list of addresses.""" 2060e390cbSSean Callanan 2160e390cbSSean Callanan breakpoint = None 2260e390cbSSean Callanan target = frame.GetThread().GetProcess().GetTarget() 2360e390cbSSean Callanan 2460e390cbSSean Callanan matched = False 2560e390cbSSean Callanan 2660e390cbSSean Callanan if (not matched): 2760e390cbSSean Callanan mo = re.match("^([0-9]+)$", linespec) 28b9c1b51eSKate Stone if (mo is not None): 2960e390cbSSean Callanan matched = True 3060e390cbSSean Callanan # print "Matched <linenum>" 3160e390cbSSean Callanan line_number = int(mo.group(1)) 3260e390cbSSean Callanan line_entry = frame.GetLineEntry() 3360e390cbSSean Callanan if not line_entry.IsValid(): 34b9c1b51eSKate Stone result.AppendMessage( 35b9c1b51eSKate Stone "Specified a line in the current file, but the current frame doesn't have line table information.") 3660e390cbSSean Callanan return 37b9c1b51eSKate Stone breakpoint = target.BreakpointCreateByLocation( 38b9c1b51eSKate Stone line_entry.GetFileSpec(), line_number) 3960e390cbSSean Callanan 4060e390cbSSean Callanan if (not matched): 4160e390cbSSean Callanan mo = re.match("^\+([0-9]+)$", linespec) 42b9c1b51eSKate Stone if (mo is not None): 4360e390cbSSean Callanan matched = True 4460e390cbSSean Callanan # print "Matched +<count>" 4560e390cbSSean Callanan line_number = int(mo.group(1)) 4660e390cbSSean Callanan line_entry = frame.GetLineEntry() 4760e390cbSSean Callanan if not line_entry.IsValid(): 48b9c1b51eSKate Stone result.AppendMessage( 49b9c1b51eSKate Stone "Specified a line in the current file, but the current frame doesn't have line table information.") 5060e390cbSSean Callanan return 51b9c1b51eSKate Stone breakpoint = target.BreakpointCreateByLocation( 52b9c1b51eSKate Stone line_entry.GetFileSpec(), (line_entry.GetLine() + line_number)) 5360e390cbSSean Callanan 5460e390cbSSean Callanan if (not matched): 5560e390cbSSean Callanan mo = re.match("^\-([0-9]+)$", linespec) 56b9c1b51eSKate Stone if (mo is not None): 5760e390cbSSean Callanan matched = True 5860e390cbSSean Callanan # print "Matched -<count>" 5960e390cbSSean Callanan line_number = int(mo.group(1)) 6060e390cbSSean Callanan line_entry = frame.GetLineEntry() 6160e390cbSSean Callanan if not line_entry.IsValid(): 62b9c1b51eSKate Stone result.AppendMessage( 63b9c1b51eSKate Stone "Specified a line in the current file, but the current frame doesn't have line table information.") 6460e390cbSSean Callanan return 65b9c1b51eSKate Stone breakpoint = target.BreakpointCreateByLocation( 66b9c1b51eSKate Stone line_entry.GetFileSpec(), (line_entry.GetLine() - line_number)) 6760e390cbSSean Callanan 6860e390cbSSean Callanan if (not matched): 6960e390cbSSean Callanan mo = re.match("^(.*):([0-9]+)$", linespec) 70b9c1b51eSKate Stone if (mo is not None): 7160e390cbSSean Callanan matched = True 7260e390cbSSean Callanan # print "Matched <filename>:<linenum>" 7360e390cbSSean Callanan file_name = mo.group(1) 7460e390cbSSean Callanan line_number = int(mo.group(2)) 75b9c1b51eSKate Stone breakpoint = target.BreakpointCreateByLocation( 76b9c1b51eSKate Stone file_name, line_number) 7760e390cbSSean Callanan 7860e390cbSSean Callanan if (not matched): 7960e390cbSSean Callanan mo = re.match("\*((0x)?([0-9a-f]+))$", linespec) 80b9c1b51eSKate Stone if (mo is not None): 8160e390cbSSean Callanan matched = True 8260e390cbSSean Callanan # print "Matched <address-expression>" 83bfb77918SSerge Guelton address = int(mo.group(1), base=0) 8460e390cbSSean Callanan breakpoint = target.BreakpointCreateByAddress(address) 8560e390cbSSean Callanan 8660e390cbSSean Callanan if (not matched): 8760e390cbSSean Callanan # print "Trying <function-name>" 8860e390cbSSean Callanan breakpoint = target.BreakpointCreateByName(linespec) 8960e390cbSSean Callanan 9060e390cbSSean Callanan num_locations = breakpoint.GetNumLocations() 9160e390cbSSean Callanan 9260e390cbSSean Callanan if (num_locations == 0): 93b9c1b51eSKate Stone result.AppendMessage( 94b9c1b51eSKate Stone "The line specification provided doesn't resolve to any addresses.") 9560e390cbSSean Callanan 9660e390cbSSean Callanan addr_list = [] 9760e390cbSSean Callanan 9860e390cbSSean Callanan for location_index in range(num_locations): 9960e390cbSSean Callanan location = breakpoint.GetLocationAtIndex(location_index) 10060e390cbSSean Callanan addr_list.append(location.GetAddress()) 10160e390cbSSean Callanan 10260e390cbSSean Callanan target.BreakpointDelete(breakpoint.GetID()) 10360e390cbSSean Callanan 10460e390cbSSean Callanan return addr_list 10560e390cbSSean Callanan 106b9c1b51eSKate Stone 10760e390cbSSean Callanandef usage_string(): 10860e390cbSSean Callanan return """ Sets the program counter to a specific address. 10960e390cbSSean Callanan 11060e390cbSSean CallananSyntax: jump <linespec> [<location-id>] 11160e390cbSSean Callanan 11260e390cbSSean CallananCommand Options Usage: 11360e390cbSSean Callanan jump <linenum> 11460e390cbSSean Callanan jump +<count> 11560e390cbSSean Callanan jump -<count> 11660e390cbSSean Callanan jump <filename>:<linenum> 11760e390cbSSean Callanan jump <function-name> 11860e390cbSSean Callanan jump *<address-expression> 11960e390cbSSean Callanan 12060e390cbSSean Callanan<location-id> serves to disambiguate when multiple locations could be meant.""" 12160e390cbSSean Callanan 122b9c1b51eSKate Stone 12360e390cbSSean Callanandef jump(debugger, command, result, internal_dict): 12460e390cbSSean Callanan if (command == ""): 12560e390cbSSean Callanan result.AppendMessage(usage_string()) 12660e390cbSSean Callanan 12760e390cbSSean Callanan args = command.split() 12860e390cbSSean Callanan 12960e390cbSSean Callanan if not debugger.IsValid(): 13060e390cbSSean Callanan result.AppendMessage("Invalid debugger!") 13160e390cbSSean Callanan return 13260e390cbSSean Callanan 13360e390cbSSean Callanan target = debugger.GetSelectedTarget() 13460e390cbSSean Callanan if not target.IsValid(): 13560e390cbSSean Callanan result.AppendMessage("jump requires a valid target.") 13660e390cbSSean Callanan return 13760e390cbSSean Callanan 13860e390cbSSean Callanan process = target.GetProcess() 13960e390cbSSean Callanan if not process.IsValid(): 14060e390cbSSean Callanan result.AppendMessage("jump requires a valid process.") 14160e390cbSSean Callanan return 14260e390cbSSean Callanan 14360e390cbSSean Callanan thread = process.GetSelectedThread() 14460e390cbSSean Callanan if not thread.IsValid(): 14560e390cbSSean Callanan result.AppendMessage("jump requires a valid thread.") 14660e390cbSSean Callanan return 14760e390cbSSean Callanan 14860e390cbSSean Callanan frame = thread.GetSelectedFrame() 14960e390cbSSean Callanan if not frame.IsValid(): 15060e390cbSSean Callanan result.AppendMessage("jump requires a valid frame.") 15160e390cbSSean Callanan return 15260e390cbSSean Callanan 15360e390cbSSean Callanan addresses = parse_linespec(args[0], frame, result) 15460e390cbSSean Callanan 15560e390cbSSean Callanan stream = lldb.SBStream() 15660e390cbSSean Callanan 15760e390cbSSean Callanan if len(addresses) == 0: 15860e390cbSSean Callanan return 15960e390cbSSean Callanan 16060e390cbSSean Callanan desired_address = addresses[0] 16160e390cbSSean Callanan 16260e390cbSSean Callanan if len(addresses) > 1: 16360e390cbSSean Callanan if len(args) == 2: 16460e390cbSSean Callanan desired_index = int(args[1]) 16560e390cbSSean Callanan if (desired_index >= 0) and (desired_index < len(addresses)): 16660e390cbSSean Callanan desired_address = addresses[desired_index] 16760e390cbSSean Callanan else: 168b9c1b51eSKate Stone result.AppendMessage( 169b9c1b51eSKate Stone "Desired index " + 170b9c1b51eSKate Stone args[1] + 171b9c1b51eSKate Stone " is not one of the options.") 17260e390cbSSean Callanan return 17360e390cbSSean Callanan else: 17460e390cbSSean Callanan index = 0 175b9c1b51eSKate Stone result.AppendMessage( 176b9c1b51eSKate Stone "The specified location resolves to multiple targets.") 17760e390cbSSean Callanan for address in addresses: 17860e390cbSSean Callanan stream.Clear() 17960e390cbSSean Callanan address.GetDescription(stream) 180b9c1b51eSKate Stone result.AppendMessage( 181b9c1b51eSKate Stone " Location ID " + 182b9c1b51eSKate Stone str(index) + 183b9c1b51eSKate Stone ": " + 184b9c1b51eSKate Stone stream.GetData()) 18560e390cbSSean Callanan index = index + 1 186b9c1b51eSKate Stone result.AppendMessage( 187b9c1b51eSKate Stone "Please type 'jump " + 188b9c1b51eSKate Stone command + 189b9c1b51eSKate Stone " <location-id>' to choose one.") 19060e390cbSSean Callanan return 19160e390cbSSean Callanan 19260e390cbSSean Callanan frame.SetPC(desired_address.GetLoadAddress(target)) 19360e390cbSSean Callanan 194*1441ffe6SDave Leedef __lldb_init_module(debugger, internal_dict): 19560e390cbSSean Callanan # Module is being run inside the LLDB interpreter 19660e390cbSSean Callanan jump.__doc__ = usage_string() 197*1441ffe6SDave Lee debugger.HandleCommand('command script add -f jump.jump jump') 198525cd59fSSerge Guelton print('The "jump" command has been installed, type "help jump" or "jump <ENTER>" for detailed help.') 199