当前位置:文档之家› ELF 文件格式分析TN05.ELF.Format.Summary

ELF 文件格式分析TN05.ELF.Format.Summary

ELF 文件格式分析TN05.ELF.Format.Summary
ELF 文件格式分析TN05.ELF.Format.Summary

技术笔记

PKU/SSDB-03-TN-005

JBEOS-TN-03-005

2003年5月ELF文件格式分析

滕启明

北京大学信息科学技术学院操作系统实验室

2003年5月

声明

本研究工作是在国家863计划软件重大专项《构件化嵌入式操作系统及开发环境》资助下开展的。本报告中涉及的技术观点主要参考相关研究项目公开发表的成果,不提供任何形式、任何意义保证。本报告仅作为内部技术交流材料使用。任何外部使用须经北京大学软件研究所授权。

摘要嵌入式操作系统应用领域广,硬件环境复杂多样,降低开发成本、缩短开发周期、提高产品质量是工业界和学术界共同关注的问题。借鉴软件复用的思想,

采用基于构件的软件开发思路来开发嵌入式操作系统是一条可行的途径。本文

是作者在探索系统软件构件的复用技术的过程中生成的技术笔记,重点分析了

UNIX类操作系统中普遍采用的目标文件格式ELF(Executable and Linkable Format),目的是研究操作系统中二进制级软件构件的静态、动态组装技术。

本文首先介绍ELF文件格式规范,然后结合一个简单的C语言程序,分析编

译、链接后生成的可重定位、可执行格式实例。

关键词操作系统编译链接目标文件软件构件

目录

1简介 (1)

2相关标准 (1)

2.1S YSTEM V ABI (1)

2.2LSB (2)

3ELF文件格式 (2)

3.1简介 (2)

3.1.1目标文件中的数据表示 (2)

3.2目标文件格式 (3)

3.3ELF H EADER部分 (3)

3.4节区(S ECTIONS) (6)

3.4.1节区头部表格 (6)

3.4.2节区头部 (7)

3.4.3特殊节区 (10)

3.5字符串表(S TRING T ABLE) (12)

3.6符号表(S YMBOL T ABLE) (13)

3.6.1关于st_info的说明 (13)

3.6.2符号类型 (14)

3.6.3特殊的节区索引 (15)

3.6.4STN_UNDEF符号 (15)

3.6.5符号取值 (15)

3.7重定位信息 (16)

3.7.1重定位表项 (16)

3.7.2重定位类型 (17)

3.8程序加载和动态链接 (19)

3.8.1程序头部(Program Header) (19)

3.8.2程序加载 (21)

3.8.3动态链接 (23)

3.8.4全局偏移表(GOT) (27)

3.8.5过程链接表(PLT) (28)

3.8.6哈希表(Hash Table) (30)

3.8.7初始化和终止函数 (31)

3.9C库 (31)

3.9.1关于C库函数 (31)

3.9.2全局数据符号 (33)

图形目录

图1目标文件格式 (3)

图 2 ELF Header数据结构 (3)

图 3 节区头部数据结构 (7)

图 4 符号表项格式定义 (13)

图 5 符号表项的st_info字段合成 (13)

图 6 重定位表项的格式 (16)

图 7 程序头部数据结构 (19)

图 8 注释节区示例 (21)

图 9 可执行文件布局示例 (22)

图 10 动态节区符号结构 (24)

图 11绝对过程链接表 (28)

图 12 位置独立的过程链接表 (29)

图 13 符号哈希表的组织 (30)

可执行链接格式(Executable and Linking Format)最初是由UNIX系统实验室(UNIX System Laboratories,USL)开发并发布的,作为应用程序二进制接口(Application Binary Interface,ABI)的一部分。工具接口标准(Tool Interface Standards,TIS)委员会将还在发展的ELF标准选作为一种可移植的目标文件格式,可以在32位Intel体系结构上的很多操作系统中使用[1, 2]。

ELF标准的目的是为软件开发人员提供一组二进制接口定义,这些接口可以延伸到多种操作环境,从而减少重新编码、重新编译程序的需要。接口的内容包括目标模块格式、可执行文件格式以及调试记录信息与格式等。

TIS给出的Portable Formats Specification 1.1版本中主要针对三种不同类型的目标文件作了规定,并规定了程序加载与动态链接相关过程细节,给出了标准ANSI C和libc 例程必须提供的符号[1]。在该组织随后发布的Executable and Linking Format(ELF) Specification 1.2版本中则分如下三个部分,主要的不同点是对与操作系统相关的部分进行了重新组织:

Book I: Executable and Linking Format,描述ELF目标文件格式;

Book II: Processor Specific(Intel Architecture),描述ELF中与硬件相关的信息; Book III: Operating System Specific,描述ELF中与操作系统相关的部分,例如System V Release 4信息等。

2 相关标准

2.1 System V ABI

System V Application Binary Interface(ABI)为已编译的应用程序定义了系统接口,同时也为安装脚本支持提供了一个最小环境。其目的是为应用程序提供一个标准的二进制接口,使得这些程序能够运行在符合X/Open Commen Application Environment Specification, Issue 4.2和System V Interface Definition, Fourth Edition的操作系统上。二进制要包含与不同处理器体系结构相关的信息,所以ABI并不是只有一个规范,而是一个规范体系。System V ABI由两个部分组成:一个通用的部分,描述System V在所有硬件平台上都一致的接口[3];一个处理器相关的部分,描述特定于某个处理器体系结构的具体实现[4]。

System V ABI的主要参考标准包括:

目标系统处理器的体系结构手册

System V Interface Definition(接口定义), 第4版

IEEE POSIX 1003.1-1990标准操作系统规范

X/Open Common Application Environment Specification(CAE), Issue 4.2

International Standard, ISO/IEC 9899:1990(E), Programming Languages – C, 12/15/90.

X Window System?, X Version 11, Release 5, 图形用户界面规范

由于我们所关心的主要是Linux平台上目标文件的格式,所以Linux标准LSB (Linux Standard Base)也是重要的参考资料。LSB的目标是增强不同的Linux发布版本之间的兼容性,与ABI类似,也由两个部分组成:

gLSB(Generic LSB)适用于所有体系结构

archLSB(Architecture Specific LSB)特定某种体系结构的LSB

目前,LSB由SourceForge开放源码项目社区提供支持。

3 ELF文件格式

3.1 简介

目标文件有三种类型:

可重定位文件(Relocatable File)包含适合于与其他目标文件链接来创建可执行文件或者共享目标文件的代码和数据。

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

共享目标文件(Shared Object File)包含可在两种上下文中链接的代码和数据。首先链接编辑器可以将它和其它可重定位文件和共享目标文件一起处理,

生成另外一个目标文件。其次,动态链接器(Dynamic Linker)可能将它与某

个可执行文件以及其它共享目标一起组合,创建进程映像。

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

3.1.1 目标文件中的数据表示

目标文件格式支持 8 位字节/32位体系结构。不过这种格式是可以扩展的,目标文件因此以某些机器独立的格式表达某些控制数据,使得能够以一种公共的方式来识别和解释其内容。目标文件中的其它数据使用目标处理器的编码结构,而不管文件在何种机器上创建。

表 1 ELF中常用数据格式

名称大小对齐目的

Elf32_Addr44无符号程序地址

Elf32_Half22无符号中等整数

Elf32_Off44无符号文件偏移

Elf32_SWord44有符号大整数

Elf32_Word44无符号大整数

unsigned char11无符号小整数

目标文件中的所有数据结构都遵从“自然”大小和对齐规则。如果必要,数据结构可以包含显式的补齐,例如为了确保4字节对象按4字节边界对齐。数据对齐同样适用于

文件内部。

3.2 目标文件格式

目标文件既要参与程序链接又要参与程序执行。出于方便性和效率考虑,目标文件格式提供了两种并行视图,分别反映了这些活动的不同需求。

图1目标文件格式

链接视图执行视图

ELF 头部ELF 头部

程序头部表(可选)程序头部表

节区1

段1

...

节区n

段2

...

......

节区头部表节区头部表(可选)

文件开始处是一个ELF 头部(ELF Header),用来描述整个文件的组织。节区部分包含链接视图的大量信息:指令、数据、符号表、重定位信息等等。

程序头部表(Program Header Table),如果存在的话,告诉系统如何创建进程映像。用来构造进程映像的目标文件必须具有程序头部表,可重定位文件不需要这个表。

节区头部表(Section Heade Table)包含了描述文件节区的信息,每个节区在表中都有一项,每一项给出诸如节区名称、节区大小这类信息。用于链接的目标文件必须包含节区头部表,其他目标文件可以有,也可以没有这个表。

注意:尽管图中显示的各个组成部分是有顺序的,实际上除了 ELF 头部表以外,

其他节区和段都没有规定的顺序

3.3 ELF Header部分

文件的最开始几个字节给出如何解释文件的提示信息。这些信息独立于处理器,也独立于文件中的其余内容。ELF Header部分可以用下图中的数据结构表示:

图 2 ELF Header数据结构

#define EI_NIDENT 16

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;

其中,e_ident数组给出了ELF的一些标识信息,这个数组中不同下标的含义如表2所示:

表 2 e_ident[] 标识索引

名称取值目的

EI_MAG00文件标识

EI_MAG11文件标识

EI_MAG22文件标识

EI_MAG33文件标识

EI_CLASS4文件类

EI_DATA5数据编码

EI_VERSION6文件版本

EI_PAD7补齐字节开始处

EI_NIDENT16e_ident[]大小

这些索引访问包含以下数值的字节:

表 3 e_ident[]的内容说明

索引 说明

EI_MAG0 到EI_MAG3魔数(Magic Number),标志此文件是一个 ELF 目标文件。名称取值位置

EI_MAG00x7f e_ident[EI_MAG0]

EI_MAG1'E'e_ident[EI_MAG1]

EI_MAG2'L'e_ident[EI_MAG2]

EI_MAG3'F'e_ident[EI_MAG3]

EI_CLASS 标识文件的类别,或者说,容量。

名称取值位置

ELFCLASSNONE0非法类别

ELFCLASS32132 位目标

ELFCLASS64264 位目标

ELFCLASS32 支持虚存范围 4 GB。ELFCLASS64 是为 64 位预留的,不过文件中的其他内容都没有针对 64 位定义。

EI_DATA字节 e_ident[EI_DATA] 给出处理器特定数据的数据编码方式。

名称取值位置

ELFDATANONE0非法数据编码

ELFDATA2LSB1高位在前

ELFDATA2MSB2低位在前

EI_VERSION ELF 头部的版本号码,不前此值必须是 EV_CURRENT。

EI_PAD标记 e_ident 中未使用字节的开始。初始化为0。

某些目标文件控制结构可以增长,因为 ELF 头部能够给出它们的实际大小。如果目标文件格式确实发生改变,可能会发生控制结构比预期的大或者小的情况。在这种情况下,忽略这些信息是允许的。至于对“缺失”信息的处理方式则要依赖于上下文,如果定义了扩展的话,将会对这些做出规定。

注意:在 32 位 Intel 体系结构上要求:

1、标志

位置取值

e_ident[EI_CLASS]ELFCLASS32

e_ident[EI_DATA]ELFDATA2LSB

2、处理器标识(e_machine)成员必须是 EM_386。

ELF Header中各个字段的说明如表4:

表 4 ELF Header中各个字段的含义

成员 说明

e_ident 目标文件标识

e_type 目标文件类型:

名称取值含义

ET_NONE0未知目标文件格式

ET_REL1可重定位文件

ET_EXEC2可执行文件

ET_DYN3共享目标文件

ET_CORE4Core 文件(转储格式)

ET_LOPROC0xff00特定处理器文件

ET_HIPROC0xffff特定处理器文件

ET_LOPROC 和 ET_HIPROC 之间的取值用来标识与处理器相关的文件格式。

e_machine 给出文件的目标体系结构类型

名称取值含义

EM_NONE 0未指定

EM_M32 1AT&T WE 32100 EM_SPARC 2SPARC

EM_386 3Intel 80386

EM_68K 4Motorola 68000 EM_88K 5Motorola 88000

EM_860 7Intel 80860

EM_MIPS 8MIPS RS3000

其它值都是保留的。特定处理器的 ELF 名称会使用机器名来进行区分。

e_version 目标文件版本

名称取值含义

EV_NONE 0非法版本 E V_CURRENT 1当前版本

e_entry 程序入口的虚拟地址。如果目标文件没有程序入口,可以为0。

e_phoff 程序头部表格(Program Header Table)的偏移量(按字节计算)。如果文件没有程序头部表格,可以为0。

e_shoff 节区头部表格(Section Header Table)的偏移量(按字节计算)。如果文件没有节区头部表格,可以为0。

e_flags 保存与文件相关的,特定于处理器的标志。标志名称采用EF_machine_flag 的格式。

e_ehsize ELF 头部的大小(以字节计算)。

e_phentsize 程序头部表格的表项大小(按字节计算)。 e_phnum 程序头部表格的表项数目。可以为0。

e_shentsize 节区头部表格的表项大小(按字节计算)。 e_shnum 节区头部表格的表项数目。可以为0。

e_shstrndx 节区头部表格中与节区名称字符串表相关的表项的索引。如果文件没有节区名称字符串表,此参数可以为 SHN_UNDEF。

3.4 节区(Sections)

节区中包含目标文件中的所有信息,除了:ELF 头部、程序头部表格、节区头部表格。节区满足以下条件:

(1).目标文件中的每个节区都有对应的节区头部描述它,反过来,有节区头部不意

味着有节区。

(2).每个节区占用文件中一个连续字节区域(这个区域可能长度为0)。

(3).文件中的节区不能重叠,不允许一个字节存在于两个节区中的情况发生。

(4).目标文件中可能包含非活动空间(INACTIVE SPACE)。这些区域不属于任何

头部和节区,其内容未指定。

3.4.1 节区头部表格

ELF 头部中,e_shoff 成员给出从文件头到节区头部表格的偏移字节数;e_shnum 给出表格中条目数目;e_shentsize 给出每个项目的字节数。从这些信息中可以确切地定位节区的具体位置、长度。

节区头部表格中比较特殊的几个下标如下:

表 5 节区头部表格中的特殊下标

名称 取值 说明

SHN_UNDEF0标记未定义的、缺失的、不相关的,或者没有含义的

节区引用

SHN_LORESERVE OXFF00保留索引的下界

SHN_LOPROC0XFF00

SHN_HIPROC0XFF1F

保留给处理器特殊的语义

SHN_ABS OXFFF1包含对应引用量的绝对取值。这些值不会被重定位所影响

SHN_COMMON OXFFF2相对于此节区定义的符号是公共符号。如 FORTRAN 中 COMMON 或者未分配的 C 外部变量。

SHN_HIRESERVE0XFFFF保留索引的上界

介于 SHN_LORESERVE 和 SHN_HIRESERVE 之间的表项不会出现在节区头部表中。

3.4.2 节区头部

每个节区头部可以用如下数据结构描述:

图 3 节区头部数据结构

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;

对其中各个字段的解释如下:

表 6 节区头部字段说明

成员说明

sh_name 给出节区名称。是节区头部字符串表节区(Section Header String Table Section)的索引。名字是一个 NULL 结尾的字符串。

sh_type为节区的内容和语义进行分类。参见节区类型。

sh_flags节区支持 1 位形式的标志,这些标志描述了多种属性。

sh_addr 如果节区将出现在进程的内存映像中,此成员给出节区的第一个字节应处的位置。否则,此字段为0。

sh_offset 此成员的取值给出节区的第一个字节与文件头之间的偏移。不过,SHT_NOBITS 类型的节区不占用文件的空间,因此其 sh_offset 成员给出的是其概念性的偏移。

sh_size 此成员给出节区的长度(字节数)。除非节区的类型是SHT_NOBITS,否则节区占用文件中的 sh_size 字节。类型为

SHT_NOBITS 的节区长度可能非零,不过却不占用文件中的空间。

sh_link此成员给出节区头部表索引链接。其具体的解释依赖于节区类型。sh_info此成员给出附加信息,其解释依赖于节区类型。

sh_addralign 某些节区带有地址对齐约束。例如,如果一个节区保存一个doubleword,那么系统必须保证整个节区能够按双字对齐。sh_addr 对 sh_addralign 取模,结果必须为0。目前仅允许取值为 0 和 2 的幂次数。数值 0 和 1 表示节区没有对齐约束。

sh_entsize 某些节区中包含固定大小的项目,如符号表。对于这类节区,此成员给出每个表项的长度字节数。如果节区中并不包含固定长度表项的表格,此成员取值为0。

索引为零(SHN_UNDEF)的节区头部也是存在的,尽管此索引标记的是未定义的节区引用。这个节区的内容固定如下:

表 7 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 无表项

3.4.2.1节区类型—sh_type字段

节区类型定义如表8:

表 8 节区类型定义

名称取值说明

SHT_NULL0此值标志节区头部是非活动的,没有对应的节区。此节区头部中的其他成员取值无意义。

SHT_PROGBITS1此节区包含程序定义的信息,其格式和含义都由程序来解释。

SHT_SYMTAB 2此节区包含一个符号表。目前目标文件对每种类型的节区都只能包含一个,不过这个限制将来可能发生变化。

一般,SHT_SYMTAB 节区提供用于链接编辑(指 ld 而言)的符号,尽管也可用来实现动态链接。

SHT_STRTAB3此节区包含字符串表。目标文件可能包含多个字符串表节区。

SHT_RELA4此节区包含重定位表项,其中可能会有补齐内容(addend),例如 32 位目标文件中的 Elf32_Rela 类型。目标文件可能拥有多个重定位节区。

SHT_HASH5此节区包含符号哈希表。所有参与动态链接的目标都必须包含一个符号哈希表。目前,一个目标文件只能包含一个哈希表,不过此限制将来可能会解除。

SHT_DYNAMIC6此节区包含动态链接的信息。目前一个目标文件中只能包含一个动态节区,将来可能会取消这一限制。

SHT_NOTE7此节区包含以某种方式来标记文件的信息。

SHT_NOBITS8这种类型的节区不占用文件中的空间,其他方面和SHT_PROGBITS 相似。尽管此节区不包含任何字节,成员sh_offset 中还是会包含概念性的文件偏移

SHT_REL9此节区包含重定位表项,其中没有补齐(addends),例如 32 位目标文件中的 Elf32_rel 类型。目标文件中可以拥有多个重定位节区。

SHT_SHLIB10此节区被保留,不过其语义是未规定的。包含此类型节区的程序与 ABI 不兼容。

SHT_DYNSYM11作为一个完整的符号表,它可能包含很多对动态链接而言不必要的符号。因此,目标文件也可以包含一个 SHT_DYNSYM 节区,其中保存动态链接符号的一个最小集合,以节省空间。

SHT_LOPROC0X70000000

SHT_HIPROC OX7FFFFFFF

这一段(包括两个边界),是保留给处理器专用语义的。

SHT_LOUSER0X80000000此值给出保留给应用程序的索引下界。

SHT_HIUSER0X8FFFFFFF此值给出保留给应用程序的索引上界。

其它的节区类型是保留的。

3.4.2.2sh_flags 字段

sh_flags字段定义了一个节区中包含的内容是否可以修改、是否可以执行等信息。如果一个标志位被设置,则该位取值为1。未定义的各位都设置为0。

表 9 节区头部的 sh_flags字段取值

名称 取值

SHF_WRITE 0x1

SHF_ALLOC 0x2

SHF_EXECINSTR 0x4

SHF_MASKPROC 0xF0000000

其中已经定义了的各位含义如下:

SHF_WRITE: 节区包含进程执行过程中将可写的数据。

SHF_ALLOC: 此节区在进程执行过程中占用内存。某些控制节区并不出现于目标文件的内存映像中,对于那些节区,此位应设置为 0。

SHF_EXECINSTR: 节区包含可执行的机器指令。

SHF_MASKPROC: 所有包含于此掩码中的四位都用于处理器专用的语义。

3.4.2.3sh_link和sh_info字段

根据节区类型的不同,sh_link 和 sh_info 的具体含义也有所不同:

表 10 sh_link和sh_info字段解释

sh_type sh_link sh_info

SHT_DYNAMIC 此节区中条目所用到的字符串表格

的节区头部索引

SHT_HASH 此哈希表所适用的符号表的节区头

部索引

SHT_REL SHT_RELA 相关符号表的节区头部索引

重定位所适用的节区的

节区头部索引

SHT_SYMTAB SHT_DYNSYM 相关联的字符串表的节区头部索引

最后一个局部符号(绑

定 STB_LOCAL)的符

号表索引值加一

其它SHN_UNDEF0

3.4.3 特殊节区

很多节区中包含了程序和控制信息。下面的表中给出了系统使用的节区,以及它们的类型和属性。

表 11 常见特殊节区

名称 类型 属性 含义

.bss SHT_NOBITS SHF_ALLOC +

SHF_WRITE

包含将出现在程序的内存映像中的为初始

化数据。根据定义,当程序开始执行,系统

将把这些数据初始化为0。此节区不占用文

件空间。

.comment SHT_PROGBITS (无) 包含版本控制信息。

.data SHT_PROGBITS SHF_ALLOC + SHF_WRITE

.data1 SHT_PROGBITS SHF_ALLOC +

SHF_WRITE

这些节区包含初始化了的数据,将出现在程

序的内存映像中。

.debug SHT_PROGBITS (无) 此节区包含用于符号调试的信息。

.dynamic SHT_DYNAMIC 此节区包含动态链接信息。节区的属性将包含 SHF_ALLOC 位。是否 SHF_WRITE 位被设置取决于处理器。

.dynstr SHT_STRTAB SHF_ALLOC 此节区包含用于动态链接的字符串,大多数情况下这些字符串代表了与符号表项相关的名称。

.dynsym SHT_DYNSYM SHF_ALLOC 此节区包含了动态链接符号表。

.fini SHT_PROGBITS SHF_ALLOC +

SHF_EXECINSTR

此节区包含了可执行的指令,是进程终止代

码的一部分。程序正常退出时,系统将安排

执行这里的代码。

.got SHT_PROGBITS 此节区包含全局偏移表。

.hash SHT_HASH SHF_ALLOC 此节区包含了一个符号哈希表。

.init SHT_PROGBITS SHF_ALLOC +

SHF_EXECINSTR

此节区包含了可执行指令,是进程初始化代

码的一部分。当程序开始执行时,系统要在

开始调用主程序入口之前(通常指 C 语言

的 main 函数)执行这些代码。

.interp SHT_PROGBITS 此节区包含程序解释器的路径名。如果程序包含一个可加载的段,段中包含此节区,那么节区的属性将包含SHF_ALLOC 位,否则该位为0。

.line SHT_PROGBITS (无) 此节区包含符号调试的行号信息,其中描述了源程序与机器指令之间的对应关系。其内容是未定义的。

.note SHT_NOTE (无) 此节区中包含注释信息,有独立的格式。

.plt SHT_PROGBITS 此节区包含过程链接表(procedure linkage table)。

.rel name SHT_REL .rela name SHT_RELA 这些节区中包含了重定位信息。如果文件中包含可加载的段,段中有重定位内容,节区的属性将包含 SHF_ALLOC 位,否则该位置0。传统上 name 根据重定位所适用的节区给定。例如 .text 节区的重定位节区名字将是:.rel.text 或者 .rela.text。

.rodata SHT_PROGBITS SHF_ALLOC .rodata1 SHT_PROGBITS SHF_ALLOC 这些节区包含只读数据,这些数据通常参与进程映像的不可写段。

.shstrtab SHT_STRTAB 此节区包含节区名称。

.strtab SHT_STRTAB 此节区包含字符串,通常是代表与符号表项相关的名称。如果文件拥有一个可加载的段,段中包含符号串表,节区的属性将包含SHF_ALLOC 位,否则该位为0。

.symtab SHT_SYMTAB 此节区包含一个符号表。如果文件中包含一个可加载的段,并且该段中包含符号表,那么节区的属性中包含SHF_ALLOC 位,否则该位置为0。

.text SHT_PROGBITS SHF_ALLOC +

SHF_EXECINSTR

此节区包含程序的可执行指令。

在分析这些节区的时候,需要注意如下事项:

以“.”开头的节区名称是系统保留的。应用程序可以使用没有前缀的节区名称,以避免与系统节区冲突。

目标文件格式允许人们定义不在上述列表中的节区。

目标文件中也可以包含多个名字相同的节区。

保留给处理器体系结构的节区名称一般构成为:处理器体系结构名称简写 + 节区名称。

处理器名称应该与 e_machine 中使用的名称相同。例如 .FOO.psect 街区是由FOO 体系结构定义的 psect 节区。

另外,有些编译器对如上节区进行了扩展,这些已存在的扩展都使用约定俗成的名称,如:

.sdata

.tdesc

.sbss

.lit4

.lit8

.reginfo

.gptab

.liblist

.conflict

3.5 字符串表(String Table)

字符串表节区包含以NULL(ASCII码0)结尾的字符序列,通常称为字符串。ELF 目标文件通常使用字符串来表示符号和节区名称。对字符串的引用通常以字符串在字符串表中的下标给出。

一般,第一个字节(索引为0)定义为一个空字符串。类似的,字符串表的最后一个字节也定义为 NULL,以确保所有的字符串都以NULL结尾。索引为0的字符串在不同的上下文中可以表示无名或者名字为 NULL的字符串。

允许存在空的字符串表节区,其节区头部的sh_size成员应该为0。对空的字符串表而言,非0的索引值是非法的。

例如:对于各个节区而言,节区头部的sh_name成员包含其对应的节区头部字符串表节区的索引,此节区由ELF 头的e_shstrndx 成员给出。下图给出了包含 25 个字节的一个字符串表,以及与不同索引相关的字符串。

表 12 字符串表示例

索引+0+1+2+3+4+5+6+7+8+9

0\0n a m e.\0V a r

10i a b l e\0a b l e

20\0\0x x\0

表 12中包含的字符串如下:

索引 字符串

0(无)

1name.

7Variable

11able

16able

24(空字符串)

在使用、分析字符串表时,要注意以下几点:

字符串表索引可以引用节区中任意字节。

字符串可以出现多次

可以存在对子字符串的引用

同一个字符串可以被引用多次。

字符串表中也可以存在未引用的字符串。

3.6 符号表(Symbol Table)

目标文件的符号表中包含用来定位、重定位程序中符号定义和引用的信息。符号表索引是对此数组的索引。索引0表示表中的第一表项,同时也作为未定义符号的索引。

符号表项的格式如下:

图 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;

其中各个字段的含义说明如表 13:

表 13 符号表项字段

字段 说明

st_name 包含目标文件符号字符串表的索引,其中包含符号名的字符串表示。如果该值非0,则它表示了给出符号名的字符串表索引,否则符号表项没有名称。

注:外部 C 符号在 C 语言和目标文件的符号表中具有相同的名称。

st_value 此成员给出相关联的符号的取值。依赖于具体的上下文,它可能是一个绝对值、一个地址等等。

st_size 很多符号具有相关的尺寸大小。例如一个数据对象的大小是对象中包含的字节数。如果符号没有大小或者大小未知,则此成员为0。

st_info 此成员给出符号的类型和绑定属性。下面给出若干取值和含义的绑定关系。

st_other该成员当前包含0,其含义没有定义。

st_shndx 每个符号表项都以和其他节区间的关系的方式给出定义。此成员给出相关的节区头部表索引。某些索引具有特殊含义。

3.6.1 关于st_info的说明

st_info 中包含符号类型和绑定信息,操纵方式如:

图 5 符号表项的st_info字段合成

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

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

#define ELF32_ST_INFO(b, t) (((b)<<4) + ((t)&0xf))

从中可以看出,st_info的低四位表示符号绑定,用于确定链接可见性和行为。具体的绑定类型如:

表 14 符号的绑定类型

名称取值说明

STB_LOCAL0局部符号在包含该符号定义的目标文件以外不可见。相同名称的局部符号可以存在于多个文件中,互不影响。

STB_GLOBAL1全局符号对所有将组合的目标文件都是可见的。一个文件中对某个全局符号的定义将满足另一个文件对相同全局符号的未定义引用。

STB_WEAK2弱符号与全局符号类似,不过他们的定义优先级比较低。

STB_LOPROC13

STB_HIPROC15

处于这个范围的取值是保留给处理器专用语义的。

全局符号与弱符号之间的区别主要有两点:

(1).当链接编辑器组合若干可重定位的目标文件时,不允许对同名的

STB_GLOBAL 符号给出多个定义。

另一方面如果一个已定义的全局符号已经存在,出现一个同名的弱符号并

不会产生错误。链接编辑器尽关心全局符号,忽略弱符号。

类似地,如果一个公共符号(符号的 st_shndx 中包含 SHN_COMMON),那

么具有相同名称的弱符号出现也不会导致错误。链接编辑器会采纳公共定

义,而忽略弱定义。

(2).当链接编辑器搜索归档库(archive libraries)时,会提取那些包含未定

义全局符号的档案成员。成员的定义可以是全局符号,也可以是弱符号。

连接编辑器不会提取档案成员来满足未定义的弱符号。

未能解析的弱符号取值为0。

在每个符号表中,所有具有 STB_LOCAL 绑定的符号都优先于弱符号和全局符号。符号表节区中的 sh_info 头部成员包含第一个非局部符号的符号表索引。

3.6.2 符号类型

符号类型(ELF32_ST_TYPE)定义如下:

表 15 符号类型

名称取值说明

STT_NOTYPE0符号的类型没有指定

STT_OBJECT1符号与某个数据对象相关,比如一个变量、数组等等

STT_FUNC2符号与某个函数或者其他可执行代码相关

STT_SECTION3符号与某个节区相关。这种类型的符号表项主要用于重定位,通常具有 STB_LOCAL 绑定。

STT_FILE4传统上,符号的名称给出了与目标文件相关的源文件的名称。文件符号具有 STB_LOCAL 绑定,其节区索引是

SHN_ABS,并且它优先于文件的其他 STB_LOCAL 符号

(如果有的话)

STT_LOPROC13

此范围的符号类型值保留给处理器专用语义用途。

STT_HIPROC15

在共享目标文件中的函数符号(类型为 STT_FUNC)具有特别的重要性。当其他目标文件引用了来自某个共享目标中的函数时,链接编辑器自动为所引用的符号创建过程链接表项。类型不是 STT_FUNC 的共享目标符号不会自动通过过程链接表进行引用。

如果一个符号的取值引用了某个节区中的特定位置,那么它的节区索引成员(st_shndx)包含了其在节区头部表中的索引。当节区在重定位过程中被移动时,符号的取值也会随之变化,对符号的引用始终会“指向”程序中的相同位置。

3.6.3 特殊的节区索引

某些特殊的节区索引具有不同的语义:

SHN_ABS:符号具有绝对取值,不会因为重定位而发

生变化。

SHN_COMMON:符号标注了一个尚未分配的公共

块。符号的取值给出了对齐约束,与节区的 sh_addralign

成员类似。就是说,链接编辑器将为符号分配存储空间,

地址位于 st_value 的倍数处。符号的大小给出了所需要

的字节数。

SHN_UNDEF:此节区表索引值意味着符号没有定义。

当链接编辑器将此目标文件与其他定义了该符号的目标

文件进行组合时,此文件中对该符号的引用将被链接到实

际定义的位置。

3.6.4 STN_UNDEF符号

如上所述,符号表中下标为0(STN_UNDEF)的表项被保留。其中包含如下数值:

表 16 STN_UNDEF符号

名称取值说明

st_name 0 无名称

st_value 0 0

st_size 0

无大小

无类型,局部绑定

st_info 0

st_other 0 无附加信息

st_shndx 0 无节区

3.6.5 符号取值

不同的目标文件类型中符号表项对st_value成员具有不同的解释:

(1).在可重定位文件中,st_value 中遵从了节区索引为 SHN_COMMON 的符号

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/d218257901.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/d218257901.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/d218257901.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

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