ios底层原理

swift-类属性-MachO读取

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

上一篇 swift-类属性 为源码层面类属性结构剖析,接下来从MachO层面验证读取类属性内容

极简类结构

    class IFLPerson2 {
        var age: Int = 20
        var heigh: Double = 180
    }

MachO-__swift5_types读取

    var size: UInt = 0
    //__swift5_types section 的pFile
    var ptr = getsectdata("__TEXT", "__swift5_types", &size)
    print("ptr: __swift5_types")
    print(ptr)
image.png image.png image.png

通过 api - getsectdata("__TEXT", "__swift5_types", &size)

读取到 __swift5_types 指针基址

__swift5_types 指针基址 + 存储的内容 对应着 类结构中的 type metadata

也就是 Metadata 结构 首地址

image.png
    // 计算当前链接地址
    var setCommond64Ptr = getsegbyname("__LINKEDIT")
    var linkBaseAddress: UInt64 = 0
    if let vmaddr = setCommond64Ptr?.pointee.vmaddr, let fileOff = 
        setCommond64Ptr?.pointee.fileoff{
        linkBaseAddress = vmaddr - fileOff
    }
    print("linkBaseAddress: vmaddr - fileOff")
    print(linkBaseAddress)      // 0x100000000
    
    // 减去虚拟基址的结果 -  __swift5_types 左侧的基址
    var offset: UInt64 = 0
    if let unwrappedPtr = ptr{
        // Int 两次转换 转换为UInt64, 因为没有直接转的方法
        let intRepresentation = 
            UInt64(bitPattern: Int64(Int(bitPattern: unwrappedPtr)))
        offset = intRepresentation - linkBaseAddress
        print("offset: intRepresentation - linkBaseAddress")
        print(offset)
    }
image.png

linkBaseAddress = 4294967296 == 0x100000000,也就是 虚拟偏移基址

offset 31668 == 0x7BB4 也就是 MachO中 __swift5_types 基址

第一个4字节存储的内容

08 F7 FF FF 小端读取 就是 0xFFFFF708

image.png

4294998964 转换成16进制 就是 0x100007BB4

0x100007BB4 - linkBaseAddress: 0x100000000 = 0x7BB4

0x7BB4 + 0xFFFFF708 = 0x1000072BC

0x1000072BC - linkBaseAddress: 0x100000000 = 0x72BC

MachO -__const读取

这里 const 里存储的是 初始化过的常量信息,当然包括类结构初始化metadata结构

image.png

从上一步的 metadata 结构 首地址偏移 4个4字节位置开始为 FieldDescriptor结构地址

0x7BB4 + 0xFFFFF708 = 0x1000072BC

image.png

4294996668 转换为16进制 就是 0x1000072BC

0x1000072BC - 虚拟偏移基址0x100000000 = 0x72BC

image.png

0x72BC 从 50 00 00 80 这个位置开始

image.png

从 50 00 00 80 偏移 4个4字节 得到 1C 07 00 00

内存中为小端模式(高位数据存储到内存低位,低位数据存储到内存高位)存取, 反向读取就是 0x0000071C

基址 0x72CC + 0x0000071C = 0x79E8

也就是前面提到的 metada结构中的 FiledDescriptor结构

image.png

MachO - 类名的读取

image.png image.png

29360 转换为16进制 -> 0x72B0

0x72B0 就是 类名的地址

FieldRecord读取

image.png

FieldDescriptor 从第一个字节存储的内容 50 FE FF FF

按照FieldDescriptor结构偏移 4个4字节 -> 0x79F8

就是 首个FieldRecord 结构了

image.png

0x79F8 地址结构 按照 FieldRecord 结构 偏移到 第3个4字节处 也就是 0x7A00 FieldName

0x7A00 + 0xFFFFFE90 = 0x100007890

0x100007890 - 虚拟偏移基址0x100000000 = 0x7890

MachO - __swift5_reflstr 读取

image.png

获取FieldDescriptor 指针

image.png image.png

stride : 前面偏移过的个FieldRecord结构 所占内存大小 为 3个4字节即 12字节的倍数

fieldNameRelactiveAddress: FieldRecord 的 fieldName的地址,

FieldRecord结构中的fieldName 为真正属性name的偏移

所以最终name的读取需要 fieldNameRelactiveAddress + fieldName(为name的偏移)

上一篇下一篇

猜你喜欢

热点阅读