MachO文件是蘋果可執行二進制文件的格式xcode
LC_SEGMENT_64
將可執行文件(64位)映射到進程地址空間
32位系統的是LC_SEGMENT
是加載的主要命令,負責指導內核來設置進程的內存空間bash
LC_DYLD_INFO_ONLY
動態連接相關信息數據結構
LC_SYMTAB
符號表地址函數
LC_DYSYMTAB
動態符號地址表工具
LC_LOAD_DYLINKER
加載一個動態連接器,路徑「/usr/lib/dyld」ui
LC_UUID
二進制文件的標識ID,dSYM文件、crash中都存在這個值,肯定兩個文件是否匹配,分析出對應的崩潰位置this
LC_VERSION_MIN_MACOSX
二進制文件要求的最低系統版本,和xcode中配置的target有關spa
LC_MAIN
設置程序的入口,編譯型的語言須要指定入口地址,解釋器語言對此沒有邀請翻譯
LC_SOURCE_VERSION
構建二進制文件使用的源代碼版本3d
LC_FUNCTION_STARTS
定義函數的起始地址表,使咱們的調試器很容易看到地址
LC_DATA_IN_CODE
定義在代碼段內的非指令數據
#import <mach-o/loader.h>
struct segment_command { /* for 32-bit architectures */
uint32_t cmd; /* LC_SEGMENT */
uint32_t cmdsize; /* includes sizeof section structs */
char segname[16]; /* segment name */
uint32_t vmaddr; /* memory address of this segment */
uint32_t vmsize; /* memory size of this segment */
uint32_t fileoff; /* file offset of this segment */
uint32_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 */
};
複製代碼
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 */
};
複製代碼
** 段結構圖(代碼段__TEXT): ** 
段(segment)和節(section)
"__TEXT"表明的是segment,
「__text」表明的是section
複製代碼
__PAGEZERO段
一個全用0填充的段,用戶抓取空指針引用(非法內存訪問)。一般不會佔用物理內存
__TEXT段
代碼段:只有可執行代碼和其餘只讀數據
__text 主程序的代碼
__stubs 動態庫連接的樁
__stub_helper 動態庫連接的樁的輔助
__cstring 字符串常量(代碼中寫固定的字符)當即數(代碼中直接寫的數字,成爲模數)
常量字符串表的描述信息,經過該信息,能夠獲取常量字符符號的表地址
__unwind_info 用於異常處理
複製代碼
__DATA段
用於讀取和寫入數據的一個段
__nl_symbol_ptr 非延時導入符號表指針
_la_symbol_ptr 延時導入符號表指針
複製代碼
__LINKEDIT
包含給動態連接庫連接器(ldyd)的原始數據段,包含符號表和字符串表,壓縮動態連接信息,以及動態符號表
struct section { /* for 32-bit architectures */
char sectname[16]; /* name of this section */
char segname[16]; /* segment this section goes in */
uint32_t addr; /* memory address of this section */
uint32_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) */
};
複製代碼
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 */
};
複製代碼
節結構圖(代碼段):
char sectname[16]; /* Section名字 */
char segname[16]; /* Section所在的segment的名字 */
uint32_t addr; /* 內存中起始位置 */
uint32_t size; /* Section大小 */
uint32_t offset; /* Section的文件偏移 */
uint32_t align; /* 對其 */
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) */
複製代碼
__TEXT:__cstring 分析 源代碼:
static int PI = 3.1415;
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSString* hello = @"hello";
NSLog(@"%@", hello);
NSLog(@"Hello, World!!");
NSLog(@"Hello Hello");
NSLog(@"Hello Hello");
NSLog(@"PI = %d", PI);
int a = 100;
int b = 200;
int c = a + b;
NSLog(@"c = %d", c);
}
return 0;
}
複製代碼
對應的_cstring 節內容以下:

能夠看到全部的字符串保存在一張字符串表中,對應的內容是能夠被修改的,運行的時候執行的結果也會變成修改以後的內容。
LC_DYLD_INFO_ONLY
數據結構:
struct dyld_info_command {
uint32_t cmd; /* LC_DYLD_INFO or LC_DYLD_INFO_ONLY */
uint32_t cmdsize; /* sizeof(struct dyld_info_command) */
uint32_t rebase_off; /* file offset to rebase info */
uint32_t rebase_size; /* size of rebase info */
uint32_t bind_off; /* file offset to binding info */
uint32_t bind_size; /* size of binding info */
uint32_t weak_bind_off; /* file offset to weak binding info */
uint32_t weak_bind_size; /* size of weak binding info */
uint32_t lazy_bind_off; /* file offset to lazy binding info */
uint32_t lazy_bind_size; /* size of lazy binding infs */
uint32_t export_off; /* file offset to lazy binding info */
uint32_t export_size; /* size of lazy binding infs */
};
複製代碼

** 重定向數據rebase(命令碼:高四位、低四位) ** 11:REBASE_OPCODE_SET_TYPE_IMM 高四位0x10表示設置當即數類型 低四0x01位表示當即數類型爲指針
22:REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + 2 重定向到數據段的第2個section

Action 爲翻譯出來的內容,指向的是數據段的第2個節(Load Commands中的因此) 
具體的內容
弱綁定數據 weak_bind
延時綁定 lazy_bind
對於須要從動態庫加載的函數符號(_printf)
能夠使用nm工具查看二進制文件的導出符號 【 nm - display name list (symbol table)】
➜ Debug nm MachOTest
U _NSLog
0000000100001100 d _PI
U ___CFConstantStringClassReference
0000000100000000 T __mh_execute_header
0000000100000e40 T _main
U _objc_autoreleasePoolPop
U _objc_autoreleasePoolPush
U _objc_retain
U _objc_storeStrong
U dyld_stub_binder
複製代碼

TODO