ELF文件

  • Post author:
  • Post category:其他



ELF(Executable and Linking Format)是一种对象文件的格式。他用于描述下列三种文件:


可重定向对象文件


典型的是gcc -c main.c main.o  其中main.o就是可重定向对象文件


可执行对象文件


典型的gcc main.o -o main main文件就是可执行对象文件


可动态链接共享对象文件


常用的pthread.so等就是可动态链接共享对象文件



上面都是对象文件,利用连接器,可重定向对象文件可以生成可执行对象文件或者可动态链接共享对象文件。


整个ELF分为4个部分:

ELF header

program header table

sections/segments

section header table

以下面程序为例:

	.section .data
data_items:
	.long 3,4,5,6,7,8
hellostring:
	.ascii "hello world"
	.section .text
	.globl _start
_start:
	movl $1,eax
	movl $4,ebx
	int $0x80

可生成对象文件和可执行文件

as main.s -o main.o

ld main.o -o main

使用工具readelf可以查看这两个文件的结构

可重定向对象文件

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:          144 (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:         7
  Section header string table index: 4


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 00000c 00  AX  0   0  4
  [ 2] .data             PROGBITS        00000000 000040 000023 00  WA  0   0  4
  [ 3] .bss              NOBITS          00000000 000064 000000 00  WA  0   0  4
  [ 4] .shstrtab         STRTAB          00000000 000064 00002c 00      0   0  1
  [ 5] .symtab           SYMTAB          00000000 0001a8 000070 10      6   6  4
  [ 6] .strtab           STRTAB          00000000 000218 00001f 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)


There are no section groups in this file.


There are no program headers in this file.


There are no relocations in this file.


There are no unwind sections in this file.


Symbol table '.symtab' contains 7 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00000000     0 SECTION LOCAL  DEFAULT    1 
     2: 00000000     0 SECTION LOCAL  DEFAULT    2 
     3: 00000000     0 SECTION LOCAL  DEFAULT    3 
     4: 00000000     0 NOTYPE  LOCAL  DEFAULT    2 data_items
     5: 00000018     0 NOTYPE  LOCAL  DEFAULT    2 hellostring
     6: 00000000     0 NOTYPE  GLOBAL DEFAULT    1 _start


分析ELF Headers:

Entry point address:               0x0

这里表明入口地址为0,因此可以用作重定向。

  Start of program headers:          0 (bytes into file)
  Start of section headers:          144 (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:         7

00000040  03 00 00 00 04 00 00 00  05 00 00 00 06 00 00 00  |................|
00000050  07 00 00 00 08 00 00 00  68 65 6c 6c 6f 20 77 6f  |........hello wo|
00000060  72 6c 64 00 00 2e 73 79  6d 74 61 62 00 2e 73 74  |rld...symtab..st|

对应之前看到的.data段信息:起始地址0x40,长度为0x23。可以看到所有的被初始化的全局数据。

readelf -a main.o最后输出了.symtab符号表。每个符号代表着程序中的函数名称或者变量名。可以看到是否全局/局部以及所属段ID。

例如hellostring为局部变量,所在段序号为2,代表.data段。

可在偏移144找到section headers,大小为40字节<p>program headers为空,这是因为program header只在可执行文件中生成。

分析Section可以看到7个secions:

.text 程序段

.data     被初始化的全局数据

.bsss    未被初始化的全局数据

.shstrtab 段表字符串表段(Section Header String Table)

.symtab   符号表段(变量、函数)

.strtab     字符串段(变量名,函数名字符串)

每个段列出了一些信息:

Name: 名称

Type:类型

Addr:虚拟地址

Off:段内偏移

Size:此段大小

ES:有些段有,例如.symtab存储了程序符号表,ES为10代表符号表中每行占用10字节

Flg:标志位输出有说明,一般来说W代表数据,X代表程序,A代表程序运行时需要分配内存。可以看到.data为WA,说明这是个数据区,且程序加载时必须分配内存存储初始化数据。.bss为W说明是数据区,但程序加载时不用分配内存。

Lk/inf:和特定Section相关

Al:段内地址对齐

使用HexDump可以查看对应段内的数据,例如:hexdump -C main.o

可执行对象文件

htm@htm:~/test/testassemble$ readelf -a main
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:                              EXEC (Executable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x8048074
  Start of program headers:          52 (bytes into file)
  Start of section headers:          204 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         2
  Size of section headers:           40 (bytes)
  Number of section headers:         6
  Section header string table index: 3

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        08048074 000074 00000c 00  AX  0   0  4
  [ 2] .data             PROGBITS        08049080 000080 000023 00  WA  0   0  4
  [ 3] .shstrtab         STRTAB          00000000 0000a3 000027 00      0   0  1
  [ 4] .symtab           SYMTAB          00000000 0001bc 000090 10      5   5  4
  [ 5] .strtab           STRTAB          00000000 00024c 000037 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

There are no section groups in this file.

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x08048000 0x08048000 0x00080 0x00080 R E 0x1000
  LOAD           0x000080 0x08049080 0x08049080 0x00023 0x00023 RW  0x1000

 Section to Segment mapping:
  Segment Sections...
   00     .text 
   01     .data 

There is no dynamic section in this file.

There are no relocations in this file.

There are no unwind sections in this file.

Symbol table '.symtab' contains 9 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 08048074     0 SECTION LOCAL  DEFAULT    1 
     2: 08049080     0 SECTION LOCAL  DEFAULT    2 
     3: 08049080     0 NOTYPE  LOCAL  DEFAULT    2 data_items
     4: 08049098     0 NOTYPE  LOCAL  DEFAULT    2 hellostring
     5: 08048074     0 NOTYPE  GLOBAL DEFAULT    1 _start
     6: 080490a3     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
     7: 080490a3     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
     8: 080490a4     0 NOTYPE  GLOBAL DEFAULT  ABS _end

No version information found in this file.

比较之前的可重定向对象文件:

Entry point address:               0x8048074

这里可执行入口变为了一个有效的虚拟地址。

  Size of program headers:           32 (bytes)
  Number of program headers:         2

因为这是可执行文件,所以需要有program headers,它描述了两个Segments

Seg1:0x08048000->0x08048000+0x80   可读可执行(里面放置了.text段)

Seg2:0x08049080->0x08049080+0x23   可读可写     (里面放置了.data段)

(这里的Segments是具有共同属性的Sections的集合,如RE/RW等)

从上面还可以看到虽然整个main文件大小不到1k,但占用的内存范围确是0x08048000->0x08049080+0x23。原因是,Segments是基于页存储的,因此必须是4K字节对齐(MMU的限制,从Segments的Align信息也可以看出)。

bss段被去掉了,因为这个段的长度为0

其他的段的加载地址也变为了有效的虚拟地址。



版权声明:本文为king523103原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。