电脑技术学习

UNIX 目标文件初探

dn001

  正如从该输出中看到的,简单的 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:       0
  Address Length
  080482c0 34
 Length:          52
 Version:         2
 Offset into .debug_info: 10b
 Pointer Size:       4
 Segment Size:       0
  Address Length
  08048308 4
  08048458 18
  08048278 11
  080482e4 36
 Length:          44
 Version:         2
 Offset into .debug_info: 19b
 Pointer Size:       4
 Segment Size:       0
  Address Length
  08048308 4
  0804846f 6
  0804828d 2
Contents of the .debug_pubnames section:
 Length:               33
 Version:               2
 Offset into .debug_info section:   122
 Size of area in .debug_info section: 145
  Offset   Name
  121         _IO_stdin_used
The 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_list  DW_FORM_data4
  DW_AT_low_pc    DW_FORM_addr
  DW_AT_high_pc   DW_FORM_addr
  DW_AT_name     DW_FORM_string
  DW_AT_comp_dir   DW_FORM_string
  DW_AT_producer   DW_FORM_string
  DW_AT_language   DW_FORM_data2
 Number TAG
  1   DW_TAG_compile_unit  [has children]
  DW_AT_stmt_list  DW_FORM_data4
  DW_AT_high_pc   DW_FORM_addr
  DW_AT_low_pc    DW_FORM_addr
  DW_AT_producer   DW_FORM_strp
  DW_AT_language   DW_FORM_data1
  DW_AT_name     DW_FORM_strp
  DW_AT_comp_dir   DW_FORM_strp
  2   DW_TAG_base_type  [no children]
  DW_AT_name     DW_FORM_strp
  DW_AT_byte_size  DW_FORM_data1
  DW_AT_encoding   DW_FORM_data1
  3   DW_TAG_base_type  [no children]
  DW_AT_name     DW_FORM_string
  DW_AT_byte_size  DW_FORM_data1
  DW_AT_encoding   DW_FORM_data1
  4   DW_TAG_variable  [no children]
  DW_AT_name     DW_FORM_strp
  DW_AT_decl_file  DW_FORM_data1
  DW_AT_decl_line  DW_FORM_data1
  DW_AT_type     DW_FORM_ref4
  DW_AT_external   DW_FORM_flag
  DW_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_list  DW_FORM_data4
  DW_AT_name     DW_FORM_string
  DW_AT_comp_dir   DW_FORM_string
  DW_AT_producer   DW_FORM_string
  DW_AT_language   DW_FORM_data2
 Number TAG
  1   DW_TAG_compile_unit  [no children]
  DW_AT_stmt_list  DW_FORM_data4
  DW_AT_name     DW_FORM_string
  DW_AT_comp_dir   DW_FORM_string
  DW_AT_producer   DW_FORM_string
  DW_AT_language   DW_FORM_data2
Dump 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 args
The Directory Table:
 ../sysdeps/i386/elf
The File Name Table:
 Entry Dir   Time  Size  Name
 1   1    0    0    start.S
Line 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 args
The Directory Table is empty.
The File Name Table:
 Entry Dir   Time  Size  Name
 1   0    0    0    init.c
Line 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 args
The Directory Table:
 /build/buildd/glibc-2.3.6/build-tree/i386-libc/csu
The File Name Table:
 Entry Dir   Time  Size  Name
 1   1    0    0    crti.S
Line 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 args
The Directory Table:
 /build/buildd/glibc-2.3.6/build-tree/i386-libc/csu
The File Name Table:
 Entry Dir   Time  Size  Name
 1   1    0    0    crtn.S
Line 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 Sequence
Contents 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 目录中的程序进行分析,仔细研究其输出结果,并找出您的硬件制造商所提供的系统文档。

标签: