JHHK

欢迎来到我的个人网站
行者常至 为者常成

MachO文件

目录

什么是MachO文件

一、Mach-O

Mach-O其实是Mach Object文件格式的缩写,是macOS、iOS、iPadOS存储程序(可执行文件)和库的文件格式,对应系统通过应用二进制接口(application binary interface,缩写为 ABI)来运行该格式的文件。

ABI稳定指的是Mach-O文件的内部结构稳定了下来,相应的系统在调用解析Mach-O文件时的流程也就稳定了下来.

类似于windows上的PE格式(Portable Executable),Linux上的elf格式(Executable and Linking Format)。

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

Mach-O格式用来替代BSD系统的a.out格式。Mach-O文件格式保存了在编译过程和链接过程中产生的机器代码和数据,从而为静态链接和动态链接的代码提供了单一文件格式。

可以理解为 Mach-O = 文件配置 + 二进制代码

objdump –macho –private-headers 文件

二、属于MachO格式的常见文件

目标文件: .o

库文件: .a .dylib .Framework

可执行文件

dyld

.dsym

三、查看文件格式

可通过file指令查看文件类型

1、查看.o文件的类型

$  vi test.c
$  clang -c test.c
$  file test.o
test.o: Mach-O 64-bit object x86_64

test.c文件内容

#include <stdio.h>

int main(){
	printf("helloWorld!\n");
	return 0;
}

2、查看.dylib文件的类型

$ find / -name "*.dylib"
/usr/local/mysql-8.0.12-macos10.13-x86_64/lib/libssl.dylib
/usr/local/mysql-8.0.12-macos10.13-x86_64/lib/plugin/libcrypto.1.0.0.dylib
/usr/local/mysql-8.0.12-macos10.13-x86_64/lib/plugin/libssl.1.0.0.dylib
/usr/local/mysql-8.0.12-macos10.13-x86_64/lib/plugin/debug/libcrypto.1.0.0.dylib
/usr/local/mysql-8.0.12-macos10.13-x86_64/lib/plugin/debug/libssl.1.0.0.dylib
/usr/local/mysql-8.0.12-macos10.13-x86_64/lib/libmysqlclient.21.dylib
...

file /usr/local/mysql-8.0.12-macos10.13-x86_64/lib/libssl.dylib
/usr/local/mysql-8.0.12-macos10.13-x86_64/lib/libssl.dylib: Mach-O 64-bit dynamically linked shared library x86_64

3、查看可执行文件的类型

$ clang test.o
$ ls
a.out	test.c	test.o
$ ./a.out
helloWorld!
$ file a.out
a.out: Mach-O 64-bit executable x86_64

我们改造下test.c文件

#include <stdio.h>

void test1();

int main(){
	printf("helloWorld!\n");

	test1();

	return 0;
}

在创建一个test1.c文件

void test1(){

	printf("test1\n");
}

查看文件类型

$ clang -c test.c test1.c       //编译
clang -o demo test.o test1.o    //连接
./demo                          //执行
helloWorld!
test1

$ file demo
demo: Mach-O 64-bit executable x86_64

在看下我们iOS工程的可执行文件的类型

$ file XXXClient
XXXClient: Mach-O universal binary with 2 architectures: [arm_v7:Mach-O executable arm_v7] [arm64]
XXXClient (for architecture armv7):	Mach-O executable arm_v7
XXXClient (for architecture arm64):	Mach-O 64-bit executable arm64

4、查看dyld文件的类型

$  cd /usr/lib
$ ls dyld
dyld
$ file dyld
dyld: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit dynamic linker x86_64] [i386:Mach-O dynamic linker i386]
dyld (for architecture x86_64):	Mach-O 64-bit dynamic linker x86_64
dyld (for architecture i386):	Mach-O dynamic linker i386

5、查看.dsym文件类型

$ ls -l
total 48
-rwxr-xr-x  1 LKLC  staff  8432  4 24 16:50 a.out
-rw-r--r--  1 LKLC  staff    72  4 24 16:50 test.c
-rw-r--r--  1 LKLC  staff   776  4 24 16:50 test.o
-rw-r--r--  1 LKLC  staff    38  4 24 16:12 test1.c
drwxr-xr-x  3 LKLC  staff    96  4 23 11:03 xxx.app.dSYM
$ file ./xxx.app.dSYM/Contents/Resources/DWARF/xxx
./xxx.app.dSYM/Contents/Resources/DWARF/xxx: Mach-O universal binary with 2 architectures: [arm_v7:Mach-O dSYM companion file arm_v7] [arm64]
./xxx.app.dSYM/Contents/Resources/DWARF/xxx (for architecture armv7):	Mach-O dSYM companion file arm_v7
./xxx.app.dSYM/Contents/Resources/DWARF/xxx (for architecture arm64):	Mach-O 64-bit dSYM companion file arm64

universal binary

一、介绍

苹果公司提出的一种程序代码。能同时适用多种架构的二进制文件。

同一程序包中同时为多种架构提供最理想的性能。

因为需要存储多种代码,通用二进制应用程序通常比单一平台二进制的程序要大。

但是由于两种架构有共通的非执行资源,所以并不会达到单一版本的两倍之多。

而且由于执行中只调用一部分代码,运行起来也不需要额外的内存。

另外从iOS11的系统开始,只支持arm64架构

看下在xcode中如何配置

img

二、拆分与合并(lipo命令)

1、使用 lipo -info MachO文件 查看MachO文件包含的架构

$ lipo -info xxxmacho
Architectures in the fat file: macho are: armv7 arm64

2、使用 lipo MachO文件 -thin 架构 -output 输出文件路径 拆分某种架构

$ lipo xxxmacho -thin arm64 -output macho_arm64
$ lipo -info macho_arm64
Non-fat file: macho_arm64 is architecture: arm64

$ lipo xxxmacho -thin armv7 -o macho_armv7
$ lipo -info macho_armv7
Non-fat file: macho_armv7 is architecture: armv7

3、使用 lipo -create macho文件1 macho文件2 -output 输入文件路径 合并多种架构

$ lipo -create macho_armv7 macho_arm64 -output macho_lc
$ lipo -info macho_lc
Architectures in the fat file: macho_lc are: armv7 arm64

localhost:test LKLC$ md5 xxxmacho
MD5 (xxxmacho) = 882235a199c6cfb1bcf3f437527f7961

localhost:test LKLC$ md5 macho_lc
MD5 (macho_lc) = 882235a199c6cfb1bcf3f437527f7961

MachO文件结构

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

img

MachO的组成结构如图所示包括了

一、Header包含该二进制文件的一般信息

字节顺序(大小端)、架构类型、加载指令的数量等。

使得可以快速确认一些信息,比如当前文件用于32位还是64位,对应的处理器是什么、文件类型是什么

程序加载的时候会首先解析头部信息,在xcode内command+shift+o 搜索loader.h可以看到头部的一些数据结构

img

通过MachOView工具看下头部信息

img

二、Load commands 一张包含很多内容的表

内容包括区域的位置、符号表、动态符号表等。

img

三、Data 通常是对象文件中最大的部分

包含 segement的具体数据

img

MachO可以简单类比成一本书,其中header为序,Load Commands为目录,Data为具体的内容。


行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.