 Chromium Code Reviews
 Chromium Code Reviews Issue 1733021:
  Add an ExceptionBarrier around outbound calls to patched methods in IE. In so...  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src/
    
  
    Issue 1733021:
  Add an ExceptionBarrier around outbound calls to patched methods in IE. In so...  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src/| OLD | NEW | 
|---|---|
| 1 | 1 | 
| 2 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 2 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 
| 3 // Use of this source code is governed by a BSD-style license that can be | 3 // Use of this source code is governed by a BSD-style license that can be | 
| 4 // found in the LICENSE file. | 4 // found in the LICENSE file. | 
| 5 | 5 | 
| 6 // crash_report.cc : Implementation crash reporting. | 6 // crash_report.cc : Implementation crash reporting. | 
| 7 #include "chrome_frame/crash_reporting/crash_report.h" | 7 #include "chrome_frame/crash_reporting/crash_report.h" | 
| 8 | 8 | 
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" | 
| 10 #include "base/lock.h" | |
| 10 #include "breakpad/src/client/windows/handler/exception_handler.h" | 11 #include "breakpad/src/client/windows/handler/exception_handler.h" | 
| 11 | 12 | 
| 12 // TODO(joshia): factor out common code with chrome used for crash reporting | 13 // TODO(joshia): factor out common code with chrome used for crash reporting | 
| 13 const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\"; | 14 const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\"; | 
| 14 static google_breakpad::ExceptionHandler * g_breakpad = NULL; | 15 static google_breakpad::ExceptionHandler * g_breakpad = NULL; | 
| 16 static Lock g_breakpad_lock; | |
| 
Sigurður Ásgeirsson
2010/04/28 01:54:10
comment on what this lock protects, please. I'm no
 
robertshield
2010/04/28 10:45:57
Will add a comment in another patch. Generally: th
 | |
| 15 | 17 | 
| 16 // These minidump flag combinations have been tested safe agains the | 18 // These minidump flag combinations have been tested safe agains the | 
| 17 // DbgHelp.dll version that ships with Windows XP SP2. | 19 // DbgHelp.dll version that ships with Windows XP SP2. | 
| 18 const MINIDUMP_TYPE kSmallDumpType = static_cast<MINIDUMP_TYPE>( | 20 const MINIDUMP_TYPE kSmallDumpType = static_cast<MINIDUMP_TYPE>( | 
| 19 MiniDumpWithProcessThreadData | // Get PEB and TEB. | 21 MiniDumpWithProcessThreadData | // Get PEB and TEB. | 
| 20 MiniDumpWithUnloadedModules); // Get unloaded modules when available. | 22 MiniDumpWithUnloadedModules); // Get unloaded modules when available. | 
| 21 | 23 | 
| 22 const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>( | 24 const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>( | 
| 23 MiniDumpWithProcessThreadData | // Get PEB and TEB. | 25 MiniDumpWithProcessThreadData | // Get PEB and TEB. | 
| 24 MiniDumpWithUnloadedModules | // Get unloaded modules when available. | 26 MiniDumpWithUnloadedModules | // Get unloaded modules when available. | 
| (...skipping 15 matching lines...) Expand all Loading... | |
| 40 #pragma code_seg(pop) | 42 #pragma code_seg(pop) | 
| 41 | 43 | 
| 42 // Place code in .text$veh_m. | 44 // Place code in .text$veh_m. | 
| 43 #pragma code_seg(push, ".text$vm") | 45 #pragma code_seg(push, ".text$vm") | 
| 44 #include "chrome_frame/crash_reporting/vectored_handler-impl.h" | 46 #include "chrome_frame/crash_reporting/vectored_handler-impl.h" | 
| 45 | 47 | 
| 46 // Use Win32 API; use breakpad for dumps; checks for single (current) module. | 48 // Use Win32 API; use breakpad for dumps; checks for single (current) module. | 
| 47 class CrashHandlerTraits : public Win32VEHTraits, | 49 class CrashHandlerTraits : public Win32VEHTraits, | 
| 48 public ModuleOfInterestWithExcludedRegion { | 50 public ModuleOfInterestWithExcludedRegion { | 
| 49 public: | 51 public: | 
| 50 CrashHandlerTraits() : breakpad_(NULL) {} | 52 CrashHandlerTraits() {} | 
| 51 void Init(google_breakpad::ExceptionHandler* breakpad) { | 53 | 
| 52 breakpad_ = breakpad; | 54 // Note that breakpad_lock must be held when this is called. | 
| 55 void Init(google_breakpad::ExceptionHandler* breakpad, Lock* breakpad_lock) { | |
| 56 DCHECK(breakpad); | |
| 57 DCHECK(breakpad_lock); | |
| 58 breakpad_lock->AssertAcquired(); | |
| 59 | |
| 53 Win32VEHTraits::InitializeIgnoredBlocks(); | 60 Win32VEHTraits::InitializeIgnoredBlocks(); | 
| 54 ModuleOfInterestWithExcludedRegion::SetCurrentModule(); | 61 ModuleOfInterestWithExcludedRegion::SetCurrentModule(); | 
| 55 // Pointers to static (non-extern) functions take the address of the | 62 // Pointers to static (non-extern) functions take the address of the | 
| 56 // function's first byte, as opposed to an entry in the compiler generated | 63 // function's first byte, as opposed to an entry in the compiler generated | 
| 57 // JMP table. In release builds /OPT:REF wipes away the JMP table, but debug | 64 // JMP table. In release builds /OPT:REF wipes away the JMP table, but debug | 
| 58 // builds are not so lucky. | 65 // builds are not so lucky. | 
| 59 ModuleOfInterestWithExcludedRegion::SetExcludedRegion(&veh_segment_start, | 66 ModuleOfInterestWithExcludedRegion::SetExcludedRegion(&veh_segment_start, | 
| 60 &veh_segment_end); | 67 &veh_segment_end); | 
| 61 } | 68 } | 
| 62 | 69 | 
| 63 void Shutdown() { | 70 void Shutdown() { | 
| 64 breakpad_ = 0; | |
| 65 } | 71 } | 
| 66 | 72 | 
| 67 inline bool WriteDump(EXCEPTION_POINTERS* p) { | 73 inline bool WriteDump(EXCEPTION_POINTERS* p) { | 
| 68 return breakpad_->WriteMinidumpForException(p); | 74 return WriteMinidumpForException(p); | 
| 69 } | 75 } | 
| 70 | |
| 71 private: | |
| 72 google_breakpad::ExceptionHandler* breakpad_; | |
| 73 }; | 76 }; | 
| 74 | 77 | 
| 75 class CrashHandler { | 78 class CrashHandler { | 
| 76 public: | 79 public: | 
| 77 CrashHandler() : veh_id_(NULL), handler_(&crash_api_) {} | 80 CrashHandler() : veh_id_(NULL), handler_(&crash_api_) {} | 
| 78 bool Init(google_breakpad::ExceptionHandler* breakpad); | 81 | 
| 82 // Note that breakpad_lock is used to protect accesses to breakpad and must | |
| 83 // be held when Init() is called. | |
| 84 bool Init(google_breakpad::ExceptionHandler* breakpad, Lock* breakpad_lock); | |
| 85 | |
| 79 void Shutdown(); | 86 void Shutdown(); | 
| 80 private: | 87 private: | 
| 81 VectoredHandlerT<CrashHandlerTraits> handler_; | 88 VectoredHandlerT<CrashHandlerTraits> handler_; | 
| 82 CrashHandlerTraits crash_api_; | 89 CrashHandlerTraits crash_api_; | 
| 83 void* veh_id_; | 90 void* veh_id_; | 
| 84 | 91 | 
| 85 static LONG WINAPI VectoredHandlerEntryPoint(EXCEPTION_POINTERS* exptrs); | 92 static LONG WINAPI VectoredHandlerEntryPoint(EXCEPTION_POINTERS* exptrs); | 
| 86 }; | 93 }; | 
| 87 | 94 | 
| 88 static CrashHandler g_crash_handler; | 95 static CrashHandler g_crash_handler; | 
| 89 | 96 | 
| 90 // Turn off FPO optimization, so ::RtlCaptureStackBackTrace returns sane result. | 97 // Turn off FPO optimization, so ::RtlCaptureStackBackTrace returns sane result. | 
| 91 #pragma optimize("y", off) | 98 #pragma optimize("y", off) | 
| 92 LONG WINAPI CrashHandler::VectoredHandlerEntryPoint( | 99 LONG WINAPI CrashHandler::VectoredHandlerEntryPoint( | 
| 93 EXCEPTION_POINTERS* exptrs) { | 100 EXCEPTION_POINTERS* exptrs) { | 
| 94 return g_crash_handler.handler_.Handler(exptrs); | 101 return g_crash_handler.handler_.Handler(exptrs); | 
| 95 } | 102 } | 
| 96 #pragma optimize("y", on) | 103 #pragma optimize("y", on) | 
| 97 | 104 | 
| 98 #pragma code_seg(pop) | 105 #pragma code_seg(pop) | 
| 99 | 106 | 
| 100 bool CrashHandler::Init(google_breakpad::ExceptionHandler* breakpad) { | 107 bool CrashHandler::Init(google_breakpad::ExceptionHandler* breakpad, | 
| 108 Lock* breakpad_lock) { | |
| 109 DCHECK(breakpad); | |
| 110 DCHECK(breakpad_lock); | |
| 111 breakpad_lock->AssertAcquired(); | |
| 112 | |
| 101 if (veh_id_) | 113 if (veh_id_) | 
| 102 return true; | 114 return true; | 
| 103 | 115 | 
| 104 void* id = ::AddVectoredExceptionHandler(FALSE, &VectoredHandlerEntryPoint); | 116 void* id = ::AddVectoredExceptionHandler(FALSE, &VectoredHandlerEntryPoint); | 
| 105 if (id != NULL) { | 117 if (id != NULL) { | 
| 106 veh_id_ = id; | 118 veh_id_ = id; | 
| 107 crash_api_.Init(breakpad); | 119 crash_api_.Init(breakpad, breakpad_lock); | 
| 108 return true; | 120 return true; | 
| 109 } | 121 } | 
| 110 | 122 | 
| 111 return false; | 123 return false; | 
| 112 } | 124 } | 
| 113 | 125 | 
| 114 void CrashHandler::Shutdown() { | 126 void CrashHandler::Shutdown() { | 
| 115 if (veh_id_) { | 127 if (veh_id_) { | 
| 116 ::RemoveVectoredExceptionHandler(veh_id_); | 128 ::RemoveVectoredExceptionHandler(veh_id_); | 
| 117 veh_id_ = NULL; | 129 veh_id_ = NULL; | 
| 118 } | 130 } | 
| 119 | 131 | 
| 120 crash_api_.Shutdown(); | 132 crash_api_.Shutdown(); | 
| 121 } | 133 } | 
| 122 | 134 | 
| 123 std::wstring GetCrashServerPipeName(const std::wstring& user_sid) { | 135 std::wstring GetCrashServerPipeName(const std::wstring& user_sid) { | 
| 124 std::wstring pipe_name = kGoogleUpdatePipeName; | 136 std::wstring pipe_name = kGoogleUpdatePipeName; | 
| 125 pipe_name += user_sid; | 137 pipe_name += user_sid; | 
| 126 return pipe_name; | 138 return pipe_name; | 
| 127 } | 139 } | 
| 128 | 140 | 
| 129 bool InitializeVectoredCrashReportingWithPipeName( | 141 bool InitializeVectoredCrashReportingWithPipeName( | 
| 130 bool full_dump, | 142 bool full_dump, | 
| 131 const wchar_t* pipe_name, | 143 const wchar_t* pipe_name, | 
| 132 const std::wstring& dump_path, | 144 const std::wstring& dump_path, | 
| 133 google_breakpad::CustomClientInfo* client_info) { | 145 google_breakpad::CustomClientInfo* client_info) { | 
| 146 AutoLock lock(g_breakpad_lock); | |
| 134 if (g_breakpad) | 147 if (g_breakpad) | 
| 135 return true; | 148 return true; | 
| 136 | 149 | 
| 137 if (dump_path.empty()) { | 150 if (dump_path.empty()) { | 
| 138 return false; | 151 return false; | 
| 139 } | 152 } | 
| 140 | 153 | 
| 141 // TODO(siggi): Consider switching to kSmallerDumpType post-beta. | 154 // TODO(siggi): Consider switching to kSmallerDumpType post-beta. | 
| 142 MINIDUMP_TYPE dump_type = full_dump ? kFullDumpType : kLargerDumpType; | 155 MINIDUMP_TYPE dump_type = full_dump ? kFullDumpType : kLargerDumpType; | 
| 143 g_breakpad = new google_breakpad::ExceptionHandler( | 156 g_breakpad = new google_breakpad::ExceptionHandler( | 
| 144 dump_path, NULL, NULL, NULL, | 157 dump_path, NULL, NULL, NULL, | 
| 145 google_breakpad::ExceptionHandler::HANDLER_INVALID_PARAMETER | | 158 google_breakpad::ExceptionHandler::HANDLER_INVALID_PARAMETER | | 
| 146 google_breakpad::ExceptionHandler::HANDLER_PURECALL, dump_type, | 159 google_breakpad::ExceptionHandler::HANDLER_PURECALL, dump_type, | 
| 147 pipe_name, client_info); | 160 pipe_name, client_info); | 
| 148 | 161 | 
| 149 if (!g_breakpad) | 162 if (!g_breakpad) | 
| 150 return false; | 163 return false; | 
| 151 | 164 | 
| 152 if (!g_crash_handler.Init(g_breakpad)) { | 165 if (!g_crash_handler.Init(g_breakpad, &g_breakpad_lock)) { | 
| 153 delete g_breakpad; | 166 delete g_breakpad; | 
| 154 g_breakpad = NULL; | 167 g_breakpad = NULL; | 
| 155 return false; | 168 return false; | 
| 156 } | 169 } | 
| 157 | 170 | 
| 158 return true; | 171 return true; | 
| 159 } | 172 } | 
| 160 | 173 | 
| 161 bool InitializeVectoredCrashReporting( | 174 bool InitializeVectoredCrashReporting( | 
| 162 bool full_dump, | 175 bool full_dump, | 
| 163 const wchar_t* user_sid, | 176 const wchar_t* user_sid, | 
| 164 const std::wstring& dump_path, | 177 const std::wstring& dump_path, | 
| 165 google_breakpad::CustomClientInfo* client_info) { | 178 google_breakpad::CustomClientInfo* client_info) { | 
| 166 DCHECK(user_sid); | 179 DCHECK(user_sid); | 
| 167 DCHECK(client_info); | 180 DCHECK(client_info); | 
| 168 | 181 | 
| 169 std::wstring pipe_name = GetCrashServerPipeName(user_sid); | 182 std::wstring pipe_name = GetCrashServerPipeName(user_sid); | 
| 170 | 183 | 
| 171 return InitializeVectoredCrashReportingWithPipeName(full_dump, | 184 return InitializeVectoredCrashReportingWithPipeName(full_dump, | 
| 172 pipe_name.c_str(), | 185 pipe_name.c_str(), | 
| 173 dump_path, | 186 dump_path, | 
| 174 client_info); | 187 client_info); | 
| 175 } | 188 } | 
| 176 | 189 | 
| 177 bool ShutdownVectoredCrashReporting() { | 190 bool ShutdownVectoredCrashReporting() { | 
| 178 g_crash_handler.Shutdown(); | 191 g_crash_handler.Shutdown(); | 
| 192 AutoLock lock(g_breakpad_lock); | |
| 179 delete g_breakpad; | 193 delete g_breakpad; | 
| 180 g_breakpad = NULL; | 194 g_breakpad = NULL; | 
| 181 return true; | 195 return true; | 
| 182 } | 196 } | 
| 197 | |
| 198 bool WriteMinidumpForException(EXCEPTION_POINTERS* p) { | |
| 199 AutoLock lock(g_breakpad_lock); | |
| 200 bool success = false; | |
| 201 if (g_breakpad) { | |
| 202 success = g_breakpad->WriteMinidumpForException(p); | |
| 203 } | |
| 204 return success; | |
| 205 } | |
| OLD | NEW |