然后使用gcc –g hello.c –o hello编译。生成hello文件。
Hello文件是elf格式的,elf一般由多个节(section)组成,不熟悉的可以看前面两篇关于elf文件格式的文章。调试信息被包含在某几个节中,如果是用dwarf2格式编译的,这些节的名字一般是以.debug开头,如.debug_info,.debug_line,.debug_frame等,如果是用dwarf1格式编译的,这些节的名字一般是.debug,.line等。现在的编译器默认大多数是dwarf2格式编译,当然可以通过gcc的编译选项改变。
现在来看hello文件都包含了哪些调试信息。
首先来看都包含了哪些调试节,使用readelf –S hello命令,产生如下输出(已删一些无关内容):[Nr] Name Type Addr Off Size
[ 0] NULL 00000000 000000 000000
[ 1] .text PROGBITS 00008000 008000 0006c4
[ 2] .ARM.exidx ARM_EXIDX 000086c4 0086c4 000008
[ 3] .data PROGBITS 000086d0 0086d0 000520
[ 4] .bss NOBITS 00008bf0 008bf0 000020
[ 5] .debug_aranges PROGBITS 00000000 008bf0 000020
[ 6] .debug_pubnames PROGBITS 00000000 008c10 000023
[ 7] .debug_info PROGBITS 00000000 008c33 0000cc
[ 8] .debug_abbrev PROGBITS 00000000 008cff 00006b
[ 9] .debug_line PROGBITS 00000000 008d6a 00003e
[10] .debug_frame PROGBITS 00000000 008da8 000188
[11] .debug_loc PROGBITS 00000000 008f30 000054
[12] .ARM.attributes ARM_ATTRIBUTES 00000000 008f84 000010
[13] .comment PROGBITS 00000000 008f94 000032
[14] .shstrtab STRTAB 00000000 008fc6 0000ad
[15] .symtab SYMTAB 00000000 00931c 000780
[16] .strtab STRTAB 00000000 009a9c 000416
可见一共包含了17个节,其中7个调试信息的节。
在来看一下各个调试信息节包含的内容,使用readelf –w* hello命令,*是调试节名的第一个字母,如-wi就是查看.debug_info节的内容,-wl就是查看.debug_line节的内容。
对于一个调试文件,.debug_info和.debug_line节是必须有的,其他的不见得。同时也可以自己写链接脚本实现对所有节(不局限于调试节)的控制,如指定每个节的基址等。
.debug_info基本包含了一个源文件内部的大部分信息,如函数、参数、变量、类型等等,我们看一下它的输出:
The section .debug_info contains:
Compilation Unit @ offset 0x0:
Length: 200
Version: 2
Abbrev Offset: 0
Pointer Size: 4
<0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
DW_AT_stmt_list : 0
DW_AT_high_pc : 0x8248
DW_AT_low_pc : 0x81ac
DW_AT_producer : GNU C 4.1.1
DW_AT_language : 1 (ANSI C)
DW_AT_name : hello.c
DW_AT_comp_dir : C:\Program Files\CodeSourcery\Sourcery G++\bin
<1><5c>: Abbrev Number: 2 (DW_TAG_subprogram)
DW_AT_sibling : <92>
DW_AT_external : 1
DW_AT_name : main
DW_AT_decl_file : 1
DW_AT_decl_line : 5
DW_AT_type : <92>
DW_AT_low_pc : 0x81ac
DW_AT_high_pc : 0x8214
DW_AT_frame_base : 0 (location list)
<2><79>: Abbrev Number: 3 (DW_TAG_variable)
DW_AT_name : i
DW_AT_decl_file : 1
DW_AT_decl_line : 6
DW_AT_type : <92>
DW_AT_location : 2 byte block: 91 68 (DW_OP_fbreg: -24)
<2><85>: Abbrev Number: 3 (DW_TAG_variable)
DW_AT_name : j
DW_AT_decl_file : 1
DW_AT_decl_line : 6
DW_AT_type : <92>
DW_AT_location : 2 byte block: 91 6c (DW_OP_fbreg: -20)
<1><92>: Abbrev Number: 4 (DW_TAG_base_type)
DW_AT_name : int
DW_AT_byte_size : 4
DW_AT_encoding : 5 (signed)
<1><99>: Abbrev Number: 5 (DW_TAG_subprogram)
DW_AT_external : 1
DW_AT_name : add
DW_AT_decl_file : 1
DW_AT_decl_line : 15
DW_AT_prototyped : 1
DW_AT_type : <92>
DW_AT_low_pc : 0x8214
DW_AT_high_pc : 0x8248
DW_AT_frame_base : 0x2a (location list)
<2><b2>: Abbrev Number: 6 (DW_TAG_formal_parameter)
DW_AT_name : a
DW_AT_decl_file : 1
DW_AT_decl_line : 14
DW_AT_type : <92>
DW_AT_location : 2 byte block: 91 6c (DW_OP_fbreg: -20)
<2><be>: Abbrev Number: 6 (DW_TAG_formal_parameter)
DW_AT_name : b
DW_AT_decl_file : 1
DW_AT_decl_line : 14
DW_AT_type : <92>
DW_AT_location : 2 byte block: 91 68 (DW_OP_fbreg: -24)
.debug_line包含了所有地址和源文件行的对应信息,内容如下:
Dump of debug contents of section .debug_line:
Length: 58
DWARF Version: 2
Prologue Length: 30
Minimum Instruction Length: 2
Initial value of 'is_stmt': 1
Line Base: -5
Line Range: 14
Opcode Base: 13
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 hello.c
Line Number Statements:
Extended opcode 2: set Address to 0x81ac
Special opcode 9: advance Address by 0 to 0x81ac and Line by 4 to 5
Special opcode 120: advance Address by 16 to 0x81bc and Line by 3 to 8
Special opcode 90: advance Address by 12 to 0x81c8 and Line by 1 to 9
Special opcode 88: advance Address by 12 to 0x81d4 and Line by -1 to 8
Advance PC by constant 34 to 0x81f6
Special opcode 78: advance Address by 10 to 0x8200 and Line by 3 to 11
Special opcode 34: advance Address by 4 to 0x8204 and Line by 1 to 12
Special opcode 120: advance Address by 16 to 0x8214 and Line by 3 to 15
Special opcode 174: advance Address by 24 to 0x822c and Line by 1 to 16
Special opcode 90: advance Address by 12 to 0x8238 and Line by 1 to 17
Advance PC by 16 to 0x8248