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