上一篇 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.png4294998964 转换成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.png4294996668 转换为16进制 就是 0x1000072BC
0x1000072BC - 虚拟偏移基址0x100000000 = 0x72BC
image.png0x72BC 从 50 00 00 80 这个位置开始
image.png从 50 00 00 80 偏移 4个4字节 得到 1C 07 00 00
内存中为小端模式(高位数据存储到内存低位,低位数据存储到内存高位)存取, 反向读取就是 0x0000071C
基址 0x72CC + 0x0000071C = 0x79E8
也就是前面提到的 metada结构中的 FiledDescriptor结构
image.pngMachO - 类名的读取
image.png image.png29360 转换为16进制 -> 0x72B0
0x72B0 就是 类名的地址
FieldRecord读取
image.pngFieldDescriptor 从第一个字节存储的内容 50 FE FF FF
按照FieldDescriptor结构偏移 4个4字节 -> 0x79F8
就是 首个FieldRecord 结构了
image.png0x79F8 地址结构 按照 FieldRecord 结构 偏移到 第3个4字节处 也就是 0x7A00 FieldName
0x7A00 + 0xFFFFFE90 = 0x100007890
0x100007890 - 虚拟偏移基址0x100000000 = 0x7890
MachO - __swift5_reflstr 读取
image.png获取FieldDescriptor 指针
image.png image.pngstride : 前面偏移过的个FieldRecord结构 所占内存大小 为 3个4字节即 12字节的倍数
fieldNameRelactiveAddress: FieldRecord 的 fieldName的地址,
FieldRecord结构中的fieldName 为真正属性name的偏移
所以最终name的读取需要 fieldNameRelactiveAddress + fieldName(为name的偏移)
网友评论