MachO文件

2020-04-29  本文已影响0人  coder_feng

MachO文件

Mach-O其实就是Mach Object文件格式的缩写,是mac以及iOS上可执行文件的格式,类似于windows上的PE格式(Portable Executable),linux上的elf格式(Executable and Linking Format)

Mach-O 文件格式

Mach-O为Mach Object文件格式的缩写,它是一种用于可执行文件,目标代码,动态库的文件格式。作为a.out格式的替代,Mach-O提供了更强的扩展性

属于MachO格式的常见文件

File指令

通用二进制文件(Universal binary)

lipo命令

$lipo -info MachO 文件
$lipo MachO 文件 -thin架构 -output 输出文件路径
$lipo -create MachO1 MachO2 -output 输出文件路径

MachO 文件结构

因为MachO文件本身是一种文件格式,所以我们一定需要了解其文件内部结构 image.png

Mach-O 的组成机构如图所示包括了

Header的数据结构

struct mach_header_64 {
 unit32_t magic; /*魔数,快速定位属于64还是32位*/
cpu_type_t cputype; /*CPU类型,比如ARM*/
cpu_subtype_t cpusubtype;/*CPU的具体类型arm64\arm7*/
uint32_t filetype;/*文件类型,比如可执行文件*/
unit32_t ncmds;/*loadCommands条数*/
uint32_t sizeofcmds;/*LoadCommands的大小*/
uint32_t flags;/*标志位标识二进制文件支持的功能,主要是和系统加载,链接有关*/
uint32_t reserved;/*reserved*/
}

LoadCommands

image.png

Mach-O Data

Data区域是由Segment段和Section节组成。先来看看Segment的组成,代码来自loader.h

Segment 的组成段

#define    SEG_PAGEZERO    "__PAGEZERO" /* 当时 MH_EXECUTE 文件时,捕获到空指针 */
#define    SEG_TEXT    "__TEXT" /* 代码/只读数据段 */
#define    SEG_DATA    "__DATA" /* 数据段 */
#define    SEG_OBJC    "__OBJC" /* Objective-C runtime 段 */
#define    SEG_LINKEDIT    "__LINKEDIT" /* 包含需要被动态链接器使用的符号和其他表,包括符号表、字符串表等 */

Segment 的数据结构

struct segment_command_64 { 
    uint32_t    cmd;        /* LC_SEGMENT_64 */
    uint32_t    cmdsize;    /* section_64 结构体所需要的空间 */
    char        segname[16];    /* segment 名字,上述宏中的定义 */
    uint64_t    vmaddr;        /* 所描述段的虚拟内存地址 */
    uint64_t    vmsize;        /* 为当前段分配的虚拟内存大小 */
    uint64_t    fileoff;    /* 当前段在文件中的偏移量 */
    uint64_t    filesize;    /* 当前段在文件中占用的字节 */
    vm_prot_t    maxprot;    /* 段所在页所需要的最高内存保护,用八进制表示 */
    vm_prot_t    initprot;    /* 段所在页原始内存保护 */
    uint32_t    nsects;        /* 段中 Section 数量 */
    uint32_t    flags;        /* 标识符 */
};

Segment可以说是由多个Section组成的,下面是Section具体的数据结构

struct section_64 { 
    char        sectname[16];    /* Section 名字 */
    char        segname[16];    /* Section 所在的 Segment 名称 */
    uint64_t    addr;        /* Section 所在的内存地址 */
    uint64_t    size;        /* Section 的大小 */
    uint32_t    offset;        /* Section 所在的文件偏移 */
    uint32_t    align;        /* Section 的内存对齐边界 (2 的次幂) */
    uint32_t    reloff;        /* 重定位信息的文件偏移 */
    uint32_t    nreloc;        /* 重定位条目的数目 */
    uint32_t    flags;        /* 标志属性 */
    uint32_t    reserved1;    /* 保留字段1 (for offset or index) */
    uint32_t    reserved2;    /* 保留字段2 (for count or sizeof) */
    uint32_t    reserved3;    /* 保留字段3 */
};

一下是一些常见的Section

Section 账号
__TEXT.__text 主程序代码
__TEXT.__cstring C 语言字符串
__TEXT.__const const 关键字修饰的常量
__TEXT.__stubs 用于 Stub 的占位代码,很多地方称之为桩代码。
__TEXT.__stubs_helper 当 Stub 无法找到真正的符号地址后的最终指向
__TEXT.__objc_methname Objective-C 方法名称
__TEXT.__objc_methtype Objective-C 方法类型
__TEXT.__objc_classname Objective-C 类名称
__DATA.__data 初始化过的可变数据
__DATA.__la_symbol_ptr lazy binding 的指针表,表中的指针一开始都指向 __stub_helper
__DATA.nl_symbol_ptr 非 lazy binding 的指针表,每个表项中的指针都指向一个在装载过程中,被动态链机器搜索完成的符号
__DATA.__const 没有初始化过的常量
__DATA.__cfstring 程序中使用的 Core Foundation 字符串(CFStringRefs)
__DATA.__bss BSS,存放为初始化的全局变量,即常说的静态内存分配
__DATA.__common 没有初始化过的符号声明
__DATA.__objc_classlist Objective-C 类列表
__DATA.__objc_protolist Objective-C 原型
__DATA.__objc_imginfo Objective-C 镜像信息
__DATA.__objc_selfrefs Objective-C self 引用
__DATA.__objc_protorefs Objective-C 原型引用
__DATA.__objc_superrefs Objective-C 超类引用

DYLD

dyld(the dynamic link editor)是苹果的动态链接器,是苹果操作系统一个重要组成部分,在系统内核做好程序准备工作之后,交由dyld负责余下的工作

参数解释

源码地址

opensource.apple.com
Mach-O文件格式探索

上一篇 下一篇

猜你喜欢

热点阅读