Mach-O初探 &编译与链接

Mach-O与连接器的一个作用

Mach-o到底是什么?
Mach-O(Mach Object)是macOS、iOS、iPadOS存储序和库的文件格式。对应系统通过引用二进制接口(application binary interface,所写为ABI)来运行该格式的文件。
Mach-O格式用来替代BSD系统的a.out格式。Mach-O文件格式保存了在编译过程的连接过重产生的机器代码和数据,从而为静态连接和动态连接的代码提供了单一文件格式。
Mach-O 是iOS系统不同运行时期,可执行文件类型的统称。它是一种用于,可执行文件、目标代码、动态库、内核转储的文件格式。
Mach -O 的三种类型:Executable 、Dylib 、bundle

  • 思考一个问题当我们项目点击运行那一刻发生了什么系统到底做了什么?
    首先它去加载 ipa包,然后去找到 ipa包里的一个可执行文件黑不溜秋的。
截屏2021-01-21 下午9.10.25.png

其可执行文件的调用过程:

  • 1.调用fork函数,创建一个process
  • 2.调用execve或其衍生函数,在该进程上加载,执行我们的Mach-O文件
    当我们调用时execve(程序加载器),内核实际上在执行:
  • 1.将文件加载到内存
  • 2.开始分析Mach-O中的mach_header,以确认它是有效的Mach-O文件

对于上面的我们先不了解过深我们先看它到底是怎样一种格式我们理解
通过下面命令

objdump --macho --private-headers / 黑不溜秋的地址 

截屏2021-01-21 下午9.26.47.png

可以看到里面他有 mach header 有多个 load command 有多个section ,那他们之间的关系是怎样的呢?我们先看下面每个字段的含义。

Mach header :指定文件的目标体系结构,自我描述信息
  • magic: ,系统加载器通过该字段快速,判断当前文件
  • cputype: 标识cpu架构,比如ARM, X86,i386等等,该字段确保系统可以将合适的二进制文件在当前架构下运行。
  • cpusubtype: 具体的cpu类型,区分不同版本的处理器,如arm64,armv7
  • filetype: 说明该mach-o文件类型(可执行文件,库文件,核心转储文件,内核扩展,DYSM文件,动态库)。
  • ncmds: loadCommands数量,每个LoadCommands代表了一种Segment的加载方式 .
  • sizeofcmmds:所有Load commands的总字节大小
  • flags:标识二进制文件支持的功能,主要与系统的加载、连接有关
  • reserved:保留的字段。
Load commands: 在虚拟内存中指定文件的逻辑结构和文件的布局。类似书的目录
  • load commands 跟在mach_header之后。所有命令的总大小由mach_header中sizeofcmmds字段给出。
  • load command必须有前两个字段 cmd 和 cmdsize. cmd字段以该命令类型的常量填充。每个命令类型都有专门追对它的结构。cmdsize字段是特定加载命令结构的字节大小加跟随它的任何一部分,这是加载命令(即节结构、字符串等)的须是4字节的倍数,对于64位架构必须是8字节的倍数(这些永远是任何加载命令的最大对齐)。填充的字节必须为0.
  • 目标文件中的所有表也必须遵循这些规则,以便文件可以进行内容映射。否则,这些表的指针在某些机器上无法正常工作或根本无法真长工作。所有padding归零对象
Raw segment data: 包含在加载命令中定义的段的原始数据。主要包含代码、数据、符号表等

因为mach -O里面全部都是二进制的,我们就可以理解为 配置文件+二进制代码,比如说 为什么我们程序的启动都是main?就是因为mach- O指定了它的入口函数 在dyld解析的时候会根据这个字段来找到入口函数
通过下面命令 找到 LC_MAIN

objdump --macho --private-headers / 黑不溜秋的地址 | ag 'LC_MAIN' -A  3
截屏2021-01-21 下午9.40.14.png

总结

Mach-O图解1
  • 比如通过黄色区域 _TEXT load Command 就可以找到其_TEXT代码具体的执行二进制的位置。
  • 通过 _DATA Load Command 就可以 找到 _DATA 具体的执行位置
  • load Command 就向一本书的目录. 可以通过目录 来定位 具体的章节
Mach-O图解2

此图更能形象的描述出 Mach-O 的结构,整个 Mach-O 均为二进制文件,它就向一本书,Mach header 就像 书的前言 自描述着,load commands 就像书的目录 Data 就向是目录 具体的内容。

编译链接过程

截屏2021-02-20 下午1.12.58.png

对于上面的描述有些生硬,我来实操一下


截屏2021-02-20 下午2.12.46.png

看如上代码只编译一个mian.m 然后我们通过命令去查看编译出来的可执行文件代码 段

objdump --macho -d /黑不溜秋的地址。
截屏2021-02-20 下午2.15.23.png
  • 可以看到NSLog变成了一条指令 callq 这个地址
    那在编译的时候实际干了点什么事情呢?

编译

  1. 再编译过程把能变成汇编的尽量变成汇编变成机器码
  2. 不能变成汇编的给其进行一个归类。

比如上面的NSLog 可以callq一个地址,向其他的变量就要进行归类 比如说 数据,那应该放在数据段,其他的放在其他地方,比如变成目标文件的时候像NSlog在其他的mach-O 中,需要链接的时候才能确定一些东西那怎么办?所以就是,将不能变成机器码的符号进行一个归类

下面我们看一下当前的重定位符号表 我们先将 main.m 用clang编译器成 中间代码.o

$ clang -x objective-c \
> -target x86_64-apple-macos10.15 \
> -fobjc-arc \
> -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk \
> -c main.m -o main.o
  • -x objective-c :指定编译语言
  • -target x86_64-apple-macos10.15 :指定编译架构
  • -fobjc-arc : 指定编译 是arc
  • -isysroot 比如<Foundation/Foundation.h> 系统sdk在哪
  • 输出。

编译出中间代码.o之后 我们在来看一下 当前.o 的重定位符号表

objdump --macho --reloc  .o地址
$ objdump --macho --reloc /Users/lh/Desktop/LHObject/symbol/symbol/main.o 
/Users/lh/Desktop/LHObject/symbol/symbol/main.o:
Relocation information (__TEXT,__text) 4 entries
address  pcrel length extern type    scattered symbolnum/value
00000033 True  long   True   BRANCH  False     _NSLog
00000029 True  long   True   SIGNED  False     _static_init_value
0000001f True  long   True   SIGNED4 False     _static_uninit_value
0000000b True  long   False  SIGNED  False     5 (__DATA,__cfstring)
Relocation information (__DATA,__cfstring) 2 entries
address  pcrel length extern type    scattered symbolnum/value
00000010 False quad   False  UNSIGND False     4 (__TEXT,__cstring)
00000000 False quad   True   UNSIGND False     ___CFConstantStringClassReference
Relocation information (__LD,__compact_unwind) 1 entries
address  pcrel length extern type    scattered symbolnum/value
00000000 False quad   False  UNSIGND False     1 (__TEXT,__text)

对应上面的我们看一下都代表什么意思


截屏2021-02-20 下午3.42.35.png
  • 从这里我们就能明白,重定位符号表里 的保存的是当前文件你用到的符号,使用了的在这里,没有使用的不在这里。
总结:

程序编译过程 就是将.m 变成.o 的过程。里面做了通过词法分析语法分析展开宏啊清除注释啊,能变成机器码的尽量变成机器码。不能变成对符号进行归类,对于当前.m文件用到的符号,放在重定向符号表里。

链接:

当程序被编译成一个个中间代码.o, 接下来就需要进行一个链接过程,处理编译情况。 把多个目标文件合并到一起,之后 也就意味着,重定位符号表,包括 其他符号,就被合并到一张表中,最后生成我们的可执行文件 exec

Symbol Table
  • symbol Table:用来保存符号
  • StringTable: 用来保存符号的名称
  • indrect Symbol Table:间接符号表,保存使用外部符号,更准确一点就是使用的外部动态库的符号,是symbolTable的子集(例如: NSLog)
看到这里在回顾一下上面mach -O
截屏2021-02-20 下午4.39.37.png
  • 一样通过load Command 来找到 符号表的一个具体的位置。
总结:
  • 链接过程就是在处理目标文件符号的过程。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容