zoukankan      html  css  js  c++  java
  • Google Breakpad 完全解析(一) —— Windows入门篇

    原创文章,转载请标明出处:Soul Apogee (http://bigasp.com),谢谢。

    Google breakpad是一个非常实用的跨平台的崩溃转储和分析模块,他支持Windows,Linux和Mac和Solaris。由于他本身跨平台,所以很大的减少我们在平台移植时的工作,毕竟崩溃转储,每个平台下都不同,使用起来很难统一,而Google breakpad就帮我们做到了这一点,不管是哪个平台下的崩溃,都能够进行统一的分析。现在很多工程都在使用他:最著名的几个如Chrome,Firefox,Picasa和Google Earth。另外他的License是BSD的,也就是说,我们即便是在商业软件中使用,也是合法的,哈哈,这么好的东西,我们能放过么?现在就让我们来看看这个神奇的软件吧。

    原理简介

    breakpad抓取dump的方式和一般我们抓取dump的方式不一样。在breakpad的wiki上有一幅图可以很好的概括他的原理。

    breakpad把应用程序分成三个部分,代码,breakpad客户端和调试信息。

    1. 在build system中,通过symbol dumper用平台相关的调试信息生成平台无关的symbol文件。这样做的好处很明显,一旦平台无关了,所有平台的崩溃就可以做统一的分析了。
    2. breakpad采取进程外转储和分析崩溃的方式,他使用C/S结构,客户端用来捕获当前进程中发生的崩溃,并通知服务端崩溃发生。服务端用来响应客户端,抓取dump文件。这样做的目的是为了减少崩溃进程对dump的影响。
    3. Dump生成后转发到崩溃分析器中,这个部分可以在本地也可以在服务器上,他对Dump文件进行解析,生成可读的堆栈信息。

    这就是breakpad处理dump大概的流程。

    对于原理的介绍google写的已经相当好了。更多的详细信息,可以直接移步到breakpad的wiki

    安装和编译

    breakpad的编译比较曲折,所以在此记录一下。

    编译breakpad,请确认你的机器上装有以下的软件:
    1. python 2.4.3
    请不要使用python3,会报错。另外python2中推荐这个版本,使用新的版本在编译其他google的工程时有时会报错

    2. Windows SDK 7
    如果没有这个,编译会报错。另外这个是在线安装,时间很久,最好并行做其他的事情。

    3. VS2005的补丁
    KB918559
    KB926601
    KB935225
    KB943969
    KB947315

    已经安装了以上软件的童鞋,就可以开始进行下面的工作鸟

    1. 使用svn把代码checkout下来

    1
    2
    # Non-members may check out a read-only working copy anonymously over HTTP.
    svn checkout http://google-breakpad.googlecode.com/svn/trunk/ google-breakpad-read-only

    2. 设置Windows SDK 7
    装过其他版本Windows SDK的童鞋,记得一定要进行这一步,SDK的安装程序,并不会帮你设置VS。
    运行开始菜单->程序->Microsoft Windows SDK v7.0->Visual Studio Registration->Windows SDK Configuration Tool,选择v7.0,点击Make Current。

    3. 为python设置环境变量
    由于breakpad使用python来生成Windows下的工程文件,所以需要将python所在目录,设置到环境变量PATH中去。

    4. 生成Windows工程文件

    1
    2
    3
    4
    cd "源码目录/src/tools/gyp"
     
    # 注意,此处不能使用全路径,不然会出错
    gyp.bat "../../client/windows/breakpad_client.gyp"

    此时,在src/client/windows下就可以看到生成好的breakpad_client.sln了。运行吧!

    5. Hello World!
    编译build all,现在一般是不会报错了,如果报错,请检查是不是漏了什么步骤,特别是补丁。
    编译完成之后,运行crash_generation_app吧,这是他的测试程序,dump的默认位置保存在C:Dumps下,请注意先建立好目录,不然会无法使用。
    启动测试程序之后,此时还不能抓取dump,因为这个是breakpad中的服务器端,需要再启动一个测试程序,在第二个测试程序中,我们就可以试验Client菜单中的各种崩溃了。这些崩溃都会被抓住转存到C:Dumps目录下。

    如何使用breakpad

    在Windows下使用breakpad的方法很简单,只需要创建一个ExceptionHandler的类即可,大家可以在crash_generation_app这个工程中找到示例代码,也可以直接移步Wiki,上面说的也很详细。

    1.进程内抓取Dump文件

    进程内抓取Dump文件是最简单的breakpad的用法。使用方法很简单:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    const std::wstring s_strCrashDir = L"c:dumps";
     
    bool
    InitBreakpad()
    {
        google_breakpad::ExceptionHandler *pCrashHandler =
            new google_breakpad::ExceptionHandler(s_strCrashDir,
            onExceptionFilter,
            onMinidumpDumped,
            NULL,
            google_breakpad::ExceptionHandler::HANDLER_ALL,
            MiniDumpNormal,
            NULL,
            NULL);
     
        if(pCrashHandler == NULL) {
            return false;
        }
     
        return true;
    }

    2.进程外抓取Dump文件

    使用进程外抓取Dump时,需要指定服务端和客户端,在服务端中需要创建CrashGenerationServer的实例,而在客户端中则只需要创建ExceptionHandler即可。此外,如果服务端自己需要抓进程内的Dump,请将pipe的参数置为NULL。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    const wchar_t s_pPipeName[] = L"\.pipereakpadcrash_handler_server";
    const std::wstring s_strCrashDir = L"c:dumps";
     
    bool
    InitBreakpad()
    {
        google_breakpad::CrashGenerationServer *pCrashServer =
            new google_breakpad::CrashGenerationServer(s_pPipeName,
            NULL,
            onClientConnected,
            NULL,
            onClientDumpRequest,
            NULL,
            onClientExited,
            NULL,
            true,
            &s_strCrashDir);
     
        if(pCrashServer == NULL) {
            return false;
        }
     
        // 如果已经服务端已经启动了,此处启动会失败
        if(!pCrashServer->Start()) {
            delete pCrashServer;
            pCrashServer = NULL;
        }
     
        google_breakpad::ExceptionHandler *pCrashHandler =
            new google_breakpad::ExceptionHandler(s_strCrashDir,
            onExceptionFilter,
            onMinidumpDumped,
            NULL,
            google_breakpad::ExceptionHandler::HANDLER_ALL,
            MiniDumpNormal,
            (pCrashServer == NULL) ? s_pPipeName : NULL, // 如果是服务端,则直接使用进程内dump
            NULL);
     
        if(pCrashHandler == NULL) {
            return false;
        }
     
        return true;
    }

    使用breakpad的时候,有两个地方需要注意:
    1. 记得把breakpad的solution下的几个工程,包含到你开发的工程中,或者直接包含他们的lib。
    common:基础功能,包含一个对GUID的封装和http上传的类。
    exception_handler:用来捕获崩溃的类。
    crash_generation_server:breakpad的服务端,用来在产生崩溃时抓取dump。
    crash_generation_client:breakpad的客户端,用来捕获当前进程的崩溃。

    2. 在初始化breakpad之前,记得先创建好dump文件的目录,不然breakpad服务端将不能正常的写dump,这会导致breakpad客户端在崩溃时无限等待服务端dump写完的消息,最后失去响应。

    一条评论

      1. 李一 说道:

        终于找到原版了,之前一直看到的都是转载你的,想问一下,我按照你说的,安装python2.4.3,with open报错,然后安装python2.6版本的,没有报错,但是并没有生成breakpad_client.sln文件,环境变量设置了,没装SDK7,应该和这个没关系吧,希望能发邮件给我,拜谢!

  • 相关阅读:
    trie树(板子)
    A. Many Equal Substrings(思维)
    D2 Equalizing by Division (hard version) &&D1 Equalizing by Division (easy version) (easy version)(Codeforces Round #582 (Div. 3))
    B. Square Filling ( Educational Codeforces Round 71 (Rated for Div. 2))
    A. Creating a Character(Educational Codeforces Round 72 (Rated for Div. 2) )
    字符画 (CSU 2163 )
    The Nth Item (The 2019 Asia Nanchang First Round Online Programming Contest)
    Magic Master (The 2019 Asia Nanchang First Round Online Programming Contest)
    Fire-Fighting Hero (The 2019 Asia Nanchang First Round Online Programming Contest)
    Pangu Separates Heaven and Earth(签到题)(The 2019 Asia Nanchang First Round Online Programming Contest)
  • 原文地址:https://www.cnblogs.com/lancidie/p/3145504.html
Copyright © 2011-2022 走看看