dmp文件读取(一)- 概述


| 阅读 |,阅读约 3 分钟
| 复制链接:

Overview

dmp文件解析

dmp读取源码分析(一)

1. 入口文件:

src/processor/minidump_stackwalk.cc 文件 main函数

1int main(int argc, char **argv) {
2    ...
3    // 解析参数
4    ...
5    // dmp分析的核心函数
6    PrintMinidumpProcess(...)
7    ...
8}

2. 总体流程:

Minidump对象用于保存dmp文件流内容,核心代码

 1PrintMinidumpProcess(...) {
 2    ...
 3    // 第一步:读取dmp文件内容
 4    Minidump dump(minidump_file);
 5    if (!dump.Read()) {
 6      BPLOG(ERROR) << "Minidump " << dump.path() << " could not be read";
 7      return false;
 8    }
 9    
10    // 第二步:开始分析dmp
11    minidump_processor.Process(&dump, &process_state)
12    
13    // 第三步:打印分析结果
14    PrintProcessState(...)
15}

3. dmp读取流程:

 1bool Minidump::Read() {
 2
 3    // 读取文件流,保存为 std::istream
 4    if (!Open()) {
 5        BPLOG(ERROR) << "Minidump cannot open minidump";
 6        return false;
 7    }
 8    
 9    // 读取文件头,流的前32自节,保存为 MDRawHeader
10    if (!ReadBytes(&header_, sizeof(MDRawHeader))) {
11        BPLOG(ERROR) << "Minidump cannot read header";
12        return false;
13    }
14    
15    // 读取文件头:(0-4byte)
16    // 根据文件头内容,判断使用的架构是大端还是小端
17    // 文件标志是PMDM,如果是DMPM,则说明所有的高8位和低8位数据都需要做交换
18    if (header_.signature != MD_HEADER_SIGNATURE) {
19        swap_ = true;
20    } else {
21        swap_ = false;
22    }
23    
24    // 校验文件版本(5-8byte)
25    if ((header_.version & 0x0000ffff) != MD_HEADER_VERSION) {
26    BPLOG(ERROR) << "Minidump version mismatch: " <<
27                    HexString(header_.version & 0x0000ffff) << " != " <<
28                    HexString(MD_HEADER_VERSION);
29    return false;
30    }
31
32    
33    // 读取stream索引,
34    if (!SeekSet(header_.stream_directory_rva)) {
35        BPLOG(ERROR) << "Minidump cannot seek to stream directory";
36        return false;
37    }
38    
39    if (!SeekSet(header_.stream_directory_rva)) {
40    BPLOG(ERROR) << "Minidump cannot seek to stream directory";
41    return false;
42  }
43
44    // 判断流的梳理不能超过128
45    if (header_.stream_count > max_streams_) {
46        BPLOG(ERROR) << "Minidump stream count " << header_.stream_count <<
47                        " exceeds maximum " << max_streams_;
48        return false;
49    }
50    
51    // 读取各种流,保存到字典中
52    // 这一步只读取了各种流在文件中的偏移位置和大小
53    // 具体每种流的读取细节在后面的函数中展开
54    if (header_.stream_count != 0) {
55    scoped_ptr<MinidumpDirectoryEntries> directory(
56        new MinidumpDirectoryEntries(header_.stream_count));
57
58    // Read the entire array in one fell swoop, instead of reading one entry
59    // at a time in the loop.
60    if (!ReadBytes(&(*directory)[0],
61                   sizeof(MDRawDirectory) * header_.stream_count)) {
62      BPLOG(ERROR) << "Minidump cannot read stream directory";
63      return false;
64    }
65}

4. 流的读取

共有10多种流,这里只介绍主题流程,每种流具体如何读取,下一篇介绍

 1ProcessResult MinidumpProcessor::Process(
 2    Minidump *dump, ProcessState *process_state) {
 3    
 4    // 获取dmp崩溃时间,流类型:15:MD_MISC_INFO_STREAM
 5    bool has_process_create_time =
 6      GetProcessCreateTime(dump, &process_state->process_create_time_);
 7    
 8    // 获取cpu信息
 9    bool has_cpu_info = GetCPUInfo(dump, &process_state->system_info_);
10    
11    // 获取操作系统信息,流类型:7:MD_SYSTEM_INFO_STREAM
12    bool has_os_info = GetOSInfo(dump, &process_state->system_info_);
13    
14    // 获取自定义崩溃信息
15    MinidumpBreakpadInfo *breakpad_info = dump->GetBreakpadInfo();
16    
17    // 获取异常信息,流类型:6:MD_EXCEPTION_STREAM
18    MinidumpException *exception = dump->GetException();
19    
20    // 获取模块信息,流类型:4:MD_MODULE_LIST_STREAM
21    MinidumpModuleList *module_list = dump->GetModuleList();
22    
23    // 获取未加载的模块信息
24    MinidumpUnloadedModuleList *unloaded_module_list =
25      dump->GetUnloadedModuleList();
26    
27    // 获取内存信息,流类型:5:MD_MEMORY_LIST_STREAM
28    MinidumpMemoryList *memory_list = dump->GetMemoryList();
29    
30    // 获取县城信息,流类型:3:MD_THREAD_LIST_STREAM
31    MinidumpThreadList *threads = dump->GetThreadList();
32
33    // 根据cpu架构获取匹配的堆栈追溯器
34    scoped_ptr<Stackwalker> stackwalker(
35        Stackwalker::StackwalkerForCPU(process_state->system_info(),
36                                       context,
37                                       thread_memory,
38                                       process_state->modules_,
39                                       process_state->unloaded_modules_,
40                                       frame_symbolizer_));
41
42    scoped_ptr<CallStack> stack(new CallStack());
43    if (stackwalker.get()) {
44    
45        // 堆栈回溯主流程 --- 核心流程
46      if (!stackwalker->Walk(stack.get(),
47                             &process_state->modules_without_symbols_,
48                             &process_state->modules_with_corrupt_symbols_)) {
49        BPLOG(INFO) << "Stackwalker interrupt (missing symbols?) at "
50                    << thread_string;
51        interrupted = true;
52      }
53
54}