Chrome的Crash Report服务(一)

来源:互联网 发布:淘宝pos机下架 编辑:程序博客网 时间:2024/04/28 15:28

本文翻译自debugInfo网站上一篇文章generating debug information with visual c++。由于Chrome的Crash产生的Debug信息和这个有一些关系,因此做一些背景知识介绍

简介


当我们采用一个调试器调试一个应用程序时,我们总是希望能单步跟踪代码、设置断点、查看变量值,哪怕变量是自定义的用户类型。但是对于一个EXE程序来说,基本上就是一堆二进制数据(目前的Windows中EXE程序中还包含了一些头部信息,用于系统执行程序)。当一个EXE程序运行时,系统将为这些EXE分配一些额外的内存用于存储运行时数据(Stack,Heap)。但是依旧没有任何调试方面的信息。当程序Coredump时,像WinDBG这些调试器是如何定位到哪一行的呢,这些都是Visual Studio中的一些编译特性。

调试信息种类

在Intel X86指令体系下的Windows平台,一个EXE或者DLL中主要有下面几种调试信息:

Debug类型
说明
Public functions and variables
主要包括了一些全局变量和全局函数信息。在Debug信息中主要存储了他们的位置、大小、名字信息
Private functions and variables
主要包含了非全局的变量和函数信息。
Source File and  Line Information
主要包含了每一行代码在EXE中的对应位置信息
Type Information
主要存储了各种数据类型信息,包括用户自定义的数据类型
FPO Information
FPO(Frame Pointer Omission)。Frame Pointer 是一种用来在调用堆栈(Call stack)中找到下一个将要被调用的函数的数据结构源代码的行序号(Source-line numbers);编译器可针对这一特性做优化,Debug信息中依旧可以存储一些信息,用来查询函数的栈区帧大小信息。
Edit and Continue Information
主要包含了要实现用户编辑后可以继续执行特性的相关信息。
表1 Windows平台下调试信息分类


调试文件格式分类
在过去二十多年的时间里,微软采用了三种形式来存储DEBUG信息:COFF,CodeView,Program Database。我们从三个维度来对比分析一下这三种格式:
1. 每种格式中存储了哪些调试信息?
2. 每种格式的调试信息存储在哪里?(包含在EXE中还是单独的调试信息文件)
3. 每种格式的设计文档是否齐全?

COFF

这是最老的一种格式,只能存储三种信息:Public functions and variables, source file and line information, FPO信息。COFF信息是存储在EXE文件中的,不能单独存储。这种格式文档有详细 的说明: Microsoft Portable Executable and Common Object File Format Specification。

CodeView

这是在COFF基础上推出的一个更为复杂一些的格式。它可以存储表1中除了Edit and Continue Information外的其他信息。CodeView信息通常存储在EXE文件中,但是它也可以存储在单独的文件(.DBG)中。CodeView的格式文档在MSDN上有部分说明,不是很齐全。

Program Database

这是微软最新的格式。他可以存储表1中所有信息。另外,他还存储了增量链接(increase Linking)信息。这在其他格式中不可能存在的。
Program Database格式信息通常存储在单独的文件(.PDB)中。
Program Database格式微软并没有提供格式文档说明。但是微软提供了两套SDK接口:DBGHelp和DIA供用户调用。PDB有两个版本,一个是PDB 2.0, 主要在VS6.0中使用。一个是PDB7.0,主要用在Visual Studio.NET之后的版本。DBGHelp是普通的API接口。而DIA提供的是COM接口。相对来说DBGHelp使用起来相对简单一些,但是DIA提供的信息相对丰富一些。
下表是三种格式的对比:

格式
文档齐全度
存储
public function and variables
Type information FPO information EnC information COFF
齐全
EXE
+
-
+
-
CodeView
部分
EXE或者单独文件(.DBG)
+
+
+
-
Program Database

单独文件(.PDB)
+
+
+
+
表2:三种不同格式的对比

如何产生调试信息

在Windows下,一个EXE典型的生成过程主要分为两步:编译(Compile)和链接(Link),可以用下图来描述:

 C++编译过程

如果我们想产生DEBUG信息,同样需要分为两步:我们要求编译器(Compiler)为每一个源文件产生相应的调试信息文件;然后由链接器(Linker)把各个调试文件合并成一个大的调试文件。可以用下图来描述:

 调试信息生成过程

在缺省情况下,编译器和链接器不会产生调试信息,我们需要在编译和链接选项中设置参数,告诉编译器和链接器我们需要生成DEBUG信息、生成什么格式的调试信息、调试信息存储在哪里等。
下面我们按照Visual C++6.0和Visual C++.NET两种不同版本的IDE分别介绍。

Visual C++ 6.0

编译器选项

主要包含了下面几个选项:
/Zd 产生COFF格式调试信息,并保存在目标文件中。
/Z7 产生CodeView格式调试信息,并保证在目标文件中。
/Zi 产生Program Database格式调试信息,并单独存储在.PDB文件中。
/ZI 和Zi类似。并在Zi基础上增加了Edit and Continue信息。

选项
格式
存储格式
包含内容
/Zd
COFF
.obj
  • Public functions and variables
  • Source file and line information
  • FPO information
/Z7
CodeView
.obj
  • Public functions and variables
  • Private functions and variables
  • Source file and line information
  • Type information
  • FPO information
/Zi
Program Database
.PDB
  • Public functions and variables
  • Private functions and variables
  • Source file and line information
  • Type information
  • FPO information
/ZI
Program Database .PDB
  • Public functions and variables
  • Private functions and variables
  • Source file and line information
  • Type information
  • FPO information
  • Edit and Continue data

 

链接器选项

主要包含了一下链接选项:

/debug 告诉Linker产生调试信息,如果该选项未设置,其它选项设置都不起作用。

/debugtype 告诉Linker采用哪个格式的调试信息,主要包含了下面几种:/debugtype:coff COFF格式; /debugtype:cv CodeView或者Program Database格式(依赖 /pdb 选项); /debugtype:both 同时产生COFF和CodeView/Program Database信息。

/pdb 告诉Linker到底采用CodeView还是Program Database格式. /pdb:none 告诉Linker采用CodeView格式, /pdb:filename 告诉linker采用Program Database格式而且制定了PDB文件的名字.如果debugtype:coff 选项设置了, /pdb 选项不起作用.

/pdbtype选项主要用在有多个文件需要链接时,告诉链接器如何处理各个文件的调试信息。/pdbtype:sept表示Linker不会将各个文件的PDB文件合并到最后一个PDB文件中。如果要调试,需要准备各个PDB文件,而/pdbtype:con选项就是将各个PDB文件合并到一个PDB文件中。

/debugtype /pdb 格式
存储
coff
无作用
COFF
EXE
coff
无作用
COFF
EXE
cv
/pdb:none
CodeView
EXE
cv
/pdb:filename
Program Database
.PDB both
/pdb:none COFF and CodeView EXE
both
/pdb:filename COFF and Program Database COFF信息存储在EXE中,Program Database存储在单独PDB文件中
表3 不同的Linker选项

Visual C++ 2002,2003,2005

编译器选项

主要包含了/Zd, /Z7, /Zi, /ZI。但是/Zd已经在Visual C++ 2005中不被支持了。

 

链接器选项

主要包含三个选项:
/debug 告诉Linker产生调试信息,如果该选项未设置,其它选项设置都不起作用。
/pdb:filename 告诉linker采用Program Database格式而且制定了PDB文件的名字.
/pdbstripped 告诉Linker产生单独的PDB文件,只包含两种信息:public functions and variables;FPO information.
在Visual C++.NET中,Linker已经不支持COFF和CODEVIEW两种格式了。

 静态库的调试信息

由于静态库不需要Linker,因此静态库的调试信息相对来说就简单多了,设置/Z*(Z7,Zd,Zi,ZI)选项就可以产生相应的调试信息。
对于Z7和Zd选项,调试信息存储在相应的.lib文件中,而Zi和ZI选项,调试信息存储在独立的.PDB文件中。

调试信息和可执行文件大小关系

调试信息是否影响最终EXE文件的大小,依赖于调试信息存储的地方,说到底依赖于我们选择的格式。
当采用COFF和CodeView方式时,通常调试信息存储在EXE文件中,将会导致EXE文件极度膨胀,基本上会翻倍。
当采用Program Database方式时,EXE文件就几乎不受影响了。EXE文件仅仅增加了几百个字节的头域,用于定位相应的PDB文件信息。

选项
格式
存储
内容
/Z7 CodeView .OBJ
  • Public functions and variables
  • Private functions and variables
  • Source file and line information
  • Type information
  • FPO information
/Zi Program Database .PDB
  • Public functions and variables
  • Private functions and variables
  • Source file and line information
  • Type information
  • FPO information
/ZI Program Database .PDB
  • Public functions and variables
  • Private functions and variables
  • Source file and line information
  • Type information
  • FPO information
  • Edit and Continue data

表4:Visual C++.NET下的编译选项