定义一个类
定义一个类,并从这个类开始讲起
@interface GPerson : NSObject {
NSString *address;
}
@property (nonatomic, copy) NSString *name;
- (void)eat;
+ (void)sleep;
@end
类的定义
typedef struct objc_class *Class;
objc_class继承于objc_object
struct objc_class : objc_object {
// Class ISA; // 继承于objc_object
Class superclass; // 父类
cache_t cache; // 缓存信息
class_data_bits_t bits; // 包含属性列表,方法列表等信息
......
}
如何探索bits中的内容?通过内存平移的方式我们来看一下bits中的内容,其中继承于objc_object所以其中有一个isa指针占8字节,superclass占8字节,cache_t是结构体类型,cache_t的16字节
properties
x/6gx拿到首地址
当前对象的地址0x10060df60,通过平移32得到0x10060df80,p (class_data_bits_t *)0x10060df80
现在我们拿到了class_data_bits_t,在class_data_bits_t中有一个data()方法,来获取一个class_rw_t类型的数据
class_rw_t* data() const {
return (class_rw_t *)(bits & FAST_DATA_MASK);
}
p $11->data()得到这个class_rw_t
p *$12看看这个结构中都有些什么
在当前的信息中并没有看到我们想象中的关于类的相关信息,查看class_rw_t的定义
struct class_rw_t {
// Be warned that Symbolication knows the layout of this structure.
uint32_t flags;
uint16_t witness;
#if SUPPORT_INDEXED_ISA
uint16_t index;
#endif
explicit_atomic<uintptr_t> ro_or_rw_ext;
Class firstSubclass;
Class nextSiblingClass;
private:
...... 中间省略部分代码
const method_array_t methods() const {
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get<class_rw_ext_t *>(&ro_or_rw_ext)->methods;
} else {
return method_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext)->baseMethods()};
}
}
const property_array_t properties() const {
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get<class_rw_ext_t *>(&ro_or_rw_ext)->properties;
} else {
return property_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext)->baseProperties};
}
}
const protocol_array_t protocols() const {
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get<class_rw_ext_t *>(&ro_or_rw_ext)->protocols;
} else {
return protocol_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext)->baseProtocols};
}
}
};
此时我们就看到了我们经常讨论的东西methods,properties,protocols,接下来通过这个方式来查看类中定义的属性
p $12.properties()
查看list属性,类型是property_list_t
继续查看ptr以及内容
其中count就是类中定义的属性的个数,通过p $12.get(0)查看到定义的name属性
这里property_t的结构
struct property_t {
const char *name;
const char *attributes;
};
另外我们还定义了一个成员变量address但并不在properties中
methods
同样的步骤我们可以拿到methods
不同的是我们此时再用get方法获取到的是空的,因为此时的method_t
struct method_t {
static const uint32_t smallMethodListFlag = 0x80000000;
method_t(const method_t &other) = delete;
// The representation of a "big" method. This is the traditional
// representation of three pointers storing the selector, types
// and implementation.
struct big {
SEL name;
const char *types;
MethodListIMP imp;
};
......
}
获取到的method_t调用big方法
依次打印会发现并没有类方法
总结
那么实例方法和成员变量到底在什么地方呢?第二篇再来探索。