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