dmp文件读取(一)- 概述
| 阅读 | 共 1065 字,阅读约
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}