首页 > *nix技术, Shell命令 > 理解ELF文件

理解ELF文件

2012年1月13日 发表评论 阅读评论 4,030 次浏览

关于ELF(Executable and Linking Format)文件格式的基本介绍无需多说,这里直接进入正题。ELF格式文件有好几种类型:
1,可重定位文件(Relocatable file),也就是通常所说的编译中间文件,这些文件包含有代码和数据,但尚未进行形成最终的可执行文件或库。比如如下的test.o文件,另外内核模块.ko也属于此类ELF。

[root@localhost elf]# cat test.c 
/* test.c */
#include<stdio.h>
int global_data = 4;
int global_data_2;
int
main (int argc, char **argv)
{
  int local_data = 3;
  printf ("Hello Worldn");
  printf ("global_data = %dn", global_data);
  printf ("global_data_2 = %dn", global_data_2);
  printf ("local_data = %dn", local_data);
  return (0);
}
[root@localhost elf]# ls
test.c
[root@localhost elf]# gcc -c test.c 
[root@localhost elf]# ls
test.c  test.o
[root@localhost elf]# 

2,可执行文件(Executable file)。

[root@localhost elf]# gcc -o test test.c 
[root@localhost elf]# ls
test  test.c  test.o

3,共享对象文件(Shared object file),静态链接库、动态链接库。

[root@localhost elf]# ls /lib64/*.so
/lib64/ld-2.5.so
/lib64/libdevmapper.so
/lib64/libnss_files-2.5.so
/lib64/libacl.so
/lib64/libdl-2.5.so
...

通过readelf命令可以判断一个ELF文件的类型:

[root@localhost elf]# readelf -h test.o
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          440 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           64 (bytes)
  Number of section headers:         13
  Section header string table index: 10
[root@localhost elf]# readelf -h test
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x4003c0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          2792 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         8
  Size of section headers:           64 (bytes)
  Number of section headers:         29
  Section header string table index: 26
[root@localhost elf]# readelf -h /lib64/ld-2.5.so 
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x3734600a70
  Start of program headers:          64 (bytes into file)
  Start of section headers:          137624 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         6
  Size of section headers:           64 (bytes)
  Number of section headers:         28
  Section header string table index: 27
[root@localhost elf]# 

另外一个命令file同样可以检查文件类型,不够提供的信息比较简单:

[root@localhost elf]# file test.o
test.o: ELF 64-bit LSB relocatable, AMD x86-64, version 1 (SYSV), not stripped
[root@localhost elf]# file test
test: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped
[root@localhost elf]# file /lib64/ld-2.5.so 
/lib64/ld-2.5.so: ELF 64-bit LSB shared object, AMD x86-64, version 1 (SYSV), not stripped
[root@localhost elf]# 

从可执行程序test的ELF头信息里可以看到一些这样的信息:
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
64位
Data: 2’s complement, little endian
Version: 1 (current)
OS/ABI: UNIX – System V
ABI Version: 0
Type: EXEC (Executable file)
可执行文件类型
Machine: Advanced Micro Devices X86-64
ATI公司 X68-64架构
Version: 0x1
Entry point address: 0x4003c0
程序执行入口地址,并不是main函数的地址,而是_strat地址:
[root@localhost elf]# addr2line -e test -f 0x4003c0
_start
??:0

Start of program headers: 64 (bytes into file)
Start of section headers: 2792 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 8
8个segment。
Size of section headers: 64 (bytes)
Number of section headers: 29
29个section。
Section header string table index: 26
section和segment是从不同角度看得出来的逻辑结构,从链接(Link)的角度看,一个二进制文件由多个包含同等性质内容的区域,比如.text,.rel.text,.data,.rodata等,每一个区域被称为一个section;而从执行(Execution)的角度看,二进制文件在执行时将被映射加载到不同的虚拟内存区域(virtual memory area),这每一个区域称为一个segment,一个segment会包含一个或多个section。
看两张示意图(来之网络,见最后链接):


通过readelf的-S参数可以查看这些section,其中的.text section即为代码段,所以Flags标记带有可执行(X):

[root@localhost elf]# readelf -S test
There are 29 section headers, starting at offset 0xae8:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .interp           PROGBITS         0000000000400200  00000200
       000000000000001c  0000000000000000   A       0     0     1
...
  [10] .init             PROGBITS         0000000000400370  00000370
       0000000000000018  0000000000000000  AX       0     0     4
  [11] .plt              PROGBITS         0000000000400388  00000388
       0000000000000030  0000000000000010  AX       0     0     4
  [12] .text             PROGBITS         00000000004003c0  000003c0
       0000000000000218  0000000000000000  AX       0     0     16
  [13] .fini             PROGBITS         00000000004005d8  000005d8
       000000000000000e  0000000000000000  AX       0     0     4
  [14] .rodata           PROGBITS         00000000004005e8  000005e8
       0000000000000054  0000000000000000   A       0     0     8
...
  [23] .data             PROGBITS         00000000006008e0  000008e0
       0000000000000008  0000000000000000  WA       0     0     4
  [24] .bss              NOBITS           00000000006008e8  000008e8
       0000000000000010  0000000000000000  WA       0     0     8
...
  [28] .strtab           STRTAB           0000000000000000  000018a0
       000000000000025a  0000000000000000           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)
[root@localhost elf]# 

利用objdump命令对.text section进行反汇编:

[root@localhost elf]# objdump -d -j .text test

test:     file format elf64-x86-64

Disassembly of section .text:

00000000004003c0 <_start>:
  4003c0:	31 ed                	xor    %ebp,%ebp
  4003c2:	49 89 d1             	mov    %rdx,%r9
  4003c5:	5e                   	pop    %rsi
  4003c6:	48 89 e2             	mov    %rsp,%rdx
  4003c9:	48 83 e4 f0          	and    $0xfffffffffffffff0,%rsp
  4003cd:	50                   	push   %rax
  4003ce:	54                   	push   %rsp
  4003cf:	49 c7 c0 00 05 40 00 	mov    $0x400500,%r8
  4003d6:	48 c7 c1 10 05 40 00 	mov    $0x400510,%rcx
  4003dd:	48 c7 c7 98 04 40 00 	mov    $0x400498,%rdi
  4003e4:	e8 bf ff ff ff       	callq  4003a8 <__libc_start_main@plt>
  4003e9:	f4                   	hlt    
  4003ea:	90                   	nop    
  4003eb:	90                   	nop    

00000000004003ec <call_gmon_start>:
  4003ec:	48 83 ec 08          	sub    $0x8,%rsp
  4003f0:	48 8b 05 b9 04 20 00 	mov    2098361(%rip),%rax        # 6008b0 <_DYNAMIC+0x190>
  4003f7:	48 85 c0             	test   %rax,%rax
  4003fa:	74 02                	je     4003fe <call_gmon_start+0x12>
  4003fc:	ff d0                	callq  *%rax
  4003fe:	48 83 c4 08          	add    $0x8,%rsp
  400402:	c3                   	retq   
  400403:	90                   	nop    
  400404:	90                   	nop    
  400405:	90                   	nop    
  400406:	90                   	nop    
  400407:	90                   	nop    
  400408:	90                   	nop    
  400409:	90                   	nop    
  40040a:	90                   	nop    
  40040b:	90                   	nop    
  40040c:	90                   	nop    
  40040d:	90                   	nop    
  40040e:	90                   	nop    
  40040f:	90                   	nop    

0000000000400410 <__do_global_dtors_aux>:
  400410:	55                   	push   %rbp
  400411:	48 89 e5             	mov    %rsp,%rbp
  400414:	53                   	push   %rbx
  400415:	48 83 ec 08          	sub    $0x8,%rsp
  400419:	80 3d d0 04 20 00 00 	cmpb   $0x0,2098384(%rip)        # 6008f0 <completed.6145>
  400420:	75 44                	jne    400466 <__do_global_dtors_aux+0x56>
  400422:	b8 10 07 60 00       	mov    $0x600710,%eax
  400427:	48 2d 08 07 60 00    	sub    $0x600708,%rax
  40042d:	48 c1 f8 03          	sar    $0x3,%rax
  400431:	48 8d 58 ff          	lea    0xffffffffffffffff(%rax),%rbx
  400435:	48 8b 05 ac 04 20 00 	mov    2098348(%rip),%rax        # 6008e8 <__bss_start>
  40043c:	48 39 c3             	cmp    %rax,%rbx
  40043f:	76 1e                	jbe    40045f <__do_global_dtors_aux+0x4f>
  400441:	48 83 c0 01          	add    $0x1,%rax
  400445:	48 89 05 9c 04 20 00 	mov    %rax,2098332(%rip)        # 6008e8 <__bss_start>
  40044c:	ff 14 c5 08 07 60 00 	callq  *0x600708(,%rax,8)
  400453:	48 8b 05 8e 04 20 00 	mov    2098318(%rip),%rax        # 6008e8 <__bss_start>
  40045a:	48 39 c3             	cmp    %rax,%rbx
  40045d:	77 e2                	ja     400441 <__do_global_dtors_aux+0x31>
  40045f:	c6 05 8a 04 20 00 01 	movb   $0x1,2098314(%rip)        # 6008f0 <completed.6145>
  400466:	48 83 c4 08          	add    $0x8,%rsp
  40046a:	5b                   	pop    %rbx
  40046b:	c9                   	leaveq 
  40046c:	c3                   	retq   
  40046d:	0f 1f 00             	nopl   (%rax)

0000000000400470 <frame_dummy>:
  400470:	55                   	push   %rbp
  400471:	48 83 3d 9f 02 20 00 	cmpq   $0x0,2097823(%rip)        # 600718 <__JCR_END__>
  400478:	00 
  400479:	48 89 e5             	mov    %rsp,%rbp
  40047c:	74 16                	je     400494 <frame_dummy+0x24>
  40047e:	b8 00 00 00 00       	mov    $0x0,%eax
  400483:	48 85 c0             	test   %rax,%rax
  400486:	74 0c                	je     400494 <frame_dummy+0x24>
  400488:	bf 18 07 60 00       	mov    $0x600718,%edi
  40048d:	49 89 c3             	mov    %rax,%r11
  400490:	c9                   	leaveq 
  400491:	41 ff e3             	jmpq   *%r11
  400494:	c9                   	leaveq 
  400495:	c3                   	retq   
  400496:	90                   	nop    
  400497:	90                   	nop    

0000000000400498 <main>:
  400498:	55                   	push   %rbp
  400499:	48 89 e5             	mov    %rsp,%rbp
  40049c:	48 83 ec 20          	sub    $0x20,%rsp
  4004a0:	89 7d ec             	mov    %edi,0xffffffffffffffec(%rbp)
  4004a3:	48 89 75 e0          	mov    %rsi,0xffffffffffffffe0(%rbp)
  4004a7:	c7 45 fc 03 00 00 00 	movl   $0x3,0xfffffffffffffffc(%rbp)
  4004ae:	bf f8 05 40 00       	mov    $0x4005f8,%edi
  4004b3:	b8 00 00 00 00       	mov    $0x0,%eax
  4004b8:	e8 db fe ff ff       	callq  400398 <printf@plt>
  4004bd:	8b 35 21 04 20 00    	mov    2098209(%rip),%esi        # 6008e4 <global_data>
  4004c3:	bf 05 06 40 00       	mov    $0x400605,%edi
  4004c8:	b8 00 00 00 00       	mov    $0x0,%eax
  4004cd:	e8 c6 fe ff ff       	callq  400398 <printf@plt>
  4004d2:	8b 35 1c 04 20 00    	mov    2098204(%rip),%esi        # 6008f4 <global_data_2>
  4004d8:	bf 17 06 40 00       	mov    $0x400617,%edi
  4004dd:	b8 00 00 00 00       	mov    $0x0,%eax
  4004e2:	e8 b1 fe ff ff       	callq  400398 <printf@plt>
  4004e7:	8b 75 fc             	mov    0xfffffffffffffffc(%rbp),%esi
  4004ea:	bf 2b 06 40 00       	mov    $0x40062b,%edi
  4004ef:	b8 00 00 00 00       	mov    $0x0,%eax
  4004f4:	e8 9f fe ff ff       	callq  400398 <printf@plt>
  4004f9:	b8 00 00 00 00       	mov    $0x0,%eax
  4004fe:	c9                   	leaveq 
  4004ff:	c3                   	retq   

0000000000400500 <__libc_csu_fini>:
  400500:	f3 c3                	repz retq 
  400502:	0f 1f 80 00 00 00 00 	nopl   0x0(%rax)
  400509:	0f 1f 80 00 00 00 00 	nopl   0x0(%rax)

0000000000400510 <__libc_csu_init>:
  400510:	4c 89 64 24 e0       	mov    %r12,0xffffffffffffffe0(%rsp)
  400515:	4c 89 6c 24 e8       	mov    %r13,0xffffffffffffffe8(%rsp)
  40051a:	4c 8d 25 d3 01 20 00 	lea    2097619(%rip),%r12        # 6006f4 <__fini_array_end>
  400521:	4c 89 74 24 f0       	mov    %r14,0xfffffffffffffff0(%rsp)
  400526:	4c 89 7c 24 f8       	mov    %r15,0xfffffffffffffff8(%rsp)
  40052b:	49 89 f6             	mov    %rsi,%r14
  40052e:	48 89 5c 24 d0       	mov    %rbx,0xffffffffffffffd0(%rsp)
  400533:	48 89 6c 24 d8       	mov    %rbp,0xffffffffffffffd8(%rsp)
  400538:	48 83 ec 38          	sub    $0x38,%rsp
  40053c:	41 89 ff             	mov    %edi,%r15d
  40053f:	49 89 d5             	mov    %rdx,%r13
  400542:	e8 29 fe ff ff       	callq  400370 <_init>
  400547:	48 8d 05 a6 01 20 00 	lea    2097574(%rip),%rax        # 6006f4 <__fini_array_end>
  40054e:	49 29 c4             	sub    %rax,%r12
  400551:	49 c1 fc 03          	sar    $0x3,%r12
  400555:	4d 85 e4             	test   %r12,%r12
  400558:	74 1e                	je     400578 <__libc_csu_init+0x68>
  40055a:	31 ed                	xor    %ebp,%ebp
  40055c:	48 89 c3             	mov    %rax,%rbx
  40055f:	90                   	nop    
  400560:	48 83 c5 01          	add    $0x1,%rbp
  400564:	4c 89 ea             	mov    %r13,%rdx
  400567:	4c 89 f6             	mov    %r14,%rsi
  40056a:	44 89 ff             	mov    %r15d,%edi
  40056d:	ff 13                	callq  *(%rbx)
  40056f:	48 83 c3 08          	add    $0x8,%rbx
  400573:	49 39 ec             	cmp    %rbp,%r12
  400576:	75 e8                	jne    400560 <__libc_csu_init+0x50>
  400578:	48 8b 5c 24 08       	mov    0x8(%rsp),%rbx
  40057d:	48 8b 6c 24 10       	mov    0x10(%rsp),%rbp
  400582:	4c 8b 64 24 18       	mov    0x18(%rsp),%r12
  400587:	4c 8b 6c 24 20       	mov    0x20(%rsp),%r13
  40058c:	4c 8b 74 24 28       	mov    0x28(%rsp),%r14
  400591:	4c 8b 7c 24 30       	mov    0x30(%rsp),%r15
  400596:	48 83 c4 38          	add    $0x38,%rsp
  40059a:	c3                   	retq   
  40059b:	90                   	nop    
  40059c:	90                   	nop    
  40059d:	90                   	nop    
  40059e:	90                   	nop    
  40059f:	90                   	nop    

00000000004005a0 <__do_global_ctors_aux>:
  4005a0:	55                   	push   %rbp
  4005a1:	48 89 e5             	mov    %rsp,%rbp
  4005a4:	53                   	push   %rbx
  4005a5:	bb f8 06 60 00       	mov    $0x6006f8,%ebx
  4005aa:	48 83 ec 08          	sub    $0x8,%rsp
  4005ae:	48 8b 05 43 01 20 00 	mov    2097475(%rip),%rax        # 6006f8 <__CTOR_LIST__>
  4005b5:	48 83 f8 ff          	cmp    $0xffffffffffffffff,%rax
  4005b9:	74 14                	je     4005cf <__do_global_ctors_aux+0x2f>
  4005bb:	0f 1f 44 00 00       	nopl   0x0(%rax,%rax,1)
  4005c0:	48 83 eb 08          	sub    $0x8,%rbx
  4005c4:	ff d0                	callq  *%rax
  4005c6:	48 8b 03             	mov    (%rbx),%rax
  4005c9:	48 83 f8 ff          	cmp    $0xffffffffffffffff,%rax
  4005cd:	75 f1                	jne    4005c0 <__do_global_ctors_aux+0x20>
  4005cf:	48 83 c4 08          	add    $0x8,%rsp
  4005d3:	5b                   	pop    %rbx
  4005d4:	c9                   	leaveq 
  4005d5:	c3                   	retq   
  4005d6:	90                   	nop    
  4005d7:	90                   	nop    
[root@localhost elf]# 

其它section同样可以利用objdump进行反汇编查看,比如查看.data section的已初始化变量(对比源文件中的全局变量int global_data = 4;):

[root@localhost elf]# objdump -d -j .data test

test:     file format elf64-x86-64

Disassembly of section .data:

00000000006008e0 <__data_start>:
  6008e0:	00 00                	add    %al,(%rax)
	...

00000000006008e4 <global_data>:
  6008e4:	04 00 00 00                                         ....
[root@localhost elf]# 

查看.bss section的未初始化变量(对比源文件中的全局变量int global_data_2;):

[root@localhost elf]# objdump -d -j .bss test

test:     file format elf64-x86-64

Disassembly of section .bss:

00000000006008e8 <dtor_idx.6147>:
	...

00000000006008f0 <completed.6145>:
  6008f0:	00 00 00 00                                         ....

00000000006008f4 <global_data_2>:
  6008f4:	00 00 00 00                                         ....
[root@localhost elf]# 

利用readelf -s和readelf -l查看符合表以及segment分布情况:

[root@localhost elf]# readelf -s test

Symbol table '.dynsym' contains 4 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000   162 FUNC    GLOBAL DEFAULT  UND printf@GLIBC_2.2.5 (2)
     2: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     3: 0000000000000000   421 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.2.5 (2)

Symbol table '.symtab' contains 69 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000400200     0 SECTION LOCAL  DEFAULT    1 
     2: 000000000040021c     0 SECTION LOCAL  DEFAULT    2 
     3: 0000000000400240     0 SECTION LOCAL  DEFAULT    3 
     4: 0000000000400260     0 SECTION LOCAL  DEFAULT    4 
     5: 00000000004002c0     0 SECTION LOCAL  DEFAULT    5 
     6: 0000000000400300     0 SECTION LOCAL  DEFAULT    6 
     7: 0000000000400308     0 SECTION LOCAL  DEFAULT    7 
     8: 0000000000400328     0 SECTION LOCAL  DEFAULT    8 
     9: 0000000000400340     0 SECTION LOCAL  DEFAULT    9 
    10: 0000000000400370     0 SECTION LOCAL  DEFAULT   10 
    11: 0000000000400388     0 SECTION LOCAL  DEFAULT   11 
    12: 00000000004003c0     0 SECTION LOCAL  DEFAULT   12 
    13: 00000000004005d8     0 SECTION LOCAL  DEFAULT   13 
    14: 00000000004005e8     0 SECTION LOCAL  DEFAULT   14 
    15: 000000000040063c     0 SECTION LOCAL  DEFAULT   15 
    16: 0000000000400660     0 SECTION LOCAL  DEFAULT   16 
    17: 00000000006006f8     0 SECTION LOCAL  DEFAULT   17 
    18: 0000000000600708     0 SECTION LOCAL  DEFAULT   18 
    19: 0000000000600718     0 SECTION LOCAL  DEFAULT   19 
    20: 0000000000600720     0 SECTION LOCAL  DEFAULT   20 
    21: 00000000006008b0     0 SECTION LOCAL  DEFAULT   21 
    22: 00000000006008b8     0 SECTION LOCAL  DEFAULT   22 
    23: 00000000006008e0     0 SECTION LOCAL  DEFAULT   23 
    24: 00000000006008e8     0 SECTION LOCAL  DEFAULT   24 
    25: 0000000000000000     0 SECTION LOCAL  DEFAULT   25 
    26: 00000000004003ec     0 FUNC    LOCAL  DEFAULT   12 call_gmon_start
    27: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    28: 00000000006006f8     0 OBJECT  LOCAL  DEFAULT   17 __CTOR_LIST__
    29: 0000000000600708     0 OBJECT  LOCAL  DEFAULT   18 __DTOR_LIST__
    30: 0000000000600718     0 OBJECT  LOCAL  DEFAULT   19 __JCR_LIST__
    31: 00000000006008e8     8 OBJECT  LOCAL  DEFAULT   24 dtor_idx.6147
    32: 00000000006008f0     1 OBJECT  LOCAL  DEFAULT   24 completed.6145
    33: 0000000000400410     0 FUNC    LOCAL  DEFAULT   12 __do_global_dtors_aux
    34: 0000000000400470     0 FUNC    LOCAL  DEFAULT   12 frame_dummy
    35: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    36: 0000000000600700     0 OBJECT  LOCAL  DEFAULT   17 __CTOR_END__
    37: 00000000004006f0     0 OBJECT  LOCAL  DEFAULT   16 __FRAME_END__
    38: 0000000000600718     0 OBJECT  LOCAL  DEFAULT   19 __JCR_END__
    39: 00000000004005a0     0 FUNC    LOCAL  DEFAULT   12 __do_global_ctors_aux
    40: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS test.c
    41: 00000000006006f4     0 NOTYPE  LOCAL  HIDDEN   17 __preinit_array_start
    42: 00000000006006f4     0 NOTYPE  LOCAL  HIDDEN   17 __fini_array_end
    43: 00000000006008b8     0 OBJECT  LOCAL  HIDDEN   22 _GLOBAL_OFFSET_TABLE_
    44: 00000000006006f4     0 NOTYPE  LOCAL  HIDDEN   17 __preinit_array_end
    45: 00000000006006f4     0 NOTYPE  LOCAL  HIDDEN   17 __fini_array_start
    46: 00000000006006f4     0 NOTYPE  LOCAL  HIDDEN   17 __init_array_end
    47: 00000000006006f4     0 NOTYPE  LOCAL  HIDDEN   17 __init_array_start
    48: 0000000000600720     0 OBJECT  LOCAL  HIDDEN   20 _DYNAMIC
    49: 00000000006008e0     0 NOTYPE  WEAK   DEFAULT   23 data_start
    50: 0000000000000000   162 FUNC    GLOBAL DEFAULT  UND printf@@GLIBC_2.2.5
    51: 0000000000400500     2 FUNC    GLOBAL DEFAULT   12 __libc_csu_fini
    52: 00000000004003c0     0 FUNC    GLOBAL DEFAULT   12 _start
    53: 00000000006008f4     4 OBJECT  GLOBAL DEFAULT   24 global_data_2
    54: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
    55: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses
    56: 00000000004005d8     0 FUNC    GLOBAL DEFAULT   13 _fini
    57: 0000000000000000   421 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GLIBC_
    58: 00000000004005e8     4 OBJECT  GLOBAL DEFAULT   14 _IO_stdin_used
    59: 00000000006008e0     0 NOTYPE  GLOBAL DEFAULT   23 __data_start
    60: 00000000004005f0     0 OBJECT  GLOBAL HIDDEN   14 __dso_handle
    61: 0000000000600710     0 OBJECT  GLOBAL HIDDEN   18 __DTOR_END__
    62: 0000000000400510   139 FUNC    GLOBAL DEFAULT   12 __libc_csu_init
    63: 00000000006008e8     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
    64: 00000000006008f8     0 NOTYPE  GLOBAL DEFAULT  ABS _end
    65: 00000000006008e8     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
    66: 00000000006008e4     4 OBJECT  GLOBAL DEFAULT   23 global_data
    67: 0000000000400498   104 FUNC    GLOBAL DEFAULT   12 main
    68: 0000000000400370     0 FUNC    GLOBAL DEFAULT   10 _init
[root@localhost elf]# readelf -l test

Elf file type is EXEC (Executable file)
Entry point 0x4003c0
There are 8 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x00000000000001c0 0x00000000000001c0  R E    8
  INTERP         0x0000000000000200 0x0000000000400200 0x0000000000400200
                 0x000000000000001c 0x000000000000001c  R      1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x00000000000006f4 0x00000000000006f4  R E    200000
  LOAD           0x00000000000006f8 0x00000000006006f8 0x00000000006006f8
                 0x00000000000001f0 0x0000000000000200  RW     200000
  DYNAMIC        0x0000000000000720 0x0000000000600720 0x0000000000600720
                 0x0000000000000190 0x0000000000000190  RW     8
  NOTE           0x000000000000021c 0x000000000040021c 0x000000000040021c
                 0x0000000000000020 0x0000000000000020  R      4
  GNU_EH_FRAME   0x000000000000063c 0x000000000040063c 0x000000000040063c
                 0x0000000000000024 0x0000000000000024  R      4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     8

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .interp 
   02     .interp .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 
   03     .ctors .dtors .jcr .dynamic .got .got.plt .data .bss 
   04     .dynamic 
   05     .note.ABI-tag 
   06     .eh_frame_hdr 
   07     
[root@localhost elf]# 

在02 segment里,包含有“.interp .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame”这么多section,其中就有熟悉的.text section,这个segment的Flags标记为R E,即是可读可执行(Readable Executable)。VirtAddr列指示该segment的起始地址,02 segment为0x0000000000400000。PhysAddr列无效,因为Linux下应用程序在Intel/AMD 32/64位机器上总是以保护模式运行。
segment有很多类型,上面内容可以看到有PHDR、LOAD、DYNAMIC、GNU_STACK等等,其中LOAD类型表示该segment的内容从可执行文件里读取,读取的文件起始地址由Offset指定,而FileSiz指定读取的文件内容长度。GNU_STACK类型表示该segment是一个栈区域,所以除了Flags和Align,其它都为0,因为其它的值指定了也没用,它们由Linux内核决定。
可以通过proc文件系统查看进程的segment实际分布:

[root@localhost elf]# cat /proc/self/maps 
00400000-00405000 r-xp 00000000 fd:00 28540969                           /bin/cat
00604000-00606000 rw-p 00004000 fd:00 28540969                           /bin/cat
00606000-00627000 rw-p 00000000 00:00 0                                  [heap]
3734600000-373461c000 r-xp 00000000 fd:00 18219336                       /lib64/ld-2.5.so
373481b000-373481c000 r--p 0001b000 fd:00 18219336                       /lib64/ld-2.5.so
373481c000-373481d000 rw-p 0001c000 fd:00 18219336                       /lib64/ld-2.5.so
3735600000-373574e000 r-xp 00000000 fd:00 18219337                       /lib64/libc-2.5.so
373574e000-373594d000 ---p 0014e000 fd:00 18219337                       /lib64/libc-2.5.so
373594d000-3735951000 r--p 0014d000 fd:00 18219337                       /lib64/libc-2.5.so
3735951000-3735952000 rw-p 00151000 fd:00 18219337                       /lib64/libc-2.5.so
3735952000-3735957000 rw-p 00000000 00:00 0 
7fd99c621000-7fd99fbfd000 r--p 00000000 fd:00 21860321                   /usr/lib/locale/locale-archive
7fd99fbfd000-7fd99fbff000 rw-p 00000000 00:00 0 
7fd99fc1b000-7fd99fc1d000 rw-p 00000000 00:00 0 
7fff20a27000-7fff20a48000 rw-p 00000000 00:00 0                          [stack]
7fff20a61000-7fff20a62000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
You have new mail in /var/spool/mail/root
[root@localhost elf]# 

参考资料:
http://gala4th.blogspot.com/2009/12/understanding-elf-using-readelf-and.html
http://en.wikipedia.org/wiki/Executable_and_Linkable_Format

转载请保留地址:http://www.lenky.info/archives/2012/01/913http://lenky.info/?p=913


备注:如无特殊说明,文章内容均出自Lenky个人的真实理解而并非存心妄自揣测来故意愚人耳目。由于个人水平有限,虽力求内容正确无误,但仍然难免出错,请勿见怪,如果可以则请留言告之,并欢迎来讨论。另外值得说明的是,Lenky的部分文章以及部分内容参考借鉴了网络上各位网友的热心分享,特别是一些带有完全参考的文章,其后附带的链接内容也许更直接、更丰富,而我只是做了一下归纳&转述,在此也一并表示感谢。关于本站的所有技术文章,欢迎转载,但请遵从CC创作共享协议,而一些私人性质较强的心情随笔,建议不要转载。

法律:根据最新颁布的《信息网络传播权保护条例》,如果您认为本文章的任何内容侵犯了您的权利,请以Email或书面等方式告知,本站将及时删除相关内容或链接。

分类: *nix技术, Shell命令 标签: ,
  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.