swift-类结构源码探寻(一)

高级语言swift开发者了解源码,如何着手呢?

下载源码那是肯定的,官网链接

本文通过简单的demo实例 + 少量汇编代码查看 + swift编译器swiftc生成swift中间代码 sil语法分析来探究,最后通过 MachO进行验证

在进行之前,需要补充几个基本知识:

  • Swift编译器

    • OC是通过clang编译器,编译成IR,然后生成可执行文件.o(机器码)

    • Swift则是通过Swift编译器编译生成IR,然后生成可执行文件

      • -dump-parse -dump-ast 生成抽象语法树
      • -emit-silgen -emit-sil 生成swift中间语言
      • -emit-ir 生成llvm中间体语言 .ll文件 -emit-bc .bc文件
      • -emit-assembly 生成汇编
      • -o 编译生成可执行.out文件
image.png
  • 必要汇编指令

    • mov 将某一寄存器的值复制到另一寄存器

      mov x1, x0. 将寄存器x0的值复制到 寄存器x1中

    • add 将两个寄存器的值相加,结果保存在一个寄存器中

      add x0, x1, x2. 将寄存器 x1 与 x2的值相加,结果保存在x0中

    • sub 与add相反,就是相减

    • str 将寄存器中的值写入到内存中

      str x0, [x0, x8]. 将寄存器x0中的值 保存到 栈内存 (x1存储的基地址 + x8存储的偏移地址 = 目标内存地址)

    • ldr 将内存中的值读取到寄存器中

      ldr x0, [x1, x2]. 将 内存地址(x1存储的基地址 + x8存储的偏移地址 = 目标内存地址)中的值 放入到寄存器 x0中

    • bl 跳转到目标内存地址 无返回

      bl x8 跳转到 x8寄存器中存储的地址

    • blr 跳转到目标内存地址 有返回

    • ret 子程序 (函数调用) 返回指令, 返回地址已默认保存在寄存器 lr (x30) 中

  • Swift编译器生成sil脚本

    image.png
  • MachOView 打开 工程 - Products - xxxx.app - 展示包内容 - 黑色可执行文件

    image.png

预先查看验证过程

寄存器读取方法调用地址

由于过程比较繁琐,为了对swift类结构探究过程有个初步认识,先对验证结果有个整体认知,避免看不下去了

方法调用断点

image.png

打开汇编

image.png

分析汇编

image.png

由此 x8寄存器中存储的就是 方法调用地址

image.png

MachO得到方法调用地址

通过脚本生成的sil文件 对照 MachO data部分 swift5_types, 正好对应5个方法

image.png
image.png

以 test1为例,0x7ABC + 0xFFFFFB80(小端模式) = 0x10000763C

其中 0x100000000 为 MachO生成的虚拟内存的偏移基址

image.png

0x10000763C - 虚拟内存基址 = 0x763C

TEXT.const 为 初始化过的常量, 可以理解为 类结构初始化后的记录在此会找到记录

image.png

至于为什么偏移48字节,由于结果先行,具体结构还未知,后面会有结构分析说明

偏移48字节后,地址为 0x766C,开始的4字节表示结构大小

继续偏移4字节,得到 test1 test2 test3

image.png

image list 得到 ASLR,可自行查看科普

image.png

ASLR (0x0000000102b6c000) + 0x3B44 = 0x102B6FB44

对比前面读取的寄存器中 值

image.png

相等,验证完成

查看源码

image.png

通过查看汇编过程中,发现x8先获取到的是 type metadata的类型

如果分析过oc的类结构,就会知道获取方法是根据基址基础上偏移得到的,因此可以猜测 swift类结构属于 metadata类型

再者,swift可以兼容oc使用,会否metadata可以解析为 objc_class 或者 swift结构类型

源码全局搜索 metadata,耐心过滤,找到一个 Metadata.h文件

有一段注释 /// The common structure of all type metadata.

struct TargetMetadata

TargetMetadata 分析思路

乍一看的话,还是不太符合oc底层源码的习惯,代码表面达意不像oc那么明显

image.png

从 TargetMetadata c++基本数据结构 可以看出

TargetMetadata 的构造部分 出现了isa

基本上就坐实了 TargetMetadata 是个复合结构,兼容 oc isa结构的

多看一步

image.png

Metadata.h中全局搜索 getKind()

Metadata.h中全局搜索 getKind()

直到 出现有意义的搜索结果

image.png

如果是 type metadata 类型的话,得到 Description 结构

由此,descriptor是个重要的关键字,可能蕴含着swift类的关键信息

同时锁定了另一个关键字 TargetClassMetadata

TargetClassMetadata

image.png

阅读 struct TargetClassMetadata上面的两段注释

所有的类metadata结构 - 该数据结构直接嵌入到类的 heap metadata结构中, 同时该结构内存布局与oc内存布局兼容

再次查看截图中的 TargetClassMetadata 构造部分,看参数

base - 可能是个基址 据此偏移 找到结构中的各个属性

ivarDestroyer - 应该就是变量的属性信息了

size - 大小 alignMask - 对齐

等等,这些在加载内存中构建类结构过程中 都会用到的关键参数信息

还原 ClassMetadata 结构

    ClassMetadata {
        var Flags: ClassFlags; // uint32_t
        var InstanceAddressPoint: uint32_t
        var InstanceSize: uint32_t
        var InstanceAlignMask: uint16_t
        var Reserved: uint16_t
        var ClassSize: uint32_t
        var ClassAddressPoint: uint32_t // class object 偏移
        var Description: RawPointer<TargetClassDescriptor *> // 元数据指针
        var IVarDestroyer: RawPointer<TargetClassDescriptor *> // 元数据指针
    }

TargetClassMetadata 继承自 TargetAnyClassMetadata

image.png

image.png

进一步填充 ClassMetadata 结构

    TargetAnyClassMetadata {
        var Superclass: RawPointer<TargetClassMetadata *>
        var CacheData: <RawPointer, RawPointer>
        var Data: StoredSize // Int32
    }

整合

    Metadata {
        var Kind: StoredPointer   // Int32
        var Superclass: RawPointer<TargetClassMetadata *>
        var CacheData: <RawPointer, RawPointer>
        var Data: StoredSize // Int32
        var Flags: ClassFlags; // uint32_t
        var InstanceAddressPoint: uint32_t
        var InstanceSize: uint32_t
        var InstanceAlignMask: uint16_t
        var Reserved: uint16_t
        var ClassSize: uint32_t
        var ClassAddressPoint: uint32_t // class object 偏移
        var Description: RawPointer<TargetClassDescriptor *> // 元数据指针
        var IVarDestroyer: RawPointer<TargetClassDescriptor *> // 元数据指针
    }

至此,Metadata 有了一个相对明朗的可观结构,但 Description 分析上又会受阻,原因在于直接通过源码关联是没有任何结果的,关联不到内容

因为这个结构类型是 元指针,也就是 通过指针转换成了 整型标识的 一个指针,直接关联是没有任何意义的

此时,有两种方式可以并进去考虑

一种是从源码层面 结合上下文 及 注释去分析递进; 一种是通过前面的sil代码 结合之前的源码结构分析去考虑

Description分析

image.png

注释上看,Description是swift标识类型描述的越界信息

struct内存结构是通过内存偏移来一个一个标识出来的,也就是说 struct块偏移完内部描述结构之后,紧挨着的一段内存是不在struct描述块之内的,

但是可以通过继续偏移内存得到这样的 一个 Description块结构

继续分析 元数据指针 蕴含的 TargetClassDescriptor

TargetClassDescriptor

image.png

篇幅有限,swift-类结构源码探寻(二), 继续 TargetClassDescriptor分析

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容