iOS 編譯與鏈接二:編譯的產(chǎn)物Mach-O

書接上文

上一篇說到編譯產(chǎn)生了目標文件.o,我們知道不同的操作系統(tǒng),可執(zhí)行文件是不同的,系統(tǒng)能夠理解這個特殊文件,才能加載到內(nèi)存,創(chuàng)建出進程.
Mach-O是Mach object的縮寫愈腾,雖然windows,linux,unix,mac os/ios他們的可執(zhí)行文件雖然有著不同的文件,但是他們都來是來自一種叫做COFF(Common file format)的格式,是它的變種版本,特點是不同的文件有用不同的"段".,是Mac os以及 iOS上用來存儲程序的一類文件.Mach-O目標文件是源代碼編譯得到的文件,包含機器指令,數(shù)據(jù),符號表,調(diào)試信息,字符串等,然后按照不同的信息,放在不同的“段”(segment)中;比如指令一般放在代碼段里,變量一般放在數(shù)據(jù)段里.

可執(zhí)行文件

除了.o,還有像可執(zhí)行文件,framework,.a,.out等文件也都是mach-o.

一.Mach-O的結(jié)構(gòu)

mach-o的結(jié)構(gòu)

主要分為三個部分,Mach Header鞠眉、Load Command唯卖、Data.

可以使用MachOView查看mach-o文件
下載地址

一個可執(zhí)行文件main

下載源碼
從EXTERNAL_HEADERS/mach-o/loader.h中的定義可以了解mach-o的一些基本內(nèi)容.

1.Mach Header

首先是對文件類型的定義

#define MH_OBJECT   0x1     /* relocatable object file */
#define MH_EXECUTE  0x2     /* demand paged executable file */
#define MH_FVMLIB   0x3     /* fixed VM shared library file */
#define MH_CORE     0x4     /* core file */
#define MH_PRELOAD  0x5     /* preloaded executable file */
#define MH_DYLIB    0x6     /* dynamically bound shared library */
#define MH_DYLINKER 0x7     /* dynamic link editor */
#define MH_BUNDLE   0x8     /* dynamically bound bundle file */
#define MH_DYLIB_STUB   0x9     /* shared library stub for static */
                    /*  linking only, no section contents */
#define MH_DSYM     0xa     /* companion file with only debug */

MH_OBJECT : 經(jīng)過編譯和靜態(tài)鏈接(也可以沒有這個過程)的.o文件,以及靜態(tài)鏈接庫.
MH_EXECUTE : 可執(zhí)行文件
MH_DYLIB : 動態(tài)鏈接庫
MH_DYLINKER : 動態(tài)鏈接器
MH_BUNDLE : bundle資源文件
MH_DYLIB_STUB : 靜態(tài)鏈接庫
MH_DSYM : 符號表和調(diào)試信息文件

還是在EXTERNAL_HEADERS/mach-o/loader.h中,可以找到header的定義,

/*
 * The 32-bit mach header appears at the very beginning of the object file for
 * 32-bit architectures.
 */
struct mach_header {
    uint32_t    magic;      /* mach magic number identifier */
    cpu_type_t  cputype;    /* cpu specifier */
    cpu_subtype_t   cpusubtype; /* machine specifier */
    uint32_t    filetype;   /* type of file */
    uint32_t    ncmds;      /* number of load commands */
    uint32_t    sizeofcmds; /* the size of all the load commands */
    uint32_t    flags;      /* flags */
};

/* Constant for the magic field of the mach_header (32-bit architectures) */
#define MH_MAGIC    0xfeedface  /* the mach magic number */
#define MH_CIGAM    0xcefaedfe  /* NXSwapInt(MH_MAGIC) */

/*
 * The 64-bit mach header appears at the very beginning of object files for
 * 64-bit architectures.
 */
struct mach_header_64 {
    uint32_t    magic;      /* mach magic number identifier */
    cpu_type_t  cputype;    /* cpu specifier */
    cpu_subtype_t   cpusubtype; /* machine specifier */
    uint32_t    filetype;   /* type of file */
    uint32_t    ncmds;      /* number of load commands */
    uint32_t    sizeofcmds; /* the size of all the load commands */
    uint32_t    flags;      /* flags */
    uint32_t    reserved;   /* reserved */
};

/* Constant for the magic field of the mach_header_64 (64-bit architectures) */
#define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */
#define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */

magic是mach-o文件的識別符,比如MH_MAGIC,MH_MAGIC_64,MH_CIGAM,MH_CIGAM_64,除此之外還有通用二進制的FAT_MAGIC和FAT_CIGAM后面會說到.
cputype和 cpusubtype是 cpu架構(gòu)和細分.
filetype是文件類型,也就是上面那些宏定義,MH_OBJECT,MH_EXECUTE等等.
ncmds加載命令的數(shù)量
sizeofcmds加載命令的數(shù)據(jù)大小
flags標識位
reserved保留字段,沒有固定的值

可以使用命令查看header

otool -v -h main

輸出

main:
Mach header
      magic  cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
MH_MAGIC_64    ARM64        ALL  0x00     EXECUTE    21       1784   NOUNDEFS DYLDLINK TWOLEVEL PIE

或者用MachOView查看


mach header

可以看到這個main,是64位,是個可執(zhí)行文件MH_EXECUTE.

2.Load Commands
加載指令,也在EXTERNAL_HEADERS/mach-o/loader.h中定,和Header一樣,也有一個結(jié)構(gòu)體

struct load_command {
    uint32_t cmd;       /* type of load command */
    uint32_t cmdsize;   /* total size of command in bytes */
};

只有兩個屬性,命令類型,和命令的字節(jié)長度.
cmd是一批宏定義,以LC開頭,有五六十個.
主要有這些:
LC_SEGMENT_64 將文件中的段映射到進程地址空間中
LC_DYLD_INFO_ONLY 加載動態(tài)鏈接庫信息(重定向地址、弱引用綁定、懶加載綁定腔召、開放函數(shù)等的偏移值信息)
LC_SYMTAB 載入符號表地址
LC_DYSYMTAB 載入動態(tài)符號表地址
LC_LOAD_DYLINKER 加載動態(tài)鏈接器
LC_UUID 唯一標識,crash解析中也會用到弥臼,檢查dysm文件和crash文件是否匹配
LC_VERSION_MIN_MACOSX / LC_VERSION_MIN_IPHONEOS 二進制文件支持的最底操作系統(tǒng)版本
LC_SOURCE_VERSION 構(gòu)建二進制文件使用的源代碼版本
LC_MAIN 設置程序主線程的入口地址和棧大小
LC_ENCRYPTION_INFO_64 獲取加密信息
LC_LOAD_DYLIB 加載額外的動態(tài)庫
LC_FUNCTION_STARTS 函數(shù)起始地址表
LC_DATA_IN_CODE 定義在代碼段(__text)內(nèi)的非指令表
LC_CODE_SIGNATURE 應用的簽名信息

不過load_command這個結(jié)構(gòu)體似乎不怎么使用,使用的是其他更具體的定義,每種加載命令都有對應的結(jié)構(gòu)體
比如 dylib_command, symtab_command等等.他們也都有cmd和cmdsize.

struct dylib_command {
    uint32_t    cmd;        /* LC_ID_DYLIB, LC_LOAD_{,WEAK_}DYLIB,
                       LC_REEXPORT_DYLIB */
    uint32_t    cmdsize;    /* includes pathname string */
    struct dylib    dylib;      /* the library identification */
};

struct symtab_command {
    uint32_t    cmd;        /* LC_SYMTAB */
    uint32_t    cmdsize;    /* sizeof(struct symtab_command) */
    uint32_t    symoff;     /* symbol table offset */
    uint32_t    nsyms;      /* number of symbol table entries */
    uint32_t    stroff;     /* string table offset */
    uint32_t    strsize;    /* string table size in bytes */
};

另外還有segment command負責描述segment里的section

struct segment_command_64 { /* for 64-bit architectures */
    uint32_t    cmd;        /* LC_SEGMENT_64 */
    uint32_t    cmdsize;    /* includes sizeof section_64 structs */
    char        segname[16];    /* segment name */
    uint64_t    vmaddr;     /* memory address of this segment */
    uint64_t    vmsize;     /* memory size of this segment */
    uint64_t    fileoff;    /* file offset of this segment */
    uint64_t    filesize;   /* amount to map from the file */
    vm_prot_t   maxprot;    /* maximum VM protection */
    vm_prot_t   initprot;   /* initial VM protection */
    uint32_t    nsects;     /* number of sections in segment */
    uint32_t    flags;      /* flags */
};

這里的cmd固定就是LC_SEGMENT或者LC_SEGMENT_64了.
而segment_command就指定了后面數(shù)據(jù)段的布局.
vmaddr是內(nèi)存地址,
vmsize占用內(nèi)存的大小,
fileoff是這個segment在mach-o文件的數(shù)據(jù)開始位置.也叫做偏移.
filesize是這個segment包含數(shù)據(jù)的大小.也叫做段.
也就是從fileoff(也叫做偏移)取filesize字節(jié)的數(shù)據(jù)宴咧,放到內(nèi)存的vmaddr處的vmsize字節(jié).

3.Data
數(shù)據(jù)段主要由section組成,它是這樣定義的

struct section_64 { /* for 64-bit architectures */
    char        sectname[16];   /* name of this section */
    char        segname[16];    /* segment this section goes in */
    uint64_t    addr;       /* memory address of this section */
    uint64_t    size;       /* size in bytes of this section */
    uint32_t    offset;     /* file offset of this section */
    uint32_t    align;      /* section alignment (power of 2) */
    uint32_t    reloff;     /* file offset of relocation entries */
    uint32_t    nreloc;     /* number of relocation entries */
    uint32_t    flags;      /* flags (section type and attributes)*/
    uint32_t    reserved1;  /* reserved (for offset or index) */
    uint32_t    reserved2;  /* reserved (for count or sizeof) */
    uint32_t    reserved3;  /* reserved */
};
數(shù)據(jù)段

前面是segment name比如__TEXT, __DATA;
后面是section name比如__text,__cstring等.

__text 機器碼
__cstring C 語言字符串
__const 初始化的常量
__objc runtime支持
__data 初始化的變量
__bss 未初始化的靜態(tài)變量
__stubs 跳轉(zhuǎn)表,重定向到 lazy 和 non-lazy 符號的 section
__stubs_helper lazy 動態(tài)綁定符號的輔助函數(shù)
__objc_methname OC 方法名
__objc_methtype OC 方法類型
__objc_classname OC 類名
__swift5_proto swift協(xié)議
__got 全局偏移表
__la_symbol_ptr lazy binding的指針表径缅,表中的指針一開始都指向__stub_helper
__cfstring 工程中使用的Core Foundation字符串(CFStringRefs)
__objc_classlist OC 類列表
__objc_protolist OC protocol列表
__objc_imginfo OC 鏡像信息
__const 沒有初始化過的常量
__objc_selfrefs OC 引用的SEL列表
__objc_protorefs OC 引用的protocol列表
__objc_superrefs OC 引用的父類列表
__objc_ivar OC ivar信息
__objc_data class信息
__bss BSS掺栅,存放 未初始化的全局變量,就是常說的靜態(tài)內(nèi)存分配
__data 初始化的可變數(shù)據(jù)
...等等

  • Assembly 匯編代碼
    在這里存儲的是編譯main.o過程中的生成的匯編指令.


    匯編代碼

    機器碼

    __TEST__text存儲的機器碼

  • Symbol Table 符號表
    在編譯那篇說到過,clang在詞法分析這一步中,把代碼拆分成一個個token,這其中變量名,方法名,類名等等這些被叫做符號,符號表存儲了符號在字符串表中的位置,以及類型,地址,描述等等.


    符號表
  • String Table 字符串表
    存儲變量名,方法名,類名,協(xié)議,結(jié)構(gòu)體等等符號


    字符串表
  • Dynamic Symbol Table 動態(tài)符號表
    存儲的是動態(tài)庫函數(shù)位于符號表的偏移信息


    動態(tài)符號表
  • Lazy Symbol Pointers 懶加載符號表
    懶加載是指在程序運行時需要訪問這些符號的時候再去綁定,一般是動態(tài)庫里的符號.


    懶加載符號表
  • Non Lazy Symbol Pointers 非懶加載符號表
    與懶加載符號表相反,這些符號也是來自程序依賴的動態(tài)庫,不同的是會在程序一加載就綁定好.


    非懶加載符號表
  • Symbol Stubs 符號樁
    與Lazy Symbol Pointers相對應的,使用外部符號會先在符號樁查找,然后對應到懶加載符號表.


    符號樁

二.符號

1.符號

在load command中有兩個和符號表相關(guān),LC_SYMTAB和LC_DYSYMTAB,用來描述symbol table和dynamic symbol table的元數(shù)據(jù),包括位置,長度等等


LC_SYMTAB

LC_DYSYMTAB
這是前面提到的符號表加載命令
struct symtab_command {
    uint32_t    cmd;        /*固定為 LC_SYMTAB */
    uint32_t    cmdsize;          /* 這個結(jié)構(gòu)體的大小 */
    uint32_t    symoff;     /* 符號表的偏移 */
    uint32_t    nsyms;      /* 符號數(shù)量 */
    uint32_t    stroff;     /* 字符串表的便宜 */
    uint32_t    strsize;    /* 字符串表的大小 */
};

這是EXTERNAL_HEADERS/mach-o/nlist.h中符號的定義

struct nlist_64 {
    union {
        uint32_t  n_strx; /* index into the string table */
    } n_un;
    uint8_t n_type;        /* type flag, see below */
    uint8_t n_sect;        /* section number or NO_SECT */
    uint16_t n_desc;       /* see <mach-o/stab.h> */
    uint64_t n_value;      /* value of this symbol (or stab offset) */
};

n_type字段是一個8位十六進制復合字段纳猪,其中bit[0:1]表示是外部符號氧卧,bit[5:8]表調(diào)試符號,bit[4:5]表示私有 external 符號氏堤,bit[1:4]是符號類型沙绝,有 N_UNDF 未定義搏明、N_ABS 絕對地址、N_SECT 本地符號闪檬、N_PBUD 預綁定符號星著、N_INDR 同名符號幾種類型.
具體定義如下

#define N_UNDF  0x0  // 未定義
#define N_ABS 0x2    // 絕對地址
#define N_SECT 0xe   // 本地符號
#define N_PBUD 0xc   // 預定義符號
#define N_INDR 0xa   // 同名符號

#define N_STAB 0xe0  // 調(diào)試符號
#define N_PEXT 0x10  // 私有 external 符號
#define N_TYPE 0x0e  // 類型位的掩碼
#define N_EXT 0x01   // external 符號

2.符號的類型
分別使用命令和MachOView查看符號表

objdump --macho --syms main.o

輸出

main.o:

SYMBOL TABLE:
0000000000000000 l     F __TEXT,__text ltmp0
00000000000000a0 l     O __DATA,__objc_classrefs _OBJC_CLASSLIST_REFERENCES_$_
00000000000000d0 l     O __DATA,__objc_selrefs _OBJC_SELECTOR_REFERENCES_
00000000000000a8 l     O __TEXT,__cstring l_.str
00000000000000d8 l     O __DATA,__cfstring l__unnamed_cfstring_
00000000000000a0 l     O __DATA,__objc_classrefs ltmp1
00000000000000a8 l     O __TEXT,__cstring ltmp2
00000000000000bc l     O __TEXT,__objc_methname ltmp3
00000000000000bc l     O __TEXT,__objc_methname l_OBJC_METH_VAR_NAME_
00000000000000d0 l     O __DATA,__objc_selrefs ltmp4
00000000000000b1 l     O __TEXT,__cstring l_.str.1
00000000000000d8 l     O __DATA,__cfstring ltmp5
00000000000000f8 l     O __DATA,__objc_imageinfo ltmp6
0000000000000100 l     O __LD,__compact_unwind ltmp7
0000000000000000 g     F __TEXT,__text _main
0000000000000000         *UND* _NSLog
0000000000000000         *UND* _OBJC_CLASS_$_NSString
0000000000000000         *UND* ___CFConstantStringClassReference
0000000000000000         *UND* _objc_alloc
0000000000000000         *UND* _objc_autoreleasePoolPop
0000000000000000         *UND* _objc_autoreleasePoolPush
0000000000000000         *UND* _objc_msgSend

其中l(wèi)表示本地符號,g表示全局符號,下面幾個沒有l(wèi)或者的g的,這個命令無法分類,需要其他命令
其中根據(jù)功能又分為O(data),F(文件),f(file),d(debug),UDN(未定義)等.

白色的是本地符號

土黃色的是全局符號

綠色的是未定義符號/外部符號
  • 查看外部符號
objdump --macho --indirect-symbols main.o

輸出是空的,因為下面那幾個都是動態(tài)鏈接庫里的,而main.o只進行了靜態(tài)鏈接

objdump --macho --indirect-symbols main

查看可執(zhí)行文件main的,就有輸出了

main:
Indirect symbols for (__TEXT,__stubs) 5 entries
address            index name
0x0000000100003f54     2 _NSLog
0x0000000100003f60     5 _objc_alloc
0x0000000100003f6c     6 _objc_autoreleasePoolPop
0x0000000100003f78     7 _objc_autoreleasePoolPush
0x0000000100003f84     8 _objc_msgSend
Indirect symbols for (__DATA_CONST,__got) 5 entries
address            index name
0x0000000100004000     2 _NSLog
0x0000000100004008     5 _objc_alloc
0x0000000100004010     6 _objc_autoreleasePoolPop
0x0000000100004018     7 _objc_autoreleasePoolPush
0x0000000100004020     8 _objc_msgSend
  • 查看導出符號
    導出不是動詞,導出符號就是用來提供給外部訪問的符號
objdump --macho --exports-trie main

輸出

main:

Exports trie:
0x100000000  __mh_execute_header
0x100003EB4  _main

三.通用二進制

1.Fat Binary
Fat Binary本身是一個mach-o,不過它還包含了多個mach-o.
用MachOView打開一個framework,比如這個Bugly,看起來是這樣的

bugly

首先它叫做Fat Binary,胖二進制,也就是通用二進制
Fat Header

Fat Header的定義在EXTERNAL_HEADERS/mach-o/fat.h中

#define FAT_MAGIC   0xcafebabe
#define FAT_CIGAM   0xbebafeca  /* NXSwapLong(FAT_MAGIC) */

struct fat_header {
    uint32_t    magic;      /* FAT_MAGIC */
    uint32_t    nfat_arch;  /* number of structs that follow */
};

struct fat_arch {
    cpu_type_t  cputype;    /* cpu specifier (int) */
    cpu_subtype_t   cpusubtype; /* machine specifier (int) */
    uint32_t    offset;     /* file offset to this object file */
    uint32_t    size;       /* size of this object file */
    uint32_t    align;      /* alignment as a power of 2 */
};

magic是FAT_MAGIC或者FAT_CIGAM,nfat_arch表示有幾個fat_arch,從上面那張圖可以看到,這個header有五個fat_arch,表示了對五種架構(gòu)的支持,對應了五個Static Library,也就是靜態(tài)庫.


靜態(tài)庫

每個靜態(tài)庫都對應Start,Symtab Header(符號表描述),symbol table(符號表),string table(字符串表),object header(目標文件描述)和一個目標文件.o;

.o

.o也是一整個mach-o,magic是MH_MAGIC,并且文件類型是目標文件.

2.拆分和組合
通用二進制文件一般用于庫的概念,讓一個庫能夠兼容多個硬件架構(gòu),對于開發(fā)和測試來說是很方便的,但是實際運行的時候,對于一種硬件架構(gòu)的設備,就沒必要在硬盤里存儲其他架構(gòu)的文件.如果是上傳商店,蘋果會為我們做這件事.

  • 查看
lipo -info Bugly

輸出

Architectures in the fat file: Bugly are: armv7 armv7s i386 x86_64 arm64 
  • 提取
    lipo -output 取個名字 -extract 架構(gòu) 文件
lipo -output Bugly-x86_64 -extract x86_64 Bugly 
提取x86-64
  • 移除
lipo -output Bugly-noarmv7 -remove armv7 Bugly

輸出一個Bugly-noarmv7文件
查看

lipo -info Bugly-noarmv7 

Architectures in the fat file: Bugly-noarmv7 are: armv7s i386 x86_64 arm64 
  • 合并
lipo -output NewBugly -create Bugly-noarmv7 Bugly-armv7

lipo -info NewBugly           
Architectures in the fat file: NewBugly are: armv7s i386 armv7 x86_64 arm64 

上面的命令都可以使用相對路徑
上面這些命令都不會影響源文件,必須添加-output.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市粗悯,隨后出現(xiàn)的幾起案子虚循,更是在濱河造成了極大的恐慌,老刑警劉巖样傍,帶你破解...
    沈念sama閱讀 221,430評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件横缔,死亡現(xiàn)場離奇詭異,居然都是意外死亡衫哥,警方通過查閱死者的電腦和手機茎刚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來撤逢,“玉大人膛锭,你說我怎么就攤上這事〉阎剩” “怎么了泉沾?”我有些...
    開封第一講書人閱讀 167,834評論 0 360
  • 文/不壞的土叔 我叫張陵捞蚂,是天一觀的道長妇押。 經(jīng)常有香客問我,道長姓迅,這世上最難降的妖魔是什么敲霍? 我笑而不...
    開封第一講書人閱讀 59,543評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮丁存,結(jié)果婚禮上肩杈,老公的妹妹穿的比我還像新娘。我一直安慰自己解寝,他們只是感情好扩然,可當我...
    茶點故事閱讀 68,547評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著聋伦,像睡著了一般夫偶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上觉增,一...
    開封第一講書人閱讀 52,196評論 1 308
  • 那天兵拢,我揣著相機與錄音,去河邊找鬼逾礁。 笑死说铃,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播腻扇,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼债热,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了幼苛?” 一聲冷哼從身側(cè)響起阳柔,我...
    開封第一講書人閱讀 39,671評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蚓峦,沒想到半個月后舌剂,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,221評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡暑椰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,303評論 3 340
  • 正文 我和宋清朗相戀三年霍转,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片一汽。...
    茶點故事閱讀 40,444評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡避消,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出召夹,到底是詐尸還是另有隱情岩喷,我是刑警寧澤,帶...
    沈念sama閱讀 36,134評論 5 350
  • 正文 年R本政府宣布监憎,位于F島的核電站纱意,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏鲸阔。R本人自食惡果不足惜偷霉,卻給世界環(huán)境...
    茶點故事閱讀 41,810評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望褐筛。 院中可真熱鬧类少,春花似錦、人聲如沸渔扎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽晃痴。三九已至残吩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間愧旦,已是汗流浹背世剖。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留笤虫,地道東北人旁瘫。 一個月前我還...
    沈念sama閱讀 48,837評論 3 376
  • 正文 我出身青樓祖凫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親酬凳。 傳聞我的和親對象是個殘疾皇子惠况,可洞房花燭夜當晚...
    茶點故事閱讀 45,455評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 摘錄:其字德安「Mach-O文件結(jié)構(gòu)」(以此記錄一下) iOS上的可執(zhí)行文件相當于windows上的.exe可執(zhí)行...
    NJ_墨閱讀 1,768評論 0 4
  • 1. 介紹 Mach-O是Mach Object文件格式的縮寫。它是用于可執(zhí)行文件宁仔,動態(tài)庫稠屠,目標代碼的文件格式。作...
    沉江小魚閱讀 821評論 0 1
  • Mach-O文件 Mach-O是Mach Object文件格式的縮寫翎苫,是mac以及iOS上可執(zhí)行文件的格式权埠,例如當...
    YanZi_33閱讀 631評論 0 2
  • 前文講解了dyld加載Mach-O的用戶態(tài)過程,大家都知道Mach-O代表的是蘋果系統(tǒng)的可執(zhí)行文件煎谍,那你們了解Ma...
    佛系編程閱讀 1,971評論 0 2
  • 概述 ??本文檔描述了Mach-O文件格式的結(jié)構(gòu)攘蔽,它被用來存儲程序和庫到硬盤中,作為Mac OS X程序的二進制接...
    VenpleD閱讀 1,477評論 0 5