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