• 第7章——链接


    • 链接是将各种代码和数据片段收集并组合成为一个单一文件的过程

    编译器驱动程序

    • GCC首先运行C预处理器将C的源程序main.c翻译成一个ASCII码的中间文件main.i;
    • 接下来运行C编译器CC1,它将main.i翻译成一个ASCII汇编语言文件main.s;
    • 然后运行汇编器AS,它将main.s翻译成一个可重定位目标文件main.o;
    • 最后运行链接器程序ld,将main.o和sum.o以及一些不要的系统目标文件组合起来,创建一个可执行目标文件prog

    静态链接

    • 为了构造可执行文件,链接器必须完成两个主要任务:
      • 符号解析:将每个符号引用正好和一个符号定义关联起来
      • 重定位:把每个符号定义与一个内存位置关联起来
    • 目标文件是字节块的集合

    目标文件

    • 可重定位目标文件:可以在编译时与其他可重定位目标文件合并起来,创建一个可执行目标文件
    • 可执行目标文件:可以被直接复制到内存并执行
    • 共享目标文件:一种特殊类型的可重定位目标文件,可以在加载或者运行时被动态地加载进内存并链接

    可重定位目标文件

    • 每个可重定位目标文件可分为三个部分:ELF header、Sections、Section header table(描述Section信息的表)
    • ELF(Executable and Linkable Format):可执行可链接格式
    • -常见的section:
      • .text存放已编译程序的机器代码
      • .data已初始化的全局和静态变量
      • .bss未初始化的全局和静态变量,以及初始化为0的变量
      • .rodata只读数据

    符号和符号表

    • 全局符号:由该模块定义并能被其他模块引用
    • 外部符号:由其他模块定义并被该模块引用
    • 局部符号:只被该模块定义和引用,带有static属性的函数和变量
    • COMMON符号:未初始化的全局变量;.bss:未初始化的静态变量,以及初始化为0的全局或静态变量

    符号解析

    • 解析符号引用是将每个引用与它输入的可重定位目标文件的符号表中的一个确定的符号定义关联起来
    • 强符号:函数和已初始化的全局变量
    • 弱符号:未初始化的全局变量
    • 所有的编译系统都提供一种机制,将所有相关的目标模块打包成为一个单独的文件,称为静态库
    • 静态库以存档(archive)的特殊文件格式存放在磁盘中
    • 静态库的解析过程:从左到右扫描可重定位目标文件和存档文件,在扫描过程中,维护一个可重定位目标文件的集合E,一个未解析的符号集合U,一个已定义的符号集合D。若扫描完U非空,链接器就会输出一个错误并终止;否则会合并和重定位E中的目标文件,构建输出的可执行文件

    重定位

    • 重定位将合并输入模块,并为每个符号分配运行时地址,由两步组成:
      • 重定位节和符号定义:将所有相同类型的节合并为同一类型的新的聚合节
      • 重定位节中的符号引用:修改代码节和数据节中对每个符号的引用,使得它们指向正确的运行时地址
    • 汇编器遇到对最终位置未知的目标引用,它就会生成一个重定位条目
    • 重定位PC相对引用:重定位一个使用一个32位PC相对地址的引用
    • 重定位绝对引用:重定位一个使用32位绝对地址的引用

    可执行目标文件

    • 可执行目标文件的格式类似于可重定位目标文件,.init节定义了一个小函数,_init,程序的初始化代码会调用它
    • ELF可执行文件中的各类信息可分为:只读内存段、读/写内存段、不加载到内存的符号表和调试信息

    加载可执行目标文件

    • 运行可执行文件时,shell通过调用某个驻留在存储器中称为加载器的操作系统代码来运行它,任何Linux程序都可以通过调用execve函数来调用加载器
    • 将程序复制到内存并运行的过程叫做加载

    动态链接共享库

    • 共享库是一个目标模块,在运行或加载时,可以加载到任意的内存地址,并和一个在内存中的程序链接起来。这个过程称为动态链接,是由一个叫做动态链接器的程序来执行的
    • 当创建可执行文件时,静态执行一些链接,然后在程序加载时,动态完成链接过程。动态链接的可执行文件中包含一个.interp节,这一节包含动态链接器的路径名,动态链接器通过执行重定位完成链接任务

    从应用程序中加载和链接共享库

    • 应用程序可能在它运行时要求动态链接器加载和链接某个共享库,而无需在编译时将那些库链接到应用中

    位置无关代码

    • 可以加载而无需重定位的代码称为位置无关代码

    库打桩机制

    • 库打桩技术允许截获对共享库函数的调用,取而代之执行自己的代码
  • 相关阅读:
    【2 操作系统的结构】
    uniapp 下拉刷新
    【Java八股文总结】之读写分离&分库分表
    外滩大会观察|重估蚂蚁!
    二叉平衡搜索树-AVL树
    RabbitMq安装和Springboot整合
    【IMX6ULL笔记】-- GDB安装和VSCode图形调试
    源码解读etcd heartbeat,election timeout之间的拉锯
    Linux读写文件
    《Pytorch新手入门》第二节-动手搭建神经网络
  • 原文地址:https://blog.csdn.net/qq_44867112/article/details/127754125