Mach—O文件
Header: 指明了 cpu 架构、大小端序、文件类型、Load Commands 个数、大小等一些基本信息. (校验合法性, 并确定运行环境)
Load Commands: 描述了怎样加载每个 Segment 的信息. 在 Mach-O 文件中可以有多个 Segment, 每个 Segment 可能包含一个或多个 Section.
Data: Segment 的具体数据, 包含了代码和数据等.
Mach-O 头部定义(macOS 10.15 sdk):
/*
* 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) */
cputype 和 cpusubtype 确定 cpu 类型、平台
filetype 文件类型, 包括可执行文件、符号文件(DSYM)、内核扩展等
flags dyld 加载的标志
MH_NOUNDEFS 目标文件没有未定义的符号
MH_DYLDLINK 目标文件是动态链接输入文件, 不能被再次静态链接
MH_SPLIT_SEGS 只读 segments 和 可读写 segments 分离
MH_NO_HEAP_EXECUTION 堆内存不可执行
…
- filetype:
/*
* Constants for the filetype field of the 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 */
/* sections */
#define MH_KEXT_BUNDLE 0xb /* x86_64 kexts */
load command:
struct load_command {
uint32_t cmd; /* type of load command */
uint32_t cmdsize; /* total size of command in bytes */
};
如
LC_MAIN: 设置程序主线程入口地址和栈大小
LC_CODE_SIGNATURE: 代码签名
LC_SYMTAB: 符号表地址
LC_DYSYMTAB: 动态符号表地址
…
segment:
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 */
};
- segname 段名(其定义在下面与section名共同列出)
SEG_
开头为段名
SECT_
为某段中的节名
/* The currently known segment names and the section names in those segments */
#define SEG_PAGEZERO "__PAGEZERO" /* the pagezero segment which has no */
/* protections and catches NULL */
/* references for MH_EXECUTE files */
#define SEG_TEXT "__TEXT" /* the tradition UNIX text segment */
#define SECT_TEXT "__text" /* the real text part of the text */
/* section no headers, and no padding */
#define SECT_FVMLIB_INIT0 "__fvmlib_init0" /* the fvmlib initialization */
/* section */
#define SECT_FVMLIB_INIT1 "__fvmlib_init1" /* the section following the */
/* fvmlib initialization */
/* section */
#define SEG_DATA "__DATA" /* the tradition UNIX data segment */
#define SECT_DATA "__data" /* the real initialized data section */
/* no padding, no bss overlap */
#define SECT_BSS "__bss" /* the real uninitialized data section*/
/* no padding */
#define SECT_COMMON "__common" /* the section common symbols are */
/* allocated in by the link editor */
#define SEG_OBJC "__OBJC" /* objective-C runtime segment */
#define SECT_OBJC_SYMBOLS "__symbol_table" /* symbol table */
#define SECT_OBJC_MODULES "__module_info" /* module information */
#define SECT_OBJC_STRINGS "__selector_strs" /* string table */
#define SECT_OBJC_REFS "__selector_refs" /* string table */
#define SEG_ICON "__ICON" /* the icon segment */
#define SECT_ICON_HEADER "__header" /* the icon headers */
#define SECT_ICON_TIFF "__tiff" /* the icons in tiff format */
#define SEG_LINKEDIT "__LINKEDIT" /* the segment containing all structs */
/* created and maintained by the link */
/* editor. Created with -seglinkedit */
/* option to ld(1) for MH_EXECUTE and */
/* FVMLIB file types only */
#define SEG_UNIXSTACK "__UNIXSTACK" /* the unix stack segment */
#define SEG_IMPORT "__IMPORT" /* the segment for the self (dyld) */
/* modifing code stubs that has read, */
/* write and execute permissions */
-
vmaddr 段的虚存地址(未偏移), 由于 ALSR, 程序会在进程加上一段偏移量(slide), 真实的地址 = vm address + slide
-
vmsize 段的虚存大小
-
fileoff 段在文件的偏移
-
filesize 段在文件的大小
-
nsects 段中有多少个 section
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 */
};
__Text
和 __Data
都有自己的 section
- sectname section名
__Text.__text
主程序代码
__Text.__cstring
静态字符串常量
__Text.__stubs
__Text.__stub_helper
动态链接
__Text.__objc_methodname
方法名
__Text.__objc_methtype
方法类型
__Data.__data
初始化可变的数据
__Data.__objc_imageinfo
镜像信息, 在运行时初始化时 objc_init, 调用 load_images 加载新的镜像到 infolist 中
__Data.__objc_classlist
类列表
__Data.__objc_classrefs
引用的类
__Data.__got
非懒加载符号指针(表)(Non-Lazy Symbol Pointers)
__Data.__la_symbol_ptr
懒加载符号指针(表)(Lazy Symbol Pointers)