ios底層 mach-o文件分析

前言

咱們在前面學習了,編譯最終會生成mach-o文件,那麼mach-o結構是怎麼的呢?linux

mach-o的定義

  • Mach-O實際上是Mach Object文件格式的縮寫,是mac以及iOS上可執行文件的格式, 相似於windows上的PE格式 (Portable Executable ), linux上的elf格式 (Executable and Linking Format)小程序

  • 記錄編譯後的可執行文件,對象代碼,共享庫,動態加載代碼和內存轉儲的文件格式。不一樣於 xml 這樣的文件,它只是二進制字節流,裏面有不一樣的包含元信息的數據塊,好比字節順序,cpu 類型,塊大小等。文件內容是不能夠修改的,由於在 .app 目錄中有個 _CodeSignature 的目錄,裏面包含了程序代碼的簽名,這個簽名的做用就是保證簽名後 .app 裏的文件,包括資源文件,Mach-O 文件都不可以更改。windows

常見名詞Mach-o

  • Executable 可執行文件
  • Dylib 動態庫
  • Bundle 沒法被鏈接的動態庫,只能經過dlopen()加載
  • Image 指的是Executable,Dylib或者Bundle的一種,文中會屢次使用Image這個名詞。
  • Framework 動態庫(能夠是靜態庫)和對應的頭文件和資源文件的集合

mach-o的文件結構

sd
Mach-O 的內容:

  • Mach-O Header:包含字節順序,magic,cpu 類型,加載指令的數量等
  • Load Commands:包含不少內容的表,包括區域的位置,符號表,動態符號表等。每一個加載指令包含一個元信息,好比指令類型,名稱,在二進制中的位置等。
  • 原始段數據(Raw segment data):能夠擁有多個段(segment),每一個段能夠擁有零個或多個區域(section)。每個段(segment)都擁有一段虛擬地址映射到進程的地址空間。

Mach-O Header

咱們打開machOView bash

在系統源碼中也能夠看到結構體

Load Commands

Load commands是一張包含不少內容的表。 內容包括區域的位置、符號表、動態符號表等。 微信

上圖Load Commons中的大部分字段在下表中能夠找到相關的含義

符號 含義
LC_SEGMENT_64 將文件中(32位或64位)的段映射到進程地址空間中
LC_DYLD_INFO_ONLY 動態連接相關信息
LC_SYMTAB 符號地址
LC_DYSYMTAB 動態符號表地址
LC_LOAD_DYLINKER 使用誰加載,咱們使用dyld
LC_UUID 文件的UUID
LC_VERSION_MIN_MACOSX 支持最低的操做系統版本
LC_SOURCE_VERSION 源代碼版本
LC_MAIN 設置程序主線程的入口地址和棧大小
LC_LOAD_DYLIB 依賴庫的路徑,包含三方庫
LC_FUNCTION_STARTS 函數起始地址表
LC_CODE_SIGNATURE 代碼簽名

其中LC_LOAD_DYLINKERLC_LOAD_DYLIBapp

  • LC_LOAD_DYLINKER 該字段標明咱們的MachO是被誰加載進去的。 能夠理解爲LC_LOAD_DYLINKER指向的地址是微信APP加載小程序的引擎,而咱們的MachO是小程序。在上圖中能夠看到咱們的Demo1的LC_LOAD_DYLINKER指向的地址就是dyld。dyld確實是用來加載咱們app的,在下面一節將會對dyld的源碼進行分析,講述dyld是如何對MachO進行加載的。
  • LC_LOAD_DYLIB 該字段標記了全部動態庫的地址,只有在LC_LOAD_DYLIB中有標記,咱們MachO外部的動態庫(如:Framework)才能被dyld正確的引用,不然dyld不會主動加載,這也是上篇文章,代碼注入的關鍵所在!

Data

Data 一般是對象文件中最大的部分,包含Segement的具體數據,如靜態C字符串,帶參數/不帶參數的OC方法,帶參數/不帶參數的C函數。函數

使用命令xcrun size -x -l -m main查看segment中的內容學習

顯示爲測試

Mac-mini-2:測試mac jxq$ xcrun size -x -l -m main
Segment __PAGEZERO: 0x100000000 (vmaddr 0x0 fileoff 0)
Segment __TEXT: 0x1000 (vmaddr 0x100000000 fileoff 0)
	Section __text: 0x52 (addr 0x100000ef0 offset 3824)
	Section __stubs: 0x18 (addr 0x100000f42 offset 3906)
	Section __stub_helper: 0x38 (addr 0x100000f5c offset 3932)
	Section __cstring: 0x1b (addr 0x100000f94 offset 3988)
	Section __unwind_info: 0x48 (addr 0x100000fb0 offset 4016)
	total 0x105
Segment __DATA: 0x1000 (vmaddr 0x100001000 fileoff 4096)
	Section __nl_symbol_ptr: 0x8 (addr 0x100001000 offset 4096)
	Section __got: 0x8 (addr 0x100001008 offset 4104)
	Section __la_symbol_ptr: 0x20 (addr 0x100001010 offset 4112)
	Section __cfstring: 0x20 (addr 0x100001030 offset 4144)
	Section __objc_imageinfo: 0x8 (addr 0x100001050 offset 4176)
	total 0x58
Segment __LINKEDIT: 0x1000 (vmaddr 0x100002000 fileoff 8192)
total 0x100003000
複製代碼
  • Segment __PAGEZERO
  • Segment __TEXT 包含可執行的代碼,以只讀和可執行方式映射
  • Segment __DATA 包含了將會被更改的數據,以可讀寫和不可執行方式映射。
  • Segment __LINKEDIT 包含了方法和變量的元數據,代碼簽名等信息。

總結

這裏咱們大概瞭解了mach-o文件的內容,那麼mach-o是如何執行的呢? 咱們將在下一篇文章,動態連接學習。spa

相關文章
相關標籤/搜索