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