美文网首页ios底层原理
swift-类结构源码探寻(二)

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

作者: erlich | 来源:发表于2022-11-11 06:17 被阅读0次

    紧跟 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 = 方法内存地址

    相关文章

      网友评论

        本文标题:swift-类结构源码探寻(二)

        本文链接:https://www.haomeiwen.com/subject/rbxtxdtx.html