readelf命令和ELF檔案詳解
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 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)
.text區儲存的是程式的程式碼(二進位制指令),該區的標誌為X表示可執行。
下面使用objdump反彙編檢視.text的內容:
$objdump -d -j .text test
-d選項告訴objdump反彙編機器碼,-j選項告訴objdump只關心.text區。
test: file format elf64-x86-64
Disassembly 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 nop
000000000040044c <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 nop
0000000000400470 <__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 nop
0000000000400504 <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 nop
0000000000400580 <__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 nop
0000000000400620 <__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-64
Disassembly 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-64
Disassembly 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 0x400420
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
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 main
Breakpoint 1 at 0x400508
(gdb) r
Starting 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 /test
00600000-00601000 rw-p 00000000 ca:11 8626925 /test
7ffff762d000-7ffff7644000 r-xp 00000000 ca:01 332328 /lib64/libpthread-2.12.so
7ffff7644000-7ffff7843000 ---p 00017000 ca:01 332328 /lib64/libpthread-2.12.so
7ffff7843000-7ffff7844000 r--p 00016000 ca:01 332328 /lib64/libpthread-2.12.so
7ffff7844000-7ffff7845000 rw-p 00017000 ca:01 332328 /lib64/libpthread-2.12.so
7ffff7845000-7ffff7849000 rw-p 00000000 00:00 0
7ffff7849000-7ffff784b000 r-xp 00000000 ca:01 332237 /lib64/libdl-2.12.so
7ffff784b000-7ffff7a4b000 ---p 00002000 ca:01 332237 /lib64/libdl-2.12.so
7ffff7a4b000-7ffff7a4c000 r--p 00002000 ca:01 332237 /lib64/libdl-2.12.so
7ffff7a4c000-7ffff7a4d000 rw-p 00003000 ca:01 332237 /lib64/libdl-2.12.so
7ffff7a4d000-7ffff7bd3000 r-xp 00000000 ca:01 332102 /lib64/libc-2.12.so
7ffff7bd3000-7ffff7dd3000 ---p 00186000 ca:01 332102 /lib64/libc-2.12.so
7ffff7dd3000-7ffff7dd7000 r--p 00186000 ca:01 332102 /lib64/libc-2.12.so
7ffff7dd7000-7ffff7dd8000 rw-p 0018a000 ca:01 332102 /lib64/libc-2.12.so
7ffff7dd8000-7ffff7ddd000 rw-p 00000000 00:00 0
7ffff7ddd000-7ffff7dfd000 r-xp 00000000 ca:01 332126 /lib64/ld-2.12.so
7ffff7ed9000-7ffff7edc000 rw-p 00000000 00:00 0
7ffff7eeb000-7ffff7eee000 r-xp 00000000 ca:01 336319 /lib64/libonion_security.so.1.0.13
7ffff7eee000-7ffff7fee000 ---p 00003000 ca:01 336319 /lib64/libonion_security.so.1.0.13
7ffff7fee000-7ffff7fef000 rw-p 00003000 ca:01 336319 /lib64/libonion_security.so.1.0.13
7ffff7fef000-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.so
7ffff7ffd000-7ffff7ffe000 rw-p 00020000 ca:01 332126 /lib64/ld-2.12.so
7ffff7ffe000-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.
相關文章
- 目標檔案和ELF格式詳解
- Linux可執行檔案格式-ELF結構詳解Linux
- Linux環境下:程式的連結, 裝載和庫[ELF檔案詳解]Linux
- elf檔案格式
- Unix檔案系統和pwd命令實現詳解
- ELF檔案逆向分析
- Linux檔案相關命令詳解(一)Linux
- elf檔案處理工具
- 扒一扒ELF檔案
- Linux 解壓zip檔案詳解之unzip命令!Linux
- Linux常用檔案許可權命令詳解Linux
- ELF檔案的四種分類
- Linux常用命令之檔案壓縮與解壓縮命令詳解Linux
- ELF檔案中的各個節區
- Linux系統常見檔案大小常用的命令詳解!Linux
- Linux系統檢視檔案地址常用的命令詳解!Linux
- Cnetos7系統---檔案壓縮與解壓命令詳解。
- Centos7系統---檔案壓縮與解壓命令詳解。CentOS
- Dockerfile檔案詳解Docker
- mtl檔案詳解
- LD檔案詳解
- starrycan的pwn隨筆——ELF檔案和延遲繫結機制
- 實現ELF檔案解析,支援-h, -S, -s
- keepalived(一)原理介紹和配置檔案詳解
- haproxy配置檔案詳解
- JavaScript 檔案物件詳解JavaScript物件
- Class 檔案格式詳解
- redis配置檔案詳解Redis
- Scala檔案操作詳解
- redis 配置檔案詳解Redis
- java class檔案詳解Java
- Dockerfile檔案全面詳解Docker
- dlopen程式碼詳解——從ELF格式到mmap
- MachO 檔案結構詳解Mac
- git config配置檔案詳解Git
- Linux 檔案系統詳解Linux
- managed-schema 檔案詳解
- Nginx的配置檔案詳解Nginx
- Linux檔案系統詳解Linux