wordpress 用户浏览记录,seo外包团队,wordpress侧边小图标联系方式,wordpress guge基本概念
DWARF是一个用于在可执行程序和其源代码之间进行关联的调试文件格式。当开发者使用调试编译选项#xff08;例如#xff0c;使用gcc时的-g标志#xff09;编译程序时#xff0c;编译器会生成这种格式的调试信息。这些信息在后续的调试过程中非常有用#xff0c;…基本概念
DWARF是一个用于在可执行程序和其源代码之间进行关联的调试文件格式。当开发者使用调试编译选项例如使用gcc时的-g标志编译程序时编译器会生成这种格式的调试信息。这些信息在后续的调试过程中非常有用例如使用gdbGNU调试器。
以下是DWARF的一些主要特点和相关的详细信息 历史DWARF起初是为了满足UNIX系统上的高效、紧凑和跨平台的调试需求而设计的。自那时起它已经经历了多个版本每个版本都增加了新的特性。 版本从DWARF 1到DWARF 5每个版本都引入了新的特性和改进以支持新的编程语言特性、编译器优化等。 数据结构DWARF信息由一系列的记录组成这些记录描述了源代码的结构、变量、数据类型等。它们以所谓的Debugging Information Entries (DIEs)的形式存储。 查看工具有一些工具可以查看和处理DWARF调试信息。例如readelf与binutils套件一起提供可以使用-wi选项来查看DWARF信息。 优势 跨平台DWARF是一个可扩展的格式可以支持多种不同的架构和操作系统。紧凑尽管包含大量的调试信息但DWARF的设计使其尽可能紧凑避免浪费存储空间。灵活性DWARF可以描述各种编程语言构造和复杂的数据类型。 与其他格式的比较除了DWARF还有其他的调试格式例如stabs和PE/COFF。但DWARF因其丰富的特性和跨平台支持而受到许多现代系统的青睐。
总之DWARF是一个强大的调试信息格式允许开发者在程序的执行过程中访问源代码级别的详细信息。对于开发者或者正在学习调试技术的读者来说了解DWARF和如何使用它将非常有益。 示例
下面我们用一个简单的C语言程序展示它如何与DWARF调试信息交互。
假设我们有一个简单的C程序example.c
#include stdio.hint add(int a, int b) {return a b;
}int main() {int sum add(5, 7);printf(The sum is: %d\n, sum);return 0;
}我们使用GCC编译器编译这个程序并使用-g选项来生成DWARF调试信息
$ gcc -g -o example example.c现在可以使用readelf命令来查看生成的DWARF信息。例如查看DWARF头部信息
$ readelf --debug-dumpinfo example这会列出关于源代码结构的很多信息比如变量、函数等并与其在源代码中的位置进行关联。
为了进一步调试程序可以使用gdb
$ gdb ./example在GDB中可以进行各种操作如设置断点、查看变量值等。所有这些操作都是基于DWARF调试信息的。
例如可以在add函数上设置断点
(gdb) b add然后运行程序
(gdb) run程序将在add函数处暂停执行此时可以查看和修改变量值、单步执行等。
总的来说DWARF调试信息提供了程序的详细视图使得像gdb这样的调试器可以与源代码进行交互。 DWARF调试信息
下面我们来详细了解DWARF调试信息。
$ readelf --debug-dumpinfo exampleContents of the .debug_info section:Compilation Unit offset 0x0:Length: 0xf4 (32-bit)Version: 5Unit Type: DW_UT_compile (1)Abbrev Offset: 0x0Pointer Size: 80c: Abbrev Number: 3 (DW_TAG_compile_unit)d DW_AT_producer : (indirect string, offset: 0x0): GNU C17 11.4.0 -mtunegeneric -marchx86-64 -g -fasynchronous-unwind-tables -fstack-protector-strong -fstack-clash-protection -fcf-protection11 DW_AT_language : 29 (C11)12 DW_AT_name : (indirect line string, offset: 0x29): example.c16 DW_AT_comp_dir : (indirect line string, offset: 0x0): /home/majn/python_project/socket_project1a DW_AT_low_pc : 0x114922 DW_AT_high_pc : 0x562a DW_AT_stmt_list : 0x012e: Abbrev Number: 1 (DW_TAG_base_type)2f DW_AT_byte_size : 830 DW_AT_encoding : 7 (unsigned)31 DW_AT_name : (indirect string, offset: 0x8e): long unsigned int135: Abbrev Number: 1 (DW_TAG_base_type)36 DW_AT_byte_size : 437 DW_AT_encoding : 7 (unsigned)38 DW_AT_name : (indirect string, offset: 0x93): unsigned int13c: Abbrev Number: 1 (DW_TAG_base_type)3d DW_AT_byte_size : 13e DW_AT_encoding : 8 (unsigned char)3f DW_AT_name : (indirect string, offset: 0xa0): unsigned char143: Abbrev Number: 1 (DW_TAG_base_type)44 DW_AT_byte_size : 245 DW_AT_encoding : 7 (unsigned)46 DW_AT_name : (indirect string, offset: 0xbc): short unsigned int14a: Abbrev Number: 1 (DW_TAG_base_type)4b DW_AT_byte_size : 14c DW_AT_encoding : 6 (signed char)4d DW_AT_name : (indirect string, offset: 0xa2): signed char151: Abbrev Number: 1 (DW_TAG_base_type)52 DW_AT_byte_size : 253 DW_AT_encoding : 5 (signed)54 DW_AT_name : (indirect string, offset: 0xd6): short int158: Abbrev Number: 4 (DW_TAG_base_type)59 DW_AT_byte_size : 45a DW_AT_encoding : 5 (signed)5b DW_AT_name : int15f: Abbrev Number: 1 (DW_TAG_base_type)60 DW_AT_byte_size : 861 DW_AT_encoding : 5 (signed)62 DW_AT_name : (indirect string, offset: 0xb3): long int166: Abbrev Number: 1 (DW_TAG_base_type)67 DW_AT_byte_size : 168 DW_AT_encoding : 6 (signed char)69 DW_AT_name : (indirect string, offset: 0xa9): char16d: Abbrev Number: 5 (DW_TAG_const_type)6e DW_AT_type : 0x66172: Abbrev Number: 6 (DW_TAG_subprogram)73 DW_AT_external : 173 DW_AT_name : (indirect string, offset: 0xcf): printf77 DW_AT_decl_file : 278 DW_AT_decl_line : 3567a DW_AT_decl_column : 127b DW_AT_prototyped : 17b DW_AT_type : 0x587f DW_AT_declaration : 17f DW_AT_sibling : 0x8a283: Abbrev Number: 7 (DW_TAG_formal_parameter)84 DW_AT_type : 0x8a288: Abbrev Number: 8 (DW_TAG_unspecified_parameters)289: Abbrev Number: 018a: Abbrev Number: 9 (DW_TAG_pointer_type)8b DW_AT_byte_size : 88c DW_AT_type : 0x6d190: Abbrev Number: 10 (DW_TAG_subprogram)91 DW_AT_external : 191 DW_AT_name : (indirect string, offset: 0xae): main95 DW_AT_decl_file : 196 DW_AT_decl_line : 797 DW_AT_decl_column : 598 DW_AT_type : 0x589c DW_AT_low_pc : 0x1161a4 DW_AT_high_pc : 0x3eac DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa)ae DW_AT_call_all_tail_calls: 1ae DW_AT_sibling : 0xc22b2: Abbrev Number: 11 (DW_TAG_variable)b3 DW_AT_name : sumb7 DW_AT_decl_file : 1b8 DW_AT_decl_line : 8b9 DW_AT_decl_column : 9ba DW_AT_type : 0x58be DW_AT_location : 2 byte block: 91 6c (DW_OP_fbreg: -20)2c1: Abbrev Number: 01c2: Abbrev Number: 12 (DW_TAG_subprogram)c3 DW_AT_external : 1c3 DW_AT_name : addc7 DW_AT_decl_file : 1c8 DW_AT_decl_line : 3c9 DW_AT_decl_column : 5ca DW_AT_prototyped : 1ca DW_AT_type : 0x58ce DW_AT_low_pc : 0x1149d6 DW_AT_high_pc : 0x18de DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa)e0 DW_AT_call_all_calls: 12e0: Abbrev Number: 2 (DW_TAG_formal_parameter)e1 DW_AT_name : ae3 DW_AT_decl_file : 1e3 DW_AT_decl_line : 3e3 DW_AT_decl_column : 13e4 DW_AT_type : 0x58e8 DW_AT_location : 2 byte block: 91 6c (DW_OP_fbreg: -20)2eb: Abbrev Number: 2 (DW_TAG_formal_parameter)ec DW_AT_name : bee DW_AT_decl_file : 1ee DW_AT_decl_line : 3ee DW_AT_decl_column : 20ef DW_AT_type : 0x58f3 DW_AT_location : 2 byte block: 91 68 (DW_OP_fbreg: -24)2f6: Abbrev Number: 01f7: Abbrev Number: 0这是一个.debug_info节的内容该节是由readelf从ELF文件中提取的。这个节包含了程序的DWARF调试信息。以下是这些输出信息的简要说明 Compilation Unit: 表示源文件的一个编译单位。这里是example.c。 DW_AT_producer: 编译器和其版本信息。DW_AT_language: 源代码的编程语言。DW_AT_name: 源文件名。DW_AT_comp_dir: 源文件的编译目录。DW_AT_low_pc 和 DW_AT_high_pc: 表示程序地址范围。 DW_TAG_base_type: 这是基础类型的定义例如unsigned intunsigned char等。 DW_AT_byte_size: 数据类型的大小。DW_AT_encoding: 数据类型的编码例如signed、unsigned等。DW_AT_name: 数据类型的名称。 DW_TAG_subprogram: 代表一个函数或子程序。 DW_AT_external: 表明这个函数是否是外部的。DW_AT_name: 函数名。DW_AT_decl_file、DW_AT_decl_line、DW_AT_decl_column: 声明函数的文件、行号和列号。DW_AT_prototyped: 表明该函数是否有原型。DW_AT_type: 函数返回的数据类型。 DW_TAG_formal_parameter: 表示函数的一个形式参数。 DW_AT_name: 参数名称。DW_AT_decl_file、DW_AT_decl_line、DW_AT_decl_column: 参数在源文件中的位置。DW_AT_type: 参数的数据类型。DW_AT_location: 参数在堆栈上的位置。 DW_TAG_pointer_type: 表示指针类型。 DW_AT_byte_size: 指针的大小通常为地址大小。DW_AT_type: 指针所指向的数据类型。 DW_TAG_const_type: 表示常量类型。 DW_TAG_unspecified_parameters: 表示函数可能有不确定数量的参数。 DW_TAG_variable: 表示一个变量。 DW_AT_name: 变量名。DW_AT_type: 变量的数据类型。DW_AT_location: 变量的位置可能是寄存器或堆栈上的位置。
上述内容只是一个粗略的说明DWARF格式包含了大量的复杂信息用于在不运行程序的情况下对其进行详细的分析和调试。 在DWARF调试信息中DW_AT_type: 0x58表示一个引用或指针它指向另一个DWARF条目。具体来说这是一个偏移量它从当前编译单元的开始处计算指向描述该类型的DWARF条目。
在给定的输出中DW_AT_type: 0x58意味着该属性引用了偏移量为0x58的条目以获取其类型信息。
为了理解这代表什么我们应该查找偏移量为0x58的条目。在提供的输出中可以看到以下条目
158: Abbrev Number: 4 (DW_TAG_base_type)59 DW_AT_byte_size : 45a DW_AT_encoding : 5 (signed)5b DW_AT_name : int这意味着DW_AT_type: 0x58引用的是一个基础类型它是一个带符号的整数int大小为4字节。 DW_AT_stmt_list
DW_AT_stmt_list 是一个属性用于在DWARF调试信息中引用一个行号信息表的偏移量。这个属性关联了源代码的行号和生成的机器代码之间的映射使得调试工具能够准确地确定执行的源代码行。
具体来说当我们在调试器中设置断点或在运行时遇到错误时DW_AT_stmt_list 使得调试器可以准确地显示源代码中的相关行。
值得注意的是DW_AT_stmt_list 的值是一个偏移量指向 .debug_line 节区中的一个位置该位置包含与编译单元关联的行号程序。
这允许开发者和调试工具从机器代码位置回溯到源代码位置从而可以进行更有效的调试。 Abbrev Number
Abbrev Number 在 DWARF 调试信息中是一个非常重要的概念用于表示一个 “abbreviation” 的唯一标识符。它与一个特定的 “abbreviation” 对象关联该对象定义了一个特定的 DIEDebugging Information Entry的结构和属性。简单地说它是一个用于描述 DIE 结构的模板。
让我们详细解析一下 DIE (Debugging Information Entry): 在 DWARF 中调试信息由许多的 DIEs 组成。每个 DIE 描述了编译单位中的某个实体如变量、类型、函数等。每个 DIE 都有一个 “tag”如 DW_TAG_base_type用于描述其表示的实体类型。 Abbreviations: 由于调试信息可能会很大DWARF 使用一种缩写机制来减少所需的空间。这种机制通过定义一组 “abbreviations” 来工作每个 “abbreviation” 描述了一种特定的 DIE 结构包括其标签和属性。这些 “abbreviations” 存储在 .debug_abbrev 节区中。 Abbrev Number: 每个 “abbreviation” 都有一个唯一的编号称为 Abbrev Number。这允许 .debug_info 节区中的 DIEs 通过简单地引用这个编号来描述其结构而不是重复每个属性和标签。
因此当我们在 .debug_info 节区中看到 Abbrev Number: 1这意味着可以查找 .debug_abbrev 节区中的编号为 1 的 “abbreviation”从而知道该 DIE 的结构和属性。 DW_AT_low_pc 和 DW_AT_high_pc
在DWARF调试信息中DW_AT_low_pc 和 DW_AT_high_pc 是两个非常重要的属性它们定义了一个代码范围的开始和结束地址。 DW_AT_low_pc: 这是代码段的起始地址。在上面给出的例子中DW_AT_low_pc: 0x1149 表示相关的代码段可能是一个函数或其他代码块从地址 0x1149 开始。 DW_AT_high_pc: 在早期的DWARF版本中这是代码段的结束地址。但在后来的版本中尤其是DWARF4之后这的含义发生了变化它代表与DW_AT_low_pc的偏移量而不是实际的结束地址。在上面给出的例子中DW_AT_high_pc: 0x56 很可能表示代码段的长度是 0x56 字节。因此真正的结束地址将是 0x1149 0x56。
为了确定 DW_AT_high_pc 的确切含义是否是结束地址还是偏移量需要查看DWARF版本以及可能存在的其他属性如DW_AT_ranges。但在大多数情况下考虑到新版本的DWARF可以假设DW_AT_high_pc 表示从DW_AT_low_pc 的偏移量。 DW_AT_decl_file
在DWARF调试信息中DW_AT_decl_file 属性表示源文件的索引它指向文件名列表通常存储在 .debug_line 节中的文件名表中。
在上面的例子中DW_AT_decl_file : 1 表示这个特定的实体可能是一个变量、函数等是在文件名列表中索引为1的文件中声明的。
为了找出索引1真正代表的文件名需要查看 .debug_line 节并找到对应的文件名表。这个表通常会列出编译单元中用到的所有文件每个文件都有一个唯一的索引号从1开始。这样DWARF信息可以通过简单地引用索引号来指代一个特定的文件而不是多次重复文件的完整路径名从而节省空间。