7.DYLD

例:

在main函數(shù)中打上斷點(diǎn)和viewController中手寫(xiě)+(void)load 方法,在應(yīng)用啟動(dòng)的時(shí)候,是viewController 中的load先斷到

bt 指令是查看函數(shù)調(diào)用棧的

up 指令在函數(shù)調(diào)用棧中往上走

可以看到?dyldbootstrap::start 函數(shù)

查看 DYLD 源碼

全局搜索?dyldbootstrap? ,然后在?dyldbootstrap 中搜索start 函數(shù),可以找到在468行,可以通過(guò) command + shift + j 定位到這個(gè)文件


const struct macho_header* appsMachHeader, (參數(shù)是machO header,是和宏定義,64位就是64位的header)

int argc,

const char* argv[],??

intptr_t slide,(ASLR,隨機(jī)值,machO加載到內(nèi)存中是,隨機(jī)加一個(gè)變量)

const struct macho_header* dyldsMachHeader,

uintptr_t* startGlue


配置環(huán)境變量

當(dāng)我們配置了環(huán)境變量的值,可以看到打印信息,在load調(diào)用前就已經(jīng)打印了環(huán)境變量的信息

配置DYLD_PRINT_OPTS 后可以看到打印的是machO 的地址

加載共享緩存

//檢查共享緩存是否為禁用狀態(tài) 但是最后一句話告訴我們iOS設(shè)備不能禁用共享緩存

主程序的實(shí)例化


sniffLoadCommands 實(shí)例化的是抽象類,需要其他子類實(shí)力化為machO 的image?

加載動(dòng)態(tài)庫(kù)

連接三方庫(kù)

自己添加的庫(kù),會(huì)根據(jù)添加的順序加載對(duì)應(yīng)的庫(kù),+(void)load方法的調(diào)用順序也是如此。

在這里進(jìn)行weak 的綁定

run主程序




有個(gè)回調(diào)方法,sNotifyObjCInit

這個(gè)時(shí)候?(*sNotifyObjCInit)(image->getRealPath(), image->machHeader()); 就會(huì)調(diào)用objc 中的方法load_images

在?_dyld_objc_notify_register? 方法中調(diào)用?registerObjCNotifiers

可以下一個(gè)符號(hào)斷點(diǎn)來(lái)調(diào)試,可以發(fā)現(xiàn)在這個(gè)方法之前framework 的load 方法都還沒(méi)有調(diào)用,所以之前的配置環(huán)境變量、加載共享緩存、實(shí)例化主程序、加載動(dòng)態(tài)庫(kù)、鏈接三方庫(kù) 操作應(yīng)該在 all Images 中。


可以通過(guò)寄存器查看 參數(shù)?


可以查看objc 源碼,可以看到第二個(gè)參數(shù)就是 load_images

可以查找load_images 方法,(函數(shù)名稱就是函數(shù)指針)

最后到?call_load_methods ,然后循環(huán)調(diào)用每一個(gè)類的loads

context.notifySingle(dyld_image_state_dependents_initialized, this, &timingInfo); 執(zhí)行完成后所有framework的load方法都已經(jīng)執(zhí)行完畢了,然后開(kāi)始加載image


doModInitFunctions 函數(shù)會(huì)執(zhí)行 c++的構(gòu)造函數(shù) (module inti function ),framework代碼注入都在這個(gè)構(gòu)造函數(shù)之前

__attribute__((constructor))voidfunc3(){ printf("func3來(lái)了 \n"); } //固定寫(xiě)法

如果多個(gè)framework 中都有l(wèi)oad 和?__attribute__ 構(gòu)造方法,那么會(huì)根據(jù)添加的順序,執(zhí)行完每一個(gè)framework 的?load 和?__attribute__ 構(gòu)造方法 才會(huì)執(zhí)行下一個(gè)??framework 的??load 和?__attribute__ 構(gòu)造方法?


可以通過(guò)machO view 看到, _mod_init_func 中有所有的構(gòu)造函數(shù)

初始化函數(shù)執(zhí)行完后,這時(shí) main 函數(shù)還沒(méi)有執(zhí)行

result = (uintptr_t)sMainExecutable->getEntryFromLC_MAIN();? 這時(shí)才開(kāi)始調(diào)用main 函數(shù),最終將result 返回


load? ->? ?構(gòu)造函數(shù) - > main?

image 的加載過(guò)程 :加載共享緩存 ->? 加載插入的庫(kù)? -> 加載三方庫(kù)? -> 加載主程序


DYLD:

- dyld加載所有的庫(kù)和可執(zhí)行文件

- dyld加載流程

? ? ?- 程序執(zhí)行從_dyld_start 開(kāi)始

? ? ?- 進(jìn)入 dyld:main 函數(shù)

? ? ? ? ? - 配置一些環(huán)境變量

? ? ? ? ? - 加載共享緩存庫(kù),一開(kāi)始就判斷是否禁用,iOS無(wú)法被禁用

? ? ? ? ? -? 實(shí)例化主程序

? ? ? ? ? - 加載動(dòng)態(tài)庫(kù)?

? ? ? ? ?- 鏈接主程序

? ? ? ? ?- 最關(guān)鍵的地方:初始化方法

? ? ? ? ? ? ? ? ?- 經(jīng)過(guò)一些列初始化到 調(diào)用 notifySingle 函數(shù)

? ? ? ? ? ? ? ? ? ? ? ? - 該函數(shù)會(huì)執(zhí)行一個(gè)回調(diào)

? ? ? ? ? ? ? ? ? ? ? ? - 通過(guò)斷點(diǎn)調(diào)試:該回調(diào)是 _objc_init初始化的時(shí)候賦值的一個(gè)函數(shù)load_Images

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? - load_images 里面執(zhí)行的是 call_load_methods函數(shù)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? -?call_load_methods 函數(shù)循環(huán)調(diào)用各個(gè)類的load方法

? ? ? ? ? ? ? ? -??doModInitFunctions 函數(shù)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?- 內(nèi)部會(huì)調(diào)用帶?__attribute__((constructor)) 的c函數(shù)

? ? ? ? ? ? ? ? -? 返回主程序的入口函數(shù),開(kāi)始進(jìn)入主程序的main函數(shù)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容