Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: chrome_frame/crash_reporting/vectored_handler-impl.h

Issue 126143005: Remove Chrome Frame code and resources. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: sync to r244038 Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 #ifndef CHROME_FRAME_CRASH_REPORTING_VECTORED_HANDLER_IMPL_H_
6 #define CHROME_FRAME_CRASH_REPORTING_VECTORED_HANDLER_IMPL_H_
7
8 #include "base/logging.h"
9 #include "chrome_frame/crash_reporting/vectored_handler.h"
10 #include "chrome_frame/crash_reporting/nt_loader.h"
11
12 #if !defined(_M_IX86)
13 #error only x86 is supported for now.
14 #endif
15
16 #ifndef EXCEPTION_CHAIN_END
17 #define EXCEPTION_CHAIN_END ((struct _EXCEPTION_REGISTRATION_RECORD*)-1)
18 #if !defined(_WIN32_WINNT_WIN8)
19 typedef struct _EXCEPTION_REGISTRATION_RECORD {
20 struct _EXCEPTION_REGISTRATION_RECORD* Next;
21 PVOID Handler;
22 } EXCEPTION_REGISTRATION_RECORD;
23 // VEH handler flags settings.
24 // These are grabbed from winnt.h for PocketPC.
25 // Only EXCEPTION_NONCONTINUABLE in defined in "regular" winnt.h
26 // #define EXCEPTION_NONCONTINUABLE 0x1 // Noncontinuable exception
27 #define EXCEPTION_UNWINDING 0x2 // Unwind is in progress
28 #define EXCEPTION_EXIT_UNWIND 0x4 // Exit unwind is in progress
29 #define EXCEPTION_STACK_INVALID 0x8 // Stack out of limits or unaligned
30 #define EXCEPTION_NESTED_CALL 0x10 // Nested exception handler call
31 #define EXCEPTION_TARGET_UNWIND 0x20 // Target unwind in progress
32 #define EXCEPTION_COLLIDED_UNWIND 0x40 // Collided exception handler call
33
34 #define EXCEPTION_UNWIND (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND | \
35 EXCEPTION_TARGET_UNWIND | EXCEPTION_COLLIDED_UNWIND)
36
37 #define IS_UNWINDING(Flag) (((Flag) & EXCEPTION_UNWIND) != 0)
38 #define IS_DISPATCHING(Flag) (((Flag) & EXCEPTION_UNWIND) == 0)
39 #define IS_TARGET_UNWIND(Flag) ((Flag) & EXCEPTION_TARGET_UNWIND)
40 #endif // !defined(_WIN32_WINNT_WIN8)
41 #endif // EXCEPTION_CHAIN_END
42
43 template <typename E>
44 VectoredHandlerT<E>::VectoredHandlerT(E* api) : exceptions_seen_(0), api_(api) {
45 }
46
47 template <typename E>
48 VectoredHandlerT<E>::~VectoredHandlerT() {
49 }
50
51 template <typename E>
52 LONG VectoredHandlerT<E>::Handler(EXCEPTION_POINTERS* exceptionInfo) {
53 // TODO(stoyan): Consider reentrancy
54 const DWORD exceptionCode = exceptionInfo->ExceptionRecord->ExceptionCode;
55
56 // Not interested in non-error exceptions. In this category falls exceptions
57 // like:
58 // 0x40010006 - OutputDebugStringA. Seen when no debugger is attached
59 // (otherwise debugger swallows the exception and prints
60 // the string).
61 // 0x406D1388 - DebuggerProbe. Used by debug CRT - for example see source
62 // code of isatty(). Used to name a thread as well.
63 // RPC_E_DISCONNECTED and Co. - COM IPC non-fatal warnings
64 // STATUS_BREAKPOINT and Co. - Debugger related breakpoints
65 if ((exceptionCode & ERROR_SEVERITY_ERROR) != ERROR_SEVERITY_ERROR) {
66 return ExceptionContinueSearch;
67 }
68
69 // Ignore custom exception codes.
70 // MSXML likes to raise 0xE0000001 while parsing.
71 // Note the C++ SEH (0xE06D7363) also fails in that range.
72 if (exceptionCode & APPLICATION_ERROR_MASK) {
73 return ExceptionContinueSearch;
74 }
75
76 exceptions_seen_++;
77
78 // If the exception code is STATUS_STACK_OVERFLOW then proceed as usual -
79 // we want to report it. Otherwise check whether guard page in stack is gone -
80 // i.e. stack overflow has been already observed and most probably we are
81 // seeing the follow-up STATUS_ACCESS_VIOLATION(s). See bug 32441.
82 if (exceptionCode != STATUS_STACK_OVERFLOW && api_->CheckForStackOverflow()) {
83 return ExceptionContinueSearch;
84 }
85
86 // Check whether exception will be handled by the module that cuased it.
87 // This should automatically handle the case of IsBadReadPtr and family.
88 const EXCEPTION_REGISTRATION_RECORD* seh = api_->RtlpGetExceptionList();
89 if (api_->ShouldIgnoreException(exceptionInfo, seh)) {
90 return ExceptionContinueSearch;
91 }
92
93 const DWORD exceptionFlags = exceptionInfo->ExceptionRecord->ExceptionFlags;
94 // I don't think VEH is called on unwind. Just to be safe.
95 if (IS_DISPATCHING(exceptionFlags)) {
96 if (ModuleHasInstalledSEHFilter())
97 return ExceptionContinueSearch;
98
99 if (api_->IsOurModule(exceptionInfo->ExceptionRecord->ExceptionAddress)) {
100 api_->WriteDump(exceptionInfo);
101 return ExceptionContinueSearch;
102 }
103
104 // See whether our module is somewhere in the call stack.
105 void* back_trace[E::max_back_trace] = {0};
106 DWORD captured = api_->RtlCaptureStackBackTrace(0, api_->max_back_trace,
107 &back_trace[0], NULL);
108 for (DWORD i = 0; i < captured; ++i) {
109 if (api_->IsOurModule(back_trace[i])) {
110 api_->WriteDump(exceptionInfo);
111 return ExceptionContinueSearch;
112 }
113 }
114 }
115
116 return ExceptionContinueSearch;
117 }
118
119 template <typename E>
120 bool VectoredHandlerT<E>::ModuleHasInstalledSEHFilter() {
121 const EXCEPTION_REGISTRATION_RECORD* RegistrationFrame =
122 api_->RtlpGetExceptionList();
123 // TODO(stoyan): Add the stack limits check and some sanity checks like
124 // decreasing addresses of registration records
125 while (RegistrationFrame != EXCEPTION_CHAIN_END) {
126 if (api_->IsOurModule(RegistrationFrame->Handler)) {
127 return true;
128 }
129
130 RegistrationFrame = RegistrationFrame->Next;
131 }
132
133 return false;
134 }
135
136
137 // Here comes the default Windows 32-bit implementation.
138 namespace {
139 __declspec(naked)
140 static EXCEPTION_REGISTRATION_RECORD* InternalRtlpGetExceptionList() {
141 __asm {
142 mov eax, fs:0
143 ret
144 }
145 }
146
147 __declspec(naked)
148 static char* GetStackTopLimit() {
149 __asm {
150 mov eax, fs:8
151 ret
152 }
153 }
154 } // end of namespace
155
156 // Class which methods simply forwards to Win32 API.
157 // Used as template (external interface) of VectoredHandlerT<E>.
158 class Win32VEHTraits {
159 public:
160 enum {max_back_trace = 62};
161
162 static inline
163 EXCEPTION_REGISTRATION_RECORD* RtlpGetExceptionList() {
164 return InternalRtlpGetExceptionList();
165 }
166
167 static inline WORD RtlCaptureStackBackTrace(DWORD FramesToSkip,
168 DWORD FramesToCapture, void** BackTrace, DWORD* BackTraceHash) {
169 return ::RtlCaptureStackBackTrace(FramesToSkip, FramesToCapture,
170 BackTrace, BackTraceHash);
171 }
172
173 static bool ShouldIgnoreException(const EXCEPTION_POINTERS* exceptionInfo,
174 const EXCEPTION_REGISTRATION_RECORD* seh_record) {
175 const void* address = exceptionInfo->ExceptionRecord->ExceptionAddress;
176 const DWORD flags = GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT |
177 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS;
178 HMODULE crashing_module = GetModuleHandleFromAddress(address);
179 if (!crashing_module)
180 return false;
181
182 HMODULE top_seh_module = NULL;
183 if (EXCEPTION_CHAIN_END != seh_record)
184 top_seh_module = GetModuleHandleFromAddress(seh_record->Handler);
185
186 // check if the crash address belongs in a module that's expecting
187 // and handling it. This should address cases like kernel32!IsBadXXX
188 // and urlmon!IsValidInterface
189 if (crashing_module == top_seh_module)
190 return true;
191
192 // We don't want to report exceptions that occur during DLL loading,
193 // as those are captured and ignored by the NT loader. If this thread
194 // is holding the loader's lock, there's a possiblity that the crash
195 // is occurring in a loading DLL, in which case we resolve the
196 // crash address to a module and check on the module's status.
197 if (nt_loader::OwnsLoaderLock()) {
198 nt_loader::LDR_DATA_TABLE_ENTRY* entry =
199 nt_loader::GetLoaderEntry(crashing_module);
200
201 // If:
202 // 1. we found the entry in question, and
203 // 2. the entry is a DLL (has the IMAGE_DLL flag set), and
204 // 3. the DLL has a non-null entrypoint, and
205 // 4. the loader has not tagged it with the process attached called flag
206 // we conclude that the crash is most likely during the loading of the
207 // module and bail on reporting the crash to avoid false positives
208 // during crashes that occur during module loads, such as e.g. when
209 // the hook manager attempts to load buggy window hook DLLs.
210 if (entry &&
211 (entry->Flags & LDRP_IMAGE_DLL) != 0 &&
212 (entry->EntryPoint != NULL) &&
213 (entry->Flags & LDRP_PROCESS_ATTACH_CALLED) == 0)
214 return true;
215 }
216
217 return false;
218 }
219
220 static bool CheckForStackOverflow() {
221 MEMORY_BASIC_INFORMATION mi = {0};
222 const DWORD kPageSize = 0x1000;
223 void* stack_top = GetStackTopLimit() - kPageSize;
224 ::VirtualQuery(stack_top, &mi, sizeof(mi));
225 // The above call may result in moving the top of the stack.
226 // Check once more.
227 void* stack_top2 = GetStackTopLimit() - kPageSize;
228 if (stack_top2 != stack_top)
229 ::VirtualQuery(stack_top2, &mi, sizeof(mi));
230 return !(mi.Protect & PAGE_GUARD);
231 }
232
233 private:
234 static inline const void* CodeOffset(const void* code, int offset) {
235 return reinterpret_cast<const char*>(code) + offset;
236 }
237
238 static HMODULE GetModuleHandleFromAddress(const void* p) {
239 HMODULE module_at_address = NULL;
240 MEMORY_BASIC_INFORMATION mi = {0};
241 if (::VirtualQuery(p, &mi, sizeof(mi)) && (mi.Type & MEM_IMAGE)) {
242 module_at_address = reinterpret_cast<HMODULE>(mi.AllocationBase);
243 }
244
245 return module_at_address;
246 }
247 };
248
249
250 // Use Win32 API; checks for single (current) module. Will call a specified
251 // CrashHandlerTraits::DumpHandler when taking a dump.
252 class CrashHandlerTraits : public Win32VEHTraits,
253 public ModuleOfInterestWithExcludedRegion {
254 public:
255
256 typedef bool (*DumpHandler)(EXCEPTION_POINTERS* p);
257
258 CrashHandlerTraits() : dump_handler_(NULL) {}
259
260 // Note that breakpad_lock must be held when this is called.
261 void Init(const void* veh_segment_start, const void* veh_segment_end,
262 DumpHandler dump_handler) {
263 DCHECK(dump_handler);
264 dump_handler_ = dump_handler;
265 ModuleOfInterestWithExcludedRegion::SetCurrentModule();
266 // Pointers to static (non-extern) functions take the address of the
267 // function's first byte, as opposed to an entry in the compiler generated
268 // JMP table. In release builds /OPT:REF wipes away the JMP table, but debug
269 // builds are not so lucky.
270 ModuleOfInterestWithExcludedRegion::SetExcludedRegion(veh_segment_start,
271 veh_segment_end);
272 }
273
274 void Shutdown() {
275 }
276
277 inline bool WriteDump(EXCEPTION_POINTERS* p) {
278 if (dump_handler_) {
279 return dump_handler_(p);
280 } else {
281 return false;
282 }
283 }
284
285 private:
286 DumpHandler dump_handler_;
287 };
288
289 #endif // CHROME_FRAME_CRASH_REPORTING_VECTORED_HANDLER_IMPL_H_
OLDNEW
« no previous file with comments | « chrome_frame/crash_reporting/vectored_handler.h ('k') | chrome_frame/crash_reporting/vectored_handler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698