blob: 23aaba22119b4a328d4b8082dcc94f19df3c5366 [file] [log] [blame]
Argyrios Kyrtzidis32f17642012-11-09 22:59:01 +00001"""lldb data formatters for clang classes.
2
3Usage
4--
5import this file in your ~/.lldbinit by adding this line:
6
7command script import /path/to/ClangDataFormat.py
8
9After that, instead of getting this:
10
11(lldb) p Tok.Loc
12(clang::SourceLocation) $0 = {
13 (unsigned int) ID = 123582
14}
15
16you'll get:
17
18(lldb) p Tok.Loc
Argyrios Kyrtzidisa3caaf32012-11-14 23:52:11 +000019(clang::SourceLocation) $4 = "/usr/include/i386/_types.h:37:1" (offset: 123582, file, local)
Argyrios Kyrtzidis32f17642012-11-09 22:59:01 +000020"""
21
22import lldb
23
24def __lldb_init_module(debugger, internal_dict):
25 debugger.HandleCommand("type summary add -F ClangDataFormat.SourceLocation_summary clang::SourceLocation")
Argyrios Kyrtzidisa19a1262012-11-14 23:52:19 +000026 debugger.HandleCommand("type summary add -F ClangDataFormat.StringRef_summary llvm::StringRef")
Argyrios Kyrtzidis32f17642012-11-09 22:59:01 +000027
28def SourceLocation_summary(srcloc, internal_dict):
29 return SourceLocation(srcloc).summary()
30
Argyrios Kyrtzidisa19a1262012-11-14 23:52:19 +000031def StringRef_summary(strref, internal_dict):
32 return StringRef(strref).summary()
33
Argyrios Kyrtzidis32f17642012-11-09 22:59:01 +000034class SourceLocation(object):
35 def __init__(self, srcloc):
36 self.srcloc = srcloc
Argyrios Kyrtzidisec1594a2012-11-15 20:59:00 +000037 self.ID = srcloc.GetChildAtIndex(0).GetValueAsUnsigned()
Argyrios Kyrtzidis32f17642012-11-09 22:59:01 +000038
39 def offset(self):
40 return getValueFromExpression(self.srcloc, ".getOffset()").GetValueAsUnsigned()
41
Argyrios Kyrtzidisec1594a2012-11-15 20:59:00 +000042 def isInvalid(self):
43 return self.ID == 0
44
Argyrios Kyrtzidis32f17642012-11-09 22:59:01 +000045 def isMacro(self):
46 return getValueFromExpression(self.srcloc, ".isMacroID()").GetValueAsUnsigned()
47
Argyrios Kyrtzidisa3caaf32012-11-14 23:52:11 +000048 def isLocal(self, srcmgr_path):
49 return lldb.frame.EvaluateExpression("(%s).isLocalSourceLocation(%s)" % (srcmgr_path, getExpressionPath(self.srcloc))).GetValueAsUnsigned()
50
Argyrios Kyrtzidis32f17642012-11-09 22:59:01 +000051 def getPrint(self, srcmgr_path):
52 print_str = getValueFromExpression(self.srcloc, ".printToString(%s)" % srcmgr_path)
53 return print_str.GetSummary()
54
55 def summary(self):
Argyrios Kyrtzidisec1594a2012-11-15 20:59:00 +000056 if self.isInvalid():
57 return "<invalid loc>"
Argyrios Kyrtzidis32f17642012-11-09 22:59:01 +000058 desc = "(offset: %d, %s)" % (self.offset(), "macro" if self.isMacro() else "file")
59 srcmgr_path = findObjectExpressionPath("clang::SourceManager", lldb.frame)
60 if srcmgr_path:
Argyrios Kyrtzidisa3caaf32012-11-14 23:52:11 +000061 desc = "%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")
Argyrios Kyrtzidis32f17642012-11-09 22:59:01 +000062 return desc
63
Argyrios Kyrtzidisa19a1262012-11-14 23:52:19 +000064class StringRef(object):
65 def __init__(self, strref):
66 self.strref = strref
67 self.Data_value = strref.GetChildAtIndex(0)
68 self.Length = strref.GetChildAtIndex(1).GetValueAsUnsigned()
69
70 def summary(self):
71 if self.Length == 0:
72 return '""'
73 data = self.Data_value.GetPointeeData(0, self.Length)
74 error = lldb.SBError()
75 string = data.ReadRawData(error, 0, data.GetByteSize())
76 if error.Fail():
77 return None
78 return '"%s"' % string
79
80
Argyrios Kyrtzidis32f17642012-11-09 22:59:01 +000081# Key is a (function address, type name) tuple, value is the expression path for
82# an object with such a type name from inside that function.
83FramePathMapCache = {}
84
Argyrios Kyrtzidis32f17642012-11-09 22:59:01 +000085def findObjectExpressionPath(typename, frame):
86 func_addr = frame.GetFunction().GetStartAddress().GetFileAddress()
87 key = (func_addr, typename)
88 try:
89 return FramePathMapCache[key]
90 except KeyError:
91 #print "CACHE MISS"
92 path = None
93 obj = findObject(typename, frame)
94 if obj:
95 path = getExpressionPath(obj)
96 FramePathMapCache[key] = path
97 return path
98
99def findObject(typename, frame):
100 def getTypename(value):
101 # FIXME: lldb should provide something like getBaseType
102 ty = value.GetType()
103 if ty.IsPointerType() or ty.IsReferenceType():
104 return ty.GetPointeeType().GetName()
105 return ty.GetName()
106
107 def searchForType(value, searched):
108 tyname = getTypename(value)
109 #print "SEARCH:", getExpressionPath(value), value.GetType().GetName()
110 if tyname == typename:
111 return value
112 ty = value.GetType()
113 if not (ty.IsPointerType() or
114 ty.IsReferenceType() or
115 # FIXME: lldb should provide something like getCanonicalType
116 tyname.startswith("llvm::IntrusiveRefCntPtr<") or
117 tyname.startswith("llvm::OwningPtr<")):
118 return None
119 # FIXME: Hashing for SBTypes does not seem to work correctly, uses the typename instead,
120 # and not the canonical one unfortunately.
121 if tyname in searched:
122 return None
123 searched.add(tyname)
124 for i in range(value.GetNumChildren()):
125 child = value.GetChildAtIndex(i, 0, False)
126 found = searchForType(child, searched)
127 if found:
128 return found
129
130 searched = set()
131 value_list = frame.GetVariables(True, True, True, True)
132 for val in value_list:
133 found = searchForType(val, searched)
134 if found:
135 return found if not found.TypeIsPointerType() else found.Dereference()
136
137def getValueFromExpression(val, expr):
138 return lldb.frame.EvaluateExpression(getExpressionPath(val) + expr)
139
140def getExpressionPath(val):
141 stream = lldb.SBStream()
142 val.GetExpressionPath(stream)
143 return stream.GetData()