热门关键字:  ubuntu  分区  函数  Fedora  linux系统进程

当前位置 :| 主页>Linux教程>编程开发>

关于ELF文件格式的实验

来源: 作者: 时间:2007-05-19 Tag: 点击:
标 题: 关于ELF文件格式的实验
作 者: hangj
时 间: 2005-01-13,18:25
链 接: http://bbs.pediy.com/showthread.php?t=9793

现代Linux采用ELF做为其可连接和可执行文件的格式,因此ELF格式也向我们透出了一点Linux核内的情景,就像戏台维幕留下的一条未拉严的缝。本文着重讲述32位ELF的同时附带了64位的信息,这两种格式如此雷同,以致于初次接触ELF的读者不必兼顾左右。如果你对Windows比较熟悉,本文还将时时把你带回到PE中,在它们的相似之处稍做比较。ELF文件以“ELF头”开始,后面可选择的跟随着程序头和节头。地理学用等高线与等温线分别展示同一地区的地势和气候,程序头和节头则分别从加载与连接角度来描述EFL文件的组织方式。下面我们进入正文。

 

一、ELF头

     ELF头也叫ELF文件头,它位于文件中最开始的地方。我用系统的是Fedora Core 2,它在elf.h文件中同时给出了ELF头在32位系统和64位系统下的结构,我们先来看一下:

 

typedef struct

{

  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;       

  Elf32_Half    e_phentsize;        

  Elf32_Half    e_phnum;        

  Elf32_Half    e_shentsize;        

  Elf32_Half    e_shnum;        

  Elf32_Half    e_shstrndx;     

} Elf32_Ehdr;

 

typedef struct

{

  unsigned char e_ident[EI_NIDENT]; 

  Elf64_Half    e_type;         

  Elf64_Half    e_machine;      

  Elf64_Word    e_version;      

  Elf64_Addr    e_entry;        

  Elf64_Off e_phoff;        

  Elf64_Off e_shoff;        

  Elf64_Word    e_flags;        

  Elf64_Half    e_ehsize;       

  Elf64_Half    e_phentsize;        

  Elf64_Half    e_phnum;        

  Elf64_Half    e_shentsize;        

  Elf64_Half    e_shnum;        

  Elf64_Half    e_shstrndx;     

} Elf64_Ehdr;

 

elf.h中关于ELF格式所有结构给出的定义,其成员字段的类型声名都是C语言基本类型的别名,不会再嵌套结构。可以看出32位系统和64位系统下 ELF头的结构基本相同,不同的是两种结构中的某个成员字段占用字节个数有所变化。比如e_entry由32位下占4个字节的Elf32_Addr变为 64位下占8个字节的Elf64_Addr,这是因为两种系统下CPU寻址能力不同造成的。同理文件偏移也从4字节的Elf32_Off变为8字节的 Elf64_Off。有些成员字段虽然类型声名从Elf32_XXXX变成了Elf64_XXXX,该域所占的字节个数并未改变。如Elf32_Half 和Elf64_Half都占两个字节,Elf32_Word、Elf32_Sword、Elf64_Word、Elf64_Sword全都是4个字节。尽量使用elf.h中的现有定义将使我们写的程序具有很强的可移植性。另外ELF格式在两种系统下的这种雷同也使得我们可放心的抛弃它们的差别,专心研究其中的一种,然后再轻松的掌握另一种。

 

ELF头中每个字段的含意如下:

 

e_ident:

    这个字段是ELF头结构中的第一个字段,在elf.h中EI_NIDENT被定义为16,因此它占用16个字节。

    e_ident的前四个字节顺次应该是0x7f、0x45、0x4c、0x46,也就是"\177ELF"。这是ELF文件的标志,任何一个ELF文件这四个字节都完全相同。它让熟悉Windows的人想起'MZ'和'PE\O\O'。

  第5个字节标志了ELF格式是32位还是64位,32位是1,64位是2。

  第6个字节,在0x86系统上是1,表明数据存储方式为低字节优先。

  第10个字节,指明了在e_ident中从第几个字节开始后面的字节未使用。

e_type:

  ELF文件的类型,1表示此文件是重定位文件,2表示可执行文件,3表示此文件是一个动态连接库。

e_machine:

  CPU类型,它指出了此文件使用何种指令集。如果是Intel 0x386 CPU此值为3,如果是AMD 64 CPU此值为62也就是16进制的0x3E。

e_version:

  ELF文件版本。为1。

e_entry:

  可执行文件的入口虚拟地址。此字段指出了该文件中第一条可执行机器指令在进程被正确加载后的内存地址!(PE可执行文件指出的是入口的相对虚拟地址 RVA,它是相对于文件加载起始地址的一个偏移值,因此理论上PE文件可被加载到进程序空间任何位置,而ELF可执行文件只能被加载到固定位置)。

e_phoff:

  程序头在ELF文件中的偏移量。如果程序头不存在此值为0。

e_shoff:

  节头在ELF文件中的偏移量。如果节头不存在此值为0。

e_ehsize:

  它描述了“ELF头”自身占用的字节数。

e_phentsize:

  程序头中的每一个结构占用的字节数。程序头也叫程序头表,可以被看做一个在文件中连续存储的结构数组,数组中每一项是一个结构,此字段给出了这个结构占用的字节大小。e_phoff指出程序头在ELF文件中的起始偏移。

e_phnum:

  此字段给出了程序头中保存了多少个结构。如果程序头中有3个结构则程序头在文件中占用了3×e_phentsize个字节的大小。

e_shentsize:

  节头中每个结构占用的字节大小。节头与程序头类似也是一个结构数组,关于这两个结构的定义将分别在讲述程序头和节头的时候给出。

e_shnum:

  节头中保存了多少个结构。

e_shstrndx:

  这是一个整数索引值。节头可以看作是一个结构数组,用这个索引值做为此数组的下标,它在节头中指定的一个结构进一步给出了一个“字符串表”的信息,而这个字符串表保存着节头中描述的每一个节的名称,包括字符串表自己也是其中的一个节。
最新评论共有 4 位网友发表了评论
发表评论
评论内容:不能超过250字,需审核,请自觉遵守互联网相关政策法规。
用户名: 密码:
匿名?
注册