dyld 載入 Mach-O
原文出自【聽雲技術部落格】:http://blog.tingyun.com/web/article/detail/1346
前言
最近看 ObjC的runtime 是怎麼實現 +load 鉤子函式的實現。進而引申分析了 dyld 處理 Mach-O 的這部分機制。
1.簡單分析 Mach-O 在dyld 中是如何被載入到記憶體中的;
2.分析了 +load 的 特殊載入時機;
+ load
上圖的呼叫棧告訴我們哪些函式被呼叫了。
dyld 是Apple 的動態連結器;在 xnu 核心為程式啟動做好準備後,就會將 PC 控制權交給 dyld 負責剩下的工作 (dyld 是執行在 使用者態的, 這裡由 核心態 切到了使用者態)。
每當有新的映象載入之後,都會執行 load-images 方法進行回撥,這裡的回撥是在整個ObjC runtime 初始化時 -objc-init 註冊的 :
有新的映象被 map 到 runtime 時,呼叫 load-images 方法,並傳入最新映象的資訊列表 infoList:
這裡的映象就是 一些 System framework 的二進位制。
進入 下圖函式 load-images-nolock 查詢 load 函式
呼叫 prepare-load-methods 對 load 方法的呼叫進行準備(將需要呼叫 load 方法的類新增到一個列表中)
呼叫 -getObjc2NonlazyClassList 獲取所有的類的列表之後,會通過 remapClass 獲取類對應的指標,然後呼叫 schedule-class-load 遞迴地 將當前類和沒有呼叫 + load 父類進入列表。
在執行 add-class-to-loadable-list(cls) 將當前類加入載入列表之前,會先把父類加入待載入的列表,保證父類在子類前呼叫 load 方法。
在將映象載入到執行時、對 load 方法的準備就緒,執行 call-load-methods,開始呼叫 load 方法:
其中 call-class-loads 會從一個待載入的類列表 loadable-classes 中尋找對應的類,然後找到 @selector(load) 的實現並執行。
分析到這裡,已經能得知 load 函式是如何被呼叫的。
接下來分析 dyld 這部分怎麼載入映象的
1.1 資料結構
mach-o 檔案頭 操作。
1.2 ImageLoader
每一個載入的 Mach-O 檔案都會存在這樣一個ImageLoader 的 例項,上圖可以看出 這裡ImageLoader是一個抽象類,每一種具體的Mach-O 檔案都會繼承 ImageLoader類, 繼承關係 如下圖:
在載入時會根據Mach-O的格式不同選擇生成不用的例項。
1.3 -main
在呼叫-main 函式之後,做了一下幾件事情:
選擇執行環境(iOS 模擬器)
初始化資料、設定全域性變數、上下文資訊
檢查檔案是否Restricted
走完這些流程,就會呼叫 instantiateFromLoadedImage 函式,開始載入Mach-O 並且例項化 為 ImageLoader。
1.4 instantiateFromLoadedImage
這個函式做了三件事情:
檢查Mach-O 檔案是否合法
初始化 ImageLoader 例項
呼叫addImage 函式新增 初始化後的例項到管理模組中
1.5 isCompatibleMachO
Mach-O 檔案的合法性檢查:
mach-header 中的 cputype與當前執行的CPU 版本是否支援
mach-header 中的 subtype 在該CPU 架構下的所有版本都可以支援
cputype 就是CPU 平臺, x86,ARM ,POWERPC 等, 而subtype 就是同一個平臺下的不同版本, 例如:arm7,arm7.
1.6 ImageLoaderMachO: : instantiateMainExecutable
7.png
該函式主要通過 sniffLoadCommands 函式來判斷 Mach-O 檔案是否是壓縮過的,然後分別 選擇不同的 子類例項化。
1.7 sniffLoadCommands
這個函式主要做兩件事情
判斷Mach-O檔案是classic的還是compressed的。
獲取mach-O檔案的segment的數量。
1.8 ImageLoaderMachOClassic: :instantiateMainExecutable
classic 與 compressed 的初始化大同小異,先分析Classic 的實現
可以看到載入的核心程式碼 還在 instantiateStart 函式中
1.9 instantiateStart
這裡仍然沒有出現載入的核心程式碼,只是根據之前獲得的資料申請分配了記憶體,並計算 segments的 指標。 ImageLoaderMachOClassic 的建構函式才是載入 的核心邏輯。
2.0 ImageLoaderMachOClassic
根據Mach-O 檔案 segments 將資料載入到 記憶體中, 任何返回 呼叫 addImage 函式。
2.1 addImage
這個函式只是做了資料更新
將image 新增到管理容器中
更新了記憶體分佈的資訊
end
整個載入過程基本分為三個步驟:
合法加測
解析Mach-O檔案頭資訊,將segments 的具體資訊 構建到image 的例項中
新增image 到管理容器
根據 dyld的原始碼的粗略分析, 更多資訊需要分析 xnu 核心程式碼。
參考
ObjC runtime 原始碼
dyld 原始碼
《Mac OSX and iOS Internals》
相關文章
- Mach-O、dyldMac
- Mach-OMac
- Mach-O 探究Mac
- dyld: 神秘的 __dso_handle
- 分析Mach-O檔案Mac
- 解析Mach-o檔案Mac
- muymacho---dyld_root_path漏洞利用解析Mac
- dyld背後的故事&原始碼分析原始碼
- App啟動之Dyld在做什麼APP
- iOS 逆向 - Mach-O檔案iOSMac
- 探祕 Mach-O 檔案Mac
- 趣探 Mach-O:FishHook 解析MacHook
- iOS逆向(5)-不知MachO怎敢說自己懂DYLDiOSMac
- Mach-O檔案周邊二三事Mac
- Mach-O Inside: BSS SectionMacIDE
- Mach-O 可執行檔案Mac
- 趣探 Mach-O:符號解析Mac符號
- mach-o 檔案分析(解析類)Mac
- dyld: Library not loaded: @rpath/Alamofire.framework/AlamofireFramework
- 趣探 Mach-O:檔案格式分析Mac
- 懶載入和預載入
- iOS 如何獲取 Mach-O 的 UUIDiOSMacUI
- Vue 路由按需載入(路由懶載入)Vue路由
- 預載入與智慧預載入(iOS)iOS
- 類載入-載入時機學習
- 圖片預載入和懶載入
- 載入常量-從檔案中載入
- 五種 Mach-O 型別的淺要分析Mac型別
- mac下的LD_LIBRARY_PATH是DYLD_LIBRARY_PATHMac
- 前端效能優化 --- 懶載入&預載入前端優化
- Java 類載入器以及載入機制Java
- 類載入
- 載入模型模型
- 載入pdf
- 載入更多
- 列表載入
- 懶載入
- JS載入JS