forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			162 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			162 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Python
		
	
	
	
| """lldb data formatters for clang classes.
 | |
| 
 | |
| Usage
 | |
| --
 | |
| import this file in your ~/.lldbinit by adding this line:
 | |
| 
 | |
| command script import /path/to/ClangDataFormat.py
 | |
| 
 | |
| After that, instead of getting this:
 | |
| 
 | |
| (lldb) p Tok.Loc
 | |
| (clang::SourceLocation) $0 = {
 | |
|   (unsigned int) ID = 123582
 | |
| }
 | |
| 
 | |
| you'll get:
 | |
| 
 | |
| (lldb) p Tok.Loc
 | |
| (clang::SourceLocation) $4 = "/usr/include/i386/_types.h:37:1" (offset: 123582, file, local)
 | |
| """
 | |
| 
 | |
| import lldb
 | |
| 
 | |
| def __lldb_init_module(debugger, internal_dict):
 | |
| 	debugger.HandleCommand("type summary add -F ClangDataFormat.SourceLocation_summary clang::SourceLocation")
 | |
| 	debugger.HandleCommand("type summary add -F ClangDataFormat.QualType_summary clang::QualType")
 | |
| 	debugger.HandleCommand("type summary add -F ClangDataFormat.StringRef_summary llvm::StringRef")
 | |
| 
 | |
| def SourceLocation_summary(srcloc, internal_dict):
 | |
| 	return SourceLocation(srcloc).summary()
 | |
| 
 | |
| def QualType_summary(qualty, internal_dict):
 | |
| 	return QualType(qualty).summary()
 | |
| 
 | |
| def StringRef_summary(strref, internal_dict):
 | |
| 	return StringRef(strref).summary()
 | |
| 
 | |
| class SourceLocation(object):
 | |
| 	def __init__(self, srcloc):
 | |
| 		self.srcloc = srcloc
 | |
| 		self.ID = srcloc.GetChildAtIndex(0).GetValueAsUnsigned()
 | |
| 		self.frame = srcloc.GetFrame()
 | |
| 	
 | |
| 	def offset(self):
 | |
| 		return getValueFromExpression(self.srcloc, ".getOffset()").GetValueAsUnsigned()
 | |
| 
 | |
| 	def isInvalid(self):
 | |
| 		return self.ID == 0
 | |
| 
 | |
| 	def isMacro(self):
 | |
| 		return getValueFromExpression(self.srcloc, ".isMacroID()").GetValueAsUnsigned()
 | |
| 
 | |
| 	def isLocal(self, srcmgr_path):
 | |
| 		return self.frame.EvaluateExpression("(%s).isLocalSourceLocation(%s)" % (srcmgr_path, getExpressionPath(self.srcloc))).GetValueAsUnsigned()
 | |
| 
 | |
| 	def getPrint(self, srcmgr_path):
 | |
| 		print_str = getValueFromExpression(self.srcloc, ".printToString(%s)" % srcmgr_path)
 | |
| 		return print_str.GetSummary()
 | |
| 
 | |
| 	def summary(self):
 | |
| 		if self.isInvalid():
 | |
| 			return "<invalid loc>"
 | |
| 		srcmgr_path = findObjectExpressionPath("clang::SourceManager", self.frame)
 | |
| 		if srcmgr_path:
 | |
| 			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")
 | |
| 		return "(offset: %d, %s)" % (self.offset(), "macro" if self.isMacro() else "file")
 | |
| 
 | |
| class QualType(object):
 | |
| 	def __init__(self, qualty):
 | |
| 		self.qualty = qualty
 | |
| 
 | |
| 	def getAsString(self):
 | |
| 		std_str = getValueFromExpression(self.qualty, ".getAsString()")
 | |
| 		return std_str.GetSummary()
 | |
| 
 | |
| 	def summary(self):
 | |
| 		desc = self.getAsString()
 | |
| 		if desc == '"NULL TYPE"':
 | |
| 			return "<NULL TYPE>"
 | |
| 		return desc
 | |
| 
 | |
| class StringRef(object):
 | |
| 	def __init__(self, strref):
 | |
| 		self.strref = strref
 | |
| 		self.Data_value = strref.GetChildAtIndex(0)
 | |
| 		self.Length = strref.GetChildAtIndex(1).GetValueAsUnsigned()
 | |
| 
 | |
| 	def summary(self):
 | |
| 		if self.Length == 0:
 | |
| 			return '""'
 | |
| 		data = self.Data_value.GetPointeeData(0, self.Length)
 | |
| 		error = lldb.SBError()
 | |
| 		string = data.ReadRawData(error, 0, data.GetByteSize())
 | |
| 		if error.Fail():
 | |
| 			return None
 | |
| 		return '"%s"' % string
 | |
| 
 | |
| 
 | |
| # Key is a (function address, type name) tuple, value is the expression path for
 | |
| # an object with such a type name from inside that function.
 | |
| FramePathMapCache = {}
 | |
| 
 | |
| def findObjectExpressionPath(typename, frame):
 | |
| 	func_addr = frame.GetFunction().GetStartAddress().GetFileAddress()
 | |
| 	key = (func_addr, typename)
 | |
| 	try:
 | |
| 		return FramePathMapCache[key]
 | |
| 	except KeyError:
 | |
| 		#print "CACHE MISS"
 | |
| 		path = None
 | |
| 		obj = findObject(typename, frame)
 | |
| 		if obj:
 | |
| 			path = getExpressionPath(obj)
 | |
| 		FramePathMapCache[key] = path
 | |
| 		return path
 | |
| 
 | |
| def findObject(typename, frame):
 | |
| 	def getTypename(value):
 | |
| 		# FIXME: lldb should provide something like getBaseType
 | |
| 		ty = value.GetType()
 | |
| 		if ty.IsPointerType() or ty.IsReferenceType():
 | |
| 			return ty.GetPointeeType().GetName()
 | |
| 		return ty.GetName()
 | |
| 
 | |
| 	def searchForType(value, searched):
 | |
| 		tyname = getTypename(value)
 | |
| 		#print "SEARCH:", getExpressionPath(value), value.GetType().GetName()
 | |
| 		if tyname == typename:
 | |
| 			return value
 | |
| 		ty = value.GetType()
 | |
| 		if not (ty.IsPointerType() or
 | |
| 		        ty.IsReferenceType() or
 | |
| 				# FIXME: lldb should provide something like getCanonicalType
 | |
| 		        tyname.startswith("llvm::IntrusiveRefCntPtr<") or
 | |
| 		        tyname.startswith("llvm::OwningPtr<")):
 | |
| 			return None
 | |
| 		# FIXME: Hashing for SBTypes does not seem to work correctly, uses the typename instead,
 | |
| 		# and not the canonical one unfortunately.
 | |
| 		if tyname in searched:
 | |
| 			return None
 | |
| 		searched.add(tyname)
 | |
| 		for i in range(value.GetNumChildren()):
 | |
| 			child = value.GetChildAtIndex(i, 0, False)
 | |
| 			found = searchForType(child, searched)
 | |
| 			if found:
 | |
| 				return found
 | |
| 
 | |
| 	searched = set()
 | |
| 	value_list = frame.GetVariables(True, True, True, True)
 | |
| 	for val in value_list:
 | |
| 		found = searchForType(val, searched)
 | |
| 		if found:
 | |
| 			return found if not found.TypeIsPointerType() else found.Dereference()
 | |
| 
 | |
| def getValueFromExpression(val, expr):
 | |
| 	return val.GetFrame().EvaluateExpression(getExpressionPath(val) + expr)
 | |
| 
 | |
| def getExpressionPath(val):
 | |
| 	stream = lldb.SBStream()
 | |
| 	val.GetExpressionPath(stream)
 | |
| 	return stream.GetData()
 |