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