ELF文件格式
来源:互联网 发布:linux怎么定时任务 编辑:程序博客网 时间:2024/04/28 04:32
ELF 是由USL(UNIX System Laboratories)作为ABI(Application Binary Interface) 的一部分发布的。ELF 为开发者提供了一整套能应用于多个操作系统的二进制接口定义,在软件移植时大大减少了需要重新编码和编译的地方。ELF 同时支持二进制文件的三种用途,并根据这三种用途分别定义了相应的ELF 文件类型:可重定位文件(relocatable files),可执行文件(executable files),共享目标文件(shared object files) 。
1. 可重定位文件包含了适合用来链接其他目标文件的代码和数据,从而创建出可执行或可共享的目标文件;
2. 可执行文件包含了用于执行的程序,该文件规定了exec如何创建一个程序的进程映像;
3. 共享目标文件包含了用来在两个上下文之间链接的代码和数据。首先,链接器ld将该文件和其他的可重组文件或可共享目标文件进行处理后,创建出新目标文件,其次,动态链接器将该新目标文件与可执行文件或共享对象组合,来共同创建一个进程映像。
在实际使用过程中,以上三类文件其实只用于两种目的:程序连接和程序执行。可重定位文件和共享目标文件用于程序连接,可执行文件用于程序执行。
- ELF文件格式
经过汇编器以及链接器创建成的目标文件,其实是在处理器上可直接执行的程序的二进制代表。本章主要叙述了ELF文件格式以及其如何用来构建程序,同时也叙述了目标文件的几个组成部分,集中在程序执行所必须的信息上。
目标文件参与程序的链接(创建一个程序)和程序的执行(运行一个程序)。目标文件格式提供了一个用并行的视角看待文件内容的有效方法,在目标文件的具体活动中,反映出文件不同的用途。
图2-1显示了一个目标文件的组织结构。
链接视图 执行视图
ELF头部
ELF头部
程序头部表(可选)
程序头部表
节区1
段1
···
节区n
段2
···
···
···
节区头部表
节区头部表(可选)
图2-1 目标文件格式
在两种视图中,ELF头部(ELF Header)都位于文件的开始部分,位置固定,保存了路线图(road map),描述了该文件的组织情况。
在链接视图中,程序头部表(program header table)为可选。从程序的执行来看文件格式,程序头部表告诉系统如何来创建一个进程的内存映象。被用来建立进程映象(执行一个程序)的文件必须要有一个程序头部表,可重定位文件不需要这个头部表。
节区(section)保存着目标文件的信息,从链接视图看,包括指令,数据,符号表和重定位信息等等。其中包含的特殊节区会在“2.3特殊节区”章节中详细叙述。从执行视图看,一个段通常包含几个节区,同样保存着指令,数据,符号表和重定位等信息。
节区头部表(section header table)包含了描述节区的信息。每个节区在这个表中有一个入口,该入口给出了节区的名字,大小等等信息。链接过程中的文件必须有一个节区头部表,而在执行视图中这个节区头部表为可选。
目标文件格式支持8位字节/32位体系结构。不过这种格式是可以扩展的,因此,目标文件以某些机器独立的格式来表达某些控制数据,使得能够以一种的公共的方式来识别和解释其内容。目标文件中的其它数据使用目标处理器的编码结构,而不管文件在何种机器上创建。
目标文件ELF中常用的数据类型如表2-1所示。
表2-1 ELF中常用数据格式
名称
大小
对齐
说明
Elf32_Addr
4
4
无符号程序地址
Elf32_Half
2
2
无符号中等整数
Elf32_Off
4
4
有符号文件偏移
Elf32_Sword
4
4
有符号大整数
Elf32_Word
4
4
无符号大整数
unsigned char
1
1
无符号小整数
所有目标文件格式定义的数据结构是自然大小(natural size)。如果需要,数据结构中明确的包含了确保4字节对齐的填充字段,来使结构大小是4的倍数。数据从文件的开始也有适当的对齐。例如,一个包含了Elf32_Addr成员的结构将会在文件内对齐到4字节的边界上。因为移植性的原因,ELF不使用位字段。
1.2.1 ELF头部
ELF头部位于文件的开始处,用于描述整个文件的组织情况和结构。
用于程序连接的文件中有节区和节区头部表,节区中包含指令、数据、符号表、重定位信息等,节区头部表是节区的描述信息,也是节区信息的集合。
用于程序执行的文件中有段和程序头部表,一个段通常包含一个或多个节区的内容,程序头部(program header) 即段头部( segment header) 是段的叙述信息,程序头部表是程序头部的集合。
ELF头部结构数据组成如表2-2所示。
表2-2 ELF头部结构组成
名称
值
说明
unsigned char
e_ident[EI_NIDENT]
魔数和相关信息
Elf32_Half
e_type
目标文件类型
Elf32_Half
e_machine
硬件体系
Elf32_Word
e_version
目标文件版本
Elf32_Addr
e_entry
程序进入点
Elf32_Off
e_phoff
程序头部偏移量
Elf32_Off
e_shoff
节头部偏移量
Elf32_Word
e_flags
处理器特定标志
Elf32_Half
e_ehsize
ELF头部长度
Elf32_Half
e_phentsize
程序头部中一个条目的长度
Elf32_Half
e_phnum
程序头部条目个数
Elf32_Half
e_shentsize
节头部中一个条目的长度
Elf32_Half
e_shnum
节头部条目个数
Elf32_Half
e_shstrndx
节头部字符表索引
1. e_ident
这个字段标示该文件为一个目标文件,提供了一个机器无关的数据,解释文件的内容。ELF头部e_ident[]标识索引结构成员如表2-3所示。
表 2-3 e_ident[]标识索引
名称
值
说明
EI_MAG0
0
文件识别
EI_MAG1
1
文件识别
EI_MAG2
2
文件识别
EI_MAG3
3
文件识别
EI_CLASS
4
文件类
EI_DATA
5
数据编码
EI_VERSION
6
文件版本
EI_PAD
7
补齐字节开始处
EI_NIDENT
16
e_ident[]大小
通过索引访问字节,以下的变量被定义。
• EI_MAG0 to EI_MAG3:文件的前4个字节保存着一个魔术数(magic number),用来确定该文件是否为ELF的目标文件。ELF文件类型取值如表2-4所示。
表2-4 EI_MAGO-EI_MAGO3数据格式
名称
值
说明
ELFMAG0
0x7f
e_ident[EI_MAG0]
ELFMAG1
'E'
e_ident[EI_MAG1]
ELFMAG2
'L'
e_ident[EI_MAG2]
ELFMAG3
'F'
e_ident[EI_MAG3]
• EI_CLASS:接下来的字节是e_ident[EI_CLASS],用来确定文件的类型,值的意思如表2-5所示。
表2-5 EI_CLASS数据格式
名称
值
说明
ELFCLASSNONE
0
非法类别
ELFCLASS32
1
32位目标
ELFCLASS64
2
64位目标
文件格式被设计成在不同大小机器中可移植的。类型ELFCLASS32支持虚拟地址空间最大可达4GB的机器;类型ELFCLASS64为64位体系的机器保留。如果需要,其他类型将被定义,会有不同的类型和不同大小的数据尺寸。
• EI_DATA:字节e_ident[EI_DATA]指定了在目标文件中特定处理器数据的编码方式。EI_DATA数据组成如表2-6所示。
表2-6 EI_DATA数据组成
名称
值
说明
ELFDATANONE
0
无效的数据编码
ELFDATA2LSB
1
高位在前
ELFDATA2MSB
2
地位在前
ELFDATA2LSB编码如图2-2所示。低字节占用低地址空间。
图2-2 ELFDATA2LSB数据编码
ELFDATA2MSB编码如图2-3所示。高字节占用低地址空间。
图2-3 ELFDATA2MSB数据编码
• EI_VERSION:字节e_ident[EI_VERSION]表明了ELF头的版本号。现在这个变量的值设为EV_CURRENT,作为ELF头部e_version字段的解释。
• EI_PAD:该变量标识了在e_ident中开始的未使用的字节。那些字节保留并被设置为0;程序把它们从object 文件中读出但应该忽略。假如当前未被使用的字节有了新的定义,EI_PAD变量将来会被改变。
2. e_type
该成员确定该目标文件的类型,取值如表2-7所示
表2-7 e_type数据结构
名称
值
说明
ET_NONE
0
未知目标文件格式
ET_REL
1
可重定位文件
ET_EXEC
2
可执行文件
ET_DYN
3
共享目标文件
ET_CORE
4
Core文件(转储格式)
ET_LOPROC
0xff00
特定处理器文件
ET_HIPROC
0xffff
特定处理器文件
虽然CORE的文件内容未被指明,但类型ET_CORE是保留的。值从 ET_LOPROC 到 ET_HIPROC(包括ET_HIPROC)是为特殊的处理器保留的。如有需要,保留的变量将用在新的目标文件类型上。
3. e_machine
该成员变量指出了运行该程序需要的体系结构。e_machine数据结构如表2-8所示。
表2-8 e_machine数据结构
名称
值
说明
EM_NONE
0
未指定
EM_M32
1
AT&T WE 32100
EM_SPARC
2
SPARC
EM_386
3
Intel 80386
EM_68K
4
Motorola 68000
EM_88K
5
Motorola 88000
EM_860
7
Intel 80860
EM_MIPS
8
MIPS RS3000
注意:32位Intel体系结构内,ELF头部里的e_machine成员,其值必须为EM_386,e_ident[EI_CLASS]必须为ELFCLASS32,e_ident[EI_
DATA]必须为ELFDATA2LSB。
4. e_version
这个成员确定目标文件的版本。值1表示原来的文件格式,创建新版本就用>1的数。EV_CURRENT值(表中给出为1)如果需要将指向当前的版本号,目标文件版本信息如表2-9所示。
表2-9 目标文件版本信息
名称
值
含义
EV_NONE
0
非法版本
EV_CURRENT
1
当前版本
5. e_entry
该成员是系统第一个传输控制的虚拟地址,在该地址启动进程。假如文件没有如何关联的入口点,该成员就保持为0。
6. e_phoff
该成员保持着程序头部表在文件中的偏移量(以字节计数)。假如该文件没有程序头部表的的话,该成员就保持为0。
7. e_shoff
该成员保持着节区头部表在文件中的偏移量(以字节计数)。假如该文件没有节区头部表的的话,该成员就保持为0。
8. e_flags
该成员保存着相关文件的特定处理器标志。flag的名字来自于EF_<machine>_<flag>。
9. e_ehsize
该成员保存着ELF头部大小(以字节计数)。
10. e_phentsize
该成员保存着在文件的程序头部表中一个入口的大小(以字节计数)。所有的入口都是同样的大小。
11. e_phnum
该成员保存着在程序头部表中入口的个数。因此,e_phentsize和e_phnum的乘积就是表的字节数.假如没有程序头部表,e_phnum变量为0。
12. e_shentsize
该成员保存着节区头不的大小(以字节计数)。一个节区头部是在节区头部表的一个入口;所有的入口都是同样的大小。
13. e_shnum
该成员保存着在节区头部表中的入口数目。因此,e_shentsize和e_shnum的乘积就是节区头部表的大小(以字节计数)。假如文件没有section头表,e_shnum值为0。
14. e_shstrndx
该成员保存着跟字符表相关入口的节区头部表索引。假如文件中没有字符表,该变量值为SHN_UNDEF。
1.2.2 节区
ELF 头部中,e_shoff成员给出从文件头到节区头部表的偏移字节数;e_shnum给出了节区头部表中包含多少个入口;e_shentsize 给出了每个入口的大小。从这些信息中可以确切地定位节区的具体位置、长度。
节区头部表中比较特殊的几个下标如表2-10所示:
表2-10节区头部表格中的特殊下标
名称
取值
说明
SHN_UNDEF
0
标记未定义的,缺失的,不相关的的节区引用
SHN_LORESERVE
0xff00
保留索引的下界
SHN_LOPROC
0xff00
保留给处理器特殊的语义
SHN_HIPROC
0xff1f
保留给处理器特殊的语义
SHN_ABS
0xfff1
包含对应引用量的绝对取值,不会被重定位影响
SHN_COMMON
0xfff2
相对于此节区定义的符号是公共符号
SHN_HIRESERVE
0xffff
保留索引的上界
• SHN_UNDEF:该值表明没有定义,缺少,不相关的或者其他涉及到的无意义的节区。
注意: 虽然索引0保留作为未定义的值,节区头部表包含了一个索引0的入口。因此,假如ELF头部描述一个文件的节区头部表中有6个节区入口,e_shnum的值应该是从0到5。最初的入口的内容会在这个节区中被指定。
• SHN_LORESERVE:该值指定保留的索引范围的最小值。
• SHN_LOPROC 到 SHN_HIPROC:该值包含了特定处理器语意的保留范围。
• SHN_ABS:该变量是相对于相应参考的绝对地址。
• SHN_COMMON:该节区的标号是一个公共(common)的标号,就象FORTRAN COMMON或者不允许的扩展变量。
• SHN_HIRESERVE:该值指定保留的索引范围的上限。系统保留的索引值是从SHN_LORESERVE到SHN_HIRESERVE;该变量不涉及到节区头部表。因此,节区头部表不为保留的索引值包含入口。
目标文件的节区满足以下条件:
• 每个在目标文件中的节区都有自己的一个节区头部来叙述它。节区头可能存在但节区可以不存在。
• 每个节区在文件中都占有一个连续顺序的空间(但可能为空)。
• 文件中的节区不可能重复。文件中没有一个字节既在这个节区中又在另外的一个节区中。
• 目标文件可以有"非活动的"空间。不同的头部和节区可以不覆盖到目标文件中的每个字节。"非活动"数据内容是未指定的。
一个节区头部就是一个Elf32_Shdr结构的数组,数据组成如表2-11所示。
表2-11 节区头部数据组成
名称
值
说明
Elf32_Word
sh_name
给出节区名称
Elf32_Word
sh_type
为节区的内容和语义进行分类
Elf32_Word
sh_flags
节区支持1位形式的标志,这标志叙述多种属性
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
某些节区中包含固定大小的项目,如符号表
1. sh_name
该成员指定了这个节区的名字。它的值是字符表的索引。
2. sh_type
该成员把节区按内容和意义分类。节区的类型和他们的叙述如表2-12所示。
表2-12 节区类型sh_type各字段语义
名称
值
说明
SHT_NULL
0
此值标志节区头部是非活动的,没有对应的节区。
SHT_PROGBITS
1
包含程序定义的信息,其格式和含义都由程序来解释。
SHT_SYMTAB
2
包含一个符号表
SHT_STRTAB
3
包含字符串表。目标文件可能包含多个字符串表节区。
SHT_RELA
4
包含重定位表项,其中可能会有补齐内容(addend)
SHT_HASH
5
包含符号哈希表。
SHT_DYNAMIC
6
此节区包含动态链接的信息
SHT_NOTE
7
此节区包含以某种方式来标记文件的信息
SHT_NOBITS
8
不占用文件中的空间,其他方面和SHT_PROGBITS 相似。
SHT_REL
9
包含重定位表项,其中没有补齐(addends)
SHT_SHLIB
10
此节区被保留,不过其语义是未规定的
SHT_DYNSYM
11
作为完整的符号表,可能包含对动态链接不必要的符号
SHT_LOPROC
0x70000000
这一段(包括两个边界),
是保留给处理器专用语义的
SHT_HIPROC
0x7fffffff
SHT_LOUSER
0x80000000
此值给出保留给应用程序的索引下界
SHT_HIUSER
0xffffffff
此值给出保留给应用程序的索引上界
3. sh_flags
节区支持位的标记,用来叙述多个属性。一个节区头部表的sh_flags成员保存着1位标记,用来叙述节区的属性。sh_flags定义的值如表2-13所示,其他的值保留。
表2-13 节区头部的 sh_flags字段取值
名称
值
说明
SHF_WRITE
0x1
节区包含进程执行过程中将可写的数据
SHF_ALLOC
0x2
此节区在进程执行过程中占用内存
SHF_EXECINSTR
0x4
节区包含可执行的机器指令
SHF_MASKPROC
0xf0000000
包含于此掩码中的四位都用于处理器专用的语义
假如在sh_flags中的一个标记位被设置,该节区相应的属性也被打开。否则,该属性没有被应用。未明的属性就设为0。
4. sh_addr
假如该节区将出现在进程的内存映象空间里,该成员给出了一个该节区在内存中的位置。否则,该变量为0。
5. sh_offset
该成员变量给出了该节区的字节偏移量(从文件开始计数)。
6. sh_size
该成员给你了节区的字节大小。除非这个节区的类型为SHT_NOBITS,否则该节区将在文件中将占有sh_size个字节。SHT_NOBITS类型的节区可能为非0的大小,但是不占文件空间。
7. sh_link
该成员保存了一个节区头部表的索引连接,它的解释依靠该节区的类型。
8. sh_info
该成员保存着额外的信息,它的解释依靠该节区的类型。
在节区头部中,两个成员sh_link和sh_info的解释依靠该节区的类型,其意义如表2-14所示。
表2-14 sh_link和sh_info的字段解释
sh_type
sh_link
sh_info
SHT_DYNAMIC
此节区中条目所用到的字
符串表的索引
0
SHT_HASH
此哈希表所适用的符号表
的节区头部索引
0
SHT_REL
SHT_RELA
相关符号表的节区头部索
引
重定位所适用的节区的节区头
部索引
SHT_SYMTAB
SHT_DYNSYM
相关联的字符串表的节区
头部索引
最后一个局部符号(绑定 STB_
LOCAL)的符号表索引值加一
其他
SHN_UNDEF
0
9. sh_addralign
一些节区有地址对齐的约束。例如,假如一个节区保存着双字,系统就必须确定整个节区是否双字对齐。所以sh_addr的值以sh_addralign的值作为模,那么一定为0。
10. sh_entsize
一些节区保存着一张固定大小入口的表,就象符号表。对于这样一个节区来说,该成员给出了每个入口的字节大小。如果该节区没有保存着一张固定大小入口的表,该成员就为0。
值得说明的是索引为0 (SHN_UNDEF)的节区头部也是存在的,尽管此索引标记的是未定义的节区引用。这个入口保存着以下固定的信息,如表2-15所示。
表2-15 SHN_UNDEF(0)节区的内容
名称
值
说明
sh_name
0
名称
sh_type
SHT_NULL
非活动
sh_flags
0
标志
sh_addr
0
地址
sh_offset
0
文件偏移
sh_size
0
尺寸大小
sh_link
SHN_UNDEF
链接信息
sh_info
0
辅助信息
sh_addralign
0
对齐要求
sh_entsize
0
表项
特殊节区不同的节区保存着程序和控制信息。特殊节区被系统使用,指示了类型和属性。特殊节区的组成如表2-16所示。
表2-16 特殊的节区
名称
类型
属性
.bss
SHT_NOBITS
SHF_ALLOCSHF_WRITE
.comment
SHT_PROGBITS
none
.data
SHT_PROGBITS
SHF_ALLOCSHF_WRITE
.data1
SHT_PROGBITS
SHF_ALLOCSHF_WRITE
.debug
SHT_PROGBITS
none
.dynamic
SHT_DYNAMIC
see below
.dynstr
SHT_STRTAB
SHF_ALLOC
.dynsym
SHT_DYNSYM
SHF_ALLOC
.fini
SHT_PROGBITS
SHF_ALLOCSHF_EXECINSTR
.got
SHT_PROGBITS
see below
.hash
SHT_HASH
SHF_ALLOC
.init
SHT_PROGBITS
SHF_ALLOCSHF_EXECINSTR
.interp
SHT_PROGBITS
see below
.line
SHT_PROGBITS
none
.note
SHT_NOTE
none
.plt
SHT_PROGBITS
see below
.rel<name>
SHT_REL
see below
.rela<name>
SHT_RELA
see below
.rodata
SHT_PROGBITS
SHF_ALLOC
.rodata1
SHT_PROGBITS
SHF_ALLOC
.shstrtab
SHT_STRTAB
none
.strtab
SHT_STRTAB
see below
.symtab
SHT_SYMTAB
see below
.text
SHT_PROGBITS
SHF_ALLOCSHF_EXECINSTR
1 .bss
该节区保存着未初始化的数据,这些数据存在于程序内存映象中。通过定义,当程序开始运行,系统初始化那些数据为0。该节区不占文件空间,和它的节区类型SHT_NOBITS指示的一致。
2 .comment
该节区保存着版本控制信息。
3 .data and .data1
这些节区保存着初始化了的数据,那些数据存在于程序内存映象中。
4 .debug
该节区保存着调试的信息,内容是未指明的。
5 .dynamic
该节区保存着动态连接的信息。
6 .dynstr
该节区保存着动态连接时需要的字符串,一般情况下,名字字符串关联着符号表的入口。
7 .dynsym
该节区保存着动态符号表,如符号表的描述。
8 .fini
该节区保存着可执行指令,它构成了进程的终止代码。因此,当一个程序正常退出时,系统安排执行这个节区的中的代码。
9 .got
该节区保存着全局的偏移量表。
10 .hash
该节区保存着一个标号的哈希表。
11 .init
该节区保存着可执行指令,它构成了进程的初始化代码。因此,当一个程序开始运行时,在main函数被调用之前(c语言称为main),系统安排执行这个节区中的代码。
12 .interp
该节区保存了程序的解释程序(interpreter)的路径。
13 .line
该节区包含编辑字符的行数信息,它叙述源程序与机器代码之间的对应关系。
14 .note
该节区保存一些信息。
15 .plt
该节区保存着过程连接表(Procedure Linkage Table)。
16 .rel<name> and .rela<name>
这些节区保存着重定位的信息。按照惯例,<name>由重定位适用的节区来提供。因此,一个重定位的节区适用的是.text,那么该名字就为.rel.text或者是.rela.text。
17 .rodata and .rodata1
这些节区保存着只读数据,在进程映象中构造不可写的段。
18 .shstrtab
该节区保存着节区名称。
19 .strtab
该节区保存着字符串,一般地,叙述名字的字符串和一个标号的入口相关联。假如文件有一个可装载的段,并且该段包括了符号字符串表,那么节区的SHF_ALLOC属性将被设置;否则不设置。
20 .symtab
该节区保存着一个符号表,正如在这个节区里符号表的描述。
21 .text
该节区保存着程序的“text”或者说是可执行指令。
前缀是点(.)的节区名是系统保留的,尽管应用程序可以用那些保留的节区名。应用程序可以使用不带前缀的名字以避免和系统的节区冲突。
特殊节区主要包含了三个部分信息:字符串表,符号表和重定位。
1.3.1 字符串表
字符串表节区保存着以NULL终止的一系列字符,一般我们称为字符串。目标文件使用这些字符串来描绘符号和节区名。一个字符串的参考是一个字符串表节区的索引。第一个字节,即索引0,被定义保存着一个NULL字符。同样的,一个字符串表的最后一个字节保存着一个NULL字符,所有的字符串都是以NULL终止。索引0的字符串是没有名字或者说是NULL,它的解释依靠上下文。一个空的字符串是允许的;它的节区头的成员sh_size将为0。对空的字符串表来说,非0的索引是没有用的。
一个节区头的 sh_name 成员保存了一个对应于该节区头字符表部分的索引。表2-17列出了一个有 25 字节的字符串表(这些字符串和不同的索引相关联)。
表2-17 字符串表示例
索引
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
0
\0
n
a
m
e
.
\0
V
a
r
10
i
a
b
l
e
\0
a
b
l
e
20
\0
\0
x
x
\0
其中包含的字符串如表2-18所示:
表2-18 字符串表示索引
索引
字符串
0
(空)
1
"name."
7
"Variable"
11
"able"
16
"able"
24
(空字符串)
如上所示,一个字符串表可能涉及该节区中的任意字节。一个字符串可能引用不止一次;引用子串的情况是可能存在的;一个字符串也可能被引用若干次;而不被引用的字符串也是允许存在的。
1.3.2 符号表
一个目标文件的符号表保存了一个程序在定位和重定位时需要的定义和引用的信息。一个符号表入口的格式如图2-4所示。
typedef struct
{
Elf32_Word st_name;
Elf32_Addr st_value;
Elf32_Word st_size;
unsigned char st_info;
unsigned char st_other;
Elf32_Half st_shndx;
} Elf32_Sym;
图2-4 符号表入口格式
符号表入口对于不同的目标文件而言其st_value成员有一些不同的解释。
• 在可重定位文件中,st_value保存了节区索引为SHN_COMMON 符号的强制对齐值。
• 在可重定位文件中,st_value保存了一个符号的节区偏移。也就是说,st_value是从st_shndx定义的节区开头的偏移量。
• 在可执行的和共享的目标文件中,st_value保存了一个虚拟地址。为了使这些文件符号对于动态链接器更为有效,文件层面上的节区偏移让位于内存层面上的虚拟地址(节区编号的目的)。
尽管符号表值对于不同的目标文件有相似的含义,相应的程序还是可以有效地访问数据。
1.3.3 重定位
重定位是连接符号引用和符号定义的过程。比如,当一个程序调用一个函数的时候,相关的调用必须在执行时把控制传送到正确的目标地址。换句话说,重定位文件应当包含有如何修改他们的节区内容的信息,从而允许可执行文件或共享目标文件为一个进程的程序映像保存正确的信息。重定位入口的数据结构如图2-5所示。
typedef struct
{
Elf32_Addr r_offset;
Elf32_Word r_info;
} Elf32_Rel;
typedef struct
{
Elf32_Addr r_offset;
Elf32_Word r_info;
Elf32_Sword r_addend;
} Elf32_Rela;
图2-5 重定位入口
• r_offset:该成员给出了应用重定位行为的地址。对于一个重定位文件而言,该值是从该节区开始处到受到重定位影响的存储单位的字节偏移量。对一个可执行文件或一个共享目标而言,该值是受到重定位影响的存储单位的虚拟地址。
• r_info:该成员给出了具有受重定位影响因素的符号表索引和重定位应用的类型。比如,一个调用指令的重定位入口应当包含被调用函数的符号索引。如果该索引是 STN_UNDEF(未定义的符号索引),重定位将使用0作为该符号的值。重定位类型是和处理器相关的。当正文(text)引用到一个重定位入口的重定位类型或符号表索引,它表明相应的应ELF32_R_TYPE或 ELF32_R_SYM 于入口的 r_info 成员,如图2-6所示。
#define ELF32_R_SYM(i) ((i)>>8)
#define ELF32_R_TYPE(i) ((unsigned char)(i))
#define ELF32_R_INFO(s, t) ((s)<<8+(unsigned char)(t))
图2-6 r_info成员
• r_addend:该成员指定一个常量,用于计算将要存储于重定位域中的值。
只有 Elf32_Rela 入口包含一个明确的加数。Elf32_Rel 类型的入口在可以修改的地址中存储一个隐含的加数,依赖于处理器结构,因此,特定机器的应用应当使用一种排他性的形式或依赖于上下文的形式。
重定位入口中的成员 r_offset对于不同的目标文件有少许差异:
• 在可重定位文件中,r_offset 表示了一个节区偏移。也就是说,重定位节区自己叙述了如何修改其他在文件中的其他节区;重定位偏移量指明了一个在第二个节区中的存储器单元。
• 在可执行和共享的目标文件中,r_offset 表示一个虚拟地址。为了使得这些文件的重定位入口更为有用(对于动态链接器而言),该节区偏移(文件中)应当让位于一个虚拟地址(内存中的)。
重定位入口叙述了怎样变更指令和数据域(位数在表的两边角下),重定位区域指定一个以任意字节对齐方式占用 4 字节的 32 位域。这些值使用与32位 Intel体系相同的字节顺序。
计算假设正在将一个可重定位文件转换为一个可执行或共享目标文件。从概念上来说,链接器合并一个或多个可重定位文件来组成输出。它首先决定怎样合并、定位输入文件,然后更新符号值,最后进行重定位。对于可执行文件和共享的目标文件而言,重定位过程是相似的并且有相同的结果。
- elf文件格式
- elf文件格式
- elf文件格式
- ELF文件格式
- ELF 文件格式
- ELF文件格式
- elf文件格式
- ELF文件格式
- elf文件格式
- ELF文件格式
- ELF文件格式
- ELF文件格式
- elf文件格式
- elf文件格式
- ELF文件格式
- ELF文件格式
- ELF文件格式
- ELF文件格式
- Jquery系列-Jquery选择器
- 数通软件开发工程师(协议软件开发)
- 写给学生网的孩纸们看的~~
- Cocos2d 查看 pvr 图片的详细格式
- hdu 1848 - Fibonacci again and again(简单博弈)
- ELF文件格式
- Jquery系列-Jquery链式编程
- Automake入门实例
- 浙工ACM1310
- HDU--1754--I Hate It--线段树
- pvr 与 png 的内存占用
- java简易计算器
- 使用 C++ 和 MFC 进行多线程编程
- Jquery系列-Jquery模拟星级评分