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
42namespace google_breakpad {
43
44static const int kWaitForHandlerThreadMs = 60000;
45static const int kExceptionHandlerThreadInitialStackSize = 64 * 1024;
46
47// As documented on MSDN, on failure SuspendThread returns (DWORD) -1
48static const DWORD kFailedToSuspendThread = static_cast<DWORD>(-1);
49
50// This is passed as the context to the MinidumpWriteDump callback.
51typedef struct {
52  AppMemoryList::const_iterator iter;
53  AppMemoryList::const_iterator end;
54} MinidumpCallbackContext;
55
56vector<ExceptionHandler*>* ExceptionHandler::handler_stack_ = NULL;
57LONG ExceptionHandler::handler_stack_index_ = 0;
58CRITICAL_SECTION ExceptionHandler::handler_stack_critical_section_;
59volatile LONG ExceptionHandler::instance_count_ = 0;
60
61ExceptionHandler::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
81ExceptionHandler::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
101ExceptionHandler::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
122ExceptionHandler::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
139void 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
295ExceptionHandler::~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
379bool ExceptionHandler::RequestUpload(DWORD crash_id) {
380  return crash_generation_client_->RequestUpload(crash_id);
381}
382
383// static
384DWORD 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.
419class 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
471LONG 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
540void 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
634void 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
698bool 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
735bool 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
750bool 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
765bool 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
774bool 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
829bool 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
867BOOL 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
905bool 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
1031void 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
1051void 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
1065void 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