节概述

在ELF文件中可以包含很多“节”(section),所有这些“节”都记录在一张称为“节头表”(section header table)的数组里。节头表的每一个表项是一个 Elf32_Shdr 结构,通过每一个表项可以定位到对应的节。

在 ELF 文件头中, e_shoff 成员给出节头表在 ELF 文件中相对于文件开始处的偏移量;e_shnum 成员指明节头表中包含多少个表项;e_shentsize 成员指明了每一个表项的大小。

节头表数组中,某些表项的索引值被保留,有特殊的含义。ELF 文件的节头表中不会出现索引值为以下各值的表项:

名字

SHN_UNDEF

SHN_LORESERVE

SHN_LOPROC

SHN_HIPROC

SHN_ABS

SHN_COMMON

SHN_HIRESERVE

 

0

0xff00

0xff00

0xff1f

0xfff1

0xfff2

0xffff

SHN_UNDEF

该值被定义为 0,它表示一个未定义的、不存在的节的索引。尽管索引值 0 是一个未定义的保留值,但在节头表中的索引还是会从 0 开始, 0 号表项的意义将在后面说明。

SHN_LORESERVE:被保留索引号区间的下限。

SHN_LOPROC:为特定处理器定制节所保留的索引号区间的下限。

SHN_HIPROC:为特定处理器定制节所保留的索引号区间的上限。

SHN_ABS:此节中所定义的符号有绝对的值,这个值不会因重定位而改变。

SHN_COMMON:此节中所定义的符号是公共的,比如 FORTRAN COMMON 符号或者未分配的 C 外部变量。

SHN_HIRESERVE:被保留索引号区间的上限。

除 0 以外,节头表中所有保留的索引值都位于 SHN_LORESERVE ~SHN_HIRESERVE 范围之间。与索引值”0”不同,这些大数值的索引并不出现在节头表中。

通常,目标文件中含有众多的“节”,“节”区是文件中最大的部分,它们需要满足下列这些条件:

  • ELf文件中的每一个节一定对应有一个节头,节头中有对节的描述信息;但有的节头可以没有对应的节,而只是一个空的头。
  • 每一个节所占用的空间是连续的。
  • 各个节之间不能互相重叠。
  • 在ELF文件中,节与节之间可能会存在一些多余的字节,这些字节不属于任何节。

节头的结构

可以用以下这个数据结构体来描述节头。

typedef struct { // 下面一些数据类型的大小在第二篇中有介绍Elf32_Word sh_name;Elf32_Word sh_type;Elf32_Word sh_flags;Elf32_Addr sh_addr;Elf32_Off sh_offset;Elf32_Word sh_size;Elf32_Word sh_link;Elf32_Word sh_info;Elf32_Word sh_addralign;Elf32_Word sh_entsize;
} Elf32_Shdr;

各个成员的含义如下:

h_name:本节的名字。名字并不存储在这里,它仅是一个索引号,指向“字符串表”节中的某个位置,那里存储了一个节名字符串。

sh_type: 本节的类型。下表给出了所有的节类型。

名字

解释说明

SHT_NULL

0

此值表明本节头是个无效的节头,它也没有对应的节。

SHT_PROGBITS

1

本节所含有的信息的格式和含义都由程序来决定。

SHT_SYMTAB

/SHT_DYNSYM

2/11

这两类节都含有符号表,只能各包含一个这两种节。SHT_SYMTAB 提供的符号用于在创建ELF文件的时候编辑连接,在运行期间也有可能会用于动态连接

SHT_STRTAB

3

本节是字符串表,ELF文件中可包含多个字符串表节

SHT_RELA

4

重定位节,一个ELF文件可能含有多个重定位节

SHT_HASH

5

本节包含一张哈希表,所有参与动态连接的ELF文件都必须要包含一个符号哈希表。目前,一个ELF文件中最多只能有一个哈希表

SHT_DYNAMIC

6

动态连接信息。一个ELF文件中最多只能有一个 。

SHT_NOTE

7

本节包含的信息用于以某种方式来标记本文件

SHT_NOBITS

8

这一节的内容是空的,节并不占用实际的空间。

SHT_REL

9

本节是一个重定位节

SHT_SHLIB

10

此值是一个保留值,暂未指定语义。

SHT_LOPROC~SHT_HIPROC

0x70000000~0x7fffffff

SHT_LOPROC~SHT_HIPROC区间是为特殊处理器节类型的保留值。

SHT_LOUSER~SHT_HIUSER

0x80000000~0xffffffff

SHT_LOUSER~SHT_HIUSER,由应用程序自定义区间类型,是一段保留值。

sh_flags :本节的一些属性,由一系列标志比特位组成,以下是这些标志位的列表及含义。

名字

SHF_WRITE

0x1

如果此标志被设置,表示本节所包含的内容在进程运行过程中是可写的。

SHF_ALLOC

0x2

如果此标志被设置,表示本节内容在进程运行过程中要占用内存单元。

SHF_EXECINSTR

0x4

如果此标志被设置,表示此节内容是指令代码。

SHF_MASHPROC

0xf0000000

所有被此值所覆盖的位都是保留做特殊处理器扩展用的。

sh_addr:如果本节的内容需要映射到进程空间中去,此成员指定映射的起始地址;如果不需要映射,此值为 0。

sh_offset:指明了本节第一个字节相对于文件开头的偏移量。单位是字节。如果该节的类型为 SHT_NOBITS 的话,表明这一节的内容是空的,节并不占用实际的空间,这时 sh_offset 只代表一个逻辑上的位置概念,并不代表实际的内容。

sh_size:指明节的大小,单位是字节。如果该节的类型为 SHT_NOBITS,此值仍然可能为非零,但没有实际的意义。

sh_link: 此成员是一个索引值,指向节头表中本节所对应的位置。根据节的类型不同,本成员的意义也有所不同,具体见下表。

sh_info: 此成员含有此节的附加信息,根据节的类型不同,本成员的意义也有所不同。

sh_type sh_link sh_info
SHT_DYNAMIC 本节中项目的字符串表在节头表中相应的索引值 0
SHT_HASH 本节中哈希表的符号表在节头表中相应的索引值 0
SHT_REL /SHT_RELA 相应符号表在节头表中的索引值 本重定位节所应用到目标节在节头表中的索引值
SHT_SYMTAB/SHT_DYNSYM 相关字符串表的节头索引 符号表中最后一个本地符号的索引值加 1
其它 SHN_UNDEF 0

sh_addralign

此成员指明本节内容如何对齐字节,即该节的地址应该向多少个字节对齐。也就是说,本节内容在进程空间中的映射地址 sh_addr 必须是一个向sh_addralign 对齐,即能被 sh_addralign 整除的值。目前,sh_addralign 只能取 0、1或者 2 的正整数倍。如果该值为 0 或 1,表明本节没有字节对齐约束。

sh_entsize

有一些节的内容是一张表,其中每一个表项的大小是固定的,比如符号表。对于这种表来说,本成员指定其每一个表项的大小。如果此值为 0 则表明本节内容不是这种表格。

索引值0节头项内容

下面说一下索引值为 0 的节头表项,它并不表达实际的内容,只是一个空的表项,内容见下表。

名字 意义 名字 意义
sh_name 0 无名字 sh_size 0 无大小
sh_type SHT_NULL 非活动类型 sh_link SHN_UNDEF 无节头表对应项
sh_flags 0 无标志 sh_info 0 无附加信息
sh_addr 0 无地址 sh_addralign 0 无对齐格式
sh_offset 0 无文件内偏移量 sh_entsize 0 无表项大小

特殊节

在 ELF 文件中有一些特定的节是预定义好的,其内容是指令代码或者控制信息,这些节专门为操作系统使用。在构建可执行程序时,连接器(linker)可能需要把一些独立的目标文件和库文件连接在一起,在这个过程中,连接器要解析各个文件中的相互引用,调整某些目标文件中的绝对引用,并重定位指令码。每种操作系统都有自己的一套连接模型,但总的来说,不外乎静态和动态两类:

静态连接 :所有的目标文件和动态连接库被静态地绑定在一起,所有的符号都被解析出来。所创建的目标文件是完整的,运行时不依赖于任何外部的库。

动态连接 :所有的目标文件、系统共享资源以及共享库以动态的形式连接在一起,外部库的内容没有完整地拷贝进来。如果创建的是可执行文件的话,程序在运行的时候,在构建时所依赖的那些库必须在系统中能找到,把它们一并装载之后,程序才能运行起来。运行期间如何解析那些动态连接进来的符号引用,不同的系统有各自不同的方式。

动态连接过程所需要的信息由.dynsym、.dynstr、.interp、.hash、.dynamic、.rel、.rela、.got、.plt 等节提供。.init 和.fini 节用于进程的初始化和终止过程。

名字

类型

属性

 

.bss

SHT_NOBITS

SHF_ALLOC+SHF_WRITE

包含未初始化的全局变量。可执行程序在开始运行的时候,系统会把这一段内容清零。但是,在运行期间的 bss 段是由系统初始化而成的,在ELF文件中.bss 节并不包含任何内容,其长度为 0,所以它的节类型为 SHT_NOBITS。

.comment

SHT_PROGBITS

本节包含版本控制信息。

.data

.data1

SHT_PROGBITS

SHF_ALLOC+SHF_WRITE

这两个节用于存放程序中被初始化过的全局变量。在ELF文件中,它们是占用实际的存储空间的,与.bss 节不同。

.debug

SHT_PROGBITS

调试信息,内容格式没有统一规定。

.dynamic

SHT_DYNAMIC

SHF_ALLOC+[SHF_WRITE] 本节包含动态连接信息

.dynstr

SHT_STRTAB

SHF_ALLOC

含有用于动态连接的字符串,一般是那些与符号表相关的名字

.dynsym

SHT_DYNSYM

SHF_ALLOC

此节含有动态连接符号表。

.fini

SHT_PROGBITS

SHF_ALLOC+SHF_EXECINSTR

此节包含进程终止时要执行的程序指令。当程序正常退出时,系统会执行这一节中的代码。

.got

SHT_PROGBITS

SHF_ALLOC+SHF_WRITE

此节包含全局偏移量表。

.hash

SHT_HASH

SHF_ALLOC

本节包含一张符号哈希表。

.init

SHT_PROGBITS

SHF_ALLOC+SHF_EXECINSTR

此节包含进程初始化时要执行的程序指令。当程序开始运行时,系统会在进入主函数之前执行这一节中的代码。

.interp

SHT_PROGBITS

[SHF_ALLOC]

此节含有 ELF 程序解析器的路径名。

.line

SHT_PROGBITS

本节也是一个用于调试的节,它包含那些调试符号的行号,为程序指令码与源文件的行号建立起联系。其内容格式没有统一规定。

.note

SHT_NOTE

注释节详细描述

.plt

SHT_PROGBITS

SHF_ALLOC+SHF_EXECINSTR

此节包含函数连接表。

.relname

.relaname

SHT_REL

/SHT_RELA

[SHF_ALLOC]

重定位信息。注意,这两个节的名字中”name”是可替换的部分,执照惯例,对哪一节做重定位就把”name”换成哪一节的名字。比如,.text 节的重定位节的名字将是.rel.text 或.rela.text。

.rodata

.rodata1

SHT_PROGBITS

SHF_ALLOC

本节包含程序中的只读数据,在程序装载时,它们一般会被装入进程空间中那些只读的段中去。

.shstrtab

SHT_STRTAB

本节是“节名字表”,含有所有其它节的名字。

.strtab

SHT_STRTAB

[SHF_ALLOC]

本节用于存放字符串,主要是那些符号表项的名字。

.symtab

SHT_SYMTAB

[SHF_ALLOC] 本节用于存放符号表。

.text

SHT_PROGBITS

SHF_ALLOC+SHF_EXECINSTR

本节包含程序指令代码。

以点号”.”为前缀的节名字是为系统保留的。应用程序也可以构造自己的段,但最好不要取与上述系统已定义的节相同的名字,也不要取以点号开头的名字,以避免潜在的冲突。注意,目标文件中节的名字并不具有唯一性,可以存在多个相同名字的节。

ELF文件系列第三篇ELF文件静态结构中的节相关推荐

  1. [深度][PyTorch] DDP系列第三篇:实战与技巧

    [深度][PyTorch] DDP系列第三篇:实战与技巧 转自:https://zhuanlan.zhihu.com/p/250471767 零. 概览 想要让你的PyTorch神经网络在多卡环境上跑 ...

  2. 深入理解javascript作用域系列第三篇

    前面的话 一般认为,javascript代码在执行时是由上到下一行一行执行的.但实际上这并不完全正确,主要是因为声明提升的存在.本文是深入理解javascript作用域系列第三篇--声明提升(hois ...

  3. C++之文件操作探究(三):写文件——二进制文件

    相关博文:C++之文件操作探究(一):写文件--文本文件 相关博文:C++之文件操作探究(二):读文件--文本文件 相关博文:C++之文件操作探究(三):写文件--二进制文件 相关博文:C++之文件操 ...

  4. javascript面向对象系列第三篇——实现继承的3种形式

    前面的话 学习如何创建对象是理解面向对象编程的第一步,第二步是理解继承.开宗明义,继承是指在原有对象的基础上,略作修改,得到一个新的对象.javascript主要包括类式继承.原型继承和拷贝继承这三种 ...

  5. ROS系列教程三:roslaunch文件及参数服务器

    一.标签简介 1.<launch> ... </launch> : 根标签,一般写在整个launch文件的头尾,斜杠/代表结束: 2.<node> :启动节点,如果 ...

  6. 初学Python——文件操作第三篇

    一.引言 什么?有了第二篇文件操作还不够?远远不够!而且在读完第三篇文件操作还是不够.关于文件的操作,后续的学习中将不断学习新的操作方式,使用更加合适的方法. 进入正题,上一篇讲到,Python对文件 ...

  7. Python之路【第三篇】:文件操作

    一.文件操作步骤 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 歌名:<大火> 演唱:李佳薇 作词:姚若龙 作曲:马奕强 歌词: 有座巨大的停了的时钟 倾倒在赶 ...

  8. UR机械臂+RG2机械手控制 学习及实际控制 系列第三篇-1

    1.机械臂UR的控制包括两种,一种是通过终端控制 比较笨重不方便,用于测试使用,另一种是通过ros例程包,订阅位置信息控制机械臂的移动,moveit自动规划机械臂的路径,并躲过设置好的盒子(box) ...

  9. 【Windows编程】系列第三篇:文本字符输出

    2019独角兽企业重金招聘Python工程师标准>>> 上一篇我们展示了如何使用Windows SDK创建基本控件,本篇来讨论如何输出文本字符. 在使用Win32编程时,我们常常要输 ...

最新文章

  1. Linux下多播的配置【十全十美】
  2. IntelliJ IDEA WEB项目的部署配置
  3. java poi 读取xlsx文件_使用POI读取xlsx文件(SXSSFWorkbook)
  4. 快速谱峭度matlab,一种基于快速谱峭度分析的泵潜在空化故障检测方法与流程
  5. 重磅!神策智能推荐获 2019 大数据“星河奖”
  6. 修改IIS7并发连接数目限制
  7. 【JDK源码】java.lang包常用类详解
  8. 数据库-null值处理及元数据
  9. RAC环境创建本地数据文件的解决方法
  10. 如何优雅的处理异常(java)
  11. (25)软件工程开发规范
  12. 自己动手写操作系统——开发环境搭建
  13. f1c100s 调试问题汇总
  14. Android 接入穿山甲SDK之激励视频广告
  15. CRC32绕过RAR密码
  16. GPU中实现反距离加权插值(IDW)
  17. jQuery学习之旅 Item1 选择器【一】
  18. Fortran简明自学手册
  19. Ubuntu14.04 64位+Python3.4环境下安装matplotlib的方法
  20. 耦合和解耦的概念解析!

热门文章

  1. zookeeper c api主备切换例子
  2. 计算广告(一)【Ad Click Prediction: a View from the Trenches】工程实践视角下的广告点击率预估
  3. 代码的好味道和坏味道之22种坏味道
  4. 一键清除maven仓库中下载失败的jar包
  5. java中substract,【vapor和evaporate都有蒸发的意思,那怎样区分它们
  6. ArcGIS教程:趋势分析
  7. 整理的5种真实的判断IE9浏览器方法
  8. acrobat pro dc 2015打开文件出现内容准备进度的解决方法
  9. 强化学习在人岗匹配系统中的应用
  10. 华为OceanStor全闪存技术论坛登陆上海滩:探寻智能时代闪存普惠