Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(142)

Side by Side Diff: third_party/breakpad/src/client/windows/crash_generation/minidump_generator.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2008, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 #include "client/windows/crash_generation/minidump_generator.h"
31 #include <cassert>
32 #include "client/windows/common/auto_critical_section.h"
33 #include "common/windows/guid_string.h"
34
35 using std::wstring;
36
37 namespace google_breakpad {
38
39 MinidumpGenerator::MinidumpGenerator(const wstring& dump_path)
40 : dbghelp_module_(NULL),
41 rpcrt4_module_(NULL),
42 dump_path_(dump_path),
43 write_dump_(NULL),
44 create_uuid_(NULL) {
45 InitializeCriticalSection(&module_load_sync_);
46 InitializeCriticalSection(&get_proc_address_sync_);
47 }
48
49 MinidumpGenerator::~MinidumpGenerator() {
50 if (dbghelp_module_) {
51 FreeLibrary(dbghelp_module_);
52 }
53
54 if (rpcrt4_module_) {
55 FreeLibrary(rpcrt4_module_);
56 }
57
58 DeleteCriticalSection(&get_proc_address_sync_);
59 DeleteCriticalSection(&module_load_sync_);
60 }
61
62 bool MinidumpGenerator::WriteMinidump(HANDLE process_handle,
63 DWORD process_id,
64 DWORD thread_id,
65 DWORD requesting_thread_id,
66 EXCEPTION_POINTERS* exception_pointers,
67 MDRawAssertionInfo* assert_info,
68 MINIDUMP_TYPE dump_type,
69 bool is_client_pointers,
70 wstring* dump_path) {
71 // Just call the full WriteMinidump with NULL as the full_dump_path.
72 return this->WriteMinidump(process_handle, process_id, thread_id,
73 requesting_thread_id, exception_pointers,
74 assert_info, dump_type, is_client_pointers,
75 dump_path, NULL);
76 }
77
78 bool MinidumpGenerator::WriteMinidump(HANDLE process_handle,
79 DWORD process_id,
80 DWORD thread_id,
81 DWORD requesting_thread_id,
82 EXCEPTION_POINTERS* exception_pointers,
83 MDRawAssertionInfo* assert_info,
84 MINIDUMP_TYPE dump_type,
85 bool is_client_pointers,
86 wstring* dump_path,
87 wstring* full_dump_path) {
88 MiniDumpWriteDumpType write_dump = GetWriteDump();
89 if (!write_dump) {
90 return false;
91 }
92
93 wstring dump_file_path;
94 if (!GenerateDumpFilePath(&dump_file_path)) {
95 return false;
96 }
97
98 // If the client requests a full memory dump, we will write a normal mini
99 // dump and a full memory dump. Both dump files use the same uuid as file
100 // name prefix.
101 bool full_memory_dump = (dump_type & MiniDumpWithFullMemory) != 0;
102 wstring full_dump_file_path;
103 if (full_memory_dump) {
104 full_dump_file_path.assign(dump_file_path);
105 full_dump_file_path.resize(full_dump_file_path.size() - 4); // strip .dmp
106 full_dump_file_path.append(TEXT("-full.dmp"));
107 }
108
109 HANDLE dump_file = CreateFile(dump_file_path.c_str(),
110 GENERIC_WRITE,
111 0,
112 NULL,
113 CREATE_NEW,
114 FILE_ATTRIBUTE_NORMAL,
115 NULL);
116
117 if (dump_file == INVALID_HANDLE_VALUE) {
118 return false;
119 }
120
121 HANDLE full_dump_file = INVALID_HANDLE_VALUE;
122 if (full_memory_dump) {
123 full_dump_file = CreateFile(full_dump_file_path.c_str(),
124 GENERIC_WRITE,
125 0,
126 NULL,
127 CREATE_NEW,
128 FILE_ATTRIBUTE_NORMAL,
129 NULL);
130
131 if (full_dump_file == INVALID_HANDLE_VALUE) {
132 CloseHandle(dump_file);
133 return false;
134 }
135 }
136
137 MINIDUMP_EXCEPTION_INFORMATION* dump_exception_pointers = NULL;
138 MINIDUMP_EXCEPTION_INFORMATION dump_exception_info;
139
140 // Setup the exception information object only if it's a dump
141 // due to an exception.
142 if (exception_pointers) {
143 dump_exception_pointers = &dump_exception_info;
144 dump_exception_info.ThreadId = thread_id;
145 dump_exception_info.ExceptionPointers = exception_pointers;
146 dump_exception_info.ClientPointers = is_client_pointers;
147 }
148
149 // Add an MDRawBreakpadInfo stream to the minidump, to provide additional
150 // information about the exception handler to the Breakpad processor.
151 // The information will help the processor determine which threads are
152 // relevant. The Breakpad processor does not require this information but
153 // can function better with Breakpad-generated dumps when it is present.
154 // The native debugger is not harmed by the presence of this information.
155 MDRawBreakpadInfo breakpad_info = {0};
156 if (!is_client_pointers) {
157 // Set the dump thread id and requesting thread id only in case of
158 // in-process dump generation.
159 breakpad_info.validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID |
160 MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID;
161 breakpad_info.dump_thread_id = thread_id;
162 breakpad_info.requesting_thread_id = requesting_thread_id;
163 }
164
165 // Leave room in user_stream_array for a possible assertion info stream.
166 MINIDUMP_USER_STREAM user_stream_array[2];
167 user_stream_array[0].Type = MD_BREAKPAD_INFO_STREAM;
168 user_stream_array[0].BufferSize = sizeof(breakpad_info);
169 user_stream_array[0].Buffer = &breakpad_info;
170
171 MINIDUMP_USER_STREAM_INFORMATION user_streams;
172 user_streams.UserStreamCount = 1;
173 user_streams.UserStreamArray = user_stream_array;
174
175 MDRawAssertionInfo* actual_assert_info = assert_info;
176 MDRawAssertionInfo client_assert_info = {0};
177
178 if (assert_info) {
179 // If the assertion info object lives in the client process,
180 // read the memory of the client process.
181 if (is_client_pointers) {
182 SIZE_T bytes_read = 0;
183 if (!ReadProcessMemory(process_handle,
184 assert_info,
185 &client_assert_info,
186 sizeof(client_assert_info),
187 &bytes_read)) {
188 CloseHandle(dump_file);
189 if (full_dump_file != INVALID_HANDLE_VALUE)
190 CloseHandle(full_dump_file);
191 return false;
192 }
193
194 if (bytes_read != sizeof(client_assert_info)) {
195 CloseHandle(dump_file);
196 if (full_dump_file != INVALID_HANDLE_VALUE)
197 CloseHandle(full_dump_file);
198 return false;
199 }
200
201 actual_assert_info = &client_assert_info;
202 }
203
204 user_stream_array[1].Type = MD_ASSERTION_INFO_STREAM;
205 user_stream_array[1].BufferSize = sizeof(MDRawAssertionInfo);
206 user_stream_array[1].Buffer = actual_assert_info;
207 ++user_streams.UserStreamCount;
208 }
209
210 bool result_minidump = write_dump(
211 process_handle,
212 process_id,
213 dump_file,
214 static_cast<MINIDUMP_TYPE>((dump_type & (~MiniDumpWithFullMemory))
215 | MiniDumpNormal),
216 exception_pointers ? &dump_exception_info : NULL,
217 &user_streams,
218 NULL) != FALSE;
219
220 bool result_full_memory = true;
221 if (full_memory_dump) {
222 result_full_memory = write_dump(
223 process_handle,
224 process_id,
225 full_dump_file,
226 static_cast<MINIDUMP_TYPE>(dump_type & (~MiniDumpNormal)),
227 exception_pointers ? &dump_exception_info : NULL,
228 &user_streams,
229 NULL) != FALSE;
230 }
231
232 bool result = result_minidump && result_full_memory;
233
234 CloseHandle(dump_file);
235 if (full_dump_file != INVALID_HANDLE_VALUE)
236 CloseHandle(full_dump_file);
237
238 // Store the path of the dump file in the out parameter if dump generation
239 // succeeded.
240 if (result && dump_path) {
241 *dump_path = dump_file_path;
242 }
243 if (result && full_memory_dump && full_dump_path) {
244 *full_dump_path = full_dump_file_path;
245 }
246
247 return result;
248 }
249
250 HMODULE MinidumpGenerator::GetDbghelpModule() {
251 AutoCriticalSection lock(&module_load_sync_);
252 if (!dbghelp_module_) {
253 dbghelp_module_ = LoadLibrary(TEXT("dbghelp.dll"));
254 }
255
256 return dbghelp_module_;
257 }
258
259 MinidumpGenerator::MiniDumpWriteDumpType MinidumpGenerator::GetWriteDump() {
260 AutoCriticalSection lock(&get_proc_address_sync_);
261 if (!write_dump_) {
262 HMODULE module = GetDbghelpModule();
263 if (module) {
264 FARPROC proc = GetProcAddress(module, "MiniDumpWriteDump");
265 write_dump_ = reinterpret_cast<MiniDumpWriteDumpType>(proc);
266 }
267 }
268
269 return write_dump_;
270 }
271
272 HMODULE MinidumpGenerator::GetRpcrt4Module() {
273 AutoCriticalSection lock(&module_load_sync_);
274 if (!rpcrt4_module_) {
275 rpcrt4_module_ = LoadLibrary(TEXT("rpcrt4.dll"));
276 }
277
278 return rpcrt4_module_;
279 }
280
281 MinidumpGenerator::UuidCreateType MinidumpGenerator::GetCreateUuid() {
282 AutoCriticalSection lock(&module_load_sync_);
283 if (!create_uuid_) {
284 HMODULE module = GetRpcrt4Module();
285 if (module) {
286 FARPROC proc = GetProcAddress(module, "UuidCreate");
287 create_uuid_ = reinterpret_cast<UuidCreateType>(proc);
288 }
289 }
290
291 return create_uuid_;
292 }
293
294 bool MinidumpGenerator::GenerateDumpFilePath(wstring* file_path) {
295 UUID id = {0};
296
297 UuidCreateType create_uuid = GetCreateUuid();
298 if (!create_uuid) {
299 return false;
300 }
301
302 create_uuid(&id);
303 wstring id_str = GUIDString::GUIDToWString(&id);
304
305 *file_path = dump_path_ + TEXT("\\") + id_str + TEXT(".dmp");
306 return true;
307 }
308
309 } // namespace google_breakpad
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698