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

Side by Side Diff: components/crash/content/app/crashpad_win.cc

Issue 1416133003: Crashpad Windows: Use the Crashpad client instead of Breakpad on Windows (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: gn secondary, mac .S not on windows Created 5 years, 1 month 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
OLDNEW
(Empty)
1 // Copyright 2015 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 #include "components/crash/content/app/crashpad.h"
6
7 #include "base/environment.h"
8 #include "base/lazy_instance.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/numerics/safe_conversions.h"
11 #include "base/path_service.h"
12 #include "base/strings/string16.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "build/build_config.h"
16 #include "components/crash/content/app/crash_reporter_client.h"
17 #include "third_party/crashpad/crashpad/client/crashpad_client.h"
18 #include "third_party/crashpad/crashpad/client/crashpad_info.h"
19
20 namespace crash_reporter {
21 namespace internal {
22
23 namespace {
24
25 base::LazyInstance<crashpad::CrashpadClient>::Leaky g_crashpad_client =
26 LAZY_INSTANCE_INITIALIZER;
27
28 } // namespace
29
30 base::FilePath PlatformCrashpadInitialization(bool initial_client,
31 bool browser_process) {
32 base::FilePath database_path; // Only valid in the browser process.
33 bool result;
34
35 const char kPipeNameVar[] = "CHROME_CRASHPAD_PIPE_NAME";
36 scoped_ptr<base::Environment> env(base::Environment::Create());
37
38 DCHECK_EQ(initial_client, browser_process);
39
40 if (initial_client) {
41 CrashReporterClient* crash_reporter_client = GetCrashReporterClient();
42 crash_reporter_client->GetCrashDumpLocation(&database_path);
43
44 base::FilePath exe_file;
45 CHECK(PathService::Get(base::FILE_EXE, &exe_file));
46 base::string16 product_name, version, special_build, channel_name;
47 crash_reporter_client->GetProductNameAndVersion(
48 exe_file, &product_name, &version, &special_build, &channel_name);
49 std::map<std::string, std::string> process_annotations;
50 process_annotations["prod"] = base::UTF16ToUTF8(product_name);
51 process_annotations["ver"] = base::UTF16ToUTF8(version);
52 process_annotations["channel"] = base::UTF16ToUTF8(channel_name);
53 if (!special_build.empty())
54 process_annotations["special"] = base::UTF16ToUTF8(special_build);
55 #if defined(ARCH_CPU_X86)
56 process_annotations["plat"] = std::string("Win32");
57 #elif defined(ARCH_CPU_X86_64)
58 process_annotations["plat"] = std::string("Win64");
59 #endif
60 #if defined(GOOGLE_CHROME_BUILD)
61 std::string url = "https://clients2.google.com/cr/report";
62 #else
63 std::string url = "";
Mark Mentovai 2015/11/19 22:21:38 Without the = "" should be slightly cheaper.
scottmg 2015/11/20 19:52:48 Done.
64 #endif
65
66 std::vector<std::string> arguments;
67
68 // In test binaries, use crashpad_handler directly. Otherwise, we launch
69 // chrome.exe with --type=crashpad-handler.
70 if (exe_file.BaseName().value() != FILE_PATH_LITERAL("chrome.exe")) {
71 base::FilePath exe_dir;
72 CHECK(PathService::Get(base::DIR_EXE, &exe_dir));
73 exe_file = exe_dir.Append(FILE_PATH_LITERAL("crashpad_handler.exe"));
74 } else {
75 arguments.push_back("--type=crashpad-handler");
76 }
77
78 result = g_crashpad_client.Get().StartHandler(
79 exe_file, database_path, url, process_annotations, arguments, false);
80
81 // If we're the browser, push the pipe name into the environment so child
82 // processes can connect to it.
83 DCHECK(!env->HasVar(kPipeNameVar));
Mark Mentovai 2015/11/19 22:21:37 If the browser restarts itself (like after a chang
scottmg 2015/11/20 19:52:48 Possibly. It looks like some similar failures in b
Mark Mentovai 2015/11/20 20:00:23 scottmg wrote:
scottmg 2015/11/20 21:30:10 OK, makes sense. In the test case, it's browser_te
84 env->SetVar(kPipeNameVar,
85 base::UTF16ToUTF8(g_crashpad_client.Get().GetHandlerIPCPipe()));
86 } else {
87 std::string pipe_name_utf8;
88 result = env->GetVar(kPipeNameVar, &pipe_name_utf8);
89 if (result) {
90 result = g_crashpad_client.Get().SetHandlerIPCPipe(
91 base::UTF8ToUTF16(pipe_name_utf8));
92 }
93 }
94
95 if (result) {
96 result = g_crashpad_client.Get().UseHandler();
97 }
98
99 return database_path;
100 }
101
102 // Crashes the process after generating a dump for the provided exception. Note
103 // that the crash reporter should be initialized before calling this function
104 // for it to do anything.
105 // NOTE: This function is used by SyzyASAN to invoke a crash. If you change the
106 // the name or signature of this function you will break SyzyASAN instrumented
107 // releases of Chrome. Please contact syzygy-team@chromium.org before doing so!
108 extern "C" int __declspec(dllexport) CrashForException(
Mark Mentovai 2015/11/19 22:21:37 This and the other functions after this point (exc
scottmg 2015/11/20 19:52:48 Done.
109 EXCEPTION_POINTERS* info) {
110 g_crashpad_client.Get().DumpAndCrash(info);
111 return EXCEPTION_CONTINUE_SEARCH;
112 }
113
114 #if defined(ARCH_CPU_X86_64)
115 int CrashForExceptionInNonABICompliantCodeRange(
Mark Mentovai 2015/11/19 22:21:37 This can be in an anonymous namespace.
scottmg 2015/11/20 19:52:48 How about static because of the inter-function cal
116 PEXCEPTION_RECORD ExceptionRecord,
117 ULONG64 EstablisherFrame,
118 PCONTEXT ContextRecord,
119 PDISPATCHER_CONTEXT DispatcherContext) {
120 EXCEPTION_POINTERS info = { ExceptionRecord, ContextRecord };
121 return CrashForException(&info);
122 }
123
124 // See https://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
125 typedef struct _UNWIND_INFO {
126 unsigned char Version : 3;
127 unsigned char Flags : 5;
128 unsigned char SizeOfProlog;
129 unsigned char CountOfCodes;
130 unsigned char FrameRegister : 4;
131 unsigned char FrameOffset : 4;
132 ULONG ExceptionHandler;
133 } UNWIND_INFO, *PUNWIND_INFO;
134
135 struct ExceptionHandlerRecord {
136 RUNTIME_FUNCTION runtime_function;
137 UNWIND_INFO unwind_info;
138 unsigned char thunk[12];
139 };
140
141 // These are GetProcAddress()d from V8 binding code.
142 extern "C" void __declspec(dllexport) __cdecl
143 RegisterNonABICompliantCodeRange(void* start, size_t size_in_bytes) {
144 ExceptionHandlerRecord* record =
145 reinterpret_cast<ExceptionHandlerRecord*>(start);
146
147 // We assume that the first page of the code range is executable and
148 // committed and reserved for breakpad. What could possibly go wrong?
149
150 // All addresses are 32bit relative offsets to start.
151 record->runtime_function.BeginAddress = 0;
152 record->runtime_function.EndAddress =
153 base::checked_cast<DWORD>(size_in_bytes);
154 record->runtime_function.UnwindData =
155 offsetof(ExceptionHandlerRecord, unwind_info);
156
157 // Create unwind info that only specifies an exception handler.
158 record->unwind_info.Version = 1;
159 record->unwind_info.Flags = UNW_FLAG_EHANDLER;
160 record->unwind_info.SizeOfProlog = 0;
161 record->unwind_info.CountOfCodes = 0;
162 record->unwind_info.FrameRegister = 0;
163 record->unwind_info.FrameOffset = 0;
164 record->unwind_info.ExceptionHandler =
165 offsetof(ExceptionHandlerRecord, thunk);
166
167 // Hardcoded thunk.
168 // mov imm64, rax
169 record->thunk[0] = 0x48;
170 record->thunk[1] = 0xb8;
171 void* handler = &CrashForExceptionInNonABICompliantCodeRange;
172 memcpy(&record->thunk[2], &handler, 8);
173
174 // jmp rax
175 record->thunk[10] = 0xff;
176 record->thunk[11] = 0xe0;
177
178 // Protect reserved page against modifications.
179 DWORD old_protect;
180 CHECK(VirtualProtect(
181 start, sizeof(ExceptionHandlerRecord), PAGE_EXECUTE_READ, &old_protect));
182 CHECK(RtlAddFunctionTable(
183 &record->runtime_function, 1, reinterpret_cast<DWORD64>(start)));
184 }
185
186 extern "C" void __declspec(dllexport) __cdecl
187 UnregisterNonABICompliantCodeRange(void* start) {
188 ExceptionHandlerRecord* record =
189 reinterpret_cast<ExceptionHandlerRecord*>(start);
190
191 CHECK(RtlDeleteFunctionTable(&record->runtime_function));
192 }
193 #endif // ARCH_CPU_X86_64
194
195 } // namespace internal
196 } // namespace crash_reporter
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698