objc_runtime.py revision 00f9ebe460fd6e9c226f4ba3f6610fbed7b0ef29
1f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata"""
2f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico GranataObjective-C runtime wrapper for use by LLDB Python formatters
3f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
4f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granatapart of The LLVM Compiler Infrastructure
5f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico GranataThis file is distributed under the University of Illinois Open Source
6f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico GranataLicense. See LICENSE.TXT for details.
7f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata"""
8b370df27c76fd875f3312be487868528121a4838Enrico Granataimport lldb
90d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granataimport lldb.formatters.cache
100d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granataimport lldb.formatters.attrib_fromdict
11f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granataimport functools
120d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granataimport lldb.formatters.Logger
13b370df27c76fd875f3312be487868528121a4838Enrico Granata
14b370df27c76fd875f3312be487868528121a4838Enrico Granataclass Utilities:
15b370df27c76fd875f3312be487868528121a4838Enrico Granata	@staticmethod
161328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata	def read_ascii(process, pointer,max_len=128):
170d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
18b370df27c76fd875f3312be487868528121a4838Enrico Granata		error = lldb.SBError()
191328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		content = None
201328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		try:
211328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			content = process.ReadCStringFromMemory(pointer,max_len,error)
221328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		except:
231328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			pass
24d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if content is None or len(content) == 0 or error.fail:
251328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			return None
261328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		return content
27b370df27c76fd875f3312be487868528121a4838Enrico Granata
28b370df27c76fd875f3312be487868528121a4838Enrico Granata	@staticmethod
29d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata	def is_valid_pointer(pointer, pointer_size, allow_tagged=0, allow_NULL=0):
300d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
31d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if pointer is None:
32d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			return 0
33b370df27c76fd875f3312be487868528121a4838Enrico Granata		if pointer == 0:
341328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			return allow_NULL
351328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		if allow_tagged and (pointer % 2) == 1:
36d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			return 1
37b370df27c76fd875f3312be487868528121a4838Enrico Granata		return ((pointer % pointer_size) == 0)
38b370df27c76fd875f3312be487868528121a4838Enrico Granata
39b370df27c76fd875f3312be487868528121a4838Enrico Granata	# Objective-C runtime has a rule that pointers in a class_t will only have bits 0 thru 46 set
40b370df27c76fd875f3312be487868528121a4838Enrico Granata	# so if any pointer has bits 47 thru 63 high we know that this is not a valid isa
41b370df27c76fd875f3312be487868528121a4838Enrico Granata	@staticmethod
42b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_allowed_pointer(pointer):
430d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
44d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if pointer is None:
45d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			return 0
461328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		return ((pointer & 0xFFFF800000000000) == 0)
47b370df27c76fd875f3312be487868528121a4838Enrico Granata
48b370df27c76fd875f3312be487868528121a4838Enrico Granata	@staticmethod
49b370df27c76fd875f3312be487868528121a4838Enrico Granata	def read_child_of(valobj,offset,type):
500d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
51d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if offset == 0 and type.GetByteSize() == valobj.GetByteSize():
52d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			return valobj.GetValueAsUnsigned()
53b370df27c76fd875f3312be487868528121a4838Enrico Granata		child = valobj.CreateChildAtOffset("childUNK",offset,type)
54d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if child is None or child.IsValid() == 0:
55b370df27c76fd875f3312be487868528121a4838Enrico Granata			return None;
56b370df27c76fd875f3312be487868528121a4838Enrico Granata		return child.GetValueAsUnsigned()
57b370df27c76fd875f3312be487868528121a4838Enrico Granata
58b370df27c76fd875f3312be487868528121a4838Enrico Granata	@staticmethod
59b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_valid_identifier(name):
600d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
61b370df27c76fd875f3312be487868528121a4838Enrico Granata		if name is None:
62b370df27c76fd875f3312be487868528121a4838Enrico Granata			return None
63b370df27c76fd875f3312be487868528121a4838Enrico Granata		if len(name) == 0:
64b370df27c76fd875f3312be487868528121a4838Enrico Granata			return None
651328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		# technically, the ObjC runtime does not enforce any rules about what name a class can have
661328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		# in practice, the commonly used byte values for a class name are the letters, digits and some
671328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		# symbols: $, %, -, _, .
681328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		# WARNING: this means that you cannot use this runtime implementation if you need to deal
691328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		# with class names that use anything but what is allowed here
701328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		ok_values = dict.fromkeys("$%_.-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890")
711328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		return all(c in ok_values for c in name)
721328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata
731328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata	@staticmethod
741328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata	def check_is_osx_lion(target):
750d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
761328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		# assume the only thing that has a Foundation.framework is a Mac
771328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		# assume anything < Lion does not even exist
783b031d93d53b509c43d592cbcdc17a862f3508b8Enrico Granata		try:
793b031d93d53b509c43d592cbcdc17a862f3508b8Enrico Granata			mod = target.module['Foundation']
803b031d93d53b509c43d592cbcdc17a862f3508b8Enrico Granata		except:
813b031d93d53b509c43d592cbcdc17a862f3508b8Enrico Granata			mod = None
82d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if mod is None or mod.IsValid() == 0:
831328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			return None
841328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		ver = mod.GetVersion()
85d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if ver is None or ver == []:
861328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			return None
871328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		return (ver[0] < 900)
88b370df27c76fd875f3312be487868528121a4838Enrico Granata
89579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	# a utility method that factors out code common to almost all the formatters
90579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	# takes in an SBValue and a metrics object
91579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	# returns a class_data and a wrapper (or None, if the runtime alone can't decide on a wrapper)
92579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	@staticmethod
93579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	def prepare_class_detection(valobj,statistics):
940d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
95579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		class_data = ObjCRuntime(valobj)
96d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if class_data.is_valid() == 0:
97579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			statistics.metric_hit('invalid_pointer',valobj)
98579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			wrapper = InvalidPointer_Description(valobj.GetValueAsUnsigned(0) == 0)
99579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return class_data,wrapper
100579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		class_data = class_data.read_class_data()
101d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if class_data.is_valid() == 0:
102579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			statistics.metric_hit('invalid_isa',valobj)
103579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			wrapper = InvalidISA_Description()
104579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return class_data,wrapper
105579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		if class_data.is_kvo():
106579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			class_data = class_data.get_superclass()
10700f9ebe460fd6e9c226f4ba3f6610fbed7b0ef29Enrico Granata		if class_data.class_name() == '_NSZombie_OriginalClass':
10800f9ebe460fd6e9c226f4ba3f6610fbed7b0ef29Enrico Granata			wrapper = ThisIsZombie_Description()
109579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return class_data,wrapper
110579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		return class_data,None
111579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
112579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
113b370df27c76fd875f3312be487868528121a4838Enrico Granataclass RoT_Data:
114b370df27c76fd875f3312be487868528121a4838Enrico Granata	def __init__(self,rot_pointer,params):
1150d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
116d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if (Utilities.is_valid_pointer(rot_pointer.GetValueAsUnsigned(),params.pointer_size, allow_tagged=0)):
117b370df27c76fd875f3312be487868528121a4838Enrico Granata			self.sys_params = params
118b370df27c76fd875f3312be487868528121a4838Enrico Granata			self.valobj = rot_pointer
1191328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			#self.flags = Utilities.read_child_of(self.valobj,0,self.sys_params.uint32_t)
120f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			#self.instanceStart = Utilities.read_child_of(self.valobj,4,self.sys_params.uint32_t)
121f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.instanceSize = None # lazy fetching
1221328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			offset = 24 if self.sys_params.is_64_bit else 16
1231328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			#self.ivarLayoutPtr = Utilities.read_child_of(self.valobj,offset,self.sys_params.addr_ptr_type)
124f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.namePointer = Utilities.read_child_of(self.valobj,offset,self.sys_params.types_cache.addr_ptr_type)
125d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 1 # self.check_valid()
126b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
1278f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - rot is invalid"
128d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
129b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.valid:
130b370df27c76fd875f3312be487868528121a4838Enrico Granata			self.name = Utilities.read_ascii(self.valobj.GetTarget().GetProcess(),self.namePointer)
131b370df27c76fd875f3312be487868528121a4838Enrico Granata			if not(Utilities.is_valid_identifier(self.name)):
1328f18240a09893310c43673901d863892ae7b0611Enrico Granata				logger >> "Marking as invalid - name is invalid"
133d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata				self.valid = 0
134b370df27c76fd875f3312be487868528121a4838Enrico Granata
135f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# perform sanity checks on the contents of this class_ro_t
136b370df27c76fd875f3312be487868528121a4838Enrico Granata	def check_valid(self):
137d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		self.valid = 1
138b370df27c76fd875f3312be487868528121a4838Enrico Granata		# misaligned pointers seem to be possible for this field
139d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		#if not(Utilities.is_valid_pointer(self.namePointer,self.sys_params.pointer_size,allow_tagged=0)):
140d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		#	self.valid = 0
141b370df27c76fd875f3312be487868528121a4838Enrico Granata		#	pass
142b370df27c76fd875f3312be487868528121a4838Enrico Granata
143b370df27c76fd875f3312be487868528121a4838Enrico Granata	def __str__(self):
1440d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
1451328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		return \
146f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		 "instanceSize = " + hex(self.instance_size()) + "\n" + \
147b370df27c76fd875f3312be487868528121a4838Enrico Granata		 "namePointer = " + hex(self.namePointer) + " --> " + self.name
148b370df27c76fd875f3312be487868528121a4838Enrico Granata
149b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_valid(self):
150b370df27c76fd875f3312be487868528121a4838Enrico Granata		return self.valid
151b370df27c76fd875f3312be487868528121a4838Enrico Granata
152d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata	def instance_size(self,align=0):
1530d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
154d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if self.is_valid() == 0:
155f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			return None
156d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if self.instanceSize is None:
157f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.instanceSize = Utilities.read_child_of(self.valobj,8,self.sys_params.types_cache.uint32_t)
158f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if align:
159d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			unalign = self.instance_size(0)
160f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			if self.sys_params.is_64_bit:
161f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata				return ((unalign + 7) & ~7) % 0x100000000
162f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			else:
163f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata				return ((unalign + 3) & ~3) % 0x100000000
164f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		else:
165f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			return self.instanceSize
166b370df27c76fd875f3312be487868528121a4838Enrico Granata
167b370df27c76fd875f3312be487868528121a4838Enrico Granataclass RwT_Data:
168b370df27c76fd875f3312be487868528121a4838Enrico Granata	def __init__(self,rwt_pointer,params):
1690d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
170d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if (Utilities.is_valid_pointer(rwt_pointer.GetValueAsUnsigned(),params.pointer_size, allow_tagged=0)):
171b370df27c76fd875f3312be487868528121a4838Enrico Granata			self.sys_params = params
172b370df27c76fd875f3312be487868528121a4838Enrico Granata			self.valobj = rwt_pointer
1731328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			#self.flags = Utilities.read_child_of(self.valobj,0,self.sys_params.uint32_t)
1741328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			#self.version = Utilities.read_child_of(self.valobj,4,self.sys_params.uint32_t)
175f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.roPointer = Utilities.read_child_of(self.valobj,8,self.sys_params.types_cache.addr_ptr_type)
176b370df27c76fd875f3312be487868528121a4838Enrico Granata			self.check_valid()
177b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
1788f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - rwt is invald"
179d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
180b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.valid:
1816bf058b8054a1152bb227d37d6fe7c6b21a14dd3Enrico Granata			self.rot = self.valobj.CreateValueFromData("rot",lldb.SBData.CreateDataFromUInt64Array(self.sys_params.endianness, self.sys_params.pointer_size, [self.roPointer]),self.sys_params.types_cache.addr_ptr_type)
1826bf058b8054a1152bb227d37d6fe7c6b21a14dd3Enrico Granata#			self.rot = self.valobj.CreateValueFromAddress("rot",self.roPointer,self.sys_params.types_cache.addr_ptr_type).AddressOf()
183b370df27c76fd875f3312be487868528121a4838Enrico Granata			self.data = RoT_Data(self.rot,self.sys_params)
184b370df27c76fd875f3312be487868528121a4838Enrico Granata
185b370df27c76fd875f3312be487868528121a4838Enrico Granata	# perform sanity checks on the contents of this class_rw_t
186b370df27c76fd875f3312be487868528121a4838Enrico Granata	def check_valid(self):
1870d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
188d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		self.valid = 1
189d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if not(Utilities.is_valid_pointer(self.roPointer,self.sys_params.pointer_size,allow_tagged=0)):
1908f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - ropointer is invalid"
191d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
192b370df27c76fd875f3312be487868528121a4838Enrico Granata
193b370df27c76fd875f3312be487868528121a4838Enrico Granata	def __str__(self):
1940d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
1951328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		return \
196b370df27c76fd875f3312be487868528121a4838Enrico Granata		 "roPointer = " + hex(self.roPointer)
197b370df27c76fd875f3312be487868528121a4838Enrico Granata
198b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_valid(self):
1990d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
200b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.valid:
201b370df27c76fd875f3312be487868528121a4838Enrico Granata			return self.data.is_valid()
202d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return 0
203b370df27c76fd875f3312be487868528121a4838Enrico Granata
204b370df27c76fd875f3312be487868528121a4838Enrico Granataclass Class_Data_V2:
205b370df27c76fd875f3312be487868528121a4838Enrico Granata	def __init__(self,isa_pointer,params):
2060d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
207d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if (isa_pointer != None) and (Utilities.is_valid_pointer(isa_pointer.GetValueAsUnsigned(),params.pointer_size, allow_tagged=0)):
208b370df27c76fd875f3312be487868528121a4838Enrico Granata			self.sys_params = params
209b370df27c76fd875f3312be487868528121a4838Enrico Granata			self.valobj = isa_pointer
210b370df27c76fd875f3312be487868528121a4838Enrico Granata			self.check_valid()
211b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
2128f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - isa is invalid or None"
213d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
214b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.valid:
2156bf058b8054a1152bb227d37d6fe7c6b21a14dd3Enrico Granata			self.rwt = self.valobj.CreateValueFromData("rwt",lldb.SBData.CreateDataFromUInt64Array(self.sys_params.endianness, self.sys_params.pointer_size, [self.dataPointer]),self.sys_params.types_cache.addr_ptr_type)
2166bf058b8054a1152bb227d37d6fe7c6b21a14dd3Enrico Granata#			self.rwt = self.valobj.CreateValueFromAddress("rwt",self.dataPointer,self.sys_params.types_cache.addr_ptr_type).AddressOf()
217b370df27c76fd875f3312be487868528121a4838Enrico Granata			self.data = RwT_Data(self.rwt,self.sys_params)
218b370df27c76fd875f3312be487868528121a4838Enrico Granata
219b370df27c76fd875f3312be487868528121a4838Enrico Granata	# perform sanity checks on the contents of this class_t
220f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# this call tries to minimize the amount of data fetched- as soon as we have "proven"
221f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# that we have an invalid object, we stop reading
222b370df27c76fd875f3312be487868528121a4838Enrico Granata	def check_valid(self):
2230d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
224d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		self.valid = 1
225ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
226f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.isaPointer = Utilities.read_child_of(self.valobj,0,self.sys_params.types_cache.addr_ptr_type)
227d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if not(Utilities.is_valid_pointer(self.isaPointer,self.sys_params.pointer_size,allow_tagged=0)):
2288f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - isaPointer is invalid"
229d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
230b370df27c76fd875f3312be487868528121a4838Enrico Granata			return
231f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if not(Utilities.is_allowed_pointer(self.isaPointer)):
2328f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - isaPointer is not allowed"
233d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
234f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			return
235f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
236f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.cachePointer = Utilities.read_child_of(self.valobj,2*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
237d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if not(Utilities.is_valid_pointer(self.cachePointer,self.sys_params.pointer_size,allow_tagged=0)):
2388f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - cachePointer is invalid"
239d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
240b370df27c76fd875f3312be487868528121a4838Enrico Granata			return
241f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if not(Utilities.is_allowed_pointer(self.cachePointer)):
2428f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - cachePointer is not allowed"
243d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
244f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			return
245f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
246f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.vtablePointer = Utilities.read_child_of(self.valobj,3*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
247d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if not(Utilities.is_valid_pointer(self.vtablePointer,self.sys_params.pointer_size,allow_tagged=0)):
2488f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - vtablePointer is invalid"
249d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
250b370df27c76fd875f3312be487868528121a4838Enrico Granata			return
251f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if not(Utilities.is_allowed_pointer(self.vtablePointer)):
2528f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - vtablePointer is not allowed"
253d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
254b370df27c76fd875f3312be487868528121a4838Enrico Granata			return
255f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
256f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.dataPointer = Utilities.read_child_of(self.valobj,4*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
257d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if not(Utilities.is_valid_pointer(self.dataPointer,self.sys_params.pointer_size,allow_tagged=0)):
2588f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - dataPointer is invalid"
259d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
260b370df27c76fd875f3312be487868528121a4838Enrico Granata			return
261f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if not(Utilities.is_allowed_pointer(self.dataPointer)):
2628f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - dataPointer is not allowed"
263d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
264b370df27c76fd875f3312be487868528121a4838Enrico Granata			return
265f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
266f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.superclassIsaPointer = Utilities.read_child_of(self.valobj,1*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
267d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if not(Utilities.is_valid_pointer(self.superclassIsaPointer,self.sys_params.pointer_size,allow_tagged=0, allow_NULL=1)):
2688f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - superclassIsa is invalid"
269d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
270b370df27c76fd875f3312be487868528121a4838Enrico Granata			return
271f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if not(Utilities.is_allowed_pointer(self.superclassIsaPointer)):
2728f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - superclassIsa is not allowed"
273d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
274b370df27c76fd875f3312be487868528121a4838Enrico Granata			return
275b370df27c76fd875f3312be487868528121a4838Enrico Granata
2761328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata	# in general, KVO is implemented by transparently subclassing
2771328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata	# however, there could be exceptions where a class does something else
2781328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata	# internally to implement the feature - this method will have no clue that a class
2791328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata	# has been KVO'ed unless the standard implementation technique is used
280b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_kvo(self):
2810d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
282b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.is_valid():
2831328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			if self.class_name().startswith("NSKVONotifying_"):
284d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata				return 1
285d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return 0
286b370df27c76fd875f3312be487868528121a4838Enrico Granata
287f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# some CF classes have a valid ObjC isa in their CFRuntimeBase
288f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# but instead of being class-specific this isa points to a match-'em-all class
289f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# which is __NSCFType (the versions without __ also exists and we are matching to it
290f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	#                      just to be on the safe side)
291f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def is_cftype(self):
2920d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
293f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if self.is_valid():
294579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return self.class_name() == '__NSCFType' or self.class_name() == 'NSCFType'
295f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
296b370df27c76fd875f3312be487868528121a4838Enrico Granata	def get_superclass(self):
2970d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
298b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.is_valid():
299b370df27c76fd875f3312be487868528121a4838Enrico Granata			parent_isa_pointer = self.valobj.CreateChildAtOffset("parent_isa",
300b370df27c76fd875f3312be487868528121a4838Enrico Granata				self.sys_params.pointer_size,
301b370df27c76fd875f3312be487868528121a4838Enrico Granata				self.sys_params.addr_ptr_type)
302b370df27c76fd875f3312be487868528121a4838Enrico Granata			return Class_Data_V2(parent_isa_pointer,self.sys_params)
303b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
304b370df27c76fd875f3312be487868528121a4838Enrico Granata			return None
305b370df27c76fd875f3312be487868528121a4838Enrico Granata
306b370df27c76fd875f3312be487868528121a4838Enrico Granata	def class_name(self):
3070d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
308b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.is_valid():
309b370df27c76fd875f3312be487868528121a4838Enrico Granata			return self.data.data.name
310b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
311b370df27c76fd875f3312be487868528121a4838Enrico Granata			return None
312b370df27c76fd875f3312be487868528121a4838Enrico Granata
313b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_valid(self):
3140d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
315b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.valid:
316b370df27c76fd875f3312be487868528121a4838Enrico Granata			return self.data.is_valid()
317d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return 0
318b370df27c76fd875f3312be487868528121a4838Enrico Granata
319b370df27c76fd875f3312be487868528121a4838Enrico Granata	def __str__(self):
3200d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
321b370df27c76fd875f3312be487868528121a4838Enrico Granata		return 'isaPointer = ' + hex(self.isaPointer) + "\n" + \
322b370df27c76fd875f3312be487868528121a4838Enrico Granata		 "superclassIsaPointer = " + hex(self.superclassIsaPointer) + "\n" + \
323b370df27c76fd875f3312be487868528121a4838Enrico Granata		 "cachePointer = " + hex(self.cachePointer) + "\n" + \
324b370df27c76fd875f3312be487868528121a4838Enrico Granata		 "vtablePointer = " + hex(self.vtablePointer) + "\n" + \
325b370df27c76fd875f3312be487868528121a4838Enrico Granata		 "data = " + hex(self.dataPointer)
326b370df27c76fd875f3312be487868528121a4838Enrico Granata
327b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_tagged(self):
328d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return 0
329b370df27c76fd875f3312be487868528121a4838Enrico Granata
330d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata	def instance_size(self,align=0):
3310d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
332d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if self.is_valid() == 0:
333e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata			return None
334f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return self.rwt.rot.instance_size(align)
335e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata
336b370df27c76fd875f3312be487868528121a4838Enrico Granata# runtime v1 is much less intricate than v2 and stores relevant information directly in the class_t object
337b370df27c76fd875f3312be487868528121a4838Enrico Granataclass Class_Data_V1:
338b370df27c76fd875f3312be487868528121a4838Enrico Granata	def __init__(self,isa_pointer,params):
3390d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
340d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if (isa_pointer != None) and (Utilities.is_valid_pointer(isa_pointer.GetValueAsUnsigned(),params.pointer_size, allow_tagged=0)):
341d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 1
342b370df27c76fd875f3312be487868528121a4838Enrico Granata			self.sys_params = params
343b370df27c76fd875f3312be487868528121a4838Enrico Granata			self.valobj = isa_pointer
344f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.check_valid()
345b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
3468f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - isaPointer is invalid or None"
347d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
348b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.valid:
349b370df27c76fd875f3312be487868528121a4838Enrico Granata			self.name = Utilities.read_ascii(self.valobj.GetTarget().GetProcess(),self.namePointer)
350b370df27c76fd875f3312be487868528121a4838Enrico Granata			if not(Utilities.is_valid_identifier(self.name)):
3518f18240a09893310c43673901d863892ae7b0611Enrico Granata				logger >> "Marking as invalid - name is not valid"
352d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata				self.valid = 0
353b370df27c76fd875f3312be487868528121a4838Enrico Granata
354b370df27c76fd875f3312be487868528121a4838Enrico Granata	# perform sanity checks on the contents of this class_t
355b370df27c76fd875f3312be487868528121a4838Enrico Granata	def check_valid(self):
3560d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
357d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		self.valid = 1
358f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
359f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.isaPointer = Utilities.read_child_of(self.valobj,0,self.sys_params.types_cache.addr_ptr_type)
360d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if not(Utilities.is_valid_pointer(self.isaPointer,self.sys_params.pointer_size,allow_tagged=0)):
3618f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - isaPointer is invalid"
362d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
363b370df27c76fd875f3312be487868528121a4838Enrico Granata			return
364f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
365f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.superclassIsaPointer = Utilities.read_child_of(self.valobj,1*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
366d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if not(Utilities.is_valid_pointer(self.superclassIsaPointer,self.sys_params.pointer_size,allow_tagged=0,allow_NULL=1)):
3678f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - superclassIsa is invalid"
368d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
3691328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			return
370b370df27c76fd875f3312be487868528121a4838Enrico Granata
371f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.namePointer = Utilities.read_child_of(self.valobj,2*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
372d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		#if not(Utilities.is_valid_pointer(self.namePointer,self.sys_params.pointer_size,allow_tagged=0,allow_NULL=0)):
373d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		#	self.valid = 0
374f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		#	return
375f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
3761328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata	# in general, KVO is implemented by transparently subclassing
3771328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata	# however, there could be exceptions where a class does something else
3781328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata	# internally to implement the feature - this method will have no clue that a class
3791328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata	# has been KVO'ed unless the standard implementation technique is used
380b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_kvo(self):
3810d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
382b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.is_valid():
3831328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			if self.class_name().startswith("NSKVONotifying_"):
384d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata				return 1
385d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return 0
386b370df27c76fd875f3312be487868528121a4838Enrico Granata
387f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# some CF classes have a valid ObjC isa in their CFRuntimeBase
388f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# but instead of being class-specific this isa points to a match-'em-all class
389f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# which is __NSCFType (the versions without __ also exists and we are matching to it
390f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	#                      just to be on the safe side)
391f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def is_cftype(self):
3920d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
393f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if self.is_valid():
394579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return self.class_name() == '__NSCFType' or self.class_name() == 'NSCFType'
395f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
396b370df27c76fd875f3312be487868528121a4838Enrico Granata	def get_superclass(self):
3970d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
398b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.is_valid():
399b370df27c76fd875f3312be487868528121a4838Enrico Granata			parent_isa_pointer = self.valobj.CreateChildAtOffset("parent_isa",
400b370df27c76fd875f3312be487868528121a4838Enrico Granata				self.sys_params.pointer_size,
401b370df27c76fd875f3312be487868528121a4838Enrico Granata				self.sys_params.addr_ptr_type)
402b370df27c76fd875f3312be487868528121a4838Enrico Granata			return Class_Data_V1(parent_isa_pointer,self.sys_params)
403b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
404b370df27c76fd875f3312be487868528121a4838Enrico Granata			return None
405b370df27c76fd875f3312be487868528121a4838Enrico Granata
406b370df27c76fd875f3312be487868528121a4838Enrico Granata	def class_name(self):
4070d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
408b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.is_valid():
409b370df27c76fd875f3312be487868528121a4838Enrico Granata			return self.name
410b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
411b370df27c76fd875f3312be487868528121a4838Enrico Granata			return None
412b370df27c76fd875f3312be487868528121a4838Enrico Granata
413b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_valid(self):
414b370df27c76fd875f3312be487868528121a4838Enrico Granata		return self.valid
415b370df27c76fd875f3312be487868528121a4838Enrico Granata
416b370df27c76fd875f3312be487868528121a4838Enrico Granata	def __str__(self):
4170d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
418b370df27c76fd875f3312be487868528121a4838Enrico Granata		return 'isaPointer = ' + hex(self.isaPointer) + "\n" + \
419b370df27c76fd875f3312be487868528121a4838Enrico Granata		 "superclassIsaPointer = " + hex(self.superclassIsaPointer) + "\n" + \
420e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata		 "namePointer = " + hex(self.namePointer) + " --> " + self.name + \
421f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		 "instanceSize = " + hex(self.instanceSize()) + "\n"
422b370df27c76fd875f3312be487868528121a4838Enrico Granata
423b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_tagged(self):
424d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return 0
425b370df27c76fd875f3312be487868528121a4838Enrico Granata
426d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata	def instance_size(self,align=0):
4270d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
428d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if self.is_valid() == 0:
429e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata			return None
430d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if self.instanceSize is None:
431f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.instanceSize = Utilities.read_child_of(self.valobj,5*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
432e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata		if align:
433d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			unalign = self.instance_size(0)
4341328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			if self.sys_params.is_64_bit:
435e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata				return ((unalign + 7) & ~7) % 0x100000000
436e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata			else:
437e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata				return ((unalign + 3) & ~3) % 0x100000000
438e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata		else:
439e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata			return self.instanceSize
440e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata
441a0e904189172b6748935e4d00bc05d21f340caaaEnrico Granata# these are the only tagged pointers values for current versions
4423069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata# of OSX - they might change in future OS releases, and no-one is
443a0e904189172b6748935e4d00bc05d21f340caaaEnrico Granata# advised to rely on these values, or any of the bitmasking formulas
444a0e904189172b6748935e4d00bc05d21f340caaaEnrico Granata# in TaggedClass_Data. doing otherwise is at your own risk
4453069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico GranataTaggedClass_Values_Lion = {1 : 'NSNumber', \
4463069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata                           5: 'NSManagedObject', \
4473069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata                           6: 'NSDate', \
4483069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata                           7: 'NSDateTS' };
4493069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico GranataTaggedClass_Values_NMOS = {0: 'NSAtom', \
4503069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata                           3 : 'NSNumber', \
4513069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata                           4: 'NSDateTS', \
4523069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata                           5: 'NSManagedObject', \
4533069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata                           6: 'NSDate' };
4541328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata
455b370df27c76fd875f3312be487868528121a4838Enrico Granataclass TaggedClass_Data:
456b370df27c76fd875f3312be487868528121a4838Enrico Granata	def __init__(self,pointer,params):
4570d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
4583069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata		global TaggedClass_Values_Lion,TaggedClass_Values_NMOS
459d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		self.valid = 1
460b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.name = None
461b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.sys_params = params
462b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj = pointer
463b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.val = (pointer & ~0x0000000000000000FF) >> 8
464b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.class_bits = (pointer & 0xE) >> 1
465b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.i_bits = (pointer & 0xF0) >> 4
466ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
4673069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata		if self.sys_params.is_lion:
4683069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata			if self.class_bits in TaggedClass_Values_Lion:
4693069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata				self.name = TaggedClass_Values_Lion[self.class_bits]
4703069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata			else:
4718f18240a09893310c43673901d863892ae7b0611Enrico Granata				logger >> "Marking as invalid - not a good tagged pointer for Lion"
472d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata				self.valid = 0
473b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
4743069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata			if self.class_bits in TaggedClass_Values_NMOS:
4753069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata				self.name = TaggedClass_Values_NMOS[self.class_bits]
4763069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata			else:
4778f18240a09893310c43673901d863892ae7b0611Enrico Granata				logger >> "Marking as invalid - not a good tagged pointer for NMOS"
478d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata				self.valid = 0
4791328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata
480b370df27c76fd875f3312be487868528121a4838Enrico Granata
481b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_valid(self):
482b370df27c76fd875f3312be487868528121a4838Enrico Granata		return self.valid
483b370df27c76fd875f3312be487868528121a4838Enrico Granata
484b370df27c76fd875f3312be487868528121a4838Enrico Granata	def class_name(self):
4850d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
486b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.is_valid():
487b370df27c76fd875f3312be487868528121a4838Enrico Granata			return self.name
488b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
489d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			return 0
490b370df27c76fd875f3312be487868528121a4838Enrico Granata
491b370df27c76fd875f3312be487868528121a4838Enrico Granata	def value(self):
492b370df27c76fd875f3312be487868528121a4838Enrico Granata		return self.val if self.is_valid() else None
493b370df27c76fd875f3312be487868528121a4838Enrico Granata
494b370df27c76fd875f3312be487868528121a4838Enrico Granata	def info_bits(self):
495b370df27c76fd875f3312be487868528121a4838Enrico Granata		return self.i_bits if self.is_valid() else None
496b370df27c76fd875f3312be487868528121a4838Enrico Granata
497b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_kvo(self):
498d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return 0
499b370df27c76fd875f3312be487868528121a4838Enrico Granata
500f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def is_cftype(self):
501d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return 0
502f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
503b370df27c76fd875f3312be487868528121a4838Enrico Granata	# we would need to go around looking for the superclass or ask the runtime
504b370df27c76fd875f3312be487868528121a4838Enrico Granata	# for now, we seem not to require support for this operation so we will merrily
505b370df27c76fd875f3312be487868528121a4838Enrico Granata	# pretend to be at a root point in the hierarchy
506b370df27c76fd875f3312be487868528121a4838Enrico Granata	def get_superclass(self):
507b370df27c76fd875f3312be487868528121a4838Enrico Granata		return None
508b370df27c76fd875f3312be487868528121a4838Enrico Granata
509b370df27c76fd875f3312be487868528121a4838Enrico Granata	# anything that is handled here is tagged
510b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_tagged(self):
511d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return 1
512b370df27c76fd875f3312be487868528121a4838Enrico Granata
513e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata	# it seems reasonable to say that a tagged pointer is the size of a pointer
514d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata	def instance_size(self,align=0):
5150d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
516d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if self.is_valid() == 0:
517e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata			return None
518f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return self.sys_params.pointer_size
519e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata
520e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata
521b370df27c76fd875f3312be487868528121a4838Enrico Granataclass InvalidClass_Data:
522b370df27c76fd875f3312be487868528121a4838Enrico Granata	def __init__(self):
523b370df27c76fd875f3312be487868528121a4838Enrico Granata		pass
524b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_valid(self):
525d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return 0
526b370df27c76fd875f3312be487868528121a4838Enrico Granata
527ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
528f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granataclass Version:
529f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def __init__(self, major, minor, release, build_string):
530f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self._major = major
531f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self._minor = minor
532f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self._release = release
533f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self._build_string = build_string
534f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
535f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def get_major(self):
536f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return self._major
537f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def get_minor(self):
538f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return self._minor
539f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def get_release(self):
540f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return self._release
541f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def get_build_string(self):
542f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return self._build_string
543f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
544f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	major = property(get_major,None)
545f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	minor = property(get_minor,None)
546f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	release = property(get_release,None)
547f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	build_string = property(get_build_string,None)
548f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
549f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def __lt__(self,other):
550f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if (self.major < other.major):
551d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			return 1
552f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if (self.minor < other.minor):
553d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			return 1
554f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if (self.release < other.release):
555d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			return 1
556f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		# build strings are not compared since they are heavily platform-dependent and might not always
557f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		# be available
558d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return 0
559f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
560f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def __eq__(self,other):
561f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return (self.major == other.major) and \
562f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		       (self.minor == other.minor) and \
563f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		       (self.release == other.release) and \
564f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		       (self.build_string == other.build_string)
565f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
566ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas	# Python 2.6 doesn't have functools.total_ordering, so we have to implement
567ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas	# other comparators
568ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas	def __gt__(self, other):
569ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas		return other < self
570ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
571ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas	def __le__(self, other):
572ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas		return not other < self
573ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
574ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas	def __ge__(self, other):
575ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas		return not self < other
576ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
577ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
5780d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granataruntime_version = lldb.formatters.cache.Cache()
5790d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granataos_version = lldb.formatters.cache.Cache()
5800d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granatatypes_caches = lldb.formatters.cache.Cache()
5810d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granataisa_caches = lldb.formatters.cache.Cache()
582b370df27c76fd875f3312be487868528121a4838Enrico Granata
583b370df27c76fd875f3312be487868528121a4838Enrico Granataclass SystemParameters:
584b370df27c76fd875f3312be487868528121a4838Enrico Granata	def __init__(self,valobj):
5850d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
586b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.adjust_for_architecture(valobj)
587f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.adjust_for_process(valobj)
588b370df27c76fd875f3312be487868528121a4838Enrico Granata
589f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def adjust_for_process(self, valobj):
5900d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
591b370df27c76fd875f3312be487868528121a4838Enrico Granata		global runtime_version
5921328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		global os_version
593f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		global types_caches
594f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		global isa_caches
595ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
596f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		process = valobj.GetTarget().GetProcess()
597f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.pid = process.GetProcessID()
598ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
599f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if runtime_version.look_for_key(self.pid):
600f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.runtime_version = runtime_version.get_value(self.pid)
601b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
602f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.runtime_version = ObjCRuntime.runtime_version(process)
603f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			runtime_version.add_item(self.pid,self.runtime_version)
604ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
605f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if os_version.look_for_key(self.pid):
606f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.is_lion = os_version.get_value(self.pid)
6071328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		else:
6081328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			self.is_lion = Utilities.check_is_osx_lion(valobj.GetTarget())
609f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			os_version.add_item(self.pid,self.is_lion)
610ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
611f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if types_caches.look_for_key(self.pid):
612f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.types_cache = types_caches.get_value(self.pid)
613f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		else:
614d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.types_cache = lldb.formatters.attrib_fromdict.AttributesDictionary(allow_reset=0)
615f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.types_cache.addr_type = valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
616f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.types_cache.addr_ptr_type = self.types_cache.addr_type.GetPointerType()
617f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.types_cache.uint32_t = valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
618f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			types_caches.add_item(self.pid,self.types_cache)
619ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
620f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if isa_caches.look_for_key(self.pid):
621f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.isa_cache = isa_caches.get_value(self.pid)
622f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		else:
6230d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata			self.isa_cache = lldb.formatters.cache.Cache()
624f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			isa_caches.add_item(self.pid,self.isa_cache)
625f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
626f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def adjust_for_architecture(self,valobj):
627f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		process = valobj.GetTarget().GetProcess()
628f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.pointer_size = process.GetAddressByteSize()
629f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.is_64_bit = (self.pointer_size == 8)
6306bf058b8054a1152bb227d37d6fe7c6b21a14dd3Enrico Granata		self.endianness = process.GetByteOrder()
6316bf058b8054a1152bb227d37d6fe7c6b21a14dd3Enrico Granata		self.is_little = (self.endianness == lldb.eByteOrderLittle)
632de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		self.cfruntime_size = 16 if self.is_64_bit else 8
633b370df27c76fd875f3312be487868528121a4838Enrico Granata
634f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# a simple helper function that makes it more explicit that one is calculating
635f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# an offset that is made up of X pointers and Y bytes of additional data
636f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# taking into account pointer size - if you know there is going to be some padding
637f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# you can pass that in and it will be taken into account (since padding may be different between
638f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# 32 and 64 bit versions, you can pass padding value for both, the right one will be used)
639f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def calculate_offset(self, num_pointers = 0, bytes_count = 0, padding32 = 0, padding64 = 0):
640f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		value = bytes_count + num_pointers*self.pointer_size
641f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return value + padding64 if self.is_64_bit else value + padding32
642b370df27c76fd875f3312be487868528121a4838Enrico Granata
643b370df27c76fd875f3312be487868528121a4838Enrico Granataclass ObjCRuntime:
644b370df27c76fd875f3312be487868528121a4838Enrico Granata
645b370df27c76fd875f3312be487868528121a4838Enrico Granata	# the ObjC runtime has no explicit "version" field that we can use
646b370df27c76fd875f3312be487868528121a4838Enrico Granata	# instead, we discriminate v1 from v2 by looking for the presence
647b370df27c76fd875f3312be487868528121a4838Enrico Granata	# of a well-known section only present in v1
648b370df27c76fd875f3312be487868528121a4838Enrico Granata	@staticmethod
649b370df27c76fd875f3312be487868528121a4838Enrico Granata	def runtime_version(process):
6500d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
651d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if process.IsValid() == 0:
6528f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "No process - bailing out"
653b370df27c76fd875f3312be487868528121a4838Enrico Granata			return None
654b370df27c76fd875f3312be487868528121a4838Enrico Granata		target = process.GetTarget()
655b370df27c76fd875f3312be487868528121a4838Enrico Granata		num_modules = target.GetNumModules()
656b370df27c76fd875f3312be487868528121a4838Enrico Granata		module_objc = None
657b370df27c76fd875f3312be487868528121a4838Enrico Granata		for idx in range(num_modules):
658b370df27c76fd875f3312be487868528121a4838Enrico Granata			module = target.GetModuleAtIndex(idx)
659b370df27c76fd875f3312be487868528121a4838Enrico Granata			if module.GetFileSpec().GetFilename() == 'libobjc.A.dylib':
660b370df27c76fd875f3312be487868528121a4838Enrico Granata				module_objc = module
661b370df27c76fd875f3312be487868528121a4838Enrico Granata				break
662d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if module_objc is None or module_objc.IsValid() == 0:
6638f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "no libobjc - bailing out"
664b370df27c76fd875f3312be487868528121a4838Enrico Granata			return None
665b370df27c76fd875f3312be487868528121a4838Enrico Granata		num_sections = module.GetNumSections()
666b370df27c76fd875f3312be487868528121a4838Enrico Granata		section_objc = None
667b370df27c76fd875f3312be487868528121a4838Enrico Granata		for idx in range(num_sections):
668b370df27c76fd875f3312be487868528121a4838Enrico Granata			section = module.GetSectionAtIndex(idx)
669b370df27c76fd875f3312be487868528121a4838Enrico Granata			if section.GetName() == '__OBJC':
670b370df27c76fd875f3312be487868528121a4838Enrico Granata				section_objc = section
671b370df27c76fd875f3312be487868528121a4838Enrico Granata				break
672b370df27c76fd875f3312be487868528121a4838Enrico Granata		if section_objc != None and section_objc.IsValid():
6738f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "found __OBJC: v1"
674b370df27c76fd875f3312be487868528121a4838Enrico Granata			return 1
6758f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger >> "no __OBJC: v2"
676b370df27c76fd875f3312be487868528121a4838Enrico Granata		return 2
677b370df27c76fd875f3312be487868528121a4838Enrico Granata
67867812172eecc4426c17b25354af072f6a4a9aad9Enrico Granata	@staticmethod
67967812172eecc4426c17b25354af072f6a4a9aad9Enrico Granata	def runtime_from_isa(isa):
6800d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
68167812172eecc4426c17b25354af072f6a4a9aad9Enrico Granata		runtime = ObjCRuntime(isa)
68267812172eecc4426c17b25354af072f6a4a9aad9Enrico Granata		runtime.isa = isa
68367812172eecc4426c17b25354af072f6a4a9aad9Enrico Granata		return runtime
68467812172eecc4426c17b25354af072f6a4a9aad9Enrico Granata
685b370df27c76fd875f3312be487868528121a4838Enrico Granata	def __init__(self,valobj):
6860d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
687b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj = valobj
688b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.adjust_for_architecture()
689b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.sys_params = SystemParameters(self.valobj)
6901328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		self.unsigned_value = self.valobj.GetValueAsUnsigned()
6911328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		self.isa_value = None
692b370df27c76fd875f3312be487868528121a4838Enrico Granata
693b370df27c76fd875f3312be487868528121a4838Enrico Granata	def adjust_for_architecture(self):
694f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		pass
695b370df27c76fd875f3312be487868528121a4838Enrico Granata
696b370df27c76fd875f3312be487868528121a4838Enrico Granata# an ObjC pointer can either be tagged or must be aligned
697b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_tagged(self):
6980d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
699b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.valobj is None:
700d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			return 0
701d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return (Utilities.is_valid_pointer(self.unsigned_value,self.sys_params.pointer_size, allow_tagged=1) and \
702d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		not(Utilities.is_valid_pointer(self.unsigned_value,self.sys_params.pointer_size, allow_tagged=0)))
703b370df27c76fd875f3312be487868528121a4838Enrico Granata
704b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_valid(self):
7050d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
706b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.valobj is None:
707d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			return 0
708d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if self.valobj.IsInScope() == 0:
709d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			return 0
710d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return Utilities.is_valid_pointer(self.unsigned_value,self.sys_params.pointer_size, allow_tagged=1)
711b370df27c76fd875f3312be487868528121a4838Enrico Granata
712579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	def is_nil(self):
713579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		return self.unsigned_value == 0
714579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
715b370df27c76fd875f3312be487868528121a4838Enrico Granata	def read_isa(self):
7160d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
7171328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		if self.isa_value != None:
7188f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "using cached isa"
7191328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			return self.isa_value
720d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		self.isa_pointer = self.valobj.CreateChildAtOffset("cfisa",
721b370df27c76fd875f3312be487868528121a4838Enrico Granata			0,
722f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.sys_params.types_cache.addr_ptr_type)
723d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if self.isa_pointer is None or self.isa_pointer.IsValid() == 0:
7248f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "invalid isa - bailing out"
725b370df27c76fd875f3312be487868528121a4838Enrico Granata			return None;
726d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		self.isa_value = self.isa_pointer.GetValueAsUnsigned(1)
727d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if self.isa_value == 1:
7288f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "invalid isa value - bailing out"
729b370df27c76fd875f3312be487868528121a4838Enrico Granata			return None;
730d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return Ellipsis
731b370df27c76fd875f3312be487868528121a4838Enrico Granata
732b370df27c76fd875f3312be487868528121a4838Enrico Granata	def read_class_data(self):
7330d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
734b370df27c76fd875f3312be487868528121a4838Enrico Granata		global isa_cache
735b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.is_tagged():
736b370df27c76fd875f3312be487868528121a4838Enrico Granata			# tagged pointers only exist in ObjC v2
737b370df27c76fd875f3312be487868528121a4838Enrico Granata			if self.sys_params.runtime_version == 2:
7388f18240a09893310c43673901d863892ae7b0611Enrico Granata				logger >> "on v2 and tagged - maybe"
739b370df27c76fd875f3312be487868528121a4838Enrico Granata				# not every odd-valued pointer is actually tagged. most are just plain wrong
740b370df27c76fd875f3312be487868528121a4838Enrico Granata				# we could try and predetect this before even creating a TaggedClass_Data object
741b370df27c76fd875f3312be487868528121a4838Enrico Granata				# but unless performance requires it, this seems a cleaner way to tackle the task
7421328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata				tentative_tagged = TaggedClass_Data(self.unsigned_value,self.sys_params)
7438f18240a09893310c43673901d863892ae7b0611Enrico Granata				if tentative_tagged.is_valid():
7448f18240a09893310c43673901d863892ae7b0611Enrico Granata					logger >> "truly tagged"
7458f18240a09893310c43673901d863892ae7b0611Enrico Granata					return tentative_tagged
7468f18240a09893310c43673901d863892ae7b0611Enrico Granata				else:
7478f18240a09893310c43673901d863892ae7b0611Enrico Granata					logger >> "not tagged - error"
7488f18240a09893310c43673901d863892ae7b0611Enrico Granata					return InvalidClass_Data()
749b370df27c76fd875f3312be487868528121a4838Enrico Granata			else:
7508f18240a09893310c43673901d863892ae7b0611Enrico Granata				logger >> "on v1 and tagged - error"
751b370df27c76fd875f3312be487868528121a4838Enrico Granata				return InvalidClass_Data()
752d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if self.is_valid() == 0 or self.read_isa() is None:
753b370df27c76fd875f3312be487868528121a4838Enrico Granata			return InvalidClass_Data()
754d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		data = self.sys_params.isa_cache.get_value(self.isa_value,default=None)
755b370df27c76fd875f3312be487868528121a4838Enrico Granata		if data != None:
756b370df27c76fd875f3312be487868528121a4838Enrico Granata			return data
757b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.sys_params.runtime_version == 2:
758d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			data = Class_Data_V2(self.isa_pointer,self.sys_params)
759b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
760d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			data = Class_Data_V1(self.isa_pointer,self.sys_params)
761d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if data is None:
762b370df27c76fd875f3312be487868528121a4838Enrico Granata			return InvalidClass_Data()
763b370df27c76fd875f3312be487868528121a4838Enrico Granata		if data.is_valid():
764d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.sys_params.isa_cache.add_item(self.isa_value,data,ok_to_replace=1)
765b370df27c76fd875f3312be487868528121a4838Enrico Granata		return data
766e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata
767579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata# these classes below can be used by the data formatters to provide a consistent message that describes a given runtime-generated situation
768579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granataclass SpecialSituation_Description:
769579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	def message(self):
770579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		return ''
771579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
772579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granataclass InvalidPointer_Description(SpecialSituation_Description):
773579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
774579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	def __init__(self,nil):
775579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		self.is_nil = nil
776579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
777579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	def message(self):
778579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		if self.is_nil:
779579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return '@"<nil>"'
780579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		else:
781579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return '<invalid pointer>'
782579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
783579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granataclass InvalidISA_Description(SpecialSituation_Description):
784579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
785579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	def __init__(self):
786579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		pass
787579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
788579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	def message(self):
789579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		return '<not an Objective-C object>'
790579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
79100f9ebe460fd6e9c226f4ba3f6610fbed7b0ef29Enrico Granataclass ThisIsZombie_Description(SpecialSituation_Description):
79200f9ebe460fd6e9c226f4ba3f6610fbed7b0ef29Enrico Granata	def message(self):
79300f9ebe460fd6e9c226f4ba3f6610fbed7b0ef29Enrico Granata		return '<freed object>'