ELF文件结构描述

合集下载

elf文件格式

elf文件格式

第1章文件格式1.1 Executable and Linking Format (ELF)1.1.1整体结构ELF对象格式用于目标文件(.o扩展名)和执行文件. 有些信息只出现在目标文件或执行文件中.ELF文件由下列部件构成. ELF header必须放在文件的开始;其他部件可以随便排放(ELF header给出了其他部件的偏移量).1.1.2ELF头[ELF Header]ELF头包含目标文件的一般信息;具有如下结构(from elf.h):#define EI_NIDENT 16typedef struct {unsigned char e_ident[EI_NIDENT];Elf32_Half e_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;Elf32_Half e_phentsize;Elf32_Half e_phnum;Elf32_Half e_shentsize;Elf32_Half e_shnum;Elf32_Half e_shstrndx;};ELF头域描述:1.1.3程序头[Program Header]程序头为一结构数组,每个元素描述执行文件的一个可载入段.元素结构如下(from elf.h):typedef struct {Elf32_Word p_type;Elf32_Off p_offset;Elf32_Addr p_vaddr;Elf32_Addr p_paddr;Elf32_Word p_filesz;Elf32_Word p_memsz;Elf32_Word p_flags;Elf32_Word p_align;} Elf32_Phdr;1.1.4Section HeadersELF文件中的每个section的都有激励[incitation]头; Section个数由ELF Header中的e_shnum域指明. Section headers结构如下(from elf.h):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;1.1.5Special Sections1.1.6重定位信息[Relocation Information]重定位信息section包含关于非确定引用[unresolved references]的信息.因为编译器[compilers]和汇编器[assemblers]不知道符号将分配的绝对内存地址,和别的文件的符号定义;所以对符号的每个引用都将创建一个重定位条目. 该条目指向地址(where the reference is being made), 和指向包含被引用符号的符号表. 连接器[linker]给所有符号分配地址之后, 将使用重定位信息添入正确的地址. 执行文件没有重定位section.例如: 汇编表示符号加上偏移:move.l var+16,d0偏移量存储在r_addend域,这样,符号真实地址加上该地址域将产生一个正确的引用.重定位条目有如下结构(from elf.h):typedef struct {Elf32_Addr r_offset;Elf32_Word r_info;Elf32_Sword r_addend;} Elf32_Rel;1.1.7符号表符号表section .symtab为一数组,数组元素包含关于被ELF文件引用的符号的信息.符号表条目有如下结构(from elf.h):typedef struct {ELF32_Word st_name;ELF32_Addr st_value;ELF32_Word st_size;unsigned char st_info;unsigned char st_other;Elf32_Half sth_shndx;} Elf32_Sym;1.1.8串表串表sections( .strtab和.shstrtab)包含符号表中符号名和section名.名都以null结束. 这些符号通过偏移指向[point into]串表. 串表的第一字节总是零, 其后所有串顺序存放.。

linux elf执行流程

linux elf执行流程

linux elf执行流程Linux ELF 执行流程ELF(Executable and Linkable Format)是Linux系统中可执行文件的一种格式。

在Linux下,当我们执行一个可执行文件时,操作系统会按照一定的流程解析和执行该文件。

本文将介绍Linux ELF 的执行流程。

1. ELF文件格式ELF文件由多个段(section)组成,每个段都有特定的作用。

常见的段包括.text段(包含程序的指令)、.data段(包含程序的全局变量和静态变量)、.bss段(包含未初始化的全局变量和静态变量)等。

2. 加载可执行文件当用户在终端输入可执行文件名并按下回车键时,操作系统会通过解析文件头判断该文件是否为有效的ELF文件。

如果是有效的ELF 文件,操作系统会为该进程分配一块内存空间,并将ELF文件中的各个段加载到相应的内存地址上。

3. 解析程序入口操作系统会根据ELF文件中的程序入口地址(Entry Point)来确定程序的入口点。

程序入口地址通常位于.text段的起始位置。

操作系统将程序计数器(PC)设置为程序入口地址,从而开始执行程序。

4. 执行程序指令程序从程序入口地址开始执行,按照顺序执行.text段中的指令。

每条指令都会被解码和执行,直到程序结束或者遇到跳转指令。

5. 解析跳转指令在程序执行过程中,可能会遇到跳转指令(如条件跳转、无条件跳转、函数调用等)。

当遇到跳转指令时,操作系统会根据指令中的目标地址重新设置程序计数器,从而改变程序的执行流程。

6. 处理函数调用当程序执行到函数调用指令时,操作系统会将函数的返回地址和参数等信息保存到栈中,并跳转到函数的入口地址执行。

函数执行完毕后,操作系统会从栈中恢复返回地址,继续执行函数调用指令后面的指令。

7. 处理系统调用程序中可能会包含系统调用指令,用于请求操作系统提供各种服务。

当遇到系统调用指令时,操作系统会切换到内核态,执行相应的系统调用处理程序,并返回结果给用户程序。

elf 结构解析

elf 结构解析

elf 结构解析一、ELF文件的基本结构1. ELF文件头(ELF Header):ELF文件的入口点,包含了文件的基本信息和描述,如魔数、文件类型、入口地址等。

2. 程序头表(Program Header Table):描述了ELF文件的各个段(Segment)的加载和运行时的属性,如可执行代码段、数据段、只读段等。

3. 节头表(Section Header Table):描述了ELF文件的各个节(Section)的属性和位置信息,如代码节、数据节、字符串节等。

4. 节区(Section):包含了ELF文件的各种数据和代码,如程序的实际指令、全局变量、局部变量等。

5. 字符串表(String Table):存储了ELF文件中使用的所有字符串,如符号表中的符号名、节名等。

6. 符号表(Symbol Table):记录了ELF文件中定义和引用的各个符号的信息,如函数、变量等。

7. 重定位表(Relocation Table):用于修正程序中的跳转地址,使得程序可以正确地链接和执行。

二、ELF文件加载和链接过程1. 加载:当操作系统执行一个ELF可执行文件时,将会执行加载过程。

操作系统会按照程序头表中的描述,将各个段加载到内存中的相应位置,建立虚拟地址和物理地址之间的映射关系。

2. 符号解析:在加载过程中,操作系统会解析符号表,建立符号名与符号地址之间的映射关系。

这样,在程序执行过程中,可以通过符号名来访问对应的函数或变量。

3. 重定位:由于不同的目标文件可能会引用其他目标文件中的符号,所以在加载过程中,操作系统会根据重定位表的信息,修正程序中的跳转地址,确保程序可以正确地链接和执行。

三、ELF文件的应用1. 可执行文件:ELF格式的可执行文件可以直接在操作系统中运行,例如Linux系统中的可执行文件就是以ELF格式存储的。

2. 共享库:ELF格式的共享库包含了一组可被多个可执行文件共享的代码和数据,可以在程序运行时动态加载和链接。

ELF文件格式

ELF文件格式

ELF文件格式•目标文件有三种类型:–可重定位文件(Relocatable File)包含适合于与其他目标文件链接来创建可执行文件或者共享目标文件的代码和数据。

–可执行文件(Executable File)包含适合于执行的一个程序,此文件规定了exec()如何创建一个程序的进程映像。

–共享目标文件(Shared Object File)包含可在两种上下文中链接的代码和数据。

首先链接编辑器可以将它和其它可重定位文件和共享目标文件一起处理,生成另外一个目标文件。

其次,动态链接器(Dynamic Linker)可能将它与某个可执行文件以及其它共享目标一起组合,创建进程映像。

•目标文件全部是程序的二进制表示,目的是直接在某种处理器上直接执行。

ELF格式文件目前是UNIX系统非常常见二进制文件格式,ELF文件格式主要3大部分,ELF 文件头,节区表,和节区。

对于可执行文件对应的是段表,段。

下面这3部分简单分布情况,上面这条横条可以看成ELF文件从头到尾。

对于ELF头,节区表,节区都对应分布在文件里面,通过偏移来表示其对应在文件的位置。

2、ELF头对应字段的意义简单用下图来说明,其他字段可以对应解析3、节区相关信息4、对于节区经常使用的两个信息字段sh_info,sh_link对应字段意义5、对于一个ELF目标文件,通常都会有以下几个节区,可以通readelf–S test.oSection Headers:[Nr]Name Type Addr Off Size ES Flg Lk Inf Al [0]NULL0000000000000000000000000[1].text PROGBITS0000000000003400001100AX004[2].data PROGBITS0000000000004800000000WA004[3].bss NOBITS0000000000004800000000WA004[4].comment PROGBITS0000000000004800002a00001[5].note.GNU-stack PROGBITS0000000000007200000000001[6].shstrtab STRTAB0000000000007200004500001[7].symtab SYMTAB0000000000022000008010874[8].strtab STRTAB000000000002a000000a00001符号表:对应于.symtab,它保存着目标文件中所有的符号信息字符串表:.strtab,保存字符窜信息。

ELF文件格式分析

ELF文件格式分析

ELF⽂件格式分析⼀般的 ELF ⽂件包括三个索引表:ELF header,Program header table,Section header table。

1)ELF header:在⽂件的开始,保存了路线图,描述了该⽂件的组织情况。

2)Program header table:告诉系统如何创建进程映像。

⽤来构造进程映像的⽬标⽂件必须具有程序头部表,可重定位⽂件不需要这个表。

3)Section header table :包含了描述⽂件节区的信息,每个节区在表中都有⼀项,每⼀项给出诸如节区名称、节区⼤⼩这类信息。

⽤于链接的⽬标⽂件必须包含节区头部表,其他⽬标⽂件可以有,也可以没有这个表。

⼀、分析ELF⽂件头vi /usr/include/elf.h查看elf头数据结构⽤readelf –h 1(可执⾏⽂件名)读取⼀个简单可执⾏⽂件的elf头可见elf头⼤⼩为52字节,⽤dump命令16进制读取前52个字节进⾏分析命令:hexdump –x 1 –n 52解析:第⼀⾏,对应e_ident[EI_NIDENT]。

⼩端法实际表⽰内容为7f454c46010101000000000000000000,前四个字节为elf固定开头7f454c46(0x45,0x4c,0x46是'e','l','f'对应的ascii编码),表⽰这是⼀个ELF对象。

接下来的⼀个字节01表⽰是⼀个32位对象,接下来的⼀个字节01表⽰是⼩端法表⽰,再接下来的⼀个字节01表⽰⽂件头版本。

剩下的默认都设置为0.第⼆⾏,e_type值为0x0002,表⽰是⼀个可执⾏⽂件。

e_machine值为0x0003,表⽰是intel80386处理器体系结构。

e_version值为0x00000001,表⽰是当前版本。

e_entry值为0x08048320,表⽰⼊⼝点。

e_phoff值为0x00000034,表⽰程序头表的偏移量为0x34即52个字节刚好是elf头⼤⼩。

ELF文件格式分析

ELF文件格式分析

ELF文件格式分析ELF(Executable and Linkable Format)是一种常见的可执行文件格式,用于在UNIX和类UNIX系统上存储和执行程序。

在本文中,我们将详细分析ELF文件格式的结构和各个部分的作用。

首先是标识部分,它占据ELF文件的最开始位置,有以下几个字段:1. Magic Number:ELF文件的前四个字节,用于识别文件类型。

对于32位系统,它的值是0x7F、'E'、'L'和'F';对于64位系统,它的值是0x7F、'E'、'L'和'F'以及0x022.类型:指定了ELF文件的类型,比如可执行文件、目标文件、共享库等等。

3.类型机器:指定了目标机器的体系结构,如x86、ARM等等。

4.版本:指定了ELF文件的版本号。

5.入口点:对于可执行文件,指定程序的入口点。

6.程序头表和节头表的偏移地址和大小。

接下来是文件头部分,它描述了ELF文件的整体结构和布局:1.类型:表示ELF文件的类型,如可重定位文件、可执行文件、共享目标文件等。

2.目标机器:标识目标机器的类型。

3.版本:指定了ELF文件的版本号。

4.入口点:指定程序的入口点。

5.程序头表偏移地址和节头表偏移地址。

6.程序头表项的大小、数量和节头表项的大小、数量。

7.字符串表索引,用于找到文件中的字符串。

最后是节头表部分,它包含了所有节(Section)的相关信息,比如代码段、数据段等等。

每个节头表项包含以下字段:1.节的名称:用于标识节的名称。

2.节的类型:描述节的属性,如代码段、数据段、符号表等。

3.节的标志:描述节的属性,如可写、可执行等。

4.节的虚拟地址:指定节在内存中的虚拟地址。

5.节的文件偏移地址:指定节在文件中的偏移地址。

6.节的大小:指定节的大小。

7.链接和信息:用于指定其他与节相关的信息。

通过分析ELF文件的结构,我们可以获得有关程序入口点、机器类型、节的信息等重要的元数据。

elf中的filesize

elf中的filesize

elf中的filesizeElf中的文件大小:探索文件大小与存储空间的关系在计算机领域中,文件大小是指文件占用的存储空间大小。

在Elf (可执行和可链接格式)文件中,文件大小是一个重要的指标,它决定了文件在系统中的存储需求和传输速度。

本文将探索Elf文件中的文件大小,并分析文件大小与存储空间的关系。

一、Elf文件的结构和组成Elf文件是一种常见的二进制文件格式,用于存储可执行程序、库文件和目标文件。

它由多个节(section)组成,每个节都有自己的类型和内容。

Elf文件的头部(header)包含了对文件结构的描述信息,如文件大小、节表的位置和偏移量等。

二、Elf文件大小的计算Elf文件的大小由多个因素决定,包括头部的大小、节的大小以及其他元数据的大小。

在计算文件大小时,需要考虑以下几个方面:1. 头部大小:Elf文件的头部包含了对文件的描述信息,如文件的魔数、版本号等。

头部的大小在不同的Elf文件中可能有所不同,但通常都是固定大小。

2. 节的大小:Elf文件中的每个节都有自己的大小。

不同类型的节可能包含不同的数据,如代码、数据、符号表等。

每个节的大小由其中包含的数据量决定。

3. 对齐方式:为了提高访问效率和存储利用率,Elf文件中的节通常按照一定的对齐方式进行存储。

对齐方式可以使节的大小增大,从而增加文件的大小。

4. 其他元数据:除了头部和节的数据外,Elf文件可能还包含其他元数据,如字符串表、重定位表等。

这些元数据也会增加文件的大小。

Elf文件的大小可以通过计算头部大小、节的大小和其他元数据的大小来得出。

三、文件大小与存储空间的关系文件大小与存储空间之间存在着紧密的关系。

文件大小决定了文件在存储介质中占用的空间大小,而存储空间则决定了系统可以存储的文件数量和传输文件的速度。

1. 存储介质的容量:存储介质的容量决定了系统可以存储的文件大小。

如果一个Elf文件的大小超过了存储介质的容量,那么该文件将无法存储在该介质中。

elf结构与编译运行

elf结构与编译运行

elf结构与编译运行Elf结构与编译运行一、引言Elf(Executable and Linkable Format)是一种可执行和可链接格式,广泛应用于Linux系统中的可执行文件、共享库和内核模块。

本文将着重介绍Elf结构以及与编译运行相关的内容。

二、Elf结构Elf结构由多个部分组成,包括文件头、程序头表、节区头表和节区数据。

下面将逐一介绍这些部分的作用和内容。

1. 文件头(File Header)文件头包含了一些描述整个Elf文件的基本信息,如文件类型、目标体系结构、入口地址等。

文件头的大小固定为52个字节,可以通过读取文件头来确定Elf文件的版本和目标体系结构。

2. 程序头表(Program Header Table)程序头表描述了如何创建一个进程映像,包括加载和运行程序所需的信息。

每个条目都描述了一个段(segment),段是进程映像的基本单位,用于存储代码、数据等信息。

程序头表的大小和数量可变,每个条目的大小为32个字节。

3. 节区头表(Section Header T able)节区头表包含了所有节区的描述信息,如名称、大小、类型等。

节区是Elf文件中的一个逻辑部分,用于存储不同类型的数据,如代码、数据、符号表等。

节区头表的大小和数量可变,每个条目的大小为40个字节。

4. 节区数据(Section Data)节区数据是Elf文件中实际存储的各个节区的数据内容。

每个节区的数据内容可以是代码、数据、符号表等。

三、编译运行过程编译运行是将源代码编译成可执行文件并执行的过程。

一般包括以下几个步骤:预处理、编译、汇编、链接和运行。

1. 预处理(Preprocessing)预处理是编译过程的第一步,主要进行宏展开、头文件包含等操作。

预处理器将源代码中的宏定义进行替换,并将头文件的内容插入到源代码中,生成预处理后的代码。

2. 编译(Compiling)编译是将预处理后的代码转换为汇编语言的过程。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

ELF文件结构描述3.4 ELF文件结构描述我们已经通过SimpleSection.o的结构大致了解了ELF文件的轮廓,接着就来看看ELF 文件的结构格式。

图3-4描述的是ELF目标文件的总体结构,我们省去了ELF一些繁琐的结构,把最重要的结构提取出来,形成了如图3-4所示的ELF文件基本结构图,随着我们讨论的展开,ELF文件结构会在这个基本结构之上慢慢变得复杂起来。

ELF目标文件格式的最前部是ELF文件头(ELF Header),它包含了描述整个文件的基本属性,比如ELF文件版本、目标机器型号、程序入口地址等。

紧接着是ELF文件各个段。

其中ELF文件中与段有关的重要结构就是段表(Section Header Table),该表描述了ELF文件包含的所有段的信息,比如每个段的段名、段的长度、在文件中的偏移、读写权限及段的其他属性。

接着将详细分析ELF文件头、段表等ELF关键的结构。

另外还会介绍一些ELF中辅助的结构,比如字符串表、符号表等,这些结构我们在本节只是简单介绍一下,到相关章节中再详细展开。

3.4.1 文件头我们可以用readelf命令来详细查看ELF文件,代码如清单3-2所示。

ELF文件头结构及相关常数被定义在“/usr/include/elf.h”里,因为ELF文件在各种平台下都通用,ELF文件有32位版本和64位版本。

它的文件头结构也有这两种版本,分别叫做“Elf32_Ehdr”和“Elf64_Ehdr”。

32位版本与64位版本的ELF文件的文件头内容是一样的,只不过有些成员的大小不一样。

为了对每个成员的大小做出明确的规定以便于在不同的编译环境下都拥有相同的字段长度,“elf.h”使用typedef定义了一套自己的变量体系,如表3-3所示。

我们这里以32位版本的文件头结构“Elf32_Ehdr”作为例子来描述,它的定义如下:让我们拿ELF文件头结构跟前面readelf输出的ELF文件头信息相比照,可以看到输出的信息与ELF文件头中的结构很多都一一对应。

有点例外的是“Elf32_Ehdr”中的e_ident 这个成员对应了readelf输出结果中的“Class”、“Data”、“Version”、“OS/ABI”和“ABI Version”这5个参数。

剩下的参数与“Elf32_Ehdr”中的成员都一一对应。

我们在表3-4中简单地列举一下,让大家有个初步的印象,详细的定义可以在ELF标准文档里面找到。

表3-4是ELF文件头中各个成员的含义与readelf输出结果的对照表。

这些字段的相关常量都定义在“elf.h”里面,我们在表3-5中会列举一些常见的常量,完整的常量定义请参考“elf.h”。

ELF魔数我们可以从前面readelf的输出看到,最前面的“Magic”的16个字节刚好对应“Elf32_Ehdr”的e_ident这个成员。

这16个字节被ELF标准规定用来标识ELF文件的平台属性,比如这个ELF字长(32位/64位)、字节序、ELF文件版本,如图3-5所示。

最开始的4个字节是所有ELF文件都必须相同的标识码,分别为0x7F、0x45、0x4c、0x46,第一个字节对应ASCII字符里面的DEL控制符,后面3个字节刚好是ELF这3个字母的ASCII码。

这4个字节又被称为ELF文件的魔数,几乎所有的可执行文件格式的最开始的几个字节都是魔数。

比如a.out格式最开始两个字节为 0x01、0x07;PE/COFF文件最开始两个个字节为0x4d、0x5a,即ASCII字符MZ。

这种魔数用来确认文件的类型,操作系统在加载可执行文件的时候会确认魔数是否正确,如果不正确会拒绝加载。

接下来的一个字节是用来标识ELF的文件类的,0x01表示是32位的,0x02表示是64位的;第6个字是字节序,规定该ELF文件是大端的还是小端的(见附录:字节序)。

第7个字节规定ELF文件的主版本号,一般是1,因为ELF标准自1.2版以后就再也没有更新了。

后面的9个字节ELF标准没有定义,一般填0,有些平台会使用这9个字节作为扩展标志。

各种魔数的由来a.out格式的魔数为0x01、0x07,为什么会规定这个魔数呢?UNIX早年是在PDP小型机上诞生的,当时的系统在加载一个可执行文件后直接从文件的第一个字节开始执行,人们一般在文件的最开始放置一条跳转(jump)指令,这条指令负责跳过接下来的7个机器字的文件头到可执行文件的真正入口。

而0x01 0x07这两个字节刚好是当时PDP-11的机器的跳转7个机器字的指令。

为了跟以前的系统保持兼容性,这条跳转指令被当作魔数一直被保留到了几十年后的今天。

计算机系统中有很多怪异的设计背后有着很有趣的历史和传统,了解它们的由来可以让我们了解到很多很有意思的事情。

这让我想起了经济学里面所谓的“路径依赖”,其中一个很有意思的叫“马屁股决定航天飞机”的故事在网上流传很广泛,有兴趣的话你可以在google以“马屁股”和“航天飞机”作为关键字搜索一下。

ELF文件标准历史20世纪90年代,一些厂商联合成立了一个委员会,起草并发布了一个ELF文件格式标准供公开使用,并且希望所有人能够遵循这项标准并且从中获益。

1993年,委员会发布了ELF文件标准。

当时参与该委员会的有来自于编译器的厂商,如Watcom和Borland;来自CPU 的厂商如IBM和Intel;来自操作系统的厂商如IBM和Microsoft。

1995年,委员会发布了ELF 1.2标准,自此委员会完成了自己的使命,不久就解散了。

所以ELF文件格式标准的最新版本为1.2。

文件类型 e_type成员表示ELF文件类型,即前面提到过的3种ELF文件类型,每个文件类型对应一个常量。

系统通过这个常量来判断ELF的真正文件类型,而不是通过文件的扩展名。

相关常量以“ET_”开头,如表3-5所示。

常量值含义机器类型 ELF文件格式被设计成可以在多个平台下使用。

这并不表示同一个ELF文件可以在不同的平台下使用(就像java的字节码文件那样),而是表示不同平台下的ELF文件都遵循同一套ELF标准。

e_machine成员就表示该ELF文件的平台属性,比如3表示该ELF 文件只能在Intel x86机器下使用,这也是我们最常见的情况。

相关的常量以“EM_”开头,如表3-6所示。

3.4.2 段表我们知道ELF文件中有很多各种各样的段,这个段表(Section Header Table)就是保存这些段的基本属性的结构。

段表是ELF文件中除了文件头以外最重要的结构,它描述了ELF 的各个段的信息,比如每个段的段名、段的长度、在文件中的偏移、读写权限及段的其他属性。

也就是说,ELF文件的段结构就是由段表决定的,编译器、链接器和装载器都是依靠段表来定位和访问各个段的属性的。

段表在ELF文件中的位置由ELF文件头的“e_shoff”成员决定,比如SimpleSection.o中,段表位于偏移0x118。

前文中我们使用了“objudmp -h”来查看ELF文件中包含的段,结果是SimpleSection 里面看到了总共有6个段,分别是“.code”、“.data”、“.bss”、“.rodata”、“.comment”和“.note.GNU-stack”。

实际上的情况却有所不同,“objdump -h”命令只是把ELF文件中关键的段显示了出来,而省略了其他的辅助性的段,比如:符号表、字符串表、段名字符串表、重定位表等。

我们可以使用readelf工具来查看ELF文件的段,它显示出来的结果才是真正的段表结构:readelf输出的结果就是ELF文件段表的内容,那么就让我们对照这个输出来看看段表的结构。

段表的结构比较简单,它是一个以“Elf32_Shdr”结构体为元素的数组。

数组元素的个数等于段的个数,每个“Elf32_Shdr”结构体对应一个段。

“Elf32_Shdr”又被称为段描述符(Section Descriptor)。

对于SimpleSection.o来说,段表就是有11个元素的数组。

ELF段表的这个数组的第一个元素是无效的段描述符,它的类型为“NULL”,除此之外每个段描述符都对应一个段。

也就是说SimpleSection.o共有10个有效的段。

数组的存放方式ELF文件里面很多地方采用了这种与段表类似的数组方式保存。

一般定义一个固定长度的结构,然后依次存放。

这样我们就可以使用下标来引用某个结构。

Elf32_Shdr被定义在“/usr/include/elf.h”,代码如清单3-3所示。

Elf32_Shdr的各个成员的含义如表3-7所示。

注1:事实上段的名字对于编译器、链接器来说是有意义的,但是对于操作系统来说并没有实质的意义,对于操作系统来说,一个段该如何处理取决于它的属性和权限,即由段的类型和段的标志位这两个成员决定。

注2:关于这些字段,涉及一些映像文件的加载的概念,我们将在本书的第2部分详细介绍其相关内容,读者也可以先阅读第2部分的最前面一章“可执行文件的装载与进程”,了解一下加载的概念,然后再来阅读关于段的虚拟大小和虚拟地址的内容。

当然,如果读者对映像文件加载过程比较熟悉,应该很容易理解这些内容。

让我们对照Elf32_Shdr和“readelf -S”的输出结果,可以很明显看到,结构体的每一个成员对应于输出结果中从第二列“Name”开始的每一列。

于是SimpleSection的段表的位置如图3-6所示。

到了这一步,我们才彻彻底底把SimpleSection的所有段的位置和长度给分析清楚了。

在图3-6中,SectionTable长度为0x1b8,也就是440个字节,它包含了11个段描述符,每个段描述符为40个字节,这个长度刚好等于sizeof(Elf32_Shdr),符合段描述符的结构体长度;整个文件最后一个段“.rel.text”结束后,长度为0x450,即1104字节,即刚好是SimpleSection.o的文件长度。

中间Section Table和“.rel.text”都因为对齐的原因,与前面的段之间分别有一个字节和两个字节的间隔。

段的类型(sh_type) 正如前面所说的,段的名字只是在链接和编译过程中有意义,但它不能真正地表示段的类型。

我们也可以将一个数据段命名为“.text”,对于编译器和链接器来说,主要决定段的属性的是段的类型(sh_type)和段的标志位(sh_flags)。

段的类型相关常量以SHT_开头,列举如表3-8所示。

段的标志位(sh_flag) 段的标志位表示该段在进程虚拟地址空间中的属性,比如是否可写,是否可执行等。

相关常量以SHF_开头,如表3-9所示。

段的链接信息(sh_link、sh_info) 如果段的类型是与链接相关的(不论是动态链接或静态链接),比如重定位表、符号表等,那么sh_link和sh_info这两个成员所包含的意义如表3-11所示。

相关文档
最新文档