Mach-O初探 &编译与链接

2021-02-20  本文已影响0人  猿人

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

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

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

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

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

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

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

Mach header :指定文件的目标体系结构,自我描述信息
Load commands: 在虚拟内存中指定文件的逻辑结构和文件的布局。类似书的目录
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 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

编译

  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

编译出中间代码.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
看到这里在回顾一下上面mach -O
截屏2021-02-20 下午4.39.37.png
总结:
上一篇 下一篇

猜你喜欢

热点阅读