CFString.py revision 98222732528a6dd271da301b5f9f2467912502e3
1579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata"""
2579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico GranataLLDB AppKit formatters
3579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
4579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granatapart of The LLVM Compiler Infrastructure
5579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico GranataThis file is distributed under the University of Illinois Open Source
6579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico GranataLicense. See LICENSE.TXT for details.
7579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata"""
898222732528a6dd271da301b5f9f2467912502e3Enrico Granata# example synthetic children and summary provider for CFString (and related NSString class)
998222732528a6dd271da301b5f9f2467912502e3Enrico Granata# the real code is part of the LLDB core
10b370df27c76fd875f3312be487868528121a4838Enrico Granataimport lldb
110d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granataimport lldb.runtime.objc.objc_runtime
120d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granataimport lldb.formatters.Logger
13b370df27c76fd875f3312be487868528121a4838Enrico Granata
14b370df27c76fd875f3312be487868528121a4838Enrico Granatadef CFString_SummaryProvider (valobj,dict):
150d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata	logger = lldb.formatters.Logger.Logger()
16b370df27c76fd875f3312be487868528121a4838Enrico Granata	provider = CFStringSynthProvider(valobj,dict);
17b370df27c76fd875f3312be487868528121a4838Enrico Granata	if provider.invalid == False:
18579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		try:
1980731ec9368b8e1cbfe093fb9ec257457ef29133Enrico Granata			summary = provider.get_child_at_index(provider.get_child_index("content"))
2080731ec9368b8e1cbfe093fb9ec257457ef29133Enrico Granata			if type(summary) == lldb.SBValue:
2180731ec9368b8e1cbfe093fb9ec257457ef29133Enrico Granata				summary = summary.GetSummary()
2280731ec9368b8e1cbfe093fb9ec257457ef29133Enrico Granata			else:
2380731ec9368b8e1cbfe093fb9ec257457ef29133Enrico Granata				summary = '"' + summary + '"'
24579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		except:
25579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			summary = None
26579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		if summary == None:
27579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			summary = '<variable is not NSString>'
28579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		return '@'+summary
29b370df27c76fd875f3312be487868528121a4838Enrico Granata	return ''
30b370df27c76fd875f3312be487868528121a4838Enrico Granata
31b370df27c76fd875f3312be487868528121a4838Enrico Granatadef CFAttributedString_SummaryProvider (valobj,dict):
320d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata	logger = lldb.formatters.Logger.Logger()
33b370df27c76fd875f3312be487868528121a4838Enrico Granata	offset = valobj.GetTarget().GetProcess().GetAddressByteSize()
34b370df27c76fd875f3312be487868528121a4838Enrico Granata	pointee = valobj.GetValueAsUnsigned(0)
35579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	summary = '<variable is not NSAttributedString>'
36b370df27c76fd875f3312be487868528121a4838Enrico Granata	if pointee != None and pointee != 0:
37b370df27c76fd875f3312be487868528121a4838Enrico Granata		pointee = pointee + offset
38b370df27c76fd875f3312be487868528121a4838Enrico Granata		child_ptr = valobj.CreateValueFromAddress("string_ptr",pointee,valobj.GetType())
39b370df27c76fd875f3312be487868528121a4838Enrico Granata		child = child_ptr.CreateValueFromAddress("string_data",child_ptr.GetValueAsUnsigned(),valobj.GetType()).AddressOf()
40b370df27c76fd875f3312be487868528121a4838Enrico Granata		provider = CFStringSynthProvider(child,dict);
41b370df27c76fd875f3312be487868528121a4838Enrico Granata		if provider.invalid == False:
42b370df27c76fd875f3312be487868528121a4838Enrico Granata			try:
43b370df27c76fd875f3312be487868528121a4838Enrico Granata				summary = provider.get_child_at_index(provider.get_child_index("content")).GetSummary();
44b370df27c76fd875f3312be487868528121a4838Enrico Granata			except:
45579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata				summary = '<variable is not NSAttributedString>'
46b370df27c76fd875f3312be487868528121a4838Enrico Granata	if summary == None:
47579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		summary = '<variable is not NSAttributedString>'
48b370df27c76fd875f3312be487868528121a4838Enrico Granata	return '@'+summary
49b370df27c76fd875f3312be487868528121a4838Enrico Granata
50b370df27c76fd875f3312be487868528121a4838Enrico Granata
51b370df27c76fd875f3312be487868528121a4838Enrico Granatadef __lldb_init_module(debugger,dict):
52b370df27c76fd875f3312be487868528121a4838Enrico Granata	debugger.HandleCommand("type summary add -F CFString.CFString_SummaryProvider NSString CFStringRef CFMutableStringRef")
53b370df27c76fd875f3312be487868528121a4838Enrico Granata	debugger.HandleCommand("type summary add -F CFString.CFAttributedString_SummaryProvider NSAttributedString")
54b370df27c76fd875f3312be487868528121a4838Enrico Granata
55b370df27c76fd875f3312be487868528121a4838Enrico Granataclass CFStringSynthProvider:
56b370df27c76fd875f3312be487868528121a4838Enrico Granata	def __init__(self,valobj,dict):
570d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
58b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj = valobj;
59b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.update()
60b370df27c76fd875f3312be487868528121a4838Enrico Granata
61b370df27c76fd875f3312be487868528121a4838Enrico Granata	# children other than "content" are for debugging only and must not be used in production code
62b370df27c76fd875f3312be487868528121a4838Enrico Granata	def num_children(self):
630d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
64b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.invalid:
65b370df27c76fd875f3312be487868528121a4838Enrico Granata			return 0;
66b370df27c76fd875f3312be487868528121a4838Enrico Granata		return 6;
67b370df27c76fd875f3312be487868528121a4838Enrico Granata
68a695aa28bc34a0bc4d9b61e3752f7cff1454c39bEnrico Granata	def read_unicode(self, pointer,max_len=2048):
690d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
70b370df27c76fd875f3312be487868528121a4838Enrico Granata		process = self.valobj.GetTarget().GetProcess()
71b370df27c76fd875f3312be487868528121a4838Enrico Granata		error = lldb.SBError()
72b370df27c76fd875f3312be487868528121a4838Enrico Granata		pystr = u''
73b370df27c76fd875f3312be487868528121a4838Enrico Granata		# cannot do the read at once because the length value has
74b370df27c76fd875f3312be487868528121a4838Enrico Granata		# a weird encoding. better play it safe here
75a695aa28bc34a0bc4d9b61e3752f7cff1454c39bEnrico Granata		while max_len > 0:
76b370df27c76fd875f3312be487868528121a4838Enrico Granata			content = process.ReadMemory(pointer, 2, error)
77b370df27c76fd875f3312be487868528121a4838Enrico Granata			new_bytes = bytearray(content)
78b370df27c76fd875f3312be487868528121a4838Enrico Granata			b0 = new_bytes[0]
79b370df27c76fd875f3312be487868528121a4838Enrico Granata			b1 = new_bytes[1]
80b370df27c76fd875f3312be487868528121a4838Enrico Granata			pointer = pointer + 2
81b370df27c76fd875f3312be487868528121a4838Enrico Granata			if b0 == 0 and b1 == 0:
82b370df27c76fd875f3312be487868528121a4838Enrico Granata				break
83b370df27c76fd875f3312be487868528121a4838Enrico Granata			# rearrange bytes depending on endianness
84b370df27c76fd875f3312be487868528121a4838Enrico Granata			# (do we really need this or is Cocoa going to
85b370df27c76fd875f3312be487868528121a4838Enrico Granata			#  use Windows-compatible little-endian even
86b370df27c76fd875f3312be487868528121a4838Enrico Granata			#  if the target is big endian?)
87b370df27c76fd875f3312be487868528121a4838Enrico Granata			if self.is_little:
88b370df27c76fd875f3312be487868528121a4838Enrico Granata				value = b1 * 256 + b0
89b370df27c76fd875f3312be487868528121a4838Enrico Granata			else:
90b370df27c76fd875f3312be487868528121a4838Enrico Granata				value = b0 * 256 + b1
91b370df27c76fd875f3312be487868528121a4838Enrico Granata			pystr = pystr + unichr(value)
92a695aa28bc34a0bc4d9b61e3752f7cff1454c39bEnrico Granata			# read max_len unicode values, not max_len bytes
93a695aa28bc34a0bc4d9b61e3752f7cff1454c39bEnrico Granata			max_len = max_len - 1
94b370df27c76fd875f3312be487868528121a4838Enrico Granata		return pystr
95b370df27c76fd875f3312be487868528121a4838Enrico Granata
96b370df27c76fd875f3312be487868528121a4838Enrico Granata	# handle the special case strings
97b370df27c76fd875f3312be487868528121a4838Enrico Granata	# only use the custom code for the tested LP64 case
98b370df27c76fd875f3312be487868528121a4838Enrico Granata	def handle_special(self):
990d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
1001328b1410eb0f5e03c3b3ee302e9adca3e1b0361Enrico Granata		if self.is_64_bit == False:
101b370df27c76fd875f3312be487868528121a4838Enrico Granata			# for 32bit targets, use safe ObjC code
102b370df27c76fd875f3312be487868528121a4838Enrico Granata			return self.handle_unicode_string_safe()
103b370df27c76fd875f3312be487868528121a4838Enrico Granata		offset = 12
104b370df27c76fd875f3312be487868528121a4838Enrico Granata		pointer = self.valobj.GetValueAsUnsigned(0) + offset
105b370df27c76fd875f3312be487868528121a4838Enrico Granata		pystr = self.read_unicode(pointer)
106b370df27c76fd875f3312be487868528121a4838Enrico Granata		return self.valobj.CreateValueFromExpression("content",
107b370df27c76fd875f3312be487868528121a4838Enrico Granata			"(char*)\"" + pystr.encode('utf-8') + "\"")
108b370df27c76fd875f3312be487868528121a4838Enrico Granata
109b370df27c76fd875f3312be487868528121a4838Enrico Granata	# last resort call, use ObjC code to read; the final aim is to
110b370df27c76fd875f3312be487868528121a4838Enrico Granata	# be able to strip this call away entirely and only do the read
111b370df27c76fd875f3312be487868528121a4838Enrico Granata	# ourselves
112b370df27c76fd875f3312be487868528121a4838Enrico Granata	def handle_unicode_string_safe(self):
113b370df27c76fd875f3312be487868528121a4838Enrico Granata		return self.valobj.CreateValueFromExpression("content",
114b370df27c76fd875f3312be487868528121a4838Enrico Granata			"(char*)\"" + self.valobj.GetObjectDescription() + "\"");
115b370df27c76fd875f3312be487868528121a4838Enrico Granata
116b370df27c76fd875f3312be487868528121a4838Enrico Granata	def handle_unicode_string(self):
1170d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
118b370df27c76fd875f3312be487868528121a4838Enrico Granata		# step 1: find offset
119b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.inline:
120b370df27c76fd875f3312be487868528121a4838Enrico Granata			pointer = self.valobj.GetValueAsUnsigned(0) + self.size_of_cfruntime_base();
121b370df27c76fd875f3312be487868528121a4838Enrico Granata			if self.explicit == False:
122b370df27c76fd875f3312be487868528121a4838Enrico Granata				# untested, use the safe code path
123b370df27c76fd875f3312be487868528121a4838Enrico Granata				return self.handle_unicode_string_safe();
124b370df27c76fd875f3312be487868528121a4838Enrico Granata			else:
1253dcbb2336d4a7b7162aab4719c5f3fff1d1b2355Enrico Granata				# a full pointer is skipped here before getting to the live data
126f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata				pointer = pointer + self.pointer_size
127b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
12880731ec9368b8e1cbfe093fb9ec257457ef29133Enrico Granata			pointer = self.valobj.GetValueAsUnsigned(0) + self.size_of_cfruntime_base()
129b370df27c76fd875f3312be487868528121a4838Enrico Granata			# read 8 bytes here and make an address out of them
130b370df27c76fd875f3312be487868528121a4838Enrico Granata			try:
13180731ec9368b8e1cbfe093fb9ec257457ef29133Enrico Granata				char_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType()
13280731ec9368b8e1cbfe093fb9ec257457ef29133Enrico Granata				vopointer = self.valobj.CreateValueFromAddress("dummy",pointer,char_type);
13380731ec9368b8e1cbfe093fb9ec257457ef29133Enrico Granata				pointer = vopointer.GetValueAsUnsigned(0)
134b370df27c76fd875f3312be487868528121a4838Enrico Granata			except:
13580731ec9368b8e1cbfe093fb9ec257457ef29133Enrico Granata				return self.valobj.CreateValueFromExpression("content",
136b370df27c76fd875f3312be487868528121a4838Enrico Granata                                                             '(char*)"@\"invalid NSString\""')
137b370df27c76fd875f3312be487868528121a4838Enrico Granata		# step 2: read Unicode data at pointer
138b370df27c76fd875f3312be487868528121a4838Enrico Granata		pystr = self.read_unicode(pointer)
139b370df27c76fd875f3312be487868528121a4838Enrico Granata		# step 3: return it
14080731ec9368b8e1cbfe093fb9ec257457ef29133Enrico Granata		return pystr.encode('utf-8')
141b370df27c76fd875f3312be487868528121a4838Enrico Granata
142b370df27c76fd875f3312be487868528121a4838Enrico Granata	def handle_inline_explicit(self):
1430d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
144f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		offset = 3*self.pointer_size
145b370df27c76fd875f3312be487868528121a4838Enrico Granata		offset = offset + self.valobj.GetValueAsUnsigned(0)
146b370df27c76fd875f3312be487868528121a4838Enrico Granata		return self.valobj.CreateValueFromExpression("content",
147b370df27c76fd875f3312be487868528121a4838Enrico Granata				"(char*)(" + str(offset) + ")")
148b370df27c76fd875f3312be487868528121a4838Enrico Granata
149b370df27c76fd875f3312be487868528121a4838Enrico Granata	def handle_mutable_string(self):
1500d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
151f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		offset = 2 * self.pointer_size
152b370df27c76fd875f3312be487868528121a4838Enrico Granata		data = self.valobj.CreateChildAtOffset("content",
153b370df27c76fd875f3312be487868528121a4838Enrico Granata			offset, self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType());
154b370df27c76fd875f3312be487868528121a4838Enrico Granata		data_value = data.GetValueAsUnsigned(0)
155a695aa28bc34a0bc4d9b61e3752f7cff1454c39bEnrico Granata		if self.explicit and self.unicode:
156a695aa28bc34a0bc4d9b61e3752f7cff1454c39bEnrico Granata			return self.read_unicode(data_value).encode('utf-8')
157a695aa28bc34a0bc4d9b61e3752f7cff1454c39bEnrico Granata		else:
158a695aa28bc34a0bc4d9b61e3752f7cff1454c39bEnrico Granata			data_value = data_value + 1
159a695aa28bc34a0bc4d9b61e3752f7cff1454c39bEnrico Granata			return self.valobj.CreateValueFromExpression("content", "(char*)(" + str(data_value) + ")")
160b370df27c76fd875f3312be487868528121a4838Enrico Granata
161b370df27c76fd875f3312be487868528121a4838Enrico Granata	def handle_UTF8_inline(self):
1620d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
163b370df27c76fd875f3312be487868528121a4838Enrico Granata		offset = self.valobj.GetValueAsUnsigned(0) + self.size_of_cfruntime_base();
164b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.explicit == False:
165b370df27c76fd875f3312be487868528121a4838Enrico Granata			offset = offset + 1;
166b370df27c76fd875f3312be487868528121a4838Enrico Granata		return self.valobj.CreateValueFromAddress("content",
167b370df27c76fd875f3312be487868528121a4838Enrico Granata				offset, self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar)).AddressOf();
168b370df27c76fd875f3312be487868528121a4838Enrico Granata
169b370df27c76fd875f3312be487868528121a4838Enrico Granata	def handle_UTF8_not_inline(self):
1700d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
171b370df27c76fd875f3312be487868528121a4838Enrico Granata		offset = self.size_of_cfruntime_base();
172b370df27c76fd875f3312be487868528121a4838Enrico Granata		return self.valobj.CreateChildAtOffset("content",
173b370df27c76fd875f3312be487868528121a4838Enrico Granata				offset,self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType());
174b370df27c76fd875f3312be487868528121a4838Enrico Granata
175b370df27c76fd875f3312be487868528121a4838Enrico Granata	def get_child_at_index(self,index):
1760d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
1778f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger >> "Querying for child [" + str(index) + "]"
178b370df27c76fd875f3312be487868528121a4838Enrico Granata		if index == 0:
179b370df27c76fd875f3312be487868528121a4838Enrico Granata			return self.valobj.CreateValueFromExpression("mutable",
180b370df27c76fd875f3312be487868528121a4838Enrico Granata				str(int(self.mutable)));
181b370df27c76fd875f3312be487868528121a4838Enrico Granata		if index == 1:
182b370df27c76fd875f3312be487868528121a4838Enrico Granata			return self.valobj.CreateValueFromExpression("inline",
183b370df27c76fd875f3312be487868528121a4838Enrico Granata				str(int(self.inline)));
184b370df27c76fd875f3312be487868528121a4838Enrico Granata		if index == 2:
185b370df27c76fd875f3312be487868528121a4838Enrico Granata			return self.valobj.CreateValueFromExpression("explicit",
186b370df27c76fd875f3312be487868528121a4838Enrico Granata				str(int(self.explicit)));
187b370df27c76fd875f3312be487868528121a4838Enrico Granata		if index == 3:
188b370df27c76fd875f3312be487868528121a4838Enrico Granata			return self.valobj.CreateValueFromExpression("unicode",
189b370df27c76fd875f3312be487868528121a4838Enrico Granata				str(int(self.unicode)));
190b370df27c76fd875f3312be487868528121a4838Enrico Granata		if index == 4:
191b370df27c76fd875f3312be487868528121a4838Enrico Granata			return self.valobj.CreateValueFromExpression("special",
192b370df27c76fd875f3312be487868528121a4838Enrico Granata				str(int(self.special)));
193b370df27c76fd875f3312be487868528121a4838Enrico Granata		if index == 5:
194b370df27c76fd875f3312be487868528121a4838Enrico Granata			# we are handling the several possible combinations of flags.
195b370df27c76fd875f3312be487868528121a4838Enrico Granata			# for each known combination we have a function that knows how to
196b370df27c76fd875f3312be487868528121a4838Enrico Granata			# go fetch the data from memory instead of running code. if a string is not
197b370df27c76fd875f3312be487868528121a4838Enrico Granata			# correctly displayed, one should start by finding a combination of flags that
198b370df27c76fd875f3312be487868528121a4838Enrico Granata			# makes it different from these known cases, and provide a new reader function
199b370df27c76fd875f3312be487868528121a4838Enrico Granata			# if this is not possible, a new flag might have to be made up (like the "special" flag
200b370df27c76fd875f3312be487868528121a4838Enrico Granata			# below, which is not a real flag in CFString), or alternatively one might need to use
201b370df27c76fd875f3312be487868528121a4838Enrico Granata			# the ObjC runtime helper to detect the new class and deal with it accordingly
20280731ec9368b8e1cbfe093fb9ec257457ef29133Enrico Granata			#print 'mutable = ' + str(self.mutable)
20380731ec9368b8e1cbfe093fb9ec257457ef29133Enrico Granata			#print 'inline = ' + str(self.inline)
20480731ec9368b8e1cbfe093fb9ec257457ef29133Enrico Granata			#print 'explicit = ' + str(self.explicit)
20580731ec9368b8e1cbfe093fb9ec257457ef29133Enrico Granata			#print 'unicode = ' + str(self.unicode)
20680731ec9368b8e1cbfe093fb9ec257457ef29133Enrico Granata			#print 'special = ' + str(self.special)
207b370df27c76fd875f3312be487868528121a4838Enrico Granata			if self.mutable == True:
208b370df27c76fd875f3312be487868528121a4838Enrico Granata				return self.handle_mutable_string()
209b370df27c76fd875f3312be487868528121a4838Enrico Granata			elif self.inline == True and self.explicit == True and \
210b370df27c76fd875f3312be487868528121a4838Enrico Granata			   self.unicode == False and self.special == False and \
211b370df27c76fd875f3312be487868528121a4838Enrico Granata			   self.mutable == False:
212b370df27c76fd875f3312be487868528121a4838Enrico Granata				return self.handle_inline_explicit()
213b370df27c76fd875f3312be487868528121a4838Enrico Granata			elif self.unicode == True:
214b370df27c76fd875f3312be487868528121a4838Enrico Granata				return self.handle_unicode_string();
215b370df27c76fd875f3312be487868528121a4838Enrico Granata			elif self.special == True:
216b370df27c76fd875f3312be487868528121a4838Enrico Granata				return self.handle_special();
217b370df27c76fd875f3312be487868528121a4838Enrico Granata			elif self.inline == True:
218b370df27c76fd875f3312be487868528121a4838Enrico Granata				return self.handle_UTF8_inline();
219b370df27c76fd875f3312be487868528121a4838Enrico Granata			else:
220b370df27c76fd875f3312be487868528121a4838Enrico Granata				return self.handle_UTF8_not_inline();
221b370df27c76fd875f3312be487868528121a4838Enrico Granata
222b370df27c76fd875f3312be487868528121a4838Enrico Granata	def get_child_index(self,name):
2230d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
2248f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger >> "Querying for child ['" + str(name) + "']"
225b370df27c76fd875f3312be487868528121a4838Enrico Granata		if name == "content":
226b370df27c76fd875f3312be487868528121a4838Enrico Granata			return self.num_children() - 1;
227b370df27c76fd875f3312be487868528121a4838Enrico Granata		if name == "mutable":
228b370df27c76fd875f3312be487868528121a4838Enrico Granata			return 0;
229b370df27c76fd875f3312be487868528121a4838Enrico Granata		if name == "inline":
230b370df27c76fd875f3312be487868528121a4838Enrico Granata			return 1;
231b370df27c76fd875f3312be487868528121a4838Enrico Granata		if name == "explicit":
232b370df27c76fd875f3312be487868528121a4838Enrico Granata			return 2;
233b370df27c76fd875f3312be487868528121a4838Enrico Granata		if name == "unicode":
234b370df27c76fd875f3312be487868528121a4838Enrico Granata			return 3;
235b370df27c76fd875f3312be487868528121a4838Enrico Granata		if name == "special":
236b370df27c76fd875f3312be487868528121a4838Enrico Granata			return 4;
237b370df27c76fd875f3312be487868528121a4838Enrico Granata
238b370df27c76fd875f3312be487868528121a4838Enrico Granata	# CFRuntimeBase is defined as having an additional
239b370df27c76fd875f3312be487868528121a4838Enrico Granata	# 4 bytes (padding?) on LP64 architectures
240b370df27c76fd875f3312be487868528121a4838Enrico Granata	# to get its size we add up sizeof(pointer)+4
241b370df27c76fd875f3312be487868528121a4838Enrico Granata	# and then add 4 more bytes if we are on a 64bit system
242b370df27c76fd875f3312be487868528121a4838Enrico Granata	def size_of_cfruntime_base(self):
2430d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
244f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return self.pointer_size+4+(4 if self.is_64_bit else 0)
245b370df27c76fd875f3312be487868528121a4838Enrico Granata
246b370df27c76fd875f3312be487868528121a4838Enrico Granata	# the info bits are part of the CFRuntimeBase structure
247b370df27c76fd875f3312be487868528121a4838Enrico Granata	# to get at them we have to skip a uintptr_t and then get
248b370df27c76fd875f3312be487868528121a4838Enrico Granata	# at the least-significant byte of a 4 byte array. If we are
249b370df27c76fd875f3312be487868528121a4838Enrico Granata	# on big-endian this means going to byte 3, if we are on
250b370df27c76fd875f3312be487868528121a4838Enrico Granata	# little endian (OSX & iOS), this means reading byte 0
251b370df27c76fd875f3312be487868528121a4838Enrico Granata	def offset_of_info_bits(self):
2520d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
253f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		offset = self.pointer_size
254b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.is_little == False:
255b370df27c76fd875f3312be487868528121a4838Enrico Granata			offset = offset + 3;
256b370df27c76fd875f3312be487868528121a4838Enrico Granata		return offset;
257b370df27c76fd875f3312be487868528121a4838Enrico Granata
258b370df27c76fd875f3312be487868528121a4838Enrico Granata	def read_info_bits(self):
2590d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
260b370df27c76fd875f3312be487868528121a4838Enrico Granata		cfinfo = self.valobj.CreateChildAtOffset("cfinfo",
261b370df27c76fd875f3312be487868528121a4838Enrico Granata					self.offset_of_info_bits(),
262b370df27c76fd875f3312be487868528121a4838Enrico Granata					self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar));
263b370df27c76fd875f3312be487868528121a4838Enrico Granata		cfinfo.SetFormat(11)
264b370df27c76fd875f3312be487868528121a4838Enrico Granata		info = cfinfo.GetValue();
265b370df27c76fd875f3312be487868528121a4838Enrico Granata		if info != None:
266b370df27c76fd875f3312be487868528121a4838Enrico Granata			self.invalid = False;
267b370df27c76fd875f3312be487868528121a4838Enrico Granata			return int(info,0);
268b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
269b370df27c76fd875f3312be487868528121a4838Enrico Granata			self.invalid = True;
270b370df27c76fd875f3312be487868528121a4838Enrico Granata			return None;
271b370df27c76fd875f3312be487868528121a4838Enrico Granata
272b370df27c76fd875f3312be487868528121a4838Enrico Granata	# calculating internal flag bits of the CFString object
273b370df27c76fd875f3312be487868528121a4838Enrico Granata	# this stuff is defined and discussed in CFString.c
274b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_mutable(self):
2750d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
276b370df27c76fd875f3312be487868528121a4838Enrico Granata		return (self.info_bits & 1) == 1;
277b370df27c76fd875f3312be487868528121a4838Enrico Granata
278b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_inline(self):
2790d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
280b370df27c76fd875f3312be487868528121a4838Enrico Granata		return (self.info_bits & 0x60) == 0;
281b370df27c76fd875f3312be487868528121a4838Enrico Granata
282b370df27c76fd875f3312be487868528121a4838Enrico Granata	# this flag's name is ambiguous, it turns out
283b370df27c76fd875f3312be487868528121a4838Enrico Granata	# we must skip a length byte to get at the data
284b370df27c76fd875f3312be487868528121a4838Enrico Granata	# when this flag is False
285b370df27c76fd875f3312be487868528121a4838Enrico Granata	def has_explicit_length(self):
2860d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
287b370df27c76fd875f3312be487868528121a4838Enrico Granata		return (self.info_bits & (1 | 4)) != 4;
288b370df27c76fd875f3312be487868528121a4838Enrico Granata
289b370df27c76fd875f3312be487868528121a4838Enrico Granata	# probably a subclass of NSString. obtained this from [str pathExtension]
290b370df27c76fd875f3312be487868528121a4838Enrico Granata	# here info_bits = 0 and Unicode data at the start of the padding word
291b370df27c76fd875f3312be487868528121a4838Enrico Granata	# in the long run using the isa value might be safer as a way to identify this
292b370df27c76fd875f3312be487868528121a4838Enrico Granata	# instead of reading the info_bits
293b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_special_case(self):
2940d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
295b370df27c76fd875f3312be487868528121a4838Enrico Granata		return self.info_bits == 0;
296b370df27c76fd875f3312be487868528121a4838Enrico Granata
297b370df27c76fd875f3312be487868528121a4838Enrico Granata	def is_unicode(self):
2980d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
299b370df27c76fd875f3312be487868528121a4838Enrico Granata		return (self.info_bits & 0x10) == 0x10;
300b370df27c76fd875f3312be487868528121a4838Enrico Granata
301b370df27c76fd875f3312be487868528121a4838Enrico Granata	# preparing ourselves to read into memory
302b370df27c76fd875f3312be487868528121a4838Enrico Granata	# by adjusting architecture-specific info
303b370df27c76fd875f3312be487868528121a4838Enrico Granata	def adjust_for_architecture(self):
3040d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
305f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.pointer_size = self.valobj.GetTarget().GetProcess().GetAddressByteSize()
306f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.is_64_bit = self.pointer_size == 8
307f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.is_little = self.valobj.GetTarget().GetProcess().GetByteOrder() == lldb.eByteOrderLittle
308b370df27c76fd875f3312be487868528121a4838Enrico Granata
309b370df27c76fd875f3312be487868528121a4838Enrico Granata	# reading info bits out of the CFString and computing
310b370df27c76fd875f3312be487868528121a4838Enrico Granata	# useful values to get at the real data
311b370df27c76fd875f3312be487868528121a4838Enrico Granata	def compute_flags(self):
3120d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
313b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.info_bits = self.read_info_bits();
314b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.info_bits == None:
315b370df27c76fd875f3312be487868528121a4838Enrico Granata			return;
316b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.mutable = self.is_mutable();
317b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.inline = self.is_inline();
318b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.explicit = self.has_explicit_length();
319b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.unicode = self.is_unicode();
320b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.special = self.is_special_case();
321b370df27c76fd875f3312be487868528121a4838Enrico Granata
322b370df27c76fd875f3312be487868528121a4838Enrico Granata	def update(self):
3230d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
324b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.adjust_for_architecture();
3258f18240a09893310c43673901d863892ae7b0611Enrico Granata		self.compute_flags();
326