summaryrefslogtreecommitdiffstats
path: root/chrome_frame/crash_reporting/vectored_handler.h
blob: 1466bb5db17157750b4f8cb584186144a6edc71b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_FRAME_CRASH_REPORTING_VECTORED_HANDLER_H_
#define CHROME_FRAME_CRASH_REPORTING_VECTORED_HANDLER_H_


#if !defined(_M_IX86)
#error only x86 is supported for now.
#endif

// 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.
// 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:
  VectoredHandlerT(E* api);
  ~VectoredHandlerT();

  // 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_;
  }

 private:
  bool ModuleHasInstalledSEHFilter();
  E* api_;
  long exceptions_seen_;
};

// 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_);
  }

  // Helpers.
  inline void SetModule(const void* module_start, const void* module_end) {
    start_ = module_start;
    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);
  }

  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_;
};


#endif  // CHROME_FRAME_CRASH_REPORTING_VECTORED_HANDLER_H_