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.
- readelf命令和ELF文件详解
- ELF文件及readelf命令使用
- readelf和ldd分析elf文件
- readelf--读elf文件信息
- 目标文件解析命令:objdump和readelf
- readelf 命令详解
- readelf命令详解
- 研究ELF文件的工具objdump&readelf
- ELF文件查看利器之readelf用法
- elf和readelf的选项参数
- Linux命令之readelf详解
- ELF格式文件符号表全解析及readelf命令使用方法
- ELF格式文件符号表全解析及readelf命令使用方法
- ELF格式文件符号表全解析及readelf命令使用方法
- ELF格式文件符号表全解析及readelf命令使用方法
- ELF格式文件符号表全解析及readelf命令使用方法
- ELF格式文件符号表全解析及readelf命令使用方法
- ELF格式文件符号表全解析及readelf命令使用方法
- springmvc学习笔记
- 【图像处理】MATLAB:退化函数及多种复原方法
- 剑指offer之调整数组顺序使奇数位于偶数前面
- Linux命令行大全总结(一)
- RAC初识--004--RACSubject
- readelf命令和ELF文件详解
- iOS11之后刷新tableview会出现漂移的现象解决办法
- VS bower配置
- c语言实现单向循环链表
- mysql优化-explain使用
- UDP的结构和传输原理
- 阿里巴巴的“达摩院”,必是一场闹剧
- Qter 开发资源大集合
- hadoop安装问题:root@localhost's password:localhost:permission denied,please try again