dyld 載入 Mach-O

来源:http://www.cnblogs.com/TingyunAPM/archive/2016/12/08/6143828.html
-Advertisement-
Play Games

➠更多技術乾貨請戳:聽雲博客 前言 最近看 ObjC的runtime 是怎麼實現 +load 鉤子函數的實現。進而引申分析了 dyld 處理 Mach-O 的這部分機制。 1.簡單分析 Mach-O 在dyld 中是如何被載入到記憶體中的; 2.分析了 +load 的 特殊載入時機; + load 上 ...


更多技術乾貨請戳:聽雲博客

前言

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

1.簡單分析 Mach-O 在dyld 中是如何被載入到記憶體中的;

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

+ load

1.png

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

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

每當有新的鏡像載入之後,都會執行 load-images 方法進行回調,這裡的回調是在整個ObjC runtime 初始化時 -objc-init 註冊的 :

二.png

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

三.png

這裡的鏡像就是 一些 System framework 的二進位。

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

四.png

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

五.png

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

六.png

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

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

七.png

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

八.png

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

九.png

接下來分析 dyld 這部分怎麼載入鏡像的

1.1 數據結構

mach-o 文件頭 操作。 

1.png

1.2 ImageLoader

2.png

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

16.png

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

1.3 -main

4.png

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

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

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

  3. 檢查文件是否Restricted

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

1.4 instantiateFromLoadedImage

5.png

這個函數做了三件事情: 

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

  2. 初始化 ImageLoader 實例 

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

1.5 isCompatibleMachO

6.png

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

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

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

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

1.6 ImageLoaderMachO: : instantiateMainExecutable

7.png

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

17.png

1.7 sniffLoadCommands

這個函數主要做兩件事情 

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

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

7-1.png

8.PNG

9.PNG

10.PNG

1.8 ImageLoaderMachOClassic: :instantiateMainExecutable

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

11.png

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

1.9 instantiateStart

12.png

這裡仍然沒有出現載入的核心代碼,只是根據之前獲得的數據申請分配了記憶體,並計算 segments的 指針。 ImageLoaderMachOClassic 的構造函數才是載入 的核心邏輯。

2.0 ImageLoaderMachOClassic

13.png

14.png

根據Mach-O 文件 segments 將數據載入到 記憶體中, 任何返回 調用 addImage 函數。

2.1 addImage

15.png

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

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

  2. 更新了記憶體分佈的信息

end

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

  1. 合法加測

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

  3. 添加image 到管理容器

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

參考

ObjC runtime 源代碼

dyld 源代碼

《Mac OSX and iOS Internals》

原文鏈接:http://blog.tingyun.com/web/article/detail/1346


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 嘿嘿 我也是查網上的啦 然後放到我的博客里來 下次就會了 ...
  • 一個好的app不光要用好的功能,還要有好的界面,這樣內外兼修才算得上是一個好的App。其實跟人一樣,不能只刷帥,要有內涵(看清楚哦,內涵不是指悶騷)。 ...
  • 我們在使用APP的過程中,軟體會偶爾提示我們進行版本更新,我們點擊確認更新後,會在通知欄顯示下載更新進度(已知長度的進度條)以及安裝情況(不確定進度條),這就是我們今天要實現的功能。實現效果如下: 在代碼實現功能前,我們先解釋進度條的兩種狀態: (1)顯示一個已知長度的進度條指示器(Displayi ...
  • 我們打開QQ空間的時候有個箭頭按鈕點擊之後彈出PopupWindow會根據位置的變化顯示在箭頭的上方還是下方,比普通的PopupWindow彈在屏幕中間顯示好看的多。 先看QQ空間效果圖: 這個要實現這個效果可以分幾步進行 1.第一步自定義PopupWindow,實現如圖的樣式,這個繼承PopupW ...
  • 給Android Studio項目裡面的一個文件改名以後,再提交SVN時總是提示衝突,沒辦法解決。再後來不知道怎麼弄的,每次提交時停留在SVN Performing VCS Refresh始終都不會完成,一直在那裡轉,結束掉以後Performing VCS Commit又始終都不會完成,也一直在那裡 ...
  • 原文地址: "http://www.jianshu.com/p/5358f587af38" Images.xcassets在app打包後,以Assets.car文件的形式出現在bundle中。其作用在於: 自動識別@2x,@3x圖片,對內容相同但解析度不同的圖片統一管理。 可以對圖片進行剪裁和拉伸處 ...
  • 前言 學習本系列內容需要具備一定 HTML 開發基礎,沒有基礎的朋友可以先轉至 "HTML快速入門(一)" 學習 本人接觸 React Native 時間並不是特別長,所以對其中的內容和性質瞭解可能會有所偏差,在學習中如果有錯會及時修改內容,也歡迎萬能的朋友們批評指出,謝謝 文章第一版出自簡書,如果 ...
  • 前言: 項目APP有時候會出現Crash,然後就是彈出系統強制退出的對話框,點擊關閉APP。 有的APP進行了處理,會發現,當程式出現異常的時候,會Toast一個提示“程式出現異常,3秒後將退出程式”。3秒後即關閉程式而不再顯示強制關閉的對話框。 那麼它們是如何處理沒有try-catch 捕獲到的異 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...