iOS——编译链接

news2024/11/23 8:41:22

编译连接的过程

  1. 预处理
  2. 编译
  3. 汇编
  4. 链接

预处理

clang -E main.m -o main.i
  1. “#define"删除并展开对应宏定义。
  2. 处理所有的条件预编译指令。如#if/#ifdef/#else/#endif。
  3. ”#include/#import"包含的文件递归插入到此处。
  4. 删除所有的注释"//或/**/"。
  5. 添加行号和文件名标识,编译调试会用到。

编译

clang -S main.i -o main.s

这个过程就是把上面的main.i文件进行:词法分析、语法分析、静态分析,优化生成相应的汇编代码,最终生成main.s文件。

  1. 词法分析:把源代码的字符序列分割成一个个token(关键字、表示符、字面量、特殊符号),比如把标识符放到符号表里面。
  2. 语法分析:生成抽象语法树AST,此时运算符号的优先级确定了;有些符号具有多重含义也确定了,比如:*是乘号还是对指针取内容;表达式不合法、括号不匹配等等,都会报错。
  3. 静态分析:分析类型声明和匹配问题。比如整型和字符串相加,肯定会报错。
  4. 中间语法生成:CodeGen根据AST自上向下逐步翻译成LLVM IR,并且对在编译期就可以确定的表达式进行优化,比如代码里面的a=1+3,可以优化成a=4。(假如开启了bitcode)
  5. 目标代码生成与优化:根据中间语法生成依赖具体机器的汇编语言;并优化汇编语言。这个过程中,假如有变量且定义在同一个编译单元里,那么就给这个变量分配空间,确定变量的地址。假如变量或者函数不定义在这个编译单元里面,那就等到链接的时候才能确定地址。

汇编

clang -c main.s -o main.o

将main.s文件编译成main.o文件。(也就是我们常说的目标文件)

这个过程就是把上面得到的main.s文件里面的汇编指令翻译成机器指令,最终生成等到main.o。

链接

clang main.o -o main

这个过程就是将main.o编译成对应的Mach-O文件,也就是我们常说的可执行文件。链接的本质就是把一个或多个目标文件和需要的库(静态库/动态库,如果需要的话)组合成一个文件(Mach-O可执行文件)。

动静态库

什么是静态库和动态库?

  • 库是已经编译完成的二进制文件。
  • 代码需要提供给外部使用又不想代码被更改,就可以把代码封装成库,只暴露头文件以供调用。
  • 希望提高编译速度,可以把部分代码封装成库,编译时只需要链接。
  • 库都是需要链接的,链接库的方式有静态和动态,所以就产生了静态库和动态库。

静态库

静态库是静态链接库;是多个目标文件经过压缩打包后形成的文件包。这些目标文件在编译时被链接到应用程序中。静态库通常以 .a(Unix、Linux)或 .lib(Windows)以及MacOS 独有的 .framework为扩展名。

在编译阶段,静态库的代码被直接链接到生成的可执行文件中。这个过程将库的代码和应用程序的代码合并成一个单一的可执行文件。

由于静态库的代码被嵌入到可执行文件中,生成的可执行文件在运行时不依赖于外部的库文件。这意味着可以在没有静态库的环境中运行该应用程序。

如果静态库被更新,需要重新编译和链接应用程序,以确保应用程序包含最新的库代码。

动态库

动态库是动态链接库,是实现共享函数库的一种方式。动态库在编译的时候不会被拷贝到目标程序中,目标程序只会存储下动态库的引用。
真正用到动态库内的函数时才会去查找 - 绑定 - 使用函数。
动态库的格式有:.framework、.dylib、.tbd……

动态库的代码在运行时被加载到内存中,应用程序通过链接器解析符号,并在需要时调用库中的代码。

多个应用程序可以共享同一个动态库的实例,减少内存占用。

动态库可以在应用程序启动时加载,也可以在运行过程中按需加载,提供更灵活的加载方式。

如何区分framework是静态库还是动态库

众所周知,framework其实是一种文件的打包方式,把头文件、二进制文件、资源文件封装在一起,方便管理和分发。所以动态库和静态库的文件格式都会有.framework。那么我们手头上有个framework,如何区分它的类型呢?
在这里插入图片描述

方法:命令行进入动态库文件,使用file命令查看输出内容可以看到区别。以静态库文件-MAMapKit.framework与动态库文件-AFNetworking.framework为例。

  1. 静态库文件-MAMapKit.framework
cd /Users/***/Desktop/Framework/MAMapKit.framework
file MAMapKit

输出

MAMapKit: Mach-O universal binary with 4 architectures: [arm_v7:current ar archive random library] [arm64]
MAMapKit (for architecture armv7):  current ar archive random library
MAMapKit (for architecture i386):   current ar archive random library
MAMapKit (for architecture x86_64): current ar archive random library
MAMapKit (for architecture arm64):  current ar archive random library

archive表明这是一个静态库

  1. 动态库文件-AFNetworking.framework
cd /Users/***/Desktop/Framework/AFNetworking.framework
file AFNetworking

输出

AFNetworking: Mach-O universal binary with 2 architectures: [arm_v7:Mach-O dynamically linked shared library arm_v7] [arm64:Mach-O 64-bit dynamically linked shared library arm64]
AFNetworking (for architecture armv7):  Mach-O dynamically linked shared library arm_v7
AFNetworking (for architecture arm64):  Mach-O 64-bit dynamically linked shared library arm64

dynamically linked shared library表明这是一个动态库

动态库和静态库的区别

静态库

  • 在编译时加载
  • 优点:代码装载和执行速度比动态库快。
  • 缺点:浪费内存和磁盘空间,模块更新困难。

动态库

  • 在运行时加载
  • 优点:体积比静态库小很多,更加节省内存。
  • 缺点:代码装载和执行速度比静态库慢。

注:
体积小于最小单位16k的静态库编译出来的动态库体积会等于16k。
换成动态库会导致⼀些速度变低,但是会通过延迟绑定(Lazy Binding)技术优化。

延迟绑定:首次使用的时候查找并记录方法的内存地址,后续调用就可以省略查找流程。

动态库和静态库链接到主程序以后放在什么位置?

在这里插入图片描述

静态库链接后的位置

  • 静态库中的可执行代码会被链接到可执行文件的代码段中,与主程序的代码一起存储在这个段中。
  • 静态库中的初始化数据会被链接到可执行文件的数据段中。
  • 静态库中的未初始化数据会被链接到 BSS 段中。

动态库链接后的位置

动态库的链接过程不同于静态库,它在编译时并不会被包含到可执行文件中,而是在运行时由操作系统的动态链接器加载。

当主程序运行时,动态链接器(如 macOS 上的 dyld,Linux 上的 ld.so,Windows 上的 LoadLibrary)会将动态库加载到一个随机的内存地址(使用地址空间布局随机化,ASLR),以提高安全性。

dyld动态链接器

dyld(the dynamic link editor)是苹果的动态链接器,是苹果操作系统一个重要组成部分,在系统内核 XNU 完成 Mach-O 文件的加载,做好程序准备工作之后,交由 dyld 负责余下的工作。在 macOS 系统中,dyld 位于 D/usr/lib/dyld。

dyld2

  • dyld 2具有对 C++ 初始化程序语义的正确支持,扩展了 Mach-O 格式,并更新了 dyld ,以便有效支持的 C++ 库。
  • dyld 2 具有完整的 dlopen 和 dlsym 实现,此时弃用了旧版 API。

支持更多的架构及平台

  • 自从Power PC上 发布 dyld 2.0 以来,添加了 x86,x86 64 arm,arm64 等架构,支持了 iOS, tvOS, 和 watchOS 平台

通过多种方式提高了安全性

  • Codesigning : 代码签名
  • ASLR :Address space layout randomization 地址空间配置随机加载
  • bounds checking:对 Mach-O Header 中的许多内容添加了重要的边界检查功能,从而可以避免恶意二进制数据的注入

提升性能

  • 使用 shared cache 技术完全替代了预绑定 prebinding;

执行流程:

在这里插入图片描述

  1. dyld 的初始化,主要代码在 dyldbootstrap::start,接着执行 dyld::_main ,dyld::_main 代码较多,是 dyld 加载的核心部分;
  2. 检查并准备环境,比如获取二进制路径,检查环境变量,解析主二进制的 image header 等信息;
  3. 实例化主二进制的 image loader ,校验主二进制和 dyld 的版本是否匹配;
  4. 检查 shared cache 是否已经 map ,没有的话则先执行 map shared cache 操作;
  5. 检查 DYLD_INSERT_LIBRARIES,有的话则加载插入的动态库(实例化 image loader);
  6. 执行 link 操作。这个过程比较复杂,会先递归加载依赖的所有动态库(会对依赖库进行排序,被依赖的总是在前面),同时在这阶段将执行符号绑定,以及rebase,binding 操作;
  7. 执行初始化方法。Objective-C 的 +load 以及 C 的 constructor方法都会在这个阶段执行;
  8. 读取 Mach-O 的 LC_MAIN段 获取程序的入口地址,调用 main 方法。

dyld3

dyld 3是全新的动态链接器,它完全改变了动态链接概念。dyld 3 完全兼容 dyld 2,API 接口是一样的,所以在大部分情况下,开发者不需要做额外的适配就能平滑过渡。

执行流程
在这里插入图片描述

dyld 3 包含这三个部分:

  • 进程外 Mach-O 分析器和编译器 (out-of-process mach-o parser)
    由于 dyld 2 存在的问题,dyld 3 中将采用提前写入把结果数据缓存成文件的方式构成一个 lauch closure(可以理解为缓存文件)

  • 进程内引擎 执行 launch closure 处理 (in-process engine)
    验证”lauch closures“是否正确,映射dylib,执行main函数。此时,它不再需要分析mach-o header和执行符号查找,节省了不少时间。

  • launch closure 缓存服务 (launch closure cache )
    系统程序的 lauch closure 直接内置在 shared cache 中,而对于第三方APP,将在APP安装或更新时生成,这样就能保证 launch closure 总是在 APP 打开之前准备好。

大多数程序启动会使用缓存,而不需要调用进程外 mach-o分析器或编译器;并且 launch closure 比 Mach-O 更简单,它们是内存映射文件,不需要用复杂的方法进行分析,我们可以简单地验证它们,其作用是为了提高速度

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1936895.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python—爬虫的初步了解

Python 爬虫(Web Scraping)是一种自动化从网站上提取数据的技术。Python 由于其简洁的语法、丰富的库和强大的社区支持,成为了实现网络爬虫的首选语言之一。下面是一些Python爬虫的基本概念和步骤: 1. 爬虫的基本概念 请求&…

JavaEE:Spring Web简单小项目实践三(留言板实现)

学习目的: 1、理解前后端交互过程 2、学习接口传参,数据返回以及页面展示 目录 1、准备工作 2、约定前后端交互接口 1、获取全部留言 2、发表新留言 3、实现服务器端代码 4、调整前端页面代码 5、运行测试 1、准备工作 创建SpringBoot项目&#x…

WebRTC音视频-环境搭建

目录 期望效果 1:虚拟机和系统安装 2:WebRTC客户端环境搭建 2.1:VScode安装 2.2:MobaXterm安装 3:WebRTC服务器环境搭建 3.1:安装openssh服务器 3.2:安装Node.js 3.3:coturn穿透和转发服务器 3.3.1&a…

构建高效Node.js中间层:探索请求合并转发的艺术

🎉 博客主页:【剑九 六千里-CSDN博客】 🎨 上一篇文章:【CSS盒模型:掌握网页布局的核心】 🎠 系列专栏:【面试题-八股系列】 💖 感谢大家点赞👍收藏⭐评论✍ 引言&#x…

阿里云 https证书部署

一.申请证书 二.查看状态 查看状态,已签发是完成了申请证书 三.部署 我在nginx服务器上部署 具体操作链接:阿里云文档 修改前 修改后 四.重启ngnix 五.验证是否成功 在浏览器输入域名查看

maven 私服搭建(tar+docker)

maven私服搭建 一、linux安装nexus1、工具下载 二、 docker 搭建nexus1、镜像下载创建目录2、运行nexus3、访问确认,修改默认密码,禁用匿名用户登录4、创建仓库5、创建hostd仓库6、创建Blob Stores7、创建docker私服1、创建proxy仓库2、创建hotsed本地仓…

Qt自定义下拉列表-可为选项设置标题、可禁用选项

在Qt中,ComboBox(组合框)是一种常用的用户界面控件,它提供了一个下拉列表,允许用户从预定义的选项中选择一个。在项目开发中,如果简单的QComboBox无法满足需求,可以通过自定义QComboBox来实现更复杂的功能。本文介绍一个自定义的下…

144. 字典序最小的 01 字符串(卡码网周赛第二十六期(23年阿里淘天笔试真题))

题目链接 144. 字典序最小的 01 字符串(卡码网周赛第二十六期(23年阿里淘天笔试真题)) 题目描述 小红有一个 01 字符串,她可以进行最多 k 次提作,每次操作可以交换相邻的两个字符,问可以得到的…

C++的STL简介

0.STL简介 C的STL(Standard Template Library,标准模板库)是C标准库的一部分,它提供了一套通用的类和函数模板,用于处理数据结构和算法。STL的主要组件包括: 容器分配器算法迭代器适配器仿函数 容器 容…

制造运营管理系统(MOM系统),企业实现先进制造的关键一步

随着全球制造业的快速发展,企业对于生产效率和成本控制的要求日益增高。在这个背景下,制造运营管理系统(MOM系统)成为了企业提升竞争力的关键工具。盘古信息作为业内领先的智能制造解决方案提供商,其MOM系统更是以其卓…

作为爬虫工程师,在封装API时如何做得更好

在数据驱动的时代,爬虫工程师的角色日益重要。他们不仅是数据的收集者,更是数据的桥梁构建者,通过编写高效、稳定的爬虫程序,将互联网上的海量信息转化为有价值的数据集。而在这一过程中,API(应用程序接口&…

最小二乘求待定位点的位置(三维环境)|MATLAB

前言 之前发过三点法求待测点位置的程序讲解,哪个是二维的,见:基于伪逆的三点法距离求位置,MATLAB源代码(MATLAB函数) 这里给出三维情况下的函数和测试代码。对于函数,输入已知锚点的位置、待…

唐山养老院哪家好---守护晚年幸福,用服务引领老年人高品质养老生活

随着社会的快速发展和人口老龄化趋势的加剧,老年人对养老机构的需求日益增长,选择养老机构作为养老方式已成为许多老年人的必然选择。随着年龄的增长,生理功能的退化和疾病风险的增加,使得老年人更加需要专业的医疗照护和日常生活…

无人机的发展前景大吗?

随着科技的飞速发展,无人机(Unmanned Aerial Vehicle, UAV)作为一种新兴的航空器,已逐渐从军事领域渗透到民用领域。无人机的应用广泛,包括但不限于航拍、物流配送、环境监测、农业植保、应急救援等多个领域。本文旨在…

神经网络之卷积神经网络

目录 一、卷积神经网络概述:1.卷积层:1.1卷积核与神经元:1.2卷积层作用:1.3多通道概念: 2.池化层:2.1池化层作用: 3.隐藏层与卷积层、池化层关系: 一、卷积神经网络概述:…

Nginx部署前端项目尝试 - windows版

前端还是要学一点服务器端的东西,才能更好的理解一些知识 1、项目打包 生成dist 2、下载nginx解压,start nginx 启动 浏览器输入 localhost 显示如下页面表示启动成功 3、配置nginx server {listen 8080;# ip 不要加http 前后不要加 /server_name…

LeetCode做题记录(第二天)169. 多数元素

题目:169. 多数元素 标签:数组 哈希表 分治 计数 排序 题目信息: 思路一: 在题目中出现了计数,那我们就可以直接考虑考虑使用哈希表 unordered_map 即遍历的时候记录每个数的出现次数,当出现次数大于n/…

无法启动此程序,因为计算机丢失api-ms-win-core-path-l1-1-0.dll的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

Qt实现仿微信在线聊天工具(服务器、客户端)V1_ 04

上一篇实现了客户端与服务器的通信,这一篇继续实现相关功能 本章内容 服务器与数据库的连接通信格式的规范登录信息的验证 1.数据库的建立 这里连接的是Mysql8.0数据库,如果想要简单点可以直接用sqlite3数据库,调用逻辑基本差不多,数据库语法也基本一致。 在服务器工程里…

puzzle(0611)《组合+图论》追捕问题

目录 一,追及问题 1,警察和小偷 2,旋转的4个硬币 3,抓狐狸 二,围堵问题 三,追及围堵 一,追及问题 1,警察和小偷 如下图,警察先走,警察和小偷轮流一人…