iOS--编译连接的过程_2

news/2024/12/29 8:17:07/

文章目录

  • iOS编译
      • (一)编译器前端
  • 编译器后端
    • 执行一次XCode build的流程
  • IPA包的内容
  • 二进制文件的内容
    • iOS Link Map File文件说明
      • 1. Link Map File 是什么
      • 2. Link Map File 有什么用
      • 3. 生成 Link Map File
      • 查看Link Map File
        • 1)路径部分
        • 计算机系统知识
          • a. __TEXT段中的 Section
          • b. __DATA段中的 Section
          • (4) Symbols 部分
          • (5)二进制重排

一般可以将编程语言分为两种,编译语言和直译式语言。

像C++,Objective C都是编译语言。编译语言在执行的时候,必须先通过编译器生成机器码,机器码可以直接在CPU上执行,所以执行效率较高。

像JavaScript,Python都是直译式语言。直译式语言不需要经过编译的过程,而是在执行的时候通过一个中间的解释器将代码解释为CPU可以执行的代码。所以,较编译语言来说,直译式语言效率低一些,但是编写的更灵活

iOS编译

Objective C采用Clang(swift采用swiftc)作为编译器前端,LLVM作为编译器后端。

简单的编译过程如图
在这里插入图片描述

(一)编译器前端

编译器前端的任务是进行:词法分析,语法分析,语义分析,生成中间代码(intermediate representation )。在这个过程中,会进行类型检查,如果发现错误或者警告会标注出来在哪一行。
在这里插入图片描述

编译器后端

编译器后端会进行机器无关的代码优化,生成机器语言,并且进行机器相关的代码优化。iOS的编译过程,后端的处理如下

  • LVVM优化器会进行BitCode的生成,链接期优化等等

  • 在这里插入图片描述

  • LLVM机器码生成器会针对不同的架构,比如arm64等生成不同的机器码

  • 在这里插入图片描述

执行一次XCode build的流程

当你在XCode中,选择build的时候(快捷键command+B),会执行如下过程

编译信息写入辅助文件,创建编译后的文件架构(name.app)
处理文件打包信息,例如在debug环境下

Entitlements:
{
“application-identifier” = “app的bundleid”;
“aps-environment” = development;
}

执行CocoaPod编译前脚本
例如对于使用CocoaPod的工程会执行CheckPods Manifest.lock
编译各个.m文件,使用CompileC和clang命令。

CompileC ClassName.o ClassName.m normal x86_64 objective-c com.apple.compilers.llvm.clang.1_0.compiler
export LANG=en_US.US-ASCII
export PATH=“…”
clang -x objective-c -arch x86_64 -fmessage-length=0 -fobjc-arc… -Wno-missing-field-initializers … -DDEBUG=1 … -isysroot iPhoneSimulator10.1.sdk -fasm-blocks … -I 上文提到的文件 -F 所需要的Framework -iquote 所需要的Framework … -c ClassName.c -o ClassName.o

通过这个编译的命令,我们可以看到

clang是实际的编译命令
-x objective-c 指定了编译的语言
-arch x86_64制定了编译的架构,类似还有arm7等
-fobjc-arc 一些列-f开头的,指定了采用arc等信息。这个也就是为什么你可以对单独的一个.m文件采用非ARC编程。
-Wno-missing-field-initializers 一系列以-W开头的,指的是编译的警告选项,通过这些你可以定制化编译选项
-DDEBUG=1 一些列-D开头的,指的是预编译宏,通过这些宏可以实现条件编译
-iPhoneSimulator10.1.sdk 制定了编译采用的iOS SDK版本
-I 把编译信息写入指定的辅助文件
-F 链接所需要的Framework
-c ClassName.c 编译文件
-o ClassName.o 编译产物

  • 链接需要的Framework,例如Foundation.framework,AFNetworking.framework,ALiPay.fframework
  • 编译xib文件
  • 拷贝xib,图片等资源文件到结果目录
  • 编译ImageAssets
  • 处理info.plist
  • 执行CocoaPod脚本
  • 拷贝Swift标准库
  • 创建.app文件和对其签名

IPA包的内容

例如,我们通过iTunes Store下载微信,然后获得ipa安装包,然后实际看看其安装包的内容。
在这里插入图片描述

二进制文件的内容

通过XCode的Link Map File,我们可以窥探二进制文件中布局。 在XCode -> Build Settings -> 搜索map -> 开启Write Link Map File
![

iOS Link Map File文件说明

1. Link Map File 是什么

Link Map File 直译为 链接映射文件,是 Xcode 生成可执行文件时一起生成的文本,用于记录链接相关信息。

可执行文件的路径
CPU架构
.o目标路径
方法符号

2. Link Map File 有什么用

查看代码加载顺序
理解内存分段分区
Crash 时通过 Symbols 定位源码的机制
分析可执行文件中类或库体积,优化包体积

3. 生成 Link Map File

Xcode 在生成可执行文件的时候默认情况下不生成该文件。 在Xcode的配置中 Target -> Build Setting -> Linking 将Write Link Map File设置为YES来生成Link Map File,运行代码即可生成Link Map File在这里插入图片描述

查看Link Map File

主要分为三个部分

  • 路径部分,展示生成的相关文件路径
  • Section部分,展示相关地址段
  • Symbols部分,方法符号段

1)路径部分

  • Path是.app文件路径
  • Object files是.o文件路径
  • 在这里插入图片描述

计算机系统知识

a. text 段
这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读(某些架构也允许代码段为可写,即允许修改程序)。
代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域。

在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。

b. data 段

数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。

c. bss 段

bss段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。

bss是英文Block Started by Symbol的简称。

d. 堆(heap)

堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。

当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);

当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。

e. 栈(stack)

栈又称堆栈,是用户存放程序临时创建的局部变量,

也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。

除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。

由于栈的先进先出(FIFO)特点,所以栈特别方便用来保存/恢复调用现场。

从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

(3)Section 部分

Mach-O 文件中的虚拟地址最终会映射到物理地址上。这些地址被分成不同的Segement: TEXT段、DATA段、__LINKEDIT段。

__TEXT 包含 Mach header,被执行的代码和只读常量(如C 字符串),只读可执行(r-x)。
__DATA 包含全局变量,静态变量等,可读写(rw-)。
__LINKEDIT 包含了加载程序的元数据,比如函数的名称和地址,只读(r–)。

Segement 划分成了不同的 Section,不同的 Section 存储着不同的信息,下面是一些常用的 Section 的介绍。

a. __TEXT段中的 Section

在这里插入图片描述

b. __DATA段中的 Section

在这里插入图片描述
在这里插入图片描述

(4) Symbols 部分
  • Address:方法代码的地址
  • Size:方法占用的空间
  • File:文件的编号
  • Name:.o文件里面的方法符号
(5)二进制重排

二进制重排 就是要重新排列这些 方法符号的顺序 ,中心思想就是把启动用到的代码挪到前面的位置加载!


http://www.ppmy.cn/news/974291.html

相关文章

Chat GPT真的是风险大于收益?

不可否认,自从允许公众访问和使用以来,ChatGPT 就一直是热门话题。人工智能现在已经成为每个人都知道的话题,尤其是在科技界。它已成为学校和大学课程的一部分,并且该主题已在教育学位和课程中占有一席之地。有几个 Open AI 应用程序以某种形式存在了很长一段时间,但并没有…

win11系统之安装MySQL8.0版本

win11系统之安装MySQL8.0版本 一、本次实践介绍1.1 MySQL简介1.2MySQL8.0特点1.2 环境介绍二、下载MySQL软件包2.1 MySQL官网2.2 下载MySQL安装包三、环境配置工作3.1 解压软件包3.2 新建mysql.inI配置文件3.3 设置环境变量四、MySQL的初始化设置4.1 打开cmd工具4.2 切换目录4.…

ubuntu22.04上如何创建有privilege权限,有固定自定义IP的空容器

需求背景: 我想用docker来隔离自己的主机环境,来创建一个隔离的空白全新的开发环境,并且使之有固定的IP,在里面可以自由更新下载各种编译依赖,具有privileged权限的容器,以下是操作实现的具体步骤 查看do…

ssh打开远程vscode

如果想要远程打开其他终端的vscode,首先要知道远程终端的ip地址和用户名称以及用户密码 1、打开本地vscode 2、点击左下角蓝色区域 3、页面上部出现如下图,点击ssh,我这里已经连接,所以是connect to host 4、选择Add New SSH Host…

iOS--编译链接的过_1

iOS 开发中使用的是编译语言,所谓编译语言是在执行的时候,必须先通过编译器生成机器码,机器码可以直接在CPU上执行,所以执行效率较高,是使用 Clang / LLVM 来编译的。LLVM是一个模块化和可重用的编译器和工具链技术的集…

ElasticSearch学习--数据聚合

介绍 数据聚合可以帮助我们对海量的数据进行统计分析,如果结合kibana,我们还能形成可视化的图形报表。自动补全可以根据用户输入的部分关键字去自动补全和提示。数据同步可以帮助我们解决es和mysql的数据一致性问题。集群可以帮助我们了解结构和不同节点…

从简单线性回归到TensorFlow深度学习

大家好,人工智能近年来变得越来越流行,学习人工智能的需求也随之增加,尤其是许多IT专业人士希望利用机器学习的强大功能,但面临不小的挑战,尤其是在理论和数学上。 步骤1:线性回归 线性回归是一种统计学中…

【CN-Docker】window11下Docker下开启kubernetes

1. 安装Docker 安装docker步骤如下: 下载Docker启用hyper-v 2.1.powershell,管理员运行Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All安装wsl配置Docker镜像加速地址(阿里云) 4.1. "registry-mirrors": [&quo…