dmp文件读取(四)- Exception
| 阅读 | 共 845 字,阅读约
Overview
dmp文件读取(四)
前面两篇文章,已经把分析dmp所需要的准备工作:线程信息、模块信息的读取都分析完了。今天该崩溃的主角出场:异常(Exception) Stream的读取
Exception Stream概述
- Exception Stream记录了进程崩溃时,崩溃现场的基本信息
- 崩溃信息包括:
- 崩溃时的线程id
- 异常状态码
- 异常标识
- 异常的内存地址
- 寄存器信息
- 其他信息
- 以上信息都保存在
MDRawExceptionStream
中
Exception Stream读取入口
- dump的GetException方法,获取dmp文件中的崩溃信息
- 读取的模块列表信息保存在MinidumpException中
1ProcessResult MinidumpProcessor::Process(
2 Minidump *dump, ProcessState *process_state) {
3 ...
4 // 异常信息读取入口
5 MinidumpException *exception = dump->GetException();
6 ...
7}
MinidumpException
- Exception Stream的类型为MD_EXCEPTION_STREAM
- 存储在dmp文件中的exectpion信息,反序列化之后保存为MDRawExceptionStream对象
1class MinidumpException : public MinidumpStream {
2 public:
3 virtual ~MinidumpException();
4
5 const MDRawExceptionStream* exception() const {
6 return valid_ ? &exception_ : NULL;
7 }
8
9 // The thread ID is used to determine if a thread is the exception thread,
10 // so a special getter is provided to retrieve this data from the
11 // MDRawExceptionStream structure. Returns false if the thread ID cannot
12 // be determined.
13 bool GetThreadID(uint32_t *thread_id) const;
14
15 MinidumpContext* GetContext();
16
17 // Print a human-readable representation of the object to stdout.
18 void Print();
19
20 private:
21 friend class Minidump;
22
23 static const uint32_t kStreamType = MD_EXCEPTION_STREAM;
24
25 explicit MinidumpException(Minidump* minidump);
26
27 bool Read(uint32_t expected_size) override;
28
29 MDRawExceptionStream exception_;
30 MinidumpContext* context_;
31
32 DISALLOW_COPY_AND_ASSIGN(MinidumpException);
33};
MDRawExceptionStream
1typedef struct {
2 // 线程id
3 uint32_t thread_id;
4 uint32_t __align;
5
6 // 异常详情
7 MDException exception_record;
8
9 // 线程上下文
10 MDLocationDescriptor thread_context;
11} MDRawExceptionStream; /* MINIDUMP_EXCEPTION_STREAM */
Exception stream读取核心代码
- 这部分实现和上一篇介绍的一样,此处不再赘述
1MinidumpException* Minidump::GetException() {
2 MinidumpException* exception;
3 return GetStream(&exception);
4}
Read方法
- 该方法和前面介绍的也基本相同
- 先读取数据信息到exception_对象中
- 根据大小端判断是否需要做高低位交换
- 读取完毕,崩溃现场信息就保存在MinidumpException对象中,为后续真正分析做准备
1bool MinidumpException::Read(uint32_t expected_size) {
2 // Invalidate cached data.
3 delete context_;
4 context_ = NULL;
5
6 valid_ = false;
7
8 if (expected_size != sizeof(exception_)) {
9 BPLOG(ERROR) << "MinidumpException size mismatch, " << expected_size <<
10 " != " << sizeof(exception_);
11 return false;
12 }
13
14 if (!minidump_->ReadBytes(&exception_, sizeof(exception_))) {
15 BPLOG(ERROR) << "MinidumpException cannot read exception";
16 return false;
17 }
18
19 if (minidump_->swap()) {
20 Swap(&exception_.thread_id);
21 // exception_.__align is for alignment only and does not need to be
22 // swapped.
23 Swap(&exception_.exception_record.exception_code);
24 Swap(&exception_.exception_record.exception_flags);
25 Swap(&exception_.exception_record.exception_record);
26 Swap(&exception_.exception_record.exception_address);
27 Swap(&exception_.exception_record.number_parameters);
28 // exception_.exception_record.__align is for alignment only and does not
29 // need to be swapped.
30 for (unsigned int parameter_index = 0;
31 parameter_index < MD_EXCEPTION_MAXIMUM_PARAMETERS;
32 ++parameter_index) {
33 Swap(&exception_.exception_record.exception_information[parameter_index]);
34 }
35 Swap(&exception_.thread_context);
36 }
37
38 valid_ = true;
39 return true;
40}