iOS底层探索之类的结构(中):bits
在上一篇博客里面iOS底层探索之类的结构(上):ISA已经大致的,了解了类的结构
类的结构
struct objc_class : objc_object {objc_class(const objc_class&) = delete;objc_class(objc_class&&) = delete;void operator=(const objc_class&) = delete;void operator=(objc_class&&) = delete;// Class ISA;Class superclass;cache_t cache; // formerly cache pointer and vtableclass_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
}
class_data_bits
我们主要探究是class_data_bits_t bits
,在bits
里面有我们关心的类的信息。
那么我们怎么拿呢?先看看下面这个JPPerson
类
@interface JPPerson : NSObject
{int age;
}
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *hobby;- (void)sayHello;
+ (void)sayNB;
@end
@implementation JPPerson- (instancetype)init{if (self = [super init]) {self.name = @"reno";}return self;
}
- (void)sayHello{}
+ (void)sayNB{}
@end
使用lldb
调试 x/4gx
命令打印了JPPerson
这个类的内存信息
第一个是isa
;第二个是superclass
,po
出来是NSObject
,JPPerson
是继承NSObject
的;那么以此类推,第三个是cache
,第四个是bits
。
bits
我们要了解bits
里面的data
信息,该怎么拿呢?光知道一个地址也不行啊?那么我们既然知道了isa
(首地址),是不是就可以通过指针偏移
,内存偏移
拿到呢?那么要偏移多少个呢?
要想拿到
bits
,指针在内存中必须要平移指向bits
,我知道isa
是8个字节长度,superclass
也是8个字节长度,那么cache_t呢?看看内部结构分析下
cache_t
分析得到cache_t
是16,那么加isa
和superclass
一共就是32
个字节的长度。
(lldb) x/4gx JPPerson.class
0x100008358: 0x0000000100008380 0x000000010036a140
0x100008368: 0x00000001003623c0 0x0000802800000000
(lldb) p/x 0x100008358+0x20
(long) $1 = 0x0000000100008378
(lldb) p (class_data_bits_t*)0x0000000100008378
(class_data_bits_t *) $2 = 0x0000000100008378
(lldb) p $2->data()
(class_rw_t *) $3 = 0x0000000101b06bc0
(lldb) p *$3
(class_rw_t) $4 = {flags = 2148007936witness = 0ro_or_rw_ext = {std::__1::atomic<unsigned long> = {Value = 4295000144}}firstSubclass = nilnextSiblingClass = NSUUID
}
好尴尬啊!
class_rw_t
里面没有看到我们该看到的信息啊!
class_rw_t
没有错啊!打印的信息和在class_rw_t
源码里面的结构是一样的啊?
那怎么没有呢?我们刚打印的是结构信息,里面的方法没有找到,我们继续去看看源码,看看有没有打印属性的方法。
还真有方法,你说巧不巧啊!嘿嘿
那么靓仔,直接调用properties()
不就可以了吗!
properties
(lldb) p $3.properties()
(const property_array_t) $5 = {list_array_tt<property_t, property_list_t, RawPtr> = {= {list = {ptr = 0x0000000100008198}arrayAndFlag = 4295000472}}
}Fix-it applied, fixed expression was: $3->properties()
(lldb)
调用properties()
方法得到property_array_t
property_array_t
class property_array_t : public list_array_tt<property_t, property_list_t, RawPtr>
{typedef list_array_tt<property_t, property_list_t, RawPtr> Super;public:property_array_t() : Super() { }property_array_t(property_list_t *l) : Super(l) { }
};
list_array_tt
list_array_tt
<property_t, property_list_t, RawPtr>
知道了结构,我们就一层一层的往下扒
(lldb) p $3.properties()
(const property_array_t) $5 = {list_array_tt<property_t, property_list_t, RawPtr> = {= {list = {ptr = 0x0000000100008198}arrayAndFlag = 4295000472}}
}Fix-it applied, fixed expression was: $3->properties()
(lldb) p $5.list
(const RawPtr<property_list_t>) $6 = {ptr = 0x0000000100008198
}
(lldb) p $6.ptr
(property_list_t *const) $7 = 0x0000000100008198
(lldb) p $7*
error: <user expression 9>:2:1: expected expression
;
^
(lldb) p *$7
(property_list_t) $8 = {entsize_list_tt<property_t, property_list_t, 0, PointerModifierNop> = (entsizeAndFlags = 16, count = 2)
}
(lldb) p $8.get(0)
(property_t) $9 = (name = "name", attributes = "T@\"NSString\",C,N,V_name")
(lldb) p $8.get(1)
(property_t) $10 = (name = "hobby", attributes = "T@\"NSString\",C,N,V_hobby")
(lldb)
还有谁?靓仔看到没有,JPPerson
的属性打印出来了,我们要的类的信息成功输出来了!我这该死的魅力啊!
methods()
上面打印了属性,接下来该看看方法了
(lldb) p $3.methods()
(const method_array_t) $15 = {list_array_tt<method_t, method_list_t, method_list_t_authed_ptr> = {= {list = {ptr = 0x0000000100008098}arrayAndFlag = 4295000216}}
}Fix-it applied, fixed expression was: $3->methods()
(lldb) p $15.list.ptr
(method_list_t *const) $18 = 0x0000000100008098
(lldb) p *$18
(method_list_t) $19 = {entsize_list_tt<method_t, method_list_t, 4294901763, method_t::pointer_modifier> = (entsizeAndFlags = 27, count = 6)
}
(lldb) p $19.get(0)
(method_t) $20 = {}
(lldb) p $19.get(0)
(method_t) $21 = {}
(lldb) p $19.get(1)
(method_t) $22 = {}
what ??什么鬼啊?怎么get打印不出来啊?别急继续探索下去
method_t
在源码里面发现了method_t
结构体,里面嵌套了一个big
结构体,big
里面有个SEL
还有imp
那么可以通过method_t
结构体拿到big
,就可以获取到里面的方法,源码里面也发现了获取big
方法big()
big()
(lldb) p $19.get(0).big
(method_t::big) $23 = {name = "sayHello"types = 0x0000000100003f94 "v16@0:8"imp = 0x0000000100003cd0 (JPObjcBuild`-[JPPerson sayHello])
}Fix-it applied, fixed expression was: $19.get(0).big()
(lldb) p $19.get(1).big
(method_t::big) $24 = {name = "hobby"types = 0x0000000100003f8c "@16@0:8"imp = 0x0000000100003d40 (JPObjcBuild`-[JPPerson hobby])
}Fix-it applied, fixed expression was: $19.get(1).big()
(lldb) p $19.get(2).big
(method_t::big) $25 = {name = "setHobby:"types = 0x0000000100003f9c "v24@0:8@16"imp = 0x0000000100003d70 (JPObjcBuild`-[JPPerson setHobby:])
}Fix-it applied, fixed expression was: $19.get(2).big()
(lldb) p $19.get(3).big
(method_t::big) $26 = {name = "init"types = 0x0000000100003f8c "@16@0:8"imp = 0x0000000100003c70 (JPObjcBuild`-[JPPerson init])
}Fix-it applied, fixed expression was: $19.get(3).big()
(lldb) p $19.get(4).big
(method_t::big) $27 = {name = "name"types = 0x0000000100003f8c "@16@0:8"imp = 0x0000000100003ce0 (JPObjcBuild`-[JPPerson name])
}Fix-it applied, fixed expression was: $19.get(4).big()
(lldb) p $19.get(5).big
(method_t::big) $28 = {name = "setName:"types = 0x0000000100003f9c "v24@0:8@16"imp = 0x0000000100003d10 (JPObjcBuild`-[JPPerson setName:])
}Fix-it applied, fixed expression was: $19.get(5).big()
干的漂亮!哈哈
iOS底层探索之类的结构(中):bits相关推荐
- iOS底层探索二(OC 中 alloc 方法 初探)
前言 相关文章: iOS底层探索一(底层探索方法) iOS底层探索三(内存对齐与calloc分析) iOS底层探索四(isa初探-联合体,位域,内存优化) iOS底层探索五(isa与类的关系) iOS ...
- iOS底层探索(二) - 写给小白看的Clang编译过程原理
iOS底层探索(一) - 从零开始认识Clang与LLVM 写在前面 编译器是属于底层知识,在日常开发中少有涉及,但在我的印象中,越接近底层是越需要编程基本功,也是越复杂的.但要想提升技术却始终绕不开 ...
- iOS 底层探索篇 —— KVC 底层原理
iOS 底层探索篇 -- KVC 底层原理 1. Method Swizzling的坑与应用 1.1 method-swizzling 是什么? 1.2 坑点 坑点1:method-swizzling ...
- iOS 底层探索 - 消息转发
一.动态方法解析流程分析 我们在上一章<消息查找>分析到了动态方法解析,为了更好的掌握具体的流程,我们接下来直接进行源码追踪. 我们先来到 _class_resolveMethod 方法, ...
- iOS底层基础知识-文件目录结构
一:iOS沙盒知识 出于安全考虑,iOS系统把每个应用以及数据都放到一个沙盒(sandbox)里面,应用只能访问自己沙盒目录里面的文件.网络资源等(也有例外,比如系统通讯录.照相机.照片等能在用户授权 ...
- Swift: iOS底层基础知识-文件目录结构
一:iOS沙盒知识 出于安全考虑,iOS系统把每个应用以及数据都放到一个沙盒(sandbox)里面,应用只能访问自己沙盒目录里面的文件.网络资源等(也有例外,比如系统通讯录.照相机.照片等能在用户授权 ...
- ios底层核心模板结构 - list_array_tt entsize_list_tt
探索objc底层原理过程中,经常会碰到一个模板 list_array_tt 你在类加载,方法查找,散列表,同步锁等等都会碰到这个结构,c++的模板功能十分强大,但代码看上去确实比较头疼 其实没那么糟了 ...
- app启动页数秒加载 代码_iOS 底层探索 - 应用加载
一.前导知识 以下参考自 WWDC 2016 Optimizing App Startup Time : 1.1 Mach-O Mach-O is a bunch of file types for ...
- iOS底层原理之架构设计
文章目录 何为架构? MVC - Apple版 MVC – 变种 MVP MVVM 设计模式 面试题 何为架构? 架构(Architecture):软件开发中的设计方案,类与类之间的关系.模块与模块之 ...
- iOS底层原理总结 - OC对象的本质
苹果官方文档 The Objective-C language defers as many decisions as it can from compile time and link time t ...
最新文章
- Matlab标识指令中字符的精细控制
- 【算法】螺旋方阵 上交OJ1021
- ORC文件存储格式的深入探究
- 设计模式(C++实现)--一句话总结
- element元素 取属性_js element类型的属性和方法整理
- js Promise理解,同时请求多个接口等
- 用python写网络爬虫-英文翻译
- MapInfo中MIF文件和MID文件的格式
- 程序员 -- 当我彻底放弃自私自利后,前途变得一片光明,不能过多的只是关注自己的功夫,生活不能只局限在方寸虚拟世界里
- 浏览器点击复制内容并打开微信
- Cadence PVS (Physical Verification System) rule 语法详解
- 关于TopoJSON以及制作方法
- 青龙-聚看点(稳定的毛)
- django批量修改table_Django 使用 modelformset 组件批量修改表单数据
- 界面原型设计工具开源软件
- 这些东西适合做什么?
- OD常用断点函数(转载)
- Ubuntu怎么查看电脑配置(ubuntu怎么查看系统配置)
- Python qrcode模块(生成二维码)
- 模拟浏览器操作程序(数据结构课设)
热门文章
- JS实现new关键字的功能
- linux 英汉词典程序shell+postgresql版
- Django 2.0.1 官方文档翻译: 文档目录 (Page 1)
- 构建根文件系统之busybox
- 自定义View调用onDraw方法
- cf1063A Oh Those Palindromes (贪心)
- Spring Security 3多用户登录实现之二 多登录界面展示
- C++ getline在VC6.0的一个bug(处理方法)(转)
- 编译运行Cube_slam
- Docker 容器的数据管理