]> granicus.if.org Git - clang/commitdiff
Add lldb data formatters for clang classes, starting with SourceLocation.
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Fri, 9 Nov 2012 22:59:01 +0000 (22:59 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Fri, 9 Nov 2012 22:59:01 +0000 (22:59 +0000)
When installed, instead of getting this:

(lldb) p Tok.Loc
(clang::SourceLocation) $0 = {
  (unsigned int) ID = 123582
}

you'll get:

(lldb) p Tok.Loc
(clang::SourceLocation) $4 = "/usr/include/i386/_types.h:37:1" (offset: 123582, file)

This depends on r167629.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@167640 91177308-0d34-0410-b5e6-96231b3b80d8

utils/ClangDataFormat.py [new file with mode: 0644]

diff --git a/utils/ClangDataFormat.py b/utils/ClangDataFormat.py
new file mode 100644 (file)
index 0000000..6e8f5aa
--- /dev/null
@@ -0,0 +1,116 @@
+"""lldb data formatters for clang classes.
+
+Usage
+--
+import this file in your ~/.lldbinit by adding this line:
+
+command script import /path/to/ClangDataFormat.py
+
+After that, instead of getting this:
+
+(lldb) p Tok.Loc
+(clang::SourceLocation) $0 = {
+  (unsigned int) ID = 123582
+}
+
+you'll get:
+
+(lldb) p Tok.Loc
+(clang::SourceLocation) $4 = "/usr/include/i386/_types.h:37:1" (offset: 123582, file)
+"""
+
+import lldb
+
+def __lldb_init_module(debugger, internal_dict):
+       debugger.HandleCommand("type summary add -F ClangDataFormat.SourceLocation_summary clang::SourceLocation")
+
+def SourceLocation_summary(srcloc, internal_dict):
+       return SourceLocation(srcloc).summary()
+
+class SourceLocation(object):
+       def __init__(self, srcloc):
+               self.srcloc = srcloc
+       
+       def offset(self):
+               return getValueFromExpression(self.srcloc, ".getOffset()").GetValueAsUnsigned()
+
+       def isMacro(self):
+               return getValueFromExpression(self.srcloc, ".isMacroID()").GetValueAsUnsigned()
+
+       def getPrint(self, srcmgr_path):
+               print_str = getValueFromExpression(self.srcloc, ".printToString(%s)" % srcmgr_path)
+               return print_str.GetSummary()
+
+       def summary(self):
+               desc = "(offset: %d, %s)" % (self.offset(), "macro" if self.isMacro() else "file")
+               srcmgr_path = findObjectExpressionPath("clang::SourceManager", lldb.frame)
+               if srcmgr_path:
+                       desc = self.getPrint(srcmgr_path) + " " + desc
+               return desc
+
+# Key is a (function address, type name) tuple, value is the expression path for
+# an object with such a type name from inside that function.
+FramePathMapCache = {}
+
+def findSourceManager(frame):
+       return findObject("clang::SourceManager", SourceManager_Paths, frame)
+
+def findObjectExpressionPath(typename, frame):
+       func_addr = frame.GetFunction().GetStartAddress().GetFileAddress()
+       key = (func_addr, typename)
+       try:
+               return FramePathMapCache[key]
+       except KeyError:
+               #print "CACHE MISS"
+               path = None
+               obj = findObject(typename, frame)
+               if obj:
+                       path = getExpressionPath(obj)
+               FramePathMapCache[key] = path
+               return path
+
+def findObject(typename, frame):
+       def getTypename(value):
+               # FIXME: lldb should provide something like getBaseType
+               ty = value.GetType()
+               if ty.IsPointerType() or ty.IsReferenceType():
+                       return ty.GetPointeeType().GetName()
+               return ty.GetName()
+
+       def searchForType(value, searched):
+               tyname = getTypename(value)
+               #print "SEARCH:", getExpressionPath(value), value.GetType().GetName()
+               if tyname == typename:
+                       return value
+               ty = value.GetType()
+               if not (ty.IsPointerType() or
+                       ty.IsReferenceType() or
+                               # FIXME: lldb should provide something like getCanonicalType
+                       tyname.startswith("llvm::IntrusiveRefCntPtr<") or
+                       tyname.startswith("llvm::OwningPtr<")):
+                       return None
+               # FIXME: Hashing for SBTypes does not seem to work correctly, uses the typename instead,
+               # and not the canonical one unfortunately.
+               if tyname in searched:
+                       return None
+               searched.add(tyname)
+               for i in range(value.GetNumChildren()):
+                       child = value.GetChildAtIndex(i, 0, False)
+                       found = searchForType(child, searched)
+                       if found:
+                               return found
+
+       searched = set()
+       value_list = frame.GetVariables(True, True, True, True)
+       for val in value_list:
+               found = searchForType(val, searched)
+               if found:
+                       return found if not found.TypeIsPointerType() else found.Dereference()
+
+def getValueFromExpression(val, expr):
+       return lldb.frame.EvaluateExpression(getExpressionPath(val) + expr)
+
+def getExpressionPath(val):
+       stream = lldb.SBStream()
+       val.GetExpressionPath(stream)
+       return stream.GetData()