blob: bde38111d2d6b865e9cffe40ed50c4018d86ec7a [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
37
38 def offset(self):
39 return getValueFromExpression(self.srcloc, ".getOffset()").GetValueAsUnsigned()
40
41 def isMacro(self):
42 return getValueFromExpression(self.srcloc, ".isMacroID()").GetValueAsUnsigned()
43
Argyrios Kyrtzidisa3caaf32012-11-14 23:52:11 +000044 def isLocal(self, srcmgr_path):
45 return lldb.frame.EvaluateExpression("(%s).isLocalSourceLocation(%s)" % (srcmgr_path, getExpressionPath(self.srcloc))).GetValueAsUnsigned()
46
Argyrios Kyrtzidis32f17642012-11-09 22:59:01 +000047 def getPrint(self, srcmgr_path):
48 print_str = getValueFromExpression(self.srcloc, ".printToString(%s)" % srcmgr_path)
49 return print_str.GetSummary()
50
51 def summary(self):
52 desc = "(offset: %d, %s)" % (self.offset(), "macro" if self.isMacro() else "file")
53 srcmgr_path = findObjectExpressionPath("clang::SourceManager", lldb.frame)
54 if srcmgr_path:
Argyrios Kyrtzidisa3caaf32012-11-14 23:52:11 +000055 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 +000056 return desc
57
Argyrios Kyrtzidisa19a1262012-11-14 23:52:19 +000058class StringRef(object):
59 def __init__(self, strref):
60 self.strref = strref
61 self.Data_value = strref.GetChildAtIndex(0)
62 self.Length = strref.GetChildAtIndex(1).GetValueAsUnsigned()
63
64 def summary(self):
65 if self.Length == 0:
66 return '""'
67 data = self.Data_value.GetPointeeData(0, self.Length)
68 error = lldb.SBError()
69 string = data.ReadRawData(error, 0, data.GetByteSize())
70 if error.Fail():
71 return None
72 return '"%s"' % string
73
74
Argyrios Kyrtzidis32f17642012-11-09 22:59:01 +000075# Key is a (function address, type name) tuple, value is the expression path for
76# an object with such a type name from inside that function.
77FramePathMapCache = {}
78
Argyrios Kyrtzidis32f17642012-11-09 22:59:01 +000079def findObjectExpressionPath(typename, frame):
80 func_addr = frame.GetFunction().GetStartAddress().GetFileAddress()
81 key = (func_addr, typename)
82 try:
83 return FramePathMapCache[key]
84 except KeyError:
85 #print "CACHE MISS"
86 path = None
87 obj = findObject(typename, frame)
88 if obj:
89 path = getExpressionPath(obj)
90 FramePathMapCache[key] = path
91 return path
92
93def findObject(typename, frame):
94 def getTypename(value):
95 # FIXME: lldb should provide something like getBaseType
96 ty = value.GetType()
97 if ty.IsPointerType() or ty.IsReferenceType():
98 return ty.GetPointeeType().GetName()
99 return ty.GetName()
100
101 def searchForType(value, searched):
102 tyname = getTypename(value)
103 #print "SEARCH:", getExpressionPath(value), value.GetType().GetName()
104 if tyname == typename:
105 return value
106 ty = value.GetType()
107 if not (ty.IsPointerType() or
108 ty.IsReferenceType() or
109 # FIXME: lldb should provide something like getCanonicalType
110 tyname.startswith("llvm::IntrusiveRefCntPtr<") or
111 tyname.startswith("llvm::OwningPtr<")):
112 return None
113 # FIXME: Hashing for SBTypes does not seem to work correctly, uses the typename instead,
114 # and not the canonical one unfortunately.
115 if tyname in searched:
116 return None
117 searched.add(tyname)
118 for i in range(value.GetNumChildren()):
119 child = value.GetChildAtIndex(i, 0, False)
120 found = searchForType(child, searched)
121 if found:
122 return found
123
124 searched = set()
125 value_list = frame.GetVariables(True, True, True, True)
126 for val in value_list:
127 found = searchForType(val, searched)
128 if found:
129 return found if not found.TypeIsPointerType() else found.Dereference()
130
131def getValueFromExpression(val, expr):
132 return lldb.frame.EvaluateExpression(getExpressionPath(val) + expr)
133
134def getExpressionPath(val):
135 stream = lldb.SBStream()
136 val.GetExpressionPath(stream)
137 return stream.GetData()