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

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

Issue 5622006: Improve filtering for false positive crashes... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years 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
« no previous file with comments | « no previous file | chrome_frame/crash_reporting/vectored_handler_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef CHROME_FRAME_CRASH_REPORTING_VECTORED_HANDLER_IMPL_H_ 5 #ifndef CHROME_FRAME_CRASH_REPORTING_VECTORED_HANDLER_IMPL_H_
6 #define CHROME_FRAME_CRASH_REPORTING_VECTORED_HANDLER_IMPL_H_ 6 #define CHROME_FRAME_CRASH_REPORTING_VECTORED_HANDLER_IMPL_H_
7 7
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "chrome_frame/crash_reporting/vectored_handler.h" 9 #include "chrome_frame/crash_reporting/vectored_handler.h"
10 #include "chrome_frame/crash_reporting/nt_loader.h" 10 #include "chrome_frame/crash_reporting/nt_loader.h"
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 exceptions_seen_++; 76 exceptions_seen_++;
77 77
78 // If the exception code is STATUS_STACK_OVERFLOW then proceed as usual - 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 - 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 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. 81 // seeing the follow-up STATUS_ACCESS_VIOLATION(s). See bug 32441.
82 if (exceptionCode != STATUS_STACK_OVERFLOW && api_->CheckForStackOverflow()) { 82 if (exceptionCode != STATUS_STACK_OVERFLOW && api_->CheckForStackOverflow()) {
83 return ExceptionContinueSearch; 83 return ExceptionContinueSearch;
84 } 84 }
85 85
86 // Check whether exception address is inbetween 86 // Check whether exception will be handled by the module that cuased it.
87 // [IsBadReadPtr, IsBadReadPtr + 0xXX] 87 // This should automatically handle the case of IsBadReadPtr and family.
88 if (api_->ShouldIgnoreException(exceptionInfo)) { 88 const EXCEPTION_REGISTRATION_RECORD* seh = api_->RtlpGetExceptionList();
89 if (api_->ShouldIgnoreException(exceptionInfo, seh)) {
89 return ExceptionContinueSearch; 90 return ExceptionContinueSearch;
90 } 91 }
91 92
92 const DWORD exceptionFlags = exceptionInfo->ExceptionRecord->ExceptionFlags; 93 const DWORD exceptionFlags = exceptionInfo->ExceptionRecord->ExceptionFlags;
93 // I don't think VEH is called on unwind. Just to be safe. 94 // I don't think VEH is called on unwind. Just to be safe.
94 if (IS_DISPATCHING(exceptionFlags)) { 95 if (IS_DISPATCHING(exceptionFlags)) {
95 if (ModuleHasInstalledSEHFilter()) 96 if (ModuleHasInstalledSEHFilter())
96 return ExceptionContinueSearch; 97 return ExceptionContinueSearch;
97 98
98 if (api_->IsOurModule(exceptionInfo->ExceptionRecord->ExceptionAddress)) { 99 if (api_->IsOurModule(exceptionInfo->ExceptionRecord->ExceptionAddress)) {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 EXCEPTION_REGISTRATION_RECORD* RtlpGetExceptionList() { 163 EXCEPTION_REGISTRATION_RECORD* RtlpGetExceptionList() {
163 return InternalRtlpGetExceptionList(); 164 return InternalRtlpGetExceptionList();
164 } 165 }
165 166
166 static inline WORD RtlCaptureStackBackTrace(DWORD FramesToSkip, 167 static inline WORD RtlCaptureStackBackTrace(DWORD FramesToSkip,
167 DWORD FramesToCapture, void** BackTrace, DWORD* BackTraceHash) { 168 DWORD FramesToCapture, void** BackTrace, DWORD* BackTraceHash) {
168 return ::RtlCaptureStackBackTrace(FramesToSkip, FramesToCapture, 169 return ::RtlCaptureStackBackTrace(FramesToSkip, FramesToCapture,
169 BackTrace, BackTraceHash); 170 BackTrace, BackTraceHash);
170 } 171 }
171 172
172 static bool ShouldIgnoreException(const EXCEPTION_POINTERS* exceptionInfo) { 173 static bool ShouldIgnoreException(const EXCEPTION_POINTERS* exceptionInfo,
174 const EXCEPTION_REGISTRATION_RECORD* seh_record) {
173 const void* address = exceptionInfo->ExceptionRecord->ExceptionAddress; 175 const void* address = exceptionInfo->ExceptionRecord->ExceptionAddress;
174 for (int i = 0; i < kIgnoreEntries; i++) { 176 const DWORD flags = GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT |
175 const CodeBlock& code_block = IgnoreExceptions[i]; 177 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS;
176 DCHECK(code_block.code) << "Win32VEHTraits::CodeBlocks not initialized!"; 178 HMODULE crashing_module = GetModuleHandleFromAddress(address);
177 if ((CodeOffset(code_block.code, code_block.begin_offset) <= address) && 179 if (!crashing_module)
178 (address < CodeOffset(code_block.code, code_block.end_offset))) { 180 return false;
179 return true; 181
180 } 182 HMODULE top_seh_module = NULL;
181 } 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;
182 191
183 // We don't want to report exceptions that occur during DLL loading, 192 // We don't want to report exceptions that occur during DLL loading,
184 // as those are captured and ignored by the NT loader. If this thread 193 // as those are captured and ignored by the NT loader. If this thread
185 // is holding the loader's lock, there's a possiblity that the crash 194 // is holding the loader's lock, there's a possiblity that the crash
186 // is occurring in a loading DLL, in which case we resolve the 195 // is occurring in a loading DLL, in which case we resolve the
187 // crash address to a module and check on the module's status. 196 // crash address to a module and check on the module's status.
188 const DWORD flags = GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | 197 if (nt_loader::OwnsLoaderLock()) {
189 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS;
190 HMODULE crashing_module = NULL;
191 if (nt_loader::OwnsLoaderLock() && ::GetModuleHandleEx(
192 flags, reinterpret_cast<LPCWSTR>(address), &crashing_module)) {
193 nt_loader::LDR_DATA_TABLE_ENTRY* entry = 198 nt_loader::LDR_DATA_TABLE_ENTRY* entry =
194 nt_loader::GetLoaderEntry(crashing_module); 199 nt_loader::GetLoaderEntry(crashing_module);
195 200
196 // If: 201 // If:
197 // 1. we found the entry in question, and 202 // 1. we found the entry in question, and
198 // 2. the entry is a DLL (has the IMAGE_DLL flag set), and 203 // 2. the entry is a DLL (has the IMAGE_DLL flag set), and
199 // 3. the DLL has a non-null entrypoint, and 204 // 3. the DLL has a non-null entrypoint, and
200 // 4. the loader has not tagged it with the process attached called flag 205 // 4. the loader has not tagged it with the process attached called flag
201 // we conclude that the crash is most likely during the loading of the 206 // we conclude that the crash is most likely during the loading of the
202 // module and bail on reporting the crash to avoid false positives 207 // module and bail on reporting the crash to avoid false positives
203 // during crashes that occur during module loads, such as e.g. when 208 // during crashes that occur during module loads, such as e.g. when
204 // the hook manager attempts to load buggy window hook DLLs. 209 // the hook manager attempts to load buggy window hook DLLs.
205 if (entry && 210 if (entry &&
206 (entry->Flags & LDRP_IMAGE_DLL) != 0 && 211 (entry->Flags & LDRP_IMAGE_DLL) != 0 &&
207 (entry->EntryPoint != NULL) && 212 (entry->EntryPoint != NULL) &&
208 (entry->Flags & LDRP_PROCESS_ATTACH_CALLED) == 0) 213 (entry->Flags & LDRP_PROCESS_ATTACH_CALLED) == 0)
209 return true; 214 return true;
210 } 215 }
211 216
212 return false; 217 return false;
213 } 218 }
214 219
215 static bool CheckForStackOverflow() { 220 static bool CheckForStackOverflow() {
216 MEMORY_BASIC_INFORMATION mi; 221 MEMORY_BASIC_INFORMATION mi = {0};
217 const DWORD kPageSize = 0x1000; 222 const DWORD kPageSize = 0x1000;
218 void* stack_top = GetStackTopLimit() - kPageSize; 223 void* stack_top = GetStackTopLimit() - kPageSize;
219 ::VirtualQuery(stack_top, &mi, sizeof(mi)); 224 ::VirtualQuery(stack_top, &mi, sizeof(mi));
220 // The above call may result in moving the top of the stack. 225 // The above call may result in moving the top of the stack.
221 // Check once more. 226 // Check once more.
222 void* stack_top2 = GetStackTopLimit() - kPageSize; 227 void* stack_top2 = GetStackTopLimit() - kPageSize;
223 if (stack_top2 != stack_top) 228 if (stack_top2 != stack_top)
224 ::VirtualQuery(stack_top2, &mi, sizeof(mi)); 229 ::VirtualQuery(stack_top2, &mi, sizeof(mi));
225 return !(mi.Protect & PAGE_GUARD); 230 return !(mi.Protect & PAGE_GUARD);
226 } 231 }
227 232
228 static void InitializeIgnoredBlocks() {
229 // Initialize ignored exception list
230 for (int i = 0; i < kIgnoreEntries; i++) {
231 CodeBlock& code_block = IgnoreExceptions[i];
232 if (!code_block.code) {
233 HMODULE module = GetModuleHandleA(code_block.module);
234 DCHECK(module) << "GetModuleHandle error: " << GetLastError();
235 code_block.code = GetProcAddress(module, code_block.function);
236 DCHECK(code_block.code) << "GetProcAddress error: "<< GetLastError();
237 }
238 }
239 }
240
241 private: 233 private:
242 static inline const void* CodeOffset(const void* code, int offset) { 234 static inline const void* CodeOffset(const void* code, int offset) {
243 return reinterpret_cast<const char*>(code) + offset; 235 return reinterpret_cast<const char*>(code) + offset;
244 } 236 }
245 237
246 // Block of code to be ignored for exceptions 238 static HMODULE GetModuleHandleFromAddress(const void* p) {
247 struct CodeBlock { 239 HMODULE module_at_address = NULL;
248 char* module; 240 MEMORY_BASIC_INFORMATION mi = {0};
249 char* function; 241 if (::VirtualQuery(p, &mi, sizeof(mi)) && (mi.Type & MEM_IMAGE)) {
250 int begin_offset; 242 module_at_address = reinterpret_cast<HMODULE>(mi.AllocationBase);
251 int end_offset; 243 }
252 const void* code;
253 };
254 244
255 static const int kIgnoreEntries = 4; 245 return module_at_address;
256 static CodeBlock IgnoreExceptions[kIgnoreEntries]; 246 }
257 }; 247 };
258 248
259 DECLSPEC_SELECTANY Win32VEHTraits::CodeBlock
260 Win32VEHTraits::IgnoreExceptions[kIgnoreEntries] = {
261 { "kernel32.dll", "IsBadReadPtr", 0, 100, NULL },
262 { "kernel32.dll", "IsBadWritePtr", 0, 100, NULL },
263 { "kernel32.dll", "IsBadStringPtrA", 0, 100, NULL },
264 { "kernel32.dll", "IsBadStringPtrW", 0, 100, NULL },
265 };
266 249
267 // Use Win32 API; checks for single (current) module. Will call a specified 250 // Use Win32 API; checks for single (current) module. Will call a specified
268 // CrashHandlerTraits::DumpHandler when taking a dump. 251 // CrashHandlerTraits::DumpHandler when taking a dump.
269 class CrashHandlerTraits : public Win32VEHTraits, 252 class CrashHandlerTraits : public Win32VEHTraits,
270 public ModuleOfInterestWithExcludedRegion { 253 public ModuleOfInterestWithExcludedRegion {
271 public: 254 public:
272 255
273 typedef bool (*DumpHandler)(EXCEPTION_POINTERS* p); 256 typedef bool (*DumpHandler)(EXCEPTION_POINTERS* p);
274 257
275 CrashHandlerTraits() : dump_handler_(NULL) {} 258 CrashHandlerTraits() : dump_handler_(NULL) {}
276 259
277 // Note that breakpad_lock must be held when this is called. 260 // Note that breakpad_lock must be held when this is called.
278 void Init(const void* veh_segment_start, const void* veh_segment_end, 261 void Init(const void* veh_segment_start, const void* veh_segment_end,
279 DumpHandler dump_handler) { 262 DumpHandler dump_handler) {
280 DCHECK(dump_handler); 263 DCHECK(dump_handler);
281 dump_handler_ = dump_handler; 264 dump_handler_ = dump_handler;
282 Win32VEHTraits::InitializeIgnoredBlocks();
283 ModuleOfInterestWithExcludedRegion::SetCurrentModule(); 265 ModuleOfInterestWithExcludedRegion::SetCurrentModule();
284 // Pointers to static (non-extern) functions take the address of the 266 // Pointers to static (non-extern) functions take the address of the
285 // function's first byte, as opposed to an entry in the compiler generated 267 // function's first byte, as opposed to an entry in the compiler generated
286 // JMP table. In release builds /OPT:REF wipes away the JMP table, but debug 268 // JMP table. In release builds /OPT:REF wipes away the JMP table, but debug
287 // builds are not so lucky. 269 // builds are not so lucky.
288 ModuleOfInterestWithExcludedRegion::SetExcludedRegion(veh_segment_start, 270 ModuleOfInterestWithExcludedRegion::SetExcludedRegion(veh_segment_start,
289 veh_segment_end); 271 veh_segment_end);
290 } 272 }
291 273
292 void Shutdown() { 274 void Shutdown() {
293 } 275 }
294 276
295 inline bool WriteDump(EXCEPTION_POINTERS* p) { 277 inline bool WriteDump(EXCEPTION_POINTERS* p) {
296 if (dump_handler_) { 278 if (dump_handler_) {
297 return dump_handler_(p); 279 return dump_handler_(p);
298 } else { 280 } else {
299 return false; 281 return false;
300 } 282 }
301 } 283 }
302 284
303 private: 285 private:
304 DumpHandler dump_handler_; 286 DumpHandler dump_handler_;
305 }; 287 };
306 288
307 #endif // CHROME_FRAME_CRASH_REPORTING_VECTORED_HANDLER_IMPL_H_ 289 #endif // CHROME_FRAME_CRASH_REPORTING_VECTORED_HANDLER_IMPL_H_
OLDNEW
« no previous file with comments | « no previous file | chrome_frame/crash_reporting/vectored_handler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698