diff options
author | stoyan@chromium.org <stoyan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-31 22:17:07 +0000 |
---|---|---|
committer | stoyan@chromium.org <stoyan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-31 22:17:07 +0000 |
commit | 30f9ac3cd37f6a4833be4ce0aefa969dea9a1808 (patch) | |
tree | af91ba96d5f2170bba3f63fbbe8726dbaf3a2c41 /chrome_frame/crash_reporting/vectored_handler.h | |
parent | b20074de864b34a617630fe8cbcb487d9edcca6e (diff) | |
download | chromium_src-30f9ac3cd37f6a4833be4ce0aefa969dea9a1808.zip chromium_src-30f9ac3cd37f6a4833be4ce0aefa969dea9a1808.tar.gz chromium_src-30f9ac3cd37f6a4833be4ce0aefa969dea9a1808.tar.bz2 |
Prevent excessive crash reporting due stack overflow (due exception in SEH filter).
BUG=32441
Review URL: http://codereview.chromium.org/557021
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37673 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame/crash_reporting/vectored_handler.h')
-rw-r--r-- | chrome_frame/crash_reporting/vectored_handler.h | 142 |
1 files changed, 82 insertions, 60 deletions
diff --git a/chrome_frame/crash_reporting/vectored_handler.h b/chrome_frame/crash_reporting/vectored_handler.h index 7447bba..1466bb5 100644 --- a/chrome_frame/crash_reporting/vectored_handler.h +++ b/chrome_frame/crash_reporting/vectored_handler.h @@ -5,87 +5,109 @@ #ifndef CHROME_FRAME_CRASH_REPORTING_VECTORED_HANDLER_H_ #define CHROME_FRAME_CRASH_REPORTING_VECTORED_HANDLER_H_ -// Base class for VectoredHandlerT just to hold some members (independent of -// template parameter) -class VectoredHandlerBase { - public: - // For RtlCaptureStackBackTrace MSDN says: - // Windows Server 2003 and Windows XP: The sum of the FramesToSkip and - // FramesToCapture parameters must be less than 64. - // In practice (on XPSP2) it has to be less than 63, hence leaving us with - // max back trace of 62. - static const DWORD max_back_trace = 62; - static unsigned long g_exceptions_seen; - protected: - static void* g_handler; -}; -DECLSPEC_SELECTANY void* VectoredHandlerBase::g_handler; -DECLSPEC_SELECTANY unsigned long VectoredHandlerBase::g_exceptions_seen; +#if !defined(_M_IX86) +#error only x86 is supported for now. +#endif -// The E class is supposed to provide external/API functions. Using template -// make testability easier. It shall confirm the following concept/archetype: -// void* Register(PVECTORED_EXCEPTION_HANDLER, -// const void* module_start, const void* module_end) -// Registers Vectored Exception Handler, non-unittest implementation shall call -// ::AddVectoredExceptionHandler Win32 API -// ULONG Unregister(void*) - ::RemoveVectoredExceptionHandler Win32 API -// int IsOurModule(const void* address) - -// void WriteDump(EXCEPTION_POINTERS*) - -// WORD RtlCaptureStackBackTrace(..) - same as Win32 API -// EXCEPTION_REGISTRATION_RECORD* RtlpGetExceptionList() - same as Win32 API -// You may want to derive own External class by deriving from -// VEHExternalBase helper (see below). // Create dump policy: // 1. Scan SEH chain, if there is a handler/filter that belongs to our // module - assume we expect this one and hence do nothing here. // 2. If the address of the exception is in our module - create dump. // 3. If our module is in somewhere in callstack - create dump. -template <class E> -class VectoredHandlerT : public VectoredHandlerBase { +// The E class is supposed to provide external/API functions. Using template +// make testability easier. It shall confirm the following concept/archetype: +//struct E { +// void WriteDump(EXCEPTION_POINTERS* p) { +// } +// +// // Used mainly to ignore exceptions from IsBadRead/Write/Ptr. +// bool ShouldIgnoreException(const EXCEPTION_POINTERS* exptr) { +// return 0; +// } +// +// // Retrieve the SEH list head. +// EXCEPTION_REGISTRATION_RECORD* RtlpGetExceptionList() { +// return NULL; +// } +// +// // Get the stack trace as correctly as possible. +// WORD RtlCaptureStackBackTrace(DWORD FramesToSkip, DWORD FramesToCapture, +// void** BackTrace, DWORD* BackTraceHash) { +// return 0; +// } +// +// // Check whether the stack guard page is in place. +// bool CheckForStackOverflow(EXCEPTION_POINTERS* p) { +// return 0; +// } +// +// bool IsOurModule(const void* address) { +// return 0; +// } +//}; +// The methods shall be placed in .text$veh_m +template <typename E> +class VectoredHandlerT { public: - static void* Register(const void* module_start, const void* module_end) { - g_exceptions_seen = 0; - g_handler = E::Register(&VectoredHandler, module_start, module_end); - return g_handler; - } + VectoredHandlerT(E* api); + ~VectoredHandlerT(); - static ULONG Unregister() { - if (g_handler) - return E::Unregister(g_handler); - return 0; + // TODO(stoyan): Come with better way to skip initial stack frames. + FORCEINLINE LONG Handler(EXCEPTION_POINTERS* exceptionInfo); + long get_exceptions_seen() const { + return exceptions_seen_; } - static LONG WINAPI VectoredHandler(EXCEPTION_POINTERS* exceptionInfo); private: - static BOOL ModuleHasInstalledSEHFilter(); + bool ModuleHasInstalledSEHFilter(); + E* api_; + long exceptions_seen_; }; -// Handy class supposed to act as a base class for classes used as template -// parameter of VectoredHandlerT<E> -class VEHTraitsBase { - public: - static const void* g_module_start; - static const void* g_module_end; +// Maintains start and end address of a single module of interest. If we want +// do check for multiple modules, this class has to be extended to support a +// list of modules (DLLs). +struct ModuleOfInterest { + // The callback from VectoredHandlerT::Handler(). + inline bool IsOurModule(const void* address) { + return (start_ <= address && address < end_); + } - static inline int IsOurModule(const void* address) { - return (g_module_start <= address && address < g_module_end); + // Helpers. + inline void SetModule(const void* module_start, const void* module_end) { + start_ = module_start; + end_ = module_end; } - static inline void SetModule(const void* module_start, - const void* module_end) { - g_module_start = module_start; - g_module_end = module_end; + inline void SetCurrentModule() { + // Find current module boundaries. + const void* start = &__ImageBase; + const char* s = reinterpret_cast<const char*>(start); + const IMAGE_NT_HEADERS32* nt = reinterpret_cast<const IMAGE_NT_HEADERS32*> + (s + __ImageBase.e_lfanew); + const void* end = s + nt->OptionalHeader.SizeOfImage; + SetModule(start, end); } - static bool ShouldIgnoreException(const EXCEPTION_POINTERS* exceptionInfo) { - return false; + const void* start_; + const void* end_; +}; + +struct ModuleOfInterestWithExcludedRegion : public ModuleOfInterest { + inline bool IsOurModule(const void* address) { + return (start_ <= address && address < end_) && + (address < special_region_start_ || special_region_end_ <= address); } + + inline void SetExcludedRegion(const void* start, const void* end) { + special_region_start_ = start; + special_region_end_ = end; + } + + const void* special_region_start_; + const void* special_region_end_; }; -DECLSPEC_SELECTANY const void* VEHTraitsBase::g_module_start; -DECLSPEC_SELECTANY const void* VEHTraitsBase::g_module_end; -class Win32VEHTraits; -typedef class VectoredHandlerT<Win32VEHTraits> VectoredHandler; #endif // CHROME_FRAME_CRASH_REPORTING_VECTORED_HANDLER_H_ |