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		self.dataPointer = Utilities.read_child_of(self.valobj,4*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
246d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if not(Utilities.is_valid_pointer(self.dataPointer,self.sys_params.pointer_size,allow_tagged=0)):
2478f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - dataPointer is invalid"
248d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
249b370df27c76fd875f3312be487868528121a4838Enrico Granata			return
250f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if not(Utilities.is_allowed_pointer(self.dataPointer)):
2518f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - dataPointer is not allowed"
252d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
253b370df27c76fd875f3312be487868528121a4838Enrico Granata			return
254f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
255f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.superclassIsaPointer = Utilities.read_child_of(self.valobj,1*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
256d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if not(Utilities.is_valid_pointer(self.superclassIsaPointer,self.sys_params.pointer_size,allow_tagged=0, allow_NULL=1)):
2578f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - superclassIsa is invalid"
258d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
259b370df27c76fd875f3312be487868528121a4838Enrico Granata			return
260f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if not(Utilities.is_allowed_pointer(self.superclassIsaPointer)):
2618f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - superclassIsa is not allowed"
262d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
263b370df27c76fd875f3312be487868528121a4838Enrico Granata			return
264b370df27c76fd875f3312be487868528121a4838Enrico Granata
2651328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata	# in general, KVO is implemented by transparently subclassing
2661328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata	# however, there could be exceptions where a class does something else
2671328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata	# internally to implement the feature - this method will have no clue that a class
2681328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata	# has been KVO'ed unless the standard implementation technique is used
269b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_kvo(self):
2700d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
271b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.is_valid():
2721328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			if self.class_name().startswith("NSKVONotifying_"):
273d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata				return 1
274d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return 0
275b370df27c76fd875f3312be487868528121a4838Enrico Granata
276f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# some CF classes have a valid ObjC isa in their CFRuntimeBase
277f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# but instead of being class-specific this isa points to a match-'em-all class
278f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# which is __NSCFType (the versions without __ also exists and we are matching to it
279f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	#                      just to be on the safe side)
280f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def is_cftype(self):
2810d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
282f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if self.is_valid():
283579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return self.class_name() == '__NSCFType' or self.class_name() == 'NSCFType'
284f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
285b370df27c76fd875f3312be487868528121a4838Enrico Granata	def get_superclass(self):
2860d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
287b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.is_valid():
288b370df27c76fd875f3312be487868528121a4838Enrico Granata			parent_isa_pointer = self.valobj.CreateChildAtOffset("parent_isa",
289b370df27c76fd875f3312be487868528121a4838Enrico Granata				self.sys_params.pointer_size,
290b370df27c76fd875f3312be487868528121a4838Enrico Granata				self.sys_params.addr_ptr_type)
291b370df27c76fd875f3312be487868528121a4838Enrico Granata			return Class_Data_V2(parent_isa_pointer,self.sys_params)
292b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
293b370df27c76fd875f3312be487868528121a4838Enrico Granata			return None
294b370df27c76fd875f3312be487868528121a4838Enrico Granata
295b370df27c76fd875f3312be487868528121a4838Enrico Granata	def class_name(self):
2960d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
297b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.is_valid():
298b370df27c76fd875f3312be487868528121a4838Enrico Granata			return self.data.data.name
299b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
300b370df27c76fd875f3312be487868528121a4838Enrico Granata			return None
301b370df27c76fd875f3312be487868528121a4838Enrico Granata
302b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_valid(self):
3030d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
304b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.valid:
305b370df27c76fd875f3312be487868528121a4838Enrico Granata			return self.data.is_valid()
306d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return 0
307b370df27c76fd875f3312be487868528121a4838Enrico Granata
308b370df27c76fd875f3312be487868528121a4838Enrico Granata	def __str__(self):
3090d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
310b370df27c76fd875f3312be487868528121a4838Enrico Granata		return 'isaPointer = ' + hex(self.isaPointer) + "\n" + \
311b370df27c76fd875f3312be487868528121a4838Enrico Granata		 "superclassIsaPointer = " + hex(self.superclassIsaPointer) + "\n" + \
312b370df27c76fd875f3312be487868528121a4838Enrico Granata		 "cachePointer = " + hex(self.cachePointer) + "\n" + \
313b370df27c76fd875f3312be487868528121a4838Enrico Granata		 "data = " + hex(self.dataPointer)
314b370df27c76fd875f3312be487868528121a4838Enrico Granata
315b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_tagged(self):
316d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return 0
317b370df27c76fd875f3312be487868528121a4838Enrico Granata
318d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata	def instance_size(self,align=0):
3190d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
320d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if self.is_valid() == 0:
321e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata			return None
322f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return self.rwt.rot.instance_size(align)
323e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata
324b370df27c76fd875f3312be487868528121a4838Enrico Granata# runtime v1 is much less intricate than v2 and stores relevant information directly in the class_t object
325b370df27c76fd875f3312be487868528121a4838Enrico Granataclass Class_Data_V1:
326b370df27c76fd875f3312be487868528121a4838Enrico Granata	def __init__(self,isa_pointer,params):
3270d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
328d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if (isa_pointer != None) and (Utilities.is_valid_pointer(isa_pointer.GetValueAsUnsigned(),params.pointer_size, allow_tagged=0)):
329d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 1
330b370df27c76fd875f3312be487868528121a4838Enrico Granata			self.sys_params = params
331b370df27c76fd875f3312be487868528121a4838Enrico Granata			self.valobj = isa_pointer
332f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.check_valid()
333b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
3348f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - isaPointer is invalid or None"
335d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
336b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.valid:
337b370df27c76fd875f3312be487868528121a4838Enrico Granata			self.name = Utilities.read_ascii(self.valobj.GetTarget().GetProcess(),self.namePointer)
338b370df27c76fd875f3312be487868528121a4838Enrico Granata			if not(Utilities.is_valid_identifier(self.name)):
3398f18240a09893310c43673901d863892ae7b0611Enrico Granata				logger >> "Marking as invalid - name is not valid"
340d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata				self.valid = 0
341b370df27c76fd875f3312be487868528121a4838Enrico Granata
342b370df27c76fd875f3312be487868528121a4838Enrico Granata	# perform sanity checks on the contents of this class_t
343b370df27c76fd875f3312be487868528121a4838Enrico Granata	def check_valid(self):
3440d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
345d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		self.valid = 1
346f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
347f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.isaPointer = Utilities.read_child_of(self.valobj,0,self.sys_params.types_cache.addr_ptr_type)
348d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if not(Utilities.is_valid_pointer(self.isaPointer,self.sys_params.pointer_size,allow_tagged=0)):
3498f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - isaPointer is invalid"
350d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
351b370df27c76fd875f3312be487868528121a4838Enrico Granata			return
352f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
353f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.superclassIsaPointer = Utilities.read_child_of(self.valobj,1*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
354d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if not(Utilities.is_valid_pointer(self.superclassIsaPointer,self.sys_params.pointer_size,allow_tagged=0,allow_NULL=1)):
3558f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "Marking as invalid - superclassIsa is invalid"
356d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.valid = 0
3571328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			return
358b370df27c76fd875f3312be487868528121a4838Enrico Granata
359f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.namePointer = Utilities.read_child_of(self.valobj,2*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
360d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		#if not(Utilities.is_valid_pointer(self.namePointer,self.sys_params.pointer_size,allow_tagged=0,allow_NULL=0)):
361d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		#	self.valid = 0
362f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		#	return
363f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
3641328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata	# in general, KVO is implemented by transparently subclassing
3651328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata	# however, there could be exceptions where a class does something else
3661328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata	# internally to implement the feature - this method will have no clue that a class
3671328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata	# has been KVO'ed unless the standard implementation technique is used
368b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_kvo(self):
3690d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
370b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.is_valid():
3711328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			if self.class_name().startswith("NSKVONotifying_"):
372d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata				return 1
373d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return 0
374b370df27c76fd875f3312be487868528121a4838Enrico Granata
375f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# some CF classes have a valid ObjC isa in their CFRuntimeBase
376f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# but instead of being class-specific this isa points to a match-'em-all class
377f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# which is __NSCFType (the versions without __ also exists and we are matching to it
378f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	#                      just to be on the safe side)
379f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def is_cftype(self):
3800d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
381f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if self.is_valid():
382579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return self.class_name() == '__NSCFType' or self.class_name() == 'NSCFType'
383f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
384b370df27c76fd875f3312be487868528121a4838Enrico Granata	def get_superclass(self):
3850d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
386b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.is_valid():
387b370df27c76fd875f3312be487868528121a4838Enrico Granata			parent_isa_pointer = self.valobj.CreateChildAtOffset("parent_isa",
388b370df27c76fd875f3312be487868528121a4838Enrico Granata				self.sys_params.pointer_size,
389b370df27c76fd875f3312be487868528121a4838Enrico Granata				self.sys_params.addr_ptr_type)
390b370df27c76fd875f3312be487868528121a4838Enrico Granata			return Class_Data_V1(parent_isa_pointer,self.sys_params)
391b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
392b370df27c76fd875f3312be487868528121a4838Enrico Granata			return None
393b370df27c76fd875f3312be487868528121a4838Enrico Granata
394b370df27c76fd875f3312be487868528121a4838Enrico Granata	def class_name(self):
3950d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
396b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.is_valid():
397b370df27c76fd875f3312be487868528121a4838Enrico Granata			return self.name
398b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
399b370df27c76fd875f3312be487868528121a4838Enrico Granata			return None
400b370df27c76fd875f3312be487868528121a4838Enrico Granata
401b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_valid(self):
402b370df27c76fd875f3312be487868528121a4838Enrico Granata		return self.valid
403b370df27c76fd875f3312be487868528121a4838Enrico Granata
404b370df27c76fd875f3312be487868528121a4838Enrico Granata	def __str__(self):
4050d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
406b370df27c76fd875f3312be487868528121a4838Enrico Granata		return 'isaPointer = ' + hex(self.isaPointer) + "\n" + \
407b370df27c76fd875f3312be487868528121a4838Enrico Granata		 "superclassIsaPointer = " + hex(self.superclassIsaPointer) + "\n" + \
408e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata		 "namePointer = " + hex(self.namePointer) + " --> " + self.name + \
409f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		 "instanceSize = " + hex(self.instanceSize()) + "\n"
410b370df27c76fd875f3312be487868528121a4838Enrico Granata
411b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_tagged(self):
412d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return 0
413b370df27c76fd875f3312be487868528121a4838Enrico Granata
414d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata	def instance_size(self,align=0):
4150d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
416d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if self.is_valid() == 0:
417e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata			return None
418d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if self.instanceSize is None:
419f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.instanceSize = Utilities.read_child_of(self.valobj,5*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
420e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata		if align:
421d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			unalign = self.instance_size(0)
4221328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			if self.sys_params.is_64_bit:
423e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata				return ((unalign + 7) & ~7) % 0x100000000
424e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata			else:
425e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata				return ((unalign + 3) & ~3) % 0x100000000
426e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata		else:
427e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata			return self.instanceSize
428e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata
429a0e904189172b6748935e4d00bc05d21f340caaaEnrico Granata# these are the only tagged pointers values for current versions
4303069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata# of OSX - they might change in future OS releases, and no-one is
431a0e904189172b6748935e4d00bc05d21f340caaaEnrico Granata# advised to rely on these values, or any of the bitmasking formulas
432a0e904189172b6748935e4d00bc05d21f340caaaEnrico Granata# in TaggedClass_Data. doing otherwise is at your own risk
4333069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico GranataTaggedClass_Values_Lion = {1 : 'NSNumber', \
4343069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata                           5: 'NSManagedObject', \
4353069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata                           6: 'NSDate', \
4363069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata                           7: 'NSDateTS' };
4373069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico GranataTaggedClass_Values_NMOS = {0: 'NSAtom', \
4383069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata                           3 : 'NSNumber', \
4393069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata                           4: 'NSDateTS', \
4403069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata                           5: 'NSManagedObject', \
4413069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata                           6: 'NSDate' };
4421328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata
443b370df27c76fd875f3312be487868528121a4838Enrico Granataclass TaggedClass_Data:
444b370df27c76fd875f3312be487868528121a4838Enrico Granata	def __init__(self,pointer,params):
4450d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
4463069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata		global TaggedClass_Values_Lion,TaggedClass_Values_NMOS
447d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		self.valid = 1
448b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.name = None
449b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.sys_params = params
450b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj = pointer
451b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.val = (pointer & ~0x0000000000000000FF) >> 8
452b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.class_bits = (pointer & 0xE) >> 1
453b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.i_bits = (pointer & 0xF0) >> 4
454ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
4553069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata		if self.sys_params.is_lion:
4563069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata			if self.class_bits in TaggedClass_Values_Lion:
4573069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata				self.name = TaggedClass_Values_Lion[self.class_bits]
4583069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata			else:
4598f18240a09893310c43673901d863892ae7b0611Enrico Granata				logger >> "Marking as invalid - not a good tagged pointer for Lion"
460d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata				self.valid = 0
461b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
4623069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata			if self.class_bits in TaggedClass_Values_NMOS:
4633069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata				self.name = TaggedClass_Values_NMOS[self.class_bits]
4643069c62fc7d3c0b857cd1e9269ff22011ed418fbEnrico Granata			else:
4658f18240a09893310c43673901d863892ae7b0611Enrico Granata				logger >> "Marking as invalid - not a good tagged pointer for NMOS"
466d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata				self.valid = 0
4671328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata
468b370df27c76fd875f3312be487868528121a4838Enrico Granata
469b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_valid(self):
470b370df27c76fd875f3312be487868528121a4838Enrico Granata		return self.valid
471b370df27c76fd875f3312be487868528121a4838Enrico Granata
472b370df27c76fd875f3312be487868528121a4838Enrico Granata	def class_name(self):
4730d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
474b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.is_valid():
475b370df27c76fd875f3312be487868528121a4838Enrico Granata			return self.name
476b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
477d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			return 0
478b370df27c76fd875f3312be487868528121a4838Enrico Granata
479b370df27c76fd875f3312be487868528121a4838Enrico Granata	def value(self):
480b370df27c76fd875f3312be487868528121a4838Enrico Granata		return self.val if self.is_valid() else None
481b370df27c76fd875f3312be487868528121a4838Enrico Granata
482b370df27c76fd875f3312be487868528121a4838Enrico Granata	def info_bits(self):
483b370df27c76fd875f3312be487868528121a4838Enrico Granata		return self.i_bits if self.is_valid() else None
484b370df27c76fd875f3312be487868528121a4838Enrico Granata
485b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_kvo(self):
486d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return 0
487b370df27c76fd875f3312be487868528121a4838Enrico Granata
488f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def is_cftype(self):
489d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return 0
490f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
491b370df27c76fd875f3312be487868528121a4838Enrico Granata	# we would need to go around looking for the superclass or ask the runtime
492b370df27c76fd875f3312be487868528121a4838Enrico Granata	# for now, we seem not to require support for this operation so we will merrily
493b370df27c76fd875f3312be487868528121a4838Enrico Granata	# pretend to be at a root point in the hierarchy
494b370df27c76fd875f3312be487868528121a4838Enrico Granata	def get_superclass(self):
495b370df27c76fd875f3312be487868528121a4838Enrico Granata		return None
496b370df27c76fd875f3312be487868528121a4838Enrico Granata
497b370df27c76fd875f3312be487868528121a4838Enrico Granata	# anything that is handled here is tagged
498b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_tagged(self):
499d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return 1
500b370df27c76fd875f3312be487868528121a4838Enrico Granata
501e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata	# it seems reasonable to say that a tagged pointer is the size of a pointer
502d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata	def instance_size(self,align=0):
5030d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
504d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if self.is_valid() == 0:
505e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata			return None
506f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return self.sys_params.pointer_size
507e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata
508e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata
509b370df27c76fd875f3312be487868528121a4838Enrico Granataclass InvalidClass_Data:
510b370df27c76fd875f3312be487868528121a4838Enrico Granata	def __init__(self):
511b370df27c76fd875f3312be487868528121a4838Enrico Granata		pass
512b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_valid(self):
513d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return 0
514b370df27c76fd875f3312be487868528121a4838Enrico Granata
515ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
516f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granataclass Version:
517f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def __init__(self, major, minor, release, build_string):
518f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self._major = major
519f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self._minor = minor
520f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self._release = release
521f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self._build_string = build_string
522f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
523f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def get_major(self):
524f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return self._major
525f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def get_minor(self):
526f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return self._minor
527f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def get_release(self):
528f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return self._release
529f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def get_build_string(self):
530f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return self._build_string
531f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
532f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	major = property(get_major,None)
533f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	minor = property(get_minor,None)
534f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	release = property(get_release,None)
535f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	build_string = property(get_build_string,None)
536f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
537f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def __lt__(self,other):
538f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if (self.major < other.major):
539d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			return 1
540f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if (self.minor < other.minor):
541d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			return 1
542f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if (self.release < other.release):
543d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			return 1
544f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		# build strings are not compared since they are heavily platform-dependent and might not always
545f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		# be available
546d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return 0
547f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
548f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def __eq__(self,other):
549f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return (self.major == other.major) and \
550f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		       (self.minor == other.minor) and \
551f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		       (self.release == other.release) and \
552f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		       (self.build_string == other.build_string)
553f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
554ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas	# Python 2.6 doesn't have functools.total_ordering, so we have to implement
555ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas	# other comparators
556ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas	def __gt__(self, other):
557ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas		return other < self
558ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
559ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas	def __le__(self, other):
560ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas		return not other < self
561ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
562ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas	def __ge__(self, other):
563ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas		return not self < other
564ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
565ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
5660d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granataruntime_version = lldb.formatters.cache.Cache()
5670d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granataos_version = lldb.formatters.cache.Cache()
5680d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granatatypes_caches = lldb.formatters.cache.Cache()
5690d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granataisa_caches = lldb.formatters.cache.Cache()
570b370df27c76fd875f3312be487868528121a4838Enrico Granata
571b370df27c76fd875f3312be487868528121a4838Enrico Granataclass SystemParameters:
572b370df27c76fd875f3312be487868528121a4838Enrico Granata	def __init__(self,valobj):
5730d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
574b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.adjust_for_architecture(valobj)
575f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.adjust_for_process(valobj)
576b370df27c76fd875f3312be487868528121a4838Enrico Granata
577f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def adjust_for_process(self, valobj):
5780d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
579b370df27c76fd875f3312be487868528121a4838Enrico Granata		global runtime_version
5801328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		global os_version
581f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		global types_caches
582f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		global isa_caches
583ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
584f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		process = valobj.GetTarget().GetProcess()
585209473a3e32a515f28cde69464ba2e625ae8f55cEnrico Granata		self.pid = process.GetUniqueID() # using the unique ID for added guarantees (see svn revision 172628 for further details)
586ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
587f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if runtime_version.look_for_key(self.pid):
588f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.runtime_version = runtime_version.get_value(self.pid)
589b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
590f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.runtime_version = ObjCRuntime.runtime_version(process)
591f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			runtime_version.add_item(self.pid,self.runtime_version)
592ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
593f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if os_version.look_for_key(self.pid):
594f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.is_lion = os_version.get_value(self.pid)
5951328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		else:
5961328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			self.is_lion = Utilities.check_is_osx_lion(valobj.GetTarget())
597f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			os_version.add_item(self.pid,self.is_lion)
598ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
599f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if types_caches.look_for_key(self.pid):
600f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.types_cache = types_caches.get_value(self.pid)
601f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		else:
602d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.types_cache = lldb.formatters.attrib_fromdict.AttributesDictionary(allow_reset=0)
603f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.types_cache.addr_type = valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
604f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.types_cache.addr_ptr_type = self.types_cache.addr_type.GetPointerType()
605f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.types_cache.uint32_t = valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
606f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			types_caches.add_item(self.pid,self.types_cache)
607ee1747d7ae79fdce19b3807c39f81ee8b63c13a0Filipe Cabecinhas
608f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if isa_caches.look_for_key(self.pid):
609f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.isa_cache = isa_caches.get_value(self.pid)
610f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		else:
6110d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata			self.isa_cache = lldb.formatters.cache.Cache()
612f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			isa_caches.add_item(self.pid,self.isa_cache)
613f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
614f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def adjust_for_architecture(self,valobj):
615f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		process = valobj.GetTarget().GetProcess()
616f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.pointer_size = process.GetAddressByteSize()
617f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.is_64_bit = (self.pointer_size == 8)
6186bf058b8054a1152bb227d37d6fe7c6b21a14dd3Enrico Granata		self.endianness = process.GetByteOrder()
6196bf058b8054a1152bb227d37d6fe7c6b21a14dd3Enrico Granata		self.is_little = (self.endianness == lldb.eByteOrderLittle)
620de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		self.cfruntime_size = 16 if self.is_64_bit else 8
621b370df27c76fd875f3312be487868528121a4838Enrico Granata
622f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# a simple helper function that makes it more explicit that one is calculating
623f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# an offset that is made up of X pointers and Y bytes of additional data
624f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# taking into account pointer size - if you know there is going to be some padding
625f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# you can pass that in and it will be taken into account (since padding may be different between
626f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	# 32 and 64 bit versions, you can pass padding value for both, the right one will be used)
627f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def calculate_offset(self, num_pointers = 0, bytes_count = 0, padding32 = 0, padding64 = 0):
628f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		value = bytes_count + num_pointers*self.pointer_size
629f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return value + padding64 if self.is_64_bit else value + padding32
630b370df27c76fd875f3312be487868528121a4838Enrico Granata
631b370df27c76fd875f3312be487868528121a4838Enrico Granataclass ObjCRuntime:
632b370df27c76fd875f3312be487868528121a4838Enrico Granata
633b370df27c76fd875f3312be487868528121a4838Enrico Granata	# the ObjC runtime has no explicit "version" field that we can use
634b370df27c76fd875f3312be487868528121a4838Enrico Granata	# instead, we discriminate v1 from v2 by looking for the presence
635b370df27c76fd875f3312be487868528121a4838Enrico Granata	# of a well-known section only present in v1
636b370df27c76fd875f3312be487868528121a4838Enrico Granata	@staticmethod
637b370df27c76fd875f3312be487868528121a4838Enrico Granata	def runtime_version(process):
6380d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
639d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if process.IsValid() == 0:
6408f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "No process - bailing out"
641b370df27c76fd875f3312be487868528121a4838Enrico Granata			return None
642b370df27c76fd875f3312be487868528121a4838Enrico Granata		target = process.GetTarget()
643b370df27c76fd875f3312be487868528121a4838Enrico Granata		num_modules = target.GetNumModules()
644b370df27c76fd875f3312be487868528121a4838Enrico Granata		module_objc = None
645b370df27c76fd875f3312be487868528121a4838Enrico Granata		for idx in range(num_modules):
646b370df27c76fd875f3312be487868528121a4838Enrico Granata			module = target.GetModuleAtIndex(idx)
647b370df27c76fd875f3312be487868528121a4838Enrico Granata			if module.GetFileSpec().GetFilename() == 'libobjc.A.dylib':
648b370df27c76fd875f3312be487868528121a4838Enrico Granata				module_objc = module
649b370df27c76fd875f3312be487868528121a4838Enrico Granata				break
650d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if module_objc is None or module_objc.IsValid() == 0:
6518f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "no libobjc - bailing out"
652b370df27c76fd875f3312be487868528121a4838Enrico Granata			return None
653b370df27c76fd875f3312be487868528121a4838Enrico Granata		num_sections = module.GetNumSections()
654b370df27c76fd875f3312be487868528121a4838Enrico Granata		section_objc = None
655b370df27c76fd875f3312be487868528121a4838Enrico Granata		for idx in range(num_sections):
656b370df27c76fd875f3312be487868528121a4838Enrico Granata			section = module.GetSectionAtIndex(idx)
657b370df27c76fd875f3312be487868528121a4838Enrico Granata			if section.GetName() == '__OBJC':
658b370df27c76fd875f3312be487868528121a4838Enrico Granata				section_objc = section
659b370df27c76fd875f3312be487868528121a4838Enrico Granata				break
660b370df27c76fd875f3312be487868528121a4838Enrico Granata		if section_objc != None and section_objc.IsValid():
6618f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "found __OBJC: v1"
662b370df27c76fd875f3312be487868528121a4838Enrico Granata			return 1
6638f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger >> "no __OBJC: v2"
664b370df27c76fd875f3312be487868528121a4838Enrico Granata		return 2
665b370df27c76fd875f3312be487868528121a4838Enrico Granata
66667812172eecc4426c17b25354af072f6a4a9aad9Enrico Granata	@staticmethod
66767812172eecc4426c17b25354af072f6a4a9aad9Enrico Granata	def runtime_from_isa(isa):
6680d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
66967812172eecc4426c17b25354af072f6a4a9aad9Enrico Granata		runtime = ObjCRuntime(isa)
67067812172eecc4426c17b25354af072f6a4a9aad9Enrico Granata		runtime.isa = isa
67167812172eecc4426c17b25354af072f6a4a9aad9Enrico Granata		return runtime
67267812172eecc4426c17b25354af072f6a4a9aad9Enrico Granata
673b370df27c76fd875f3312be487868528121a4838Enrico Granata	def __init__(self,valobj):
6740d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
675b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj = valobj
676b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.adjust_for_architecture()
677b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.sys_params = SystemParameters(self.valobj)
6781328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		self.unsigned_value = self.valobj.GetValueAsUnsigned()
6791328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		self.isa_value = None
680b370df27c76fd875f3312be487868528121a4838Enrico Granata
681b370df27c76fd875f3312be487868528121a4838Enrico Granata	def adjust_for_architecture(self):
682f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		pass
683b370df27c76fd875f3312be487868528121a4838Enrico Granata
684b370df27c76fd875f3312be487868528121a4838Enrico Granata# an ObjC pointer can either be tagged or must be aligned
685b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_tagged(self):
6860d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
687b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.valobj is None:
688d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			return 0
689d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return (Utilities.is_valid_pointer(self.unsigned_value,self.sys_params.pointer_size, allow_tagged=1) and \
690d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		not(Utilities.is_valid_pointer(self.unsigned_value,self.sys_params.pointer_size, allow_tagged=0)))
691b370df27c76fd875f3312be487868528121a4838Enrico Granata
692b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_valid(self):
6930d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
694b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.valobj is None:
695d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			return 0
696d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if self.valobj.IsInScope() == 0:
697d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			return 0
698d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return Utilities.is_valid_pointer(self.unsigned_value,self.sys_params.pointer_size, allow_tagged=1)
699b370df27c76fd875f3312be487868528121a4838Enrico Granata
700579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	def is_nil(self):
701579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		return self.unsigned_value == 0
702579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
703b370df27c76fd875f3312be487868528121a4838Enrico Granata	def read_isa(self):
7040d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
7051328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		if self.isa_value != None:
7068f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "using cached isa"
7071328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata			return self.isa_value
708d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		self.isa_pointer = self.valobj.CreateChildAtOffset("cfisa",
709b370df27c76fd875f3312be487868528121a4838Enrico Granata			0,
710f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.sys_params.types_cache.addr_ptr_type)
711d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if self.isa_pointer is None or self.isa_pointer.IsValid() == 0:
7128f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "invalid isa - bailing out"
713b370df27c76fd875f3312be487868528121a4838Enrico Granata			return None;
714d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		self.isa_value = self.isa_pointer.GetValueAsUnsigned(1)
715d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if self.isa_value == 1:
7168f18240a09893310c43673901d863892ae7b0611Enrico Granata			logger >> "invalid isa value - bailing out"
717b370df27c76fd875f3312be487868528121a4838Enrico Granata			return None;
718d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		return Ellipsis
719b370df27c76fd875f3312be487868528121a4838Enrico Granata
720b370df27c76fd875f3312be487868528121a4838Enrico Granata	def read_class_data(self):
7210d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
722b370df27c76fd875f3312be487868528121a4838Enrico Granata		global isa_cache
723b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.is_tagged():
724b370df27c76fd875f3312be487868528121a4838Enrico Granata			# tagged pointers only exist in ObjC v2
725b370df27c76fd875f3312be487868528121a4838Enrico Granata			if self.sys_params.runtime_version == 2:
7268f18240a09893310c43673901d863892ae7b0611Enrico Granata				logger >> "on v2 and tagged - maybe"
727b370df27c76fd875f3312be487868528121a4838Enrico Granata				# not every odd-valued pointer is actually tagged. most are just plain wrong
728b370df27c76fd875f3312be487868528121a4838Enrico Granata				# we could try and predetect this before even creating a TaggedClass_Data object
729b370df27c76fd875f3312be487868528121a4838Enrico Granata				# but unless performance requires it, this seems a cleaner way to tackle the task
7301328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata				tentative_tagged = TaggedClass_Data(self.unsigned_value,self.sys_params)
7318f18240a09893310c43673901d863892ae7b0611Enrico Granata				if tentative_tagged.is_valid():
7328f18240a09893310c43673901d863892ae7b0611Enrico Granata					logger >> "truly tagged"
7338f18240a09893310c43673901d863892ae7b0611Enrico Granata					return tentative_tagged
7348f18240a09893310c43673901d863892ae7b0611Enrico Granata				else:
7358f18240a09893310c43673901d863892ae7b0611Enrico Granata					logger >> "not tagged - error"
7368f18240a09893310c43673901d863892ae7b0611Enrico Granata					return InvalidClass_Data()
737b370df27c76fd875f3312be487868528121a4838Enrico Granata			else:
7388f18240a09893310c43673901d863892ae7b0611Enrico Granata				logger >> "on v1 and tagged - error"
739b370df27c76fd875f3312be487868528121a4838Enrico Granata				return InvalidClass_Data()
740d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if self.is_valid() == 0 or self.read_isa() is None:
741b370df27c76fd875f3312be487868528121a4838Enrico Granata			return InvalidClass_Data()
742d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		data = self.sys_params.isa_cache.get_value(self.isa_value,default=None)
743b370df27c76fd875f3312be487868528121a4838Enrico Granata		if data != None:
744b370df27c76fd875f3312be487868528121a4838Enrico Granata			return data
745b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.sys_params.runtime_version == 2:
746d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			data = Class_Data_V2(self.isa_pointer,self.sys_params)
747b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
748d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			data = Class_Data_V1(self.isa_pointer,self.sys_params)
749d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata		if data is None:
750b370df27c76fd875f3312be487868528121a4838Enrico Granata			return InvalidClass_Data()
751b370df27c76fd875f3312be487868528121a4838Enrico Granata		if data.is_valid():
752d0a098024ae5cd6e98429682590e687cecb6b0feEnrico Granata			self.sys_params.isa_cache.add_item(self.isa_value,data,ok_to_replace=1)
753b370df27c76fd875f3312be487868528121a4838Enrico Granata		return data
754e859697139685b7bbe27d3d420e77c727af2080aEnrico Granata
755579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata# these classes below can be used by the data formatters to provide a consistent message that describes a given runtime-generated situation
756579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granataclass SpecialSituation_Description:
757579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	def message(self):
758579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		return ''
759579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
760579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granataclass InvalidPointer_Description(SpecialSituation_Description):
761579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
762579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	def __init__(self,nil):
763579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		self.is_nil = nil
764579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
765579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	def message(self):
766579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		if self.is_nil:
767579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return '@"<nil>"'
768579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		else:
769579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return '<invalid pointer>'
770579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
771579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granataclass InvalidISA_Description(SpecialSituation_Description):
772579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
773579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	def __init__(self):
774579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		pass
775579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
776579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	def message(self):
777579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		return '<not an Objective-C object>'
778579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
77900f9ebe460fd6e9c226f4ba3f6610fbed7b0ef29Enrico Granataclass ThisIsZombie_Description(SpecialSituation_Description):
78000f9ebe460fd6e9c226f4ba3f6610fbed7b0ef29Enrico Granata	def message(self):
78100f9ebe460fd6e9c226f4ba3f6610fbed7b0ef29Enrico Granata		return '<freed object>'