编译链接装载总结

一、编译和链接

我们编写的源代码最后要形成一个可执行文件,对apple来说就是一个ipa,最后提交给苹果审核,那么代码是怎么变成可执行文件的,一个源代码变为可执行文件会经过4个步骤 1、预编译 2、编译 3、汇编 4、链接

1、预编译阶段

OC代码优先会转成C++代码,举例以.c为例,预编译主要是处理宏、头文件、删除注释,最后会形成一个.i文件

2、编译阶段

编译主要是将.i文件编译成.o目标文件,该文件中的代码是汇编代码,编译阶段分为前端编译和后端编译,以IR代码会分界线,IR代码想成前属于前端编译,IR形成代码后的阶段属于后端编译

  • 经过词法分析,形成token,是将代码切成一个个的符号
less 复制代码
int a = b + 2
//会被分解成
  • 经过语法分析形成语法树,以3目条件等式,形成对应的语法树
  • 语义分析,主要是对一些类型的校验
  • IR的生成,经过一些优化后的代码,主要是对一些代码的合并等的一些优化
  • 目标代码的生成,前端生成的一些代码是与平台无关,编译后端是对代码添加一些与平台硬件相关的代码,最终的文件就是.s文件,是汇编代码

3、汇编

将汇编代码转为机器指令,形成的文件.o目标文件

4、链接

将不同的目标文件链接成一个可执行文件,为什么要进行链接,因为本模块会引用其他模块的符号,所以要链接以后才能形成一个可执行文件,总结就是模块拼接,在链接的过程,链接也是做了许多东西

  • 地址和空间分配,将相似段合并
  • 符号决议,即找到对应的符号,(1、包含多个符号时的决议,2、弱符号等 3、建立引用符号的地方和符号定义地方的链接映射)
  • 重定位,A模块引用B模块中的foo函数,A模块编译的时候,foo符合未找到就加到需要重定位表,并且地址是不对的,上面的符号决议已经确定了符号所在的模块,以及符合的地址,会通过查找重定位表找到对应的入口进行地址重定位

二、可执行文件中有什么内容

1、目标文件中在磁盘中是以什么形式存在的

代码中是以段的形式存在的,里面有文件头,段表,text代码段,data数据段,BSS段,字符串表段,符号表段,重定位表段、调试信息,其他自定义段

2、可执行文件在磁盘中是以什么形式存在的

是多个目标文件经过链接后形成的,头文件段、多个text段组合的text段,多个data段组成的data段,多个目标文件组成的全局符号表,字符串表段、重定位表段(这个也是比较重要的),调试信息段

  • 头文件段,里面有版本,平台等相关信息,段表位置(比较重要的),找到对应的段表,将数据镜像到虚拟内存中,程序入口地址
  • 重定位表,这个里面的主要是可执行文件依赖的动态库的符号,在静态编译阶段无法确定符号及重定位,所以记录到重定位表中

三、装载与动态链接

装载的本质,分为两个阶段

  • 初始阶段,只是创建虚拟空间,建立可执行文件到虚拟空间的映射,动态库也是一样只是建立映射
  • 运行时阶段,当程序(即某条指令)执行到某个虚拟地址时,会去访问对应的物理页,若不存在,会触发缺页中断
    • 可执行文件从磁盘读取到物理内存,是操作系统做的
    • 动态库从磁盘读到物理内存,是动态链接器做的

可执行文件只有被装载到内存中,才可以被CPU运行,整个装载过程简单来说就是将磁盘中的可执行文件读取到内存中的过程。这里要提到一个进程虚拟地址空间的概念,进程虚拟地址空间的大小与寻址地址线的位数有关系,比如32位的计算机,即可以寻找的地址大小0x00000000~0xFFFFFFFF-1,即虚拟地址空间大小为4GB,但是这4GB的虚拟空间不是都给用户使用,系统要占用一部分,只有部分会暴露给开发者,程序读取磁盘中的数据和指令到内存中是以页为单位(页为4KB大小)进行读取的,因为若是没有虚拟地址的话,直接用物理内存的话,因为内存是不连续的,并且地址是不隔离的,即A程序也可以访问某个地址空间,B也可以访问,不安全,解决的办法就是增加一层虚拟地址层,然后有一个方法可以映射到内存物理空间就可以了,所以要有进程虚拟地址空间。

装载的过程采用的是页映射机制,不会一次性将磁盘上所有数据都加载的内存中,是按照页为单位按需加载由页错误机制驱动动态加入到内存中,从操作系统角度看,加载一个程序只是创建一个进程(即创建虚拟空间)然后加载可执行文件到内存中,CPU执行响应的指令

最开始分为3个步骤

  • 创建虚拟地址空间
  • 读取可执行文件头,建立虚拟地址空间和可执行文件的映射,操作系统的映射是以权限为维度去映射的
    • 可读可执行的代码段
    • 可读可写的数据段
    • 只读的数据段
    • 还会映射创建虚拟的堆空间页
    • 虚拟栈空间页
    • 把上面有相同权限的section合并到一块儿叫segment,以segment为单位去映射
  • 将cpu的指令寄存器地址,设置成可执行文件的入口

上面的步骤进行了程序初始启动,后面将可执行文件装载到内存,也页错误的方式驱动,当执行到某块儿指令的时候,根据MMA去映射内存上的地址B,这时如果发现内存上的地址不存在,页中断去根据虚拟地址反推出对应的可执行文件的地址A,将地址A加载的内存B,有动态链接的步骤,

动态链接下的装载,为什么要有动态链接,因为我们的可执行文件中有一些代码依赖系统库的某些函数,如果将这些库都静态链接到可执行文件中,会造成浪费,会在可执行文件中两份,映射到虚拟地址控价两份,从虚拟空间加载到物理内存2份,造成严重的资源浪费,所以有一些库采用动态链接的形式,即可执行文件中A有依赖的动态库C的某些符号时,这时候将这些符号加到动态符号表中,地址暂时写为0x00不做重定位,这样可执行文件中不包含动态库C,可执行文件到虚拟空间的映射会将动态库映射到虚拟空间,可执行文件B也依赖动态库C的某些符号,这时候将这些符号添加到动态符号表中,地址暂时写为0x00不做重定位,这样可执行文件中不包含动态库C,可执行文件映射到虚拟空间的映射会有一份动态库C的映射,因为可执行文件中依赖的动态符号并没有链接到可执行文件中,所以没有重定向,所以需要再动态链接时去做重定向,以保证可执行文件中指令的正常访问,那么动态库如何装载和链接呢?

动态链接的步骤与实现

1、启动动态链接器本身(动态链接器自举)

动态链接器本身也是一个动态库,其他动态库的装载和链接是由动态链接器来完成的,那么他自身的装载和链接是谁来完成的,所以动态链接器本身有些特殊 1、动态链接器本身不依赖其他动态库,2 它本身所需的一些全局变量和静态变量的重定位由它自身完成。自举完成后动态链接器将可执行文件和动态链接器本身的一些符号合并到一个全局符号表中。这里有一个问题,动态链接器自身的装载是谁来加载的还没有说清楚,只说了动态链接器自身的链接说清楚了

2、动态库的装载

可执行文件中有一个段叫.dynamic,这个段中存储的是可执行文件所依赖的动态库,动态链接器将这些所依赖的动态库名字放入到一个装载集合中,然后动态链接器去这些动态库所在的磁盘文件中读取文件头将对应的代码段和数据段读到虚拟内存中, 如果动态库有依赖其他动态库,会是一个递归的遍历过程,会以广度优先的遍历方式将所有的动态库都加载完毕会

3、动态库与可执行文件的链接

当上面的动态库都加载完毕后,这时候动态链接器会遍历可执行文件和每个动态库的重定位表,进行对应的指令地址的重定位,重定位完成后,如果某些动态库有.init字段,那么动态链接器会执行对应的代码实现动态库中某些对象的初始化,完成了重定位和初始化后,动态链接器本身的工作完成了,将控制权交还给程序的入口地址开始执行

4、动态链接器本身是被谁装载的

操作系统会先读取可执行文件的文件头,里面存储着所有的段表信息、程序入口地址、动态链接器地址、以及目标基地址,

  • 段表信息,可以将所有的段一一映射到虚拟内存空间
  • Image Base 程序装载的目标地址,如果虚拟空间中该地址已经被占用则换一个地址,可执行文件需要做一遍Rebase
  • 程序入口地址,赋值给CPU寄存器程序运行的入口(ios中即main函数的地址)
  • 动态链接器地址,操作系统会去加载动态链接器这个动态库,后续将操作权限交给他,让他进行动态库的加载
相关推荐
名字不要太长 像我这样就好8 小时前
【iOS】源码阅读(二)——NSObject的alloc源码
开发语言·macos·ios·objective-c
I烟雨云渊T16 小时前
iOS实名认证模块的具体实现过程(swift)
ios·cocoa·swift
小鹿撞出了脑震荡18 小时前
汇编学习——iOS开发对arm64汇编的初步了解
汇编·学习·ios
小鹿撞出了脑震荡18 小时前
「OC」源码学习—— 消息发送、动态方法解析和消息转发
学习·ios·objective-c
恋猫de小郭1 天前
Flutter 合并 ‘dot-shorthands‘ 语法糖,Dart 开始支持交叉编译
android·flutter·ios
恋猫de小郭1 天前
React Native 前瞻式重大更新 Skia & WebGPU & ThreeJS,未来可期
android·javascript·flutter·react native·react.js·ios
美狐美颜sdk2 天前
什么是直播美颜SDK?跨平台安卓、iOS美颜SDK开发实战详解
ios·音视频·美颜sdk·直播美颜sdk
I烟雨云渊T2 天前
iOS瀑布流布局的实现(swift)
开发语言·ios·swift
鸿蒙布道师2 天前
鸿蒙NEXT开发动画案例3
android·ios·华为·harmonyos·鸿蒙系统·arkui·huawei
鸿蒙布道师2 天前
AI原生手机:三大技术阵营的终极对决与未来展望
android·人工智能·ios·华为·智能手机·ai-native·hauwei