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