中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

dyld 加載 Mach-O

發布時間:2020-06-15 15:17:03 來源:網絡 閱讀:941 作者:聽云博客 欄目:移動開發

原文出自【聽云技術博客】:http://blog.tingyun.com/web/article/detail/1346

前言

最近看 ObjC的runtime 是怎么實現 +load 鉤子函數的實現。進而引申分析了 dyld 處理 Mach-O 的這部分機制。

1.簡單分析 Mach-O 在dyld 中是如何被加載到內存中的;

2.分析了 +load 的 特殊加載時機;

+ load

dyld 加載 Mach-O

上圖的調用棧告訴我們哪些函數被調用了。

dyld 是Apple 的動態鏈接器;在 xnu 內核為程序啟動做好準備后,就會將 PC 控制權交給 dyld 負責剩下的工作 (dyld 是運行在 用戶態的, 這里由 內核態 切到了用戶態)。

每當有新的鏡像加載之后,都會執行 load-p_w_picpaths 方法進行回調,這里的回調是在整個ObjC runtime 初始化時 -objc-init 注冊的 :

dyld 加載 Mach-O

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

dyld 加載 Mach-O

這里的鏡像就是 一些 System framework 的二進制。

進入 下圖函數 load-p_w_picpaths-nolock 查找 load 函數

dyld 加載 Mach-O

調用 prepare-load-methods 對 load 方法的調用進行準備(將需要調用 load 方法的類添加到一個列表中)

dyld 加載 Mach-O

調用 -getObjc2NonlazyClassList 獲取所有的類的列表之后,會通過 remapClass 獲取類對應的指針,然后調用 schedule-class-load 遞歸地 將當前類和沒有調用 + load 父類進入列表。

dyld 加載 Mach-O

在執行 add-class-to-loadable-list(cls) 將當前類加入加載列表之前,會先把父類加入待加載的列表,保證父類在子類前調用 load 方法。

在將鏡像加載到運行時、對 load 方法的準備就緒,執行 call-load-methods,開始調用 load 方法:

dyld 加載 Mach-O

其中 call-class-loads 會從一個待加載的類列表 loadable-classes 中尋找對應的類,然后找到 @selector(load) 的實現并執行。

dyld 加載 Mach-O

分析到這里,已經能得知 load 函數是如何被調用的。

dyld 加載 Mach-O

接下來分析 dyld 這部分怎么加載鏡像的

1.1 數據結構

mach-o 文件頭 操作。 

dyld 加載 Mach-O

1.2 ImageLoader

dyld 加載 Mach-O

每一個加載的 Mach-O 文件都會存在這樣一個ImageLoader 的 實例,上圖可以看出 這里ImageLoader是一個抽象類,每一種具體的Mach-O 文件都會繼承 ImageLoader類, 繼承關系 如下圖:

dyld 加載 Mach-O

 在加載時會根據Mach-O的格式不同選擇生成不用的實例。

1.3 -main

dyld 加載 Mach-O

dyld 加載 Mach-O

在調用-main 函數之后,做了一下幾件事情:

  1. 選擇運行環境(iOS 模擬器)

  2. 初始化數據、設置全局變量、上下文信息

  3. 檢查文件是否Restricted

走完這些流程,就會調用 instantiateFromLoadedImage 函數,開始加載Mach-O 并且實例化 為 ImageLoader。

1.4 instantiateFromLoadedImage

dyld 加載 Mach-O

這個函數做了三件事情: 

  1. 檢查Mach-O 文件是否合法 

  2. 初始化 ImageLoader 實例 

  3. 調用addImage 函數添加 初始化后的實例到管理模塊中

1.5 isCompatibleMachO

dyld 加載 Mach-O

Mach-O 文件的合法性檢查: 

  1. mach-header 中的 cputype與當前運行的CPU 版本是否支持

  2. mach-header 中的 subtype 在該CPU 架構下的所有版本都可以支持

cputype 就是CPU 平臺, x86,ARM ,POWERPC 等, 而subtype 就是同一個平臺下的不同版本, 例如:arm7,arm7.

1.6 ImageLoaderMachO: : instantiateMainExecutable

dyld 加載 Mach-O

該函數主要通過 sniffLoadCommands 函數來判斷 Mach-O 文件是否是壓縮過的,然后分別 選擇不同的 子類實例化。 

dyld 加載 Mach-O

1.7 sniffLoadCommands

這個函數主要做兩件事情 

  1. 判斷Mach-O文件是classic的還是compressed的。 

  2. 獲取mach-O文件的segment的數量。

dyld 加載 Mach-O

dyld 加載 Mach-O

dyld 加載 Mach-O

dyld 加載 Mach-O

1.8 ImageLoaderMachOClassic: :instantiateMainExecutable

classic 與 compressed 的初始化大同小異,先分析Classic 的實現 

dyld 加載 Mach-O

可以看到加載的核心代碼 還在 instantiateStart 函數中

1.9 instantiateStart

dyld 加載 Mach-O

這里仍然沒有出現加載的核心代碼,只是根據之前獲得的數據申請分配了內存,并計算 segments的 指針。 ImageLoaderMachOClassic 的構造函數才是加載 的核心邏輯。

2.0 ImageLoaderMachOClassic

dyld 加載 Mach-O

dyld 加載 Mach-O

根據Mach-O 文件 segments 將數據加載到 內存中, 任何返回 調用 addImage 函數。

2.1 addImage

dyld 加載 Mach-O

這個函數只是做了數據更新 

  1. 將p_w_picpath 添加到管理容器中

  2. 更新了內存分布的信息

end

整個加載過程基本分為三個步驟:

  1. 合法加測

  2. 解析Mach-O文件頭信息,將segments 的具體信息 構建到p_w_picpath 的實例中

  3. 添加p_w_picpath 到管理容器

根據 dyld的源代碼的粗略分析, 更多信息需要分析 xnu 內核代碼。

參考

ObjC runtime 源代碼

dyld 源代碼

《Mac OSX and iOS Internals》

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

台北县| 古交市| 宝丰县| 大连市| 定日县| 大新县| 江津市| 南靖县| 平湖市| 彭山县| 治多县| 上犹县| 大新县| 雅江县| 古浪县| 怀柔区| 揭东县| 凤冈县| 库尔勒市| 晋城| 文水县| 涞水县| 安国市| 新竹县| 稻城县| 永昌县| 恩施市| 靖宇县| 清苑县| 花莲市| 高密市| 临海市| 斗六市| 丹阳市| 临泉县| 延安市| 齐齐哈尔市| 拜城县| 双鸭山市| 南充市| 麻阳|