[Lldb-commits] [lldb] r176841 - Created a sample "jump" command that handles

Sean Callanan scallanan at apple.com
Mon Mar 11 17:08:40 PDT 2013


Author: spyffe
Date: Mon Mar 11 19:08:40 2013
New Revision: 176841

URL: http://llvm.org/viewvc/llvm-project?rev=176841&view=rev
Log:
Created a sample "jump" command that handles
GDB-style linespecs.  This command allows changing
the PC without manually looking up the new address.

Added:
    lldb/trunk/examples/python/jump.py

Added: lldb/trunk/examples/python/jump.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/jump.py?rev=176841&view=auto
==============================================================================
--- lldb/trunk/examples/python/jump.py (added)
+++ lldb/trunk/examples/python/jump.py Mon Mar 11 19:08:40 2013
@@ -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.'





More information about the lldb-commits mailing list