swift-类结构源码探寻(二)
紧跟 swift-类结构源码探寻(一),继续 TargetClassDescriptor分析
image.pngimage.png
TargetClassDescriptor 中包含了超长的基类描述,超多的using
我们分析主干思路,重在检索数据结构,暂时无关的信息暂时忽略掉
先从 TargetClassDescriptor 属性信息 整理
TargetClassDescriptor {
var SuperclassType: TargetRelativeDirectPointer // Int32
var MetadataNegativeSizeInWords: uint32_t
var MetadataPositiveSizeInWords: uint32_t
var NumImmediateMembers: uint32_t
var NumFields: uint32_t
var FieldOffsetVectorOffset: uint32_t
}
TargetTypeContextDescriptor {
var Name: TargetRelativeDirectPointer // Int32
var AccessFunctionPtr: TargetRelativeDirectPointer // Int32
var Fields: TargetRelativeDirectPointer // Int32
}
TargetContextDescriptor {
var Flags: ContextDescriptorFlags // uint32
var Parent: TargetRelativeContextPointer // Int32
}
汇总
TargetClassDescriptor {
var Flags: ContextDescriptorFlags // uint32
var Parent: TargetRelativeContextPointer // Int32
var Name: TargetRelativeDirectPointer // Int32
var AccessFunctionPtr: TargetRelativeDirectPointer // Int32
var Fields: TargetRelativeDirectPointer // Int32
var SuperclassType: TargetRelativeDirectPointer // Int32
var MetadataNegativeSizeInWords: uint32_t
var MetadataPositiveSizeInWords: uint32_t
var NumImmediateMembers: uint32_t
var NumFields: uint32_t
var FieldOffsetVectorOffset: uint32_t
}
注意FieldOffsetVectorOffset 注释信息
image.png结合 探寻(一) 关于 Description: TargetClassDescriptor 越界描述
大概意思是 偏移出 metadata结构 之外,还存在的一些信息
接下来就是 进一步分析偏移出 metadata结构 之外的信息了, 既然提到了vector,不妨看下 探寻(一) 中生成的sil文件
既然暂时线性逻辑分析 遇到阻碍,进一步猜想,根据前面的 FieldOffsetVectorOffset 注释说明,需要找到 Descriptor 结构之后的偏移数据
跳转到 sil
image.png继续在 Metadata.h 中搜索vtable 关键字
image.png发现了 vtable判断逻辑,有vtable的条件下,获取trailingObjects, 说白了 就是尾部的偏移逻辑了
TargetClassDescriptor 继承父类
image.png其中包含一个 TargetVTableDescriptorHeader,继续分析
image.png这样,跟前面的分析中断处有了 衔接,VtableOffset 与 VtableSize 分别是
TargetClassDescriptor 结构之后的 偏移结构的 offset 与 偏移结构大小
继续补充结构
TargetClassDescriptor {
var Flags: ContextDescriptorFlags // uint32
var Parent: TargetRelativeContextPointer // Int32
var Name: TargetRelativeDirectPointer // Int32
var AccessFunctionPtr: TargetRelativeDirectPointer // Int32
var Fields: TargetRelativeDirectPointer // Int32
var SuperclassType: TargetRelativeDirectPointer // Int32
var MetadataNegativeSizeInWords: uint32_t
var MetadataPositiveSizeInWords: uint32_t
var NumImmediateMembers: uint32_t
var NumFields: uint32_t
var FieldOffsetVectorOffset: uint32_t
var VTableOffset: uint32_t
var VTableSize: uint32_t
// ......... VTable部分
}
Metadata 结构基本梳理完
swift oc 兼容缘由
image.png注释很明确,所有堆开辟类型的元数据 通用结构 -- TargetHeapMetadata
全局搜索 HeapMetadata, 其中慢慢筛选过滤, HeapObject.h 中有包含 HeapMetadata 属性
image.png image.png image.pngstruct HeapObject {
var metadata: HeapMetadata // UnsafeRawPointer 8字节
var refCount1 // UInt32
var refCount2 // UInt32
}
验证HeapObject结构
image.pngimage.png
image.png
阅读vtable部分源码
全局搜索 VTableOffset
好在 结果不多,方便筛选
筛选掉明显不需要花精力阅读的文件及sil文件,锁定两个文件 GenMeta.cpp 与 MedataLayout.cpp 两个文件
先通过 MedataLayout.cpp 中查看
找到 addVTableEntries
在GenMeta.cpp 中搜索结果定位的位置 发现关键字 VTableEntries
image.png在 GenMeta.cpp 中搜索 addVTableEntries, 找到了调用
image.png目光之余 发现了 addVTable()
通过继承关系,找到父类 layout()
image.png通过跋涉,终于看到了直给的东西
正好对应 前面整理的结构
image.pngaddVTable 逻辑
image.png正好对应 TargetClassDescriptor结构最后部分
var VTableOffset: uint32_t
var VTableSize: uint32_t
// ......... VTable部分
复习MachO验证
回想swift-类结构源码探寻(一)中的验证部分逻辑
image.png这里存放的就是 clsss/struct/enumor descriptor的内存地址信息
0x7ABC + 0xFFFFFB80 = 0x10000763C
0x10000763C - 虚拟基址0x100000000 = 0x763C
image.png通过这里 结合 Descriptor 结构信息 进行地址偏移,偏移13个4字节
image.png0x7670 就是VTable部分
image.png其中 0x7670 基址开始的第一个4字节为 method描述 Flags
0x7670 + 0x4 + offset(0xFFFFC4D0) - 虚拟基址0x100000000 + ALSR = 方法内存地址