首页 > 其他分享 >静态链接

静态链接

时间:2024-02-08 21:11:05浏览次数:18  
标签:可执行文件 文件 符号 静态 编译器 地址 链接

编程代码无非是由函数和各种变量以及对这些变量的读、写所组成,而不管是变量还是函数,它们最终都要存储在内存里。为每个变量和函数正确地分配内存空间,记录它们的地址,并把这个地址复写回调用或引用它们的地方,这是一个十分重要且困难的任务。

我们在使用gcc时,往往执行一个命令后,就能得到可执行程序,所以你可能会误认为是编译器负责为变量分配内存地址,但是实际上,这个工作是由链接器来完成的。每个变量都有自己的明成,通常我们把这些名称叫作符号。简单来讲,链接器的作用就是为符号转换成地址,一般来说可以分为三种情况:

  1. 生成二进制可执行文件的过程中。这种情况称为静态链接。
  2. 在二进制文件被加载进内存时。这种情况是在二进制文件保留符号,在加载时再把符号解析成真实的内存地址,这种情况被称为动态链接。
  3. 在运行期间解析符号。这种情况会把符号的解析延迟到最后不得不做时才去做符号的解析,这也是动态链接的一种。

链接小例子

编译

gcc example.c -c -o example.o -fno-PIC -g
gcc external.c -c -o external.o -fno-PIC -g

-c: 告诉gcc不要进行链接,只要编译到.o就可以了。

-o: 指定输出文件名。

-fno-PIC: 告诉编译器不要生成PIC的代码。gcc4.8版本在编译过程中默认就是PIC模式。这个选项对于动态链接意义较大。静态链接不使用。

-g:打开调试信息,让我们分析过程中能够对源码有更完整的对应关系。

链接

将两个.o文件链接生成可执行文件,由目标文件生成可执行文件的过程就是链接。

gcc external.o example.o -o a.out -no-pie

-no-pie表示关闭pie模式。

gcc会默认打开pie模式,也就意味着系统loader对加载可执行文件时的起始地址,会随机加载。关闭pie后,在Linux64位的系统下,默认的加载起始地址是0x400000。

这样,就得到了可执行二进制文件a.out,以上内容就是编译和链接的全过程。

链接器的作用

程序员在开发代码的过程中,也是直接跟这些符号打交道的。如果想获取某个变量的值,就直接从变量符号里读取内容;如果想调用某个函数,也是直接下一个函数符号的调用语句。

但是,我们知道,CPU在执行程序代码的时候,并不理解符号的概念,它所理解的只有内存地址的概念。不管是读数据,调用函数还是读指令,对于CPU而言都是一个个的内存地址。因此,这里需要一个连接CPU与程序员之间的桥梁,把程序中的符号转换成CPU执行的内存地址。这个桥梁就是链接器,它负责将符号转换为地址。

链接器的第一个作用就是把多个中间文件合并成一个可执行文件。每个中间文件都有自己的代码段和数据段等多个section,在合并成一个可执行程序时,多个中间文件的代码段会被合并到可执行文件的代码段,它们数据段也会被合并为可执行文件的数据段。

但是链接器在合并多个目标文件的时候并不是简单地将各个section合并就可以了,它还需要考虑每个目标中的符号地址,这就引出了链接器的第二个任务:重定位。所谓重定位,就是当被调用者的地址变化了,要让调用者知道新的地址是什么。

两步链接

根据上面的分析,链接器的工作流程主要分两步:

第一步是,链接器需要对编译器生成的多个目标(.o)文件进行合并,一般采取的策略是相似段的合并,最终生成共享文件(.so)或者可执行文件。这个阶段中,链接器对输入的各个目标文件进行扫描,获取各个段的大小,并且同时会收集所有的符号定义以及引用信息,构建一个全局的符号表。当链接器构造好了最终的文件布局以及虚拟内存布局后,我们根据符号表,也就能确定了每个符号的虚拟地址了。

第二步是,链接器会对整个文件再进行第二遍扫描,这一阶段,会利用第一遍扫描得到的符号表信息,依次对文件中每个符号引用的地方进行地址替换。也就是对符号的解析以及重定位过程。

这就是链接器常用的两部链接(two-pass linking)的步骤。简单来讲就是进行两遍扫描:第一遍扫描完成文件合并、虚拟内存布局的分配以及符号信息收集;第二遍扫描则是完成了符号的重定位过程。

总结

我们说,从源文件生成二进制可执行文件,这一过程主要包含了编译和链接两个步骤。其中,编译的作用是生成性能优越的机器码。对于编译单元内部的静态函数,可以在编译时通过相对地址的办法,生成call指令,因为无论将来调用者和被调用者被安置到什么地方,它们之间的相对距离不会发生变化。

而其他类型的变量和函数在编译时,编译器并不知道它们的最终地址,所以只能使用占位符(比如0)来临时代替目标地址。

而链接器的任务是为所有变量和函数分配地址,并把被分配到的地址回写到调用处。链接器的过程主要分为两步,第一步是多文件合并,同时为符号分配地址,第二步则是将符号的地址回写到引用它的地方。其中,地址回写有一个专门的名字叫做重定位。重定位的过程依赖目标文件中的重定位表。

编译器和链接器的作用

编译器的作用主要是把源代码文件翻译成中间结构(例如LVM IR),然后对它进行优化,以优化程序性能。编译器的输出是汇编文件,汇编文件中仍然保留了符号。然后,汇编编辑器再将汇编文件翻译成中间文件。最后,链接器将中间文件合并起来,组成二进制可执行程序。这种合并不是简单地拼接,而是要为符号分配地址,然后再把地址回填到引用符号的地方,这个过程就是重定位。而重定位才是链接器最重要的任务。

内容来自极客时间

标签:可执行文件,文件,符号,静态,编译器,地址,链接
From: https://www.cnblogs.com/lixiaomeng/p/18012132

相关文章

  • 如何下载链接为blob类型的视频
    示例这里以央视网视频为例获取m3u8链接F12打开开发者工具,网络中搜索m3u8,有可能有多个,要区别出我们想要下载的那个注:有些网站不是m3u8格式,比如B站根据链接转为mp4并下载使用这个网站m3u8视频在线提取工具可以转换。参考关于VideoSrc带有blob:http的视频如何......
  • 在K8S中,什么是静态 Pod?
    在Kubernetes(K8s)中,静态Pod是由kubelet直接管理的特殊类型Pod。与通常通过KubernetesAPIServer创建和管理的Pod不同,静态Pod的定义文件直接放置在特定节点上的kubelet配置目录中,而非由APIServer创建和调度。特点:直接由kubelet管理:kubelet会定期检查其配置目录(默认为/etc/kub......
  • sonarqube静态代码扫描工具常见用法
    安装服务器端的sonarqube下载地址:https://www.cnblogs.com/cxygg/p/18008738客户端有很多种比如SonarScannerCLI,JenkinsextensionforSonarQube,SonarScannerforMaven,sonarlint等创建项目后获取tokenSonarScannerCLI的使用下载地址解压后修改配置文件......
  • 静态库和动态库
    一、库的定义库文件是计算机上的一类文件,可以简单的把库文件看成一种代码仓库,它提供给使用者一些可以直接拿来用的变量、函数或类。二、库的好处方便保密;便于部署和分发三、静态库和动态库的区别静态库在程序的链接阶段被复制到程序中;动态库在程序运行时被系统动态地加载到内......
  • 【转】【Centos】配置静态IP
    转自:https://blog.csdn.net/zhujing16/article/details/88677253如果已经安装了Centos里的GNOME桌面,可以不用命令行下操作#查看当前IP地址ipaddr在Centos里,无法使用ifconfig来查看IP#查看网卡ens33对应的配置文件名ls/etc/sysconfig/network-scripts......
  • c语言判断是文件还是文件夹,软链接,硬链接
    摘自:文心一言在C语言中,可以使用stat()函数来判断一个路径对应的是文件、文件夹或者其他类型。#include<stdio.h>#include<sys/types.h>#include<sys/stat.h>intmain(){charpath[]="/path/to/file_or_folder";//要判断的路径structstatfileInfo......
  • 安卓动态链接库文件体积优化探索实践
    背景介绍应用安装包的体积影响着用户下载量、安装时长、用户磁盘占用量等多个方面,据GooglePlay统计,应用体积每增加6MB,安装的转化率将下降1%。   安装包的体积受诸多方面影响,针对dex、资源文件、so文件都有不同的优化策略,在此不做一一展开,本文主要记录了在研发时针对动态......
  • Drvsetup.dll 是 Windows 操作系统中的一个动态链接库文件,用于设备驱动程序的安装和配
     Drvsetup.dll是Windows操作系统中的一个动态链接库文件,用于设备驱动程序的安装和配置过程中。该文件通常位于C:\Windows\System32文件夹下。Drvsetup.dll主要负责设备驱动程序的安装和配置过程中的一些核心功能,包括驱动程序的复制、注册、配置和卸载等。在设备驱动程序......
  • drvstore.dll 是 Windows 操作系统中的一个动态链接库文件
    drvstore.dll是Windows操作系统中的一个动态链接库文件,用于存储和管理设备驱动程序的信息。它通常位于系统目录(如C:\Windows\System32)下。drvstore.dll的主要作用是维护设备驱动程序的备份和安装信息,以便在需要时能够快速找到并加载正确的驱动程序。当用户连接新设备或更新设......
  • NTFS文件系统支持硬链接和符号链接,这两种链接机制都可以让不同的文件指向同一个物理位
    NTFS文件系统支持硬链接和符号链接,这两种链接机制都可以让不同的文件指向同一个物理位置,从而节省磁盘空间和提高文件系统的效率。虽然它们的用途相似,但是硬链接和符号链接有一些不同之处。硬链接:硬链接(HardLink)是指将多个文件名链接到同一个物理位置的一种机制。它可以让多个文......