MachO格式_mac文件格式

MachO格式_mac文件格式MachO(MachObject)格式文件可在Mac及iOS环境上执行,类似于windows上的PE格式文件(PortableExecutable轻量级执行文件),linux系统上的elf格式文件(ExecutableandLinkingFormat)轻量级执行文件Mac/iOS系统:MachO(MachObject)格式文件windows系统:PE(PortableExecutable)格式文件linux系统:elf(ExecutableandLinkingFormat)格式文件

MachO(MachObject)格式文件可在Mac及iOS环境上执行,类似于windows上的PE格式文件(Portable Executable轻量级执行文件),linux系统上的elf格式文件(Executable and Linking Format)
file/pod体系脚本命令
xxx体系脚本命令
交互环境型应用

轻量级执行文件

Mac/iOS系统:MachO(MachObject)格式文件
windows系统:PE(Portable Executable)格式文件
linux系统:elf(Executable and Linking Format)格式文件


MachO格式轻量级执行文件:用于可执行文件/目标代码/动态库。

文件遵循MachO格式
目标代码
目标文件.o

库文件
.a
.dylib
.Framework

可执行文件
dyld
.dsym

终端Bash语法脚本命令

File指令(file体系脚本命令)eg: file -v/file --help
通过约定标记file进行文件类型操作符操作。

通用二进制文件(Universal binary)
苹果公司提出的程序码文件,能同时适应多种架构的二进制文件。
同一个程序包中通过各种二进制文件为多种架构提供最理想的性能。
平台通用型二进制编码程序包通常会比单一型特定平台的二进制编码程序包容量要大,但由于不同架构间有共通的非执行资源,所以通用型程序包并不会达到单一版本的两倍多
而且由于运行时特性实际执行时只调用一部分代码并开辟该部分代码对应数据写入所需要内存空间,不需要额外多余的内存占用。


lipo命令(lipo体系脚本命令)
lipo -info //-info指令符查看MachO格式文件中涉及到的架构引入

$lipo -info MachO 文件
只听到从架构师办公室传来架构君的声音:
渐困倚、孤眠清熟。有谁来对上联或下联?

lipo -thin拆分某种架构

此代码由Java架构师必看网-架构君整理
$lipo MachO 文件 -thin架构 -output 输出文件路径

lipo -create 合并多种架构

$lipo -create MachO1 MachO2 -output 输出文件路径

MachO格式文件结构分层
MachO格式文件本身是一种带有某种MachO格式的文件
在这里插入图片描述
MachO格式的结构分层如图所示(总体3层):
Header区域包含该二进制文件的一般特性信息:字节顺序,架构类型,加载指令的数量等。可以快速确认一些特性信息,如当前文件用于32还是64位/对应的处理器是什么/文件类型是什么。

LoadCommands加载命令集(包含很多内容的 命令符号表):涉及区域的位置/符号表/动态符号表。

Data区通常是该二进制文件中所占容量最大的部分:包含Segment段域的具体数据。

Header结构分层的数据结构(开辟具有struct结构体特征的内存区)

此代码由Java架构师必看网-架构君整理
struct mach_header_64 { unit32_t magic; /*结构体内成员字段名magic魔数,快速定位属于64还是32位解析器*/ cpu_type_t cputype; /*CPU类型,比如ARM*/ cpu_subtype_t cpusubtype;/*CPU的具体类型arm64\arm7*/ uint32_t filetype;/*文件类型,比如可执行文件/io文件*/ unit32_t ncmds;/*loadCommands条数*/ uint32_t sizeofcmds;/*LoadCommands的大小*/ uint32_t flags;/*标志位标识二进制文件支持的功能,主要是和系统加载,链接有关*/ uint32_t reserved;/*reserved*/ }

LoadCommands
在这里插入图片描述
MachObject 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区节使用场景:
在这里插入图片描述
在这里插入图片描述
DYLD
dyld(the dynamic link editor)是苹果的动态链接器,是苹果操作系统一个重要组成部分,在系统内核做好程序准备工作之后,交由dyld负责余下的工作。

参数解释
LC_SEGMENT_64:将该段(64位)隐射到进程地址空间中
-LC_DYLD_INFO_ONLY:加载动态链接库信息(重定向地址、弱引用绑定、懒加载绑定、开放函数等的偏移值等信息)
-LC_SYMTAB:载入符号表地址
LC_DYSYMTAB:载入动态符号表地址
LC_LOAD_DYLINKER:加载动态加载库
LC_UUID:确定文件的唯一标识,crash解析中也会有这个,去检测dysm文件和crash文件是否匹配
LC_VERSION_MIN_MACOSX/LC_VERSION_MIN_IPHONEOS:确定二进制文件要求的最低操作系统版本
LC_SOURCE_VERSION:构建该二进制文件使用的源代码版本
LC_MAIN:设置程序主线程的入口地址和栈大小
LC_ENCRYPTION_INFO_64:获取加密信息
LC_LOAD_DYLIB:加载额外的动态库
LC_FUNCTION_STARTS:定义一个函数起始地址表,使调试器和其他程序易于看到一个地址是否在函数内
-LC_DATA_IN_CODE:定义在代码段内的非指令的表
-LC_CODE_SIGNATURE:获取应用签名信息

本文来源HaiJunYa,由架构君转载发布,观点不代表Java架构师必看的立场,转载请标明来源出处:https://javajgs.com/archives/210258
0
   

发表评论