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