1e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis"""lldb data formatters for clang classes.
2e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis
3e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios KyrtzidisUsage
4e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis--
5e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidisimport this file in your ~/.lldbinit by adding this line:
6e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis
7e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidiscommand script import /path/to/ClangDataFormat.py
8e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis
9e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios KyrtzidisAfter that, instead of getting this:
10e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis
11e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis(lldb) p Tok.Loc
12e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis(clang::SourceLocation) $0 = {
13e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis  (unsigned int) ID = 123582
14e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis}
15e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis
16e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidisyou'll get:
17e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis
18e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis(lldb) p Tok.Loc
1929a67e8f3adbd433acf271f7be699c50ceb7bdefArgyrios Kyrtzidis(clang::SourceLocation) $4 = "/usr/include/i386/_types.h:37:1" (offset: 123582, file, local)
20e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis"""
21e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis
22e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidisimport lldb
23e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis
24e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidisdef __lldb_init_module(debugger, internal_dict):
25e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis	debugger.HandleCommand("type summary add -F ClangDataFormat.SourceLocation_summary clang::SourceLocation")
26fc0eb2a77b3b48f4f7f9338b158fa913cda0f774Argyrios Kyrtzidis	debugger.HandleCommand("type summary add -F ClangDataFormat.QualType_summary clang::QualType")
271a03b262d0f07d4a3091b0a9b7310100d9bd0aa9Argyrios Kyrtzidis	debugger.HandleCommand("type summary add -F ClangDataFormat.StringRef_summary llvm::StringRef")
28e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis
29e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidisdef SourceLocation_summary(srcloc, internal_dict):
30e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis	return SourceLocation(srcloc).summary()
31e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis
32fc0eb2a77b3b48f4f7f9338b158fa913cda0f774Argyrios Kyrtzidisdef QualType_summary(qualty, internal_dict):
33fc0eb2a77b3b48f4f7f9338b158fa913cda0f774Argyrios Kyrtzidis	return QualType(qualty).summary()
34fc0eb2a77b3b48f4f7f9338b158fa913cda0f774Argyrios Kyrtzidis
351a03b262d0f07d4a3091b0a9b7310100d9bd0aa9Argyrios Kyrtzidisdef StringRef_summary(strref, internal_dict):
361a03b262d0f07d4a3091b0a9b7310100d9bd0aa9Argyrios Kyrtzidis	return StringRef(strref).summary()
371a03b262d0f07d4a3091b0a9b7310100d9bd0aa9Argyrios Kyrtzidis
38e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidisclass SourceLocation(object):
39e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis	def __init__(self, srcloc):
40e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		self.srcloc = srcloc
41596be9372b79842b74c0654ab3dab33200812e8aArgyrios Kyrtzidis		self.ID = srcloc.GetChildAtIndex(0).GetValueAsUnsigned()
4234983d5f8fbdced8f38d61a933ce32aff3e0886cArgyrios Kyrtzidis		self.frame = srcloc.GetFrame()
43e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis
44e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis	def offset(self):
45e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		return getValueFromExpression(self.srcloc, ".getOffset()").GetValueAsUnsigned()
46e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis
47596be9372b79842b74c0654ab3dab33200812e8aArgyrios Kyrtzidis	def isInvalid(self):
48596be9372b79842b74c0654ab3dab33200812e8aArgyrios Kyrtzidis		return self.ID == 0
49596be9372b79842b74c0654ab3dab33200812e8aArgyrios Kyrtzidis
50e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis	def isMacro(self):
51e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		return getValueFromExpression(self.srcloc, ".isMacroID()").GetValueAsUnsigned()
52e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis
5329a67e8f3adbd433acf271f7be699c50ceb7bdefArgyrios Kyrtzidis	def isLocal(self, srcmgr_path):
5434983d5f8fbdced8f38d61a933ce32aff3e0886cArgyrios Kyrtzidis		return self.frame.EvaluateExpression("(%s).isLocalSourceLocation(%s)" % (srcmgr_path, getExpressionPath(self.srcloc))).GetValueAsUnsigned()
5529a67e8f3adbd433acf271f7be699c50ceb7bdefArgyrios Kyrtzidis
56e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis	def getPrint(self, srcmgr_path):
57e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		print_str = getValueFromExpression(self.srcloc, ".printToString(%s)" % srcmgr_path)
58e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		return print_str.GetSummary()
59e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis
60e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis	def summary(self):
61596be9372b79842b74c0654ab3dab33200812e8aArgyrios Kyrtzidis		if self.isInvalid():
62596be9372b79842b74c0654ab3dab33200812e8aArgyrios Kyrtzidis			return "<invalid loc>"
6334983d5f8fbdced8f38d61a933ce32aff3e0886cArgyrios Kyrtzidis		srcmgr_path = findObjectExpressionPath("clang::SourceManager", self.frame)
64e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		if srcmgr_path:
65fc0eb2a77b3b48f4f7f9338b158fa913cda0f774Argyrios Kyrtzidis			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")
66fc0eb2a77b3b48f4f7f9338b158fa913cda0f774Argyrios Kyrtzidis		return "(offset: %d, %s)" % (self.offset(), "macro" if self.isMacro() else "file")
67fc0eb2a77b3b48f4f7f9338b158fa913cda0f774Argyrios Kyrtzidis
68fc0eb2a77b3b48f4f7f9338b158fa913cda0f774Argyrios Kyrtzidisclass QualType(object):
69fc0eb2a77b3b48f4f7f9338b158fa913cda0f774Argyrios Kyrtzidis	def __init__(self, qualty):
70fc0eb2a77b3b48f4f7f9338b158fa913cda0f774Argyrios Kyrtzidis		self.qualty = qualty
71fc0eb2a77b3b48f4f7f9338b158fa913cda0f774Argyrios Kyrtzidis
72fc0eb2a77b3b48f4f7f9338b158fa913cda0f774Argyrios Kyrtzidis	def getAsString(self):
73fc0eb2a77b3b48f4f7f9338b158fa913cda0f774Argyrios Kyrtzidis		std_str = getValueFromExpression(self.qualty, ".getAsString()")
74fc0eb2a77b3b48f4f7f9338b158fa913cda0f774Argyrios Kyrtzidis		return std_str.GetSummary()
75fc0eb2a77b3b48f4f7f9338b158fa913cda0f774Argyrios Kyrtzidis
76fc0eb2a77b3b48f4f7f9338b158fa913cda0f774Argyrios Kyrtzidis	def summary(self):
77fc0eb2a77b3b48f4f7f9338b158fa913cda0f774Argyrios Kyrtzidis		desc = self.getAsString()
78fc0eb2a77b3b48f4f7f9338b158fa913cda0f774Argyrios Kyrtzidis		if desc == '"NULL TYPE"':
79fc0eb2a77b3b48f4f7f9338b158fa913cda0f774Argyrios Kyrtzidis			return "<NULL TYPE>"
80e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		return desc
81e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis
821a03b262d0f07d4a3091b0a9b7310100d9bd0aa9Argyrios Kyrtzidisclass StringRef(object):
831a03b262d0f07d4a3091b0a9b7310100d9bd0aa9Argyrios Kyrtzidis	def __init__(self, strref):
841a03b262d0f07d4a3091b0a9b7310100d9bd0aa9Argyrios Kyrtzidis		self.strref = strref
851a03b262d0f07d4a3091b0a9b7310100d9bd0aa9Argyrios Kyrtzidis		self.Data_value = strref.GetChildAtIndex(0)
861a03b262d0f07d4a3091b0a9b7310100d9bd0aa9Argyrios Kyrtzidis		self.Length = strref.GetChildAtIndex(1).GetValueAsUnsigned()
871a03b262d0f07d4a3091b0a9b7310100d9bd0aa9Argyrios Kyrtzidis
881a03b262d0f07d4a3091b0a9b7310100d9bd0aa9Argyrios Kyrtzidis	def summary(self):
891a03b262d0f07d4a3091b0a9b7310100d9bd0aa9Argyrios Kyrtzidis		if self.Length == 0:
901a03b262d0f07d4a3091b0a9b7310100d9bd0aa9Argyrios Kyrtzidis			return '""'
911a03b262d0f07d4a3091b0a9b7310100d9bd0aa9Argyrios Kyrtzidis		data = self.Data_value.GetPointeeData(0, self.Length)
921a03b262d0f07d4a3091b0a9b7310100d9bd0aa9Argyrios Kyrtzidis		error = lldb.SBError()
931a03b262d0f07d4a3091b0a9b7310100d9bd0aa9Argyrios Kyrtzidis		string = data.ReadRawData(error, 0, data.GetByteSize())
941a03b262d0f07d4a3091b0a9b7310100d9bd0aa9Argyrios Kyrtzidis		if error.Fail():
951a03b262d0f07d4a3091b0a9b7310100d9bd0aa9Argyrios Kyrtzidis			return None
961a03b262d0f07d4a3091b0a9b7310100d9bd0aa9Argyrios Kyrtzidis		return '"%s"' % string
971a03b262d0f07d4a3091b0a9b7310100d9bd0aa9Argyrios Kyrtzidis
981a03b262d0f07d4a3091b0a9b7310100d9bd0aa9Argyrios Kyrtzidis
99e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis# Key is a (function address, type name) tuple, value is the expression path for
100e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis# an object with such a type name from inside that function.
101e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios KyrtzidisFramePathMapCache = {}
102e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis
103e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidisdef findObjectExpressionPath(typename, frame):
104e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis	func_addr = frame.GetFunction().GetStartAddress().GetFileAddress()
105e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis	key = (func_addr, typename)
106e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis	try:
107e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		return FramePathMapCache[key]
108e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis	except KeyError:
109e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		#print "CACHE MISS"
110e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		path = None
111e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		obj = findObject(typename, frame)
112e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		if obj:
113e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis			path = getExpressionPath(obj)
114e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		FramePathMapCache[key] = path
115e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		return path
116e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis
117e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidisdef findObject(typename, frame):
118e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis	def getTypename(value):
119e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		# FIXME: lldb should provide something like getBaseType
120e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		ty = value.GetType()
121e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		if ty.IsPointerType() or ty.IsReferenceType():
122e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis			return ty.GetPointeeType().GetName()
123e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		return ty.GetName()
124e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis
125e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis	def searchForType(value, searched):
126e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		tyname = getTypename(value)
127e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		#print "SEARCH:", getExpressionPath(value), value.GetType().GetName()
128e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		if tyname == typename:
129e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis			return value
130e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		ty = value.GetType()
131e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		if not (ty.IsPointerType() or
132e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		        ty.IsReferenceType() or
133e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis				# FIXME: lldb should provide something like getCanonicalType
134e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		        tyname.startswith("llvm::IntrusiveRefCntPtr<") or
135e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		        tyname.startswith("llvm::OwningPtr<")):
136e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis			return None
137e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		# FIXME: Hashing for SBTypes does not seem to work correctly, uses the typename instead,
138e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		# and not the canonical one unfortunately.
139e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		if tyname in searched:
140e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis			return None
141e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		searched.add(tyname)
142e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		for i in range(value.GetNumChildren()):
143e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis			child = value.GetChildAtIndex(i, 0, False)
144e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis			found = searchForType(child, searched)
145e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis			if found:
146e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis				return found
147e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis
148e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis	searched = set()
149e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis	value_list = frame.GetVariables(True, True, True, True)
150e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis	for val in value_list:
151e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		found = searchForType(val, searched)
152e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis		if found:
153e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis			return found if not found.TypeIsPointerType() else found.Dereference()
154e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis
155e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidisdef getValueFromExpression(val, expr):
15634983d5f8fbdced8f38d61a933ce32aff3e0886cArgyrios Kyrtzidis	return val.GetFrame().EvaluateExpression(getExpressionPath(val) + expr)
157e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis
158e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidisdef getExpressionPath(val):
159e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis	stream = lldb.SBStream()
160e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis	val.GetExpressionPath(stream)
161e9d417d9fcefc50dfb75388cdc641cf8894cdd71Argyrios Kyrtzidis	return stream.GetData()
162