初识Mach-O文件

详细版本 https://www.yuque.com/docs/share/077aaf76-0fe6-47da-a7c9-d2af0c4b4e3a?# 《初识Mach-O 文件》

何为Mach-O文件?

Mach-O为Mach Object文件格式的缩写,它是一种用于可执行文件,目标代码,动态库,内核转储的档案格式,mac和iOS的可执行文件都是这种格式

当然了,他也有很多种存在的格式

  • 目标文件.o
  • 库文件:.a静态库文件;.dylib动态库文件;.framework系统级为动态库文件,自己创建的为静态库文件
  • 可执行文件及MDW.app内部的MDW文件(通用二进制文件)
  • .dyld动态链接器将依赖的动态库加载到内存
  • .dsym符号表

发展历史

macOS系统一路走来,支持的CPU及硬件平台都有了很大的变化,从早期的PowerPC平台,到后来的x86,再到现在主流的arm、x86-64平台。软件开发人员为了做到不同硬件平台的兼容性,如果需要为每一个平台编译一个可执行文件,这将是非常繁琐的。为了解决软件在多个硬件平台上的兼容性问题,苹果开发了一个通用的二进制文件格式(Universal Binary)。

Mach-O文件的内部结构

官方图片

image.png

文件分为三个部分:

1、Header:包含Mach-O文件的基本信息,字节顺序、架构类型、加载指令的数量等

2、Load commands:包含区域位置、符号表、动态符号表,加载Mach-O文件时使用这里的数据确定内存分布

3、Data:数据段segement,包含具体代码、常量、类、方法等,有多个segment,每个segment有0到多个section,每个段有一个虚拟地址映射到进程的地址空间

通过Mach-O文件 可以查看到里面的内容


image.png

Header

image.png
  • magic:魔数,确定是64位还是32位
  • cputype:cpu类型
  • cpusubtype:cpu子类型(arm64 armv7)
  • filetype:Mach-O支持多种文件类型,使用filetype来标注具体文件类型,比如可执行文件、目标文件等等
  • ncmds:加载命令(load commands)的数量
  • sizeofcmds:命令区域(load commands)总的字节大小
  • flags:标识二进制文件所支持的功能,主要与系统的加载、链接有关

Load commands

image.png
  • LC_SEGMENT_64:将文件中的段映射到进程地址空间中
  • LC_DYLD_INFO_ONLY:动态链接相关信息
  • LC_SYMTAB:符号表信息,位置、偏移、数据个数,供dyld使用
  • LC_DYSYMTAB:动态符号表信息,供dyld使用
  • LC_LOAD_DYLINKER:链接器信息,记录使用那些链接器完成内核后序的加载工作
  • LC_UUID:Mach-O文件的唯一标识
  • LC_VERSION_MIN_MACOSX:支持最低操作系统版本
  • LC_SOURCE_VERSION:源代码的版本号
  • LC_MAIN:设置主线程的入口即栈大小
  • LC_LOAD_DYLIB:依赖库信息,dyld通过该命令去加载依赖库
  • LC_FUNCTION_STARTS:函数的起始地址表
  • LC_CODE_SIGNATURE:代码签名
image.png
  • sectname:是__text ,就是主程序代码
  • segname:该section所属的segment名,第一个是__TEXT
  • addr:当前section在内存中的起始位置
  • size:当前section所占内存大小
  • offset:当前section的文件偏移
  • align:字节大小对齐
  • reloff:重定位入口的文件偏移,0
  • nreloc:需要重定位的入口数量,0
  • flags:包含section的type和attributes
  • reserved1、reserved2预留字段

Data

Data区域由Segment段和Section节组成

Segment

segment主要有__TEXT和__DATA组成

__text:是主程序代码
__stubs、__stub_helper:是动态链接的桩
__cstring:程序中c语言字符串
__const:常量
image.png
image.png

Section
在 Segment 里面会包含不同的 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 */
};

sectname: section 的名字
segname: segment 的名字
addr: 映射到虚拟地址的偏移
size: section 的大小
offset: section 在当前架构中的偏移
align: section的字节对齐大小 n
reloff: 重定位入口的文件偏移
nreloc: 重定位入口的个数
flags: section的类型与属性:
reserved: 保留位

你可能感兴趣的:(初识Mach-O文件)