iOS啓動優化之Mach-O相關術語

掃一掃關注公衆號,得到更多iOS相關內容前端


這篇文章講的是OS啓動優化相關的理論部分。安全

Mach-O術語

Mach-O是運行時可執行文件的文件類型,這些文件類型包括:app

  • 可執行文件:應用中最重要的二進制文件,也是應用擴展文件的主二進制文件。
  • Dylib:動態連接庫(又稱DSO或DLL)。動態連接庫包括:iOS中用到的全部系統framework,加載OC runtime方法的libobjc,系統級別的libSystem,例如libdispatch(GCD)和libsystem_blocks(Block)。
  • Bundle:捆綁包,不能被連接的Dylib,只能在運行時使用dlopen()加載,macOS的插件會用到它。

Image:指的是任意這三種類型。 Framework:這裏指的是一個特殊的Dylib,它有一個目錄結構用來存儲該Dylib所需的文件。函數

全部動態連接庫和靜態庫.a和全部類文件.o文件最終都由Dyld(apple的動態連接器)加載到內存中。佈局

Mach-O鏡像文件

Mach-O的鏡像文件被分割成一些segment(段),segment名字都是大寫的。全部的segments都是page(頁)大小的整數倍。優化

頁的大小跟硬件有關:加密

  • arm64上是16KB
  • 其他的爲4KB

一個Segment包含若干個sections(分區),因此section名字都是小寫的,分區不遵循頁面大小,分區間是不重疊的。 spa

幾乎全部的二進制文件都包含這三個段(segment):__TEXT,__DATA和__LINKEDIT:插件

  • TEXT段是文件的開頭,包含了Mach的頭文件、被執行的代碼和只讀常量(如C字符串)。只讀可執行(r-x)。
  • DATA段是重寫段,包含全部的:全局變量,靜態變量等。可讀寫(rw-)。
  • LINKEDIT段包含加載程序的元數據,好比函數的名稱和地址。只讀(r-)。

Mach-O的通用文件

假設你生成一個64位的iOS應用,那麼你就會有一個Mach-O文件,若是你也想讓它在32位的機器上運行,Xcode裏會發生什麼變化呢? Xcode會從新生成一個Mach-O文件,這個是爲32位生成的armv7s,以後Xcode會將這兩個文件合併成第三個文件,這個文件就是Mach-O的通用文件。線程

這個文件前端有一個頭文件,全部的頭文件都有一個全部體系的列表,它們的偏移值也在文件裏,該文件佔用一頁空間大小。

虛擬內存

虛擬內存是一個間接層。每一個進程都是一個邏輯地址空間,映射到RAM(隨機存取存儲器)的某個物理頁, 這種映射不必定是一對一的。

特色以下:

  • 若是有一個邏輯地址不映射任何物理RAM,當進程訪問該地址時,就會觸發page defult,內核會中止該線程,並試圖找出解決方案。

  • 當多個邏輯地址映射到同一物理RAM上時,會形成多進程共享內存。

  • 基於文件的映射

    • 不用一次性將整個文件讀入物理RAM,可使用分頁映射(mmap()函數)的方式讀取。也就是把文件某個段映射到進程邏輯內存的某個頁上。
    • lazy reading(懶加載)。

    總結:Dylib或者imgae的TEXT段能夠映射到多個進程,將會形成讀取遲緩,而全部這些頁面能夠在進程間共享。

  • Copy-On-Write(寫入時複製),簡稱COW。也就是多個進程共享一頁內存空間時,一旦有進程要作寫操做,它會將這頁內存內容複製一份出來,而後從新映射邏輯地址到新的RAM頁上。也就是這個進程本身擁有了那分內存的拷貝。

  • Dirty vs. clean pages:上面複製出來的副本被認爲是髒頁面,髒頁面是指含有進程特定信息的頁面。乾淨頁面是指內核能夠按照須要從新創建的頁面,好比從新讀取磁盤。髒頁面比干淨頁面要昂貴的多,

  • Permissions(權限界限):這裏指能夠標記一個頁面,可讀,可寫或可執行,或者是它們的任意組合。

Mach-O鏡像加載

在多個進程加載Mach-O鏡像時 __TEXT和__LINKEDIT是隻讀的,都是能夠共享內存的。而__DATA是可讀寫的,會產生dirty page。當dyld執行結束後,__LINKEDIT就沒用了,對應的內存頁就會被回收。

安全

兩點安全問題會影響Dyld:

  • ASLR:地址空間佈局隨機化。鏡像會在隨機的地址上加載。
  • 代碼簽名:爲了在運行時驗證Mach-O文件的簽名,並非每次重複讀入整個文件,而是把每頁的內容都生成一個單獨的加密散列值,並存儲在__LINKEDIT中。這使得文件每頁的內容在讀取時都能及時校驗並確保不被篡改。

下期預告:iOS啓動優化之從exec()到main()

相關文章
相關標籤/搜索