当前位置:文档之家› elf文件

elf文件

elf文件
elf文件

1 Executable and Linkable Format(ELF)初稿,图请参考ELF_Format手册

1.1 Preface

ELF-可执行链接格式最初是由UNIX系统实验室(USL)作为应用程序二进制接口(ABI)开发和发行。工具接口标准委员会TIS已经将ELF作为运行在Intel32位架构之上的各类型操作系统的可导出对象文件格式标准。ELF标准为开发者提供了一组横跨多运行环境的二进制接口定义来组织软件开发。

1.2 对象文件$leads................

1.2.1 介绍

本部分描述了iABI对象文件格式,也称之为ELF。有三种主要类型的对象文件:

1. 可重组(relocatable)文件包含了适合用来链接其他对象文件的代码和数据,从而创建出可执行或可共享的对象文件;

2. 可执行(executable)文件包含了用于执行的程序,该文件规定了exec如何创建一个程序的进程映像;

3. 可共享对象(shared object)文件包含了用来在两个上下文之间链接的代码和数据。首先,链接器ld将该文件和其他的可重组文件或可共享对象文件进行处理后,创建出新对象文件,其次,动态链接器将该新对象文件与可执行文件或共享对象组合,来共同创建一个进程映像;经过汇编器以及链接器创建成的对象文件,其是在处理器上可直接执行的程序的二进制代表。本部分主要描述文件格式以及其如何用来构建程序。后一部分也描述了对象文件,集中在程序执行所必须的信息上。

1.2.1.1 文件格式

在程序链接和程序执行过程都涉及到对象文件。出于方便和效率,对象文件格式图从链接和运行两个视角来展示文件的内容。

ELF header位于文件的开始处,其用来描述文件的组织结构。Section包含了大量的对象文件信息,从链接的视角来看就是指令、数据、符号表、重组信息等等。Segment和Program 是从程序执行视角来观看的,这将在下部分讲解。

如果存在Program Header table的话,其将告诉操作系统如何创建进程映像。用来创建进程映像(执行程序)的文件必须包含program header table。可重组(relocatable)文件可以没有该信息。Section header table包含了用来描述文件section的信息。每个section在该表中都有一个对应的表项,每个表项给出了诸如section名称、尺寸等等信息。用于链接的文件必须有section header table,其他的对象文件可有可无。

这里需要注意的是,虽然图中Program header table紧接着ELF header,section header table 紧接着sections,实际的文件中并不一定是这样。而且,sections和segments也可以不按次序排放,只有ELF header是固定在文件的首部。

1.2.1.2 数据的表示

对象文件格式支持8位、32位等架构的大量处理器。然而,为了保证其容易扩展到更多的体系架构,因此对象文件提供了一些机器独立的控制数据,用来按照统一的方式标明和解释对象文件的内容。对象文件中其余的数据都是按照目标处理器硬编码的,当然不用考虑该文件是在哪个文件上创建的。

对象文件格式中定义的所有数据结构定义都沿守自然尺寸以及对齐原则。必要时,数据结构可以包含填补内容来保证4字节对象的4字节对齐。数据也可以相对于文件起始位置对齐,例如,包含Elf32_Addr成员的数据结构在文件中将会按照4字节对齐。为了保证可移植性,

EFL中不使用bit域。

1.2.2 ELF Header

1.2.2.1 ELF Header结构

一些对象文件控制结构可能会增长,因为ELF header包含了这些结构的实际尺寸。如果对象文件格式发生改变,那么程序有可能会碰到控制结构比原来大或者比原来小的情况,这样,程序有可能就会忽略一些额外的信息。至于这些丢失的信息如何处理,则依赖于上下文环境。

e_ident 这段最先开始的字节标识该文件为对象文件,并且提供了机器独立的数据,其用来解释文件内容。完整的描述见下面的ELF Identification。

e_type 该成员指定了对象文件的类型。虽然核心文件内容没有明确的规定,但是ET_CORE 类型则专门为该文件保留。

从0xFF00到0xFFFF,为特定处理器保留。剩余所有其他的值也是保留的,用于新类型的对象文件。ET_NONE 0 No

ET_REL 1 Relocatable

ET_EXEC 2 Executable

ET_DYN 3 Shared

ET_CORE 4 Core

ET_LOPROC 0xff00 Processor-specific

ET_HIPROC 0xffff Processor-specific

e_machine 该成员指定了文件适用的计算机架构。除了定义的值之外,其他的值保留,在必要时用于新的计算机架构。

EM_NONE 0 No

EM_M32 1 AT&T

EM_SPARC 2 SPARC

EM_386 3 Intel

EM_68K 4 Motorola

EM_88K 5 Motorola

EM_860 7 Intel

EM_MIPS 8 MIPS

e_version 该成员指定了对象文件版本,1表示该文件为最初文件格式。如果扩展了,则使用更高的编号。EV_NONE 0 Invalid

EV_CURRENT 1 Current

e_entry

该成员标明了系统接管该进程控制的第一条指令的逻辑地址,从而开始了该进程。如果没有关联切入点,则默认为0。

e_phoff 该成员包含了program header table的文件偏移地址(按字节),如果该文件没有program header table,则该成员为0。

e_shoff 该成员包含了section header table的文件偏移地址(按字节),如果该文件没有section header tables,则该成员为0。

e_flags 该成员包含了文件与处理器相关的标识。

e_ehsize 该成员包含了ELF header的尺寸(按字节)。

e_phentsize 包含了program header table中一条表项的字节数,所有表项大小相等。

e_phnum 包含了program header table中表项的数目。如果该文件没有program header table,则该值为0。

e_shentsize 包含了section header table中一条表项的字节数,所有表项大小相等。

e_shnum 包含了section header table中表项的数目。如果该文件不含section header table,则该值为0。

e_shstrndx section name string table(段名称字符串表)独立构成一个section。

e_shstrndx成员包含了该section在section header table中表项的索引号。如果该文件不含section name string table,该成员中填充的值为SHN_UNDEF,见……Sections??和……String Table??。

1.2.2.2 ELF ELF Identification Header

像上面提及到的一样,ELF提供了对象文件框架来支持多处理器、多数据编码、多类型的机器。为了支持这些对象文件家族,文件的初始字节必须指明如何解析本文件,而且该指明过程必须和处理器(查询解析信息就是通过该处理器进行的)无关以及和该文件剩余的内容无关。

EFL Header的初始字节也就是e_ident成员。

每个字节的具体值及其含义如下:

EI_MAG0 到EI_MAG3

文件的头4个字节包含了特征码,其用来表明该文件是一个ELF对象文件

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]指明了文件的种类或容量。

ELF文件格式在设计时就考虑到了在不同总线宽度的机器中通用,而不用考虑到诸如把最大总线宽度的机器码强加到最小机器上去。

类别ELFCLASS 32支持高达4GB的虚拟地址空间和文件尺寸,其使用上面定义的基本类型。类别ELFCLASS64为64位架构保留,其也表明了对象文件可能的改变,不过64位格式还没有定义。

其他的类别也会在需要时定义,相应的基本类型和尺寸也会发生变化。ELFCLASSNONE 0 Invalid

ELFCLASS32 1 32-bit

ELFCLASS64 2 64-bit

EI_DA TA

e_ident[EI_DATA]规定了对象文件中和处理器相关的数据的如何编码。更多的下面会详解。ELFDATANONE 0 Invalid

ELFDATA2LSB 1 See below

ELFDATA2MSB 2 See below

EI_VERSION

e_ident[EI_DATA]指定了EFL header版本号。当前情况下,必须是EV_CURRENT,后面会详细解释。

EI_PAD

该值标明了在e_ident中无用字节的开始,这些字节被设置为0,为保留;读取对象文件的进程应该忽略这些字节。如果未来某些未用字节派上用场了,该值在也许会改变。

文件的数据解码规定了如何翻译文件中的基本对象。如上所述,类别ELFCLASS32文件使用占用1、2、4字节的对象。在编码的前提下,对象的排布如下图所示,序号在每个单元的左上角。

ELFDATA2LSB编码规范规定了最末端字节占用最低地址:

ELFDATA2MSB编码规范规定了最末端字节占用最高地址:

机器信息?1.2.2.3 ELF Header

对于32位Intel体系架构而言,文件标识e_ident中相关成员的值应该如下:

e_ident[EI_CLASS]= ELFCLASS32

e_ident[EI_DATA]= ELFDATA2LSB

同时在ELF header中的e_machine成员必须为EM_286。ELF header中的e_flags成员包含了和文件相关的比特标志位。32位Intel体系架构不需要任何标志位,因此该值为0。

1.2.3 Section header table及section特征

1.2.3.1 section header table概述

对象文件的section header tables使得可以轻而易举的定位所有的section,section header table 是一个Elf32_Shdr结构的数组。section header table index是数组中某个元素的下标。ELF header中的e_shoff成员给出了section header table到文件头的偏移(按字节),e_shnum给出了section header table中包含多少个表项,e_shentsize给出了每个表项的字节数。

1.2.3.2 section header 特殊的section index?table

某些section header table index是保留的,对象文件中的section不应该占用这些特殊index。

SHN_UNDEF 该值标明了一个没有定义的、丢失的、或者没有意义的section引用,例如,一个“已经定义了”的符号引用了SHN_UNDEF section序号的,则该符号实际被当作为未定义符号。

注意:虽然索引0被保留为一个未定义的值,但是section header table仍然包含了用于0索引的表项,也就是说,如果e_shnum=6,则索引为0-5 。

SHN_LORESERVE 该值指定了保留索引的低端。

SHN_LOPROC 至SHN_HIPROC 此范围内的索引用于特定的处理器,也是保留的。

SHN_ABS 该值指定了相应引用的绝对值。例如,引用了SHN_ABS section序号的已定义符号,其地址将是绝对的,不会被重组所影响。

SHN_COMMON 引用该section的符号都是常用的符号,例如FORTRAN COMMON或没有分配的C外部变量。

SHN_HIRESERVE 该值指定了保留索引高端,系统保留索引在SHN_LORESERVE和SHN_HIRESERVE范围之间(包含SHN_LORESERVE和SHN_HIRESERVE)。Section head table中不会包含这些保留索引的表项。

1.2.3.3 section的特征

除了ELF header、program header table、section header table之外,Section包含了对象文件中的所有信息。另外,对象文件的section还必须满足以下几个要求:

1. 对象文件中的每个section在section header table中都必须有一个表项来描述它。即使一个

section都没有,section header table也可以存在;

2. 每个section在文件中都占用一段连续字节的空间(当然也可以为空);

3. 一个文件中的sections不能重叠,文件中的一个字节不能同时位于一个以上的section中;

4. 对象文件中可以有不活动的空间,大量的Headers以及sections不一定会覆盖对象文件的每个字节,不活动数据的内容是不确定的。

1.2.4 section header?section header table

1.2.4.1 section header结构

section header的结构如下:

1. sh_name: 该成员指定了section的名称,其值为section “section header string table”(注意section header string table本身构成了一个Section)中某一表项的索引,该索引中为一个以nul终止的字符串;

2. sh_type: 该成员一句section的内容和语义将section分类。section类型及其描述下面将会有详细描述;

3. sh_flags: Section支持使用1bit标志来描述大量的属性,下面将会详细描述;

4. sh_addr: 如果某个section将会出现在进程的内存映射中,该成员给出的就是该section第一个字节驻留在内存中的地址。否则,该成员将会为0;

5. sh_offsect: 该成员给出了从文件开始处到section中第一个字节的偏移(按字节)。这里需要提到的SHT_NOBITS类型的section,其在文件中不占用任何空间,其sh_offsect则为其在文件中的虚位置;

6. sh_size: 该成员给出了section的大小尺寸(按字节),如果该section类型不是SHT_NOBITS,则该size即为该section在文件中所占的字节数。如果是,则即使该值不为0,但是其也不会在文件中占用任何空间;

7. sh_link: 该成员包含了一个section header table的索引链接,其如何解释依赖于该section 的类型,下面将会详细描述;

8. sh_info: 该成员包含了些额外的信息,其如何解释也依赖于section的类型;

9. sh_addralign: 一些section可能会有地址对齐约束,例如我们要求,如果section包含了一个双字,则系统必须确保整个section按照双字对齐。也就是说,sh_addr取模sh_addralign 的值必须为0。目前只有0和2的整数次幂值可以在此处使用,0和1意味着无需对齐;10. sh_entsize: 有些section包含的是一组固定大小表项的表,例如符号表,对于这样的section,该成员给出了每个表项的尺寸大小。如果section不包括这样的内容,则该值为0 。section type?1.2.4.2 section header

section header的sh_type成员包含了如下的语义:

1. SHT_NULL: 该值表示该section header是不活动的,其没有对应的section,此时section header中其他的成员都没有意义;

2. SHT_PROGBITS: 该section包含了程序自定义信息,其格式和含义由程序自行决定;

3. SHT_SYMTAB和SHT_DYNSYM: 该section包含了符号表。当前每种类型的section在对象文件中只能有一个,该限制在未来有望被放开。SHT_SYMTAB为连接器提供了符号,当然其也包含了用于动态链接的符号。但是由于一个完整的符号表可能会包含了大量的对于动态链接没有用的符号,所以,对象文件或许也应该包含一个SHT_DYNSYM section,其中包含了一组最小化的动态链接符号,用来节省空间;

4. SHT_STRTAB: 该section包含了一个string table。一个对象文件可以有多个string table sections;

5. SHT_RELA: 该section包含了重组表项(with explicit addends);

6. SHT_HASH: 该section包含了符号hash表,所有参与动态链接的对象都必须包含一个符号hash表;

7. SHT_DYNAMIC: 该section包含了动态链接信息;

8. SHT_NOTE: 该section包含了特定的信息,详见Note Section;

9. SHT_NOBITS: 该section在文件中不占用空间,但是其类似与SHT_PROGBITS,虽然该section不包含任何字节,但是其sh_offset成员仍然包含了概念上的相对文件起始的偏移地址;

10. SHT_REL: 该section包含了重组表项(without explicit addends);

11. SHT_SHLIB: 该section类型是保留的,还没有被指定语义,和ABI一致的程序不应该包含该section;

12. SHT_LOPROC到SHT_HIPROC: 该范围内的值是为特定处理器语义保留的;

13. SHT_LOUSER: 该值指定了为应用程序编程者保留的索引范围的低端;

14. SHT_HIUSER: 该值指定了为应用程序编程者保留的索引范围的高端,在SHT_LOUSER 到SHT_HIUSER之间的类型的section可以被应用程序使用,而不会同当前的或者未来的为系统定义的类型起冲突;

除上述类型之以外,剩余所有的类型值统统保留,

section flag属性?1.2.4.3 section header

section header的sh_flags成员包含了1比特标志,用来描述该section的属性,定义的值如下:

如果sh_flags中其中一个标志bit位被设置,则该属性就为section打开了。

1. SHF_WRITE: 该section包含了在进程执行期间可写的数据;

2. SHF_ALLOC: 该section在进程执行期间会占用内存。一些控制section不会驻留在对象文件的内存映像里,对于这些section,该属性就为OFF;

3. SHF_EXECINSTR: 该section包含了可执行的机器指令;

4. SHF_MASKPROC: 所有包含在该mask中的属性都用于特定处理器的语义;

sh_link和sh_info属性?1.2.4.4 section header

section header中的sh_link和sh_info成员根据section type的不同,包含了不同的特殊信息。Figure1-13: sh_link和sh_info说明

sh_type sh_link sh_info

SHT_DYNAMIC 对于当前的sh_type,该属性的值即为该section所使用的string table section 在section header table中的索引0

SHT_HASH 对于当前的sh_type,该属性的值即为该hash表section所使用的符号表section 在section header table中的索引0

SHT_REL

SHT_RELA 对于当前的sh_type,该属性的值即为该section所相关的符号表section在section header table中的索引对于当前的sh_type,该属性的值即为该section将要应用重组的section 在section header table中的索引

SHT_SYMTAB

SHT_DYNSYM 对于当前的sh_type,该属性的值即为该section所相关的符号表string在section header table中的索引比符号表中最后一个Local符号(STB_LOCAL)索引还要大的数值

other SHN_UNDEF 0

特殊的section?1.2.4.5 section header

几个特殊的sections说明:

1. .bss,该section包含了在内存中的程序的未初始化的数据,当程序开始运行时,系统将用0来初始化该区域。该section不占用文件空间,该section type = SHT_NOBITS;

2. .comment,该section包含了版本控制信息;

3. .data和.data1,该section包含了在内存中的程序的初始化数据;

4. .debug,该section包含了符号调试信息,其中内容没有硬性规定;

5. .dynamic,该section包含了动态链接信息,该section属性将包含SHF_ALLOC比特位,而SHF_WRITE比特位是否为1取决于处理器;

6. .dynstr,该section包含了用于动态链接的字符串,通常是符号表项名称字符串;

7. .dynsym,该section包含了动态链接符号表;

8. .fini,该section包含了用于终止进程可执行指令代码;

9. .got,该section包含了全局偏移表;

10. .hash,该section包含了符号hash表;

11. .init,该section包含了用于初始化进程的可执行代码,也就是说,当一个程序开始运行的时候,系统将会执行在该section中的代码,然后才会调用程序的入口点(对于C程序而言就是main);

12. .interp,该section包含了程序解释其的路径;

13. .line,该section包含了符号调试信息的行号,其用于描述程序源代码和机器码之间的相应关系;

14. .note,该section包含了供应商及程序兼容信息等;

15. .plt,该section包含了程序链接表;

16. .relname和.relaname,该section包含了relocation信息,该section的属性包括了SHF_ALLOC比特位,通常,name为将要被重组的section的名称,例如如果要重组.text,那么名称就为.rel.text或者.rela.text;

17. .rodata和.rodata1,该section包含了只读数据,通常进程中的不可写段,例如Program Header;

18. .shstrtab,该section包含了section名称;

19. .strtab,该section包含了符号表项名称字符串,如果文件包含了一个可加载的并且包含了符号字符串表的segment,则section的SHF_ALLOC比特位属性将被设置;

20. .symtab,该section包含了符号表,如果文件包含了一个可加载的并且包含了符号表的segment,则section的SHF_ALLOC比特位属性将被设置;

21. .text,该section包含了程序的可执行指令。

带有(.)前缀的section是系统保留的,当然应用程序也可以在这些section语义允许的情况下使用这些section。应用程序可是使用前缀来命名其自己使用的section,以避免和系统section冲突。

String table?1.2.5 特殊的section

String table section包含了null终止的字符序列,也就是字符串。对象文件使用这些字符串来代表符号和section名称。对一个字符串的引用其实就是字符串表的索引。第一个字节,也就是0号索引,通常是一个null字符。同样地,字符串表的最后一个字节也是null,确保所有的字符串都是以null结尾。索引为0的字符串为0,即要么是没有名字要么是空名字,这要取决于上下文。空字符串表section也是允许的,此情况下,其section header的sh_size

成员必须为0 。

首先,section header string table section在section header中表项的索引通过ELF header的e_shstrndx成员找到,然后section header的sh_name定位该string table中的某一表项。例如:

从图中我们可以看出,一个string table index可以指向该section中的任何字节,一个字符串可能会出现多次,当然也允许字符串未被引用;

Symbol?1.2.6 特殊的section Table

1.2.6.1 什么是内核符号表?

内核并不使用符号名。它是通过变量或函数的地址(指针)来使用变量或函数的,而不是使用size_t BytesRead,内核更喜欢使用(例如)c0343f20来引用这个变量。而另一方面,人们并不喜欢象c0343f20这样的名字。我们跟喜欢使用象size_t BytesRead这样的表示。通常,这并不会带来什么问题。内核主要是用C语言写成的,所以在我们编程时编译器/连接程序允许我们使用符号名,并且使内核在运行时使用地址表示。这样大家都满意了。然而,存在一种情况,此时我们需要知道一个符号的地址(或者一个地址对应的符号)。这是通过符号表来做到的,与gdb能够从一个地址给出函数名(或者给出一个函数名的地址)的情况很相似。符号表是所有符号及其对应地址的一个列表。例如:

c03441a0 B dmi_broken

c03441a4 B is_sony_vaio_laptop

c034420c b pirq_router_dev

c0344220 b ascii_buffer

c0344224 b ascii_buf_bytes

你可以看出名称为dmi_broken的变量位于内核地址c03441a0处。

表项格式?1.2.6.2 符号表项

对象文件的符号表用来保存用于定位和重组程序的符号定义和引用的信息,其可以独自占用一个section。符号表项0 STN_UNDEF指明了该表中第一项,其用与未定义符号。表项的初始内容将在后面讲到。

符号表项的内容格式如下:

1. st_name 该成员包含了对象文件的符号字符串表中一个表项的索引号,其保存了该符号的名称;如果该值为非0,其就是一个用来描述该符号名称的字符表索引,否则,该符号表项没有名字;

2. st_value 该成员给出了相关符号的值,至于其中的内容是个绝对的值还是地址等等,取决于上下文;

* 在可重组文件中,st_value包含了符号的对齐约束,该符号必须位于index为SHN_COMMON符号的section中;

* 在可重组文件中,st_value包含了已定义符号的section偏移。也就是说,st_value为自st_shndx指向的section开始处的偏移;

* 在可执行和共享对象文件中,st_value包含了逻辑地址,为了使得这些文件的符号更利于动态连接器使用,对应section的offset给定的是内存逻辑地址;

3. st_size 许多符号都有尺寸,例如,一个数据对象的尺寸就是该对象中包含的字节数。如果符号没有大小或者大小未知,则该值为0;

4. st_info 该成员指定了符号的类型和绑定属性,详述见下,其和bind以及type结合计算方

法如下:

#define ELF32_ST_BIND(i) ((i)>>4)

#define ELF32_ST_TYPE(i) ((i)&0xf)

#define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf));//b=bind,t=type

5. st_other 该成员未定义;

6. st_shndx 每个符号表项都和某section相关,该成员保存了此section在section head table 中的索引。

绑定行为?1.2.6.3 符号表项

符号的绑定决定了链接的可见性以及行为:

1. STB_LOCAL 本地符号,对于外部对象文件不可见。同样名称的符号也许会存在于多个文件中而不会互相干扰;

2. STB_GLOBAL 全局符号,一个对象文件定义,所有对象文件共享;

3. STB_WEAK 类似于全局符号,不过其优先权更低;

4. STB_LOPROC到STB_HIPROC 该范围内的符号为处理器特定的语义;

在每个符号表中,所有STB_LOCAL类型的符号优先级最高。

符号类型?1.2.6.4 符号表项

符号类型提供了实体的分类:

1. STT_NOTYPE 该符号类型未指定;

2. STT_OBJECT 该符号和数据对象相关,例如变量,数组等等;

3. STT_FUNC 该符号和函数或者其他可执行代码相关;

4. STT_SECTION 该符号和section相关,其绑定行为一般为STB_LOCAL;

5. STT_FILE 通常文件符号的名字给出了该对象文件相关的源文件的名字,其绑定行为一般为STB_LOCAL;

6. STT_LOPROC 到STT_HIPROC该范围内的符号为处理器特定的语义;

Relocation?1.2.7 特殊的section

重组就是将符号定义和符号引用连接起来的过程;例如,当程序调用函数时,调用指令必须被传递给执行时正确的目的地址。换句话说,可重组的文件必须包含了这样的信息:该信息描述了如何修改可重组文件的section内容,从而使得可执行或者共享对象文件包含了正确的进程内存映像信息。而Relocation表项就是可重组文件需要包含的信息;

1. r_offset 该成员给出了应用重组动作的位置,对于一个可重组文件而言,该值就是从该section开始到重组将要影响的存储单元之间的字节偏移。对于可执行文件或共享对象文件而言,该值就是将要被重组影响的存储单元的逻辑地址;

2. r_info 该成员给出了该需要重组的符号表索引,以及将要重组的类型。类如,一个调用指令的重组表项包含了将要被调用函数的符号表索引。如果其索引为STN_UNDEF,则使用0作为符号值。重组类型是和处理器相关的。其计算方式如下:

3. r_addend 该成员指定了常量加数用来计算将要被存储到重组域中的值;

关于重组的详细信息不再叙述,请查阅ELF Format。

1.3 程序的加载

1.3.1 介绍

本部分介绍了对象文件信息以及创建运行进程的系统行为。这里的一些信息适用于所有的系统,另一些是和处理器相关的。

可执行和共享对象文件只是静态地代表了程序。要执行这样的程序,操作系统利用该文件来创建动态程序表现,或进程映像。进程印象包含了段,段包含了text、data、stack等等。本部分主要讨论以下几个问题:

1. Program header 该部分补充了前一章讲述的内容,主要描述了程序执行时的对象文件结构,以及用于定位段映像的program header table基本数据结构;

2. Program loading 给定一个对象文件,操作系统必须将其加载如内存来作为程序运行;

3. Dynamic linking 详细信息不再叙述,请查阅ELF Format。

1.3.2 Program header table

可执行或共享对象文件的program header table是一个数据结构数组,每一个表项都描述了一个段或者其他系统用来为程序运行做准备的信息。对象文件的段可以包含多个section,下面的“段内容”将会详细描述。program header table只对可执行和共享对象文件有意义。文件通常通过其ELF header中的e_phentsize和e_phnum成员来指定其自身的program header table 大小。

1.3.3 Program ?header table rogram header

1. p_type 该成员表明了该数组元素所描述的段的类型以及如何解释该数组元素的属性;

2. p_offset 该成员段的第一字节至文件开始处的偏移;

3. p_vaddr 该成员给出了段的第一字节在内存中的逻辑地址;

4. p_paddr 基本无用;

5. p_filesz 该成员给出了该段在文件中占用的字节数,可以为0;

6. p_memsz 该成员给出了该段在内存映像中占用的字节,可以为0;

7. p_flags 该成员给出了段相关的标志;

8. p_align 当程序加载后,可加载的进程段的p_vaddr和p_offset取模page size(4KB)之后的值必须相等。该成员给出该段应该在内存和文件中的对齐值。

?1.3.4 Program header table rogram header Type?

一些表项描述了进程段,其他的一些给出了对进程映像并无作用的辅助信息。段表项可以按照任何顺序出现,除非明确指定。

1. PT_NULL 该元素不适用,其告诉program header table忽略它;

2. PT_LOAD 其指定了可加载段,由p_filesz 和p_memsz来描述。文件中的字节被映射到内存段中。如果段的内存尺寸大于其在文件中的尺寸,那么额外的数据将被填充为0。可加载的段,在program header table中通常按照p_vaddr升序排列;

3. PT_DYNAMIC 该成员指定了动态链接信息;

4. PT_INTERP 指定了翻译器的未知;

5. PT_NOTE 指定了辅助信息的位置和大小;

6. PT_SHLIB 保留;

7. PT_PHDR 如果存在,指定了program header table本身在文件/内存中的位置和大小;

8. PT_LOPROC 至PT_HIPROC 保留;

1.3.5 Base Address

可执行和共享对象文件都有基地址,其是程序对象文件内存映射后的最低的虚拟地址。基地址的用途就是用来在动态链接过程中重组内存映像;详细信息不再叙述,请查阅ELF Format。

1.3.6 初始化和终止函数

当动态连接器已经建立起进程映像并且执行完毕重组后,每一个共享对象都有机会执行一些初始化代码,这些初始化代码并不是按照特定顺序的,但是所有共享对象的初始化都是发生在可执行文件活动控制权之前。程序可以通过动态结构中的DT_INIT和DT_FINI动态表项来定义动态section,通常这些代码都驻留在.init和.fini section中,详细信息不再叙述,请查阅ELF Format。

1.3.7 程序的加载

当操作系统创建或者增加一个进程映像的时候,其理论上将会拷贝文件的段到虚拟内存段中。系统读取文件内容的实际依赖于程序的执行环境的行为。一个进程在运行的过程中,如果没有引用逻辑页面,则其也不需要物理页面,通常大部分页面进程都是没有使用的。因此,延缓读取物理页面可以提高系统性能。为了获取该效率,可执行和共享对象文件的段的文件偏移及虚拟地址必须在按页面(4KB)取模后相等。

虽然上面的例子文件中,对于text和data段而言,文件偏移和逻辑地址取模4KB后都是相等的。但是:

1. text的第一个页面包含了ELF header,program header table以及其他的信息;

2. text的最后一个页面包含了data的开始部分数据的拷贝;

3. data的第一个页面包含了text的末尾数据的拷贝;

4. data的最后一个页面也许包含了和运行进程不相关的文件信息;

理论上讲,系统对待每个段的内存权限都是相互独立的。段地址不得不调整来确保地址空间中的每个逻辑页面都有自己的权限;在上面的例子中,包含了text结尾和data开始的区域将要被映射两次:一次就是包含了text和data开始部分,另一个就是text末尾部分和data;data段的末尾还需要对为初始化数据的特殊处理,系统通常将其清零

pe文件格式

PE文件格式详解(一)――基础知识 什么是PE文件格式: 我们知道所有文件都是一些连续(当然实际存储在磁盘上的时候不一定是连续的)的数据组织起来的,不同类型的文件肯定组织形式也各不相同;PE文件格式便是一种文件组织形式,它是32位Wind ow系统中的可执行文件EXE以及动态连接库文件DLL的组织形式。为什么我们双击一个EXE文件之后它就会被Window运行,而我们双击一个DOC文件就会被Word打开并显示其中的内容;这说明文件中肯定除了存在那些文件的主体内容(比如EXE文件中的代码,数据等,DOC文件中的文件内容等)之外还存在其他一些重要的信息。这些信息是给文件的使用者看的,比如说EXE文件的使用者就是Window,而DOC文件的使用者就是Word。Window可以根据这些信息知道把文件加载到地址空间的那个位置,知道从哪个地址开始执行;加载到内存后如何修正一些指令中的地址等等。那么PE文件中的这些重要信息都是由谁加入的呢?是由编译器和连接器完成的,针对不同的编译器和连接器通常会提供不同的选项让我们在编译和 联结生成PE文件的时候对其中的那些Window需要的信息进行设定;当然也可以按照默认的方式编译连接生成Window中默认的信息。例如:WindowNT默认的程序加载基址是0x40000;你可以在用VC连接生成EXE文件的时候使用选项更改这个地址值。在不同的操作系统中可执行文件的格式是不同的,比如在Linux上就有一种流行的ELF格式;当然它是由在Linux上的编译器和连接器生成的,

所以编译器、连接器是针对不同的CPU架构和不同的操作系统而涉及出来的。在嵌入式领域中我们经常提到交叉编译器一词,它的作用就是在一种平台下编译出能在另一个平台下运行的程序;例如,我们可以使用交叉编译器在跑Linux的X86机器上编译出能在Arm上运行的程序。 程序是如何运行起来的: 一个程序从编写出来到运行一共需要那些工具,他们都对程序作了些什么呢?里面都涉及哪些知识需要学习呢?先说工具:编辑器-》编译器-》连接器-》加载器;首先我们使用编辑器编辑源文件;然后使用编译器编译程目标文件OBJ,这里面涉及到编译原理的知识;连接器把OBJ文件和其他一些库文件和资源文件连接起来生成EXE文件,这里面涉及到不同的连接器的知识,连接器根据OS的需要生成EXE文件保存着磁盘上;当我们运行EXE文件的时候有W indow的加载器负责把EXE文件加载到线性地址空间,加载的时候便是根据上一节中说到的PE文件格式中的哪些重要信息。然后生成一个进程,如果进程中涉及到多个线程还要生成一个主线程;此后进程便开始运行;这里面涉及的东西很多,包括:PE文件格式的内容;内存管理(CPU内存管理的硬件环境以及在此基础上的OS内存管理方式);模块,进程,线程的知识;只有把这些都弄清楚之后才能比较清楚的了解这整个过程。下面就让我们先来学习PE文件格式吧。

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 16 typedef 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;

elf详解

ARM-ELF文件格式与GNU ARM Linker机制 作者:admin 日期:2008-10-13 字体大小: 小中大

里面除了二进制的机器代码,还有一些可用于进行重定位的信息。它主要是作为LINKER(ld)的输入,LINKER将跟据这些信息,将需要重定位的符号重定位,进而产生可执行的OBJECT 文件。ELF格式的可重定位OBJECT文件由header与section 组成。 Header 包括ELF header 与 section header. ELF header 位于文件的头部,用于存储目标机器的架构,大小端配置,ELF header 大小,object文件类型,section header 在文件中的偏移,section header 的大小,section header 中的项目数等信息。Section header 则定义了文件中每个section 的类型,位置,大小等信息。Linker就是通过查找ELF header,找到 section header 的入口,再在section header 中找到相应的section 入口,进而定位到目标section 的。 Section 包括 .text :经过编译的机器代码。 .rodata :只读的数据,例如printf(“hello!”)中的字符串hello。.data :已初始化的全局变量,局部变量将在运行时被存放在堆栈中,不会在.data或 .bss段中出现。 .bss :未初始化的全局变量,在这里只是一个占位符,在object 文件中并没有实际的存储空间。 .symtab :符号表,用于存放程序中被定义的或被引用到的全局变量和函数的信息。

elf文件资料格式(中文版)

3. 页标题的容和文章的页脚已经在开始的时候被换掉了。 4. 文章的排版也已经修正过了。 5. 如果必要,不同的字体已经被忽略了。大部分地方,这片文档能让你 充分的理解。然而,很小的地方,原始的文档使用了斜体字来指出文 章中的字符变量。在那种情况下,本文使用<尖括号>。在原始的文档 中没有出现尖括号。 6. 原始的文档有三个错误,如果你是不经意读它的话,是不会明显 就能找出的。但是在这里,明确的被鉴别出来了。 我很冒昧的纠正了那些错误。在他们的位置用一个{*}做上了标记。 可能还有其他我没有看出来的的错误。 如果有如何其他的区别都是我的责任。这样的错误请 mailto:breadboxmuppetlabs.. Brian Raiter [Last edited Fri Jul 23 1999] ________________________________________________________________ EXECUTABLE AND LINKABLE FORMAT (ELF) Portable Formats Specification, Version 1.1 Tool Interface Standards (TIS) ________________________________________________________________ =========================== Contents 容=========================== 序言 1. OBJECT文件 导言 ELF头(ELF Header) Sections String表(String Table) Symbol表(Symbol Table) 重定位(Relocation) 2. 程序装载与动态连接 导言 Program头(Program Header)

关于ELF文件格式

现代Linux采用ELF(Executable and Linking Format)做为其可连接和可执行文件的格式,因此ELF格式也向我们透出了一点Linux核内的情景,就像戏台维幕留下的一条未拉严的缝。 PC世界32仍是主流,但64位的脚步却已如此的逼近。如果你对Windows比较熟悉,本文还将时时把你带回到PE中,在它们的相似之处稍做比较。ELF文件以“ELF 头”开始,后面可选择的跟随着程序头和节头。地理学用等高线与等温线分别展示同一地区的地势和气候,程序头和节头则分别从加载与连接角度来描述EFL文件的组织方式。 ELF头 ------------------------------------------------ ELF头也叫ELF文件头,它位于文件中最开始的地方。 /usr/src/linux/include/linux/elf.h typedef struct elf32_hdr{ unsigned char e_ident[EI_NIDENT]; Elf32_Half e_type; Elf32_Half e_machine; Elf32_Word e_version; Elf32_Addr e_entry; /* Entry point */ 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; #define EI_NIDENT 16 ELF头中每个字段的含意如下: Elf32_Ehdr->e_ident[] (Magic) 这个字段是ELF头结构中的第一个字段,在elf.h中EI_NIDENT被定义为16,因此它占用16个字节。e_ident的前四个字节顺次应该是0x7f、 0x45、 0x4c、 0x46,也就是"\177ELF"。这是ELF文件的标志,任何一个ELF文件这四个字节都完全相同。 16进制 8进制字母 0x7f 0177 0x45 E 0x4c L

目标文件格式分析工具-ar-nm等等

目标文件格式分析工具: ar,nm,objdump,objcopy,readelf 如果普通编程不需要了解这些东西,如果想精确控制你的目标文件的格式或者你想查看一下文件里的内容以便作出某种判断,那么你可以看一下下面的工具:ar,nm,objdump,objcopy。具体用法请参考man在线手册。 ar基本用法 ar命令可以用来创建、修改库,也可以从库中提出单个模块。库是一单独的文件,里面包含了按照特定的结构组织起来的其它的一些文件(称做此库文件的member)。原始文件的内容、模式、时间戳、属主、组等属性都保留在库文件中。 下面是ar命令的格式: ar [-]{dmpqrtx}[abcfilNoPsSuvV] [membername] [count] archive files... 例如我们可以用ar rv libtest.a hello.o hello1.o来生成一个库,库名字是test,链接时可以用-ltest链接。该库中存放了两个模块hello.o和hello1.o。选项前可以有‘-'字符,也可以没有。下面我们来看看命令的操作选项和任选项。现在我们把{dmpqrtx}部分称为操作选项,而[abcfilNoPsSuvV]部分称为任选项。 {dmpqrtx}中的操作选项在命令中只能并且必须使用其中一个,它们的含义如下: ?d:从库中删除模块。按模块原来的文件名指定要删除的模块。如果使用了任选项v 则列出被删除的每个模块。 ?m:该操作是在一个库中移动成员。当库中如果有若干模块有相同的符号定义(如函数定义),则成员的位置顺序很重要。如果没有指定任选项,任何指定的成员将移到库的最后。也可以使用'a','b',或'I'任选项移动到指定的位置。 ?p:显示库中指定的成员到标准输出。如果指定任选项v,则在输出成员的内容前,将显示成员的名字。如果没有指定成员的名字,所有库中的文件将显示出来。 ?q:快速追加。增加新模块到库的结尾处。并不检查是否需要替换。'a','b',或'I'任选项对此操作没有影响,模块总是追加的库的结尾处。如果使用了任选项v则列出每个模块。 这时,库的符号表没有更新,可以用'ar s'或ranlib来更新库的符号表索引。 ?r:在库中插入模块(替换)。当插入的模块名已经在库中存在,则替换同名的模块。 如果若干模块中有一个模块在库中不存在,ar显示一个错误消息,并不替换其他同名模块。默认的情况下,新的成员增加在库的结尾处,可以使用其他任选项来改变增加的位置。 ?t:显示库的模块表清单。一般只显示模块名。 ?x:从库中提取一个成员。如果不指定要提取的模块,则提取库中所有的模块。 下面在看看可与操作选项结合使用的任选项: ?a:在库的一个已经存在的成员后面增加一个新的文件。如果使用任选项a,则应该为命令行中membername参数指定一个已经存在的成员名。

计算机操作系统实验_解析ELF文件

西北工业大学操作系统实验实验报告 一、实验目的 熟悉可执行链接文件(ELF)的结构,了解GeekOS将ELF格式的可执行程序加载到内存,建立内核线程并运行的实现技术。 二、实验要求 1.修改Project1项目中的/GeekOS/elf.c文件:在函数Parse_ELF_Executable()中添加代码,分析ELF格式的可执行文件(包括分析得出ELF文件头、程序头),获取可执行文件长度、代码段、数据段等信息,并打印输出。并且,填充Exe_Format 数据结构中的值域。 2.掌握GeekOS在核心态运行可执行程序的原理,绘制出可执行程序在内核中加载、运行的流程图(需反映关键函数的调用关系)。 3.回答实验讲义P125页的思考题。 三、实验过程及结果 1、修改Project1项目中的/GeekOS/elf.c文件:在函数Parse_ELF_Executable()中添加代码,分析ELF格式的可执行文件(包括分析得出ELF文件头、程序头),获取可执行文件长度、代码段、数据段等信息,并打印输出。并且,填充Exe_Format 数据结构中的值域。 答:修改Project1项目中的/GeekOS/elf.c文件:在函数Parse_ELF_Executable()中添加代码,如下: ==============elf.c=================== int Parse_ELF_Executable(char *exeFileData, ulong_t exeFileLength, struct Exe_Format *exeFormat) { int i; elfHeader *head=(elfHeader*)exeFileData; programHeader *proHeader=(programHeader *)(exeFileData+head->phoff); KASSERT(exeFileData!=NULL); KASSERT(exeFileLength>head->ehsize+head->phentsize*head->phnum); KASSERT(head->entry%4==0); exeFormat->numSegments=head->phnum;

ELF格式-中文

________________________________________________________________ EXECUTABLE AND LINKABLE FORMAT (ELF) Portable Formats Specification, Version 1.1 Tool Interface Standards (TIS) ________________________________________________________________ =========================== Contents 内容=========================== 序言 1. OBJECT文件 导言 ELF头(ELF Header) Sections String表(String Table) Symbol表(Symbol Table) 重定位(Relocation) 2. 程序装载与动态连接 导言 Program头(Program Header) Program装载(Program Loading) Dynamic连接(Dynamic Linking) 3. C LIBRARY C Library ________________________________________________________________ 导言 ________________________________________________________________ ELF: 可执行连接格式 可执行连接格式是UNIX系统实验室(USL)作为应用程序二进制接口 (Application Binary Interface(ABI)而开发和发布的。工具接口标准委 员会(TIS)选择了正在发展中的ELF标准作为工作在32位INTEL体系上不同操 作系统之间可移植的二进制文件格式。

Linux ELF 运行时内存详解 - 黑客防线官方站

Linux ELF 运行时内存详解 4/22/2012 前一段时间做ROP (return-oriented programming )的东西,想要系统的了解Linux 中程序的内存格式(memory layout ),网上有很多文章,却没有一个深入完整的介绍。所以花了些时间做深入的了解,不放过一个细节。由于最初写的是英文文档,所以文中的图都是用英文标识的,不过应该不影响阅读。 本文详细解释了Linux ELF 文件的虚拟地址空间。另外本文也大概介绍了ASLR (Address Space Layout Randomization)技术对ELF 虚拟地址空间的影响。作者的测试系统是Linux Ubuntu 2.6.32-24和Vmware Workstation 7。另外所有的分析都基于Intel x86架构。 虚拟地址空间 当代的操作系统中每个进程都有自己的独立虚拟地址空间。在32位系统上,该虚拟地址空间有4G 大小。为了将虚拟地址转换为物理地址,Linux 内核使用了一个两级(事实上是三级,但是中间一级没有任何实质操作)分页机制,即页目录表和页表。分页机制与MMU (Memory Management Unit )合作将虚拟地址转换为物理地址。当操作系统引入虚拟地址后,所有的用户操作系统和内核线程(事实上Linux 只有进程概念而没有线程概念,Linux 通过页表机制来模拟实现内核线程)都将运行于虚拟地址模式。 另外Linux (以及Windows )使用了CPU 提供的权限机制。内核代码将运行于ring 0而用户程序运行于ring 3。 因此为了适应该分级机制以及适应多任务机制,Linux 的虚拟地址空间被分为两部分,如图1所示: 0xffff ffff 0x0Linux Virtual Address Split 0xffff ffff 0x0 Windows Virtual Address Split 图1. Linux/Windows 虚拟地址空间的内核部分和用户部分。 Linux 中,内核空间为0xc0000000到0xffffffff 的地址,因此内核代码将被映射到区域。而在Windows 中,默认的分割方式为内核与用户各占2GB 。本文仅详细分析Linux 的地址空间而不再涉及Windows 。下面分两部分介绍Linux 地址空间,首先是内核地址空间然后再介绍用户地址空间。 1. 内核地址空间 黑 客防线 a c k e r .c o m .c n 明出处

Linux系统下的ELF文件分析

Linux系统下的ELF文件分析 摘要:随着linux系统的发展,elf成了十分重要的可执行文件格式。本文介绍了eIf文件的格式,并在此基础上分析出eIf文件的特性。关键词:elf文件:平台相关PIC 1.引言 ELF(Executable and Linkable Format)IN可执行连接文件格式.是LinuxSVR4和Solaris2,0默认的目标文件格式,目前标准接口委员会TIS已将ELF标准化为一种可移植的目标文件格式,运行于32一bitIntel体系微机上,可与多种操作系统兼容。分析elf文件有助于理解一些重要的系统概念,例如程序的编译和链接,程序的加载和运行等 2.ELF文件格式 2.1 ELF文件的类型ELF文件主要有三种类型 (1)可重定位文件包含了代码和数据.可与其它ELF文件建立一个可执行或共享的文件: (2)可执行文件时可直接执行的程序: (3)共享目标文件包括代码和数据,可以在两个地方链接。第一,连接器可以把它和其它可重定位文件和共享文件一起处理以建立另一个ELF文件;第二,动态链接器把它和一个可执行文件和其它共享文件结合在一起建立一个进程映像。 2.2 ELF文件的组织 ELF文件参与程序的连接(建立一个程序)和程序的执行(运行一个程序),编译器和链接器将其视为节头表(section headertable)描述的一些节(section)的集合,而加载器则将其视为程序头表(program header table)描述的段(segment)的集合,通常一个段可以包含多个节。可重定位文件都包含一个节头表.可执行文件都包含一个程序头表。共享文件两者都包含有。为此,ELF文件格式同时提供了两种看待文件内容的方式,反映了不同行为的不同要求。

elf文件格式(中文版)

3. 页标题的内容和文章的页脚已经在开始的时候被换掉了。 4. 文章的排版也已经修正过了。 5. 如果必要,不同的字体已经被忽略了。大部分地方,这片文档能让你 充分的理解。然而,很小的地方,原始的文档使用了斜体字来指出文 章中的字符变量。在那种情况下,本文使用<尖括号>。在原始的文档 中没有出现尖括号。 6. 原始的文档有三个错误,如果你是不经意读它的话,是不会明显 就能找出的。但是在这里,明确的被鉴别出来了。 我很冒昧的纠正了那些错误。在他们的位置用一个{*}做上了标记。 可能还有其他我没有看出来的的错误。 如果有如何其他的区别都是我的责任。这样的错误请 mailto:breadbox@https://www.doczj.com/doc/8015861713.html,. Brian Raiter [Last edited Fri Jul 23 1999] ________________________________________________________________ EXECUTABLE AND LINKABLE FORMAT (ELF) Portable Formats Specification, Version 1.1 Tool Interface Standards (TIS) ________________________________________________________________ =========================== Contents 内容=========================== 序言 1. OBJECT文件 导言 ELF头(ELF Header) Sections String表(String Table) Symbol表(Symbol Table) 重定位(Relocation) 2. 程序装载与动态连接 导言 Program头(Program Header)

可执行文件(ELF)格式的理解=

可执行文件(ELF)格式的理解 ELF(Executable and Linking Format)是一种对象文件的格式,用于定义不同类型的对象文件(Object files)中都放了什么东西、以及都以什么样的格式去放这些东西。它自最早在System V 系统上出现后,被xNIX 世界所广泛接受,作为缺省的二进制文件格式来使用。可以说,ELF是构成众多xNIX系统的基础之一,所以作为嵌入式Linux系统乃至内核驱动程序开发人员,你最好熟悉并掌握它。 其实,关于ELF这个主题,网络上已经有相当多的文章存在,但是其介绍的内容比较分散,使得初学者不太容易从中得到一个系统性的认识。为了帮助大家学习,我这里打算写一系列连贯的文章来介绍ELF以及相关的应用。这是这个系列中的第一篇文章,主要是通过不同工具的使用来熟悉ELF文件的内部结构以及相关的基本概念。后面的文章,我们会介绍很多高级的概念和应用,比方动态链接和加载,动态库的开发,C语言Main函数是被谁以及如何被调用的,ELF格式在内核中的支持,Linux内核中对ELF section的扩展使用等等。 好的,开始我们的第一篇文章。在详细进入正题之前,先给大家介绍一点ELF文件格式的参考资料。在ELF 格式出来之后,TISC(Tool Interface Standard Committee)委员会定义了一套ELF标准。你可以从这里(https://www.doczj.com/doc/8015861713.html,/elf/)找到详细的标准文档。TISC委员会前后出了两个版本,v1.1和v1.2。两个版本内容上差不多,但就可读性上来讲,我还是推荐你读v1.2的。因为在v1.2版本中,TISC重新组织原本在v1.1版本中的内容,将它们分成为三个部分(books): a) Book I 介绍了通用的适用于所有32位架构处理器的ELF相关内容 b) Book II 介绍了处理器特定的ELF相关内容,这里是以Intel x86 架构处理器作为例子介绍 c) Book III 介绍了操作系统特定的ELF相关内容,这里是以运行在x86上面的UNIX System V.4 作为例子介绍 值得一说的是,虽然TISC是以x86为例子介绍ELF规范的,但是如果你是想知道非x86下面的ELF实现情况,那也可以在https://www.doczj.com/doc/8015861713.html,/elf/中找到特定处理器相关的Supplment文档。比方ARM相关的,或者MIPS相关的等等。另外,相比较UNIX系统的另外一个分支BSD Unix,Linux系统更靠近System V 系统。所以关于操作系统特定的ELF内容,你可以直接参考v1.2标准中的内容。 这里多说些废话:别忘了Linus 在实现Linux的第一个版本的时候,就是看了介绍Unix内部细节的书:《The of the Unix Operating System》,得到很多启发。这本书对应的操作系统是System V 的第二个Release。这本书介绍了操作系统的很多设计观念,并且行文简单易懂。所以虽然现在的Linux也吸取了其他很多Unix 变种的设计理念,但是如果你想研究学习Linux内核,那还是以看这本书作为开始为好。这本书也是我在接触Linux内核之前所看的第一本介绍操作系统的书,所以我极力向大家推荐。(在学校虽然学过操作系统原理,但学的也是很糟糕最后导致期末考试才四十来分,记忆仿佛还在昨天:)) 好了,还是回来开始我们第一篇ELF主题相关的文章吧。这篇文章主要是通过使用不同的工具来分析对象文

ELF格式data、bss、text段内容调查

详情参考<<程序员的自我修养>> 几个特殊的sections说明: 1. .bss,该section包含了在内存中的程序的未初始化的数据,当程序开始运行时,系统将用0来初始化该区域。该section不占用文件空间,该section type = SHT_NOBITS; 2. .comment,该section包含了版本控制信息; 3. .data和.data1,该section包含了在内存中的程序的初始化数据; 4. .debug,该section包含了符号调试信息,其中内容没有硬性规定; 5. .dynamic,该section包含了动态链接信息,该section属性将包含SHF_ALLOC比特位,而SHF_WRITE比特位是否为1取决于处理器; 6. .dynstr,该section包含了用于动态链接的字符串,通常是符号表项名称字符串; 7. .dynsym,该section包含了动态链接符号表; 8. .fini,该section包含了用于终止进程可执行指令代码; 9. .got,该section包含了全局偏移表; 10. .hash,该section包含了符号hash表; 11. .init,该section包含了用于初始化进程的可执行代码,也就是说,当一个程序开始运行的时候,系统将会执行在该section中的代码,然后才会调用程序的入口点(对于C程序而言就是main); 12. .interp,该section包含了程序解释其的路径; 13. .line,该section包含了符号调试信息的行号,其用于描述程序源代码和机器码之间的相应关系; 14. .note,该section包含了供应商及程序兼容信息等; 15. .plt,该section包含了程序链接表; 16. .relname和.relaname,该section包含了relocation信息,该section的属性包括了SHF_ALLOC比特位,通常,name为将要被重组的section的名称,例如如果要重组.text,那么名称就为.rel.text或者.rela.text; 17. .rodata和.rodata1,该section包含了只读数据,通常进程中的不可写段,例如Program Header; 18. .shstrtab,该section包含了section名称; 19. .strtab,该section包含了符号表项名称字符串,如果文件包含了一个可加载的并且包含了符号字符串表的segment,则section的SHF_ALLOC比特位属性将被设置; 20. .symtab,该section包含了符号表,如果文件包含了一个可加载的并且包含了符号表的segment,则section的SHF_ALLOC比特位属性将被设置; 21. .text,该section包含了程序的可执行指令。 虽然上面的例子文件中,对于text和data段而言,文件偏移和逻辑地址取模4KB后都是相等的。但是: 1. text的第一个页面包含了ELF header,program header table以及其他的信息; 2. text的最后一个页面包含了data的开始部分数据的拷贝; 3. data的第一个页面包含了text的末尾数据的拷贝; 4. data的最后一个页面也许包含了和运行进程不相关的文件信息; 理论上讲,系统对待每个段的内存权限都是相互独立的。段地址不得不调整来确保地址空间中的每个逻辑页面都有自己的权限;在上面的例子中,包含了text结尾和data开始的区域将要被映射两次:一次就是包含了text和data开始部分,另一个就是text末尾部分和data;data段的末尾还需要对为初始化数据的特殊处理,系统通常将其清零。

FLT文件格式

FLT文件格式 [摘要] 本文首先对FLT文件格式进行了简单的介绍,然后以一个简单的例子说明FLT文件的生成及加载过程。 [正文] Linux系统支持ELF文件格式,利用虚拟内存机制,在编译时即可确定程序运行时的地址;而uClinux是针对无MMU的系统设计的,所以它没有虚拟内存机制,运行时的地址就是物理地址。由于程序被加载到的物理地址是不确定的,在uClinux中,程序在被加载时必须引入一种重定位机制进行地址重定位,ELF文件格式已经不能满足这种需求。在这种情况下,uClinux引入了一种新的文件格式——FLT文件格式。 一个简单的FLT文件结构如下: Reloc info Data Text Flat header FLT文件就像是一个进程的内存映像,text段和data段是连续的,reloc info段位于文件的末尾,它包含了FLT文件的重定位信息。 FLT文件的头部定义如下: struct flat_hdr{ char magic[4]; unsigned long rev;/*version(as above)*/ unsigned long entry;/*Offset of first executable instruction with text segment from beginning of file*/ unsigned long data_start;/*Offset of data segment from beginning of file*/ unsigned long data_end;/*Offset of end of data segment from beginning of file*/ unsigned long bss_end;/*Offset of end of bss segment from beginning of file*/ /*(It is assumed that data_end through bss_end forms the bss segment.)*/ unsigned long stack_size;/*Size of stack,in bytes*/ unsigned long reloc_start;/*Offset of relocation records from

bin和axf文件区别

hex,bin,axf,elf文件格式的区别 (2012-08-24 15:50:34) 转载▼ 分类:STM32 标签: 设置 杂谈 hex,bin,axf,elf的区别 一、HEX 和 BIN Hex文件,这里指的是Intel标准的十六进制文件,也就是机器代码的十六进制形式,并且是用一定文件格式的ASCII码来表示.具体格式介绍如下: Intel hex 文件格式 Intel hex 文件常用来保存单片机或其他处理器的目标程序代码。它保存物理程序存储区中的目标代码映象。一般的编程器都支持这种格式。Intel hex 文件全部由可打印的ASCII字符组成,如下例所示: :2000000012014c75a800e4f508f509780a7a78e4f608dafcd283fcfded240af9a7050dbd81 :2000200000010ced2488ec34ff50edc283e4fcfded240af9e76d7013ed33e43c700d0dbd2a :2000400000010ced2488ec34ff50e50509e50970020508e50924a8e50834fd50aee4f50874 Intel hex 由一条或多条记录组成,每条记录都由一个冒号“:”打头,其格式如下: :CCAAAARR...ZZ 其中: CC 本条记录中的数据字节数 AAAA 本条记录中的数据在存储区中的起始地址 RR 记录类型: 00 数据记录 (data record) 01 结束记录 (end record) 02 段记录 (paragraph record) 03 转移地址记录 (transfer address record) ... 数据域 ZZ

elf文件

1 Executable and Linkable Format(ELF)初稿,图请参考ELF_Format手册 1.1 Preface ELF-可执行链接格式最初是由UNIX系统实验室(USL)作为应用程序二进制接口(ABI)开发和发行。工具接口标准委员会TIS已经将ELF作为运行在Intel32位架构之上的各类型操作系统的可导出对象文件格式标准。ELF标准为开发者提供了一组横跨多运行环境的二进制接口定义来组织软件开发。 1.2 对象文件$leads................ 1.2.1 介绍 本部分描述了iABI对象文件格式,也称之为ELF。有三种主要类型的对象文件: 1. 可重组(relocatable)文件包含了适合用来链接其他对象文件的代码和数据,从而创建出可执行或可共享的对象文件; 2. 可执行(executable)文件包含了用于执行的程序,该文件规定了exec如何创建一个程序的进程映像; 3. 可共享对象(shared object)文件包含了用来在两个上下文之间链接的代码和数据。首先,链接器ld将该文件和其他的可重组文件或可共享对象文件进行处理后,创建出新对象文件,其次,动态链接器将该新对象文件与可执行文件或共享对象组合,来共同创建一个进程映像;经过汇编器以及链接器创建成的对象文件,其是在处理器上可直接执行的程序的二进制代表。本部分主要描述文件格式以及其如何用来构建程序。后一部分也描述了对象文件,集中在程序执行所必须的信息上。 1.2.1.1 文件格式 在程序链接和程序执行过程都涉及到对象文件。出于方便和效率,对象文件格式图从链接和运行两个视角来展示文件的内容。 ELF header位于文件的开始处,其用来描述文件的组织结构。Section包含了大量的对象文件信息,从链接的视角来看就是指令、数据、符号表、重组信息等等。Segment和Program 是从程序执行视角来观看的,这将在下部分讲解。 如果存在Program Header table的话,其将告诉操作系统如何创建进程映像。用来创建进程映像(执行程序)的文件必须包含program header table。可重组(relocatable)文件可以没有该信息。Section header table包含了用来描述文件section的信息。每个section在该表中都有一个对应的表项,每个表项给出了诸如section名称、尺寸等等信息。用于链接的文件必须有section header table,其他的对象文件可有可无。 这里需要注意的是,虽然图中Program header table紧接着ELF header,section header table 紧接着sections,实际的文件中并不一定是这样。而且,sections和segments也可以不按次序排放,只有ELF header是固定在文件的首部。 1.2.1.2 数据的表示 对象文件格式支持8位、32位等架构的大量处理器。然而,为了保证其容易扩展到更多的体系架构,因此对象文件提供了一些机器独立的控制数据,用来按照统一的方式标明和解释对象文件的内容。对象文件中其余的数据都是按照目标处理器硬编码的,当然不用考虑该文件是在哪个文件上创建的。 对象文件格式中定义的所有数据结构定义都沿守自然尺寸以及对齐原则。必要时,数据结构可以包含填补内容来保证4字节对象的4字节对齐。数据也可以相对于文件起始位置对齐,例如,包含Elf32_Addr成员的数据结构在文件中将会按照4字节对齐。为了保证可移植性,

Android平台ELF文件格式

ELF英文全程为:Executable Linkable Format,ELF属于Linux平台下可执行文件。ELF文件格式与Windows下的PE(Portable Executable)文件格式相似,都是属于COFF(Common File Format)文件格式变种。谷歌的Android操作系统内核采用Linux内核框架实现,所以Android平台原生文件格式与Linux可执行文件格式完全相似,同属于ELF类型文件。 Android平台下游戏逻辑通常使用C、C++语言实现,编译之后的可执行文件属于ELF文件格式,ELF文件格式整体布局如下图所示: 谷歌的Android NDK提供工具方便开发者查看ELF文件格式,对应工具名为:arm-linux-androideabi-readelf,工具所在NDK根目录的相对路径为:android-ndk- r9c\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\,arm-linux-androideabi-readelf工具部分使用说明如下图所示:

本章使用“libTest.so”文件作为实例介绍ELF格式信息。下面将详细讲解ELF文件格式,以便让读者对Android平台原生程序的文件格式有较好理解。 1.1.1文件头信息 ELF文件头描述文件基本属性信息,包括ELF文件版本号、目标机器型号、程序入口、段表描述信息等信息。ELF文件头数据大小为0x34字节,实例文件的ELF文件头信息二进制数据如下所示: 上图中标为蓝色的数据为ELF文件头二进制内存数据,最右边可明显看出有“ELF”字符串,读者也许已猜到数据对应ELF文件标志,即判断是否为ELF文件表示。arm-linux-androideabi-readelf工具可方便查看ELF文件头信息。 利用arm-linux-androideabi-readelf工具查看ELF文件头信息命令如下: arm-linux-androideabi-readelf.exe -h libTest.so 对应获取的文件头信息如下:

elf文件格式与动态链接库(大地小神之个人收藏)

elf文件格式与动态链接库(非常之好) 机器执行的是机器指令,而机器指令就是一堆二进制的数字。高 级语言编写的程序之所以可以在不同的机器上移植就因为有为不同 机器设计的编译器的存在。高级语言的编译器就是把高级语言写的 程序转换成某个机器能直接执行的二进制代码。以上的知识在我们 学习CS(Computer Science)的初期,老师都会这么对我们讲。但是我 就产生疑问了:既然机器都是执行的二进制代码,那么是不是说只 要硬件相互兼容,不同操作系统下的可执行文件可以互相运行呢? 答案肯定是不行。这就要谈到可执行文件的格式问题。 每个操作系统都会有自己的可执行文件的格式,比如以前的Unix?是用a.out格式的,现代的Unix?类系统使用elf格式,WindowsNT?是使用基于COFF格式的可执行文件。那么最简单的格式应该是DOS的可执行格式,严格来说DOS的可执行文件没有什么格式可言,就是把二进制代码安顺序放在文件里,运行时DOS操作系统就把所 有控制计算机的权力都给了这个程序。这种方式的不足之处是显而 易见的,所以现代的操作系统都有一种更好的方式来定义可执行文 件的格式。一种常见的方法就是为可执行文件分段,一般来说把程 序指令的内容放在.t e x t段中,把程序中的数据内容放在.d a t a段中,把程序中未初始化的数据放在.b s s段中。这种做法的好处有很多, 可以让操作系统内核来检查程序防止有严重错误的程序破坏整个运 行环境。比如:某个程序想要修改.text段中的内容,那么操作系统

就会认为这段程序有误而立即终止它的运行,因为系统会把.t e x t段的内存标记为只读。在.b s s段中的数据还没有初始化,就没有必要在可执行文件中浪费储存空间。在.bss中只是表明某个变量要使用多少的内存空间,等到程序加载的时候在由内核把这段未初始化的内存空间初始化为0。这些就是分段储存可执行文件的内容的好处。 下面谈一下Unix系统里的两种重要的格式:a.out和elf (Executable and Linking Format)。这两种格式中都有符号表(symbol table),其中包括所有的符号(程序的入口点还有变量的地址等等)。在e l f格式中符号表的内容会比a.o u t格式的丰富的多。但是这些符号表可以用s t r i p工具去除,这样的话这个文件就无法让debug程序跟踪了,但是会生成比较小的可执行文件。a.o u t文件中的符号表可以被完全去除,但是elf中的在加载运行时起着重要的作用,所以用strip永远不可能完全去除elf格式文件中的符号表。但是用strip 命令不是完全安全的,比如对未连接的目标文件来说如果用strip去掉符号表的话,会导致连接器无法连接。例如: 代码: $:gcc -c hello.c $:ls hello.c hello.o 用gcc把hello.c编译成目标文件hello.o 代码: $:strip hello.o

相关主题
文本预览
相关文档 最新文档