1 : // Copyright 2014 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/kasko/minidump.h"
16 :
17 : #include <Windows.h> // NOLINT
18 : #include <DbgHelp.h>
19 :
20 : #include "base/files/file.h"
21 : #include "base/process/process_handle.h"
22 : #include "base/win/scoped_handle.h"
23 :
24 : #include "syzygy/common/com_utils.h"
25 :
26 : namespace kasko {
27 :
28 : namespace {
29 :
30 : // Minidump with stacks, PEB, TEB, and unloaded module list.
31 : const MINIDUMP_TYPE kSmallDumpType = static_cast<MINIDUMP_TYPE>(
32 : MiniDumpWithProcessThreadData | // Get PEB and TEB.
33 : MiniDumpWithUnloadedModules); // Get unloaded modules when available.
34 :
35 : // Minidump with all of the above, plus memory referenced from stack.
36 : const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>(
37 : MiniDumpWithProcessThreadData | // Get PEB and TEB.
38 : MiniDumpWithUnloadedModules | // Get unloaded modules when available.
39 : MiniDumpWithIndirectlyReferencedMemory); // Get memory referenced by stack.
40 :
41 : // Large dump with all process memory.
42 : const MINIDUMP_TYPE kFullDumpType = static_cast<MINIDUMP_TYPE>(
43 : MiniDumpWithFullMemory | // Full memory from process.
44 : MiniDumpWithProcessThreadData | // Get PEB and TEB.
45 : MiniDumpWithHandleData | // Get all handle information.
46 : MiniDumpWithUnloadedModules); // Get unloaded modules when available.
47 :
48 : } // namespace
49 :
50 : bool GenerateMinidump(const base::FilePath& destination,
51 : base::ProcessId target_process_id,
52 : base::PlatformThreadId thread_id,
53 : unsigned long client_exception_pointers,
54 : MinidumpType minidump_type,
55 E : const std::vector<CustomStream>& custom_streams) {
56 : base::win::ScopedHandle target_process_handle(
57 E : ::OpenProcess(GENERIC_ALL, FALSE, target_process_id));
58 E : if (!target_process_handle) {
59 i : LOG(ERROR) << "Failed to open target process: " << ::common::LogWe() << ".";
60 i : return false;
61 : }
62 :
63 E : MINIDUMP_EXCEPTION_INFORMATION* dump_exception_pointers = NULL;
64 : MINIDUMP_EXCEPTION_INFORMATION dump_exception_info;
65 :
66 E : if (client_exception_pointers) {
67 E : dump_exception_info.ThreadId = thread_id;
68 : dump_exception_info.ExceptionPointers =
69 E : reinterpret_cast<PEXCEPTION_POINTERS>(client_exception_pointers);
70 E : dump_exception_info.ClientPointers = true;
71 :
72 E : dump_exception_pointers = &dump_exception_info;
73 : }
74 :
75 : base::File destination_file(destination, static_cast<base::File::Flags>(
76 : base::File::FLAG_CREATE_ALWAYS |
77 E : base::File::FLAG_WRITE));
78 E : if (!destination_file.IsValid()) {
79 E : LOG(ERROR) << "Failed to create destination file: " << destination.value();
80 E : return false;
81 : }
82 :
83 E : MINIDUMP_TYPE platform_minidump_type = kSmallDumpType;
84 :
85 E : switch (minidump_type) {
86 : case SMALL_DUMP_TYPE:
87 E : platform_minidump_type = kSmallDumpType;
88 E : break;
89 : case LARGER_DUMP_TYPE:
90 E : platform_minidump_type = kLargerDumpType;
91 E : break;
92 : case FULL_DUMP_TYPE:
93 E : platform_minidump_type = kFullDumpType;
94 E : break;
95 : default:
96 i : NOTREACHED();
97 : break;
98 : }
99 :
100 E : std::vector<MINIDUMP_USER_STREAM> user_streams;
101 E : for (const auto& custom_stream : custom_streams) {
102 : MINIDUMP_USER_STREAM user_stream = {custom_stream.type,
103 : custom_stream.length,
104 E : const_cast<void*>(custom_stream.data)};
105 E : user_streams.push_back(user_stream);
106 E : }
107 :
108 : MINIDUMP_USER_STREAM_INFORMATION
109 E : user_stream_information = {custom_streams.size(), user_streams.data()};
110 :
111 : if (::MiniDumpWriteDump(target_process_handle, target_process_id,
112 : destination_file.GetPlatformFile(),
113 : platform_minidump_type, dump_exception_pointers,
114 E : &user_stream_information, NULL) == FALSE) {
115 i : LOG(ERROR) << "MiniDumpWriteDump failed: " << ::common::LogWe() << ".";
116 i : return false;
117 : }
118 :
119 E : return true;
120 E : }
121 :
122 : } // namespace kasko
|