重學(xué)iOS系列之APP啟動(dòng)(四)Mach-O

前文講解了dyld加載Mach-O的用戶態(tài)過程,大家都知道Mach-O代表的是蘋果系統(tǒng)的可執(zhí)行文件,那你們了解Mach-O的內(nèi)部組成嗎?我們寫的代碼存儲(chǔ)在Mach-O的什么位置,我們寫的函數(shù)方法又是怎么找到具體位置調(diào)用執(zhí)行的?本文將帶大家深入了解Mach-O文件內(nèi)部構(gòu)造。

????Mach-O就是Mach object的簡(jiǎn)寫,而Mach是早期的一個(gè)微內(nèi)核。

? ? 我們都知道Mach-O是可執(zhí)行文件,那么它到底有幾種文件類型呢?

可以在xnu源碼中,查看到Mach-O格式的詳細(xì)定義(https://opensource.apple.com/tarballs/xnu/

可以在目錄????/EXTERNAL_HEADERS/mach-o/loader.h????文件里查看到具體的宏定義。

文件類型比較多,在此筆者只介紹iOS開發(fā)中能接觸到的類型

1、MH_OBJECT ? ?: ? 我們寫的代碼 編譯后得到的目標(biāo)文件(.o) 靜態(tài)庫(kù)文件(.a),靜態(tài)庫(kù)其實(shí)就是N個(gè).o合并在一起

2、MH_EXECUTE ? ? : ? ? 這個(gè)是我們最熟悉的可執(zhí)行文件

3、MH_DYLIB ? ?: ? ?動(dòng)態(tài)庫(kù)文件,XXX.dylib ? ?XXX.framework/xx

4、MH_DYLINKER ? ?:????動(dòng)態(tài)鏈接編輯器,其實(shí)就是我們前文分析的dyld,mac存放的目錄/usr/lib/dyld

5、MH_DSYM ? ?:????存儲(chǔ)著二進(jìn)制文件符號(hào)信息的文件(常用于分析APP的崩潰信息)

我們可以在Xcode中查看或者修改target的Mach-O類型,如下圖:

那么dyld可以加載哪幾種類型的mach-o文件呢?

在dyld2.cpp文件中的loadPhase6函數(shù)中有相關(guān)的判斷:

只有MH_EXECUTE、MH_DYLIB、MH_BUNDLE這3種類型的mach-o才能被dyld加載,其余的類型都會(huì)拋出錯(cuò)誤。

MachOView

使用MachOView來具體分析Mach-O文件結(jié)構(gòu),我們可以在github上下載MachOView源碼,編譯后即可直接使用。

在具體分析之前,我們先看看蘋果官方是怎么描述的:https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/MachOTopics/0-Introduction/introduction.html

官方是這樣描述的

一個(gè)Mach-O文件包含3個(gè)主要區(qū)域:

1、Header :存儲(chǔ)著mach-o的文件類型、目標(biāo)架構(gòu)類型等

2、Load commands :描述文件在虛擬內(nèi)存中的邏輯結(jié)構(gòu)、布局(其實(shí)就是一張索引表)

3、Raw segment data :在Load commands中定義的Segment的原始數(shù)據(jù)

真實(shí)情況是不是這樣呢?我們打開MachOView,然后在頂部菜單選擇file->open->xxx 來驗(yàn)證下。

咦,怎么好像跟文檔說得不一樣。其實(shí)這是因?yàn)榧虞d的mach-o文件是個(gè)胖二進(jìn)制文件,包含了2個(gè)架構(gòu),一個(gè)arm64,一個(gè)armv7。

胖二進(jìn)制文件會(huì)比單架構(gòu)的mach-o文件多一個(gè)Fat Header段。這個(gè)段從右側(cè)的數(shù)據(jù)可以看到保存了每個(gè)架構(gòu)的一些信息,比如cup type, subtype ,偏移量offset和大小size等。

我們可以在終端使用命令:

lipo -thin arm64(架構(gòu),也可以使用armv7) XXX(胖二進(jìn)制文件路徑) -output XXX(輸出路徑)

得到分離的單架構(gòu)mach-o文件。

Header段

上圖為Header在mach-o里的存儲(chǔ)的內(nèi)容。

從Description這一列可以看出Header有這么幾項(xiàng)屬性:Magic Number、CPU Type,CPU SubType ...... 等等。

再打開之前下載的mach-o源碼頭文件,看看里面Header的數(shù)據(jù)結(jié)構(gòu)是怎么定義的。

flags為不同的文件標(biāo)簽的組合,每個(gè)標(biāo)簽占一個(gè)位,可以用位或來進(jìn)行組合,常見的標(biāo)簽有:

MH_NOUNDEFS: 該文件沒有未定義的引用

MH_DYLDLINK: 該文件將要作為動(dòng)態(tài)鏈接器的輸入,不能再被靜態(tài)鏈接器修改

MH_TWOLEVEL: 該文件使用兩級(jí)名字空間綁定

MH_PIE: 可執(zhí)行文件會(huì)被加載到隨機(jī)地址,只對(duì)MH_EXECUTE有效

更多的標(biāo)簽讀者可以在文件中自行查看。

另外一個(gè)值得關(guān)注的就是ncmds和sizeofcmds,分別指定了 LOAD_COMMAND 的個(gè)數(shù)以及總大小,從這里也大概能猜到,每個(gè) command 的大小是可變的。

Load Commands

在進(jìn)行具體分析之前,筆者先說明一下幾個(gè)重要的LC_段代表的含義。

__PAGEZERO段,__PAGEZERO是一個(gè)特殊的段,主要目的是將低地址占用,防止用戶空間訪問。個(gè)人理解這是對(duì)空指針引用類型漏洞的一種緩解措施(即常見的ESC_BAD_ACCESS錯(cuò)誤)。

__TEXT段:一般用來存放不可修改的數(shù)據(jù),比如代碼和const字符串。

__DATA:數(shù)據(jù)段,一般包括可讀寫的內(nèi)容,我們定義的靜態(tài)變量,全局變量等都存儲(chǔ)在這個(gè)段。

LC_LOAD_DYLIB(XXX):代表mach-o內(nèi)部用到了這些庫(kù),需要進(jìn)行鏈接,綁定

Load Commands是mach-o的一個(gè)索引,也是體現(xiàn)mach-o拓展性的地方,每個(gè) command 的頭兩個(gè)word分別表示類型和大小。

所有的LC_SEGMENT_64在代碼里都用上圖的結(jié)構(gòu)體來表示。

cmd:代表當(dāng)前是LC_的哪個(gè)段

cmdsize:代表當(dāng)前段的大小

segname:代表當(dāng)前段的別名,即括號(hào)內(nèi)的內(nèi)容,例如__PAGEZERO

vmaddr:代表當(dāng)前段在虛擬內(nèi)存中的地址

vmsize:代表占用了虛擬內(nèi)存的大小

fileoff:代表當(dāng)前段映射到內(nèi)存中在mach-o文件中的偏移量

filesize:代表當(dāng)前段在mach-o文件中占用空間的大小

maxprot、initprot:當(dāng)前段的權(quán)限,比如read、write、execute等

nsects:當(dāng)前段包含多少個(gè)sections,只有__TEXT、__DATA這2個(gè)段才有sections

flags:一些標(biāo)志位


從注釋翻譯的解釋完全不能明白這些fileoff、filesize等成員變量的值到底有什么作用,在mach-o中如何表現(xiàn),現(xiàn)在我們根據(jù)__TEXT的具體data來實(shí)戰(zhàn)分析結(jié)構(gòu)體各個(gè)成員變量的值到底有什么意義。

我們以__TEXT段為例:

cmd:LC_SEGMENT_64

cmdsize:1032,那么這個(gè)值的意義是什么呢?

從上圖,我們可以知道,__TEXT段的地址為00000068,1032在內(nèi)存中存儲(chǔ)的16進(jìn)制值是0x408,即Data那一列存儲(chǔ)的值。

16進(jìn)制的0x68+0x408 = 0x470,(不會(huì)算的讀者可以打開Mac自帶的計(jì)算器,在菜單欄選中 ?顯示->編程器,則可以直接進(jìn)行16進(jìn)制的加減法 ),那么我們?cè)倏纯確_TEXT段的下一個(gè)段__DATA段的起始位置是多少?

上圖可以看到__DATA段的起始位置就是00000470。

總結(jié):這個(gè)值就是告訴我們當(dāng)前segment段在mach-o中占用的總大小。

segname:__TEXT,這個(gè)沒什么好解釋的,就是當(dāng)前段的名字。

vmaddr:值為 ?0000000100000000,我們知道m(xù)ach-o映射到內(nèi)存中就是4個(gè)G的大小,而vmaddr的value換算下就是4G。

vmsize: 值為 ?0000000000F58000

這2個(gè)值要放到一起說明。

看上圖,在下方Section64(__DATA,__got)段的起始地址就是00F58000,是不是和vmsize一致?

再注意看__DATA段的上面那個(gè)段,是__TEXT段,請(qǐng)注意,Section64(XXX)段代表的是真正存放數(shù)據(jù)的段,與LC_xxx段有著本質(zhì)的區(qū)別,LC_XXX段是索引,不存放具體的數(shù)據(jù)。

而vmaddr是什么呢?其實(shí)是Mach-o文件加載到虛擬內(nèi)存的地址的起始位置,在這里每個(gè)mach-o文件都是固定的數(shù)值。讀者肯定會(huì)有疑惑,如果內(nèi)存起始地址寫死在文件里,那就相當(dāng)于我可以根據(jù)地址隨意訪問mach-o中的任意數(shù)據(jù)了嗎?

蘋果為了防止出現(xiàn)這種情況,對(duì)真實(shí)的內(nèi)存地址是做了隨機(jī)偏移的,也就是傳說中的ASLR,全稱為:Address Space Layout Randomization

也就是說,真實(shí)的地址 =?vmaddr + ASLR的偏移量

但是要注意,debug調(diào)試模式下,ASLR的值是0。


fileoff:全0,也就是說TEXT段映射的時(shí)候會(huì)將當(dāng)前文件頭部分也映射到進(jìn)程空間中。__TEXT段從0開始,不能很好的說明問題,我們?cè)倏纯確_DATA段的值

看到?jīng)],__DATA的起始位置地址就是__TEXT的大小。

filesize:0000000000F58000,前面已經(jīng)分析過了,__TEXT段到__DATA段的長(zhǎng)度就是這個(gè)長(zhǎng)度。

maxprot、initprot:VM_PROT_READ、VM_PROT_EXECUTE,說明__TEXT段的數(shù)據(jù)允許讀,允許執(zhí)行。

讀者可以再查看下__DATA段的值,為VM_PROT_READ、VM_PROT_WRITE,說明__DATA段的數(shù)據(jù)是有讀寫權(quán)限的。

nsects:值為12,說明__TEXT段有12個(gè)section。注意:只有__TEXT、__DATA這2個(gè)段才有sections

flags:為空

上面分析的是__TEXT、__DATA段的具體值代表的意思,以及怎么運(yùn)用這些值在mach-o中查找相關(guān)數(shù)據(jù)。

Load Command段還有非常多的段,不同的段,數(shù)據(jù)結(jié)構(gòu)也不一定相同,但是數(shù)據(jù)分析都是大同小異的。對(duì)于后續(xù)的其他段的數(shù)據(jù)結(jié)構(gòu)不再一一詳細(xì)分析,所有的數(shù)據(jù)結(jié)構(gòu)都在XNU源碼的"/EXTERNAL_HEADERS/mach-o/loader.h"這個(gè)目錄下有定義,有興趣的讀者可以自行查閱。

Section64

需要注意的是如果segment包含一個(gè)或者多個(gè)section,那么在該segment結(jié)構(gòu)體之后就緊跟著對(duì)應(yīng)各個(gè)section頭,總大小也包括在cmdsize之中,其結(jié)構(gòu)如下

從上面的lc_segment_64結(jié)構(gòu)體分析,發(fā)現(xiàn)很多成員變量都是相似的。相信讀者肯定可以get到section_64結(jié)構(gòu)體各個(gè)成員變量的具體含義。

筆者在此僅以Section64 Header(__text)為例

之前筆者已經(jīng)告訴大家這其實(shí)是個(gè)索引,真正存放數(shù)據(jù)的位置不在這,那么在哪呢?看上圖右側(cè),offset的值為00005940,真正的代碼數(shù)據(jù)起始地址就在mach-o偏移00005940的位置。我們滑動(dòng)鼠標(biāo)滾輪往下找到Section64(__TEXT,__text)來驗(yàn)證一下。

沒錯(cuò)吧。我們?cè)趯⑹髽?biāo)點(diǎn)到Assembly,看看這些數(shù)據(jù)到底是什么樣子的。

從上圖可以看到一個(gè)一個(gè)匯編指令,大家都知道我們寫的代碼在被編譯的時(shí)候會(huì)被編譯成機(jī)器語(yǔ)言也就是匯編語(yǔ)言存儲(chǔ)在mach-o中,所以上圖驗(yàn)證了__TEXT段存儲(chǔ)的就是我們寫的代碼。


我們?cè)倏纯確_TEXT Segment 具體有哪些Section,這些Section又代表什么含義?

__text: 可執(zhí)行文件的代碼區(qū)域

__objc_methname: 方法名

__objc_classname: 類名

__objc_methtype: 方法簽名

__cstring: 類 C 風(fēng)格的字符串

LC_DYLD_INFO_ONLY

這個(gè)Command的信息主要是提供給動(dòng)態(tài)鏈接器dyld的,其結(jié)構(gòu)如下:

雖然看起來很復(fù)雜,但實(shí)際上它的目的就是為了給dyld提供能夠加載目標(biāo)MachO所需要的必要信息:?

1、因?yàn)榭赡芗虞d到隨機(jī)地址,所以需要rebase信息;

2、如果進(jìn)程依賴其他鏡像的符號(hào),則綁定需要bind信息;

3、對(duì)于C++程序而言可能需要weak bind實(shí)現(xiàn)代碼/數(shù)據(jù)復(fù)用;

4、對(duì)于一些外部符號(hào)不需要立即綁定的可以延時(shí)加載,這就需要lazy bind信息;

5、對(duì)于導(dǎo)出符號(hào)也需要對(duì)應(yīng)的export信息。

xxx_off代表該信息在mach-o中的偏移位置,根據(jù)這個(gè)偏移值,我們可以在mach-o下面的Dynamic Load Info段找到我們要找的具體信息。

我們來看看Dynamic Load Info里面就是存放著什么

Dynamic Load Info存放的信息是不是和LC_DYLD_INFO_ONLY中的索引一樣,我們完全可以這樣理解:LC_DYLD_INFO_ONLY 就是?Dynamic Load Info段的索引。


rebase/bind

為了描述這些rebase/bind信息,dyld定義了一套偽指令,用來描述具體的操作(opcode)及其操作數(shù)據(jù)。以延時(shí)綁定為例,我們從操作符看起來是這樣:

從右側(cè)我們可以獲得以下信息:

name:_AUGraphInitialize

offset:uleb128編碼的值 0xC006,如果我們直接以0xC006這個(gè)地址去查找,會(huì)發(fā)現(xiàn)找到的信息是不對(duì)的。因?yàn)閡leb128編碼的數(shù)據(jù)是不能直接使用的,需要經(jīng)過轉(zhuǎn)換才能使用。

對(duì)于uleb128編碼來說,其特點(diǎn)如下:

1)一個(gè)uleb128編碼的整形值,其占用的字節(jié)數(shù)是不確定的,長(zhǎng)度有可能在1到5個(gè)字節(jié)之間變化;

2)一個(gè)uleb128編碼的整形值,是以字節(jié)中最高位是否為0來表示字節(jié)流有沒有結(jié)束的。

那么轉(zhuǎn)換方法如下,以0xC006為例,先將其從小端轉(zhuǎn)換成大端,得到0x06C0。

然后再展開成二進(jìn)制的01數(shù)據(jù):0000 0110 1100 0000,然后從低位往高位算,以1為起始開始,每第8位的值刪除,然后再將刪除后的所有7位組合起來。以0x06C0為例:

源數(shù)據(jù): ? ? ?0000 0110 1100 0000

刪除第8位: ?0000 0110 100 0000 ?-- ?轉(zhuǎn)換成16進(jìn)制為 0x340。

你以為就結(jié)束了嗎?其實(shí)沒有,這個(gè)數(shù)據(jù)只是一個(gè)相對(duì)的偏移量,還要加上一個(gè)起始地址才能找到真實(shí)存放地址。那么這個(gè)起始地址是什么呢?之前我們說過,數(shù)據(jù)段存放的是可以讀寫的數(shù)據(jù),而rebase和bind是不是需要對(duì)指針重新計(jì)算,所以這些數(shù)據(jù)都是存放在__DATA段的,那這個(gè)起始位置就很清楚了,就是__DATA段的起始位置。上文已經(jīng)查到__DATA的起始地址是0xF58000。

那么加上轉(zhuǎn)換得到的值0x340,即得到真實(shí)數(shù)據(jù)的地址0xF58340。

我們找到__DATA段的這個(gè)地址去驗(yàn)證下:

完美!而且從上圖不難發(fā)現(xiàn),所有的symbol數(shù)據(jù)都是存放在(__DATA,__got)和(__DATA,__la_symbol_ptr)這兩個(gè)段的。

(__DATA,__got)這個(gè)段是存放非懶加載的符號(hào)指針,即在加載階段就已經(jīng)綁定好了符號(hào)地址,比如dyld_stub_binder,這個(gè)函數(shù)是用于動(dòng)態(tài)綁定函數(shù)符號(hào)地址的。

(__DATA,__la_symbol_ptr)是存放懶加載的符號(hào)指針的,即在運(yùn)行過程中再進(jìn)行動(dòng)態(tài)查找具體的函數(shù)地址。


Binding

我們來看看binding在mach-o中具體是怎么做的!

看上圖_AUGraphInitialize符號(hào)存放的數(shù)據(jù):00000000 100BD6948。這是一段地址,我們來找找這個(gè)地址在哪個(gè)段,最后發(fā)現(xiàn)在Section64(__TEXT,__stub_helper)段

不難發(fā)現(xiàn),這個(gè)地址存放的是一段匯編指令,但是他真實(shí)要執(zhí)行的指令不是100BD6948,而是100BD694C,因?yàn)榧拇嫫鞔娣胖噶畹牡刂芬惨闵?,也就是說,要加寄存器的內(nèi)存,一條指令占4個(gè)字節(jié),所以要加上4個(gè)字節(jié),即得到100BD694C,這條指令是 b ?#0x100bd690c,b是跳轉(zhuǎn)的意思,意思是跳轉(zhuǎn)到0x100bd690c這個(gè)地址去執(zhí)行。再看上面100BD6940的指令,也是?b ?#0x100bd690c,這條指令其實(shí)就是其他符號(hào)被調(diào)用的時(shí)候執(zhí)行的匯編代碼。也就是說所有需要binging的符號(hào)都會(huì)執(zhí)行到這條指令,這其實(shí)就是binging的中間跳板。然后通過這個(gè)地址的命令去尋址真實(shí)地址,通過dyld_stub_binder函數(shù)獲取,dyld_stub_binder這個(gè)函數(shù)的符號(hào)是非延遲綁定的,會(huì)在dyld進(jìn)行加載的時(shí)候就進(jìn)行綁定(該函數(shù)符號(hào)存放在Section(__DATA,__got)段的最末尾)。最后會(huì)將通過dyld_stub_binder找到的真實(shí)地址寫入到(__DATA,__la_symbol_ptr)或者(__DATA,__got)對(duì)應(yīng)函數(shù)符號(hào)地址的data中。下次再調(diào)用這個(gè)函數(shù)的時(shí)候就可以根據(jù)這個(gè)存入的數(shù)據(jù)直接調(diào)用了。

以上就是Binging的具體過程了。


Rebase

那么Rebase的過程又是怎么樣的呢?這就要提到Section64(__TEXT,__stubs)這個(gè)段了,這個(gè)段存放的全都是以 101CXXXXXXXXXXXX 開頭的數(shù)據(jù)。101C其實(shí)就是匯編指令adrp。

事實(shí)上在代碼執(zhí)行到需要rebase的函數(shù)時(shí),會(huì)跳轉(zhuǎn)到

__stub段該函數(shù)的地址。然后經(jīng)過一系列的地址計(jì)算,計(jì)算結(jié)果就是Section(__DATA,__la_symbol_ptr)中該函數(shù)的地址。然后按照上述Binging的過程就能查找到具體的地址了。

具體怎么計(jì)算的目前筆者還沒弄明白,有了解過程的讀者可以私信筆者,不勝感激!

可以參考深入理解Mach-O文件中的Rebase和Bind這篇博客。不過該博客是基于mac x86_64架構(gòu)的,arm64上的計(jì)算方式有所不同。

LC_SYMTAB

這個(gè)commond同時(shí)指定了兩個(gè)表(符號(hào)表、String表)的位置信息


LC_DYSYMTAB(動(dòng)態(tài)符號(hào)表)

動(dòng)態(tài)符號(hào)command定義了各種符號(hào)的偏移量和各種符號(hào)的個(gè)數(shù)(9種)。


LC_UUID

LC_UUID 用來標(biāo)識(shí)唯一APP,命令的定義如下:

每個(gè)可執(zhí)行程序都有一個(gè)uuid,這樣根據(jù)不同的uuid能確定包。比如崩潰日志中就會(huì)包含uuid字段。表示是哪個(gè)包崩潰了


LC_LOAD_DYLINKER

該段定義了加載動(dòng)態(tài)庫(kù)的工具dyld,并且保存了dyld的物理地址

LC_XXX_DYLIB

LC_LOAD_{,WEAK_}DYLIB用來告訴內(nèi)核(實(shí)際上是dyld)當(dāng)前可執(zhí)行文件需要使用哪些動(dòng)態(tài)庫(kù),而其結(jié)構(gòu)如下:

動(dòng)態(tài)庫(kù)(filetype為MH_DYLIB)中會(huì)包含?LC_ID_DYLIB?command 來說明自己是個(gè)什么庫(kù),包括名稱、版本、時(shí)間戳等信息。需要注意的是lc_str并不是字符串本身,而是字符串的偏移值,字符串信息在command的內(nèi)容之后,該偏移指的是距離command起始位置的偏移。

其他段的意義:

LC_VERSION_MIN_IPHONEOS? : ?存儲(chǔ)著最低支持的iOS系統(tǒng)版本。

LC_MAIN ? : ? ?保存了main函數(shù)的進(jìn)入地址。 ? ?

LC_PATH ? ?: ? ?保存Xcode上設(shè)置的相關(guān)路徑。

LC_FUNCTION_STARTS ? ?: ? ?存儲(chǔ)著方法的起始偏移地址。

LC_DATA_IN_CODE ? ?: ? ?存儲(chǔ)運(yùn)行中代碼的存儲(chǔ)空間,即棧和堆空間的offset

LC_CODE_SIGNATURE ? ?: ? ?存儲(chǔ)mach-o文件以及代碼簽名在文件中的offset。

__DATA段

__nl_symbol_ptr: 非懶加載指針表,dyld 加載會(huì)立即綁定

__ls_symbol_ptr: 懶加載指針表

__mod_init_func: constructor 函數(shù)

__mod_term_func: destructor 函數(shù)

__objc_classlist: 類列表

__objc_nlclslist: 實(shí)現(xiàn)了 load 方法的類

__objc_protolist: protocol的列表

__objc_classrefs: 被引用的類列表

__objc _catlist: Category列表

Symbol Table?符號(hào)表

Dynamic Symbol Table 動(dòng)態(tài)符號(hào)表

這個(gè)是重點(diǎn)中的重點(diǎn),符號(hào)表是將地址和符號(hào)聯(lián)系起來的橋梁。符號(hào)表并不能直接存儲(chǔ)符號(hào),而是存儲(chǔ)符號(hào)位于字符串表的位置。


String Table 字符串表

String表順序列出了二進(jìn)制mach-O文件的中的所有可見字符串。串之間通過0x00分隔。可以通過相對(duì)String表起始位置的偏移量隨機(jī)訪問String表中的字符串。符號(hào)表結(jié)構(gòu)中的n_strx指定的就是String表中的偏移量。通過這個(gè)偏移量可以訪問到符號(hào)對(duì)應(yīng)的具體字符串。

所有的變量名、函數(shù)名等,都以字符串的形式存儲(chǔ)在字符串表中


總結(jié)

最后,以一張圖作為總結(jié)吧

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

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

  • Mach-O文件 Mach-O是Mach Object文件格式的縮寫,是mac以及iOS上可執(zhí)行文件的格式,例如當(dāng)...
    YanZi_33閱讀 676評(píng)論 0 2
  • 概述 ??本文檔描述了Mach-O文件格式的結(jié)構(gòu),它被用來存儲(chǔ)程序和庫(kù)到硬盤中,作為Mac OS X程序的二進(jìn)制接...
    VenpleD閱讀 1,645評(píng)論 0 5
  • 本文主要介紹Mach-O文件的內(nèi)部結(jié)構(gòu)的演示 Mach-O內(nèi)部結(jié)構(gòu) 因?yàn)镸achO文件本身是一種文件格式,所以我們...
    iOS鑫閱讀 323評(píng)論 0 3
  • iOS 底層原理 + 逆向 文章匯總[http://www.itdecent.cn/p/412b20d9a0f6...
    Style_月月閱讀 1,423評(píng)論 0 2
  • 摘錄:其字德安「Mach-O文件結(jié)構(gòu)」(以此記錄一下) iOS上的可執(zhí)行文件相當(dāng)于windows上的.exe可執(zhí)行...
    NJ_墨閱讀 1,915評(píng)論 0 4

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