3.1 链接加载原理及elf文件格式

1、原理概述

为什么要研究链接和加载?写一个小的main函数用户态程序,或者是一个小的内核态驱动ko,都非常简单。但是这一切都是在gcc和linux内核的封装之上,你只是实现了别人提供的一个接口,至于程序怎样启动、怎样运行、怎样实现这些机制你都一无所知。接着你会对程序出现的一些异常情况束手无策,对内核代码中的一些用法不能理解,对makefile中的一些实现不知所云。所以这就是我们要研究链接和加载的目的:明白程序的映像文件是怎么组织的,程序启动是怎么实现的,相关的机制是怎么联系在一起的。“你应当了解真相,真相会使你自由”。

链接和加载(linker and loader): linker即链接器,它负责将多个.c编译生成的.o文件,链接成一个可执行文件或者是库文件;loader即加载器,它原本的功能很单一只是将可执行文件的段拷贝到编译确定的内存地址即可,但是有了动态链接库以后,部分的外部库引用符号在加载的时候才会得到解析,所以加载也要处理链接器的相同操作重定位。

这方面的资料乍一看起来非常晦涩难懂,其实根本的功能非常简单:链接和加载的最核心的内容就是重定位。链接器负责将多个.o文件链接重定位成一个大文件,而加载器再将这个大文件重定位到一个进程空间当中去。

在linux环境下,链接和加载的机制最终有一个载体来承担,这个载体就是elf文件。所以从研究elf文件格式入手,是理解链接和加载原理的好方法。

本文档描述的链接和加载主要针对用户程序而言,在操作系统的链接和加载和这里有些不同,因为如果你编译一个内核,在加载内核的时候又有谁来做动态加载呢?关于内核实现的不同以后再在专门文档中描述。

2、重定位原理

前面已经说过链接和加载的核心内容就是重定位,所以开篇先用通俗易懂的语言来阐明重定位的原理。

2.1、符号表(Symbol Table):

符号表就是一张字符符号和地址的对应表,例如使用“nm file“、”readelf -s file “等命令可以读出一个elf文件的符号表。符号表的作用就是一个助记符,用一个字符串来标示某些抽象的地址,它能标示的地址有代码地址和数据地址,代码地址包括函数名、跳转标号,数据地址包括全局变量。
符号表的组织如下图所示:

这里写图片描述

从以上描述中可以看出,符号表的作用就是将符号名称和地址进行绑定。而绑定的根本目的就是方便对符号的引用,在符号值发生改变的时候,不需要去手工改动源代码中对符号引用的地方,而这种改动是由链接程序在重新生成执行文件时自动完成的。

2.2、重定位表(Relocation):

有了符号表,就需要有人对符号表进行引用,在程序的执行过程中对全局变量的引用、跳转、调用函数,这些都涉及到相应的符号引用。符号和其引用是一对多的关系,一个符号可能被代码中多处引用。因为符号值改变的时候,也需要对所有引用符号的地方的代码进行修改,所以需要还有一张表来记录符号表的引用关系,这就是重定位表:

这里写图片描述

从上图可见,重定位表项用来记录链接和加载的过程中需要重新定位的位置,在各个段位置发生改变而引起符号地址改变时,根据重定位表来修改符号引用的值。

2.3、GOT表(Global Offset Table):

前面的符号表和重定位表已经满足编译和链接过程中的重定位需求。同样加载的过程中还需要重定位操作,需要将外部链接库中的函数和变量和本程序中的引用链接起来,但是由于加载过程中代码已经处于运行状态,使用链接过程中同样的重定位手段有些不合适。链接的重定位是通过重定位表直接修改代码来完成的,但是代码在运行过程中再去修改代码会带来很多问题和风险。
所以加载过程中的重定位,使用了一种改良的重定位手段:即通过两张间接访问表来屏蔽掉重定位带来的对代码的修改,访问外部数据使用GOT,访问外部程序使用PLT。这样可链接出位置无关代码PIC(Position Independent Code),需要重定位时只需要修改GOT和PLT的值,而不需要去改动可执行代码。

这里写图片描述

GOT表用来做数据重定位的原理如上图所示。

2.4、PLT表(Procedure Linkage Table):

从上一节可知,加载过程中的重定位为了避免对代码的修改,引入了GOT来屏蔽对数据的访问,同理对外部代码的访问也是可以用GOT来访问的。但是为了实现动态链接的特性,即使用的时候才链接,不使用时可以不用链接,对外部代码的访问引入了一个新的表项PLT。

这里写图片描述

3、elf文件

3.1、相关背景

Elf文件格式,是现有linux环境下最流行的可执行文件格式,在elf文件存储的信息之上,实现了相应的链接和加载特性。
Linux环境下可执行文件格式的发展历史是:a.out -> coff -> xcoff -> elf。
Windows环境下可执行文件格式的发展历史是:dos com/exe -> pe-coff。

3.2、elf文件格式

Linux环境下,三种类型的执行文件都可以使用elf格式来表示:可重定位文件(即编译生成但是未连接的文件)、动态库文件、可执行文件。

Elf文件提供了两种文件解析的视角,链接视角和动态加载视角。链接视角使用section的概念来解析文件,主要关注链接过程的使用;动态加载视角使用segment的概念来解析文件,主要关注加载和动态链接的实现。

这里写图片描述

整个文件的组织框图如上所示,ELF头描述了section header table和program header table的起始位置、表项大小和个数。根据section header table来寻址相应的section,根据program header table来寻址相应的segment,可以看到一般是一个segment包含多个section。

Elf文件的原理已经在上一章中阐述,elf的具体文件格式详细描述可以参考参考资料中的“Executable and Linking Format (ELF) Specification “。这里不再详细描述,只是记一些Specification上没有的概要和重点理解。

a. 加载视角的“PT_LOAD “类型segment:

  • 表明可加载到内存中的段,一般程序都包含两个此种类型的段.data、.text

b.加载视角的“PT_INTERP“类型segment:

  • 指定动态加载程序,即我们用 “ldd“命令看到的动态加载器

这里写图片描述

c. 加载视角的“PT_DYNAMIC “类型segment:

  • 相当于动态加载的一个入口段,指定了动态加载和链接需要的各种数据段的地址和类型。DT_NEEDED、DT_SONAME、DT_RPATH表项承载的是编译时指定的一些依赖库和搜索路径等等。

这里写图片描述

3.3、相关工具

Linux下可以操作elf文件的有以下工具:

a.readelf
“readelf –a file“读出elf文件的所有信息。

b.nm
“nm file“读出elf文件的符号表信息。

c.objdump
“objdump –d file“反汇编出elf文件中包含可执行代码的section,elf命令中功能最强大的一个。

d.objcopy
转换elf文件为bin或者其他格式的文件,编译内核的时候会使用到。

e.strip
去掉elf文件中符号表和调试信息,对elf文件进行减肥。

f.addr2line
将绝对地址,转换成调试信息中的源文件行号。

4、参考资料

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ELF (Executable and Linkable Format)是一种用于存储可执行文件、目标文件和共享库的文件格式。它是Linux系统上常用的二进制文件格式之一,也是其他类UNIX系统所采用的标准格式。 ELF文件格式由三个主要部分组成:头部、段表和节表。 头部包含了一些重要的信息,如文件类型、系统架构、入口地址等。它还包含了段表和节表的偏移地址和大小等信息,以便系统可以正确解析文件。 段表记录了程序的运行时需要的各种段的信息。一个段可以是代码段、数据段、动态链接信息段等。每个段都有自己的虚拟地址和大小等属性。段表中的每个条目描述了一个段的属性和位置,用于程序的加载和运行。 节表类似于段表,不过节表记录了程序的编译时需要的各种节的信息。一个节可以是代码节、数据节、符号表等。每个节都有自己的虚拟地址和大小等属性。与段表类似,节表中的每个条目描述了一个节的属性和位置,用于编译、链接和调试。 ELF文件格式的优点是它的灵活性和可扩展性。由于ELF文件规范定义了头部、段表和节表等结构,因此可以通过添加新的段或节来实现文件的自定义属性和功能。这使得ELF文件格式非常适合于Linux系统的动态链接加载机制。 总的来说,ELF文件格式是一种Linux系统中常用的二进制文件格式,它定义了文件的结构和属性,包括头部、段表和节表等部分。通过这个格式,可以实现文件的加载链接和调试等功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值