OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #include "chrome/app/breakpad_win.h" | 5 #include "chrome/app/breakpad_win.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 #include <shellapi.h> | 8 #include <shellapi.h> |
9 #include <tchar.h> | 9 #include <tchar.h> |
10 #include <userenv.h> | 10 #include <userenv.h> |
| 11 #include <winternl.h> |
11 | 12 |
12 #include <algorithm> | 13 #include <algorithm> |
13 #include <vector> | 14 #include <vector> |
14 | 15 |
15 #include "base/base_switches.h" | 16 #include "base/base_switches.h" |
16 #include "base/command_line.h" | 17 #include "base/command_line.h" |
17 #include "base/environment.h" | 18 #include "base/environment.h" |
18 #include "base/file_util.h" | 19 #include "base/file_util.h" |
19 #include "base/file_version_info.h" | 20 #include "base/file_version_info.h" |
20 #include "base/memory/scoped_ptr.h" | 21 #include "base/memory/scoped_ptr.h" |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 // of pepper/renderer processes is reduced. | 140 // of pepper/renderer processes is reduced. |
140 DWORD WINAPI DumpForHangDebuggingThread(void*) { | 141 DWORD WINAPI DumpForHangDebuggingThread(void*) { |
141 DumpProcessWithoutCrash(); | 142 DumpProcessWithoutCrash(); |
142 LOG(INFO) << "dumped for hang debugging"; | 143 LOG(INFO) << "dumped for hang debugging"; |
143 return 0; | 144 return 0; |
144 } | 145 } |
145 | 146 |
146 MSVC_POP_WARNING() | 147 MSVC_POP_WARNING() |
147 MSVC_ENABLE_OPTIMIZE() | 148 MSVC_ENABLE_OPTIMIZE() |
148 | 149 |
| 150 // Enables tracing of all operations on kernel handles. |
| 151 void EnableHandleTracing() { |
| 152 typedef NTSTATUS (WINAPI *NtSetInformationProcessFn)( |
| 153 HANDLE ProcessHandle, |
| 154 ULONG ProcessInformationClass, |
| 155 PVOID ProcessInformation, |
| 156 ULONG ProcessInformationLength); |
| 157 |
| 158 typedef struct _PROCESS_HANDLE_TRACING_ENABLE_EX { |
| 159 ULONG Flags; |
| 160 ULONG TotalSlots; |
| 161 } PROCESS_HANDLE_TRACING_ENABLE_EX, *PPROCESS_HANDLE_TRACING_ENABLE_EX; |
| 162 |
| 163 const ULONG kProcessHandleTracing = 0x20; |
| 164 |
| 165 NtSetInformationProcessFn set_information_process = |
| 166 reinterpret_cast<NtSetInformationProcessFn>( |
| 167 GetProcAddress(GetModuleHandle(L"ntdll.dll"), |
| 168 "NtSetInformationProcess")); |
| 169 |
| 170 // Enable handle tracing. It is OK to ignore the returned error code since |
| 171 // failing ot enable handle tracing is debug-only facility and should not |
| 172 // affect other functionality. |
| 173 if (set_information_process != NULL) { |
| 174 PROCESS_HANDLE_TRACING_ENABLE_EX info = { 0, 0x20000 }; |
| 175 set_information_process(GetCurrentProcess(), kProcessHandleTracing, &info, |
| 176 sizeof(info)); |
| 177 } |
| 178 } |
| 179 |
149 // Injects a thread into a remote process to dump state when there is no crash. | 180 // Injects a thread into a remote process to dump state when there is no crash. |
150 extern "C" HANDLE __declspec(dllexport) __cdecl | 181 extern "C" HANDLE __declspec(dllexport) __cdecl |
151 InjectDumpProcessWithoutCrash(HANDLE process) { | 182 InjectDumpProcessWithoutCrash(HANDLE process) { |
152 return CreateRemoteThread(process, NULL, 0, DumpProcessWithoutCrashThread, | 183 return CreateRemoteThread(process, NULL, 0, DumpProcessWithoutCrashThread, |
153 0, 0, NULL); | 184 0, 0, NULL); |
154 } | 185 } |
155 | 186 |
156 extern "C" HANDLE __declspec(dllexport) __cdecl | 187 extern "C" HANDLE __declspec(dllexport) __cdecl |
157 InjectDumpForHangDebugging(HANDLE process) { | 188 InjectDumpForHangDebugging(HANDLE process) { |
158 return CreateRemoteThread(process, NULL, 0, DumpForHangDebuggingThread, | 189 return CreateRemoteThread(process, NULL, 0, DumpForHangDebuggingThread, |
(...skipping 745 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
904 // are different because the message struct contains a pointer. As | 935 // are different because the message struct contains a pointer. As |
905 // a result, there are two different named pipes to connect to. The | 936 // a result, there are two different named pipes to connect to. The |
906 // 64-bit one is distinguished with an "-x64" suffix. | 937 // 64-bit one is distinguished with an "-x64" suffix. |
907 pipe_name += L"-x64"; | 938 pipe_name += L"-x64"; |
908 #endif | 939 #endif |
909 | 940 |
910 // Get the alternate dump directory. We use the temp path. | 941 // Get the alternate dump directory. We use the temp path. |
911 wchar_t temp_dir[MAX_PATH] = {0}; | 942 wchar_t temp_dir[MAX_PATH] = {0}; |
912 ::GetTempPathW(MAX_PATH, temp_dir); | 943 ::GetTempPathW(MAX_PATH, temp_dir); |
913 | 944 |
| 945 // Do not enable handle tracing (and do not generate STATUS_INVALID_HANDLE |
| 946 // exceptions when using an invalid handle) by default. |
| 947 bool enable_handle_tracing = false; |
| 948 |
914 MINIDUMP_TYPE dump_type = kSmallDumpType; | 949 MINIDUMP_TYPE dump_type = kSmallDumpType; |
915 // Capture full memory if explicitly instructed to. | 950 // Capture full memory if explicitly instructed to. |
916 if (command.HasSwitch(switches::kFullMemoryCrashReport)) { | 951 if (command.HasSwitch(switches::kFullMemoryCrashReport)) { |
917 dump_type = kFullDumpType; | 952 dump_type = kFullDumpType; |
| 953 enable_handle_tracing = true; |
918 } else { | 954 } else { |
919 std::wstring channel_name( | 955 std::wstring channel_name( |
920 GoogleUpdateSettings::GetChromeChannel(!is_per_user_install)); | 956 GoogleUpdateSettings::GetChromeChannel(!is_per_user_install)); |
921 | 957 |
922 // Capture more detail in crash dumps for beta and dev channel builds. | 958 // Enable handle tracing and capture more detail in crash dumps for canary |
923 if (channel_name == L"dev" || channel_name == L"beta" || | 959 // and dev channel builds. |
924 channel_name == GoogleChromeSxSDistribution::ChannelName()) | 960 if (channel_name == L"dev" || |
| 961 channel_name == GoogleChromeSxSDistribution::ChannelName()) { |
| 962 dump_type = kLargerDumpType; |
| 963 enable_handle_tracing = true; |
| 964 } |
| 965 |
| 966 // Capture more detail in crash dumps for beta builds. |
| 967 if (channel_name == L"beta") |
925 dump_type = kLargerDumpType; | 968 dump_type = kLargerDumpType; |
926 } | 969 } |
927 | 970 |
| 971 #if !defined(NDEBUG) |
| 972 // Enable handle tracing for all debug builds. |
| 973 enable_handle_tracing = true; |
| 974 #endif // !defined(NDEBUG) |
| 975 |
928 g_breakpad = new google_breakpad::ExceptionHandler(temp_dir, &FilterCallback, | 976 g_breakpad = new google_breakpad::ExceptionHandler(temp_dir, &FilterCallback, |
929 callback, NULL, | 977 callback, NULL, |
930 google_breakpad::ExceptionHandler::HANDLER_ALL, | 978 google_breakpad::ExceptionHandler::HANDLER_ALL, |
931 dump_type, pipe_name.c_str(), custom_info); | 979 dump_type, pipe_name.c_str(), custom_info); |
932 | 980 |
933 // Now initialize the non crash dump handler. | 981 // Now initialize the non crash dump handler. |
934 g_dumphandler_no_crash = new google_breakpad::ExceptionHandler(temp_dir, | 982 g_dumphandler_no_crash = new google_breakpad::ExceptionHandler(temp_dir, |
935 &FilterCallbackWhenNoCrash, | 983 &FilterCallbackWhenNoCrash, |
936 &DumpDoneCallbackWhenNoCrash, | 984 &DumpDoneCallbackWhenNoCrash, |
937 NULL, | 985 NULL, |
938 // Set the handler to none so this handler would not be added to | 986 // Set the handler to none so this handler would not be added to |
939 // |handler_stack_| in |ExceptionHandler| which is a list of exception | 987 // |handler_stack_| in |ExceptionHandler| which is a list of exception |
940 // handlers. | 988 // handlers. |
941 google_breakpad::ExceptionHandler::HANDLER_NONE, | 989 google_breakpad::ExceptionHandler::HANDLER_NONE, |
942 dump_type, pipe_name.c_str(), custom_info); | 990 dump_type, pipe_name.c_str(), custom_info); |
943 | 991 |
944 if (command.HasSwitch(switches::kPerformCrashAnalysis)) | 992 if (command.HasSwitch(switches::kPerformCrashAnalysis)) |
945 g_crash_analysis = new CrashAnalysis(); | 993 g_crash_analysis = new CrashAnalysis(); |
946 | 994 |
947 if (g_breakpad->IsOutOfProcess()) { | 995 if (g_breakpad->IsOutOfProcess()) { |
948 // Tells breakpad to handle breakpoint and single step exceptions. | 996 // Tells breakpad to handle breakpoint and single step exceptions. |
949 // This might break JIT debuggers, but at least it will always | 997 // This might break JIT debuggers, but at least it will always |
950 // generate a crashdump for these exceptions. | 998 // generate a crashdump for these exceptions. |
951 g_breakpad->set_handle_debug_exceptions(true); | 999 g_breakpad->set_handle_debug_exceptions(true); |
952 } | 1000 } |
| 1001 |
| 1002 if (enable_handle_tracing) |
| 1003 EnableHandleTracing(); |
953 } | 1004 } |
954 | 1005 |
955 void InitDefaultCrashCallback(LPTOP_LEVEL_EXCEPTION_FILTER filter) { | 1006 void InitDefaultCrashCallback(LPTOP_LEVEL_EXCEPTION_FILTER filter) { |
956 previous_filter = SetUnhandledExceptionFilter(filter); | 1007 previous_filter = SetUnhandledExceptionFilter(filter); |
957 } | 1008 } |
958 | 1009 |
959 void StringVectorToCStringVector(const std::vector<std::wstring>& wstrings, | 1010 void StringVectorToCStringVector(const std::vector<std::wstring>& wstrings, |
960 std::vector<const wchar_t*>* cstrings) { | 1011 std::vector<const wchar_t*>* cstrings) { |
961 cstrings->clear(); | 1012 cstrings->clear(); |
962 cstrings->reserve(wstrings.size()); | 1013 cstrings->reserve(wstrings.size()); |
963 for (size_t i = 0; i < wstrings.size(); ++i) | 1014 for (size_t i = 0; i < wstrings.size(); ++i) |
964 cstrings->push_back(wstrings[i].c_str()); | 1015 cstrings->push_back(wstrings[i].c_str()); |
965 } | 1016 } |
OLD | NEW |