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