1"""lldb data formatters for clang classes. 2 3Usage 4-- 5import this file in your ~/.lldbinit by adding this line: 6 7command script import /path/to/ClangDataFormat.py 8 9After that, instead of getting this: 10 11(lldb) p Tok.Loc 12(clang::SourceLocation) $0 = { 13 (unsigned int) ID = 123582 14} 15 16you'll get: 17 18(lldb) p Tok.Loc 19(clang::SourceLocation) $4 = "/usr/include/i386/_types.h:37:1" (offset: 123582, file, local) 20""" 21 22import lldb 23 24def __lldb_init_module(debugger, internal_dict): 25 debugger.HandleCommand("type summary add -F ClangDataFormat.SourceLocation_summary clang::SourceLocation") 26 debugger.HandleCommand("type summary add -F ClangDataFormat.QualType_summary clang::QualType") 27 28def SourceLocation_summary(srcloc, internal_dict): 29 return SourceLocation(srcloc).summary() 30 31def QualType_summary(qualty, internal_dict): 32 return QualType(qualty).summary() 33 34class SourceLocation(object): 35 def __init__(self, srcloc): 36 self.srcloc = srcloc 37 self.ID = srcloc.GetChildAtIndex(0).GetValueAsUnsigned() 38 self.frame = srcloc.GetFrame() 39 40 def offset(self): 41 return getValueFromExpression(self.srcloc, ".getOffset()").GetValueAsUnsigned() 42 43 def isInvalid(self): 44 return self.ID == 0 45 46 def isMacro(self): 47 return getValueFromExpression(self.srcloc, ".isMacroID()").GetValueAsUnsigned() 48 49 def isLocal(self, srcmgr_path): 50 return self.frame.EvaluateExpression("(%s).isLocalSourceLocation(%s)" % (srcmgr_path, getExpressionPath(self.srcloc))).GetValueAsUnsigned() 51 52 def getPrint(self, srcmgr_path): 53 print_str = getValueFromExpression(self.srcloc, ".printToString(%s)" % srcmgr_path) 54 return print_str.GetSummary() 55 56 def summary(self): 57 if self.isInvalid(): 58 return "<invalid loc>" 59 srcmgr_path = findObjectExpressionPath("clang::SourceManager", self.frame) 60 if srcmgr_path: 61 return "%s (offset: %d, %s, %s)" % (self.getPrint(srcmgr_path), self.offset(), "macro" if self.isMacro() else "file", "local" if self.isLocal(srcmgr_path) else "loaded") 62 return "(offset: %d, %s)" % (self.offset(), "macro" if self.isMacro() else "file") 63 64class QualType(object): 65 def __init__(self, qualty): 66 self.qualty = qualty 67 68 def getAsString(self): 69 std_str = getValueFromExpression(self.qualty, ".getAsString()") 70 return std_str.GetSummary() 71 72 def summary(self): 73 desc = self.getAsString() 74 if desc == '"NULL TYPE"': 75 return "<NULL TYPE>" 76 return desc 77 78# Key is a (function address, type name) tuple, value is the expression path for 79# an object with such a type name from inside that function. 80FramePathMapCache = {} 81 82def findObjectExpressionPath(typename, frame): 83 func_addr = frame.GetFunction().GetStartAddress().GetFileAddress() 84 key = (func_addr, typename) 85 try: 86 return FramePathMapCache[key] 87 except KeyError: 88 #print "CACHE MISS" 89 path = None 90 obj = findObject(typename, frame) 91 if obj: 92 path = getExpressionPath(obj) 93 FramePathMapCache[key] = path 94 return path 95 96def findObject(typename, frame): 97 def getTypename(value): 98 # FIXME: lldb should provide something like getBaseType 99 ty = value.GetType() 100 if ty.IsPointerType() or ty.IsReferenceType(): 101 return ty.GetPointeeType().GetName() 102 return ty.GetName() 103 104 def searchForType(value, searched): 105 tyname = getTypename(value) 106 #print "SEARCH:", getExpressionPath(value), value.GetType().GetName() 107 if tyname == typename: 108 return value 109 ty = value.GetType() 110 if not (ty.IsPointerType() or 111 ty.IsReferenceType() or 112 # FIXME: lldb should provide something like getCanonicalType 113 tyname.startswith("llvm::IntrusiveRefCntPtr<") or 114 tyname.startswith("llvm::OwningPtr<")): 115 return None 116 # FIXME: Hashing for SBTypes does not seem to work correctly, uses the typename instead, 117 # and not the canonical one unfortunately. 118 if tyname in searched: 119 return None 120 searched.add(tyname) 121 for i in range(value.GetNumChildren()): 122 child = value.GetChildAtIndex(i, 0, False) 123 found = searchForType(child, searched) 124 if found: 125 return found 126 127 searched = set() 128 value_list = frame.GetVariables(True, True, True, True) 129 for val in value_list: 130 found = searchForType(val, searched) 131 if found: 132 return found if not found.TypeIsPointerType() else found.Dereference() 133 134def getValueFromExpression(val, expr): 135 return val.GetFrame().EvaluateExpression(getExpressionPath(val) + expr) 136 137def getExpressionPath(val): 138 stream = lldb.SBStream() 139 val.GetExpressionPath(stream) 140 return stream.GetData() 141