程序编译与运行
文章平均质量分 86
程序的编译、链接与加载过程
Aspiresky
一步一步向前走!
展开
-
ELF文件格式(1):概述
概述ELF,全称Executable and Linking Format,旨在为不同操作环境下提供一组通用的ABI(二进制接口),也是现代Linux系统下可执行程序广泛使用的一种文件格式。ELF格式定义了可执行程序的静态文件格式,包括文件信息头、段及节等结构,并约定了程序在运行时,程序文件的内容是如何动态加载到内存中以及起始运行地址。了解ELF文件格式,可以帮助我们了解整个程序的生成和运行过程...原创 2020-03-22 18:14:35 · 698 阅读 · 0 评论 -
ELF文件格式(2):文件结构
概述ELF可执行文件定义了可执行程序的静态文件格式,包括文件信息头、段及节等结构,并约定了程序在运行时,程序文件的内容是如何动态加载到内存中以及起始运行地址。了解ELF文件格式,可以帮助我们了解整个程序的生成和运行过程。ELF文件布局ELF文件格式提供了两种视图,分别是链接视图和执行视图。链接视图是以节(section)为单位,执行视图是以段(segment)为单位。链接视图就是在程序链接时用到的视图,而执行视图则是在程序被装载运行时用到的视图。从表中可以看出,ELF文件格式包含ELF文件头、节(原创 2020-07-12 23:25:01 · 756 阅读 · 2 评论 -
ELF文件格式(3):符号管理
概述符号是程序对某些类型的数据或者代码的引用,典型的符号包括全局变量、函数名等。ELF文件会使用独立的符号表记录所有引用到的符号,这些符号会在程序链接以及运行时发挥作用。符号表ELF文件中使用的符号表对应的节名为.symtab。.symtab表保存了可执行文件中定义的全局变量和函数的符号信息,也包含了引用来外部文件的全局符号。使用readelf工具查看ELF文件符号表:Shell # re...原创 2020-03-22 18:15:20 · 784 阅读 · 0 评论 -
程序的编译流程
文章目录概述预处理编译汇编链接相关参考概述程序的基本编译过程可以分为四个阶段,依次为预处理、编译、汇编 以及链接,在每个阶段,编译器都会输出相应的中间文件,并作为下个阶段的输入继续处理,直至最终生成可执行文件。一个编译链接的基本过程如下图所示:在Linux平台下,最常用的编译工具就是GCC。通常情况下,只要使用如下指令,就可以完成一个简单Linux可执行程序的编译:gcc example...原创 2020-06-07 00:35:33 · 1459 阅读 · 0 评论 -
程序的静态链接(1):概述
概述编译器在完成汇编阶段之后,所有的代码源文件已经都翻译成了二进制的目标文件,但是目标文件相互之间仍然是独立的,很多依赖信息还没有解决,包括:对于每个目标文件,它可能会依赖其它目标文件或者库中的符号信息;对于每个目标文件,其在内存中的运行地址信息此时也是不确定的,因此还无法直接加载到程序中运行。这些问题将交由静态链接进行处理。静态链接过程静态链接核心的作用就是将编译生成的多个目标文件及其依赖的库进行链接,以生成最终的可执行文件。基本的静态链接基本实现过程示意如下:为了生成可执行文件,静态原创 2020-07-26 19:58:54 · 573 阅读 · 0 评论 -
程序的静态链接(2):空间与地址分配
概述空间与地址分配描述了链接器如何将多个输入的目标文件合并到一个文件中,同时根据对应的运行平台,为可执行文件中的指令和符号分配运行时地址。空间与地址分配现代链接器执行的合并策略比较简单,通过将所有相同类型的节合并到一起,例如将所有输入目标文件的.text节合并到输出文件的.text节中;然后,链接器根据运行平台中进程虚拟地址空间的划分规则,为所有输入目标文件中定义的节和符号分配运行时内存地址;完成之后,程序中的每条指令和符号都有唯一的运行时内存地址了。链接器的空间分配示意如下:在链接阶段,链接器会原创 2020-08-05 22:16:56 · 1285 阅读 · 3 评论 -
程序的静态链接(3):符号解析
概述在符号解析阶段,链接器根据所有输入的符号引用与定义信息,将程序中每个符号引用与链接过程中输入的可重定位目标文件中的符号表中的一个确定的符号关联起来。如果在链接过程中出现未定义的符号,那么链接过程中就会终止并且报错"undefined reference",这在我们日常开发中,并不少见:多重定义的全局符号解析对于局部符号以及未定义符号的解析,链接器的处理通常是很简单的,更复杂的情况是对全局符号的解析,尤其是当多个目标文件定义了相同的符号。为了能够正确处理这种多重定义的全局符号,编译器在编译时,会将原创 2020-07-26 19:57:47 · 374 阅读 · 0 评论 -
程序的静态链接(4):重定位
概述在完成地址分配和符号解析之后,程序中每个定义的符号都有了唯一的运行时内存地址,并且所有的符号引用都可以与某个确定的符号定义关联起来,然后链接器就可以进入重定位阶段了。在这个阶段中,链接器会读取所有可重定位目标文件中的重定位信息,然后调整代码段和数据段中对每个符号的引用,使它们指向正确的运行时内存地址。重定位表重定位信息描述了如何对对应的节区中的符号引用进行修改,ELF文件使用重定位表来存储重定位信息。对于可重定位文件中每个需要重定位的节区都有一个对应的重定位表(通常使用**.rel**作为前缀)。原创 2020-07-26 20:00:13 · 1083 阅读 · 0 评论 -
程序的静态链接(5):使用静态库
静态库概述静态库本质上就是一组目标文件的集合,在日常开发中,我们通常都需要依赖一些基础的库,用以实现基本的输入输出、字符串操作等功能,系统将包含这些功能的目标文件打包到单独的库文件中,程序编译时可以将这些目标文件静态链接进程序中使用。在Linux中,静态库以后缀为.a的特殊存档文件进行存储,通常可以在标准目录/lib/和/usr/lib中找到。静态库的创建准备测试程序:// add.cint add(const int a, const int b){ return (a + b);}原创 2020-07-08 22:50:26 · 404 阅读 · 0 评论 -
程序的动态链接(1):概述
概述在动态链接出现之前,可执行文件的生成都是使用静态链接的方式来生成。静态链接方式需要在程序运行前将所有的可重定位文件全部链接到一起,形成一个整体后才能加载到内存中运行,这种机制存在一些弊端:空间浪费:程序在使用静态库的时候需要将使用到的公用库函数的目标文件全部链接到程序中,这就导致不同程序会存在相同库文件的多个副本,造成空间浪费;模块更新困难:对于程序中任何参与链接的可重定位文件发生更新,整个程序都需要重新进行编译和发布。为了解决静态链接的问题,动态链接不再从一开始就将程序的所有模块静态链接在原创 2020-08-02 20:56:50 · 1202 阅读 · 0 评论 -
程序的动态链接(2):地址无关代码
概述动态库的一个主要目的就是允许多个正在运行的进程共享内存中的库代码,以节约内存资源。现代系统使用了一种称为地址无关代码(Position-Indepent Code, PIC)的技术来编译动态库,使用这种技术,可以将动态库加载到内存的任何位置而无需链接修改,所有进程都可以共享动态库中代码的单一副本。地址无关代码PIC的基本思想是将指令中那些需要进行重定位的部分剥离出来和数据部分放在一起,这样指令部分就可以保持不变,而数据部分在每个进程中都可以拥有一个副本。为了实现PIC,关键在于如何处理动态库中的各原创 2020-08-02 20:58:28 · 1473 阅读 · 0 评论 -
程序的动态链接(3):延迟绑定
概述动态链接将链接工作由编译时推迟到了运行时,在每次程序运行时,动态链接器都要寻找并加载依赖的动态库,然后进行符号查找和重定位工作,这导致动态链接的程序在加载时会带来一些额外的开销。为了提升程序的加载速度,编译系统使用了一种称为延迟绑定(Lazy Binding)的技术。延迟绑定实现使用延迟绑定是基于这样一个前提:在动态链接下,程序加载的模块中包含了大量的函数调用,因此动态链接器会耗费很多的时间用于解决模块之间的函数引用的符号查找以及重定位,而实际上只有很少的一部分符号会被立刻访问。延迟绑定通过将函数原创 2020-08-02 20:59:42 · 2072 阅读 · 1 评论 -
程序的动态链接(4):动态链接信息
操作系统在执行动态链接的可执行文件时,会首先加载动态链接器,然后由动态链接器根据保存在可执行文件中的动态链接信息,完成依赖动态库的加载、符号解析以及重定位等工作。动态链接器路径;动态链接导入导出的符号定义及引用;动态链接符号重定位描述。为了保存这些信息,ELF文件格式针对动态链接使用了一些的特殊的节。原创 2022-12-19 22:11:17 · 247 阅读 · 0 评论 -
程序的动态链接(5):使用动态库
Linux下动态库文件的命名规范是以lib开头,紧接着是动态库名,以.so为后缀名,即lib + 动态库名+.so。原创 2022-12-19 23:22:22 · 444 阅读 · 0 评论