原文出自【聽(tīng)云技術(shù)博客】:http://blog.tingyun.com/web/article/detail/1346

前言
最近看 ObjC的runtime 是怎么實(shí)現(xiàn) +load 鉤子函數(shù)的實(shí)現(xiàn)。進(jìn)而引申分析了 dyld 處理 Mach-O 的這部分機(jī)制。
1.簡(jiǎn)單分析 Mach-O 在dyld 中是如何被加載到內(nèi)存中的;
2.分析了 +load 的 特殊加載時(shí)機(jī);
+ load

上圖的調(diào)用棧告訴我們哪些函數(shù)被調(diào)用了。
dyld 是Apple 的動(dòng)態(tài)鏈接器;在 xnu 內(nèi)核為程序啟動(dòng)做好準(zhǔn)備后,就會(huì)將 PC 控制權(quán)交給 dyld 負(fù)責(zé)剩下的工作 (dyld 是運(yùn)行在 用戶態(tài)的, 這里由 內(nèi)核態(tài) 切到了用戶態(tài))。
每當(dāng)有新的鏡像加載之后,都會(huì)執(zhí)行 load-p_w_picpaths 方法進(jìn)行回調(diào),這里的回調(diào)是在整個(gè)ObjC runtime 初始化時(shí) -objc-init 注冊(cè)的 :

有新的鏡像被 map 到 runtime 時(shí),調(diào)用 load-p_w_picpaths 方法,并傳入最新鏡像的信息列表 infoList:

這里的鏡像就是 一些 System framework 的二進(jìn)制。
進(jìn)入 下圖函數(shù) load-p_w_picpaths-nolock 查找 load 函數(shù)

調(diào)用 prepare-load-methods 對(duì) load 方法的調(diào)用進(jìn)行準(zhǔn)備(將需要調(diào)用 load 方法的類(lèi)添加到一個(gè)列表中)

調(diào)用 -getObjc2NonlazyClassList 獲取所有的類(lèi)的列表之后,會(huì)通過(guò) remapClass 獲取類(lèi)對(duì)應(yīng)的指針,然后調(diào)用 schedule-class-load 遞歸地 將當(dāng)前類(lèi)和沒(méi)有調(diào)用 + load 父類(lèi)進(jìn)入列表。

在執(zhí)行 add-class-to-loadable-list(cls) 將當(dāng)前類(lèi)加入加載列表之前,會(huì)先把父類(lèi)加入待加載的列表,保證父類(lèi)在子類(lèi)前調(diào)用 load 方法。
在將鏡像加載到運(yùn)行時(shí)、對(duì) load 方法的準(zhǔn)備就緒,執(zhí)行 call-load-methods,開(kāi)始調(diào)用 load 方法:

其中 call-class-loads 會(huì)從一個(gè)待加載的類(lèi)列表 loadable-classes 中尋找對(duì)應(yīng)的類(lèi),然后找到 @selector(load) 的實(shí)現(xiàn)并執(zhí)行。

分析到這里,已經(jīng)能得知 load 函數(shù)是如何被調(diào)用的。

接下來(lái)分析 dyld 這部分怎么加載鏡像的
1.1 數(shù)據(jù)結(jié)構(gòu)
mach-o 文件頭 操作。

1.2 ImageLoader

每一個(gè)加載的 Mach-O 文件都會(huì)存在這樣一個(gè)ImageLoader 的 實(shí)例,上圖可以看出 這里ImageLoader是一個(gè)抽象類(lèi),每一種具體的Mach-O 文件都會(huì)繼承 ImageLoader類(lèi), 繼承關(guān)系 如下圖:

在加載時(shí)會(huì)根據(jù)Mach-O的格式不同選擇生成不用的實(shí)例。
1.3 -main


在調(diào)用-main 函數(shù)之后,做了一下幾件事情:
選擇運(yùn)行環(huán)境(iOS 模擬器)
初始化數(shù)據(jù)、設(shè)置全局變量、上下文信息
檢查文件是否Restricted
走完這些流程,就會(huì)調(diào)用 instantiateFromLoadedImage 函數(shù),開(kāi)始加載Mach-O 并且實(shí)例化 為 ImageLoader。
1.4 instantiateFromLoadedImage

這個(gè)函數(shù)做了三件事情:
檢查Mach-O 文件是否合法
初始化 ImageLoader 實(shí)例
調(diào)用addImage 函數(shù)添加 初始化后的實(shí)例到管理模塊中
1.5 isCompatibleMachO

Mach-O 文件的合法性檢查:
mach-header 中的 cputype與當(dāng)前運(yùn)行的CPU 版本是否支持
mach-header 中的 subtype 在該CPU 架構(gòu)下的所有版本都可以支持
cputype 就是CPU 平臺(tái), x86,ARM ,POWERPC 等, 而subtype 就是同一個(gè)平臺(tái)下的不同版本, 例如:arm7,arm7.
1.6 ImageLoaderMachO: : instantiateMainExecutable

該函數(shù)主要通過(guò) sniffLoadCommands 函數(shù)來(lái)判斷 Mach-O 文件是否是壓縮過(guò)的,然后分別 選擇不同的 子類(lèi)實(shí)例化。

1.7 sniffLoadCommands
這個(gè)函數(shù)主要做兩件事情
判斷Mach-O文件是classic的還是compressed的。
獲取mach-O文件的segment的數(shù)量。




1.8 ImageLoaderMachOClassic: :instantiateMainExecutable
classic 與 compressed 的初始化大同小異,先分析Classic 的實(shí)現(xiàn)

可以看到加載的核心代碼 還在 instantiateStart 函數(shù)中
1.9 instantiateStart

這里仍然沒(méi)有出現(xiàn)加載的核心代碼,只是根據(jù)之前獲得的數(shù)據(jù)申請(qǐng)分配了內(nèi)存,并計(jì)算 segments的 指針。 ImageLoaderMachOClassic 的構(gòu)造函數(shù)才是加載 的核心邏輯。
2.0 ImageLoaderMachOClassic


根據(jù)Mach-O 文件 segments 將數(shù)據(jù)加載到 內(nèi)存中, 任何返回 調(diào)用 addImage 函數(shù)。
2.1 addImage

這個(gè)函數(shù)只是做了數(shù)據(jù)更新
將p_w_picpath 添加到管理容器中
更新了內(nèi)存分布的信息
end
整個(gè)加載過(guò)程基本分為三個(gè)步驟:
合法加測(cè)
解析Mach-O文件頭信息,將segments 的具體信息 構(gòu)建到p_w_picpath 的實(shí)例中
添加p_w_picpath 到管理容器
根據(jù) dyld的源代碼的粗略分析, 更多信息需要分析 xnu 內(nèi)核代碼。
參考
ObjC runtime 源代碼
dyld 源代碼
《Mac OSX and iOS Internals》
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性?xún)r(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專(zhuān)為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。
新聞名稱(chēng):dyld加載Mach-O-創(chuàng)新互聯(lián)
分享網(wǎng)址:http://chinadenli.net/article18/dphidp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供手機(jī)網(wǎng)站建設(shè)、移動(dòng)網(wǎng)站建設(shè)、域名注冊(cè)、軟件開(kāi)發(fā)、定制網(wǎng)站、品牌網(wǎng)站設(shè)計(jì)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容