ios底层原理

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

2022-11-11  本文已影响0人  erlich

紧跟 swift-类结构源码探寻(一),继续 TargetClassDescriptor分析

image.png
image.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.png
struct HeapObject {
    var metadata: HeapMetadata // UnsafeRawPointer 8字节
    var refCount1 // UInt32
    var refCount2 // UInt32
}

验证HeapObject结构

image.png
image.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.png

addVTable 逻辑

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.png

0x7670 就是VTable部分

image.png

其中 0x7670 基址开始的第一个4字节为 method描述 Flags

0x7670 + 0x4 + offset(0xFFFFC4D0) - 虚拟基址0x100000000 + ALSR = 方法内存地址

上一篇下一篇

猜你喜欢

热点阅读