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