GCC编译器原理(二)------编译原理一:目标文件
一、目标文件
在 UNIX® 和 Linux® 中,任何事物都是文件。UNIX 和 Linux 编程实际上是编写处理各种文件的代码。系统由许多类型的文件组成,但目标文件具有一种特殊的设计,提供了灵活和多样的用途。
目标文件是包含带有附加地址和值的助记符号的路线图。这些符号可以用来对各种代码段和数据段进行命名,包括经过初始化的和未初始化的。它们也可以用来定位嵌入的调试信息,就像语义 Web,非常适合由程序进行阅读。
编译器可以将我们在代码编辑器中创建的文本转换为目标文件。最初,目标文件被称为代码的中间表示形式,因为它用作连接编辑器(即连接器)的输入,而连接编辑器最终完成整个任务并生成可执行的程序作为输出。
从代码到可执行代码的转换过程经过了良好的定义并实现了自动化,而目标文件是这个链中有机的连接性环节。在这个转换过程中,目标文件作为连接编辑器所使用的映象,使得它们能够解析各种符号并将不同的代码和数据段连接在一起形成统一的整体。
1.1 目标文件的格式
计算机编程领域中存在许多著名的目标文件格式。DOS 系列包括 COM、OBJ 和 EXE 格式。UNIX 和 Linux 使用 a.out、COFF 和 ELF。Microsoft® Windows® 使用可移植的执行文件 (PE) 格式,而 Macintosh 使用 PEF、Mach-O 和其他文件格式。
最初,各种类型的计算机具有自己独特的目标文件格式,但随着 UNIX 和其他在不同硬件平台上提供可移植性的操作系统的出现,一些常用的文件格式上升为通用的标准。其中包括 a.out、COFF 和 ELF 格式。
要了解目标文件,需要一组可以读取目标文件中不同部分并以更易于读取的格式显示这些内容的工具。
1.2 UNIX 目标文件
写一个简单的程序:hello.c
C 编译器的正常输出是用于所指定的目标处理器的汇编代码。汇编代码是汇编器的输入,在缺省情况下,汇编器将生成所有目标文件的祖先,即 a.out 文件。这个名称本身表示汇编输出 (Assembler Output)。要创建 a.out 文件,可以在 shell 窗口中输入下面的命令:gcc hello.c
最新的 C 编译器将编译和汇编步骤组合成一个步骤。我们可以指定不同开关选项以查看 C 编译器的汇编输出。通过输入下面的命令,我们可以看到 C 编译器的汇编输出:gcc -S hello.c
在当前目录下会生成 hello.s 文件,即为汇编输入文本。
-
接下来研究目标文件,其中使用的有价值的工具有:
- nm:列出目标文件中的符号。
- objdump:显示目标文件中的详细信息。
- readelf:显示关于 ELF 目标文件的信息。
1.2.1 nm:列出目标文件中的符号
执行命令:nm a.out
这些包含可执行代码的段称为正文段。同样地,数据段包含了不可执行的信息或数据。另一种类型的段,称为 BSS 段,它包含以符号数据开头的块。
对于 nm 命令列出的每个符号,它们的值使用十六进制来表示(缺省行为),并且在该符号前面加上了一个表示符号类型的编码字符。
-
常见的各种编码包括:
- A 表示绝对 (absolute),这意味着不能将该值更改为其他的连接;
- B 表示 BSS 段中的符号;
- C 表示引用未初始化的数据的一般符号。
可以将目标文件中所包含的不同的部分划分为段。段可以包含可执行代码、符号名称、初始数据值和许多其他类型的数据。
1.2.2 objdump:显示目标文件中的详细信息
通过输入下面的命令,可以看到目标文件中包含可执行代码的每个段的汇编清单。
objdump -d a.out
命令生成的代码如下所示:
1 a.out: file format elf64-x86-64 2 3 4 Disassembly of section .init: 5 6 00000000004003c8 <_init>: 7 4003c8: 48 83 ec 08 sub $0x8,%rsp 8 4003cc: 48 8b 05 25 0c 20 00 mov 0x200c25(%rip),%rax # 600ff8 <_DYNAMIC+0x1d0> 9 4003d3: 48 85 c0 test %rax,%rax 10 4003d6: 74 05 je 4003dd <_init+0x15> 11 4003d8: e8 43 00 00 00 callq 400420 <__libc_start_main@plt+0x10> 12 4003dd: 48 83 c4 08 add $0x8,%rsp 13 4003e1: c3 retq 14 15 Disassembly of section .plt: 16 17 00000000004003f0 <puts@plt-0x10>: 18 4003f0: ff 35 12 0c 20 00 pushq 0x200c12(%rip) # 601008 <_GLOBAL_OFFSET_TABLE_+0x8> 19 4003f6: ff 25 14 0c 20 00 jmpq *0x200c14(%rip) # 601010 <_GLOBAL_OFFSET_TABLE_+0x10> 20 4003fc: 0f 1f 40 00 nopl 0x0(%rax) 21 22 0000000000400400 <puts@plt>: 23 400400: ff 25 12 0c 20 00 jmpq *0x200c12(%rip) # 601018 <_GLOBAL_OFFSET_TABLE_+0x18> 24 400406: 68 00 00 00 00 pushq $0x0 25 40040b: e9 e0 ff ff ff jmpq 4003f0 <_init+0x28> 26 27 0000000000400410 <__libc_start_main@plt>: 28 400410: ff 25 0a 0c 20 00 jmpq *0x200c0a(%rip) # 601020 <_GLOBAL_OFFSET_TABLE_+0x20> 29 400416: 68 01 00 00 00 pushq $0x1 30 40041b: e9 d0 ff ff ff jmpq 4003f0 <_init+0x28> 31 32 Disassembly of section .plt.got: 33 34 0000000000400420 <.plt.got>: 35 400420: ff 25 d2 0b 20 00 jmpq *0x200bd2(%rip) # 600ff8 <_DYNAMIC+0x1d0> 36 400426: 66 90 xchg %ax,%ax 37 38 Disassembly of section .text: 39 40 0000000000400430 <_start>: 41 400430: 31 ed xor %ebp,%ebp 42 400432: 49 89 d1 mov %rdx,%r9 43 400435: 5e pop %rsi 44 400436: 48 89 e2 mov %rsp,%rdx 45 400439: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp 46 40043d: 50 push %rax 47 40043e: 54 push %rsp 48 40043f: 49 c7 c0 c0 05 40 00 mov $0x4005c0,%r8 49 400446: 48 c7 c1 50 05 40 00 mov $0x400550,%rcx 50 40044d: 48 c7 c7 26 05 40 00 mov $0x400526,%rdi 51 400454: e8 b7 ff ff ff callq 400410 <__libc_start_main@plt> 52 400459: f4 hlt 53 40045a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 54 55 0000000000400460 <deregister_tm_clones>: 56 400460: b8 3f 10 60 00 mov $0x60103f,%eax 57 400465: 55 push %rbp 58 400466: 48 2d 38 10 60 00 sub $0x601038,%rax 59 40046c: 48 83 f8 0e cmp $0xe,%rax 60 400470: 48 89 e5 mov %rsp,%rbp 61 400473: 76 1b jbe 400490 <deregister_tm_clones+0x30> 62 400475: b8 00 00 00 00 mov $0x0,%eax 63 40047a: 48 85 c0 test %rax,%rax 64 40047d: 74 11 je 400490 <deregister_tm_clones+0x30> 65 40047f: 5d pop %rbp 66 400480: bf 38 10 60 00 mov $0x601038,%edi 67 400485: ff e0 jmpq *%rax 68 400487: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1) 69 40048e: 00 00 70 400490: 5d pop %rbp 71 400491: c3 retq 72 400492: 0f 1f 40 00 nopl 0x0(%rax) 73 400496: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 74 40049d: 00 00 00 75 76 00000000004004a0 <register_tm_clones>: 77 4004a0: be 38 10 60 00 mov $0x601038,%esi 78 4004a5: 55 push %rbp 79 4004a6: 48 81 ee 38 10 60 00 sub $0x601038,%rsi 80 4004ad: 48 c1 fe 03 sar $0x3,%rsi 81 4004b1: 48 89 e5 mov %rsp,%rbp 82 4004b4: 48 89 f0 mov %rsi,%rax 83 4004b7: 48 c1 e8 3f shr $0x3f,%rax 84 4004bb: 48 01 c6 add %rax,%rsi 85 4004be: 48 d1 fe sar %rsi 86 4004c1: 74 15 je 4004d8 <register_tm_clones+0x38> 87 4004c3: b8 00 00 00 00 mov $0x0,%eax 88 4004c8: 48 85 c0 test %rax,%rax 89 4004cb: 74 0b je 4004d8 <register_tm_clones+0x38> 90 4004cd: 5d pop %rbp 91 4004ce: bf 38 10 60 00 mov $0x601038,%edi 92 4004d3: ff e0 jmpq *%rax 93 4004d5: 0f 1f 00 nopl (%rax) 94 4004d8: 5d pop %rbp 95 4004d9: c3 retq 96 4004da: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 97 98 00000000004004e0 <__do_global_dtors_aux>: 99 4004e0: 80 3d 51 0b 20 00 00 cmpb $0x0,0x200b51(%rip) # 601038 <__TMC_END__> 100 4004e7: 75 11 jne 4004fa <__do_global_dtors_aux+0x1a> 101 4004e9: 55 push %rbp 102 4004ea: 48 89 e5 mov %rsp,%rbp 103 4004ed: e8 6e ff ff ff callq 400460 <deregister_tm_clones> 104 4004f2: 5d pop %rbp 105 4004f3: c6 05 3e 0b 20 00 01 movb $0x1,0x200b3e(%rip) # 601038 <__TMC_END__> 106 4004fa: f3 c3 repz retq 107 4004fc: 0f 1f 40 00 nopl 0x0(%rax) 108 109 0000000000400500 <frame_dummy>: 110 400500: bf 20 0e 60 00 mov $0x600e20,%edi 111 400505: 48 83 3f 00 cmpq $0x0,(%rdi) 112 400509: 75 05 jne 400510 <frame_dummy+0x10> 113 40050b: eb 93 jmp 4004a0 <register_tm_clones> 114 40050d: 0f 1f 00 nopl (%rax) 115 400510: b8 00 00 00 00 mov $0x0,%eax 116 400515: 48 85 c0 test %rax,%rax 117 400518: 74 f1 je 40050b <frame_dummy+0xb> 118 40051a: 55 push %rbp 119 40051b: 48 89 e5 mov %rsp,%rbp 120 40051e: ff d0 callq *%rax 121 400520: 5d pop %rbp 122 400521: e9 7a ff ff ff jmpq 4004a0 <register_tm_clones> 123 124 0000000000400526 <main>: 125 400526: 55 push %rbp 126 400527: 48 89 e5 mov %rsp,%rbp 127 40052a: 48 83 ec 10 sub $0x10,%rsp 128 40052e: 89 7d fc mov %edi,-0x4(%rbp) 129 400531: 48 89 75 f0 mov %rsi,-0x10(%rbp) 130 400535: bf d4 05 40 00 mov $0x4005d4,%edi 131 40053a: e8 c1 fe ff ff callq 400400 <puts@plt> 132 40053f: b8 00 00 00 00 mov $0x0,%eax 133 400544: c9 leaveq 134 400545: c3 retq 135 400546: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 136 40054d: 00 00 00 137 138 0000000000400550 <__libc_csu_init>: 139 400550: 41 57 push %r15 140 400552: 41 56 push %r14 141 400554: 41 89 ff mov %edi,%r15d 142 400557: 41 55 push %r13 143 400559: 41 54 push %r12 144 40055b: 4c 8d 25 ae 08 20 00 lea 0x2008ae(%rip),%r12 # 600e10 <__frame_dummy_init_array_entry> 145 400562: 55 push %rbp 146 400563: 48 8d 2d ae 08 20 00 lea 0x2008ae(%rip),%rbp # 600e18 <__init_array_end> 147 40056a: 53 push %rbx 148 40056b: 49 89 f6 mov %rsi,%r14 149 40056e: 49 89 d5 mov %rdx,%r13 150 400571: 4c 29 e5 sub %r12,%rbp 151 400574: 48 83 ec 08 sub $0x8,%rsp 152 400578: 48 c1 fd 03 sar $0x3,%rbp 153 40057c: e8 47 fe ff ff callq 4003c8 <_init> 154 400581: 48 85 ed test %rbp,%rbp 155 400584: 74 20 je 4005a6 <__libc_csu_init+0x56> 156 400586: 31 db xor %ebx,%ebx 157 400588: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1) 158 40058f: 00 159 400590: 4c 89 ea mov %r13,%rdx 160 400593: 4c 89 f6 mov %r14,%rsi 161 400596: 44 89 ff mov %r15d,%edi 162 400599: 41 ff 14 dc callq *(%r12,%rbx,8) 163 40059d: 48 83 c3 01 add $0x1,%rbx 164 4005a1: 48 39 eb cmp %rbp,%rbx 165 4005a4: 75 ea jne 400590 <__libc_csu_init+0x40> 166 4005a6: 48 83 c4 08 add $0x8,%rsp 167 4005aa: 5b pop %rbx 168 4005ab: 5d pop %rbp 169 4005ac: 41 5c pop %r12 170 4005ae: 41 5d pop %r13 171 4005b0: 41 5e pop %r14 172 4005b2: 41 5f pop %r15 173 4005b4: c3 retq 174 4005b5: 90 nop 175 4005b6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 176 4005bd: 00 00 00 177 178 00000000004005c0 <__libc_csu_fini>: 179 4005c0: f3 c3 repz retq 180 181 Disassembly of section .fini: 182 183 00000000004005c4 <_fini>: 184 4005c4: 48 83 ec 08 sub $0x8,%rsp 185 4005c8: 48 83 c4 08 add $0x8,%rsp 186 4005cc: c3 retq
每个可执行代码段将在需要特定的事件时执行,这些事件包括库的初始化和该程序本身主入口点。
对于着迷于底层编程细节的程序员来说,这是一个功能非常强大的工具,可用于研究编译器和汇编器的输出。细节信息,比如这段代码中所显示的这些信息,可以揭示有关本地处理器本身运行方式的很多内容。对该处理器制造商提供的技术文档进行深入的研究,我们可以收集关于一些有价值的信息,通过这些信息可以深入地了解内部的运行机制,因为功能程序提供了清晰的输出。
1.2.3 readelf:显示关于 ELF 目标文件的信息
readelf 程序也可以清楚地列出目标文件中的内容。输入下面的命令,可以看到这一点:
readelf -all a.out
输出如下:
1 ELF Header: 2 Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 3 Class: ELF64 4 Data: 2's complement, little endian 5 Version: 1 (current) 6 OS/ABI: UNIX - System V 7 ABI Version: 0 8 Type: EXEC (Executable file) 9 Machine: Advanced Micro Devices X86-64 10 Version: 0x1 11 Entry point address: 0x400430 12 Start of program headers: 64 (bytes into file) 13 Start of section headers: 6616 (bytes into file) 14 Flags: 0x0 15 Size of this header: 64 (bytes) 16 Size of program headers: 56 (bytes) 17 Number of program headers: 9 18 Size of section headers: 64 (bytes) 19 Number of section headers: 31 20 Section header string table index: 28 21 22 Section Headers: 23 [Nr] Name Type Address Offset 24 Size EntSize Flags Link Info Align 25 [ 0] NULL 0000000000000000 00000000 26 0000000000000000 0000000000000000 0 0 0 27 [ 1] .interp PROGBITS 0000000000400238 00000238 28 000000000000001c 0000000000000000 A 0 0 1 29 [ 2] .note.ABI-tag NOTE 0000000000400254 00000254 30 0000000000000020 0000000000000000 A 0 0 4 31 [ 3] .note.gnu.build-i NOTE 0000000000400274 00000274 32 0000000000000024 0000000000000000 A 0 0 4 33 [ 4] .gnu.hash GNU_HASH 0000000000400298 00000298 34 000000000000001c 0000000000000000 A 5 0 8 35 [ 5] .dynsym DYNSYM 00000000004002b8 000002b8 36 0000000000000060 0000000000000018 A 6 1 8 37 [ 6] .dynstr STRTAB 0000000000400318 00000318 38 000000000000003d 0000000000000000 A 0 0 1 39 [ 7] .gnu.version VERSYM 0000000000400356 00000356 40 0000000000000008 0000000000000002 A 5 0 2 41 [ 8] .gnu.version_r VERNEED 0000000000400360 00000360 42 0000000000000020 0000000000000000 A 6 1 8 43 [ 9] .rela.dyn RELA 0000000000400380 00000380 44 0000000000000018 0000000000000018 A 5 0 8 45 [10] .rela.plt RELA 0000000000400398 00000398 46 0000000000000030 0000000000000018 AI 5 24 8 47 [11] .init PROGBITS 00000000004003c8 000003c8 48 000000000000001a 0000000000000000 AX 0 0 4 49 [12] .plt PROGBITS 00000000004003f0 000003f0 50 0000000000000030 0000000000000010 AX 0 0 16 51 [13] .plt.got PROGBITS 0000000000400420 00000420 52 0000000000000008 0000000000000000 AX 0 0 8 53 [14] .text PROGBITS 0000000000400430 00000430 54 0000000000000192 0000000000000000 AX 0 0 16 55 [15] .fini PROGBITS 00000000004005c4 000005c4 56 0000000000000009 0000000000000000 AX 0 0 4 57 [16] .rodata PROGBITS 00000000004005d0 000005d0 58 0000000000000011 0000000000000000 A 0 0 4 59 [17] .eh_frame_hdr PROGBITS 00000000004005e4 000005e4 60 0000000000000034 0000000000000000 A 0 0 4 61 [18] .eh_frame PROGBITS 0000000000400618 00000618 62 00000000000000f4 0000000000000000 A 0 0 8 63 [19] .init_array INIT_ARRAY 0000000000600e10 00000e10 64 0000000000000008 0000000000000000 WA 0 0 8 65 [20] .fini_array FINI_ARRAY 0000000000600e18 00000e18 66 0000000000000008 0000000000000000 WA 0 0 8 67 [21] .jcr PROGBITS 0000000000600e20 00000e20 68 0000000000000008 0000000000000000 WA 0 0 8 69 [22] .dynamic DYNAMIC 0000000000600e28 00000e28 70 00000000000001d0 0000000000000010 WA 6 0 8 71 [23] .got PROGBITS 0000000000600ff8 00000ff8 72 0000000000000008 0000000000000008 WA 0 0 8 73 [24] .got.plt PROGBITS 0000000000601000 00001000 74 0000000000000028 0000000000000008 WA 0 0 8 75 [25] .data PROGBITS 0000000000601028 00001028 76 0000000000000010 0000000000000000 WA 0 0 8 77 [26] .bss NOBITS 0000000000601038 00001038 78 0000000000000008 0000000000000000 WA 0 0 1 79 [27] .comment PROGBITS 0000000000000000 00001038 80 0000000000000035 0000000000000001 MS 0 0 1 81 [28] .shstrtab STRTAB 0000000000000000 000018cc 82 000000000000010c 0000000000000000 0 0 1 83 [29] .symtab SYMTAB 0000000000000000 00001070 84 0000000000000648 0000000000000018 30 47 8 85 [30] .strtab STRTAB 0000000000000000 000016b8 86 0000000000000214 0000000000000000 0 0 1 87 Key to Flags: 88 W (write), A (alloc), X (execute), M (merge), S (strings), l (large) 89 I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) 90 O (extra OS processing required) o (OS specific), p (processor specific) 91 92 There are no section groups in this file. 93 94 Program Headers: 95 Type Offset VirtAddr PhysAddr 96 FileSiz MemSiz Flags Align 97 PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040 98 0x00000000000001f8 0x00000000000001f8 R E 8 99 INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238 100 0x000000000000001c 0x000000000000001c R 1 101 [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] 102 LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000 103 0x000000000000070c 0x000000000000070c R E 200000 104 LOAD 0x0000000000000e10 0x0000000000600e10 0x0000000000600e10 105 0x0000000000000228 0x0000000000000230 RW 200000 106 DYNAMIC 0x0000000000000e28 0x0000000000600e28 0x0000000000600e28 107 0x00000000000001d0 0x00000000000001d0 RW 8 108 NOTE 0x0000000000000254 0x0000000000400254 0x0000000000400254 109 0x0000000000000044 0x0000000000000044 R 4 110 GNU_EH_FRAME 0x00000000000005e4 0x00000000004005e4 0x00000000004005e4 111 0x0000000000000034 0x0000000000000034 R 4 112 GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 113 0x0000000000000000 0x0000000000000000 RW 10 114 GNU_RELRO 0x0000000000000e10 0x0000000000600e10 0x0000000000600e10 115 0x00000000000001f0 0x00000000000001f0 R 1 116 117 Section to Segment mapping: 118 Segment Sections... 119 00 120 01 .interp 121 02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame 122 03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss 123 04 .dynamic 124 05 .note.ABI-tag .note.gnu.build-id 125 06 .eh_frame_hdr 126 07 127 08 .init_array .fini_array .jcr .dynamic .got 128 129 Dynamic section at offset 0xe28 contains 24 entries: 130 Tag Type Name/Value 131 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 132 0x000000000000000c (INIT) 0x4003c8 133 0x000000000000000d (FINI) 0x4005c4 134 0x0000000000000019 (INIT_ARRAY) 0x600e10 135 0x000000000000001b (INIT_ARRAYSZ) 8 (bytes) 136 0x000000000000001a (FINI_ARRAY) 0x600e18 137 0x000000000000001c (FINI_ARRAYSZ) 8 (bytes) 138 0x000000006ffffef5 (GNU_HASH) 0x400298 139 0x0000000000000005 (STRTAB) 0x400318 140 0x0000000000000006 (SYMTAB) 0x4002b8 141 0x000000000000000a (STRSZ) 61 (bytes) 142 0x000000000000000b (SYMENT) 24 (bytes) 143 0x0000000000000015 (DEBUG) 0x0 144 0x0000000000000003 (PLTGOT) 0x601000 145 0x0000000000000002 (PLTRELSZ) 48 (bytes) 146 0x0000000000000014 (PLTREL) RELA 147 0x0000000000000017 (JMPREL) 0x400398 148 0x0000000000000007 (RELA) 0x400380 149 0x0000000000000008 (RELASZ) 24 (bytes) 150 0x0000000000000009 (RELAENT) 24 (bytes) 151 0x000000006ffffffe (VERNEED) 0x400360 152 0x000000006fffffff (VERNEEDNUM) 1 153 0x000000006ffffff0 (VERSYM) 0x400356 154 0x0000000000000000 (NULL) 0x0 155 156 Relocation section '.rela.dyn' at offset 0x380 contains 1 entries: 157 Offset Info Type Sym. Value Sym. Name + Addend 158 000000600ff8 000300000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0 159 160 Relocation section '.rela.plt' at offset 0x398 contains 2 entries: 161 Offset Info Type Sym. Value Sym. Name + Addend 162 000000601018 000100000007 R_X86_64_JUMP_SLO 0000000000000000 puts@GLIBC_2.2.5 + 0 163 000000601020 000200000007 R_X86_64_JUMP_SLO 0000000000000000 __libc_start_main@GLIBC_2.2.5 + 0 164 165 The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported. 166 167 Symbol table '.dynsym' contains 4 entries: 168 Num: Value Size Type Bind Vis Ndx Name 169 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 170 1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (2) 171 2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2) 172 3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 173 174 Symbol table '.symtab' contains 67 entries: 175 Num: Value Size Type Bind Vis Ndx Name 176 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 177 1: 0000000000400238 0 SECTION LOCAL DEFAULT 1 178 2: 0000000000400254 0 SECTION LOCAL DEFAULT 2 179 3: 0000000000400274 0 SECTION LOCAL DEFAULT 3 180 4: 0000000000400298 0 SECTION LOCAL DEFAULT 4 181 5: 00000000004002b8 0 SECTION LOCAL DEFAULT 5 182 6: 0000000000400318 0 SECTION LOCAL DEFAULT 6 183 7: 0000000000400356 0 SECTION LOCAL DEFAULT 7 184 8: 0000000000400360 0 SECTION LOCAL DEFAULT 8 185 9: 0000000000400380 0 SECTION LOCAL DEFAULT 9 186 10: 0000000000400398 0 SECTION LOCAL DEFAULT 10 187 11: 00000000004003c8 0 SECTION LOCAL DEFAULT 11 188 12: 00000000004003f0 0 SECTION LOCAL DEFAULT 12 189 13: 0000000000400420 0 SECTION LOCAL DEFAULT 13 190 14: 0000000000400430 0 SECTION LOCAL DEFAULT 14 191 15: 00000000004005c4 0 SECTION LOCAL DEFAULT 15 192 16: 00000000004005d0 0 SECTION LOCAL DEFAULT 16 193 17: 00000000004005e4 0 SECTION LOCAL DEFAULT 17 194 18: 0000000000400618 0 SECTION LOCAL DEFAULT 18 195 19: 0000000000600e10 0 SECTION LOCAL DEFAULT 19 196 20: 0000000000600e18 0 SECTION LOCAL DEFAULT 20 197 21: 0000000000600e20 0 SECTION LOCAL DEFAULT 21 198 22: 0000000000600e28 0 SECTION LOCAL DEFAULT 22 199 23: 0000000000600ff8 0 SECTION LOCAL DEFAULT 23 200 24: 0000000000601000 0 SECTION LOCAL DEFAULT 24 201 25: 0000000000601028 0 SECTION LOCAL DEFAULT 25 202 26: 0000000000601038 0 SECTION LOCAL DEFAULT 26 203 27: 0000000000000000 0 SECTION LOCAL DEFAULT 27 204 28: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c 205 29: 0000000000600e20 0 OBJECT LOCAL DEFAULT 21 __JCR_LIST__ 206 30: 0000000000400460 0 FUNC LOCAL DEFAULT 14 deregister_tm_clones 207 31: 00000000004004a0 0 FUNC LOCAL DEFAULT 14 register_tm_clones 208 32: 00000000004004e0 0 FUNC LOCAL DEFAULT 14 __do_global_dtors_aux 209 33: 0000000000601038 1 OBJECT LOCAL DEFAULT 26 completed.7594 210 34: 0000000000600e18 0 OBJECT LOCAL DEFAULT 20 __do_global_dtors_aux_fin 211 35: 0000000000400500 0 FUNC LOCAL DEFAULT 14 frame_dummy 212 36: 0000000000600e10 0 OBJECT LOCAL DEFAULT 19 __frame_dummy_init_array_ 213 37: 0000000000000000 0 FILE LOCAL DEFAULT ABS hello.c 214 38: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c 215 39: 0000000000400708 0 OBJECT LOCAL DEFAULT 18 __FRAME_END__ 216 40: 0000000000600e20 0 OBJECT LOCAL DEFAULT 21 __JCR_END__ 217 41: 0000000000000000 0 FILE LOCAL DEFAULT ABS 218 42: 0000000000600e18 0 NOTYPE LOCAL DEFAULT 19 __init_array_end 219 43: 0000000000600e28 0 OBJECT LOCAL DEFAULT 22 _DYNAMIC 220 44: 0000000000600e10 0 NOTYPE LOCAL DEFAULT 19 __init_array_start 221 45: 00000000004005e4 0 NOTYPE LOCAL DEFAULT 17 __GNU_EH_FRAME_HDR 222 46: 0000000000601000 0 OBJECT LOCAL DEFAULT 24 _GLOBAL_OFFSET_TABLE_ 223 47: 00000000004005c0 2 FUNC GLOBAL DEFAULT 14 __libc_csu_fini 224 48: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab 225 49: 0000000000601028 0 NOTYPE WEAK DEFAULT 25 data_start 226 50: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@@GLIBC_2.2.5 227 51: 0000000000601038 0 NOTYPE GLOBAL DEFAULT 25 _edata 228 52: 00000000004005c4 0 FUNC GLOBAL DEFAULT 15 _fini 229 53: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_ 230 54: 0000000000601028 0 NOTYPE GLOBAL DEFAULT 25 __data_start 231 55: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 232 56: 0000000000601030 0 OBJECT GLOBAL HIDDEN 25 __dso_handle 233 57: 00000000004005d0 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used 234 58: 0000000000400550 101 FUNC GLOBAL DEFAULT 14 __libc_csu_init 235 59: 0000000000601040 0 NOTYPE GLOBAL DEFAULT 26 _end 236 60: 0000000000400430 42 FUNC GLOBAL DEFAULT 14 _start 237 61: 0000000000601038 0 NOTYPE GLOBAL DEFAULT 26 __bss_start 238 62: 0000000000400526 32 FUNC GLOBAL DEFAULT 14 main 239 63: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses 240 64: 0000000000601038 0 OBJECT GLOBAL HIDDEN 25 __TMC_END__ 241 65: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable 242 66: 00000000004003c8 0 FUNC GLOBAL DEFAULT 11 _init 243 244 Version symbols section '.gnu.version' contains 4 entries: 245 Addr: 0000000000400356 Offset: 0x000356 Link: 5 (.dynsym) 246 000: 0 (*local*) 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 0 (*local*) 247 248 Version needs section '.gnu.version_r' contains 1 entries: 249 Addr: 0x0000000000400360 Offset: 0x000360 Link: 6 (.dynstr) 250 000000: Version: 1 File: libc.so.6 Cnt: 1 251 0x0010: Name: GLIBC_2.2.5 Flags: none Version: 2 252 253 Displaying notes found at file offset 0x00000254 with length 0x00000020: 254 Owner Data size Description 255 GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag) 256 OS: Linux, ABI: 2.6.32 257 258 Displaying notes found at file offset 0x00000274 with length 0x00000024: 259 Owner Data size Description 260 GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring) 261 Build ID: c0f3db4f9706877127ed96aa53ddd338e1632814
ELF Header 为该文件中所有段入口显示了详细的摘要。在列举出这些 Header 中的内容之前,可以看到 Header 的具体数目。在研究一个较大的目标文件时,该信息可能非常有用。
从该输出中看到的,简单的 a.out Hello World 文件中包含了大量有价值的细节信息,包括版本信息、柱状图、各种符号类型的表格,等等。
除了所有这些段之外,编译器可以将调试信息放入到目标文件中,并且还可以显示这些信息。输入下面的命令,仔细分析编译器的输出(假设您扮演了调试程序的角色):readelf --debug-dump a.out | less
1.3 目标文件
在 UNIX 中,可执行文件是目标文件,并且我们可以像对 a.out 文件那样对它们进行分析。
如果倾向于使用编译器和其他的语言工具,那么您可以对组成计算机系统的各种目标文件进行仔细研究。UNIX 操作系统具有许多层次,那些通过工具查看目标文件所公开的层次,非常接近底层硬件。通过这种方式,可以真实地接触到系统。