readelf命令和ELF文件详解

来源:互联网 发布:免费数据网站 编辑:程序博客网 时间:2024/05/29 12:47

ELF(Executable and Linking Format)是一个定义了目标文件内部信息如何组成和组织的文件格式。内核会根据这些信息加载可执行文件,内核根据这些信息可以知道从文件哪里获取代码,从哪里获取初始化数据,在哪里应该加载共享库,等信息。
ELF文件有下面三种类型:
1.目标文件

$ gcc -c test.c
得到的test.o就是目标文件,目标文件通过链接可生成可执行文件。
静态库其实也算目标文件,静态库是通过ar命令将目标打包为.a文件。
如:ar crv libtest.a test.o

2.可执行文件
$gcc -o test test.c
得到的test文件就是可执行的二进制文件。

3.共享库
$ gcc test.c -fPIC -shared -o libtest.so
得到的文件listtest.so就是共享库。

可以通过readelf来区分上面三种类型的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:          456 (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

$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:               0x400420  Start of program headers:          64 (bytes into file)  Start of section headers:          2696 (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:         30  Section header string table index: 27

$readelf -h libtest.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:               0x570  Start of program headers:          64 (bytes into file)  Start of section headers:          2768 (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:         29  Section header string table index: 26

下面是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 World\n");     printf("global_data = %d\n", global_data);     printf("global_data_2 = %d\n", global_data_2);     printf("local_data = %d\n", local_data);     return (0);}

$gcc -o test test.c
生成可执行文件test,然后使用readelf对其进行分析。

$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:               0x400420  Start of program headers:          64 (bytes into file)  Start of section headers:          2696 (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:         30  Section header string table index: 27

上面的信息可以告诉我们什么信息?
1.根据Class、Type和Machine,可以知道该文件在X86-64位机器上生成的64位可执行文件。
2.根据Entry point address,可以知道当该程序启动时从虚拟地址0x400420处开始运行。这个地址并不是main函数的地址,而是_start函数的地址,_start由链接器创建,_start是为了初始化程序。通过这个命令可以看到_start函数,objdump -d -j .text test
3.根据Number of program headers,可以知道该程序有8个段。
4.根据Number of section headers,可以知道该程序有30个区。
区中存储的信息是用来链接使用的,主要包括:程序代码、程序数据(变量)、重定向信息等。比如:Code section保存的是代码,data section保存的是初始化或未初始化的数据,等等。

Linux内核无法以区的概念来识别可执行文件。内核使用包括连续页的VMA(virtual memory area)来识别进程。在每个VMA中可能映射了一个或多个区。每个VMA代表一个ELF文件的段。
那么,内核如何知道哪个区属于某个VMA(段)?映射关系保存在Program Header Table(PHT)中。

下面查看区的内容:
$readelf -S test

There are 30 section headers, starting at offset 0xa88: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  [ 2] .note.ABI-tag     NOTE             000000000040021c  0000021c       0000000000000020  0000000000000000   A       0     0     4  [ 3] .note.gnu.build-i NOTE             000000000040023c  0000023c       0000000000000024  0000000000000000   A       0     0     4  [ 4] .gnu.hash         GNU_HASH         0000000000400260  00000260       000000000000001c  0000000000000000   A       5     0     8  [ 5] .dynsym           DYNSYM           0000000000400280  00000280       0000000000000078  0000000000000018   A       6     1     8  [ 6] .dynstr           STRTAB           00000000004002f8  000002f8       0000000000000044  0000000000000000   A       0     0     1  [ 7] .gnu.version      VERSYM           000000000040033c  0000033c       000000000000000a  0000000000000002   A       5     0     2  [ 8] .gnu.version_r    VERNEED          0000000000400348  00000348       0000000000000020  0000000000000000   A       6     1     8  [ 9] .rela.dyn         RELA             0000000000400368  00000368       0000000000000018  0000000000000018   A       5     0     8  [10] .rela.plt         RELA             0000000000400380  00000380       0000000000000048  0000000000000018   A       5    12     8  [11] .init             PROGBITS         00000000004003c8  000003c8       0000000000000018  0000000000000000  AX       0     0     4  [12] .plt              PROGBITS         00000000004003e0  000003e0       0000000000000040  0000000000000010  AX       0     0     4  [13] .text             PROGBITS         0000000000400420  00000420       0000000000000238  0000000000000000  AX       0     0     16  [14] .fini             PROGBITS         0000000000400658  00000658       000000000000000e  0000000000000000  AX       0     0     4  [15] .rodata           PROGBITS         0000000000400668  00000668       0000000000000053  0000000000000000   A       0     0     8  [16] .eh_frame_hdr     PROGBITS         00000000004006bc  000006bc       0000000000000024  0000000000000000   A       0     0     4  [17] .eh_frame         PROGBITS         00000000004006e0  000006e0       000000000000007c  0000000000000000   A       0     0     8  [18] .ctors            PROGBITS         0000000000600760  00000760       0000000000000010  0000000000000000  WA       0     0     8  [19] .dtors            PROGBITS         0000000000600770  00000770       0000000000000010  0000000000000000  WA       0     0     8  [20] .jcr              PROGBITS         0000000000600780  00000780       0000000000000008  0000000000000000  WA       0     0     8  [21] .dynamic          DYNAMIC          0000000000600788  00000788       0000000000000190  0000000000000010  WA       6     0     8  [22] .got              PROGBITS         0000000000600918  00000918       0000000000000008  0000000000000008  WA       0     0     8  [23] .got.plt          PROGBITS         0000000000600920  00000920       0000000000000030  0000000000000008  WA       0     0     8  [24] .data             PROGBITS         0000000000600950  00000950       0000000000000008  0000000000000000  WA       0     0     4  [25] .bss              NOBITS           0000000000600958  00000958       0000000000000018  0000000000000000  WA       0     0     8  [26] .comment          PROGBITS         0000000000000000  00000958       000000000000002c  0000000000000001  MS       0     0     1  [27] .shstrtab         STRTAB           0000000000000000  00000984       00000000000000fe  0000000000000000           0     0     1  [28] .symtab           SYMTAB           0000000000000000  00001208       0000000000000648  0000000000000018          29    46     8  [29] .strtab           STRTAB           0000000000000000  00001850       000000000000021e  0000000000000000           0     0     1Key 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)

.text区存储的是程序的代码(二进制指令),该区的标志为X表示可执行。

下面使用objdump反汇编查看.text的内容:
$objdump -d -j .text test
-d选项告诉objdump反汇编机器码,-j选项告诉objdump只关心.text区。

test:     file format elf64-x86-64Disassembly of section .text:0000000000400420 <_start>:  400420:       31 ed                   xor    %ebp,%ebp  400422:       49 89 d1                mov    %rdx,%r9  400425:       5e                      pop    %rsi  400426:       48 89 e2                mov    %rsp,%rdx  400429:       48 83 e4 f0             and    $0xfffffffffffffff0,%rsp  40042d:       50                      push   %rax  40042e:       54                      push   %rsp  40042f:       49 c7 c0 80 05 40 00    mov    $0x400580,%r8  400436:       48 c7 c1 90 05 40 00    mov    $0x400590,%rcx  40043d:       48 c7 c7 04 05 40 00    mov    $0x400504,%rdi  400444:       e8 c7 ff ff ff          callq  400410 <__libc_start_main@plt>  400449:       f4                      hlt      40044a:       90                      nop  40044b:       90                      nop000000000040044c <call_gmon_start>:  40044c:       48 83 ec 08             sub    $0x8,%rsp  400450:       48 8b 05 c1 04 20 00    mov    0x2004c1(%rip),%rax        # 600918 <_DYNAMIC+0x190>  400457:       48 85 c0                test   %rax,%rax  40045a:       74 02                   je     40045e <call_gmon_start+0x12>  40045c:       ff d0                   callq  *%rax  40045e:       48 83 c4 08             add    $0x8,%rsp  400462:       c3                      retq     400463:       90                      nop  400464:       90                      nop  400465:       90                      nop  400466:       90                      nop  400467:       90                      nop  400468:       90                      nop  400469:       90                      nop  40046a:       90                      nop  40046b:       90                      nop  40046c:       90                      nop  40046d:       90                      nop  40046e:       90                      nop  40046f:       90                      nop0000000000400470 <__do_global_dtors_aux>:  400470:       55                      push   %rbp  400471:       48 89 e5                mov    %rsp,%rbp  400474:       53                      push   %rbx  400475:       48 83 ec 08             sub    $0x8,%rsp  400479:       80 3d d8 04 20 00 00    cmpb   $0x0,0x2004d8(%rip)        # 600958 <__bss_start>  400480:       75 4b                   jne    4004cd <__do_global_dtors_aux+0x5d>  400482:       bb 78 07 60 00          mov    $0x600778,%ebx  400487:       48 8b 05 d2 04 20 00    mov    0x2004d2(%rip),%rax        # 600960 <dtor_idx.6349>  40048e:       48 81 eb 70 07 60 00    sub    $0x600770,%rbx  400495:       48 c1 fb 03             sar    $0x3,%rbx  400499:       48 83 eb 01             sub    $0x1,%rbx  40049d:       48 39 d8                cmp    %rbx,%rax  4004a0:       73 24                   jae    4004c6 <__do_global_dtors_aux+0x56>  4004a2:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)  4004a8:       48 83 c0 01             add    $0x1,%rax  4004ac:       48 89 05 ad 04 20 00    mov    %rax,0x2004ad(%rip)        # 600960 <dtor_idx.6349>  4004b3:       ff 14 c5 70 07 60 00    callq  *0x600770(,%rax,8)  4004ba:       48 8b 05 9f 04 20 00    mov    0x20049f(%rip),%rax        # 600960 <dtor_idx.6349>  4004c1:       48 39 d8                cmp    %rbx,%rax  4004c4:       72 e2                   jb     4004a8 <__do_global_dtors_aux+0x38>  4004c6:       c6 05 8b 04 20 00 01    movb   $0x1,0x20048b(%rip)        # 600958 <__bss_start>  4004cd:       48 83 c4 08             add    $0x8,%rsp  4004d1:       5b                      pop    %rbx  4004d2:       c9                      leaveq   4004d3:       c3                      retq     4004d4:       66 66 66 2e 0f 1f 84    data32 data32 nopw %cs:0x0(%rax,%rax,1)  4004db:       00 00 00 00 00 00000000004004e0 <frame_dummy>:  4004e0:       48 83 3d 98 02 20 00    cmpq   $0x0,0x200298(%rip)        # 600780 <__JCR_END__>  4004e7:       00   4004e8:       55                      push   %rbp  4004e9:       48 89 e5                mov    %rsp,%rbp  4004ec:       74 12                   je     400500 <frame_dummy+0x20>  4004ee:       b8 00 00 00 00          mov    $0x0,%eax  4004f3:       48 85 c0                test   %rax,%rax  4004f6:       74 08                   je     400500 <frame_dummy+0x20>  4004f8:       bf 80 07 60 00          mov    $0x600780,%edi  4004fd:       c9                      leaveq   4004fe:       ff e0                   jmpq   *%rax  400500:       c9                      leaveq   400501:       c3                      retq     400502:       90                      nop  400503:       90                      nop0000000000400504 <main>:  400504:       55                      push   %rbp  400505:       48 89 e5                mov    %rsp,%rbp  400508:       48 83 ec 20             sub    $0x20,%rsp  40050c:       89 7d ec                mov    %edi,-0x14(%rbp)  40050f:       48 89 75 e0             mov    %rsi,-0x20(%rbp)  400513:       c7 45 fc 03 00 00 00    movl   $0x3,-0x4(%rbp)  40051a:       bf 78 06 40 00          mov    $0x400678,%edi  40051f:       e8 dc fe ff ff          callq  400400 <puts@plt>  400524:       8b 15 2a 04 20 00       mov    0x20042a(%rip),%edx        # 600954 <global_data>  40052a:       b8 84 06 40 00          mov    $0x400684,%eax  40052f:       89 d6                   mov    %edx,%esi  400531:       48 89 c7                mov    %rax,%rdi  400534:       b8 00 00 00 00          mov    $0x0,%eax  400539:       e8 b2 fe ff ff          callq  4003f0 <printf@plt>  40053e:       8b 15 24 04 20 00       mov    0x200424(%rip),%edx        # 600968 <global_data_2>  400544:       b8 96 06 40 00          mov    $0x400696,%eax  400549:       89 d6                   mov    %edx,%esi  40054b:       48 89 c7                mov    %rax,%rdi  40054e:       b8 00 00 00 00          mov    $0x0,%eax  400553:       e8 98 fe ff ff          callq  4003f0 <printf@plt>  400558:       b8 aa 06 40 00          mov    $0x4006aa,%eax  40055d:       8b 55 fc                mov    -0x4(%rbp),%edx  400560:       89 d6                   mov    %edx,%esi  400562:       48 89 c7                mov    %rax,%rdi  400565:       b8 00 00 00 00          mov    $0x0,%eax  40056a:       e8 81 fe ff ff          callq  4003f0 <printf@plt>  40056f:       b8 00 00 00 00          mov    $0x0,%eax  400574:       c9                      leaveq   400575:       c3                      retq     400576:       90                      nop  400577:       90                      nop  400578:       90                      nop  400579:       90                      nop  40057a:       90                      nop  40057b:       90                      nop  40057c:       90                      nop  40057d:       90                      nop  40057e:       90                      nop  40057f:       90                      nop0000000000400580 <__libc_csu_fini>:  400580:       f3 c3                   repz retq   400582:       66 66 66 66 66 2e 0f    data32 data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)  400589:       1f 84 00 00 00 00 00 0000000000400590 <__libc_csu_init>:  400590:       48 89 6c 24 d8          mov    %rbp,-0x28(%rsp)  400595:       4c 89 64 24 e0          mov    %r12,-0x20(%rsp)  40059a:       48 8d 2d bb 01 20 00    lea    0x2001bb(%rip),%rbp        # 60075c <__init_array_end>  4005a1:       4c 8d 25 b4 01 20 00    lea    0x2001b4(%rip),%r12        # 60075c <__init_array_end>  4005a8:       4c 89 6c 24 e8          mov    %r13,-0x18(%rsp)  4005ad:       4c 89 74 24 f0          mov    %r14,-0x10(%rsp)  4005b2:       4c 89 7c 24 f8          mov    %r15,-0x8(%rsp)  4005b7:       48 89 5c 24 d0          mov    %rbx,-0x30(%rsp)  4005bc:       48 83 ec 38             sub    $0x38,%rsp  4005c0:       4c 29 e5                sub    %r12,%rbp  4005c3:       41 89 fd                mov    %edi,%r13d  4005c6:       49 89 f6                mov    %rsi,%r14  4005c9:       48 c1 fd 03             sar    $0x3,%rbp  4005cd:       49 89 d7                mov    %rdx,%r15  4005d0:       e8 f3 fd ff ff          callq  4003c8 <_init>  4005d5:       48 85 ed                test   %rbp,%rbp  4005d8:       74 1c                   je     4005f6 <__libc_csu_init+0x66>  4005da:       31 db                   xor    %ebx,%ebx  4005dc:       0f 1f 40 00             nopl   0x0(%rax)  4005e0:       4c 89 fa                mov    %r15,%rdx  4005e3:       4c 89 f6                mov    %r14,%rsi  4005e6:       44 89 ef                mov    %r13d,%edi  4005e9:       41 ff 14 dc             callq  *(%r12,%rbx,8)  4005ed:       48 83 c3 01             add    $0x1,%rbx  4005f1:       48 39 eb                cmp    %rbp,%rbx  4005f4:       72 ea                   jb     4005e0 <__libc_csu_init+0x50>  4005f6:       48 8b 5c 24 08          mov    0x8(%rsp),%rbx  4005fb:       48 8b 6c 24 10          mov    0x10(%rsp),%rbp  400600:       4c 8b 64 24 18          mov    0x18(%rsp),%r12  400605:       4c 8b 6c 24 20          mov    0x20(%rsp),%r13  40060a:       4c 8b 74 24 28          mov    0x28(%rsp),%r14  40060f:       4c 8b 7c 24 30          mov    0x30(%rsp),%r15  400614:       48 83 c4 38             add    $0x38,%rsp  400618:       c3                      retq     400619:       90                      nop  40061a:       90                      nop  40061b:       90                      nop  40061c:       90                      nop  40061d:       90                      nop  40061e:       90                      nop  40061f:       90                      nop0000000000400620 <__do_global_ctors_aux>:  400620:       55                      push   %rbp  400621:       48 89 e5                mov    %rsp,%rbp  400624:       53                      push   %rbx  400625:       48 83 ec 08             sub    $0x8,%rsp  400629:       48 8b 05 30 01 20 00    mov    0x200130(%rip),%rax        # 600760 <__CTOR_LIST__>  400630:       48 83 f8 ff             cmp    $0xffffffffffffffff,%rax  400634:       74 19                   je     40064f <__do_global_ctors_aux+0x2f>  400636:       bb 60 07 60 00          mov    $0x600760,%ebx  40063b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)  400640:       48 83 eb 08             sub    $0x8,%rbx  400644:       ff d0                   callq  *%rax  400646:       48 8b 03                mov    (%rbx),%rax  400649:       48 83 f8 ff             cmp    $0xffffffffffffffff,%rax  40064d:       75 f1                   jne    400640 <__do_global_ctors_aux+0x20>  40064f:       48 83 c4 08             add    $0x8,%rsp  400653:       5b                      pop    %rbx  400654:       c9                      leaveq   400655:       c3                      retq     400656:       90                      nop  400657:       90                      nop

下面使用objdump反汇编查看.data的内容:
$objdump -d -j .data test
.data区保存的是初始化的全局变量。

test:     file format elf64-x86-64Disassembly of section .data:0000000000600950 <__data_start>:  600950:       00 00                   add    %al,(%rax)        ...0000000000600954 <global_data>:  600954:       04 00 00 00  

下面使用objdump反汇编查看.bss的内容:
$objdump -d -j .bss test
.bss区保存的是未初始化的全局变量,linux会默认将未初始化的变量置为0。

test:     file format elf64-x86-64Disassembly of section .bss:0000000000600958 <completed.6347>:        ...0000000000600960 <dtor_idx.6349>:        ...0000000000600968 <global_data_2>:        ...

下面命令可以看到test文件中所有的符号:
$readelf -s test
Value的值是符号的地址。

Symbol table '.dynsym' contains 5 entries:   Num:    Value          Size Type    Bind   Vis      Ndx Name     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND      1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf@GLIBC_2.2.5 (2)     2: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__     3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND puts@GLIBC_2.2.5 (2)     4: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.2.5 (2)Symbol table '.symtab' contains 67 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: 000000000040023c     0 SECTION LOCAL  DEFAULT    3      4: 0000000000400260     0 SECTION LOCAL  DEFAULT    4      5: 0000000000400280     0 SECTION LOCAL  DEFAULT    5      6: 00000000004002f8     0 SECTION LOCAL  DEFAULT    6      7: 000000000040033c     0 SECTION LOCAL  DEFAULT    7      8: 0000000000400348     0 SECTION LOCAL  DEFAULT    8      9: 0000000000400368     0 SECTION LOCAL  DEFAULT    9     10: 0000000000400380     0 SECTION LOCAL  DEFAULT   10     11: 00000000004003c8     0 SECTION LOCAL  DEFAULT   11     12: 00000000004003e0     0 SECTION LOCAL  DEFAULT   12     13: 0000000000400420     0 SECTION LOCAL  DEFAULT   13     14: 0000000000400658     0 SECTION LOCAL  DEFAULT   14     15: 0000000000400668     0 SECTION LOCAL  DEFAULT   15     16: 00000000004006bc     0 SECTION LOCAL  DEFAULT   16     17: 00000000004006e0     0 SECTION LOCAL  DEFAULT   17     18: 0000000000600760     0 SECTION LOCAL  DEFAULT   18     19: 0000000000600770     0 SECTION LOCAL  DEFAULT   19     20: 0000000000600780     0 SECTION LOCAL  DEFAULT   20     21: 0000000000600788     0 SECTION LOCAL  DEFAULT   21     22: 0000000000600918     0 SECTION LOCAL  DEFAULT   22     23: 0000000000600920     0 SECTION LOCAL  DEFAULT   23     24: 0000000000600950     0 SECTION LOCAL  DEFAULT   24     25: 0000000000600958     0 SECTION LOCAL  DEFAULT   25     26: 0000000000000000     0 SECTION LOCAL  DEFAULT   26     27: 000000000040044c     0 FUNC    LOCAL  DEFAULT   13 call_gmon_start    28: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c    29: 0000000000600760     0 OBJECT  LOCAL  DEFAULT   18 __CTOR_LIST__    30: 0000000000600770     0 OBJECT  LOCAL  DEFAULT   19 __DTOR_LIST__    31: 0000000000600780     0 OBJECT  LOCAL  DEFAULT   20 __JCR_LIST__    32: 0000000000400470     0 FUNC    LOCAL  DEFAULT   13 __do_global_dtors_aux    33: 0000000000600958     1 OBJECT  LOCAL  DEFAULT   25 completed.6347    34: 0000000000600960     8 OBJECT  LOCAL  DEFAULT   25 dtor_idx.6349    35: 00000000004004e0     0 FUNC    LOCAL  DEFAULT   13 frame_dummy    36: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c    37: 0000000000600768     0 OBJECT  LOCAL  DEFAULT   18 __CTOR_END__    38: 0000000000400758     0 OBJECT  LOCAL  DEFAULT   17 __FRAME_END__    39: 0000000000600780     0 OBJECT  LOCAL  DEFAULT   20 __JCR_END__    40: 0000000000400620     0 FUNC    LOCAL  DEFAULT   13 __do_global_ctors_aux    41: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS test.c    42: 0000000000600920     0 OBJECT  LOCAL  DEFAULT   23 _GLOBAL_OFFSET_TABLE_    43: 000000000060075c     0 NOTYPE  LOCAL  DEFAULT   18 __init_array_end    44: 000000000060075c     0 NOTYPE  LOCAL  DEFAULT   18 __init_array_start    45: 0000000000600788     0 OBJECT  LOCAL  DEFAULT   21 _DYNAMIC    46: 0000000000600950     0 NOTYPE  WEAK   DEFAULT   24 data_start    47: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf@@GLIBC_2.2.5    48: 0000000000400580     2 FUNC    GLOBAL DEFAULT   13 __libc_csu_fini    49: 0000000000400420     0 FUNC    GLOBAL DEFAULT   13 _start    50: 0000000000600968     4 OBJECT  GLOBAL DEFAULT   25 global_data_2    51: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__    52: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses    53: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND puts@@GLIBC_2.2.5    54: 0000000000400658     0 FUNC    GLOBAL DEFAULT   14 _fini    55: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GLIBC_    56: 0000000000400668     4 OBJECT  GLOBAL DEFAULT   15 _IO_stdin_used    57: 0000000000600950     0 NOTYPE  GLOBAL DEFAULT   24 __data_start    58: 0000000000400670     0 OBJECT  GLOBAL HIDDEN    15 __dso_handle    59: 0000000000600778     0 OBJECT  GLOBAL HIDDEN    19 __DTOR_END__    60: 0000000000400590   137 FUNC    GLOBAL DEFAULT   13 __libc_csu_init    61: 0000000000600958     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start    62: 0000000000600970     0 NOTYPE  GLOBAL DEFAULT  ABS _end    63: 0000000000600958     0 NOTYPE  GLOBAL DEFAULT  ABS _edata    64: 0000000000600954     4 OBJECT  GLOBAL DEFAULT   24 global_data    65: 0000000000400504   114 FUNC    GLOBAL DEFAULT   13 main    66: 00000000004003c8     0 FUNC    GLOBAL DEFAULT   11 _init

下面命令来查看文件的段信息:
$readelf -l test
区到段的映射,基本上是按照区的顺序进行映射。
如果Flags为R和E,表示该段可读和可执行。
如果Flags为W,表示该段可写。
VirtAddr是每个段的虚拟起始地址。这个地址并不是位于真正内存上的地址(物理地址)。

Elf file type is EXEC (Executable file)Entry point 0x400420There are 8 program headers, starting at offset 64Program 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                 0x000000000000075c 0x000000000000075c  R E    200000  LOAD           0x0000000000000760 0x0000000000600760 0x0000000000600760                 0x00000000000001f8 0x0000000000000210  RW     200000  DYNAMIC        0x0000000000000788 0x0000000000600788 0x0000000000600788                 0x0000000000000190 0x0000000000000190  RW     8  NOTE           0x000000000000021c 0x000000000040021c 0x000000000040021c                 0x0000000000000044 0x0000000000000044  R      4  GNU_EH_FRAME   0x00000000000006bc 0x00000000004006bc 0x00000000004006bc                 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 .note.gnu.build-id .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 .note.gnu.build-id    06     .eh_frame_hdr    07     

如上所示,段有多种类型,下面介绍LOAD类型
LOAD:该段的内容从可执行文件中获取。Offset标识内核从文件读取的位置。FileSiz标识读取多少字节。

那么,执行test之后的进程的段布局是如何呢?
可以通过cat /proc/pid/maps来查看。pid是进程的pid。
但是该test运行时间很短,可以使用gdb加断点来运行,或者在return语句之前加上sleep()。

下面使用gdb加断点的形式:

GNU gdb (GDB) Red Hat Enterprise Linux (7.2-50.el6)Copyright (C) 2010 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.  Type "show copying"and "show warranty" for details.This GDB was configured as "x86_64-redhat-linux-gnu".For bug reporting instructions, please see:<http://www.gnu.org/software/gdb/bugs/>...Reading symbols from /data/readyao/qqlive_zb_prj/server/cgi_push_post_replay/lib/test...(no debugging symbols found)...done.(gdb) b mainBreakpoint 1 at 0x400508(gdb) rStarting program: /data/readyao/qqlive_zb_prj/server/cgi_push_post_replay/lib/test [Thread debugging using libthread_db enabled]Breakpoint 1, 0x0000000000400508 in main ()Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.49.tl1.x86_64

$cat /proc/6929/maps

00400000-00401000 r-xp 00000000 ca:11 8626925                            /test00600000-00601000 rw-p 00000000 ca:11 8626925                            /test7ffff762d000-7ffff7644000 r-xp 00000000 ca:01 332328                     /lib64/libpthread-2.12.so7ffff7644000-7ffff7843000 ---p 00017000 ca:01 332328                     /lib64/libpthread-2.12.so7ffff7843000-7ffff7844000 r--p 00016000 ca:01 332328                     /lib64/libpthread-2.12.so7ffff7844000-7ffff7845000 rw-p 00017000 ca:01 332328                     /lib64/libpthread-2.12.so7ffff7845000-7ffff7849000 rw-p 00000000 00:00 0 7ffff7849000-7ffff784b000 r-xp 00000000 ca:01 332237                     /lib64/libdl-2.12.so7ffff784b000-7ffff7a4b000 ---p 00002000 ca:01 332237                     /lib64/libdl-2.12.so7ffff7a4b000-7ffff7a4c000 r--p 00002000 ca:01 332237                     /lib64/libdl-2.12.so7ffff7a4c000-7ffff7a4d000 rw-p 00003000 ca:01 332237                     /lib64/libdl-2.12.so7ffff7a4d000-7ffff7bd3000 r-xp 00000000 ca:01 332102                     /lib64/libc-2.12.so7ffff7bd3000-7ffff7dd3000 ---p 00186000 ca:01 332102                     /lib64/libc-2.12.so7ffff7dd3000-7ffff7dd7000 r--p 00186000 ca:01 332102                     /lib64/libc-2.12.so7ffff7dd7000-7ffff7dd8000 rw-p 0018a000 ca:01 332102                     /lib64/libc-2.12.so7ffff7dd8000-7ffff7ddd000 rw-p 00000000 00:00 0 7ffff7ddd000-7ffff7dfd000 r-xp 00000000 ca:01 332126                     /lib64/ld-2.12.so7ffff7ed9000-7ffff7edc000 rw-p 00000000 00:00 0 7ffff7eeb000-7ffff7eee000 r-xp 00000000 ca:01 336319                     /lib64/libonion_security.so.1.0.137ffff7eee000-7ffff7fee000 ---p 00003000 ca:01 336319                     /lib64/libonion_security.so.1.0.137ffff7fee000-7ffff7fef000 rw-p 00003000 ca:01 336319                     /lib64/libonion_security.so.1.0.137ffff7fef000-7ffff7ffb000 rw-p 00000000 00:00 0 7ffff7ffb000-7ffff7ffc000 r-xp 00000000 00:00 0                          [vdso]7ffff7ffc000-7ffff7ffd000 r--p 0001f000 ca:01 332126                     /lib64/ld-2.12.so7ffff7ffd000-7ffff7ffe000 rw-p 00020000 ca:01 332126                     /lib64/ld-2.12.so7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0 7ffffffea000-7ffffffff000 rw-p 00000000 00:00 0                          [stack]ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

前面一部分是VMA的起始地址和结束地址。
最后一部分是该区域内容所属文件。
在32位系统中,进程地址空间为4G,分为用户空间和内核空间。
这里写图片描述
从下面可以看到栈的地址是向下生长,堆的地址是向上生长。
这里写图片描述

参考资料:
http://www.linuxforums.org/articles/understanding-elf-using-readelf-and-objdump_125.html

http://www.linuxjournal.com/article/1059
http://www.linuxjournal.com/article/1060
Two good ELF introductory articles written by Eric Youngdale.

http://en.wikipedia.org/wiki/Executable_and_Linkable_Format
Explanation about ELF from Wikipedia. From there, you can find links to another useful documents.

http://x86.ddj.com/ftp/manuals/tools/elf.pdf
The document that completely explain all about ELF structure. Study this document after reading this article to gain complete insight about ELF.

ELFSH
A tool to do ELF binary inspection and manipulation. Pretty useful for reverse engineering too. It has scripting feature so you can automate most of your work. In the website, there are many documents that explains various ELF hacking.