blob: ec44d2a31b0fe2420090d692f186cc6a8c33a4ba [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
19(clang::SourceLocation) $4 = "/usr/include/i386/_types.h:37:1" (offset: 123582, file)
20"""
21
22import lldb
23
24def __lldb_init_module(debugger, internal_dict):
25 debugger.HandleCommand("type summary add -F ClangDataFormat.SourceLocation_summary clang::SourceLocation")
26
27def SourceLocation_summary(srcloc, internal_dict):
28 return SourceLocation(srcloc).summary()
29
30class SourceLocation(object):
31 def __init__(self, srcloc):
32 self.srcloc = srcloc
33
34 def offset(self):
35 return getValueFromExpression(self.srcloc, ".getOffset()").GetValueAsUnsigned()
36
37 def isMacro(self):
38 return getValueFromExpression(self.srcloc, ".isMacroID()").GetValueAsUnsigned()
39
40 def getPrint(self, srcmgr_path):
41 print_str = getValueFromExpression(self.srcloc, ".printToString(%s)" % srcmgr_path)
42 return print_str.GetSummary()
43
44 def summary(self):
45 desc = "(offset: %d, %s)" % (self.offset(), "macro" if self.isMacro() else "file")
46 srcmgr_path = findObjectExpressionPath("clang::SourceManager", lldb.frame)
47 if srcmgr_path:
48 desc = self.getPrint(srcmgr_path) + " " + desc
49 return desc
50
51# Key is a (function address, type name) tuple, value is the expression path for
52# an object with such a type name from inside that function.
53FramePathMapCache = {}
54
Argyrios Kyrtzidis32f17642012-11-09 22:59:01 +000055def findObjectExpressionPath(typename, frame):
56 func_addr = frame.GetFunction().GetStartAddress().GetFileAddress()
57 key = (func_addr, typename)
58 try:
59 return FramePathMapCache[key]
60 except KeyError:
61 #print "CACHE MISS"
62 path = None
63 obj = findObject(typename, frame)
64 if obj:
65 path = getExpressionPath(obj)
66 FramePathMapCache[key] = path
67 return path
68
69def findObject(typename, frame):
70 def getTypename(value):
71 # FIXME: lldb should provide something like getBaseType
72 ty = value.GetType()
73 if ty.IsPointerType() or ty.IsReferenceType():
74 return ty.GetPointeeType().GetName()
75 return ty.GetName()
76
77 def searchForType(value, searched):
78 tyname = getTypename(value)
79 #print "SEARCH:", getExpressionPath(value), value.GetType().GetName()
80 if tyname == typename:
81 return value
82 ty = value.GetType()
83 if not (ty.IsPointerType() or
84 ty.IsReferenceType() or
85 # FIXME: lldb should provide something like getCanonicalType
86 tyname.startswith("llvm::IntrusiveRefCntPtr<") or
87 tyname.startswith("llvm::OwningPtr<")):
88 return None
89 # FIXME: Hashing for SBTypes does not seem to work correctly, uses the typename instead,
90 # and not the canonical one unfortunately.
91 if tyname in searched:
92 return None
93 searched.add(tyname)
94 for i in range(value.GetNumChildren()):
95 child = value.GetChildAtIndex(i, 0, False)
96 found = searchForType(child, searched)
97 if found:
98 return found
99
100 searched = set()
101 value_list = frame.GetVariables(True, True, True, True)
102 for val in value_list:
103 found = searchForType(val, searched)
104 if found:
105 return found if not found.TypeIsPointerType() else found.Dereference()
106
107def getValueFromExpression(val, expr):
108 return lldb.frame.EvaluateExpression(getExpressionPath(val) + expr)
109
110def getExpressionPath(val):
111 stream = lldb.SBStream()
112 val.GetExpressionPath(stream)
113 return stream.GetData()