OLD | NEW |
---|---|
(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/memory/scoped_ptr.h" | |
9 #include "base/path_service.h" | |
10 #include "base/strings/string16.h" | |
11 #include "base/strings/utf_string_conversions.h" | |
12 #include "components/crash/content/app/crash_reporter_client.h" | |
13 #include "third_party/crashpad/crashpad/client/crashpad_client.h" | |
14 | |
15 namespace crash_reporter { | |
16 namespace internal { | |
17 | |
18 base::FilePath PlatformCrashpadInitialization(bool initial_client, | |
19 bool browser_process) { | |
20 base::FilePath database_path; // Only valid in the browser process. | |
21 crashpad::CrashpadClient crashpad_client; | |
22 bool result; | |
23 | |
24 static const char kPipeNameVar[] = "CHROME_CRASHPAD_PIPE_NAME"; | |
25 scoped_ptr<base::Environment> env(base::Environment::Create()); | |
26 | |
27 DCHECK_EQ(initial_client, browser_process); | |
28 | |
29 if (initial_client) { | |
30 CrashReporterClient* crash_reporter_client = GetCrashReporterClient(); | |
31 crash_reporter_client->GetCrashDumpLocation(&database_path); | |
32 | |
33 base::FilePath exe_file; | |
34 CHECK(PathService::Get(base::FILE_EXE, &exe_file)); | |
35 base::string16 product_name, version, special_build, channel_name; | |
36 crash_reporter_client->GetProductNameAndVersion( | |
37 exe_file, &product_name, &version, &special_build, &channel_name); | |
38 std::map<std::string, std::string> process_annotations; | |
39 process_annotations["prod"] = base::UTF16ToUTF8(product_name); | |
40 process_annotations["ver"] = base::UTF16ToUTF8(version); | |
41 #if defined(ARCH_CPU_X86) | |
42 process_annotations["plat"] = std::string("Win32"); | |
43 #else | |
44 process_annotations["plat"] = std::string("Win64"); | |
45 #endif | |
46 std::string url = "https://clients2.google.com/cr/report"; | |
47 | |
48 std::vector<std::string> arguments; | |
49 arguments.push_back("--crashpad_handler"); | |
50 | |
51 result = crashpad_client.StartHandler(exe_file, database_path, url, | |
52 process_annotations, arguments, true); | |
53 | |
54 // If we're the browser, push the pipe name into the environment so child | |
55 // processes can connect to it. | |
56 DCHECK(!env->HasVar(kPipeNameVar)); | |
57 env->SetVar(kPipeNameVar, | |
58 base::UTF16ToUTF8(crashpad_client.GetHandlerIPCPipe())); | |
59 } else { | |
60 std::string pipe_name_utf8; | |
61 result = env->GetVar(kPipeNameVar, &pipe_name_utf8); | |
62 if (result) { | |
63 result = | |
64 crashpad_client.SetHandlerIPCPipe(base::UTF8ToUTF16(pipe_name_utf8)); | |
65 } | |
66 } | |
67 | |
68 if (result) { | |
69 result = crashpad_client.UseHandler(); | |
70 CHECK(result); | |
71 } | |
72 | |
73 return database_path; | |
74 } | |
75 | |
76 #ifdef _WIN64 | |
scottmg
2015/11/07 00:39:43
This is mostly unchanged from breakpad integration
| |
77 int CrashForExceptionInNonABICompliantCodeRange( | |
78 PEXCEPTION_RECORD ExceptionRecord, | |
79 ULONG64 EstablisherFrame, | |
80 PCONTEXT ContextRecord, | |
81 PDISPATCHER_CONTEXT DispatcherContext) { | |
82 EXCEPTION_POINTERS info = { ExceptionRecord, ContextRecord }; | |
83 return CrashForException(&info); | |
84 } | |
85 | |
86 struct ExceptionHandlerRecord { | |
87 RUNTIME_FUNCTION runtime_function; | |
88 UNWIND_INFO unwind_info; | |
89 unsigned char thunk[12]; | |
90 }; | |
91 | |
92 // These are GetProcAddress()d from V8 binding code. | |
93 extern "C" void __declspec(dllexport) __cdecl | |
94 RegisterNonABICompliantCodeRange(void* start, size_t size_in_bytes) { | |
95 ExceptionHandlerRecord* record = | |
96 reinterpret_cast<ExceptionHandlerRecord*>(start); | |
97 | |
98 // We assume that the first page of the code range is executable and | |
99 // committed and reserved for breakpad. What could possibly go wrong? | |
100 | |
101 // All addresses are 32bit relative offsets to start. | |
102 record->runtime_function.BeginAddress = 0; | |
103 record->runtime_function.EndAddress = | |
104 base::checked_cast<DWORD>(size_in_bytes); | |
105 record->runtime_function.UnwindData = | |
106 offsetof(ExceptionHandlerRecord, unwind_info); | |
107 | |
108 // Create unwind info that only specifies an exception handler. | |
109 record->unwind_info.Version = 1; | |
110 record->unwind_info.Flags = UNW_FLAG_EHANDLER; | |
111 record->unwind_info.SizeOfProlog = 0; | |
112 record->unwind_info.CountOfCodes = 0; | |
113 record->unwind_info.FrameRegister = 0; | |
114 record->unwind_info.FrameOffset = 0; | |
115 record->unwind_info.ExceptionHandler = | |
116 offsetof(ExceptionHandlerRecord, thunk); | |
117 | |
118 // Hardcoded thunk. | |
119 // mov imm64, rax | |
120 record->thunk[0] = 0x48; | |
121 record->thunk[1] = 0xb8; | |
122 void* handler = &CrashForExceptionInNonABICompliantCodeRange; | |
123 memcpy(&record->thunk[2], &handler, 8); | |
124 | |
125 // jmp rax | |
126 record->thunk[10] = 0xff; | |
127 record->thunk[11] = 0xe0; | |
128 | |
129 // Protect reserved page against modifications. | |
130 DWORD old_protect; | |
131 CHECK(VirtualProtect( | |
132 start, sizeof(ExceptionHandlerRecord), PAGE_EXECUTE_READ, &old_protect)); | |
133 CHECK(RtlAddFunctionTable( | |
134 &record->runtime_function, 1, reinterpret_cast<DWORD64>(start))); | |
135 } | |
136 | |
137 extern "C" void __declspec(dllexport) __cdecl | |
138 UnregisterNonABICompliantCodeRange(void* start) { | |
139 ExceptionHandlerRecord* record = | |
140 reinterpret_cast<ExceptionHandlerRecord*>(start); | |
141 | |
142 CHECK(RtlDeleteFunctionTable(&record->runtime_function)); | |
143 } | |
144 #endif | |
145 | |
146 } // namespace internal | |
147 } // namespace crash_reporter | |
OLD | NEW |