Home | History | Annotate | Download | only in chrome_frame
      1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 //
      5 // A class to make it easy to tag exception propagation boundaries and
      6 // get crash reports of exceptions that pass over same.
      7 #include "chrome_frame/exception_barrier.h"
      8 
      9 #include "chrome_frame/crash_reporting/vectored_handler-impl.h"
     10 #include "chrome_frame/crash_reporting/crash_report.h"
     11 
     12 enum {
     13   // Flag set by exception handling machinery when unwinding
     14   EH_UNWINDING = 0x00000002
     15 };
     16 
     17 bool ExceptionBarrierConfig::s_enabled_ = false;
     18 
     19 ExceptionBarrierCustomHandler::CustomExceptionHandler
     20     ExceptionBarrierCustomHandler::s_custom_handler_ = NULL;
     21 
     22 // This function must be extern "C" to match up with the SAFESEH
     23 // declaration in our corresponding ASM file
     24 extern "C" EXCEPTION_DISPOSITION __cdecl
     25 ExceptionBarrierHandler(struct _EXCEPTION_RECORD* exception_record,
     26                         void* establisher_frame,
     27                         struct _CONTEXT* context,
     28                         void* reserved) {
     29   // When the exception is really propagating through us, we'd like to be
     30   // called before the state of the program has been modified by the stack
     31   // unwinding. In the absence of an exception handler, the unhandled
     32   // exception filter gets called between the first chance and the second
     33   // chance exceptions, so Windows pops either the JIT debugger or WER UI.
     34   // This is not desirable in most of the cases.
     35   EXCEPTION_POINTERS ptrs = { exception_record, context };
     36 
     37   if (ExceptionBarrierConfig::enabled() &&
     38       IS_DISPATCHING(exception_record->ExceptionFlags)) {
     39     WriteMinidumpForException(&ptrs);
     40   }
     41 
     42   return ExceptionContinueSearch;
     43 }
     44 
     45 extern "C" EXCEPTION_DISPOSITION __cdecl
     46 ExceptionBarrierReportOnlyModuleHandler(
     47     struct _EXCEPTION_RECORD* exception_record,
     48     void*  establisher_frame,
     49     struct _CONTEXT* context,
     50     void*  reserved) {
     51   EXCEPTION_POINTERS ptrs = { exception_record, context };
     52 
     53   if (ExceptionBarrierConfig::enabled() &&
     54       IS_DISPATCHING(exception_record->ExceptionFlags)) {
     55     CrashHandlerTraits traits;
     56     traits.Init(0, 0, &WriteMinidumpForException);
     57     if (traits.IsOurModule(exception_record->ExceptionAddress)) {
     58       traits.WriteDump(&ptrs);
     59     }
     60   }
     61 
     62   return ExceptionContinueSearch;
     63 }
     64 
     65 extern "C" EXCEPTION_DISPOSITION __cdecl
     66 ExceptionBarrierCallCustomHandler(struct _EXCEPTION_RECORD* exception_record,
     67                                   void* establisher_frame,
     68                                   struct _CONTEXT* context,
     69                                   void* reserved) {
     70   if (ExceptionBarrierConfig::enabled() &&
     71       IS_DISPATCHING(exception_record->ExceptionFlags)) {
     72     ExceptionBarrierCustomHandler::CustomExceptionHandler handler =
     73         ExceptionBarrierCustomHandler::custom_handler();
     74     if (handler) {
     75       EXCEPTION_POINTERS ptrs = { exception_record, context };
     76       handler(&ptrs);
     77     }
     78   }
     79 
     80   return ExceptionContinueSearch;
     81 }
     82