📄 elf.txt
字号:
ELF 鉴别(Identification)
在上面提到的,ELF提供了一个object文件的框架结构来支持多种处理机,多
样的数据编码方式,多种机器类型。为了支持这个object文件家族,最初的几
个字节指定用来说明如何解释该文件,独立于处理器,与文件剩下的内容无关。
ELF头(也就是object文件)最初的几个字节与成员e_ident相一致。
+ 图 1-4: e_ident[] Identification Indexes
Name Value Purpose
==== ===== =======
EI_MAG0 0 File identification
EI_MAG1 1 File identification
EI_MAG2 2 File identification
EI_MAG3 3 File identification
EI_CLASS 4 File class
EI_DATA 5 Data encoding
EI_VERSION 6 File version
EI_PAD 7 Start of padding bytes
EI_NIDENT 16 Size of e_ident[]
通过索引访问字节,以下的变量被定义。
* EI_MAG0 to EI_MAG3
文件的前4个字符保存着一个魔术数(magic number),用来确定该文件是否
为ELF的目标文件。
Name Value Position
==== ===== ========
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],用来确定文件的类型或者说是能力。
Name Value Meaning
==== ===== =======
ELFCLASSNONE 0 Invalid class
ELFCLASS32 1 32-bit objects
ELFCLASS64 2 64-bit objects
文件格式被设计成在不同大小机器中可移植的,在小型机上的不用大型机上
的尺寸。类型ELFCLASS32支持虚拟地址空间最大可达4GB的机器;使用上面
定义过的基本类型。
类型ELFCLASS64为64位体系的机器保留。它的出现表明了object文件可能
改变,但是64位的格式还没有被定义。如果需要,其他类型将被定义,会
有不同的类型和不同大小的数据尺寸。
* EI_DATA
字节e_ident[EI_DATA]指定了在object文件中特定处理器数据的编码
方式。当前定义了以下编码方式。
Name Value Meaning
==== ===== =======
ELFDATANONE 0 Invalid data encoding
ELFDATA2LSB 1 See below
ELFDATA2MSB 2 See below
更多的关于编码的信息出现在下面。其他值保留,将被分配一个新的编码
方式,当然如果必要的话。
* EI_VERSION
字节e_ident[EI_VERSION]表明了ELF头的版本号。
现在这个变量的是一定要设为EV_CURRENT,作为上面e_version的解释。
* EI_PAD
该变量标识了在e_ident中开始的未使用的字节。那些字节保留并被设置为
0;程序把它们从object 文件中读出但应该忽略。假如当前未被使用的字节
有了新的定义,EI_PAD变量将来会被改变。
一个文件的数据编码指出了如何来解释一个基本的object文件。在上述的
描述中,类型ELFCLAS32文件使用占用1,2和4字节的目标文件。下面定义的
编码方式,用下面的图来描绘。数据出现在左上角。
ELFDATA2LSB编码指定了2的补数值。
最小有意义的字节占有最低的地址。
+ 图1-5: Data Encoding ELFDATA2LSB
0------+
0x0102 | 01 |
+------+
0------1------+
0x010204 | 02 | 01 |
+------+------+
0------1------2------3------+
0x01020304 | 04 | 03 | 02 | 01 |
+------+------+------+------+
ELFDATA2LSB编码指定了2的补数值。
最大有意义的字节占有最低的地址。
+ 图1-6: Data Encoding ELFDATA2MSB
0------+
0x0102 | 01 |
+------+
0------1------+
0x010204 | 01 | 02 |
+------+------+
0------1------2------3------+
0x01020304 | 01 | 02 | 03 | 04 |
+------+------+------+------+
机器信息
为了确定文件,32位Intel体系结构的需要以下的变量。
+ 图1-7: 32-bit Intel Architecture Identification, e_ident
Position Value
======== =====
e_ident[EI_CLASS] ELFCLASS32
e_ident[EI_DATA] ELFDATA2LSB
处理器确认ELF头里的e_machine成员,该成员必须为EM_386。
ELF报头里的e_flags成员保存了和文件相关的位标记。32位Intel体系上未
定义该标记;所以这个成员应该为0;
=========================== Sections ===========================
一个object文件的section header table可以让我们定位所有的sections。
section header table是个Elf32_Shdr结构的数组(下面描述)。一个section
报头表(section header table)索引是这个数组的下标。ELF header table
的e_shoff成员给出了section报头表的偏移量(从文件开始的计数)。e_shnum
告诉我们section报头表中包含了多少个入口;e_shentsize 给出了每个
入口的大小。
一些section报头表索引是保留的;那些特别的索引在一个object文件中
将没有与之对应sections。
+ 图1-8: Special Section Indexes
Name Value
==== =====
SHN_UNDEF 0
SHN_LORESERVE 0xff00
SHN_LOPROC 0xff00
SHN_HIPROC 0xff1f
SHN_ABS 0xfff1
SHN_COMMON 0xfff2
SHN_HIRESERVE 0xffff
* SHN_UNDEF
该值表明没有定义,缺少,不相关的或者其他涉及到的无意义的section。
例如,标号“defined”相对于section索引号SHN_UNDEF是一个没有被
定义的标号。
注意: 虽然索引0保留作为未定义的值,section报头表包含了一个索引0的
入口。因此,假如ELF报头说一个文件的section报头表中有6个section入口
的话,e_shnum的值应该是从0到5。最初的入口的内容以后在这个section中
被指定。
* SHN_LORESERVE
该值指定保留的索引范围的最小值。
* SHN_LOPROC through SHN_HIPROC
该值包含了特定处理器语意的保留范围。
* SHN_ABS
该变量是相对于相应参考的绝对地址。
例如,section号的标号是绝对地址,不被重定位影响。
* SHN_COMMON
该section的标号是一个公共(common)的标号,就象FORTRAN COMMON
或者不允许的C扩展变量。
* SHN_HIRESERVE
该值指定保留的索引范围的上限。系统保留的索引值是从SHN_LORESERVE
到SHN_HIRESERVE;该变量不涉及到section报头表(section header table)。
因此,section报头表不为保留的索引值包含入口。
sections包含了在一个object文件中的所有信息,除了ELF报头,程序报头
表(program header table),和section报头表(section header table)。
此外,object文件的sections满足几天条件:
* 每个在object文件中的section都有自己的一个section的报头来描述它。
section头可能存在但section可以不存在。
* 每个section在文件中都占有一个连续顺序的空间(但可能是空的)。
* 文件中的Sections不可能重复。文件中没有一个字节既在这个section中
又在另外的一个section中。
* object文件可以有"非活动的"空间。不同的报头和sections可以不覆盖到
object文件中的每个字节。"非活动"数据内容是未指定的。
一个section头有如下的结构。
+ 图1-9: Section Header
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;
* sh_name
该成员指定了这个section的名字。它的值是section报头字符表section的
索引。[看以下的“String Table”], 以NULL空字符结束。
* sh_type
该成员把sections按内容和意义分类。section的类型和他们的描述在下面。
* sh_flags
sections支持位的标记,用来描述多个属性。
Flag定义出现在下面。
* sh_addr
假如该section将出现在进程的内存映象空间里,该成员给出了一个该section
在内存中的位置。否则,该变量为0。
* sh_offset
该成员变量给出了该section的字节偏移量(从文件开始计数)。SHT_NOBITS
类型的section(下面讨论)在文件中不占空间,它的sh_offset成员定位在
文件中的概念上的位置。
* sh_size
该成员给你了section的字节大小。除非这个section的类型为SHT_NOBITS,
否则该section将在文件中将占有sh_size个字节。SHT_NOBITS类型的section
可能为非0的大小,但是不占文件空间。
* sh_link
该成员保存了一个section报头表的索引连接,它的解释依靠该section的
类型。以下一个表描述了这些值。
* sh_info
该成员保存着额外的信息,它的解释依靠该section的类型。以下一个表描
述了这些值。
* sh_addralign
一些sections有地址对齐的约束。例如,假如一个section保存着双字,系统
就必须确定整个section是否双字对齐。所以sh_addr的值以sh_addralign的值
作为模,那么一定为0。当然的,仅仅0和正的2的次方是允许的。值0和1意味
着该section没有对齐要求。
* sh_entsize
一些sections保存着一张固定大小入口的表,就象符号表。对于这样一个
section来说,该成员给出了每个入口的字节大小。如果该section没有
保存着一张固定大小入口的表,该成员就为0。
section头成员sh_type指出了section的语意。
+ 图1-10: Section Types, sh_type
Name Value
==== =====
SHT_NULL 0
SHT_PROGBITS 1
SHT_SYMTAB 2
SHT_STRTAB 3
SHT_RELA 4
SHT_HASH 5
SHT_DYNAMIC 6
SHT_NOTE 7
SHT_NOBITS 8
SHT_REL 9
SHT_SHLIB 10
SHT_DYNSYM 11
SHT_LOPROC 0x70000000
SHT_HIPROC 0x7fffffff
SHT_LOUSER 0x80000000
SHT_HIUSER 0xffffffff
* SHT_NULL
该值表明该section头是无效的;它没有相关的section。
该section的其他成员的值都是未定义的。
* SHT_PROGBITS
该section保存被程序定义了的一些信息,它的格式和意义取决于程序本身。
* SHT_SYMTAB and SHT_DYNSYM
那些sections保存着一个符号表(symbol table)。一般情况下,一个
object文件每个类型section仅有一个,但是,在将来,这个约束可能被放宽。
典型的是,SHT_SYMTAB为连接器提供标号,当然它也有可能被动态连接时使用。
作为一个完整的符号表,它可能包含了一些动态连接时不需要的标号。
因此,一个object文件可能也包含了一个SHT_DYNSYM的section,它保存着
一个动态连接时所需最小的标号集合来节省空间。
看下面符号表“Symbol Table”的细节。
* SHT_STRTAB
该section保存着一个字符串表。一个object文件可以包含多个字符串表的
section。看下面字符串表“String Table”的细节。
* SHT_RELA
该section保存着具有明确加数的重定位入口。就象object文件32位的
Elf32_Rela类型。一个object文件可能有多个重定位的sections。具体细节
看重定位``Relocation''部分。
* SHT_HASH
该标号保存着一个标号的哈希(hash)表。所有的参与动态连接的object
一定包含了一个标号哈希表(hash table)。当前的,一个object文件
可能只有一个哈希表。详细细节看第二部分的哈希表"Hash Table"。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -