dwarf格式(1)

编写确保能正确工作且永远不需要调试的程序基本上是不太科学的。通常的编程周期还将是包括:编写一个程序,编译它,执行它,然后调试。然后重复以上步骤,直到程序如期工作。

学过编程课程的同学应该都知道我们人类编写的程序是人类可读的,而计算机需要将人类可读的程序转化成计算机执行的二进制的形式。这个过程是相当复杂的。计算机组成原理告诉我们,这个过程本质上包括了持续地把源代码转换到越来越简单的形式,在每一步丢弃信息,直到最后产生包含简单操作、寄存器、内存地址,及处理器真正理解的二进制值的序列。最终,处理器实际上不在乎你是否使用面向对象编程、模板,还是智能指针;它仅能理解,在有限寄存器及包含二进制值的内存位置上的,非常简单的一组操作。

我们在编写完程序进行调试时,最简单也是最常见的操作是设置一个断点。通过设置断点,我们可以知道全局变量或者局部变量的值,或者获取一些别的有用的信息。

某些操作可以被称为先进的调试功能:例如,为了可以调试多线程程序,或保存在只写内存的程序,可能希望一个调试器(或其它某些程序分析工具)记录代码的特定节(section)是否已经执行。某些调试器允许程序员在正在测试的程序里调用函数。在不远的过去,调试被优化的程序被视为一个先进的特性。

当然,比较好的测试自己代码的方法还是TDD。TDD是指测试驱动开发,是敏捷开发中的一项核心实践和技术,也是一种设计方法论。TDD的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码。TDD虽是敏捷方法的核心实践,但同样可以适用于其他开发方法和过程。

TDD的三个基本原则是:

1.先写测试代码,再写产品代码

2.只允许编写刚好能够导致失败的单元测试

3.只允许编写刚好能够导致一个失败的单元测试通过的产品代码

查了一下dwarf的意义,找到说明文字如下:

DWARF is a debugging file format used by many compilers and debuggers to support source level debugging. It addresses the requirements of a number of procedural languages, such as C, C++, and Fortran, and is designed to be extensible to other languages. DWARF is architecture independent and applicable to any processor or operating system. It is widely used on Unix, Linux and other operating systems, as well as in stand-alone environments.

意思就是说:DWARF是一种调试文件格式,许多编译器调试器都使用它来支持源代码级调试。它满足了许多过程语言(如C、c++和Fortran)的需求,并被设计为可扩展到其他语言。DWARF是独立于体系结构的,适用于任何处理器或操作系统。它广泛用于Unix、Linux和其他操作系统,以及独立环境中。

大多数现代编程语言是块结构的:每个实体(例如,一个类定义或一个函数)被包含在另一个实体中。在一个C程序里,每个文件可能包含多个数据定义、多个变量定义,及多个函数。在每个C函数里,可能有几个数据定义,后跟可执行语句。一个语句进而可以是包含数据定义及可执行语句的复合语句。这构成了词法作用域(lexical scopes),其中名字仅在定义它们的作用域中已知。为了在一个程序里找出一个特定符号的定义,你首先在当前作用域中查找,然后在依次的封装作用域里,直到找到这个符号。在不同作用域中,相同的名字可能有多个定义。编译器非常自然地在内部把一个程序表示为一棵树。在编译技术的课程中,我们叫这为抽象语法树。

DWARF遵循这个模型,因为它也是块结构的。在DWARF里每个描述性的实体(entity)(除了最顶层描述源文件的项(entry))被包含在一个父项(parententry)中,并且可能包含子实体(children entities)。如果一个节点包含多个实体,它们都是相互关联的兄弟。一个程序的DWARF描述是一个数结构,它类似于编译器的内部树,其中每个节点可以具有孩子或兄弟。这些节点可能表示类型,变量,或函数。这是一个紧凑的格式,它仅提供描述一个程序某一方面所需要的信息。这个格式可以一个统一的形式扩展,这样一个调试器可以识别并忽略一个扩展,即使它可能不能理解其含义。(这比其它大多数调试格式,在尝试读入修改后的数据时,调试器不可避免地被搞糊涂了的情形,要好得多)。DWARF也被设计为可扩展地描述几乎任何任何机器架构上的过程编程语言,而不是仅限于在有限范围架构上的,描述一个语言或一个语言的一个版本。

名字DWARF某种程度是一个双关语,因为它与ELF目标文件格式一同开发。这个名字可能是“Debugging With Attributed Record Formats(使用属性化记录格式调试)”的首字母缩写词,输入在在任何DWARF标准中都没有提到。

虽然DWARF最常见与ELF目标文件格式关联,它并不依赖于这个目标文件格式。它可以并且已经用于其它目标文件格式。所需要的一切是,在这个目标文件或可执行文件里,构成DWARF数据的不同数据节是可识别的。DWARF不会复制包含在这个目标文件里的信息,比如标记处理器架构,或者文件是bigendian,还是littleendian格式。

查看其内容的工具常用的有四种:

1. readelf

GNU提供的二进制工具,功能很多,并不限于读dwarf信息

2. gdb

这个就不用多说了吧,^_^

3. drawfdump

是一个被打包在libdwarf内的程序

4. libdwarf

是一个封装好的C库API,用来读取dwarf信息

将.o文件链接成为一个可执行文件(这里讨论ELF格式的文件)。调试信息被包含在某几个节中,如果是用dwarf2格式编译的,这些节的名字一般是以.debug开头,如.debug_info,.debug_line,.debug_frame等,如果是用dwarf1格式编译的,这些节的名字一般是.debug,.line等。现在的编译器默认大多数是dwarf2格式编译,当然可以通过gcc的编译选项改变。

dwarf文件中的数据大致如下:


其常用的标记与属性如下:

发布于 2020-02-02 19:46