preface
Now that we’ve explored alloc, let’s look at ISA analysis to metaclasses
oneisa
Go bitmap and inheritance chain
onelldb
debugging
So let’s just run the demo
LGPerson *test = [LGPerson alloc]; The break point is NSLog at sign"% @",test);
Copy the code
1. Run the following command on the LLDB terminal to obtain the IP address of the instance
po test
<LGPerson: 0x10500de60> Get the memory address of the instance objectCopy the code
2. Print memory
x/4gx 0x10500de60
0x10500de60(memory address):0x011d800100008365(How to prove that this is ISA)0x0000000000000000
0x10500de70: 0x0000000000000000 0x0000000000000000
Copy the code
3. Get the address pointed to by class ISA
p/x 0x011d800100008365 & 0x00007ffffffffff8
(unsigned long long) $2 = 0x0000000100008360Get the memory address of the classCopy the code
4. Print the class name
po 0x0000000100008360LGPerson (gets the class name)Copy the code
Here we can explore the isa-> (LGPerson: 0x0000000100008360) class of the instance object. We’ll keep you going
5. Print the memory of the class
x/4gx 0x0000000100008360
0x100008360: 0x0000000100008338(isa) 0x00007fff88bdfcc8
0x100008370: 0x0000000100641640 0x0002802c00000003
Copy the code
6. Get the address pointed to by class ISA
p/x 0x0000000100008338 & 0x00007ffffffffff8
$8 = 0x0000000100008338Get the memory address of the classCopy the code
7. Print the class name
po 0x0000000100008338LGPerson (gets the class name)Copy the code
Here we can explore (LGPerson: 0x0000000100008360) ISA -> (LGPerson: 0x0000000100008338)
8. Run another demo
Class class1 = [LGPerson class];
Class class2 = [LGPerson alloc].class;
Class class3 = object_getClass([LGPerson alloc]);
Class class4 = [LGPerson alloc].class;
NSLog(@"\n%p-\n%p-\n%p-\n%p",class1,class2,class3,class4); Print result address:0x100008360-
0x100008360-
0x100008360-
0x100008360And LGPerson:0x0000000100008360On the rightCopy the code
9. Look at the Mach-o file LGPerson: 0x0000000100008338, which should be metaclass
Where does isa point to (LGPerson: 0x0000000100008338)
10. Print the memory of the metaclass
x/4gx 0x0000000100008338
0x100008338: 0x00007fff88bdfca0(isa)0x00007fff88bdfca0
0x100008348: 0x00000001006419d0 0x0002e03500000003
Copy the code
11. Get the address that metaclass ISA points to
p/x 0x00007fff88bdfca0 & 0x00007ffffffffff8ULL
(unsigned long long) $10 = 0x00007fff88bdfca0Get the memory address of the classCopy the code
12. Print the class name
po 0x00007fff88bdfca0
NSObject
Copy the code
Here we can explore (LGPerson: 0x0000000100008338) isa points to the root metaclass (NSObject)
Print the memory of the root metaclass
x/4gx 0x00007fff88bdfca0
0x7fff88bdfca0: 0x00007fff88bdfca0 0x00007fff88bdfcc8
0x7fff88bdfcb0: 0x0000000100641b10 0x0003e03100000007
Copy the code
14. Get the address pointed to by the root metaclass isa
p/x 0x00007fff88bdfca0 & 0x00007ffffffffff8
(unsigned long long) $12 = 0x00007fff88bdfca0Get the memory address of the classCopy the code
15. Print the class name
po 0x00007fff88bdfca0
NSObject
Copy the code
At this point we can explore that the ROOT metaclass (NSObject) isa points to itself
Summary: Object ISA -> class (LGPerson: 0x0000000100008360) ISA -> metaclass (LGPerson: 0x0000000100008338) ISA -> Root metaclass (NSObject) ISA -> Root metaclass
16. We print nsobject.class directly
p/x NSObject.class
(Class) $14 = 0x00007fff88bdfcc8NSObject prints the memory of the class x/4gx0x00007fff88bdfcc8
0x7fff88bdfcc8: 0x00007fff88bdfca0 0x0000000000000000
0x7fff88bdfcd8: 0x0000000105007bd0 0x0002801000000003Prints the address p/x of the class0x00007fff88bdfca0 & 0x00007ffffffffff8
(long) $15 = 0x00007fff88bdfca0Print the name Po of the class0x00007fff88bdfca0
NSObject
Copy the code
Summary: root class ISA -> root metaclass ISA -> root metaclass
Two. Code debuggingisa
towards
1. NSObject instance object demo
We create LGPerson instance object to demonstrate:
3. Because LGTeacher inherits from LGPerson, LGTeacher instance object demonstrates:
Let’s explore how inherited ISA points to direct up code
Three. Code debuggingisa
Inheritance to
A. Class inheritanceisa
Point to the
1. Let’s first look at the ISA pointing to nsobject. class
Let’s take a look at the ISA pointing to lgperson. class
3. Let’s seeLGTeacher.class
theisa
Point to the
4. Let’s seeLGXiaowen.class
theisa
Point to the
Two. Metaclass inheritanceisa
Point to the
1. Let’s first look at the ISA pointing to the nsobject. class metaclass
2. Let’s seeLGPerson.class
metaclassisa
Point to the
3. Let’s seeLGTeacher.class
metaclassisa
Point to the
4. Let’s seeLGXiaowen.class
metaclassisa
Point to the
In combination with the above analysis, the following conclusions are drawn as follows
Source code analysis class structure
Pointer and memory translation
// Array pointer
int c[4] = {1.2.3.4};
int *d = c;
NSLog(@"%p - %p - %p",&c,&c[0],&c[1]);
NSLog(@"%p - %p - %p",d,d+1,d+2);
for (int i = 0; i<4; i++) {
int value = *(d+i);
NSLog(@"%d",value); } print out:002- Memory offset [38980:1658739] 0x7ffeefbff3c0 - 0x7ffeefbff3c0 - 0x7ffeefbff3c4
2021-06-20 13:41:36.896925+0800 002- Memory offset [38980:1658739] 0x7ffeefbff3c0 - 0x7ffeefbff3c4 - 0x7ffeefbff3c8
2021-06-20 13:41:37.939247+0800 002- Memory offset [38980:1658739] 1
2021-06-20 13:42:19.343718+0800 002- Memory offset [38980:1658739] 2
2021-06-20 13:42:19.343888+0800 002- Memory offset [38980:1658739] 3
2021-06-20 13:42:19.343959+0800 002- Memory offset [38980:1658739] 4
Copy the code
Get the value of the array based on the shift of the pointer memory so that we can get the value of the member variable in the class based on the first address of the class
Four. Class structure memory calculation
x/4gx LGPerson.class
0x100008380: 0x00000001000083a8 0x000000010036a140
0x100008390: 0x0000000101052a80 0x0002802800000003
0x00000001000083a8: corresponds to Class ISA0x000000010036a140: corresponds to Class superclass0x0000000101052a80: corresponds to cache_t cache0x0002802800000003: corresponds to cache_t cacheCopy the code
ISA(8 bytes)->superclass(8 bytes)->cache(how much)
cache = 8+8 = 16
So it shifts tobits
Need to move32
5. LLDB analysis class structure
1. Get the LGPerson properties
Look for the LGPerson member variable in class_rw_t
(lldb) x/4gx LGPerson.class
0x100008380: 0x00000001000083a8 0x000000010036a140
0x100008390: 0x0000000100764050 0x0002802800000003
(lldb) p (class_data_bits_t *) 0x1000083a0 // Get class_data_bits_t +32
(class_data_bits_t *) $1 = 0x00000001000083a0
(lldb) p $1->data() / / get class_rw_t
(class_rw_t *) $2 = 0x0000000100764010
(lldb) p * $2 / / check class_rw_t
(class_rw_t) $3 = {
flags = 2148007936
witness = 1
ro_or_rw_ext = {
std::__1::atomic<unsigned long> = {
Value = 4295000344
}
}
firstSubclass = nil
nextSiblingClass = NSUUID
}
// Get the attribute
(lldb) p $2.properties() / / check class_rw_t. The properties ()
(const property_array_t) $4 = {
list_array_tt<property_t, property_list_t, RawPtr> = {
= {
`list` = {
ptr = 0x0000000100008260
}
arrayAndFlag = 4295000672
}
}
}
Fix-it applied, fixed expression was:
$2->properties()
(lldb) p $4.list // Return from above
(const RawPtr<property_list_t>) $5 = {
`ptr` = 0x0000000100008260
}
(lldb) p $5.ptr
(property_list_t *const) $6 = 0x0000000100008260
(lldb) p *$6
(property_list_t) $7 = {
`entsize_list_tt`<property_t, property_list_t, 0, PointerModifierNop> = (entsizeAndFlags = 16, count = 4)
}
(lldb) p $7.get(0)
(property_t) $8 = (name = "name", attributes = "T@\"NSString\",C,N,V_name")
(lldb) p $7.get(1)
(property_t) $9 = (name = "hobby", attributes = "T@\"NSString\",C,V_hobby")
(lldb) p $7.get(2)
(property_t) $10 = (name = "desc", attributes = "T@\"NSString\",V_desc")
(lldb) p $7.get(3)
(property_t) $11 = (name = "idcard", attributes = "T@\"NSString\",N,V_idcard")
Copy the code
2. Methods for obtaining object instances
(lldb) p/x LGPerson.class
(Class) $0 = 0x0000000100008920 LGPerson
(lldb) p (class_data_bits_t *) 0x0000000100008940 / / get class_data_bits_t
(class_data_bits_t *) $1 = 0x0000000100008940
(lldb) p $1->data()
(class_rw_t *) $2 = 0x0000000100724a80 / / get class_rw_t
(lldb) p $2.methods()
(const method_array_t) $3 = {
list_array_tt<method_t, method_list_t, method_list_t_authed_ptr> = {
= {
list = {
ptr = 0x00000001000081f8
}
arrayAndFlag = 4295000568
}
}
}
Fix-it applied, fixed expression was:
$2->methods()
(lldb) p $3.list.ptr
(method_list_t *const) $4 = 0x00000001000081f8
(lldb) p * $4
(method_list_t) $5 = {
entsize_list_tt<method_t, method_list_t, 4294901763.method_t::pointer_modifier> = (entsizeAndFlags = 27, count = 10)
}
(lldb) p $5.get(0).big()
(method_t::big) $6 = {
name = "hobby"
types = 0x0000000100003e78 "@ @ 0:8 16"
imp = 0x0000000100003aa0 (KCObjcBuild`-[LGPerson hobby]) } (lldb) p $5.get(1).big() (method_t::big) $7 = { name = "sayNB" types = 0x0000000100003e80 "v16@0:8" imp = 0x0000000100003a30 (KCObjcBuild`-[LGPerson sayNB])
}
(lldb) p $5.get(2).big()
(method_t::big) $8 = {
name = "setHobby:"
types = 0x0000000100003ec4 "v24@0:8@16"
imp = 0x0000000100003ad0 (KCObjcBuild`-[LGPerson setHobby:]) } (lldb) p $5.get(3).big() (method_t::big) $9 = { name = "idcard" types = 0x0000000100003e78 "@16@0:8" imp = 0x0000000100003b40 (KCObjcBuild`-[LGPerson idcard])
}
(lldb) p $5.get(4).big()
(method_t::big) $10 = {
name = "setIdcard:"
types = 0x0000000100003ec4 "v24@0:8@16"
imp = 0x0000000100003b60 (KCObjcBuild`-[LGPerson setIdcard:]) } (lldb) p $5.get(5).big() (method_t::big) $11 = { name = "init" types = 0x0000000100003e78 "@16@0:8" imp = 0x00000001000039d0 (KCObjcBuild`-[LGPerson init])
}
(lldb) p $5.get(6).big()
(method_t::big) $12 = {
name = "name"
types = 0x0000000100003e78 "@ @ 0:8 16"
imp = 0x0000000100003a40 (KCObjcBuild`-[LGPerson name]) } (lldb) p $5.get(7).big() (method_t::big) $13 = { name = "setName:" types = 0x0000000100003ec4 "v24@0:8@16" imp = 0x0000000100003a70 (KCObjcBuild`-[LGPerson setName:])
}
(lldb) p $5.get(8).big()
(method_t::big) $14 = {
name = "desc"
types = 0x0000000100003e78 "@ @ 0:8 16"
imp = 0x0000000100003b00 (KCObjcBuild`-[LGPerson desc]) } (lldb) p $5.get(9).big() (method_t::big) $15 = { name = "setDesc:" types = 0x0000000100003ec4 "v24@0:8@16" imp = 0x0000000100003b20 (KCObjcBuild`-[LGPerson setDesc:])
}
Copy the code
3. Obtain the protocol method
(lldb) p/x LGPerson.class
(Class) $0 = 0x00000001000089d8 LGPerson
(lldb) p (class_data_bits_t *)0x00000001000089f8
(class_data_bits_t *) $1 = 0x00000001000089f8
(lldb) p $1->data()
(class_rw_t *) $2 = 0x000000010064eb80
(lldb) p $2.protocols()
(const protocol_array_t) $3 = {
list_array_tt<unsigned long, protocol_list_t, RawPtr> = {
= {
list = {
ptr = 0x00000001000082f0
}
arrayAndFlag = 4295000816
}
}
}
Fix-it applied, fixed expression was:
$2->protocols()
(lldb) p $3.list.ptr
(protocol_list_t *const) $4 = 0x00000001000082f0
(lldb) p $4.list[0]
(protocol_ref_t) $5 = 4295002672
Fix-it applied, fixed expression was:
$4->list[0]
(lldb) p (protocol_t *)$5
(protocol_t *) $6 = 0x0000000100008a30
(lldb) p * $6
(protocol_t) $7 = {
objc_object = {
isa = {
bits = 4298547400
cls = Protocol
= {
nonpointer = 0
has_assoc = 0
has_cxx_dtor = 0
shiftcls = 537318425
magic = 0
weakly_referenced = 0
unused = 0
has_sidetable_rc = 0
extra_rc = 0
}
}
}
mangledName = 0x0000000100003c0a "proDelegate"
protocols = 0x0000000100008488
instanceMethods = 0x00000001000084a0
classMethods = 0x0000000100008520
optionalInstanceMethods = nil
optionalClassMethods = nil
instanceProperties = 0x0000000100008540
size = 96
flags = 0
_extendedMethodTypes = 0x0000000100008568
_demangledName = 0x0000000000000000
_classProperties = nil
}
(lldb) p $7.instanceMethods // Instance method
(method_list_t *) $8 = 0x00000001000084a0
(lldb) p $8.get(0).big()
(method_t::big) $9 = {
name = "aaaTest:"
types = 0x0000000100003edb "v24@0:8@16"
imp = 0x0000000000000000
}
Fix-it applied, fixed expression was:
$8->get(0).big()
(lldb) p $8.get(1).big()
(method_t::big) $10 = {
name = "name"
types = 0x0000000100003e6a "@ @ 0:8 16"
imp = 0x0000000000000000
}
Fix-it applied, fixed expression was:
$8->get(1).big()
(lldb) p $8.get(2).big()
(method_t::big) $11 = {
name = "setName:"
types = 0x0000000100003edb "v24@0:8@16"
imp = 0x0000000000000000
}
Fix-it applied, fixed expression was:
$8->get(2).big()
(lldb) p $8.get(3).big()
(method_t::big) $12 = {
name = "age"
types = 0x0000000100003ec8 "i16@0:8"
imp = 0x0000000000000000
}
Fix-it applied, fixed expression was:
$8->get(3).big()
(lldb) p $8.get(4).big()
(method_t::big) $13 = {
name = "setAge:"
types = 0x0000000100003ed0 "v20@0:8i16"
imp = 0x0000000000000000
}
Fix-it applied, fixed expression was:
$8->get(4).big()
(lldb) p $7.classMethods / / class methods
(method_list_t *) $14 = 0x0000000100008520
(lldb) p $14.get(0).big()
(method_t::big) $15 = {
name = "aaaTest:"
types = 0x0000000100003edb "v24@0:8@16"
imp = 0x0000000000000000
}
Fix-it applied, fixed expression was:
$14->get(0).big()
(lldb) p $7.instanceProperties / / property
(property_list_t *) $16 = 0x0000000100008540
(lldb) p * $16
(property_list_t) $17 = {
entsize_list_tt<property_t, property_list_t, 0, PointerModifierNop> = (entsizeAndFlags = 16, count = 2)
}
(lldb) p $17.get(0)
(property_t) $18 = (name = "name", attributes = "T@\"NSString\",&,N")
(lldb) p $17.get(1)
(property_t) $19 = (name = "age", attributes = "Ti,N")
(lldb) p $17.get(2)
Copy the code