ELF格式文件说明

简介:

Linux可执行文件为ELF格式,ELF格式文件主要分为以下几类:
1. 可重定位文件(Relocatable File),这类文件包含了代码和数据,可以被用来链接成可执行文件或共享目标文件,静态链接库也可以归为这一类,如.o文件。

2. 可执行文件(Executable File),这类文件包含了直接执行的程序,如/bin/bash等。

3. 共享目标文件(Shared Object File),链接器可以使用这种文件跟其他的可重定位文件和共享目标文件链接,产生新的目标文件;动态链接器可以将几个共享目标文件与可执行文件结合,作为进程映像的一部分来运行,如glibc*.so。

4. 核心转储文件(Core Dump File),当进程意外终止时,系统可以将该进程的地址空间内容及终止时的一些其他信息转储到核心转储文件。
image
如 上图所示,目标文件的开头是一个文件头,它描述了整个文件的文件属性,包括文件是否可执行,是静态链接还是动态链接及入口地址(如果 是可执行文件),目标硬件,目标操作系统的信息。文件头还包括一个段表,段表其实是一个描述文件中各个段的数组。段表描述了文件中各个段在文件中的偏移位 置及段的属性等。文件头后面就是各个段的内容,如代码段保存的是程序的指令,数据段保存的是程序里的一些变量等。

程序指令与数据分离成不同段的原因:

1. 当程序被装载后,数据和指令分别被映射到两个虚存区域。由于数据区域对于进程来说是可读写的,而指令区域对于进程来说是只读的,所以这两个虚存区域的权限可以被分别设置成可读写和只读。这样可以防止程序的指令被有意或无意地改写。

2. 对于现代的CPU来说,它们有着极为强大的缓存(Cache)体系。由于缓存在现代的计算机中地位非常重要,所以程序必须尽量提高缓存的命中率。指令区和数据区的分离有利于提高程序的局部性。现代CPU的缓存一般都被设计成数据缓存和指令缓存分离,所以程序的指令和数据被分开存放对CPU的缓存命中率提高有好处。

3. 也 是最重要的原因,就是当系统中运行着多个该程序的副本时,它们的指令都是一样的,所以内存中只须要保存一份改程序的指令部分。对于指令这种只读的区域来说 是这样,对于其他的只读数据也一样,比如很多程序里面带有的图标、图片、文本等资源也是属于可以共享的。当然每个副本进程的数据区域是不一样的,它们是进 程私有的。

ELF文件中常见的段
image
文件头

文件头的结构定义如下所示:

typedef struct {

unsigned char e_ident[16]; 

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;

可通过readelf –h hello.o来查看ELF文件的文件头

 ELF Header:

  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00

  Class:                            ELF32

  Data:                            2's complement, little endian

  Version:                          1 (current)

  OS/ABI:                          UNIX - System V

  ABI Version:                       0

  Type:                            REL (Relocatable file)

  Machine:                         Intel 80386

  Version:                          0x1

  Entry point address:                0x0

  Start of program headers:            0 (bytes into file)

  Start of section headers:             220 (bytes into file)

  Flags:                             0x0

  Size of this header:                  52 (bytes)

  Size of program headers:             0 (bytes)

  Number of program headers:         0

  Size of section headers:             40 (bytes)

  Number of section headers:         11

  Section header string table index:     8

l 段表

ELF文件中有很多段,段表就是保存这些段的基本属性的结构。段表是ELF文件中出文件头以为最重要的结构,它描述了ELF的各个段的信息,如每个段的名字,段的长度,在文件中的偏移,读写权限等。ELF文件的段结构就是由段表决定的,编译器,链接器和装载器都是通过段表来定位和访问各个段的属性的。

描述段的结构如下所示:

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;

可通过readelf –S *.o来查看ELF文件的段表

There are 11 section headers, starting at offset 0xdc:

 

Section Headers:

  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al

  [ 0]                   NULL            00000000 000000 000000 00      0   0  0

  [ 1] .text             PROGBITS        00000000 000034 00001c 00  AX  0   0  4

  [ 2] .rel.text         REL             00000000 000348 000010 08      9   1  4

  [ 3] .data             PROGBITS        00000000 000050 000000 00  WA  0   0  4

  [ 4] .bss              NOBITS          00000000 000050 000000 00  WA  0   0  4

  [ 5] .rodata           PROGBITS        00000000 000050 00000c 00   A  0   0  1

  [ 6] .comment          PROGBITS        00000000 00005c 00002d 00      0   0  1

  [ 7] .note.GNU-stack   PROGBITS        00000000 000089 000000 00      0   0  1

  [ 8] .shstrtab         STRTAB          00000000 000089 000051 00      0   0  1

  [ 9] .symtab           SYMTAB          00000000 000294 0000a0 10     10   8  4

  [10] .strtab           STRTAB          00000000 000334 000013 00      0   0  1

Key to Flags:

W (write), A (alloc), X (execute), M (merge), S (strings)

I (info), L (link order), G (group), x (unknown)

O (extra OS processing required) o (OS specific), p (processor specific)

l 重定位表

从上面的输出可以看到,ELF文件中包含.rel.text的段,它是一个重定位表。链接器在处理目标文件时,需要对目标文件中某些部位进行重定位,及代码段和数据段中那些对绝对地址引用的位置。这些重定位的信息都记录在ELF文件的重定位表里面,对于每个需要重定位的代码段或数据段,都会有相应的重定位表。

l 字符串表

ELF文件中用到了很多字符串,比如段名,变量名等。因为字符串的长度往往不是固定的,故难以用固定的结构表示。常见的做法是把字符串集中起来存放到一个表,然后使用字符串在表中的偏移来引用字符串。如下所示:
image

通过该方法,在ELF文件中引用字符串只需要给出一个数字下标(偏移)即可,如上表所示:偏移0对应空字符串,偏移1对应helloworld,偏移6对应world,偏移12对应myvariable等而不用考虑字符串的长度,字符串表在ELF文件中也以段的形式保存,如.strtab(字符串表), .shstrtab(段表字符串表),前者用来保存普通的字符串,如符号的名字;后者用来保存段表中用到的字符串如段名。

一个典型的ELF目标文件的结构如下图(转自51.com)所示:
image

目录
相关文章
|
测试技术
elf格式转换为hex格式文件的两种方法
这周工作终于不太忙了,可以写点笔记总结一下了。 之前的文章如何在Keil-MDK开发环境生成Bin格式文件,介绍了如何在Keil开发环境使用fromelf软件,将生成的axf文件转换为bin文件,这次我们再来介绍一下如何将elf文件转换为hex文件。
1720 0
|
6月前
|
存储 安全 Linux
ELF文件格式
ELF文件格式
69 0
|
12月前
|
Unix
ELF文件格式入门
ELF(Executable and Linking Format),即“可执行可连接格式”,最初由 UNIX系统实验室做为应用程序二进制接口(ABI)的一部分而制定和发布。简单说就是一种文件格式。
ELF文件格式入门
|
Linux 数据安全/隐私保护
使用ofd6x工具解析elf文件
使用ofd6x工具解析elf文件
142 0
使用ofd6x工具解析elf文件
|
存储 编译器 Linux
BIN、HEX、AXF、ELF文件格式有什么区别
BIN、HEX、AXF、ELF文件格式有什么区别
193 0
BIN、HEX、AXF、ELF文件格式有什么区别
|
架构师 Android开发
【Android 逆向】ELF 文件格式 ( ELF 文件类型 | ELF 文件对应 CPU 架构 | ELF 目标文件版本 | 可执行程序起始地址 )
【Android 逆向】ELF 文件格式 ( ELF 文件类型 | ELF 文件对应 CPU 架构 | ELF 目标文件版本 | 可执行程序起始地址 )
156 0
【Android 逆向】ELF 文件格式 ( ELF 文件类型 | ELF 文件对应 CPU 架构 | ELF 目标文件版本 | 可执行程序起始地址 )
|
编译器 Android开发
【Android 逆向】ELF 文件格式 ( ELF 文件头 | ELF 文件头标志 | ELF 文件位数 | ELF 文件大小端格式 )(二)
【Android 逆向】ELF 文件格式 ( ELF 文件头 | ELF 文件头标志 | ELF 文件位数 | ELF 文件大小端格式 )(二)
143 0
【Android 逆向】ELF 文件格式 ( ELF 文件头 | ELF 文件头标志 | ELF 文件位数 | ELF 文件大小端格式 )(二)
|
Android开发
【Android 逆向】ELF 文件格式 ( ELF 文件头 | ELF 文件头标志 | ELF 文件位数 | ELF 文件大小端格式 )(一)
【Android 逆向】ELF 文件格式 ( ELF 文件头 | ELF 文件头标志 | ELF 文件位数 | ELF 文件大小端格式 )(一)
115 0
【Android 逆向】ELF 文件格式 ( ELF 文件头 | ELF 文件头标志 | ELF 文件位数 | ELF 文件大小端格式 )(一)
|
编译器 Linux Android开发
【Android 逆向】ELF 文件格式 ( ELF 文件简介 | ELF 文件结构 )
【Android 逆向】ELF 文件格式 ( ELF 文件简介 | ELF 文件结构 )
268 0
【Android 逆向】ELF 文件格式 ( ELF 文件简介 | ELF 文件结构 )