1 // Copyright 2006 Google LLC 2 // 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are 5 // met: 6 // 7 // * Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above 10 // copyright notice, this list of conditions and the following disclaimer 11 // in the documentation and/or other materials provided with the 12 // distribution. 13 // * Neither the name of Google LLC nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 // ExceptionHandler can write a minidump file when an exception occurs, 30 // or when WriteMinidump() is called explicitly by your program. 31 // 32 // To have the exception handler write minidumps when an uncaught exception 33 // (crash) occurs, you should create an instance early in the execution 34 // of your program, and keep it around for the entire time you want to 35 // have crash handling active (typically, until shutdown). 36 // 37 // If you want to write minidumps without installing the exception handler, 38 // you can create an ExceptionHandler with install_handler set to false, 39 // then call WriteMinidump. You can also use this technique if you want to 40 // use different minidump callbacks for different call sites. 41 // 42 // In either case, a callback function is called when a minidump is written, 43 // which receives the unqiue id of the minidump. The caller can use this 44 // id to collect and write additional application state, and to launch an 45 // external crash-reporting application. 46 // 47 // It is important that creation and destruction of ExceptionHandler objects 48 // be nested cleanly, when using install_handler = true. 49 // Avoid the following pattern: 50 // ExceptionHandler *e = new ExceptionHandler(...); 51 // ExceptionHandler *f = new ExceptionHandler(...); 52 // delete e; 53 // This will put the exception filter stack into an inconsistent state. 54 55 #ifndef CLIENT_WINDOWS_HANDLER_EXCEPTION_HANDLER_H__ 56 #define CLIENT_WINDOWS_HANDLER_EXCEPTION_HANDLER_H__ 57 58 #include <stdlib.h> 59 #include <windows.h> 60 #include <dbghelp.h> 61 #include <rpc.h> 62 63 #pragma warning(push) 64 // Disable exception handler warnings. 65 #pragma warning(disable:4530) 66 67 #include <list> 68 #include <string> 69 #include <vector> 70 71 #include "client/windows/common/ipc_protocol.h" 72 #include "client/windows/crash_generation/crash_generation_client.h" 73 #include "common/scoped_ptr.h" 74 #include "google_breakpad/common/minidump_format.h" 75 76 namespace google_breakpad { 77 78 using std::vector; 79 using std::wstring; 80 81 // These entries store a list of memory regions that the client wants included 82 // in the minidump. 83 struct AppMemory { 84 ULONG64 ptr; 85 ULONG length; 86 87 bool operator==(const struct AppMemory& other) const { 88 return ptr == other.ptr; 89 } 90 91 bool operator==(const void* other) const { 92 return ptr == reinterpret_cast<ULONG64>(other); 93 } 94 }; 95 typedef std::list<AppMemory> AppMemoryList; 96 97 class ExceptionHandler { 98 public: 99 // A callback function to run before Breakpad performs any substantial 100 // processing of an exception. A FilterCallback is called before writing 101 // a minidump. context is the parameter supplied by the user as 102 // callback_context when the handler was created. exinfo points to the 103 // exception record, if any; assertion points to assertion information, 104 // if any. 105 // 106 // If a FilterCallback returns true, Breakpad will continue processing, 107 // attempting to write a minidump. If a FilterCallback returns false, 108 // Breakpad will immediately report the exception as unhandled without 109 // writing a minidump, allowing another handler the opportunity to handle it. 110 typedef bool (*FilterCallback)(void* context, EXCEPTION_POINTERS* exinfo, 111 MDRawAssertionInfo* assertion); 112 113 // A callback function to run after the minidump has been written. 114 // minidump_id is a unique id for the dump, so the minidump 115 // file is <dump_path>\<minidump_id>.dmp. context is the parameter supplied 116 // by the user as callback_context when the handler was created. exinfo 117 // points to the exception record, or NULL if no exception occurred. 118 // succeeded indicates whether a minidump file was successfully written. 119 // assertion points to information about an assertion if the handler was 120 // invoked by an assertion. 121 // 122 // If an exception occurred and the callback returns true, Breakpad will treat 123 // the exception as fully-handled, suppressing any other handlers from being 124 // notified of the exception. If the callback returns false, Breakpad will 125 // treat the exception as unhandled, and allow another handler to handle it. 126 // If there are no other handlers, Breakpad will report the exception to the 127 // system as unhandled, allowing a debugger or native crash dialog the 128 // opportunity to handle the exception. Most callback implementations 129 // should normally return the value of |succeeded|, or when they wish to 130 // not report an exception of handled, false. Callbacks will rarely want to 131 // return true directly (unless |succeeded| is true). 132 // 133 // For out-of-process dump generation, dump path and minidump ID will always 134 // be NULL. In case of out-of-process dump generation, the dump path and 135 // minidump id are controlled by the server process and are not communicated 136 // back to the crashing process. 137 typedef bool (*MinidumpCallback)(const wchar_t* dump_path, 138 const wchar_t* minidump_id, 139 void* context, 140 EXCEPTION_POINTERS* exinfo, 141 MDRawAssertionInfo* assertion, 142 bool succeeded); 143 144 // HandlerType specifies which types of handlers should be installed, if 145 // any. Use HANDLER_NONE for an ExceptionHandler that remains idle, 146 // without catching any failures on its own. This type of handler may 147 // still be triggered by calling WriteMinidump. Otherwise, use a 148 // combination of the other HANDLER_ values, or HANDLER_ALL to install 149 // all handlers. 150 enum HandlerType { 151 HANDLER_NONE = 0, 152 HANDLER_EXCEPTION = 1 << 0, // SetUnhandledExceptionFilter 153 HANDLER_INVALID_PARAMETER = 1 << 1, // _set_invalid_parameter_handler 154 HANDLER_PURECALL = 1 << 2, // _set_purecall_handler 155 HANDLER_ALL = HANDLER_EXCEPTION | 156 HANDLER_INVALID_PARAMETER | 157 HANDLER_PURECALL 158 }; 159 160 // Creates a new ExceptionHandler instance to handle writing minidumps. 161 // Before writing a minidump, the optional filter callback will be called. 162 // Its return value determines whether or not Breakpad should write a 163 // minidump. Minidump files will be written to dump_path, and the optional 164 // callback is called after writing the dump file, as described above. 165 // handler_types specifies the types of handlers that should be installed. 166 ExceptionHandler(const wstring& dump_path, 167 FilterCallback filter, 168 MinidumpCallback callback, 169 void* callback_context, 170 int handler_types); 171 172 // Creates a new ExceptionHandler instance that can attempt to perform 173 // out-of-process dump generation if pipe_name is not NULL. If pipe_name is 174 // NULL, or if out-of-process dump generation registration step fails, 175 // in-process dump generation will be used. This also allows specifying 176 // the dump type to generate. 177 ExceptionHandler(const wstring& dump_path, 178 FilterCallback filter, 179 MinidumpCallback callback, 180 void* callback_context, 181 int handler_types, 182 MINIDUMP_TYPE dump_type, 183 const wchar_t* pipe_name, 184 const CustomClientInfo* custom_info); 185 186 // As above, creates a new ExceptionHandler instance to perform 187 // out-of-process dump generation if the given pipe_handle is not NULL. 188 ExceptionHandler(const wstring& dump_path, 189 FilterCallback filter, 190 MinidumpCallback callback, 191 void* callback_context, 192 int handler_types, 193 MINIDUMP_TYPE dump_type, 194 HANDLE pipe_handle, 195 const CustomClientInfo* custom_info); 196 197 // ExceptionHandler that ENSURES out-of-process dump generation. Expects a 198 // crash generation client that is already registered with a crash generation 199 // server. Takes ownership of the passed-in crash_generation_client. 200 // 201 // Usage example: 202 // crash_generation_client = new CrashGenerationClient(..); 203 // if (crash_generation_client->Register()) { 204 // // Registration with the crash generation server succeeded. 205 // // Out-of-process dump generation is guaranteed. 206 // g_handler = new ExceptionHandler(.., crash_generation_client, ..); 207 // return true; 208 // } 209 ExceptionHandler(const wstring& dump_path, 210 FilterCallback filter, 211 MinidumpCallback callback, 212 void* callback_context, 213 int handler_types, 214 CrashGenerationClient* crash_generation_client); 215 216 ~ExceptionHandler(); 217 218 // Get and set the minidump path. dump_path()219 wstring dump_path() const { return dump_path_; } set_dump_path(const wstring & dump_path)220 void set_dump_path(const wstring& dump_path) { 221 dump_path_ = dump_path; 222 dump_path_c_ = dump_path_.c_str(); 223 UpdateNextID(); // Necessary to put dump_path_ in next_minidump_path_. 224 } 225 226 // Requests that a previously reported crash be uploaded. 227 bool RequestUpload(DWORD crash_id); 228 229 // Writes a minidump immediately. This can be used to capture the 230 // execution state independently of a crash. Returns true on success. 231 bool WriteMinidump(); 232 233 // Writes a minidump immediately, with the user-supplied exception 234 // information. 235 bool WriteMinidumpForException(EXCEPTION_POINTERS* exinfo); 236 237 // Convenience form of WriteMinidump which does not require an 238 // ExceptionHandler instance. 239 static bool WriteMinidump(const wstring& dump_path, 240 MinidumpCallback callback, void* callback_context, 241 MINIDUMP_TYPE dump_type = MiniDumpNormal); 242 243 // Write a minidump of |child| immediately. This can be used to 244 // capture the execution state of |child| independently of a crash. 245 // Pass a meaningful |child_blamed_thread| to make that thread in 246 // the child process the one from which a crash signature is 247 // extracted. 248 static bool WriteMinidumpForChild(HANDLE child, 249 DWORD child_blamed_thread, 250 const wstring& dump_path, 251 MinidumpCallback callback, 252 void* callback_context, 253 MINIDUMP_TYPE dump_type = MiniDumpNormal); 254 255 // Get the thread ID of the thread requesting the dump (either the exception 256 // thread or any other thread that called WriteMinidump directly). This 257 // may be useful if you want to include additional thread state in your 258 // dumps. get_requesting_thread_id()259 DWORD get_requesting_thread_id() const { return requesting_thread_id_; } 260 261 // Controls behavior of EXCEPTION_BREAKPOINT and EXCEPTION_SINGLE_STEP. get_handle_debug_exceptions()262 bool get_handle_debug_exceptions() const { return handle_debug_exceptions_; } set_handle_debug_exceptions(bool handle_debug_exceptions)263 void set_handle_debug_exceptions(bool handle_debug_exceptions) { 264 handle_debug_exceptions_ = handle_debug_exceptions; 265 } 266 267 // Controls behavior of EXCEPTION_INVALID_HANDLE. get_consume_invalid_handle_exceptions()268 bool get_consume_invalid_handle_exceptions() const { 269 return consume_invalid_handle_exceptions_; 270 } set_consume_invalid_handle_exceptions(bool consume_invalid_handle_exceptions)271 void set_consume_invalid_handle_exceptions( 272 bool consume_invalid_handle_exceptions) { 273 consume_invalid_handle_exceptions_ = consume_invalid_handle_exceptions; 274 } 275 276 // Returns whether out-of-process dump generation is used or not. IsOutOfProcess()277 bool IsOutOfProcess() const { return crash_generation_client_.get() != NULL; } 278 279 // Calling RegisterAppMemory(p, len) causes len bytes starting 280 // at address p to be copied to the minidump when a crash happens. 281 void RegisterAppMemory(void* ptr, size_t length); 282 void UnregisterAppMemory(void* ptr); 283 284 private: 285 friend class AutoExceptionHandler; 286 287 // Initializes the instance with given values. 288 void Initialize(const wstring& dump_path, 289 FilterCallback filter, 290 MinidumpCallback callback, 291 void* callback_context, 292 int handler_types, 293 MINIDUMP_TYPE dump_type, 294 const wchar_t* pipe_name, 295 HANDLE pipe_handle, 296 CrashGenerationClient* crash_generation_client, 297 const CustomClientInfo* custom_info); 298 299 // Function pointer type for MiniDumpWriteDump, which is looked up 300 // dynamically. 301 typedef BOOL (WINAPI *MiniDumpWriteDump_type)( 302 HANDLE hProcess, 303 DWORD dwPid, 304 HANDLE hFile, 305 MINIDUMP_TYPE DumpType, 306 CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, 307 CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, 308 CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam); 309 310 // Function pointer type for UuidCreate, which is looked up dynamically. 311 typedef RPC_STATUS (RPC_ENTRY *UuidCreate_type)(UUID* Uuid); 312 313 // Runs the main loop for the exception handler thread. 314 static DWORD WINAPI ExceptionHandlerThreadMain(void* lpParameter); 315 316 // Called on the exception thread when an unhandled exception occurs. 317 // Signals the exception handler thread to handle the exception. 318 static LONG WINAPI HandleException(EXCEPTION_POINTERS* exinfo); 319 320 #if _MSC_VER >= 1400 // MSVC 2005/8 321 // This function will be called by some CRT functions when they detect 322 // that they were passed an invalid parameter. Note that in _DEBUG builds, 323 // the CRT may display an assertion dialog before calling this function, 324 // and the function will not be called unless the assertion dialog is 325 // dismissed by clicking "Ignore." 326 static void HandleInvalidParameter(const wchar_t* expression, 327 const wchar_t* function, 328 const wchar_t* file, 329 unsigned int line, 330 uintptr_t reserved); 331 #endif // _MSC_VER >= 1400 332 333 // This function will be called by the CRT when a pure virtual 334 // function is called. 335 static void HandlePureVirtualCall(); 336 337 // This is called on the exception thread or on another thread that 338 // the user wishes to produce a dump from. It calls 339 // WriteMinidumpWithException on the handler thread, avoiding stack 340 // overflows and inconsistent dumps due to writing the dump from 341 // the exception thread. If the dump is requested as a result of an 342 // exception, exinfo contains exception information, otherwise, it 343 // is NULL. If the dump is requested as a result of an assertion 344 // (such as an invalid parameter being passed to a CRT function), 345 // assertion contains data about the assertion, otherwise, it is NULL. 346 bool WriteMinidumpOnHandlerThread(EXCEPTION_POINTERS* exinfo, 347 MDRawAssertionInfo* assertion); 348 349 // This function is called on the handler thread. It calls into 350 // WriteMinidumpWithExceptionForProcess() with a handle to the 351 // current process. requesting_thread_id is the ID of the thread 352 // that requested the dump. If the dump is requested as a result of 353 // an exception, exinfo contains exception information, otherwise, 354 // it is NULL. 355 bool WriteMinidumpWithException(DWORD requesting_thread_id, 356 EXCEPTION_POINTERS* exinfo, 357 MDRawAssertionInfo* assertion); 358 359 // This function is used as a callback when calling MinidumpWriteDump, 360 // in order to add additional memory regions to the dump. 361 static BOOL CALLBACK MinidumpWriteDumpCallback( 362 PVOID context, 363 const PMINIDUMP_CALLBACK_INPUT callback_input, 364 PMINIDUMP_CALLBACK_OUTPUT callback_output); 365 366 // This function does the actual writing of a minidump. It is 367 // called on the handler thread. requesting_thread_id is the ID of 368 // the thread that requested the dump, if that information is 369 // meaningful. If the dump is requested as a result of an 370 // exception, exinfo contains exception information, otherwise, it 371 // is NULL. process is the one that will be dumped. If 372 // requesting_thread_id is meaningful and should be added to the 373 // minidump, write_requester_stream is |true|. 374 bool WriteMinidumpWithExceptionForProcess(DWORD requesting_thread_id, 375 EXCEPTION_POINTERS* exinfo, 376 MDRawAssertionInfo* assertion, 377 HANDLE process, 378 bool write_requester_stream); 379 380 // Generates a new ID and stores it in next_minidump_id_, and stores the 381 // path of the next minidump to be written in next_minidump_path_. 382 void UpdateNextID(); 383 384 FilterCallback filter_; 385 MinidumpCallback callback_; 386 void* callback_context_; 387 388 scoped_ptr<CrashGenerationClient> crash_generation_client_; 389 390 // The directory in which a minidump will be written, set by the dump_path 391 // argument to the constructor, or set_dump_path. 392 wstring dump_path_; 393 394 // The basename of the next minidump to be written, without the extension. 395 wstring next_minidump_id_; 396 397 // The full pathname of the next minidump to be written, including the file 398 // extension. 399 wstring next_minidump_path_; 400 401 // Pointers to C-string representations of the above. These are set when 402 // the above wstring versions are set in order to avoid calling c_str during 403 // an exception, as c_str may attempt to allocate heap memory. These 404 // pointers are not owned by the ExceptionHandler object, but their lifetimes 405 // should be equivalent to the lifetimes of the associated wstring, provided 406 // that the wstrings are not altered. 407 const wchar_t* dump_path_c_; 408 const wchar_t* next_minidump_id_c_; 409 const wchar_t* next_minidump_path_c_; 410 411 HMODULE dbghelp_module_; 412 MiniDumpWriteDump_type minidump_write_dump_; 413 MINIDUMP_TYPE dump_type_; 414 415 HMODULE rpcrt4_module_; 416 UuidCreate_type uuid_create_; 417 418 // Tracks the handler types that were installed according to the 419 // handler_types constructor argument. 420 int handler_types_; 421 422 // When installed_handler_ is true, previous_filter_ is the unhandled 423 // exception filter that was set prior to installing ExceptionHandler as 424 // the unhandled exception filter and pointing it to |this|. NULL indicates 425 // that there is no previous unhandled exception filter. 426 LPTOP_LEVEL_EXCEPTION_FILTER previous_filter_; 427 428 #if _MSC_VER >= 1400 // MSVC 2005/8 429 // Beginning in VC 8, the CRT provides an invalid parameter handler that will 430 // be called when some CRT functions are passed invalid parameters. In 431 // earlier CRTs, the same conditions would cause unexpected behavior or 432 // crashes. 433 _invalid_parameter_handler previous_iph_; 434 #endif // _MSC_VER >= 1400 435 436 // The CRT allows you to override the default handler for pure 437 // virtual function calls. 438 _purecall_handler previous_pch_; 439 440 // The exception handler thread. 441 HANDLE handler_thread_; 442 443 // True if the exception handler is being destroyed. 444 // Starting with MSVC 2005, Visual C has stronger guarantees on volatile vars. 445 // It has release semantics on write and acquire semantics on reads. 446 // See the msdn documentation. 447 volatile bool is_shutdown_; 448 449 // The critical section enforcing the requirement that only one exception be 450 // handled by a handler at a time. 451 CRITICAL_SECTION handler_critical_section_; 452 453 // Semaphores used to move exception handling between the exception thread 454 // and the handler thread. handler_start_semaphore_ is signalled by the 455 // exception thread to wake up the handler thread when an exception occurs. 456 // handler_finish_semaphore_ is signalled by the handler thread to wake up 457 // the exception thread when handling is complete. 458 HANDLE handler_start_semaphore_; 459 HANDLE handler_finish_semaphore_; 460 461 // The next 2 fields contain data passed from the requesting thread to 462 // the handler thread. 463 464 // The thread ID of the thread requesting the dump (either the exception 465 // thread or any other thread that called WriteMinidump directly). 466 DWORD requesting_thread_id_; 467 468 // The exception info passed to the exception handler on the exception 469 // thread, if an exception occurred. NULL for user-requested dumps. 470 EXCEPTION_POINTERS* exception_info_; 471 472 // If the handler is invoked due to an assertion, this will contain a 473 // pointer to the assertion information. It is NULL at other times. 474 MDRawAssertionInfo* assertion_; 475 476 // The return value of the handler, passed from the handler thread back to 477 // the requesting thread. 478 bool handler_return_value_; 479 480 // If true, the handler will intercept EXCEPTION_BREAKPOINT and 481 // EXCEPTION_SINGLE_STEP exceptions. Leave this false (the default) 482 // to not interfere with debuggers. 483 bool handle_debug_exceptions_; 484 485 // If true, the handler will consume any EXCEPTION_INVALID_HANDLE exceptions. 486 // Leave this false (the default) to handle these exceptions as normal. 487 bool consume_invalid_handle_exceptions_; 488 489 // Callers can request additional memory regions to be included in 490 // the dump. 491 AppMemoryList app_memory_info_; 492 493 // A stack of ExceptionHandler objects that have installed unhandled 494 // exception filters. This vector is used by HandleException to determine 495 // which ExceptionHandler object to route an exception to. When an 496 // ExceptionHandler is created with install_handler true, it will append 497 // itself to this list. 498 static vector<ExceptionHandler*>* handler_stack_; 499 500 // The index of the ExceptionHandler in handler_stack_ that will handle the 501 // next exception. Note that 0 means the last entry in handler_stack_, 1 502 // means the next-to-last entry, and so on. This is used by HandleException 503 // to support multiple stacked Breakpad handlers. 504 static LONG handler_stack_index_; 505 506 // handler_stack_critical_section_ guards operations on handler_stack_ and 507 // handler_stack_index_. The critical section is initialized by the 508 // first instance of the class and destroyed by the last instance of it. 509 static CRITICAL_SECTION handler_stack_critical_section_; 510 511 // The number of instances of this class. 512 static volatile LONG instance_count_; 513 514 // disallow copy ctor and operator= 515 explicit ExceptionHandler(const ExceptionHandler&); 516 void operator=(const ExceptionHandler&); 517 }; 518 519 } // namespace google_breakpad 520 521 #pragma warning(pop) 522 523 #endif // CLIENT_WINDOWS_HANDLER_EXCEPTION_HANDLER_H__ 524