Mach-O學(xué)習(xí)筆記

Mach-O文件結(jié)構(gòu)

image.png
  • Header部分:描述文件基本信息(如CPU、架構(gòu)、文件類型、加載命令個數(shù))
  • loadCommands部分:描述各個Data部分的內(nèi)存分布,對系統(tǒng)內(nèi)核加載器和動態(tài)連接器起指導(dǎo)作用
  • Data部分:存放代碼與數(shù)據(jù)

    • __PAGEZERO段:空指針陷阱段,映射到虛擬內(nèi)存空間的第一頁,用于捕捉對NULL指針的引用
    • __TEXT 段: 包含了執(zhí)行代碼以及其他只讀數(shù)據(jù)的,當(dāng)這個段被映射到內(nèi)存后,可以被所有進(jìn)程共享。(這主要用在frameworks, bundles和共享庫等程序中,也可以為同一個可執(zhí)行文件的多個進(jìn)程拷貝使用)
    section 描述
    __text 代碼實(shí)現(xiàn)
    __stubs 符號樁,本質(zhì)上就是段會直接跳入到lazybinding的表的對應(yīng)項(xiàng)指針指向的地址的代碼
    __stubs_helper 輔助函數(shù),上述lazybinding表中沒有找到符號地址都指向這
    __cstring C string字符串常量
    __ustring Unicode string中文常量
    __objc_methname OC方法名稱
    __objc_classname OC類名
    __objc_methtype OC方法類型
    __entitlements 簽名證書
    __unwid_info 用于存儲異常情況信息
    __const 初始化的常量
    • __DATA段: 包含了程序數(shù)據(jù),該段可寫;
    section 描述
    __const 未始化的常量
    __bss 沒有初始化和初始化為0 的全局變量
    __nl_symbol_prt / __got 非lazy-binding的指針表
    __la_symbol_prt lazy-binding的指針表,每個表項(xiàng)中的指針一開始指向stub_helper
    __cfstring CoreFoundation string
    __objc_classlist OC類列表
    __objc_catlist OC分類列表
    __objc_protollist OC協(xié)議列表
    __objc_imageinfo OC鏡像信息
    __objc_const OC類信息、方法列表、屬性列表、變量列表
    __objc_selfrefs OC類實(shí)例自引用(self)
    __objc_classfrefs OC類類自引用
    __objc_superrefs OC類超類引用(super)
    __objc_ivar OC屬性
    __objc_data OC類ISA
    • __LINKEDIT段: 含有為動態(tài)鏈接庫使用的原始數(shù)據(jù),比如符號,字符串,重定位表?xiàng)l目等等。

App啟動流程

  1. 將Mach-O中Segment與符號表等數(shù)據(jù)映射到內(nèi)存中
  2. 調(diào)用dyld(the dynamic link editor)程序,動態(tài)鏈接器
  3. 加載UUID與構(gòu)建二進(jìn)制是的的源碼版本等信息
  4. 設(shè)置程序主線程的main函數(shù)入口地址和棧大小
  5. 設(shè)置依賴的動態(tài)庫
  6. 加載代碼開始地址、代碼段內(nèi)的非指令的表、代碼簽名
  7. 系統(tǒng)kernel做好啟動程序的初始準(zhǔn)備后,動態(tài)鏈接依賴庫,并由runtime負(fù)責(zé)加載成objc定義的結(jié)構(gòu),所有初始化工作結(jié)束后,dyld調(diào)用真正的main函數(shù)
    1. 從kernel留下的原始調(diào)用棧引導(dǎo)和啟動自己

    2. 將程序依賴的動態(tài)鏈接庫遞歸加載進(jìn)內(nèi)存,系統(tǒng)有緩存機(jī)制

      1. 交由imageLoader讀取image,其中包含了我們的類,方法等各種符號
      2. 由于runtime向dyld綁定了回調(diào),當(dāng)image加載到內(nèi)存后,dyld會通知runtime進(jìn)行處理
      3. runtime接手后調(diào)用map_images做解析和處理,接下來load_images中調(diào)用call_load_methods方法,遍歷所有加載進(jìn)來的Class,按繼承層級依次調(diào)用Class的+load方法和Category的+load方法
    3. non-lazy符號立即link到可執(zhí)行文件,lazy的存表里

    4. 找到可執(zhí)行文件的main函數(shù),準(zhǔn)備參數(shù)并調(diào)用

    5. 程序執(zhí)行中負(fù)責(zé)綁定lazy符號、提供runtime dynamic loading services、提供調(diào)試器接口。

    6. 程序main函數(shù)return后執(zhí)行static terminator

    7. 某些場景下main函數(shù)結(jié)束后調(diào)libSystem的_exit函數(shù)。

參考

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

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

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