swift-类属性

860 阅读2分钟

了解属性之前,需要先了解前面的swift-类结构内容 - swift-类结构源码探寻

FieldDescriptor

TargetClassDescriptor {
    var Flags: ContextDescriptorFlags  // uint32
    var Parent: TargetRelativeContextPointer // Int32
    var Name: TargetRelativeDirectPointer // Int32
    var AccessFunctionPtr: TargetRelativeDirectPointer // Int32
    var Fields: FieldDescriptor // 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部分
}

其中 Fields 记录了当前的属性信息, 源码结构如下

// Field descriptors contain a collection of field records for a single
// class, struct or enum declaration.
struct FieldDescriptor {
    MangledTypeName int32
    Superclass int32  
    Kind uint16  
    FieldRecordSize uint16 
    NumFields uint32  // 应该就是多少个属性了
}

并未发现有属性,至此,如果是你的话,你会怎么继续探究源码来确定类的属性结构

按部就班,如果源码没有直给的信息,那就从给定的方法去找,总归会有关联的

image.png

继续 搜索, 盲目搜搜了一圈,同时FieldDescriptor全局搜索 getFields(), 根据找到的内容多属于猜测的成分,不得不意识到,已经迷失目标了

其实,回过头来

image.png

熟悉的东西又来了

指针偏移,也就是 FieldDescriptor 结构内存 向下平移自己所占的内存空间,得到 FieldRecord

FieldRecords 记录了每个属性的信息

struct FieldRecord {
    Flags uint32
    MangledTypeName int32
    FieldName int32
}

FieldRecord应该就是目标了,有FieldName属性,一个属性自然一个FieldName,自然会有多个FieldRecords [FieldRecord]

补充 FieldDescriptor

struct FieldDescriptor {
    MangledTypeName int32
    Superclass int32  
    Kind uint16  
    FieldRecordSize uint16 
    NumFields uint32  // 应该就是多少个属性了
    FieldRecords [FieldRecord]
}

至于 最终属性的获取

image.png

image.png

image.png

内存迭代器出现了

image.png

再次回看细节

多个FieldRecord 应该是连续的

此时找到内存块的第一个 FieldRecord,

image.png

image.png

Flags 占用4字节内存, 主要是起到标识作用

MangledTypeName 占4字节

FieldName 占4字节

在上面找到的第一个FieldRecord内存基础上,需要继续偏移 两个4字节,第3个4字节为 属性名称,

其实 找到的FieldName 还不是 最终目标

RelativeDirectPointer FieldName, 这里是 name的相对偏移量

所以第3个4字节的位置 + 偏移量,最终得到目标属性

类属性与MachO

  • descriptor image.png

    0x7AC8 + 0xFFFFDF60 = 0x100005A28

    0x100005A28 - 虚拟基址0x100000000 = 0x5A28

  • descriptor内存

image.png

0x5A38 + 0x2010 = 0x7A48

  • FieldDescriptor内存

image.png

0x7A48 + 4个4字节 = 0x7A58

0x7A58 开始,偏移到第3个4字节即为 FileRecord.FieldName

0x7A60 + 0xFFFFFFB3 = 0x100007A13

0x100007A13 - 虚拟基址0x100000000 = 0x7A13

  • FieldName 内存

image.png