概述:
從點擊應用到執(zhí)行 main()
之前,系統(tǒng)進行了以下行為:
-
Load dylibs
:遞歸映射所有依賴的動態(tài)庫(dylibs) -
Rebase
:對所有圖像進行重設基址 -
Bind
:對所有圖像進行綁定 -
Notify ObjC Runtime
:運行時操作 -
Initializers
:初始化
注意:
這里的圖像是 Mach-O
中的術語,指所有文件類型。
Mach-O
有三種文件類型
- Executable:應用程序的二進制文件;
- Dylib:動態(tài)庫嫩絮;
- Bundle:無法被鏈接的動態(tài)庫,只能通過 dlopen() 打開碘勉;
所有的Executable
板辽、Dylib
奇瘦、Bundle
稱為Image
。
Loading Dylibs
第一個執(zhí)行的是加載動態(tài)庫劲弦,首先需要去解析所有依賴的動態(tài)庫的列表耳标,找到 App
需要的所有 mach-o
文件。找到動態(tài)庫后邑跪,需要打開并讀取每個文件次坡,在此過程中,驗證 mach-o
文件的有效性呀袱,依次注冊代碼簽名贸毕。最后對每個 segment
調(diào)用 mmap()
方法。
加載一個動態(tài)庫后需要遞歸加載每個依賴的動態(tài)庫夜赵,一個 App
大約有 400
多個動態(tài)庫明棍,其中大部分是系統(tǒng)動態(tài)庫。
Fix-ups
加載完所有的動態(tài)庫后寇僧,動態(tài)庫只是一個個單獨的存在摊腋,此時需要通過 fix-ups
使動態(tài)庫相互關聯(lián)。在 __DATA segment
中有一個指針嘁傀,可以用來跳轉(zhuǎn)兴蒸。
fix-ups
分為兩種,rebase
和 bind
细办。rebase
是在圖像內(nèi)部調(diào)整指針橙凳;而 bind
是在圖像外部調(diào)整指針。
Rebase
因為 ASLR(Address space layout randomization)
使所有動態(tài)庫被加載到隨機地址上笑撞,所以需要 rebase
遍歷所有的內(nèi)部數(shù)據(jù)指針岛啸,然后為它們添加一個地址偏移值。
Bind
Bind
針對那些指向動態(tài)庫之外的指針茴肥,這些指針通過名稱綁定坚踩。運行時,dylb
通過符號名找到實現(xiàn)該符號的位置瓤狐,主要是遍歷查找符號表瞬铸,當找到時把值存到該數(shù)據(jù)指針中。
Notify ObjC Runtime
ObjC
是動態(tài)語言础锐,可以在運行時通過類名把類實例化嗓节,所以在運行時,ObjC
需要維護一張包含所有類與其映射的表格郁稍。每個加載類時赦政,在這個全局表格中注冊類名。在運行時還會把定義的 Category
插入到方法列表中。
Selector
對于 ObjC
是唯一的恢着。
Initializers
調(diào)用所有類的 +(void)load
方法桐愉,對所有動態(tài)庫初始化。需要從下到上初始化掰派,因為上層的一些動態(tài)庫可能依賴于下層的動態(tài)庫从诲,所以先初始化下層的動態(tài)庫保證所有的動態(tài)庫都可以正確初始化。
當所有的動態(tài)庫初始化完成后靡羡,最終調(diào)用主 dylib
程序系洛,也就是 main()
。
總結(jié)
Dyld
是一個輔助程序略步,主要功能
- 加載所有依賴庫描扯;
- 修復所有
DATA
頁面的指針; - 運行所有構(gòu)造器初始化趟薄,并最終調(diào)用
mian()
绽诚。