ISA analyzes to metaclass

A previous article on iOS Underground-Object Nature &ISA analysis explored ISA.

Print the pointer to P 0x00000001089C94f0, obtain ISA 0x011D800100008365 according to the pointer address and mask memory offset 0x00007ffffFFFF8 to get 0x0000000100008360. Po gets the current class XHPerson.

Continue to analyze the obtained 0x0000000100008360, perform memory offset 0x00007FFFFFFFFff8 to get 0x0000000100008338, Po to get the current class is also XHPerson. It follows that XHPerson: the class will be infinite with our objects, and there will be more than one class in memory. Verify printing the following code:

Class class1 = [XHPerson Class]; void lgTestClassNum(void){Class class1 = [XHPerson Class]; Class class2 = [XHPerson alloc].class; Class class3 = object_getClass([XHPerson alloc]); Class class4 = [XHPerson alloc].class; NSLog(@"\n%p-\n%p-\n%p-\n%p",class1,class2,class3,class4); } // Result 2021-06-21 15:23:32.247341+0800 002-ISA analysis [13938:273705] 0x100008360-0x100008360-0x100008360-0x100008360Copy the code

0x0000000100008360 is a class, 0x0000000100008338 is not a class. It’s called a metaclass.

Do x/4gx to the metaclass to get 0x00007FFF88a2AC20 and continue with the memory offset 0x00007FFFFFFFFFF8 to get 0x00007FFF88a2AC20 again, Po to get NSObject.

Means currentNSObjectThis class ofisaPoint to theNSObjectThe metaclass. It can be concluded according to the above analysis.

Isa bitmap and inheritance chain

  • Object ISA -> class ISA -> metaclass ISA -> root metaclass ISA -> root metaclass
  • Root class ISA -> root metaclass ISA

Isa walk a

  • Instance objectsThe instance of ttf_subclassisaPoint to theclassThe class.
  • classA class ofisaPoint to theThe metaclassMeta class.
  • The metaclassMeta classisaPoint to theA metaclass NSObject(root metal class).
  • A metaclass NSObjectThe root of meta classisaPointing at itself, forming a closed loop.

Print the following code,

#pragma mark - NSObject metaclass chain void lgTestNSObject(void){ // NSObject Class Class = object_getClass(object1); // NSObject metaClass = object_getClass(Class); // NSObject rootMetaClass Class rootMetaClass = object_getClass(metaClass); // NSObject rootMetaClass Class rootRootMetaClass = object_getClass(rootMetaClass); NSLog (@ "\ n \ n % p % p instance objects class p metaClass \ n \ n % % p root metaClass \ n % p spikes metaClass", object1, class, metaClass, rootMetaClass, rootRootMetaClass); // pMetaClass = object_getClass(xhperson.class); Class psuperClass = class_getSuperclass(pMetaClass); NSLog(@"XHPerson metaclass %@ - %p",psuperClass,psuperClass); Class tMetaClass = object_getClass(xhteacher.class); // XHTeacher -> XHPerson -> NSObject Class tsuperClass = class_getSuperclass(tMetaClass); NSLog(@"XHTeacher metaclass %@ - %p",tsuperClass,tsuperClass); // NSObject Root Class special case Class nsuperClass = class_getSuperclass(nsobjject); NSLog(@"NSObject metaclass %@ - %p",nsuperClass,nsuperClass); // root metaClass -> NSObject Class = class_getSuperclass(metaClass); NSLog (@ "root metaclass % @ - % p", rnsuperClass, rnsuperClass); } // Result 2021-06-21 16:02:30.535430+0800 002-ISA analysis [14411:327183] 0x108B06850 Instance object 0x7FFF88A2AC48 class 0x7FFF88A2AC20 metaclass 2021-06-21 16:02:30.535501+0800 002-ISA analysis [14411:327183] XHPerson metaclass NSObject - 0x7FFF88A2AC20 2021-06-21 16:02:30.535531+0800 002-ISA analysis [14411:327183] XHTeacher meta-xhPerson - 0x100008338 2021-06-21 16:02:30.535554+0800 002-ISA analysis [14411:327183] NSObject metaclass (NULL) -0x0 2021-06-21 16:02:30.535576+0800 002-ISA analysis [14411:327183] root metaclass nSObjject 0x7FFF88a2AC48Copy the code

Image courtesy of Apple

Superclass inheritance

Class inheritance

  • classTtf_subclass inherited fromThe parent classSuperClass.
  • The parent classSuperClass inherited fromThe root class NSObjectRootClass.
  • The root class NSObjectInherited fromnilIs that whyNSObjectIs the root class.

Inheritance of metaclasses

  • The metaclass of a subclassMetal subClass inherits fromThe metaclass of the parent classThe metal superClass.
  • The metaclass of the parent classMetal superClass inherits fromA metaclassRoot metal class.
  • A metaclassRoot Metal class inherits fromThe root class NSObjectThe root class.

The structure of the class

Memory migration

To analyze the structure of a class, you need to understand the memory offset. When you want to retrieve the contents of the class, you need to obtain the memory offset.

Ordinary pointer

  • aandbThey both point to 10, butaandbAddresses are different, addresses are different by 4 bytes, becauseaandbAre allintType.

Pointer to the object

  • p1andp2It’s also a pointer that points toXHPerson allocMemory address created.
  • &p1and&p2Is pointing top1andp2The address of the object pointer.

Pointer to an array

  • &cand&c[0]All I get out is the first address.
  • &cand&c[1]Difference of 4 bytes (difference between addresses, depending on the type of data stored).
  • You get the elements out of the array by starting with an offset, which is what we call an offsetThe array subscript.
  • The number of bytes in memory that the first address has moved = The offset * Data type Number of bytes

Class structure analysis

From the objC source code, you can get a rough idea of what’s inside objC_class, as shown below:

  • isa: Although noted here, butobjc_classInherited fromobjc_object, soobjc_classThere must beisaOf, 8 bytes.
  • superclass:ClassType, essentially a structure pointer, takes 8 bytes.
  • cacheIs:cache_tType, we can know through the source codecache_tIs a structure type whose memory size is determined by its internal properties.
  • bitsIs:class_data_bits_tType, the memory size of which cannot be retrieved, can only be retrieved by the memory offset described abovebits.

Calculate the cache memory size

Go to cache_t

foundcache_tIt’s a structure, minusstaticModifier, where only the two in the screenshot above affect its memory size:_bucketsAndMaybeMaskAnd the union we can getcache_tThis structure has a memory size of8 + 8 = 16Bytes.

Each member variable in the class has the following memory address

  • isaThe memory address of is the first address, which was explored earlier
  • superclassThe memory address of the+0x8
  • cacheThe memory address of the+0x10
  • bitsThe memory address of the+0x20

To obtain bits

Today’s focus is on bits.

Bits.data () should store data, and data() is of type class_rw_t*

Class_rw_t is a structure type that provides methods to get a list of methods, a list of attributes, and a list of protocols. To verify that methods, attributes, and variables are in class_rw_t, add attributes, methods, and member variables to the XHPerson class

Perform LLDB debugging

Attribute to explore

A property declared in a classname.hobbyStored in the property list preperty_list_t,p $7.get(0)andp $7.get(1)Gets the corresponding properties.

Object method exploration

  • Object methods are stored inXHPersonA list of methods in a classmethod_list_tIn the water.
  • The class method is not inXHPersonList of methodsmethod_list_tIn the water.
  • p $7.get(x)The specific value is not available in the method list becausemethod_tIs processed and passedbig()Get variables.

Class method inquiry

Object methods are stored in classes, so class methods may be stored in metaclasses. So let’s go with this idea

  • Class methodStored in theThe metaclassIn theMethods listIn the water.

conclusion

Class has isa, superclass, cache and BITS member variables. In the process of exploring bits, it is found that bits stores attribute list, method list, member variable list, protocol list, etc. Class methods are stored in metaclass.

Stay tuned for further class analysis.