当前位置:
凯发ag旗舰厅登录网址下载 >
> 编程问答
>内容正文
编程问答
dwarf调试信息格式入门 -凯发ag旗舰厅登录网址下载
凯发ag旗舰厅登录网址下载
收集整理的这篇文章主要介绍了
dwarf调试信息格式入门
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
https://www.prevanders.net/dwarf.html#testingcomment http://www.dwarfstd.org/ http://www.cnblogs.com/zqingnn/archive/2011/01/05/1926384.html
: 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>: 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)
一个程序的完成过程一般是编码、编译、运行的过程,当然这是一个理想的过程,所有的开发几乎都不可能是一帆风顺的,总会有些意想不到的错误,这时便需要调试,良好的调试器应该每一个程序员的必备。
那么调试器使用的调试信息是从哪里来的呢?答案简单的很,是从编译后的文件中来的(注意这里编译的时候要使用特定的编译选项,如vc使用debug模式,gcc使用”-g”)。在编译的时候,编译器会从源文件中收集大量的信息,例如变量名、变量类型、变量所在行号、函数名、函数参数、函数的地址范围、行号和地址的对应关系等等,然后按照一种特定的格式写入到编译后的文件中。调试的时候,调试器便从文件中读取并解析这些信息,以产生人们可读性比较强的信息。简单的说,调试信息就是在机器码和对应的源代码之间建立一座桥梁,大大方便和提高了调试程序的能力。
调试信息一般都是按照什么样的格式存放的呢?主要有下面几种:stabs,coff,pe-coff,omf,ieee-695和dwarf。其中dwarf在linux中被普遍使用,我们主要分析它。
dwarf的全称是"debugging with attributed record formats",遵从gnu fdl授权。现在已经有dwarf1,dwarf2,dwarf3三个版本。
dwarf最初被贝尔实验室设计用来供unix system v的sdb调试器使用,并且在1989年被unix国际化部门的plsig (programming languages special interest group)标准化成为dwarf1.0。但是dwarf1有着很多明显的缺点,于是plsig继续开发,改正了缺点,并加入了对c 等语言的支持,并在1990年正式公布了dwarf2的标准草案。但是稍后由于一些原因,plsig被解散,dwarf的开发陷入到多个并不合作的组织中间,造成dwarf2的一些实现细节要取决于特定的编译器。这种情况一直持续到1999年,开发工作受到了来自实现对hp/inter ia-64架构提供较好支持的推动,成立了dwarf委员会,dwarf的原作者担任负责人,
开始了dwarf3的开发,并于2006年1月份推出dwarf3.0,同时为了解决分歧,dwarf委员会加入了自由标准组织,在自由标准组织与来自linux基金会的osdl(open source development labs)合并后,dwarf重返独立状态并创建了自己的网站:dwarfstd.org。
这三个版本中,dwarf2对dwarf1的改变很大,dwarf3大多是对dwarf2的扩充。
现在dwarf已经是一种独立的标准,可以支持c、c 、java、fortran等语言。
在了解了dwarf的历史之后,来看一下如何查看dwarf所包含的调试信息内容,并在下一篇文章中介绍这些内容的具体意思。查看内容的工具常用的有四种:
1. readelf
gnu提供的二进制工具,功能很多,并不限于读dwarf信息
2. gdb
这个就不用多说了吧,^_^
3. drawfdump
是一个被打包在libdwarf内的程序
4. libdwarf
是一个封装好的c库api,用来读取dwarf信息
在这里我们主要使用readelf工具。
先写一个简单的c程序,如下:
1: 2: int add(int, int); 3: 4: int main() 5: ...{ 6: int i, j; 7: 8: for(i = 0; i < 100; i = 5, j = i * 5) 9: add(i, j); 10: 11: return 0; 12: } 13: 14: int add(int a, int b) 15: ...{ 16: return a b; 17: }然后使用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>: 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>.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 extended opcode 1: end of sequence
总结
以上是凯发ag旗舰厅登录网址下载为你收集整理的dwarf调试信息格式入门的全部内容,希望文章能够帮你解决所遇到的问题。
如果觉得凯发ag旗舰厅登录网址下载网站内容还不错,欢迎将凯发ag旗舰厅登录网址下载推荐给好友。
- 上一篇:
- 下一篇: