exception_handler.cc
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 #ifdef HAVE_CONFIG_H 30 #include <config.h> // Must come first 31 #endif 32 33 #include <objbase.h> 34 35 #include <algorithm> 36 #include <cassert> 37 #include <cstdio> 38 39 #include "common/windows/string_utils-inl.h" 40 41 #include "client/windows/common/ipc_protocol.h" 42 #include "client/windows/handler/exception_handler.h" 43 #include "common/windows/guid_string.h" 44 45 namespace google_breakpad { 46 47 // This is passed as the context to the MinidumpWriteDump callback. 48 typedef struct { 49 AppMemoryList::const_iterator iter; 50 AppMemoryList::const_iterator end; 51 } MinidumpCallbackContext; 52 53 // This define is new to Windows 10. 54 #ifndef DBG_PRINTEXCEPTION_WIDE_C 55 #define DBG_PRINTEXCEPTION_WIDE_C ((DWORD)0x4001000A) 56 #endif 57 58 vector<ExceptionHandler*>* ExceptionHandler::handler_stack_ = NULL; 59 LONG ExceptionHandler::handler_stack_index_ = 0; 60 CRITICAL_SECTION ExceptionHandler::handler_stack_critical_section_; 61 volatile LONG ExceptionHandler::instance_count_ = 0; 62 63 ExceptionHandler::ExceptionHandler(const wstring& dump_path, 64 FilterCallback filter, 65 MinidumpCallback callback, 66 void* callback_context, 67 int handler_types, 68 MINIDUMP_TYPE dump_type, 69 const wchar_t* pipe_name, 70 const CustomClientInfo* custom_info) { 71 Initialize(dump_path, 72 filter, 73 callback, 74 callback_context, 75 handler_types, 76 dump_type, 77 pipe_name, 78 NULL, // pipe_handle 79 NULL, // crash_generation_client 80 custom_info); 81 } 82 83 ExceptionHandler::ExceptionHandler(const wstring& dump_path, 84 FilterCallback filter, 85 MinidumpCallback callback, 86 void* callback_context, 87 int handler_types, 88 MINIDUMP_TYPE dump_type, 89 HANDLE pipe_handle, 90 const CustomClientInfo* custom_info) { 91 Initialize(dump_path, 92 filter, 93 callback, 94 callback_context, 95 handler_types, 96 dump_type, 97 NULL, // pipe_name 98 pipe_handle, 99 NULL, // crash_generation_client 100 custom_info); 101 } 102 103 ExceptionHandler::ExceptionHandler( 104 const wstring& dump_path, 105 FilterCallback filter, 106 MinidumpCallback callback, 107 void* callback_context, 108 int handler_types, 109 CrashGenerationClient* crash_generation_client) { 110 // The dump_type, pipe_name and custom_info that are passed in to Initialize() 111 // are not used. The ones set in crash_generation_client are used instead. 112 Initialize(dump_path, 113 filter, 114 callback, 115 callback_context, 116 handler_types, 117 MiniDumpNormal, // dump_type - not used 118 NULL, // pipe_name - not used 119 NULL, // pipe_handle 120 crash_generation_client, 121 NULL); // custom_info - not used 122 } 123 124 ExceptionHandler::ExceptionHandler(const wstring& dump_path, 125 FilterCallback filter, 126 MinidumpCallback callback, 127 void* callback_context, 128 int handler_types) { 129 Initialize(dump_path, 130 filter, 131 callback, 132 callback_context, 133 handler_types, 134 MiniDumpNormal, 135 NULL, // pipe_name 136 NULL, // pipe_handle 137 NULL, // crash_generation_client 138 NULL); // custom_info 139 } 140 141 void ExceptionHandler::Initialize( 142 const wstring& dump_path, 143 FilterCallback filter, 144 MinidumpCallback callback, 145 void* callback_context, 146 int handler_types, 147 MINIDUMP_TYPE dump_type, 148 const wchar_t* pipe_name, 149 HANDLE pipe_handle, 150 CrashGenerationClient* crash_generation_client, 151 const CustomClientInfo* custom_info) { 152 LONG instance_count = InterlockedIncrement(&instance_count_); 153 filter_ = filter; 154 callback_ = callback; 155 callback_context_ = callback_context; 156 dump_path_c_ = NULL; 157 next_minidump_id_c_ = NULL; 158 next_minidump_path_c_ = NULL; 159 dbghelp_module_ = NULL; 160 minidump_write_dump_ = NULL; 161 dump_type_ = dump_type; 162 rpcrt4_module_ = NULL; 163 uuid_create_ = NULL; 164 handler_types_ = handler_types; 165 previous_filter_ = NULL; 166 #if _MSC_VER >= 1400 // MSVC 2005/8 167 previous_iph_ = NULL; 168 #endif // _MSC_VER >= 1400 169 previous_pch_ = NULL; 170 handler_thread_ = NULL; 171 is_shutdown_ = false; 172 handler_start_semaphore_ = NULL; 173 handler_finish_semaphore_ = NULL; 174 requesting_thread_id_ = 0; 175 exception_info_ = NULL; 176 assertion_ = NULL; 177 handler_return_value_ = false; 178 handle_debug_exceptions_ = false; 179 consume_invalid_handle_exceptions_ = false; 180 181 // Attempt to use out-of-process if user has specified a pipe or a 182 // crash generation client. 183 scoped_ptr<CrashGenerationClient> client; 184 if (crash_generation_client) { 185 client.reset(crash_generation_client); 186 } else if (pipe_name) { 187 client.reset( 188 new CrashGenerationClient(pipe_name, dump_type_, custom_info)); 189 } else if (pipe_handle) { 190 client.reset( 191 new CrashGenerationClient(pipe_handle, dump_type_, custom_info)); 192 } 193 194 if (client.get() != NULL) { 195 // If successful in registering with the monitoring process, 196 // there is no need to setup in-process crash generation. 197 if (client->Register()) { 198 crash_generation_client_.reset(client.release()); 199 } 200 } 201 202 if (!IsOutOfProcess()) { 203 // Either client did not ask for out-of-process crash generation 204 // or registration with the server process failed. In either case, 205 // setup to do in-process crash generation. 206 207 // Set synchronization primitives and the handler thread. Each 208 // ExceptionHandler object gets its own handler thread because that's the 209 // only way to reliably guarantee sufficient stack space in an exception, 210 // and it allows an easy way to get a snapshot of the requesting thread's 211 // context outside of an exception. 212 InitializeCriticalSection(&handler_critical_section_); 213 handler_start_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL); 214 assert(handler_start_semaphore_ != NULL); 215 216 handler_finish_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL); 217 assert(handler_finish_semaphore_ != NULL); 218 219 // Don't attempt to create the thread if we could not create the semaphores. 220 if (handler_finish_semaphore_ != NULL && handler_start_semaphore_ != NULL) { 221 DWORD thread_id; 222 const int kExceptionHandlerThreadInitialStackSize = 64 * 1024; 223 handler_thread_ = CreateThread(NULL, // lpThreadAttributes 224 kExceptionHandlerThreadInitialStackSize, 225 ExceptionHandlerThreadMain, 226 this, // lpParameter 227 0, // dwCreationFlags 228 &thread_id); 229 assert(handler_thread_ != NULL); 230 } 231 232 dbghelp_module_ = LoadLibrary(L"dbghelp.dll"); 233 if (dbghelp_module_) { 234 minidump_write_dump_ = reinterpret_cast<MiniDumpWriteDump_type>( 235 GetProcAddress(dbghelp_module_, "MiniDumpWriteDump")); 236 } 237 238 // Load this library dynamically to not affect existing projects. Most 239 // projects don't link against this directly, it's usually dynamically 240 // loaded by dependent code. 241 rpcrt4_module_ = LoadLibrary(L"rpcrt4.dll"); 242 if (rpcrt4_module_) { 243 uuid_create_ = reinterpret_cast<UuidCreate_type>( 244 GetProcAddress(rpcrt4_module_, "UuidCreate")); 245 } 246 247 // set_dump_path calls UpdateNextID. This sets up all of the path and id 248 // strings, and their equivalent c_str pointers. 249 set_dump_path(dump_path); 250 } 251 252 // Reserve one element for the instruction memory 253 AppMemory instruction_memory; 254 instruction_memory.ptr = NULL; 255 instruction_memory.length = 0; 256 app_memory_info_.push_back(instruction_memory); 257 258 // There is a race condition here. If the first instance has not yet 259 // initialized the critical section, the second (and later) instances may 260 // try to use uninitialized critical section object. The feature of multiple 261 // instances in one module is not used much, so leave it as is for now. 262 // One way to solve this in the current design (that is, keeping the static 263 // handler stack) is to use spin locks with volatile bools to synchronize 264 // the handler stack. This works only if the compiler guarantees to generate 265 // cache coherent code for volatile. 266 // TODO(munjal): Fix this in a better way by changing the design if possible. 267 268 // Lazy initialization of the handler_stack_critical_section_ 269 if (instance_count == 1) { 270 InitializeCriticalSection(&handler_stack_critical_section_); 271 } 272 273 if (handler_types != HANDLER_NONE) { 274 EnterCriticalSection(&handler_stack_critical_section_); 275 276 // The first time an ExceptionHandler that installs a handler is 277 // created, set up the handler stack. 278 if (!handler_stack_) { 279 handler_stack_ = new vector<ExceptionHandler*>(); 280 } 281 handler_stack_->push_back(this); 282 283 if (handler_types & HANDLER_EXCEPTION) 284 previous_filter_ = SetUnhandledExceptionFilter(HandleException); 285 286 #if _MSC_VER >= 1400 // MSVC 2005/8 287 if (handler_types & HANDLER_INVALID_PARAMETER) 288 previous_iph_ = _set_invalid_parameter_handler(HandleInvalidParameter); 289 #endif // _MSC_VER >= 1400 290 291 if (handler_types & HANDLER_PURECALL) 292 previous_pch_ = _set_purecall_handler(HandlePureVirtualCall); 293 294 LeaveCriticalSection(&handler_stack_critical_section_); 295 } 296 } 297 298 ExceptionHandler::~ExceptionHandler() { 299 if (dbghelp_module_) { 300 FreeLibrary(dbghelp_module_); 301 } 302 303 if (rpcrt4_module_) { 304 FreeLibrary(rpcrt4_module_); 305 } 306 307 if (handler_types_ != HANDLER_NONE) { 308 EnterCriticalSection(&handler_stack_critical_section_); 309 310 if (handler_types_ & HANDLER_EXCEPTION) 311 SetUnhandledExceptionFilter(previous_filter_); 312 313 #if _MSC_VER >= 1400 // MSVC 2005/8 314 if (handler_types_ & HANDLER_INVALID_PARAMETER) 315 _set_invalid_parameter_handler(previous_iph_); 316 #endif // _MSC_VER >= 1400 317 318 if (handler_types_ & HANDLER_PURECALL) 319 _set_purecall_handler(previous_pch_); 320 321 if (handler_stack_->back() == this) { 322 handler_stack_->pop_back(); 323 } else { 324 // TODO(mmentovai): use advapi32!ReportEvent to log the warning to the 325 // system's application event log. 326 fprintf(stderr, "warning: removing Breakpad handler out of order\n"); 327 vector<ExceptionHandler*>::iterator iterator = handler_stack_->begin(); 328 while (iterator != handler_stack_->end()) { 329 if (*iterator == this) { 330 iterator = handler_stack_->erase(iterator); 331 } else { 332 ++iterator; 333 } 334 } 335 } 336 337 if (handler_stack_->empty()) { 338 // When destroying the last ExceptionHandler that installed a handler, 339 // clean up the handler stack. 340 delete handler_stack_; 341 handler_stack_ = NULL; 342 } 343 344 LeaveCriticalSection(&handler_stack_critical_section_); 345 } 346 347 // Some of the objects were only initialized if out of process 348 // registration was not done. 349 if (!IsOutOfProcess()) { 350 #ifdef BREAKPAD_NO_TERMINATE_THREAD 351 // Clean up the handler thread and synchronization primitives. The handler 352 // thread is either waiting on the semaphore to handle a crash or it is 353 // handling a crash. Coming out of the wait is fast but wait more in the 354 // eventuality a crash is handled. This compilation option results in a 355 // deadlock if the exception handler is destroyed while executing code 356 // inside DllMain. 357 is_shutdown_ = true; 358 ReleaseSemaphore(handler_start_semaphore_, 1, NULL); 359 const int kWaitForHandlerThreadMs = 60000; 360 WaitForSingleObject(handler_thread_, kWaitForHandlerThreadMs); 361 #else 362 TerminateThread(handler_thread_, 1); 363 #endif // BREAKPAD_NO_TERMINATE_THREAD 364 365 CloseHandle(handler_thread_); 366 handler_thread_ = NULL; 367 DeleteCriticalSection(&handler_critical_section_); 368 CloseHandle(handler_start_semaphore_); 369 CloseHandle(handler_finish_semaphore_); 370 } 371 372 // There is a race condition in the code below: if this instance is 373 // deleting the static critical section and a new instance of the class 374 // is created, then there is a possibility that the critical section be 375 // initialized while the same critical section is being deleted. Given the 376 // usage pattern for the code, this race condition is unlikely to hit, but it 377 // is a race condition nonetheless. 378 if (InterlockedDecrement(&instance_count_) == 0) { 379 DeleteCriticalSection(&handler_stack_critical_section_); 380 } 381 } 382 383 bool ExceptionHandler::RequestUpload(DWORD crash_id) { 384 return crash_generation_client_->RequestUpload(crash_id); 385 } 386 387 // static 388 DWORD ExceptionHandler::ExceptionHandlerThreadMain(void* lpParameter) { 389 ExceptionHandler* self = reinterpret_cast<ExceptionHandler*>(lpParameter); 390 assert(self); 391 assert(self->handler_start_semaphore_ != NULL); 392 assert(self->handler_finish_semaphore_ != NULL); 393 394 for (;;) { 395 if (WaitForSingleObject(self->handler_start_semaphore_, INFINITE) == 396 WAIT_OBJECT_0) { 397 // Perform the requested action. 398 if (self->is_shutdown_) { 399 // The instance of the exception handler is being destroyed. 400 break; 401 } else { 402 self->handler_return_value_ = 403 self->WriteMinidumpWithException(self->requesting_thread_id_, 404 self->exception_info_, 405 self->assertion_); 406 } 407 408 // Allow the requesting thread to proceed. 409 ReleaseSemaphore(self->handler_finish_semaphore_, 1, NULL); 410 } 411 } 412 413 // This statement is not reached when the thread is unconditionally 414 // terminated by the ExceptionHandler destructor. 415 return 0; 416 } 417 418 // HandleException and HandleInvalidParameter must create an 419 // AutoExceptionHandler object to maintain static state and to determine which 420 // ExceptionHandler instance to use. The constructor locates the correct 421 // instance, and makes it available through get_handler(). The destructor 422 // restores the state in effect prior to allocating the AutoExceptionHandler. 423 class AutoExceptionHandler { 424 public: 425 AutoExceptionHandler() { 426 // Increment handler_stack_index_ so that if another Breakpad handler is 427 // registered using this same HandleException function, and it needs to be 428 // called while this handler is running (either because this handler 429 // declines to handle the exception, or an exception occurs during 430 // handling), HandleException will find the appropriate ExceptionHandler 431 // object in handler_stack_ to deliver the exception to. 432 // 433 // Because handler_stack_ is addressed in reverse (as |size - index|), 434 // preincrementing handler_stack_index_ avoids needing to subtract 1 from 435 // the argument to |at|. 436 // 437 // The index is maintained instead of popping elements off of the handler 438 // stack and pushing them at the end of this method. This avoids ruining 439 // the order of elements in the stack in the event that some other thread 440 // decides to manipulate the handler stack (such as creating a new 441 // ExceptionHandler object) while an exception is being handled. 442 EnterCriticalSection(&ExceptionHandler::handler_stack_critical_section_); 443 handler_ = ExceptionHandler::handler_stack_->at( 444 ExceptionHandler::handler_stack_->size() - 445 ++ExceptionHandler::handler_stack_index_); 446 447 // In case another exception occurs while this handler is doing its thing, 448 // it should be delivered to the previous filter. 449 SetUnhandledExceptionFilter(handler_->previous_filter_); 450 #if _MSC_VER >= 1400 // MSVC 2005/8 451 _set_invalid_parameter_handler(handler_->previous_iph_); 452 #endif // _MSC_VER >= 1400 453 _set_purecall_handler(handler_->previous_pch_); 454 } 455 456 ~AutoExceptionHandler() { 457 // Put things back the way they were before entering this handler. 458 SetUnhandledExceptionFilter(ExceptionHandler::HandleException); 459 #if _MSC_VER >= 1400 // MSVC 2005/8 460 _set_invalid_parameter_handler(ExceptionHandler::HandleInvalidParameter); 461 #endif // _MSC_VER >= 1400 462 _set_purecall_handler(ExceptionHandler::HandlePureVirtualCall); 463 464 --ExceptionHandler::handler_stack_index_; 465 LeaveCriticalSection(&ExceptionHandler::handler_stack_critical_section_); 466 } 467 468 ExceptionHandler* get_handler() const { return handler_; } 469 470 private: 471 ExceptionHandler* handler_; 472 }; 473 474 // static 475 LONG ExceptionHandler::HandleException(EXCEPTION_POINTERS* exinfo) { 476 AutoExceptionHandler auto_exception_handler; 477 ExceptionHandler* current_handler = auto_exception_handler.get_handler(); 478 479 // Ignore EXCEPTION_BREAKPOINT and EXCEPTION_SINGLE_STEP exceptions. This 480 // logic will short-circuit before calling WriteMinidumpOnHandlerThread, 481 // allowing something else to handle the breakpoint without incurring the 482 // overhead transitioning to and from the handler thread. This behavior 483 // can be overridden by calling ExceptionHandler::set_handle_debug_exceptions. 484 DWORD code = exinfo->ExceptionRecord->ExceptionCode; 485 LONG action; 486 bool is_debug_exception = (code == EXCEPTION_BREAKPOINT) || 487 (code == EXCEPTION_SINGLE_STEP) || 488 (code == DBG_PRINTEXCEPTION_C) || 489 (code == DBG_PRINTEXCEPTION_WIDE_C); 490 491 if (code == EXCEPTION_INVALID_HANDLE && 492 current_handler->consume_invalid_handle_exceptions_) { 493 return EXCEPTION_CONTINUE_EXECUTION; 494 } 495 496 bool success = false; 497 498 if (!is_debug_exception || 499 current_handler->get_handle_debug_exceptions()) { 500 // If out-of-proc crash handler client is available, we have to use that 501 // to generate dump and we cannot fall back on in-proc dump generation 502 // because we never prepared for an in-proc dump generation 503 504 // In case of out-of-process dump generation, directly call 505 // WriteMinidumpWithException since there is no separate thread running. 506 if (current_handler->IsOutOfProcess()) { 507 success = current_handler->WriteMinidumpWithException( 508 GetCurrentThreadId(), 509 exinfo, 510 NULL); 511 } else { 512 success = current_handler->WriteMinidumpOnHandlerThread(exinfo, NULL); 513 } 514 } 515 516 // The handler fully handled the exception. Returning 517 // EXCEPTION_EXECUTE_HANDLER indicates this to the system, and usually 518 // results in the application being terminated. 519 // 520 // Note: If the application was launched from within the Cygwin 521 // environment, returning EXCEPTION_EXECUTE_HANDLER seems to cause the 522 // application to be restarted. 523 if (success) { 524 action = EXCEPTION_EXECUTE_HANDLER; 525 } else { 526 // There was an exception, it was a breakpoint or something else ignored 527 // above, or it was passed to the handler, which decided not to handle it. 528 // This could be because the filter callback didn't want it, because 529 // minidump writing failed for some reason, or because the post-minidump 530 // callback function indicated failure. Give the previous handler a 531 // chance to do something with the exception. If there is no previous 532 // handler, return EXCEPTION_CONTINUE_SEARCH, which will allow a debugger 533 // or native "crashed" dialog to handle the exception. 534 if (current_handler->previous_filter_) { 535 action = current_handler->previous_filter_(exinfo); 536 } else { 537 action = EXCEPTION_CONTINUE_SEARCH; 538 } 539 } 540 541 return action; 542 } 543 544 #if _MSC_VER >= 1400 // MSVC 2005/8 545 // static 546 void ExceptionHandler::HandleInvalidParameter(const wchar_t* expression, 547 const wchar_t* function, 548 const wchar_t* file, 549 unsigned int line, 550 uintptr_t reserved) { 551 // This is an invalid parameter, not an exception. It's safe to play with 552 // sprintf here. 553 AutoExceptionHandler auto_exception_handler; 554 ExceptionHandler* current_handler = auto_exception_handler.get_handler(); 555 556 MDRawAssertionInfo assertion; 557 memset(&assertion, 0, sizeof(assertion)); 558 _snwprintf_s(reinterpret_cast<wchar_t*>(assertion.expression), 559 sizeof(assertion.expression) / sizeof(assertion.expression[0]), 560 _TRUNCATE, L"%s", expression); 561 _snwprintf_s(reinterpret_cast<wchar_t*>(assertion.function), 562 sizeof(assertion.function) / sizeof(assertion.function[0]), 563 _TRUNCATE, L"%s", function); 564 _snwprintf_s(reinterpret_cast<wchar_t*>(assertion.file), 565 sizeof(assertion.file) / sizeof(assertion.file[0]), 566 _TRUNCATE, L"%s", file); 567 assertion.line = line; 568 assertion.type = MD_ASSERTION_INFO_TYPE_INVALID_PARAMETER; 569 570 // Make up an exception record for the current thread and CPU context 571 // to make it possible for the crash processor to classify these 572 // as do regular crashes, and to make it humane for developers to 573 // analyze them. 574 EXCEPTION_RECORD exception_record = {}; 575 CONTEXT exception_context = {}; 576 EXCEPTION_POINTERS exception_ptrs = { &exception_record, &exception_context }; 577 578 ::RtlCaptureContext(&exception_context); 579 580 exception_record.ExceptionCode = STATUS_INVALID_PARAMETER; 581 582 // We store pointers to the the expression and function strings, 583 // and the line as exception parameters to make them easy to 584 // access by the developer on the far side. 585 exception_record.NumberParameters = 3; 586 exception_record.ExceptionInformation[0] = 587 reinterpret_cast<ULONG_PTR>(&assertion.expression); 588 exception_record.ExceptionInformation[1] = 589 reinterpret_cast<ULONG_PTR>(&assertion.file); 590 exception_record.ExceptionInformation[2] = assertion.line; 591 592 bool success = false; 593 // In case of out-of-process dump generation, directly call 594 // WriteMinidumpWithException since there is no separate thread running. 595 if (current_handler->IsOutOfProcess()) { 596 success = current_handler->WriteMinidumpWithException( 597 GetCurrentThreadId(), 598 &exception_ptrs, 599 &assertion); 600 } else { 601 success = current_handler->WriteMinidumpOnHandlerThread(&exception_ptrs, 602 &assertion); 603 } 604 605 if (!success) { 606 if (current_handler->previous_iph_) { 607 // The handler didn't fully handle the exception. Give it to the 608 // previous invalid parameter handler. 609 current_handler->previous_iph_(expression, 610 function, 611 file, 612 line, 613 reserved); 614 } else { 615 // If there's no previous handler, pass the exception back in to the 616 // invalid parameter handler's core. That's the routine that called this 617 // function, but now, since this function is no longer registered (and in 618 // fact, no function at all is registered), this will result in the 619 // default code path being taken: _CRT_DEBUGGER_HOOK and _invoke_watson. 620 // Use _invalid_parameter where it exists (in _DEBUG builds) as it passes 621 // more information through. In non-debug builds, it is not available, 622 // so fall back to using _invalid_parameter_noinfo. See invarg.c in the 623 // CRT source. 624 #ifdef _DEBUG 625 _invalid_parameter(expression, function, file, line, reserved); 626 #else // _DEBUG 627 _invalid_parameter_noinfo(); 628 #endif // _DEBUG 629 } 630 } 631 632 // The handler either took care of the invalid parameter problem itself, 633 // or passed it on to another handler. "Swallow" it by exiting, paralleling 634 // the behavior of "swallowing" exceptions. 635 exit(0); 636 } 637 #endif // _MSC_VER >= 1400 638 639 // static 640 void ExceptionHandler::HandlePureVirtualCall() { 641 // This is an pure virtual function call, not an exception. It's safe to 642 // play with sprintf here. 643 AutoExceptionHandler auto_exception_handler; 644 ExceptionHandler* current_handler = auto_exception_handler.get_handler(); 645 646 MDRawAssertionInfo assertion; 647 memset(&assertion, 0, sizeof(assertion)); 648 assertion.type = MD_ASSERTION_INFO_TYPE_PURE_VIRTUAL_CALL; 649 650 // Make up an exception record for the current thread and CPU context 651 // to make it possible for the crash processor to classify these 652 // as do regular crashes, and to make it humane for developers to 653 // analyze them. 654 EXCEPTION_RECORD exception_record = {}; 655 CONTEXT exception_context = {}; 656 EXCEPTION_POINTERS exception_ptrs = { &exception_record, &exception_context }; 657 658 ::RtlCaptureContext(&exception_context); 659 660 exception_record.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION; 661 662 // We store pointers to the the expression and function strings, 663 // and the line as exception parameters to make them easy to 664 // access by the developer on the far side. 665 exception_record.NumberParameters = 3; 666 exception_record.ExceptionInformation[0] = 667 reinterpret_cast<ULONG_PTR>(&assertion.expression); 668 exception_record.ExceptionInformation[1] = 669 reinterpret_cast<ULONG_PTR>(&assertion.file); 670 exception_record.ExceptionInformation[2] = assertion.line; 671 672 bool success = false; 673 // In case of out-of-process dump generation, directly call 674 // WriteMinidumpWithException since there is no separate thread running. 675 676 if (current_handler->IsOutOfProcess()) { 677 success = current_handler->WriteMinidumpWithException( 678 GetCurrentThreadId(), 679 &exception_ptrs, 680 &assertion); 681 } else { 682 success = current_handler->WriteMinidumpOnHandlerThread(&exception_ptrs, 683 &assertion); 684 } 685 686 if (!success) { 687 if (current_handler->previous_pch_) { 688 // The handler didn't fully handle the exception. Give it to the 689 // previous purecall handler. 690 current_handler->previous_pch_(); 691 } else { 692 // If there's no previous handler, return and let _purecall handle it. 693 // This will just put up an assertion dialog. 694 return; 695 } 696 } 697 698 // The handler either took care of the invalid parameter problem itself, 699 // or passed it on to another handler. "Swallow" it by exiting, paralleling 700 // the behavior of "swallowing" exceptions. 701 exit(0); 702 } 703 704 bool ExceptionHandler::WriteMinidumpOnHandlerThread( 705 EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion) { 706 EnterCriticalSection(&handler_critical_section_); 707 708 // There isn't much we can do if the handler thread 709 // was not successfully created. 710 if (handler_thread_ == NULL) { 711 LeaveCriticalSection(&handler_critical_section_); 712 return false; 713 } 714 715 // The handler thread should only be created when the semaphores are valid. 716 assert(handler_start_semaphore_ != NULL); 717 assert(handler_finish_semaphore_ != NULL); 718 719 // Set up data to be passed in to the handler thread. 720 requesting_thread_id_ = GetCurrentThreadId(); 721 exception_info_ = exinfo; 722 assertion_ = assertion; 723 724 // This causes the handler thread to call WriteMinidumpWithException. 725 ReleaseSemaphore(handler_start_semaphore_, 1, NULL); 726 727 // Wait until WriteMinidumpWithException is done and collect its return value. 728 WaitForSingleObject(handler_finish_semaphore_, INFINITE); 729 bool status = handler_return_value_; 730 731 // Clean up. 732 requesting_thread_id_ = 0; 733 exception_info_ = NULL; 734 assertion_ = NULL; 735 736 LeaveCriticalSection(&handler_critical_section_); 737 738 return status; 739 } 740 741 bool ExceptionHandler::WriteMinidump() { 742 // Make up an exception record for the current thread and CPU context 743 // to make it possible for the crash processor to classify these 744 // as do regular crashes, and to make it humane for developers to 745 // analyze them. 746 EXCEPTION_RECORD exception_record = {}; 747 CONTEXT exception_context = {}; 748 EXCEPTION_POINTERS exception_ptrs = { &exception_record, &exception_context }; 749 750 ::RtlCaptureContext(&exception_context); 751 exception_record.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION; 752 753 return WriteMinidumpForException(&exception_ptrs); 754 } 755 756 bool ExceptionHandler::WriteMinidumpForException(EXCEPTION_POINTERS* exinfo) { 757 // In case of out-of-process dump generation, directly call 758 // WriteMinidumpWithException since there is no separate thread running. 759 if (IsOutOfProcess()) { 760 return WriteMinidumpWithException(GetCurrentThreadId(), 761 exinfo, 762 NULL); 763 } 764 765 bool success = WriteMinidumpOnHandlerThread(exinfo, NULL); 766 UpdateNextID(); 767 return success; 768 } 769 770 // static 771 bool ExceptionHandler::WriteMinidump(const wstring& dump_path, 772 MinidumpCallback callback, 773 void* callback_context, 774 MINIDUMP_TYPE dump_type) { 775 ExceptionHandler handler(dump_path, NULL, callback, callback_context, 776 HANDLER_NONE, dump_type, (HANDLE)NULL, NULL); 777 return handler.WriteMinidump(); 778 } 779 780 // static 781 bool ExceptionHandler::WriteMinidumpForChild(HANDLE child, 782 DWORD child_blamed_thread, 783 const wstring& dump_path, 784 MinidumpCallback callback, 785 void* callback_context, 786 MINIDUMP_TYPE dump_type) { 787 EXCEPTION_RECORD ex; 788 CONTEXT ctx; 789 EXCEPTION_POINTERS exinfo = { NULL, NULL }; 790 // As documented on MSDN, on failure SuspendThread returns (DWORD) -1 791 const DWORD kFailedToSuspendThread = static_cast<DWORD>(-1); 792 DWORD last_suspend_count = kFailedToSuspendThread; 793 HANDLE child_thread_handle = OpenThread(THREAD_GET_CONTEXT | 794 THREAD_QUERY_INFORMATION | 795 THREAD_SUSPEND_RESUME, 796 FALSE, 797 child_blamed_thread); 798 // This thread may have died already, so not opening the handle is a 799 // non-fatal error. 800 if (child_thread_handle != NULL) { 801 last_suspend_count = SuspendThread(child_thread_handle); 802 if (last_suspend_count != kFailedToSuspendThread) { 803 ctx.ContextFlags = CONTEXT_ALL; 804 if (GetThreadContext(child_thread_handle, &ctx)) { 805 memset(&ex, 0, sizeof(ex)); 806 ex.ExceptionCode = EXCEPTION_BREAKPOINT; 807 #if defined(_M_IX86) 808 ex.ExceptionAddress = reinterpret_cast<PVOID>(ctx.Eip); 809 #elif defined(_M_X64) 810 ex.ExceptionAddress = reinterpret_cast<PVOID>(ctx.Rip); 811 #endif 812 exinfo.ExceptionRecord = &ex; 813 exinfo.ContextRecord = &ctx; 814 } 815 } 816 } 817 818 ExceptionHandler handler(dump_path, NULL, callback, callback_context, 819 HANDLER_NONE, dump_type, (HANDLE)NULL, NULL); 820 bool success = handler.WriteMinidumpWithExceptionForProcess( 821 child_blamed_thread, 822 exinfo.ExceptionRecord ? &exinfo : NULL, 823 NULL, child, false); 824 825 if (last_suspend_count != kFailedToSuspendThread) { 826 ResumeThread(child_thread_handle); 827 } 828 829 CloseHandle(child_thread_handle); 830 831 if (callback) { 832 success = callback(handler.dump_path_c_, handler.next_minidump_id_c_, 833 callback_context, NULL, NULL, success); 834 } 835 836 return success; 837 } 838 839 bool ExceptionHandler::WriteMinidumpWithException( 840 DWORD requesting_thread_id, 841 EXCEPTION_POINTERS* exinfo, 842 MDRawAssertionInfo* assertion) { 843 // Give user code a chance to approve or prevent writing a minidump. If the 844 // filter returns false, don't handle the exception at all. If this method 845 // was called as a result of an exception, returning false will cause 846 // HandleException to call any previous handler or return 847 // EXCEPTION_CONTINUE_SEARCH on the exception thread, allowing it to appear 848 // as though this handler were not present at all. 849 if (filter_ && !filter_(callback_context_, exinfo, assertion)) { 850 return false; 851 } 852 853 bool success = false; 854 if (IsOutOfProcess()) { 855 success = crash_generation_client_->RequestDump(exinfo, assertion); 856 } else { 857 success = WriteMinidumpWithExceptionForProcess(requesting_thread_id, 858 exinfo, 859 assertion, 860 GetCurrentProcess(), 861 true); 862 } 863 864 if (callback_) { 865 // TODO(munjal): In case of out-of-process dump generation, both 866 // dump_path_c_ and next_minidump_id_ will be NULL. For out-of-process 867 // scenario, the server process ends up creating the dump path and dump 868 // id so they are not known to the client. 869 success = callback_(dump_path_c_, next_minidump_id_c_, callback_context_, 870 exinfo, assertion, success); 871 } 872 873 return success; 874 } 875 876 // static 877 BOOL CALLBACK ExceptionHandler::MinidumpWriteDumpCallback( 878 PVOID context, 879 const PMINIDUMP_CALLBACK_INPUT callback_input, 880 PMINIDUMP_CALLBACK_OUTPUT callback_output) { 881 switch (callback_input->CallbackType) { 882 case MemoryCallback: { 883 MinidumpCallbackContext* callback_context = 884 reinterpret_cast<MinidumpCallbackContext*>(context); 885 if (callback_context->iter == callback_context->end) 886 return FALSE; 887 888 // Include the specified memory region. 889 callback_output->MemoryBase = callback_context->iter->ptr; 890 callback_output->MemorySize = callback_context->iter->length; 891 callback_context->iter++; 892 return TRUE; 893 } 894 895 // Include all modules. 896 case IncludeModuleCallback: 897 case ModuleCallback: 898 return TRUE; 899 900 // Include all threads. 901 case IncludeThreadCallback: 902 case ThreadCallback: 903 return TRUE; 904 905 // Stop receiving cancel callbacks. 906 case CancelCallback: 907 callback_output->CheckCancel = FALSE; 908 callback_output->Cancel = FALSE; 909 return TRUE; 910 } 911 // Ignore other callback types. 912 return FALSE; 913 } 914 915 bool ExceptionHandler::WriteMinidumpWithExceptionForProcess( 916 DWORD requesting_thread_id, 917 EXCEPTION_POINTERS* exinfo, 918 MDRawAssertionInfo* assertion, 919 HANDLE process, 920 bool write_requester_stream) { 921 bool success = false; 922 if (minidump_write_dump_) { 923 HANDLE dump_file = CreateFile(next_minidump_path_c_, 924 GENERIC_WRITE, 925 0, // no sharing 926 NULL, 927 CREATE_NEW, // fail if exists 928 FILE_ATTRIBUTE_NORMAL, 929 NULL); 930 if (dump_file != INVALID_HANDLE_VALUE) { 931 MINIDUMP_EXCEPTION_INFORMATION except_info; 932 except_info.ThreadId = requesting_thread_id; 933 except_info.ExceptionPointers = exinfo; 934 except_info.ClientPointers = FALSE; 935 936 // Leave room in user_stream_array for possible breakpad and 937 // assertion info streams. 938 MINIDUMP_USER_STREAM user_stream_array[2]; 939 MINIDUMP_USER_STREAM_INFORMATION user_streams; 940 user_streams.UserStreamCount = 0; 941 user_streams.UserStreamArray = user_stream_array; 942 943 if (write_requester_stream) { 944 // Add an MDRawBreakpadInfo stream to the minidump, to provide 945 // additional information about the exception handler to the Breakpad 946 // processor. The information will help the processor determine which 947 // threads are relevant. The Breakpad processor does not require this 948 // information but can function better with Breakpad-generated dumps 949 // when it is present. The native debugger is not harmed by the 950 // presence of this information. 951 MDRawBreakpadInfo breakpad_info; 952 breakpad_info.validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID | 953 MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID; 954 breakpad_info.dump_thread_id = GetCurrentThreadId(); 955 breakpad_info.requesting_thread_id = requesting_thread_id; 956 957 int index = user_streams.UserStreamCount; 958 user_stream_array[index].Type = MD_BREAKPAD_INFO_STREAM; 959 user_stream_array[index].BufferSize = sizeof(breakpad_info); 960 user_stream_array[index].Buffer = &breakpad_info; 961 ++user_streams.UserStreamCount; 962 } 963 964 if (assertion) { 965 int index = user_streams.UserStreamCount; 966 user_stream_array[index].Type = MD_ASSERTION_INFO_STREAM; 967 user_stream_array[index].BufferSize = sizeof(MDRawAssertionInfo); 968 user_stream_array[index].Buffer = assertion; 969 ++user_streams.UserStreamCount; 970 } 971 972 // Older versions of DbgHelp.dll don't correctly put the memory around 973 // the faulting instruction pointer into the minidump. This 974 // callback will ensure that it gets included. 975 if (exinfo) { 976 // Find a memory region of 256 bytes centered on the 977 // faulting instruction pointer. 978 const ULONG64 instruction_pointer = 979 #if defined(_M_IX86) 980 exinfo->ContextRecord->Eip; 981 #elif defined(_M_AMD64) 982 exinfo->ContextRecord->Rip; 983 #elif defined(_M_ARM64) 984 exinfo->ContextRecord->Pc; 985 #else 986 #error Unsupported platform 987 #endif 988 989 MEMORY_BASIC_INFORMATION info; 990 if (VirtualQueryEx(process, 991 reinterpret_cast<LPCVOID>(instruction_pointer), 992 &info, 993 sizeof(MEMORY_BASIC_INFORMATION)) != 0 && 994 info.State == MEM_COMMIT) { 995 // Attempt to get 128 bytes before and after the instruction 996 // pointer, but settle for whatever's available up to the 997 // boundaries of the memory region. 998 const ULONG64 kIPMemorySize = 256; 999 ULONG64 base = 1000 (std::max)(reinterpret_cast<ULONG64>(info.BaseAddress), 1001 instruction_pointer - (kIPMemorySize / 2)); 1002 ULONG64 end_of_range = 1003 (std::min)(instruction_pointer + (kIPMemorySize / 2), 1004 reinterpret_cast<ULONG64>(info.BaseAddress) 1005 + info.RegionSize); 1006 ULONG size = static_cast<ULONG>(end_of_range - base); 1007 1008 AppMemory& elt = app_memory_info_.front(); 1009 elt.ptr = base; 1010 elt.length = size; 1011 } 1012 } 1013 1014 MinidumpCallbackContext context; 1015 context.iter = app_memory_info_.begin(); 1016 context.end = app_memory_info_.end(); 1017 1018 // Skip the reserved element if there was no instruction memory 1019 if (context.iter->ptr == 0) { 1020 context.iter++; 1021 } 1022 1023 MINIDUMP_CALLBACK_INFORMATION callback; 1024 callback.CallbackRoutine = MinidumpWriteDumpCallback; 1025 callback.CallbackParam = reinterpret_cast<void*>(&context); 1026 1027 // The explicit comparison to TRUE avoids a warning (C4800). 1028 success = (minidump_write_dump_(process, 1029 GetProcessId(process), 1030 dump_file, 1031 dump_type_, 1032 exinfo ? &except_info : NULL, 1033 &user_streams, 1034 &callback) == TRUE); 1035 1036 CloseHandle(dump_file); 1037 } 1038 } 1039 1040 return success; 1041 } 1042 1043 void ExceptionHandler::UpdateNextID() { 1044 assert(uuid_create_); 1045 UUID id = {0}; 1046 if (uuid_create_) { 1047 uuid_create_(&id); 1048 } 1049 next_minidump_id_ = GUIDString::GUIDToWString(&id); 1050 next_minidump_id_c_ = next_minidump_id_.c_str(); 1051 1052 wchar_t minidump_path[MAX_PATH]; 1053 swprintf(minidump_path, MAX_PATH, L"%s\\%s.dmp", 1054 dump_path_c_, next_minidump_id_c_); 1055 1056 // remove when VC++7.1 is no longer supported 1057 minidump_path[MAX_PATH - 1] = L'\0'; 1058 1059 next_minidump_path_ = minidump_path; 1060 next_minidump_path_c_ = next_minidump_path_.c_str(); 1061 } 1062 1063 void ExceptionHandler::RegisterAppMemory(void* ptr, size_t length) { 1064 AppMemoryList::iterator iter = 1065 std::find(app_memory_info_.begin(), app_memory_info_.end(), ptr); 1066 if (iter != app_memory_info_.end()) { 1067 // Don't allow registering the same pointer twice. 1068 return; 1069 } 1070 1071 AppMemory app_memory; 1072 app_memory.ptr = reinterpret_cast<ULONG64>(ptr); 1073 app_memory.length = static_cast<ULONG>(length); 1074 app_memory_info_.push_back(app_memory); 1075 } 1076 1077 void ExceptionHandler::UnregisterAppMemory(void* ptr) { 1078 AppMemoryList::iterator iter = 1079 std::find(app_memory_info_.begin(), app_memory_info_.end(), ptr); 1080 if (iter != app_memory_info_.end()) { 1081 app_memory_info_.erase(iter); 1082 } 1083 } 1084 1085 } // namespace google_breakpad