上一篇 swift-類屬性 為源碼層面類屬性結(jié)構(gòu)剖析宴倍,接下來(lái)從MachO層面驗(yàn)證讀取類屬性內(nèi)容
極簡(jiǎn)類結(jié)構(gòu)
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)
通過(guò) api - getsectdata("__TEXT", "__swift5_types", &size)
讀取到 __swift5_types 指針基址
__swift5_types 指針基址 + 存儲(chǔ)的內(nèi)容 對(duì)應(yīng)著 類結(jié)構(gòu)中的 type metadata
也就是 Metadata 結(jié)構(gòu) 首地址
// 計(jì)算當(dāng)前鏈接地址
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
// 減去虛擬基址的結(jié)果 - __swift5_types 左側(cè)的基址
var offset: UInt64 = 0
if let unwrappedPtr = ptr{
// Int 兩次轉(zhuǎn)換 轉(zhuǎn)換為UInt64, 因?yàn)闆](méi)有直接轉(zhuǎn)的方法
let intRepresentation =
UInt64(bitPattern: Int64(Int(bitPattern: unwrappedPtr)))
offset = intRepresentation - linkBaseAddress
print("offset: intRepresentation - linkBaseAddress")
print(offset)
}
linkBaseAddress = 4294967296 == 0x100000000,也就是 虛擬偏移基址
offset 31668 == 0x7BB4 也就是 MachO中 __swift5_types 基址
第一個(gè)4字節(jié)存儲(chǔ)的內(nèi)容
08 F7 FF FF 小端讀取 就是 0xFFFFF708
4294998964 轉(zhuǎn)換成16進(jìn)制 就是 0x100007BB4
0x100007BB4 - linkBaseAddress: 0x100000000 = 0x7BB4
0x7BB4 + 0xFFFFF708 = 0x1000072BC
0x1000072BC - linkBaseAddress: 0x100000000 = 0x72BC
MachO -__const讀取
這里 const 里存儲(chǔ)的是 初始化過(guò)的常量信息能庆,當(dāng)然包括類結(jié)構(gòu)初始化metadata結(jié)構(gòu)
從上一步的 metadata 結(jié)構(gòu) 首地址偏移 4個(gè)4字節(jié)位置開(kāi)始為 FieldDescriptor結(jié)構(gòu)地址
0x7BB4 + 0xFFFFF708 = 0x1000072BC
4294996668 轉(zhuǎn)換為16進(jìn)制 就是 0x1000072BC
0x1000072BC - 虛擬偏移基址0x100000000 = 0x72BC
0x72BC 從 50 00 00 80 這個(gè)位置開(kāi)始
從 50 00 00 80 偏移 4個(gè)4字節(jié) 得到 1C 07 00 00
內(nèi)存中為小端模式(高位數(shù)據(jù)存儲(chǔ)到內(nèi)存低位,低位數(shù)據(jù)存儲(chǔ)到內(nèi)存高位)存取, 反向讀取就是 0x0000071C
基址 0x72CC + 0x0000071C = 0x79E8
也就是前面提到的 metada結(jié)構(gòu)中的 FiledDescriptor結(jié)構(gòu)
MachO - 類名的讀取
29360 轉(zhuǎn)換為16進(jìn)制 -> 0x72B0
0x72B0 就是 類名的地址
FieldRecord讀取
FieldDescriptor 從第一個(gè)字節(jié)存儲(chǔ)的內(nèi)容 50 FE FF FF
按照FieldDescriptor結(jié)構(gòu)偏移 4個(gè)4字節(jié) -> 0x79F8
就是 首個(gè)FieldRecord 結(jié)構(gòu)了
0x79F8 地址結(jié)構(gòu) 按照 FieldRecord 結(jié)構(gòu) 偏移到 第3個(gè)4字節(jié)處 也就是 0x7A00 FieldName
0x7A00 + 0xFFFFFE90 = 0x100007890
0x100007890 - 虛擬偏移基址0x100000000 = 0x7890
MachO - __swift5_reflstr 讀取
獲取FieldDescriptor 指針
stride : 前面偏移過(guò)的個(gè)FieldRecord結(jié)構(gòu) 所占內(nèi)存大小 為 3個(gè)4字節(jié)即 12字節(jié)的倍數(shù)
fieldNameRelactiveAddress: FieldRecord 的 fieldName的地址脚线,
FieldRecord結(jié)構(gòu)中的fieldName 為真正屬性name的偏移
所以最終name的讀取需要 fieldNameRelactiveAddress + fieldName(為name的偏移)