1331722Seadler"""lldb data formatters for clang classes. 2239281Sgonzo 3239281SgonzoUsage 4239281Sgonzo-- 5239281Sgonzoimport this file in your ~/.lldbinit by adding this line: 6239281Sgonzo 7239281Sgonzocommand script import /path/to/ClangDataFormat.py 8239281Sgonzo 9239281SgonzoAfter that, instead of getting this: 10239281Sgonzo 11239281Sgonzo(lldb) p Tok.Loc 12239281Sgonzo(clang::SourceLocation) $0 = { 13239281Sgonzo (unsigned int) ID = 123582 14239281Sgonzo} 15239281Sgonzo 16239281Sgonzoyou'll get: 17239281Sgonzo 18239281Sgonzo(lldb) p Tok.Loc 19239281Sgonzo(clang::SourceLocation) $4 = "/usr/include/i386/_types.h:37:1" (offset: 123582, file, local) 20239281Sgonzo""" 21239281Sgonzo 22239281Sgonzoimport lldb 23239281Sgonzo 24239281Sgonzodef __lldb_init_module(debugger, internal_dict): 25239281Sgonzo debugger.HandleCommand("type summary add -F ClangDataFormat.SourceLocation_summary clang::SourceLocation") 26239281Sgonzo debugger.HandleCommand("type summary add -F ClangDataFormat.QualType_summary clang::QualType") 27239281Sgonzo debugger.HandleCommand("type summary add -F ClangDataFormat.StringRef_summary llvm::StringRef") 28239281Sgonzo 29239281Sgonzodef SourceLocation_summary(srcloc, internal_dict): 30239281Sgonzo return SourceLocation(srcloc).summary() 31239281Sgonzo 32239281Sgonzodef QualType_summary(qualty, internal_dict): 33239281Sgonzo return QualType(qualty).summary() 34239281Sgonzo 35239281Sgonzodef StringRef_summary(strref, internal_dict): 36239281Sgonzo return StringRef(strref).summary() 37239281Sgonzo 38239281Sgonzoclass SourceLocation(object): 39239281Sgonzo def __init__(self, srcloc): 40239281Sgonzo self.srcloc = srcloc 41239281Sgonzo self.ID = srcloc.GetChildAtIndex(0).GetValueAsUnsigned() 42239281Sgonzo self.frame = srcloc.GetFrame() 43239281Sgonzo 44239281Sgonzo def offset(self): 45239281Sgonzo return getValueFromExpression(self.srcloc, ".getOffset()").GetValueAsUnsigned() 46239281Sgonzo 47239281Sgonzo def isInvalid(self): 48239281Sgonzo return self.ID == 0 49239281Sgonzo 50239281Sgonzo def isMacro(self): 51239281Sgonzo return getValueFromExpression(self.srcloc, ".isMacroID()").GetValueAsUnsigned() 52239281Sgonzo 53239281Sgonzo def isLocal(self, srcmgr_path): 54239281Sgonzo return self.frame.EvaluateExpression("(%s).isLocalSourceLocation(%s)" % (srcmgr_path, getExpressionPath(self.srcloc))).GetValueAsUnsigned() 55239281Sgonzo 56239281Sgonzo def getPrint(self, srcmgr_path): 57239281Sgonzo print_str = getValueFromExpression(self.srcloc, ".printToString(%s)" % srcmgr_path) 58239281Sgonzo return print_str.GetSummary() 59239281Sgonzo 60239281Sgonzo def summary(self): 61239281Sgonzo if self.isInvalid(): 62239281Sgonzo return "<invalid loc>" 63239281Sgonzo srcmgr_path = findObjectExpressionPath("clang::SourceManager", self.frame) 64239281Sgonzo if srcmgr_path: 65283276Sgonzo 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") 66239281Sgonzo return "(offset: %d, %s)" % (self.offset(), "macro" if self.isMacro() else "file") 67239281Sgonzo 68239281Sgonzoclass QualType(object): 69239281Sgonzo def __init__(self, qualty): 70239281Sgonzo self.qualty = qualty 71239281Sgonzo 72239281Sgonzo def getAsString(self): 73239281Sgonzo std_str = getValueFromExpression(self.qualty, ".getAsString()") 74239281Sgonzo return std_str.GetSummary() 75239281Sgonzo 76239281Sgonzo def summary(self): 77239281Sgonzo desc = self.getAsString() 78239281Sgonzo if desc == '"NULL TYPE"': 79239281Sgonzo return "<NULL TYPE>" 80239281Sgonzo return desc 81239281Sgonzo 82239281Sgonzoclass StringRef(object): 83239281Sgonzo def __init__(self, strref): 84239281Sgonzo self.strref = strref 85239281Sgonzo self.Data_value = strref.GetChildAtIndex(0) 86239281Sgonzo self.Length = strref.GetChildAtIndex(1).GetValueAsUnsigned() 87239281Sgonzo 88239281Sgonzo def summary(self): 89239281Sgonzo if self.Length == 0: 90261410Sian return '""' 91261410Sian data = self.Data_value.GetPointeeData(0, self.Length) 92261410Sian error = lldb.SBError() 93283276Sgonzo string = data.ReadRawData(error, 0, data.GetByteSize()) 94239281Sgonzo if error.Fail(): 95239281Sgonzo return None 96283276Sgonzo return '"%s"' % string 97283276Sgonzo 98283276Sgonzo 99283276Sgonzo# Key is a (function address, type name) tuple, value is the expression path for 100239281Sgonzo# an object with such a type name from inside that function. 101239281SgonzoFramePathMapCache = {} 102239281Sgonzo 103239281Sgonzodef findObjectExpressionPath(typename, frame): 104239281Sgonzo func_addr = frame.GetFunction().GetStartAddress().GetFileAddress() 105239281Sgonzo key = (func_addr, typename) 106239281Sgonzo try: 107239281Sgonzo return FramePathMapCache[key] 108239281Sgonzo except KeyError: 109239281Sgonzo #print "CACHE MISS" 110239281Sgonzo path = None 111239281Sgonzo obj = findObject(typename, frame) 112299069Spfg if obj: 113239281Sgonzo path = getExpressionPath(obj) 114239281Sgonzo FramePathMapCache[key] = path 115239281Sgonzo return path 116239281Sgonzo 117239281Sgonzodef findObject(typename, frame): 118239281Sgonzo def getTypename(value): 119239281Sgonzo # FIXME: lldb should provide something like getBaseType 120239281Sgonzo ty = value.GetType() 121239281Sgonzo if ty.IsPointerType() or ty.IsReferenceType(): 122239281Sgonzo return ty.GetPointeeType().GetName() 123239281Sgonzo return ty.GetName() 124239281Sgonzo 125239281Sgonzo def searchForType(value, searched): 126239281Sgonzo tyname = getTypename(value) 127239281Sgonzo #print "SEARCH:", getExpressionPath(value), value.GetType().GetName() 128239281Sgonzo if tyname == typename: 129239281Sgonzo return value 130239281Sgonzo ty = value.GetType() 131239281Sgonzo if not (ty.IsPointerType() or 132310856Sloos ty.IsReferenceType() or 133310856Sloos # FIXME: lldb should provide something like getCanonicalType 134310856Sloos tyname.startswith("llvm::IntrusiveRefCntPtr<") or 135310856Sloos tyname.startswith("llvm::OwningPtr<")): 136239281Sgonzo return None 137239281Sgonzo # FIXME: Hashing for SBTypes does not seem to work correctly, uses the typename instead, 138239281Sgonzo # and not the canonical one unfortunately. 139239281Sgonzo if tyname in searched: 140239281Sgonzo return None 141239281Sgonzo searched.add(tyname) 142239281Sgonzo for i in range(value.GetNumChildren()): 143239281Sgonzo child = value.GetChildAtIndex(i, 0, False) 144239281Sgonzo found = searchForType(child, searched) 145239281Sgonzo if found: 146239281Sgonzo return found 147239281Sgonzo 148239281Sgonzo searched = set() 149239281Sgonzo value_list = frame.GetVariables(True, True, True, True) 150239281Sgonzo for val in value_list: 151239281Sgonzo found = searchForType(val, searched) 152239281Sgonzo if found: 153239281Sgonzo return found if not found.TypeIsPointerType() else found.Dereference() 154239281Sgonzo 155239281Sgonzodef getValueFromExpression(val, expr): 156239281Sgonzo return val.GetFrame().EvaluateExpression(getExpressionPath(val) + expr) 157239281Sgonzo 158239281Sgonzodef getExpressionPath(val): 159239281Sgonzo stream = lldb.SBStream() 160239281Sgonzo val.GetExpressionPath(stream) 161239281Sgonzo return stream.GetData() 162283276Sgonzo