您的位置:首页技术文章
文章详情页

UNIX 目标文件初探

浏览:62日期:2024-06-15 15:00:36

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 会话,让我们先创建一个空白的工作台,并开始对目标文件进行研究。下面的命令创建了一个目录,可以将目标文件放到该目录中进行研究:

cdmkdir srccd srcmkdir hwcd hw

然后,使用您最喜欢的代码编辑器,在 $HOME/src/hw 目录中输入清单 1 中的程序,并命名为 hw.c。

清单 1. hw.c 程序#include <stdio.h>int main(void){ printf("Hello World!"); return 0;}

要使用 UNIX 工具库中提供的各种工具,可以将这个简单的“Hello World程序作为研究的对象。您将学习构建和查看目标文件的输出,而不是使用任何快捷方法直接创建可执行文件(的确有许多这样的快捷方法)。

文件格式

C 编译器的正常输出是用于您所指定的目标处理器的汇编代码。汇编代码是汇编器的输入,在缺省情况下,汇编器将生成所有目标文件的祖先,即 a.out 文件。这个名称本身表示汇编输出 (Assembler Output)。要创建 a.out 文件,可以在 xterm 窗口中输入下面的命令:

cc hw.c

注意:如果出现了任何错误或者没有创建 a.out 文件,那么您可能需要检查自己的系统或源文件 (hw.c),以找出其中的错误。还需要检查是否已将 cc 定义为运行您的 C/C++ 编译器。

最新的 C 编译器将编译和汇编步骤组合成一个步骤。您可以指定不同开关选项以查看 C 编译器的汇编输出。通过输入下面的命令,您可以看到 C 编译器的汇编输出:

cc -S hw.c

这个命令生成了一个新的文件 hw.s,其中包含您通常无法看到的汇编输入文本,因为编译器在缺省情况下将生成 a.out 文件。正如所预期的,Unix 汇编程序可以对这种输入文件进行汇编,以生成 a.out 文件。

UNIX 特定的工具

假定编译过程一切顺利,那么在该目录中就有了一个 a.out 文件,下面让我们来对其进行研究。有许多可用于研究目标文件的有价值的工具,下面便是其中一组:

nm:列出目标文件中的符号。 objdump:显示目标文件中的详细信息。 readelf:显示关于 ELF 目标文件的信息。

列表中的第一个工具是 nm,它可以列出目标文件中的符号。如果您输入 nm 命令,您将注意到在缺省情况下,它会寻找一个名为 a.out 的文件。如果没有找到该文件,这个工具会给出相应的提示。然而,如果该工具找到了编译器创建的 a.out 文件,它将显示类似清单 2 的清单。

清单 2. nm 命令的输出08049594 A __bss_start080482e4 t call_gmon_start08049594 b completed.446308049498 d __CTOR_END__08049494 d __CTOR_LIST__08049588 D __data_start08049588 W data_start0804842c t __do_global_ctors_aux0804830c t __do_global_dtors_aux0804958c D __dso_handle080494a0 d __DTOR_END__0804949c d __DTOR_LIST__080494a8 d _DYNAMIC08049594 A _edata08049598 A _end08048458 T _fini08049494 a __fini_array_end08049494 a __fini_array_start08048478 R _fp_hw0804833b t frame_dummy08048490 r __FRAME_END__08049574 d _GLOBAL_OFFSET_TABLE_ w __gmon_start__08048308 T __i686.get_pc_thunk.bx08048278 T _init08049494 a __init_array_end08049494 a __init_array_start0804847c R _IO_stdin_used080494a4 d __JCR_END__080494a4 d __JCR_LIST__ w _Jv_RegisterClasses080483e1 T __libc_csu_fini08048390 T __libc_csu_init U __libc_start_main@@GLIBC_2.008048360 T main08049590 d p.4462 U puts@@GLIBC_2.0080482c0 T _start

这些包含可执行代码的段称为正文段。同样地,数据段包含了不可执行的信息或数据。另一种类型的段,称为 BSS 段,它包含以符号数据开头的块。

对于 nm 命令列出的每个符号,它们的值使用十六进制来表示(缺省行为),并且在该符号前面加上了一个表示符号类型的编码字符。常见的各种编码包括:A 表示绝对 (absolute),这意味着不能将该值更改为其他的连接;B 表示 BSS 段中的符号;而 C 表示引用未初始化的数据的一般符号。

可以将目标文件中所包含的不同的部分划分为段。段可以包含可执行代码、符号名称、初始数据值和许多其他类型的数据。有关这些类型的数据的详细信息,可以阅读 Unix 中 nm 的 man 页面,其中按照该命令输出中的字符编码分别对每种类型进行了描述。

细节,细节…

在目标文件阶段,即使是一个简单的 Hello World 程序,其中也包含了大量的细节信息。nm 程序可用于列举符号及其类型和值,但是,要更仔细地研究目标文件中这些命名段的内容,需要使用功能更强大的工具。

其中两种功能强大的工具是 objdump 和 readelf 程序。通过输入下面的命令,您可以看到目标文件中包含可执行代码的每个段的汇编清单。对于这么一个小的程序,编译器生成了这么多的代码,真的很令人惊异!

objdump -d a.out

这个命令生成的输出如清单 3 所示。每个可执行代码段将在需要特定的事件时执行,这些事件包括库的初始化和该程序本身主入口点。

清单 3. objdump 命令的输出a.out: file format elf32-i386Disassembly of section .init:08048278 <_init>:8048278:  55 push  %ebp8048279:  89 e5  mov%esp,%ebp804827b:  83 ec 08sub$0x8,%esp804827e:  e8 61 00 00 00 call  80482e4 <call_gmon_start>8048283:  e8 b3 00 00 00 call  804833b <frame_dummy>8048288:  e8 9f 01 00 00 call  804842c <__do_global_ctors_aux>804828d:  c9 leave804828e:  c3 retDisassembly of section .plt:08048290 <puts@plt-0x10>:8048290:  ff 35 78 95 04 08  pushl 0x80495788048296:  ff 25 7c 95 04 08  jmp*0x804957c804829c:  00 00  add%al,(%eax)...080482a0 <puts@plt>:80482a0:  ff 25 80 95 04 08  jmp*0x804958080482a6:  68 00 00 00 00 push  $0x080482ab:  e9 e0 ff ff ff jmp8048290 <_init+0x18>080482b0 <__libc_start_main@plt>:80482b0:  ff 25 84 95 04 08  jmp*0x804958480482b6:  68 08 00 00 00 push  $0x880482bb:  e9 d0 ff ff ff jmp8048290 <_init+0x18>Disassembly of section .text:080482c0 <_start>:80482c0:  31 ed  xor%ebp,%ebp80482c2:  5e pop%esi80482c3:  89 e1  mov%esp,%ecx80482c5:  83 e4 f0and$0xfffffff0,%esp80482c8:  50 push  %eax80482c9:  54 push  %esp80482ca:  52 push  %edx80482cb:  68 e1 83 04 08 push  $0x80483e180482d0:  68 90 83 04 08 push  $0x804839080482d5:  51 push  %ecx80482d6:  56 push  %esi80482d7:  68 60 83 04 08 push  $0x804836080482dc:  e8 cf ff ff ff call  80482b0 <__libc_start_main@plt>80482e1:  f4 hlt80482e2:  90 nop80482e3:  90 nop080482e4 <call_gmon_start>:80482e4:  55 push  %ebp80482e5:  89 e5  mov%esp,%ebp80482e7:  53 push  %ebx80482e8:  e8 1b 00 00 00 call  8048308 <__i686.get_pc_thunk.bx>80482ed:  81 c3 87 12 00 00  add$0x1287,%ebx80482f3:  83 ec 04sub$0x4,%esp80482f6:  8b 83 fc ff ff ff  mov0xfffffffc(%ebx),%eax80482fc:  85 c0  test  %eax,%eax80482fe:  74 02  je 8048302 <call_gmon_start+0x1e>8048300:  ff d0  call  *%eax8048302:  83 c4 04add$0x4,%esp8048305:  5b pop%ebx8048306:  5d pop%ebp8048307:  c3 ret08048308 <__i686.get_pc_thunk.bx>:8048308:  8b 1c 24mov(%esp),%ebx804830b:  c3 ret0804830c <__do_global_dtors_aux>:804830c:  55 push  %ebp804830d:  89 e5  mov%esp,%ebp804830f:  83 ec 08sub$0x8,%esp8048312:  80 3d 94 95 04 08 00cmpb  $0x0,0x80495948048319:  74 0c  je 8048327 <__do_global_dtors_aux+0x1b>804831b:  eb 1c  jmp8048339 <__do_global_dtors_aux+0x2d>804831d:  83 c0 04add$0x4,%eax8048320:  a3 90 95 04 08 mov%eax,0x80495908048325:  ff d2  call  *%edx8048327:  a1 90 95 04 08 mov0x8049590,%eax804832c:  8b 10  mov(%eax),%edx804832e:  85 d2  test  %edx,%edx8048330:  75 eb  jne804831d <__do_global_dtors_aux+0x11>8048332:  c6 05 94 95 04 08 01movb  $0x1,0x80495948048339:  c9 leave804833a:  c3 ret0804833b <frame_dummy>:804833b:  55 push  %ebp804833c:  89 e5  mov%esp,%ebp804833e:  83 ec 08sub$0x8,%esp8048341:  a1 a4 94 04 08 mov0x80494a4,%eax8048346:  85 c0  test  %eax,%eax8048348:  74 12  je 804835c <frame_dummy+0x21>804834a:  b8 00 00 00 00 mov$0x0,%eax804834f:  85 c0  test  %eax,%eax8048351:  74 09  je 804835c <frame_dummy+0x21>8048353:  c7 04 24 a4 94 04 08movl  $0x80494a4,(%esp)804835a:  ff d0  call  *%eax804835c:  c9 leave804835d:  c3 ret804835e:  90 nop804835f:  90 nop08048360 <main>:8048360:  55 push  %ebp8048361:  89 e5  mov%esp,%ebp8048363:  83 ec 08sub$0x8,%esp8048366:  83 e4 f0and$0xfffffff0,%esp8048369:  b8 00 00 00 00 mov$0x0,%eax804836e:  83 c0 0fadd$0xf,%eax8048371:  83 c0 0fadd$0xf,%eax8048374:  c1 e8 04shr$0x4,%eax8048377:  c1 e0 04shl$0x4,%eax804837a:  29 c4  sub%eax,%esp804837c:  c7 04 24 80 84 04 08movl  $0x8048480,(%esp)8048383:  e8 18 ff ff ff call  80482a0 <puts@plt>8048388:  b8 00 00 00 00 mov$0x0,%eax804838d:  c9 leave804838e:  c3 ret804838f:  90 nop08048390 <__libc_csu_init>:8048390:  55 push  %ebp8048391:  89 e5  mov%esp,%ebp8048393:  57 push  %edi8048394:  56 push  %esi8048395:  31 f6  xor%esi,%esi8048397:  53 push  %ebx8048398:  e8 6b ff ff ff call  8048308 <__i686.get_pc_thunk.bx>804839d:  81 c3 d7 11 00 00  add$0x11d7,%ebx80483a3:  83 ec 0csub$0xc,%esp80483a6:  e8 cd fe ff ff call  8048278 <_init>80483ab:  8d 83 20 ff ff ff  lea0xffffff20(%ebx),%eax80483b1:  8d 93 20 ff ff ff  lea0xffffff20(%ebx),%edx80483b7:  89 45 f0mov%eax,0xfffffff0(%ebp)80483ba:  29 d0  sub%edx,%eax80483bc:  c1 f8 02sar$0x2,%eax80483bf:  39 c6  cmp%eax,%esi80483c1:  73 16  jae80483d9 <__libc_csu_init+0x49>80483c3:  89 d7  mov%edx,%edi80483c5:  ff 14 b2call  *(%edx,%esi,4)80483c8:  8b 45 f0mov0xfffffff0(%ebp),%eax80483cb:  83 c6 01add$0x1,%esi80483ce:  29 f8  sub%edi,%eax80483d0:  89 fa  mov%edi,%edx80483d2:  c1 f8 02sar$0x2,%eax80483d5:  39 c6  cmp%eax,%esi80483d7:  72 ec  jb 80483c5 <__libc_csu_init+0x35>80483d9:  83 c4 0cadd$0xc,%esp80483dc:  5b pop%ebx80483dd:  5e pop%esi80483de:  5f pop%edi80483df:  5d pop%ebp80483e0:  c3 ret080483e1 <__libc_csu_fini>:80483e1:  55 push  %ebp80483e2:  89 e5  mov%esp,%ebp80483e4:  83 ec 18sub$0x18,%esp80483e7:  89 5d f4mov%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,%ebx80483f5:  89 75 f8mov%esi,0xfffffff8(%ebp)80483f8:  89 7d fcmov%edi,0xfffffffc(%ebp)80483fb:  8d b3 20 ff ff ff  lea0xffffff20(%ebx),%esi8048401:  8d bb 20 ff ff ff  lea0xffffff20(%ebx),%edi8048407:  29 fe  sub%edi,%esi8048409:  c1 fe 02sar$0x2,%esi804840c:  eb 03  jmp8048411 <__libc_csu_fini+0x30>804840e:  ff 14 b7call  *(%edi,%esi,4)8048411:  83 ee 01sub$0x1,%esi8048414:  83 fe ffcmp$0xffffffff,%esi8048417:  75 f5  jne804840e <__libc_csu_fini+0x2d>8048419:  e8 3a 00 00 00 call  8048458 <_fini>804841e:  8b 5d f4mov0xfffffff4(%ebp),%ebx8048421:  8b 75 f8mov0xfffffff8(%ebp),%esi8048424:  8b 7d fcmov0xfffffffc(%ebp),%edi8048427:  89 ec  mov%ebp,%esp8048429:  5d pop%ebp804842a:  c3 ret804842b:  90 nop0804842c <__do_global_ctors_aux>:804842c:  55 push  %ebp804842d:  89 e5  mov%esp,%ebp804842f:  53 push  %ebx8048430:  83 ec 04sub$0x4,%esp8048433:  a1 94 94 04 08 mov0x8049494,%eax8048438:  83 f8 ffcmp$0xffffffff,%eax804843b:  74 12  je 804844f <__do_global_ctors_aux+0x23>804843d:  bb 94 94 04 08 mov$0x8049494,%ebx8048442:  ff d0  call  *%eax8048444:  8b 43 fcmov0xfffffffc(%ebx),%eax8048447:  83 eb 04sub$0x4,%ebx804844a:  83 f8 ffcmp$0xffffffff,%eax804844d:  75 f3  jne8048442 <__do_global_ctors_aux+0x16>804844f:  83 c4 04add$0x4,%esp8048452:  5b pop%ebx8048453:  5d pop%ebp8048454:  c3 ret8048455:  90 nop8048456:  90 nop8048457:  90 nopDisassembly of section .fini:08048458 <_fini>:8048458:  55 push  %ebp8048459:  89 e5  mov%esp,%ebp804845b:  53 push  %ebx804845c:  e8 a7 fe ff ff call  8048308 <__i686.get_pc_thunk.bx>8048461:  81 c3 13 11 00 00  add$0x1113,%ebx8048467:  83 ec 04sub$0x4,%esp804846a:  e8 9d fe ff ff call  804830c <__do_global_dtors_aux>804846f:  83 c4 04add$0x4,%esp8048472:  5b pop%ebx8048473:  5d pop%ebp8048474:  c3 ret

正如从该输出中看到的,简单的 a.out Hello World 文件中包含了大量有价值的细节信息,包括版本信息、柱状图、各种符号类型的表格,等等。通过使用本文中介绍的这几种工具分析目标文件,您可以慢慢地对可执行程序进行研究。

除了所有这些段之外,编译器可以将调试信息放入到目标文件中,并且还可以显示这些信息。输入下面的命令,仔细分析编译器的输出(假设您扮演了调试程序的角色):

readelf --debug-dump a.out | less

这个命令生成的输出如清单 5 所示。调试工具,如 GDB,可以读取这些调试信息,并且当程序在调试器中运行的同时,您可以使用该工具显示更具描述性的标记,而不是对代码进行反汇编时的原始地址值。

清单 5. 该程序中的调试信息The section .debug_aranges contains: Length:  28 Version: 2 Offset into .debug_info: 0 Pointer Size: 4 Segment Size: 0Address Length080482c0 34 Length:  52 Version: 2 Offset into .debug_info: 10b Pointer Size: 4 Segment Size: 0Address Length08048308 408048458 1808048278 11080482e4 36 Length:  44 Version: 2 Offset into .debug_info: 19b Pointer Size: 4 Segment Size: 0Address Length08048308 40804846f 60804828d 2Contents of the .debug_pubnames section: Length: 33 Version: 2 Offset into .debug_info section: 122 Size of area in .debug_info section: 145Offset Name121 _IO_stdin_usedThe section .debug_info contains: Compilation Unit @ offset 0x0:  Length:118  Version:  2  Abbrev Offset: 0  Pointer Size: 4<0><b>: Abbrev Number: 1 (DW_TAG_compile_unit) DW_AT_stmt_list  : 0 DW_AT_low_pc : 0x80482c0 DW_AT_high_pc : 0x80482e2 DW_AT_name: ../sysdeps/i386/elf/start.S DW_AT_comp_dir: /build/buildd/glibc-2.3.6/build-tree/glibc-2.3.6/csu DW_AT_producer: GNU AS 2.16.91 DW_AT_language: 32769 (MIPS assembler) Compilation Unit @ offset 0x7a:  Length:141  Version:  2  Abbrev Offset: 20  Pointer Size: 4<0><85>: Abbrev Number: 1 (DW_TAG_compile_unit) DW_AT_stmt_list  : 0x5b DW_AT_high_pc : 0x80482e4 DW_AT_low_pc : 0x80482e4 DW_AT_producer: (indirect string, offset: 0x62): GNU C 3.4.6 DW_AT_language: 1 (ANSI C) DW_AT_name: (indirect string, offset: 0x0): init.c DW_AT_comp_dir: (indirect string, offset: 0x11): /build/buildd/...<1><9f>: Abbrev Number: 2 (DW_TAG_base_type) DW_AT_name: (indirect string, offset: 0x90): unsigned int DW_AT_byte_size  : 4 DW_AT_encoding: 7 (unsigned)<1><a6>: Abbrev Number: 2 (DW_TAG_base_type) DW_AT_name: (indirect string, offset: 0x54): unsigned char DW_AT_byte_size  : 1 DW_AT_encoding: 8 (unsigned char)<1><ad>: Abbrev Number: 2 (DW_TAG_base_type) DW_AT_name: (indirect string, offset: 0x9d): short unsigned int DW_AT_byte_size  : 2 DW_AT_encoding: 7 (unsigned)<1><b4>: Abbrev Number: 2 (DW_TAG_base_type) DW_AT_name: (indirect string, offset: 0x8b): long unsigned int DW_AT_byte_size  : 4 DW_AT_encoding: 7 (unsigned)<1><bb>: Abbrev Number: 2 (DW_TAG_base_type) DW_AT_name: (indirect string, offset: 0x56): signed char DW_AT_byte_size  : 1 DW_AT_encoding: 6 (signed char)<1><c2>: Abbrev Number: 2 (DW_TAG_base_type) DW_AT_name: (indirect string, offset: 0x7): short int DW_AT_byte_size  : 2 DW_AT_encoding: 5 (signed)<1><c9>: Abbrev Number: 3 (DW_TAG_base_type) DW_AT_name: int DW_AT_byte_size  : 4 DW_AT_encoding: 5 (signed)<1><d0>: Abbrev Number: 2 (DW_TAG_base_type) DW_AT_name: (indirect string, offset: 0x46): long long int DW_AT_byte_size  : 8 DW_AT_encoding: 5 (signed)<1><d7>: Abbrev Number: 2 (DW_TAG_base_type) DW_AT_name: (indirect string, offset: 0x86): long long unsigned int DW_AT_byte_size  : 8 DW_AT_encoding: 7 (unsigned)<1><de>: Abbrev Number: 2 (DW_TAG_base_type) DW_AT_name: (indirect string, offset: 0x4b): long int DW_AT_byte_size  : 4 DW_AT_encoding: 5 (signed)<1><e5>: Abbrev Number: 2 (DW_TAG_base_type) DW_AT_name: (indirect string, offset: 0x90): unsigned int DW_AT_byte_size  : 4 DW_AT_encoding: 7 (unsigned)<1><ec>: Abbrev Number: 2 (DW_TAG_base_type) DW_AT_name: (indirect string, offset: 0x5d): char DW_AT_byte_size  : 1 DW_AT_encoding: 6 (signed char)<1><f3>: Abbrev Number: 4 (DW_TAG_variable) DW_AT_name: (indirect string, offset: 0xb0): _IO_stdin_used DW_AT_decl_file  : 1 DW_AT_decl_line  : 25 DW_AT_type: <105> DW_AT_external: 1 DW_AT_location: 5 byte block: 3 7c 84 4 8 (DW_OP_addr: 804847c)<1><105>: Abbrev Number: 5 (DW_TAG_const_type) DW_AT_type: <c9> Compilation Unit @ offset 0x10b:  Length:140  Version:  2  Abbrev Offset: 86  Pointer Size: 4<0><116>: Abbrev Number: 1 (DW_TAG_compile_unit) DW_AT_stmt_list  : 0x82 DW_AT_name: /build/buildd/glibc-2.3.6/build-tree/i386-libc/csu/crti.S DW_AT_comp_dir: /build/buildd/glibc-2.3.6/build-tree/glibc-2.3.6/csu DW_AT_producer: GNU AS 2.16.91 DW_AT_language: 32769 (MIPS assembler) Compilation Unit @ offset 0x19b:  Length:140  Version:  2  Abbrev Offset: 102  Pointer Size: 4<0><1a6>: Abbrev Number: 1 (DW_TAG_compile_unit) DW_AT_stmt_list  : 0x12f DW_AT_name: /build/buildd/glibc-2.3.6/build-tree/i386-libc/csu/crtn.S DW_AT_comp_dir: /build/buildd/glibc-2.3.6/build-tree/glibc-2.3.6/csu DW_AT_producer: GNU AS 2.16.91 DW_AT_language: 32769 (MIPS assembler)Contents of the .debug_abbrev section: Number TAG  1 DW_TAG_compile_unit[no children]DW_AT_stmt_listDW_FORM_data4DW_AT_low_pc  DW_FORM_addrDW_AT_high_pc DW_FORM_addrDW_AT_name DW_FORM_stringDW_AT_comp_dir DW_FORM_stringDW_AT_producer DW_FORM_stringDW_AT_language DW_FORM_data2 Number TAG  1 DW_TAG_compile_unit[has children]DW_AT_stmt_listDW_FORM_data4DW_AT_high_pc DW_FORM_addrDW_AT_low_pc  DW_FORM_addrDW_AT_producer DW_FORM_strpDW_AT_language DW_FORM_data1DW_AT_name DW_FORM_strpDW_AT_comp_dir DW_FORM_strp  2 DW_TAG_base_type[no children]DW_AT_name DW_FORM_strpDW_AT_byte_sizeDW_FORM_data1DW_AT_encoding DW_FORM_data1  3 DW_TAG_base_type[no children]DW_AT_name DW_FORM_stringDW_AT_byte_sizeDW_FORM_data1DW_AT_encoding DW_FORM_data1  4 DW_TAG_variable[no children]DW_AT_name DW_FORM_strpDW_AT_decl_fileDW_FORM_data1DW_AT_decl_lineDW_FORM_data1DW_AT_type DW_FORM_ref4DW_AT_external DW_FORM_flagDW_AT_location DW_FORM_block1  5 DW_TAG_const_type[no children]DW_AT_type DW_FORM_ref4 Number TAG  1 DW_TAG_compile_unit[no children]DW_AT_stmt_listDW_FORM_data4DW_AT_name DW_FORM_stringDW_AT_comp_dir DW_FORM_stringDW_AT_producer DW_FORM_stringDW_AT_language DW_FORM_data2 Number TAG  1 DW_TAG_compile_unit[no children]DW_AT_stmt_listDW_FORM_data4DW_AT_name DW_FORM_stringDW_AT_comp_dir DW_FORM_stringDW_AT_producer DW_FORM_stringDW_AT_language DW_FORM_data2Dump of debug contents of section .debug_line: Length: 87 DWARF Version:  2 Prologue Length: 50 Minimum Instruction Length: 1 Initial value of 'is_stmt': 1 Line Base:  -5 Line Range: 14 Opcode Base: 13 (Pointer size:  4)Opcodes: Opcode 1 has 0 args Opcode 2 has 1 args Opcode 3 has 1 args Opcode 4 has 1 args Opcode 5 has 1 args Opcode 6 has 0 args Opcode 7 has 0 args Opcode 8 has 0 args Opcode 9 has 1 args Opcode 10 has 0 args Opcode 11 has 0 args Opcode 12 has 1 argsThe Directory Table: ../sysdeps/i386/elfThe File Name Table: Entry Dir TimeSizeName 1 1  0  0  start.SLine Number Statements: Extended opcode 2: set Address to 0x80482c0 Advance Line by 64 to 65 Copy Special opcode 38: advance Address by 2 to 0x80482c2 and Line by 5 to 70 Special opcode 20: advance Address by 1 to 0x80482c3 and Line by 1 to 71 Special opcode 39: advance Address by 2 to 0x80482c5 and Line by 6 to 77 Special opcode 48: advance Address by 3 to 0x80482c8 and Line by 1 to 78 Special opcode 24: advance Address by 1 to 0x80482c9 and Line by 5 to 83 Special opcode 21: advance Address by 1 to 0x80482ca and Line by 2 to 85 Advance Line by 24 to 109 Special opcode 19: advance Address by 1 to 0x80482cb and Line by 0 to 109 Special opcode 76: advance Address by 5 to 0x80482d0 and Line by 1 to 110 Special opcode 77: advance Address by 5 to 0x80482d5 and Line by 2 to 112 Special opcode 20: advance Address by 1 to 0x80482d6 and Line by 1 to 113 Special opcode 21: advance Address by 1 to 0x80482d7 and Line by 2 to 115 Special opcode 79: advance Address by 5 to 0x80482dc and Line by 4 to 119 Special opcode 78: advance Address by 5 to 0x80482e1 and Line by 3 to 122 Advance PC by 1 to 0x80482e2 Extended opcode 1: End of Sequence Length: 35 DWARF Version:  2 Prologue Length: 29 Minimum Instruction Length: 1 Initial value of 'is_stmt': 1 Line Base:  -5 Line Range: 14 Opcode Base: 13 (Pointer size:  4)Opcodes: Opcode 1 has 0 args Opcode 2 has 1 args Opcode 3 has 1 args Opcode 4 has 1 args Opcode 5 has 1 args Opcode 6 has 0 args Opcode 7 has 0 args Opcode 8 has 0 args Opcode 9 has 1 args Opcode 10 has 0 args Opcode 11 has 0 args Opcode 12 has 1 argsThe Directory Table is empty.The File Name Table: Entry Dir TimeSizeName 1 0  0  0  init.cLine Number Statements: Length: 169 DWARF Version:  2 Prologue Length: 80 Minimum Instruction Length: 1 Initial value of 'is_stmt': 1 Line Base:  -5 Line Range: 14 Opcode Base: 13 (Pointer size:  4)Opcodes: Opcode 1 has 0 args Opcode 2 has 1 args Opcode 3 has 1 args Opcode 4 has 1 args Opcode 5 has 1 args Opcode 6 has 0 args Opcode 7 has 0 args Opcode 8 has 0 args Opcode 9 has 1 args Opcode 10 has 0 args Opcode 11 has 0 args Opcode 12 has 1 argsThe Directory Table: /build/buildd/glibc-2.3.6/build-tree/i386-libc/csuThe File Name Table: Entry Dir TimeSizeName 1 1  0  0  crti.SLine Number Statements: Extended opcode 2: set Address to 0x8048308 Advance Line by 64 to 65 Copy Special opcode 48: advance Address by 3 to 0x804830b and Line by 1 to 66 Advance PC by 1 to 0x804830c Extended opcode 1: End of Sequence Extended opcode 2: set Address to 0x8048458 Advance Line by 46 to 47 Copy Special opcode 20: advance Address by 1 to 0x8048459 and Line by 1 to 48 Special opcode 34: advance Address by 2 to 0x804845b and Line by 1 to 49 Special opcode 20: advance Address by 1 to 0x804845c and Line by 1 to 50 Special opcode 76: advance Address by 5 to 0x8048461 and Line by 1 to 51 Special opcode 90: advance Address by 6 to 0x8048467 and Line by 1 to 52 Advance PC by 3 to 0x804846a Extended opcode 1: End of Sequence Extended opcode 2: set Address to 0x8048278 Advance Line by 31 to 32 Copy Special opcode 20: advance Address by 1 to 0x8048279 and Line by 1 to 33 Special opcode 34: advance Address by 2 to 0x804827b and Line by 1 to 34 Special opcode 48: advance Address by 3 to 0x804827e and Line by 1 to 35 Advance PC by 5 to 0x8048283 Extended opcode 1: End of Sequence Extended opcode 2: set Address to 0x80482e4 Advance Line by 10 to 11 Copy Special opcode 20: advance Address by 1 to 0x80482e5 and Line by 1 to 12 Special opcode 34: advance Address by 2 to 0x80482e7 and Line by 1 to 13 Special opcode 20: advance Address by 1 to 0x80482e8 and Line by 1 to 14 Special opcode 76: advance Address by 5 to 0x80482ed and Line by 1 to 15 Special opcode 90: advance Address by 6 to 0x80482f3 and Line by 1 to 16 Special opcode 48: advance Address by 3 to 0x80482f6 and Line by 1 to 17 Special opcode 90: advance Address by 6 to 0x80482fc and Line by 1 to 18 Special opcode 34: advance Address by 2 to 0x80482fe and Line by 1 to 19 Special opcode 34: advance Address by 2 to 0x8048300 and Line by 1 to 20 Special opcode 35: advance Address by 2 to 0x8048302 and Line by 2 to 22 Special opcode 48: advance Address by 3 to 0x8048305 and Line by 1 to 23 Special opcode 20: advance Address by 1 to 0x8048306 and Line by 1 to 24 Special opcode 20: advance Address by 1 to 0x8048307 and Line by 1 to 25 Advance PC by 1 to 0x8048308 Extended opcode 1: End of Sequence Length: 136 DWARF Version:  2 Prologue Length: 80 Minimum Instruction Length: 1 Initial value of 'is_stmt': 1 Line Base:  -5 Line Range: 14 Opcode Base: 13 (Pointer size:  4)Opcodes: Opcode 1 has 0 args Opcode 2 has 1 args Opcode 3 has 1 args Opcode 4 has 1 args Opcode 5 has 1 args Opcode 6 has 0 args Opcode 7 has 0 args Opcode 8 has 0 args Opcode 9 has 1 args Opcode 10 has 0 args Opcode 11 has 0 args Opcode 12 has 1 argsThe Directory Table: /build/buildd/glibc-2.3.6/build-tree/i386-libc/csuThe File Name Table: Entry Dir TimeSizeName 1 1  0  0  crtn.SLine Number Statements: Extended opcode 2: set Address to 0x8048308 Advance Line by 33 to 34 Copy Special opcode 48: advance Address by 3 to 0x804830b and Line by 1 to 35 Advance PC by 1 to 0x804830c Extended opcode 1: End of Sequence Extended opcode 2: set Address to 0x804846f Advance Line by 18 to 19 Copy Special opcode 48: advance Address by 3 to 0x8048472 and Line by 1 to 20 Special opcode 20: advance Address by 1 to 0x8048473 and Line by 1 to 21 Special opcode 20: advance Address by 1 to 0x8048474 and Line by 1 to 22 Advance PC by 1 to 0x8048475 Extended opcode 1: End of Sequence Extended opcode 2: set Address to 0x804828d Advance Line by 9 to 10 Copy Special opcode 20: advance Address by 1 to 0x804828e and Line by 1 to 11 Advance PC by 1 to 0x804828f Extended opcode 1: End of SequenceContents of the .debug_str section: 0x00000000 696e6974 2e630073 686f7274 20696e74 init.c.short int 0x00000010 002f6275 696c642f 6275696c 64642f67 ./build/buildd/g 0x00000020 6c696263 2d322e33 2e362f62 75696c64 libc-2.3.6/build 0x00000030 2d747265 652f676c 6962632d 322e332e -tree/glibc-2.3. 0x00000040 362f6373 75006c6f 6e67206c 6f6e6720 6/csu.long long 0x00000050 696e7400 756e7369 676e6564 20636861 int.unsigned cha 0x00000060 7200474e 55204320 332e342e 36202855 r.GNU C 3.4.6 (U 0x00000070 62756e74 7520332e 342e362d 31756275 buntu 3.4.6-1ubu 0x00000080 6e747532 29006c6f 6e67206c 6f6e6720 ntu2).long long 0x00000090 756e7369 676e6564 20696e74 0073686f unsigned int.sho 0x000000a0 72742075 6e736967 6e656420 696e7400 rt unsigned int. 0x000000b0 5f494f5f 73746469 6e5f7573 656400  _IO_stdin_used.

可执行文件是目标文件

在 Unix 中,可执行文件是 目标文件,并且您可以像对 a.out 文件那样对它们进行分析。可以进行一次有益的练习,更改到 /bin 或 /local/bin 目录,然后针对一些您最常用的命令,如 pwd、ps、cat 或 rm,运行 nm、objdump 和 readelf。通常,在您编写需要某种功能的程序时,如果标准的工具已经提供了这个功能,那么通过运行 objdump -d <command>,可以查看这些工具究竟如何完成这项任务。

如果您倾向于使用编译器和其他的语言工具,那么您可以对组成计算机系统的各种目标文件进行仔细研究,并且您将会发现这项工作是非常值得的。UNIX 操作系统具有许多层次,那些通过工具查看目标文件所公开的层次,非常接近底层硬件。通过这种方式,您可以真实地接触到系统。

结束语

研究目标文件可以极大地加深您对 UNIX 操作系统的认识,并且可以更深入地了解如何对软件的源代码进行汇编。我鼓励您使用本文中介绍的目标文件工具对系统中 /bin 或 /local/bin 目录中的程序进行分析,仔细研究其输出结果,并找出您的硬件制造商所提供的系统文档。

标签: Unix系统