緊跟 swift-類結(jié)構(gòu)源碼探尋(一)炊邦,繼續(xù) TargetClassDescriptor分析
TargetClassDescriptor 中包含了超長(zhǎng)的基類描述验残,超多的using
我們分析主干思路,重在檢索數(shù)據(jù)結(jié)構(gòu)蛇损,暫時(shí)無關(guān)的信息暫時(shí)忽略掉
先從 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 注釋信息
結(jié)合 探尋(一) 關(guān)于 Description: TargetClassDescriptor 越界描述
大概意思是 偏移出 metadata結(jié)構(gòu) 之外琢融,還存在的一些信息
接下來就是 進(jìn)一步分析偏移出 metadata結(jié)構(gòu) 之外的信息了, 既然提到了vector疗琉,不妨看下 探尋(一) 中生成的sil文件
既然暫時(shí)線性邏輯分析 遇到阻礙业栅,進(jìn)一步猜想秒咐,根據(jù)前面的 FieldOffsetVectorOffset 注釋說明,需要找到 Descriptor 結(jié)構(gòu)之后的偏移數(shù)據(jù)
跳轉(zhuǎn)到 sil
繼續(xù)在 Metadata.h 中搜索vtable 關(guān)鍵字
發(fā)現(xiàn)了 vtable判斷邏輯碘裕,有vtable的條件下携取,獲取trailingObjects, 說白了 就是尾部的偏移邏輯了
TargetClassDescriptor 繼承父類
其中包含一個(gè) TargetVTableDescriptorHeader,繼續(xù)分析
這樣帮孔,跟前面的分析中斷處有了 銜接雷滋,VtableOffset 與 VtableSize 分別是
TargetClassDescriptor 結(jié)構(gòu)之后的 偏移結(jié)構(gòu)的 offset 與 偏移結(jié)構(gòu)大小
繼續(xù)補(bǔ)充結(jié)構(gòu)
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 結(jié)構(gòu)基本梳理完
swift oc 兼容緣由
注釋很明確,所有堆開辟類型的元數(shù)據(jù) 通用結(jié)構(gòu) -- TargetHeapMetadata
全局搜索 HeapMetadata, 其中慢慢篩選過濾你弦, HeapObject.h 中有包含 HeapMetadata 屬性
struct HeapObject {
var metadata: HeapMetadata // UnsafeRawPointer 8字節(jié)
var refCount1 // UInt32
var refCount2 // UInt32
}
驗(yàn)證HeapObject結(jié)構(gòu)
閱讀vtable部分源碼
全局搜索 VTableOffset
好在 結(jié)果不多惊豺,方便篩選
篩選掉明顯不需要花精力閱讀的文件及sil文件燎孟,鎖定兩個(gè)文件 GenMeta.cpp 與 MedataLayout.cpp 兩個(gè)文件
先通過 MedataLayout.cpp 中查看
找到 addVTableEntries
在GenMeta.cpp 中搜索結(jié)果定位的位置 發(fā)現(xiàn)關(guān)鍵字 VTableEntries
在 GenMeta.cpp 中搜索 addVTableEntries, 找到了調(diào)用
目光之余 發(fā)現(xiàn)了 addVTable()
通過繼承關(guān)系禽作,找到父類 layout()
通過跋涉,終于看到了直給的東西
正好對(duì)應(yīng) 前面整理的結(jié)構(gòu)
addVTable 邏輯
正好對(duì)應(yīng) TargetClassDescriptor結(jié)構(gòu)最后部分
var VTableOffset: uint32_t
var VTableSize: uint32_t
// ......... VTable部分
復(fù)習(xí)MachO驗(yàn)證
回想swift-類結(jié)構(gòu)源碼探尋(一)中的驗(yàn)證部分邏輯
這里存放的就是 clsss/struct/enumor descriptor的內(nèi)存地址信息
0x7ABC + 0xFFFFFB80 = 0x10000763C
0x10000763C - 虛擬基址0x100000000 = 0x763C
通過這里 結(jié)合 Descriptor 結(jié)構(gòu)信息 進(jìn)行地址偏移揩页,偏移13個(gè)4字節(jié)
0x7670 就是VTable部分
其中 0x7670 基址開始的第一個(gè)4字節(jié)為 method描述 Flags
0x7670 + 0x4 + offset(0xFFFFC4D0) - 虛擬基址0x100000000 + ALSR = 方法內(nèi)存地址