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#ifndef CHROME_FRAME_CRASH_REPORTING_VECTORED_HANDLER_H_
6#define CHROME_FRAME_CRASH_REPORTING_VECTORED_HANDLER_H_
7
8
9#if !defined(_M_IX86)
10#error only x86 is supported for now.
11#endif
12
13// Create dump policy:
14// 1. Scan SEH chain, if there is a handler/filter that belongs to our
15//    module - assume we expect this one and hence do nothing here.
16// 2. If the address of the exception is in our module - create dump.
17// 3. If our module is in somewhere in callstack - create dump.
18// The E class is supposed to provide external/API functions. Using template
19// make testability easier. It shall confirm the following concept/archetype:
20//struct E {
21//  void WriteDump(EXCEPTION_POINTERS* p) {
22//  }
23//
24//  // Used mainly to ignore exceptions from IsBadRead/Write/Ptr.
25//  bool ShouldIgnoreException(const EXCEPTION_POINTERS* exptr) {
26//    return 0;
27//  }
28//
29//  // Retrieve the SEH list head.
30//  EXCEPTION_REGISTRATION_RECORD* RtlpGetExceptionList() {
31//    return NULL;
32//  }
33//
34//  // Get the stack trace as correctly as possible.
35//  WORD RtlCaptureStackBackTrace(DWORD FramesToSkip, DWORD FramesToCapture,
36//                                void** BackTrace, DWORD* BackTraceHash) {
37//      return 0;
38//  }
39//
40//  // Check whether the stack guard page is in place.
41//  bool CheckForStackOverflow(EXCEPTION_POINTERS* p) {
42//    return 0;
43//  }
44//
45//  bool IsOurModule(const void* address) {
46//    return 0;
47//  }
48//};
49// The methods shall be placed in .text$veh_m
50template <typename E>
51class VectoredHandlerT {
52 public:
53  VectoredHandlerT(E* api);
54  ~VectoredHandlerT();
55
56  // TODO(stoyan): Come with better way to skip initial stack frames.
57  FORCEINLINE LONG Handler(EXCEPTION_POINTERS* exceptionInfo);
58  long get_exceptions_seen() const {
59    return exceptions_seen_;
60  }
61
62 private:
63  bool ModuleHasInstalledSEHFilter();
64  E* api_;
65  long exceptions_seen_;
66};
67
68// Maintains start and end address of a single module of interest. If we want
69// do check for multiple modules, this class has to be extended to support a
70// list of modules (DLLs).
71struct ModuleOfInterest {
72  // The callback from VectoredHandlerT::Handler().
73  inline bool IsOurModule(const void* address) {
74    return (start_ <= address && address < end_);
75  }
76
77  // Helpers.
78  inline void SetModule(const void* module_start, const void* module_end) {
79    start_ = module_start;
80    end_ = module_end;
81  }
82
83  inline void SetCurrentModule() {
84    // Find current module boundaries.
85    const void* start = &__ImageBase;
86    const char* s = reinterpret_cast<const char*>(start);
87    const IMAGE_NT_HEADERS32* nt = reinterpret_cast<const IMAGE_NT_HEADERS32*>
88        (s + __ImageBase.e_lfanew);
89    const void* end = s + nt->OptionalHeader.SizeOfImage;
90    SetModule(start, end);
91  }
92
93  const void* start_;
94  const void* end_;
95};
96
97struct ModuleOfInterestWithExcludedRegion : public ModuleOfInterest {
98  inline bool IsOurModule(const void* address) {
99    return (start_ <= address && address < end_) &&
100           (address < special_region_start_ || special_region_end_ <= address);
101  }
102
103  inline void SetExcludedRegion(const void* start, const void* end) {
104    special_region_start_ = start;
105    special_region_end_ = end;
106  }
107
108  const void* special_region_start_;
109  const void* special_region_end_;
110};
111
112
113#endif  // CHROME_FRAME_CRASH_REPORTING_VECTORED_HANDLER_H_
114