| OLD | NEW |
| (Empty) |
| 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 // | |
| 8 // An exception barrier is used to report exceptions that pass through | |
| 9 // a boundary where exceptions shouldn't pass, such as e.g. COM interface | |
| 10 // boundaries. | |
| 11 // This is handy for any kind of plugin code, where if the exception passes | |
| 12 // through unhindered, it'll either be swallowed by an SEH exception handler | |
| 13 // above us on the stack, or be reported as an unhandled exception for | |
| 14 // the application hosting the plugin code. | |
| 15 // | |
| 16 // IMPORTANT NOTE: This class has crash_reporting disabled by default. To | |
| 17 // enable crash reporting call: | |
| 18 // | |
| 19 // @code | |
| 20 // ExceptionBarrierBase::set_crash_handling(true) | |
| 21 // @endcode | |
| 22 // | |
| 23 // somewhere in your initialization code. | |
| 24 // | |
| 25 // Then, to use this class, simply instantiate an ExceptionBarrier just inside | |
| 26 // the code boundary, like this: | |
| 27 // @code | |
| 28 // HRESULT SomeObject::SomeCOMMethod(...) { | |
| 29 // ExceptionBarrier report_crashes; | |
| 30 // | |
| 31 // ... other code here ... | |
| 32 // } | |
| 33 // @endcode | |
| 34 // | |
| 35 // There are three ExceptionBarrier types defined here: | |
| 36 // 1) ExceptionBarrier which reports all crashes it sees. | |
| 37 // 2) ExceptionBarrierReportOnlyModule which reports only crashes occurring | |
| 38 // in this module. | |
| 39 // 3) ExceptionBarrierCustomHandler which calls the handler set by a call | |
| 40 // to ExceptionBarrierCallCustomHandler::set_custom_handler(). Note that | |
| 41 // there is one custom handler for all ExceptionBarrierCallCustomHandler | |
| 42 // instances. If set_custom_handler() is never called, this places an | |
| 43 // SEH in the chain that just returns ExceptionContinueSearch. | |
| 44 | |
| 45 #ifndef CHROME_FRAME_EXCEPTION_BARRIER_H_ | |
| 46 #define CHROME_FRAME_EXCEPTION_BARRIER_H_ | |
| 47 | |
| 48 #include <windows.h> | |
| 49 | |
| 50 extern "C" IMAGE_DOS_HEADER __ImageBase; | |
| 51 | |
| 52 // This is the type dictated for an exception handler by the platform ABI | |
| 53 // @see _except_handler in excpt.h | |
| 54 typedef EXCEPTION_DISPOSITION (__cdecl* ExceptionHandlerFunc)( | |
| 55 struct _EXCEPTION_RECORD* exception_record, | |
| 56 void* establisher_frame, | |
| 57 struct _CONTEXT* context, | |
| 58 void* reserved); | |
| 59 | |
| 60 // The type of an exception record in the exception handler chain | |
| 61 struct EXCEPTION_REGISTRATION { | |
| 62 EXCEPTION_REGISTRATION* prev; | |
| 63 ExceptionHandlerFunc handler; | |
| 64 }; | |
| 65 | |
| 66 // This is our raw exception handler, it must be declared extern "C" to | |
| 67 // match up with the SAFESEH declaration in our corresponding ASM file. | |
| 68 extern "C" EXCEPTION_DISPOSITION __cdecl | |
| 69 ExceptionBarrierHandler(struct _EXCEPTION_RECORD* exception_record, | |
| 70 void* establisher_frame, | |
| 71 struct _CONTEXT* context, | |
| 72 void* reserved); | |
| 73 | |
| 74 // An alternate raw exception handler that reports crashes only for the current | |
| 75 // module. It must be declared extern "C" to match up with the SAFESEH | |
| 76 // declaration in our corresponding ASM file. | |
| 77 extern "C" EXCEPTION_DISPOSITION __cdecl | |
| 78 ExceptionBarrierReportOnlyModuleHandler( | |
| 79 struct _EXCEPTION_RECORD* exception_record, | |
| 80 void* establisher_frame, | |
| 81 struct _CONTEXT* context, | |
| 82 void* reserved); | |
| 83 | |
| 84 // An alternate raw exception handler that calls out to a custom handler. | |
| 85 // It must be declared extern "C" to match up with the SAFESEH declaration in | |
| 86 // our corresponding ASM file. | |
| 87 extern "C" EXCEPTION_DISPOSITION __cdecl | |
| 88 ExceptionBarrierCallCustomHandler( | |
| 89 struct _EXCEPTION_RECORD* exception_record, | |
| 90 void* establisher_frame, | |
| 91 struct _CONTEXT* context, | |
| 92 void* reserved); | |
| 93 | |
| 94 | |
| 95 // @name These are implemented in the associated .asm file | |
| 96 // @{ | |
| 97 extern "C" void WINAPI RegisterExceptionRecord( | |
| 98 EXCEPTION_REGISTRATION* registration, | |
| 99 ExceptionHandlerFunc func); | |
| 100 extern "C" void WINAPI UnregisterExceptionRecord( | |
| 101 EXCEPTION_REGISTRATION* registration); | |
| 102 // @} | |
| 103 | |
| 104 | |
| 105 // Traits classes for ExceptionBarrierT. | |
| 106 class EBTraitsBase { | |
| 107 public: | |
| 108 static void UnregisterException(EXCEPTION_REGISTRATION* registration) { | |
| 109 UnregisterExceptionRecord(registration); | |
| 110 } | |
| 111 }; | |
| 112 | |
| 113 class EBReportAllTraits : public EBTraitsBase { | |
| 114 public: | |
| 115 static void RegisterException(EXCEPTION_REGISTRATION* registration) { | |
| 116 RegisterExceptionRecord(registration, ExceptionBarrierHandler); | |
| 117 } | |
| 118 }; | |
| 119 | |
| 120 class EBReportOnlyThisModuleTraits : public EBTraitsBase { | |
| 121 public: | |
| 122 static void RegisterException(EXCEPTION_REGISTRATION* registration) { | |
| 123 RegisterExceptionRecord(registration, | |
| 124 ExceptionBarrierReportOnlyModuleHandler); | |
| 125 } | |
| 126 }; | |
| 127 | |
| 128 class EBCustomHandlerTraits : public EBTraitsBase { | |
| 129 public: | |
| 130 static void RegisterException(EXCEPTION_REGISTRATION* registration) { | |
| 131 RegisterExceptionRecord(registration, | |
| 132 ExceptionBarrierCallCustomHandler); | |
| 133 } | |
| 134 }; | |
| 135 | |
| 136 class ExceptionBarrierConfig { | |
| 137 public: | |
| 138 // Used to globally enable or disable crash handling by ExceptionBarrierBase | |
| 139 // instances. | |
| 140 static void set_enabled(bool enabled) { | |
| 141 s_enabled_ = enabled; | |
| 142 } | |
| 143 static bool enabled() { return s_enabled_; } | |
| 144 | |
| 145 // Whether crash reports are enabled. | |
| 146 static bool s_enabled_; | |
| 147 }; | |
| 148 | |
| 149 template <typename RegistrarTraits> | |
| 150 class ExceptionBarrierT { | |
| 151 public: | |
| 152 // Register the barrier in the SEH chain | |
| 153 ExceptionBarrierT() { | |
| 154 RegistrarTraits::RegisterException(®istration_); | |
| 155 } | |
| 156 | |
| 157 // Unregister on destruction | |
| 158 virtual ~ExceptionBarrierT() { | |
| 159 RegistrarTraits::UnregisterException(®istration_); | |
| 160 } | |
| 161 | |
| 162 protected: | |
| 163 // Our SEH frame | |
| 164 EXCEPTION_REGISTRATION registration_; | |
| 165 }; | |
| 166 | |
| 167 // This class allows for setting a custom exception handler function. The | |
| 168 // handler is shared among all instances. This class is intended to enable | |
| 169 // testing of the SEH registration. | |
| 170 template <typename RegistrarTraits> | |
| 171 class ExceptionBarrierCustomHandlerT : | |
| 172 public ExceptionBarrierT<typename RegistrarTraits> { | |
| 173 public: | |
| 174 // Signature of the handler function which gets notified when | |
| 175 // an exception propagates through a barrier. | |
| 176 typedef void (CALLBACK* CustomExceptionHandler)(EXCEPTION_POINTERS* ptrs); | |
| 177 | |
| 178 // Used to set a global custom handler used by all | |
| 179 // ExceptionBarrierCustomHandler instances. | |
| 180 static void set_custom_handler(CustomExceptionHandler handler) { | |
| 181 s_custom_handler_ = handler; | |
| 182 } | |
| 183 static CustomExceptionHandler custom_handler() { return s_custom_handler_; } | |
| 184 | |
| 185 private: | |
| 186 static CustomExceptionHandler s_custom_handler_; | |
| 187 }; | |
| 188 | |
| 189 // Convenience typedefs for the ExceptionBarrierT specializations. | |
| 190 typedef ExceptionBarrierT<EBReportAllTraits> ExceptionBarrier; | |
| 191 typedef ExceptionBarrierT<EBReportOnlyThisModuleTraits> | |
| 192 ExceptionBarrierReportOnlyModule; | |
| 193 typedef ExceptionBarrierCustomHandlerT<EBCustomHandlerTraits> | |
| 194 ExceptionBarrierCustomHandler; | |
| 195 | |
| 196 #endif // CHROME_FRAME_EXCEPTION_BARRIER_H_ | |
| OLD | NEW |