UNIX(R) 系统中运行的程序遵守一种称为目标文件格式的精心设计。了解更多关于目标文件格式的内容,以及可以用来研究系统中目标文件的工具。
计算机编程的最新技术将一种特殊的人性与一组特殊的工具结合在一起,用以生产出对其他人非常有帮助的一种神奇的产品,即软件。计算机程序员是一群注重细节的人,他们可以处理计算机中各种各样的困难。计算机的要求非常苛刻,并且不能容忍其中存在任何的偏差。毫无疑问,无论您的个性如何以及在工作中使用了何种辅助工具,计算机程序的编写都是非常困难的。
在 UNIX® 和 Linux® 中,任何事物都是文件。您可以认为,UNIX 和 Linux 编程实际上是编写处理各种文件的代码。系统由许多类型的文件组成,但目标文件具有一种特殊的设计,提供了灵活和多样的用途。
目标文件是包含带有附加地址和值的助记符号的路线图。这些符号可以用来对各种代码段和数据段进行命名,包括经过初始化的和未初始化的。它们也可以用来定位嵌入的调试信息,就像语义 Web,非常适合由程序进行阅读。
行业工具
计算机编程中使用的工具包括代码编辑器,如 vi 或 Emacs,您可以使用这些工具输入和编辑希望计算机在完成所需任务时执行的指令,以及编译器和连接器,它们可以生成真正实现这些目标的机器代码。
高级的工具,称为集成调试环境 (IDE),它以统一的外观集成了不同工具的功能。IDE 使得编辑器、编译器、连接器和调试器之间的界限变得很模糊。因此,为了更深入地研究和了解系统,在使用集成的套件之前,最好先单独地使用这些工具。(注意:IDE 也通常被称为集成开发环境。)
编译器可以将您在代码编辑器中创建的文本转换为目标文件。最初,目标文件被称为代码的中间表示形式,因为它用作连接编辑器(即连接器)的输入,而连接编辑器最终完成整个任务并生成可执行的程序作为输出。
从代码到可执行代码的转换过程经过了良好的定义并实现了自动化,而目标文件是这个链中有机的连接性环节。在这个转换过程中,目标文件作为连接编辑器所使用的映象,使得它们能够解析各种符号并将不同的代码和数据段连接在一起形成统一的整体。
历史
计算机编程领域中存在许多著名的目标文件格式。DOS 系列包括 COM、OBJ 和 EXE 格式。UNIX 和 Linux 使用 a.out、COFF 和 ELF。Microsoft® Windows® 使用可移植的执行文件 (PE) 格式,而 Macintosh 使用 PEF、Mach-O 和其他文件格式。
最初,各种类型的计算机具有自己独特的目标文件格式,但随着 UNIX 和其他在不同硬件平台上提供可移植性的操作系统的出现,一些常用的文件格式上升为通用的标准。其中包括 a.out、COFF 和 ELF 格式。
要了解目标文件,需要一组可以读取目标文件中不同部分并以更易于读取的格式显示这些内容的工具。本文将讨论这些工具中比较重要的方面。但首先,您必须创建一个工作台,并在其中建立一个研究对象。
工作台
启动一个 xterm 会话,让我们先创建一个空白的工作台,并开始对目标文件进行研究。下面的命令创建了一个目录,可以将目标文件放到该目录中进行研究:
cd
mkdir src
cd src
mkdir hw
cd hw |
然后,使用您最喜欢的代码编辑器,在 $HOME/src/hw 目录中输入清单 1 中的程序,并命名为 hw.c。
清单 1. hw.c 程序
#include <stdio.h>
int main(void)
{
printf("Hello World!\n");
return 0;
}
|
要使用 UNIX 工具库中提供的各种工具,可以将这个简单的“Hello World”程序作为研究的对象。您将学习构建和查看目标文件的输出,而不是使用任何快捷方法直接创建可执行文件(的确有许多这样的快捷方法)。
文件格式
C 编译器的正常输出是用于您所指定的目标处理器的汇编代码。汇编代码是汇编器的输入,在缺省情况下,汇编器将生成所有目标文件的祖先,即 a.out 文件。这个名称本身表示汇编输出 (Assembler Output)。要创建 a.out 文件,可以在 xterm 窗口中输入下面的命令:
注意:如果出现了任何错误或者没有创建 a.out 文件,那么您可能需要检查自己的系统或源文件 (hw.c),以找出其中的错误。还需要检查是否已将 cc 定义为运行您的 C/C++ 编译器。
最新的 C 编译器将编译和汇编步骤组合成一个步骤。您可以指定不同开关选项以查看 C 编译器的汇编输出。通过输入下面的命令,您可以看到 C 编译器的汇编输出:
这个命令生成了一个新的文件 hw.s,其中包含您通常无法看到的汇编输入文本,因为编译器在缺省情况下将生成 a.out 文件。正如所预期的,UNIX 汇编程序可以对这种输入文件进行汇编,以生成 a.out 文件。
080482e4 <call_gmon_start>:
80482e4: 55 push %ebp
80482e5: 89 e5 mov %esp,%ebp
80482e7: 53 push %ebx
80482e8: e8 1b 00 00 00 call 8048308 <__i686.get_pc_thunk.bx>
80482ed: 81 c3 87 12 00 00 add $0x1287,%ebx
80482f3: 83 ec 04 sub $0x4,%esp
80482f6: 8b 83 fc ff ff ff mov 0xfffffffc(%ebx),%eax
80482fc: 85 c0 test %eax,%eax
80482fe: 74 02 je 8048302 <call_gmon_start+0x1e>
8048300: ff d0 call *%eax
8048302: 83 c4 04 add $0x4,%esp
8048305: 5b pop %ebx
8048306: 5d pop %ebp
8048307: c3 ret
08048308 <__i686.get_pc_thunk.bx>:
8048308: 8b 1c 24 mov (%esp),%ebx
804830b: c3 ret
0804830c <__do_global_dtors_aux>:
804830c: 55 push %ebp
804830d: 89 e5 mov %esp,%ebp
804830f: 83 ec 08 sub $0x8,%esp
8048312: 80 3d 94 95 04 08 00 cmpb $0x0,0x8049594
8048319: 74 0c je 8048327 <__do_global_dtors_aux+0x1b>
804831b: eb 1c jmp 8048339 <__do_global_dtors_aux+0x2d>
804831d: 83 c0 04 add $0x4,%eax
8048320: a3 90 95 04 08 mov %eax,0x8049590
8048325: ff d2 call *%edx
8048327: a1 90 95 04 08 mov 0x8049590,%eax
804832c: 8b 10 mov (%eax),%edx
804832e: 85 d2 test %edx,%edx
8048330: 75 eb jne 804831d <__do_global_dtors_aux+0x11>
8048332: c6 05 94 95 04 08 01 movb $0x1,0x8049594
8048339: c9 leave
804833a: c3 ret
0804833b <frame_dummy>:
804833b: 55 push %ebp
804833c: 89 e5 mov %esp,%ebp
804833e: 83 ec 08 sub $0x8,%esp
8048341: a1 a4 94 04 08 mov 0x80494a4,%eax
8048346: 85 c0 test %eax,%eax
8048348: 74 12 je 804835c <frame_dummy+0x21>
804834a: b8 00 00 00 00 mov $0x0,%eax
804834f: 85 c0 test %eax,%eax
8048351: 74 09 je 804835c <frame_dummy+0x21>
8048353: c7 04 24 a4 94 04 08 movl $0x80494a4,(%esp)
804835a: ff d0 call *%eax
804835c: c9 leave
804835d: c3 ret
804835e: 90 nop
804835f: 90 nop
08048360 <main>:
8048360: 55 push %ebp
8048361: 89 e5 mov %esp,%ebp
8048363: 83 ec 08 sub $0x8,%esp
8048366: 83 e4 f0 and $0xfffffff0,%esp
8048369: b8 00 00 00 00 mov $0x0,%eax
804836e: 83 c0 0f add $0xf,%eax
8048371: 83 c0 0f add $0xf,%eax
8048374: c1 e8 04 shr $0x4,%eax
8048377: c1 e0 04 shl $0x4,%eax
804837a: 29 c4 sub %eax,%esp
804837c: c7 04 24 80 84 04 08 movl $0x8048480,(%esp)
8048383: e8 18 ff ff ff call 80482a0 <puts@plt>
8048388: b8 00 00 00 00 mov $0x0,%eax
804838d: c9 leave
804838e: c3 ret
804838f: 90 nop
08048390 <__libc_csu_init>:
8048390: 55 push %ebp
8048391: 89 e5 mov %esp,%ebp
8048393: 57 push %edi
8048394: 56 push %esi
8048395: 31 f6 xor %esi,%esi
8048397: 53 push %ebx
8048398: e8 6b ff ff ff call 8048308 <__i686.get_pc_thunk.bx>
804839d: 81 c3 d7 11 00 00 add $0x11d7,%ebx
80483a3: 83 ec 0c sub $0xc,%esp
80483a6: e8 cd fe ff ff call 8048278 <_init>
80483ab: 8d 83 20 ff ff ff lea 0xffffff20(%ebx),%eax
80483b1: 8d 93 20 ff ff ff lea 0xffffff20(%ebx),%edx
80483b7: 89 45 f0 mov %eax,0xfffffff0(%ebp)
80483ba: 29 d0 sub %edx,%eax
80483bc: c1 f8 02 sar $0x2,%eax
80483bf: 39 c6 cmp %eax,%esi
80483c1: 73 16 jae 80483d9 <__libc_csu_init+0x49>
80483c3: 89 d7 mov %edx,%edi
80483c5: ff 14 b2 call *(%edx,%esi,4)
80483c8: 8b 45 f0 mov 0xfffffff0(%ebp),%eax
80483cb: 83 c6 01 add $0x1,%esi
80483ce: 29 f8 sub %edi,%eax
80483d0: 89 fa mov %edi,%edx
80483d2: c1 f8 02 sar $0x2,%eax
80483d5: 39 c6 cmp %eax,%esi
80483d7: 72 ec jb 80483c5 <__libc_csu_init+0x35>
80483d9: 83 c4 0c add $0xc,%esp
80483dc: 5b pop %ebx
80483dd: 5e pop %esi
80483de: 5f pop %edi
80483df: 5d pop %ebp
80483e0: c3 ret
080483e1 <__libc_csu_fini>:
80483e1: 55 push %ebp
80483e2: 89 e5 mov %esp,%ebp
80483e4: 83 ec 18 sub $0x18,%esp
80483e7: 89 5d f4 mov %ebx,0xfffffff4(%ebp)
80483ea: e8 19 ff ff ff call 8048308 <__i686.get_pc_thunk.bx>
80483ef: 81 c3 85 11 00 00 add $0x1185,%ebx
80483f5: 89 75 f8 mov %esi,0xfffffff8(%ebp)
80483f8: 89 7d fc mov %edi,0xfffffffc(%ebp)
80483fb: 8d b3 20 ff ff ff lea 0xffffff20(%ebx),%esi
8048401: 8d bb 20 ff ff ff lea 0xffffff20(%ebx),%edi
8048407: 29 fe sub %edi,%esi
8048409: c1 fe 02 sar $0x2,%esi
804840c: eb 03 jmp 8048411 <__libc_csu_fini+0x30>
804840e: ff 14 b7 call *(%edi,%esi,4)
8048411: 83 ee 01 sub $0x1,%esi
8048414: 83 fe ff cmp $0xffffffff,%esi
8048417: 75 f5 jne 804840e <__libc_csu_fini+0x2d>
8048419: e8 3a 00 00 00 call 8048458 <_fini>
804841e: 8b 5d f4 mov 0xfffffff4(%ebp),%ebx
8048421: 8b 75 f8 mov 0xfffffff8(%ebp),%esi
8048424: 8b 7d fc mov 0xfffffffc(%ebp),%edi
8048427: 89 ec mov %ebp,%esp
8048429: 5d pop %ebp
804842a: c3 ret
804842b: 90 nop
0804842c <__do_global_ctors_aux>:
804842c: 55 push %ebp
804842d: 89 e5 mov %esp,%ebp
804842f: 53 push %ebx
8048430: 83 ec 04 sub $0x4,%esp
8048433: a1 94 94 04 08 mov 0x8049494,%eax
8048438: 83 f8 ff cmp $0xffffffff,%eax
804843b: 74 12 je 804844f <__do_global_ctors_aux+0x23>
804843d: bb 94 94 04 08 mov $0x8049494,%ebx
8048442: ff d0 call *%eax
8048444: 8b 43 fc mov 0xfffffffc(%ebx),%eax
8048447: 83 eb 04 sub $0x4,%ebx
804844a: 83 f8 ff cmp $0xffffffff,%eax
804844d: 75 f3 jne 8048442 <__do_global_ctors_aux+0x16>
804844f: 83 c4 04 add $0x4,%esp
8048452: 5b pop %ebx
8048453: 5d pop %ebp
8048454: c3 ret
8048455: 90 nop
8048456: 90 nop
8048457: 90 nop
Disassembly of section .fini:
08048458 <_fini>:
8048458: 55 push %ebp
8048459: 89 e5 mov %esp,%ebp
804845b: 53 push %ebx
804845c: e8 a7 fe ff ff call 8048308 <__i686.get_pc_thunk.bx>
8048461: 81 c3 13 11 00 00 add $0x1113,%ebx
8048467: 83 ec 04 sub $0x4,%esp
804846a: e8 9d fe ff ff call 804830c <__do_global_dtors_aux>
804846f: 83 c4 04 add $0x4,%esp
8048472: 5b pop %ebx
8048473: 5d pop %ebp
8048474: c3 ret