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