blob: a80f0b579fbc400b245d8f9a610ee569f1deaa39 [file] [log] [blame]
Argyrios Kyrtzidise9d417d2012-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 Kyrtzidis29a67e82012-11-14 23:52:11 +000019(clang::SourceLocation) $4 = "/usr/include/i386/_types.h:37:1" (offset: 123582, file, local)
Argyrios Kyrtzidise9d417d2012-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 Kyrtzidisfc0eb2a2012-11-16 00:25:26 +000026 debugger.HandleCommand("type summary add -F ClangDataFormat.QualType_summary clang::QualType")
Argyrios Kyrtzidis1a03b262012-11-14 23:52:19 +000027 debugger.HandleCommand("type summary add -F ClangDataFormat.StringRef_summary llvm::StringRef")
Argyrios Kyrtzidise9d417d2012-11-09 22:59:01 +000028
29def SourceLocation_summary(srcloc, internal_dict):
30 return SourceLocation(srcloc).summary()
31
Argyrios Kyrtzidisfc0eb2a2012-11-16 00:25:26 +000032def QualType_summary(qualty, internal_dict):
33 return QualType(qualty).summary()
34
Argyrios Kyrtzidis1a03b262012-11-14 23:52:19 +000035def StringRef_summary(strref, internal_dict):
36 return StringRef(strref).summary()
37
Argyrios Kyrtzidise9d417d2012-11-09 22:59:01 +000038class SourceLocation(object):
39 def __init__(self, srcloc):
40 self.srcloc = srcloc
Argyrios Kyrtzidis596be932012-11-15 20:59:00 +000041 self.ID = srcloc.GetChildAtIndex(0).GetValueAsUnsigned()
Argyrios Kyrtzidise9d417d2012-11-09 22:59:01 +000042
43 def offset(self):
44 return getValueFromExpression(self.srcloc, ".getOffset()").GetValueAsUnsigned()
45
Argyrios Kyrtzidis596be932012-11-15 20:59:00 +000046 def isInvalid(self):
47 return self.ID == 0
48
Argyrios Kyrtzidise9d417d2012-11-09 22:59:01 +000049 def isMacro(self):
50 return getValueFromExpression(self.srcloc, ".isMacroID()").GetValueAsUnsigned()
51
Argyrios Kyrtzidis29a67e82012-11-14 23:52:11 +000052 def isLocal(self, srcmgr_path):
53 return lldb.frame.EvaluateExpression("(%s).isLocalSourceLocation(%s)" % (srcmgr_path, getExpressionPath(self.srcloc))).GetValueAsUnsigned()
54
Argyrios Kyrtzidise9d417d2012-11-09 22:59:01 +000055 def getPrint(self, srcmgr_path):
56 print_str = getValueFromExpression(self.srcloc, ".printToString(%s)" % srcmgr_path)
57 return print_str.GetSummary()
58
59 def summary(self):
Argyrios Kyrtzidis596be932012-11-15 20:59:00 +000060 if self.isInvalid():
61 return "<invalid loc>"
Argyrios Kyrtzidise9d417d2012-11-09 22:59:01 +000062 srcmgr_path = findObjectExpressionPath("clang::SourceManager", lldb.frame)
63 if srcmgr_path:
Argyrios Kyrtzidisfc0eb2a2012-11-16 00:25:26 +000064 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")
65 return "(offset: %d, %s)" % (self.offset(), "macro" if self.isMacro() else "file")
66
67class QualType(object):
68 def __init__(self, qualty):
69 self.qualty = qualty
70
71 def getAsString(self):
72 std_str = getValueFromExpression(self.qualty, ".getAsString()")
73 return std_str.GetSummary()
74
75 def summary(self):
76 desc = self.getAsString()
77 if desc == '"NULL TYPE"':
78 return "<NULL TYPE>"
Argyrios Kyrtzidise9d417d2012-11-09 22:59:01 +000079 return desc
80
Argyrios Kyrtzidis1a03b262012-11-14 23:52:19 +000081class StringRef(object):
82 def __init__(self, strref):
83 self.strref = strref
84 self.Data_value = strref.GetChildAtIndex(0)
85 self.Length = strref.GetChildAtIndex(1).GetValueAsUnsigned()
86
87 def summary(self):
88 if self.Length == 0:
89 return '""'
90 data = self.Data_value.GetPointeeData(0, self.Length)
91 error = lldb.SBError()
92 string = data.ReadRawData(error, 0, data.GetByteSize())
93 if error.Fail():
94 return None
95 return '"%s"' % string
96
97
Argyrios Kyrtzidise9d417d2012-11-09 22:59:01 +000098# Key is a (function address, type name) tuple, value is the expression path for
99# an object with such a type name from inside that function.
100FramePathMapCache = {}
101
Argyrios Kyrtzidise9d417d2012-11-09 22:59:01 +0000102def findObjectExpressionPath(typename, frame):
103 func_addr = frame.GetFunction().GetStartAddress().GetFileAddress()
104 key = (func_addr, typename)
105 try:
106 return FramePathMapCache[key]
107 except KeyError:
108 #print "CACHE MISS"
109 path = None
110 obj = findObject(typename, frame)
111 if obj:
112 path = getExpressionPath(obj)
113 FramePathMapCache[key] = path
114 return path
115
116def findObject(typename, frame):
117 def getTypename(value):
118 # FIXME: lldb should provide something like getBaseType
119 ty = value.GetType()
120 if ty.IsPointerType() or ty.IsReferenceType():
121 return ty.GetPointeeType().GetName()
122 return ty.GetName()
123
124 def searchForType(value, searched):
125 tyname = getTypename(value)
126 #print "SEARCH:", getExpressionPath(value), value.GetType().GetName()
127 if tyname == typename:
128 return value
129 ty = value.GetType()
130 if not (ty.IsPointerType() or
131 ty.IsReferenceType() or
132 # FIXME: lldb should provide something like getCanonicalType
133 tyname.startswith("llvm::IntrusiveRefCntPtr<") or
134 tyname.startswith("llvm::OwningPtr<")):
135 return None
136 # FIXME: Hashing for SBTypes does not seem to work correctly, uses the typename instead,
137 # and not the canonical one unfortunately.
138 if tyname in searched:
139 return None
140 searched.add(tyname)
141 for i in range(value.GetNumChildren()):
142 child = value.GetChildAtIndex(i, 0, False)
143 found = searchForType(child, searched)
144 if found:
145 return found
146
147 searched = set()
148 value_list = frame.GetVariables(True, True, True, True)
149 for val in value_list:
150 found = searchForType(val, searched)
151 if found:
152 return found if not found.TypeIsPointerType() else found.Dereference()
153
154def getValueFromExpression(val, expr):
155 return lldb.frame.EvaluateExpression(getExpressionPath(val) + expr)
156
157def getExpressionPath(val):
158 stream = lldb.SBStream()
159 val.GetExpressionPath(stream)
160 return stream.GetData()