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