本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

Crashpad是Chromium内核提供的进程崩溃信息处理工具。在应用使用Web组件导致进程(主要是Web渲染进程)崩溃时,Crashpad会在应用主进程沙箱目录写入minidump文件(后缀为.dmp),记录进程崩溃的原因、线程信息、寄存器信息等关键数据,帮助分析和定位崩溃问题。

特点

  • 自动记录:进程崩溃时自动生成dump文件

  • 信息全面:包含崩溃原因、线程栈、寄存器状态等

  • 定位精准:可结合符号文件定位到源码位置

二、Crashpad原理

Web渲染进程崩溃
    ↓
Crashpad捕获崩溃信息
    ↓
生成minidump文件(.dmp)
    ↓
写入应用沙箱目录
    ↓
获取并解析
    ↓
定位崩溃源码位置

三、dmp文件存储位置

文件路径

当Web组件相关进程崩溃后,dmp文件会生成在应用主进程沙箱目录下:

/data/storage/el2/log/crashpad

文件格式

  • 格式:二进制格式

  • 后缀:.dmp

  • 命名:UUID格式(如:b678e0b5-894b-4794-9ab3-fb5d6dda06a3.dmp

文件内容

dmp文件记录了以下关键信息:

  • 进程崩溃的原因

  • 崩溃时的线程信息

  • CPU寄存器状态

  • 调用栈信息

  • 内存片段

四、获取dmp文件

访问应用沙箱

需要通过Native方式访问应用沙箱获取dmp文件。具体实现参考:

文件访问示例(C++)

#include <filesystem>
#include <fstream>
#include <iostream>
#include <vector>

// 获取crashpad目录路径
std::string getCrashpadPath() {
    // 沙箱基础路径
    const char* basePath = "/data/storage/el2/log";
    std::string crashpadPath = std::string(basePath) + "/crashpad";
    return crashpadPath;
}

// 列出所有dmp文件
std::vector<std::string> listDmpFiles() {
    std::vector<std::string> dmpFiles;
    std::string crashpadPath = getCrashpadPath();
    
    try {
        for (const auto& entry : std::filesystem::directory_iterator(crashpadPath)) {
            if (entry.path().extension() == ".dmp") {
                dmpFiles.push_back(entry.path().string());
                std::cout << "找到dmp文件: " << entry.path().string() << std::endl;
            }
        }
    } catch (const std::exception& e) {
        std::cerr << "访问目录失败: " << e.what() << std::endl;
    }
    
    return dmpFiles;
}

// 复制dmp文件到可访问位置
bool copyDmpFile(const std::string& sourcePath, const std::string& destPath) {
    try {
        std::filesystem::copy_file(sourcePath, destPath, 
            std::filesystem::copy_options::overwrite_existing);
        std::cout << "文件已复制到: " << destPath << std::endl;
        return true;
    } catch (const std::exception& e) {
        std::cerr << "复制文件失败: " << e.what() << std::endl;
        return false;
    }
}

五、解析dmp文件

1. 获取minidump_stackwalk工具

minidump_stackwalk由breakpad项目源码编译得到。

源码仓库

https://chromium.googlesource.com/breakpad/breakpad

编译方法(Linux环境):

# 克隆仓库
git clone https://chromium.googlesource.com/breakpad/breakpad
cd breakpad

# 配置编译
./configure
make

# 编译后的工具位于 src/processor/ 目录
# minidump_stackwalk 可执行文件

2. 使用minidump_stackwalk解析

基本命令

./minidump_stackwalk [dmp文件路径] > [输出文件]

示例

./minidump_stackwalk b678e0b5-894b-4794-9ab3-fb5d6dda06a3.dmp > parsed_stacktrace.txt

3. 输出示例

Crash reason: SIGSEGV /SEGV_MAPERR
Crash address: 0x0
Process uptime: 12 seconds

Thread 0 (crashed)
 0 libweb_engine.so + 0x2e0b340
    x0 = 0x00000006a5719ff8   x1 = 0x000000019a5a28c0
    x2 = 0x0000000000020441   x3 = 0x00000000000001b6
    x4 = 0x0000000000000018   x5 = 0x0000000000008065
    x6 = 0x0000000000008065   x7 = 0x63ff686067666d60
    x8 = 0x0000000000000000   x9 = 0x5f129cf9e7bf008c
    x10 = 0x0000000000000001  x11 = 0x0000000000000000
    x12 = 0x000000069bfcc6d8  x13 = 0x0000000009a1746e
    x14 = 0x0000000000000000  x15 = 0x0000000000000000
    x16 = 0x0000000690df4850  x17 = 0x000000010c0d47f8
    x18 = 0x0000000000000000  x19 = 0x0000005eea827db8
    x20 = 0x0000005eea827c38  x21 = 0x00000006a56b1000
    x22 = 0x00000006a8b85020  x23 = 0x00000020002103c0
    x24 = 0x00000006a56b8a70  x25 = 0x0000000000000000
    x26 = 0x00000006a8b84e00  x27 = 0x0000000000000001
    x28 = 0x0000000000000000  fp  = 0x0000005eea827c10
    lr  = 0x000000069fa4b33c  sp  = 0x0000005eea827c10
    pc  = 0x000000069fa4b340
    Found by: given as instruction pointer in context

 1 libweb_engine.so + 0x2e0b338
    fp = 0x0000005eea827d80  lr = 0x000000069fa48d44
    sp = 0x0000005eea827c20  pc = 0x000000069fa4b33c
    Found by: previous frame's frame pointer

 2 libweb_engine.so + 0x2e08d40
    fp = 0x0000005eea827e50  lr = 0x00000006a385cef8
    sp = 0x0000005eea827d90  pc = 0x000000069fa48d44
    Found by: previous frame's frame pointer

 3 libweb_engine.so + 0x6c1cef4
    fp = 0x0000005eea828260  lr = 0x00000006a0f11298
    sp = 0x0000005eea827e60  pc = 0x00000006a385cef8
...

4. 解析结果

信息项 示例 说明
Crash reason SIGSEGV /SEGV_MAPERR 导致进程崩溃的信号,此处为段错误
Crash address 0x0 崩溃时访问的内存地址
Process uptime 12 seconds 进程运行时间
Thread X (crashed) Thread 0 (crashed) 发生崩溃的线程
寄存器信息 x0-x28, fp, lr, sp, pc CPU寄存器状态
调用栈 libweb_engine.so + 0x2e0b340 各层调用栈,包含SO偏移地址

六、定位崩溃源码位置

使用llvm-addr2line工具

llvm-addr2line工具链位于SDK中,可以将SO偏移地址转换为源码位置。

基本命令

./llvm-addr2line -Cfpie [SO文件] [偏移地址]

参数说明

  • -C:反修饰C++符号名

  • -f:显示函数名

  • -p:显示每行信息

  • -i:内联函数展开

  • -e:指定可执行文件

示例

./llvm-addr2line -Cfpie libweb_engine.so 0x2e0b340

输出示例

WebEngine::RenderFrameImpl::OnMessageReceived(IPC::Message const&) at /path/to/source/render_frame_impl.cc:1234

七、完整操作

步骤1:应用崩溃后获取dmp文件

# 进入应用沙箱crashpad目录
cd /data/storage/el2/log/crashpad

# 查看生成的dmp文件
ls -la *.dmp
# 输出: b678e0b5-894b-4794-9ab3-fb5d6dda06a3.dmp

步骤2:将dmp文件导出到开发机

# 使用hdc命令导出文件
hdc file recv /data/storage/el2/log/crashpad/b678e0b5-894b-4794-9ab3-fb5d6dda06a3.dmp ./

步骤3:使用minidump_stackwalk解析

# 解析dmp文件
./minidump_stackwalk b678e0b5-894b-4794-9ab3-fb5d6dda06a3.dmp > crash_analysis.txt

# 查看解析结果
cat crash_analysis.txt

步骤4:定位源码位置

# 从解析结果中找到关键偏移地址(如0x2e0b340)
# 使用llvm-addr2line转换
./llvm-addr2line -Cfpie libweb_engine.so 0x2e0b340

步骤5:分析崩溃原因

根据解析结果判断崩溃类型:

崩溃信号 常见原因
SIGSEGV 段错误,访问非法内存地址
SIGABRT 进程主动中止
SIGFPE 算术异常(除零等)
SIGILL 非法指令
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐