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/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/utf_string_conversions.h" | |
14 #include "components/crash/content/app/crash_reporter_client.h" | |
15 #include "third_party/crashpad/crashpad/client/crashpad_client.h" | |
16 | |
17 namespace crash_reporter { | |
18 namespace internal { | |
19 | |
20 base::LazyInstance<crashpad::CrashpadClient>::Leaky g_crashpad_client = | |
21 LAZY_INSTANCE_INITIALIZER; | |
22 | |
23 base::FilePath PlatformCrashpadInitialization(bool initial_client, | |
24 bool browser_process) { | |
25 base::FilePath database_path; // Only valid in the browser process. | |
26 bool result; | |
27 | |
28 static const char kPipeNameVar[] = "CHROME_CRASHPAD_PIPE_NAME"; | |
Mark Mentovai
2015/11/10 17:21:17
static’s not helping (maybe not really hurting eit
scottmg
2015/11/16 21:48:40
Done.
| |
29 scoped_ptr<base::Environment> env(base::Environment::Create()); | |
30 | |
31 DCHECK_EQ(initial_client, browser_process); | |
32 | |
33 if (initial_client) { | |
34 CrashReporterClient* crash_reporter_client = GetCrashReporterClient(); | |
35 crash_reporter_client->GetCrashDumpLocation(&database_path); | |
36 | |
37 base::FilePath exe_file; | |
38 CHECK(PathService::Get(base::FILE_EXE, &exe_file)); | |
39 base::string16 product_name, version, special_build, channel_name; | |
40 crash_reporter_client->GetProductNameAndVersion( | |
41 exe_file, &product_name, &version, &special_build, &channel_name); | |
42 std::map<std::string, std::string> process_annotations; | |
43 process_annotations["prod"] = base::UTF16ToUTF8(product_name); | |
Mark Mentovai
2015/11/10 17:21:18
It looks like components/crash/content/app/crash_k
scottmg
2015/11/16 21:48:40
Hmm, yeah, that's a bit sticky. I guess I found a
| |
44 process_annotations["ver"] = base::UTF16ToUTF8(version); | |
45 #if defined(ARCH_CPU_X86) | |
Mark Mentovai
2015/11/10 17:21:17
build/build_config.h
scottmg
2015/11/16 21:48:40
Done.
| |
46 process_annotations["plat"] = std::string("Win32"); | |
47 #else | |
Mark Mentovai
2015/11/10 17:21:18
#elif defined(ARCH_CPU_X86_64)
scottmg
2015/11/16 21:48:40
Done.
| |
48 process_annotations["plat"] = std::string("Win64"); | |
49 #endif | |
50 std::string url = "https://clients2.google.com/cr/report"; | |
Mark Mentovai
2015/11/10 17:21:17
In GOOGLE_CHROME_BUILD + OFFICIAL_BUILD only, othe
scottmg
2015/11/16 21:48:40
Done (Not OFFICIAL_BUILD, that's an optimization s
Mark Mentovai
2015/11/16 22:11:13
scottmg wrote:
| |
51 | |
52 std::vector<std::string> arguments; | |
Mark Mentovai
2015/11/10 17:21:18
(1, std::string("--crashpad_handler"))
scottmg
2015/11/16 21:48:40
Done.
| |
53 arguments.push_back("--crashpad_handler"); | |
54 | |
55 result = g_crashpad_client.Get().StartHandler( | |
56 exe_file, database_path, url, process_annotations, arguments, true); | |
57 | |
58 // If we're the browser, push the pipe name into the environment so child | |
59 // processes can connect to it. | |
60 DCHECK(!env->HasVar(kPipeNameVar)); | |
61 env->SetVar(kPipeNameVar, | |
62 base::UTF16ToUTF8(g_crashpad_client.Get().GetHandlerIPCPipe())); | |
63 } else { | |
64 std::string pipe_name_utf8; | |
65 result = env->GetVar(kPipeNameVar, &pipe_name_utf8); | |
66 if (result) { | |
67 result = g_crashpad_client.Get().SetHandlerIPCPipe( | |
68 base::UTF8ToUTF16(pipe_name_utf8)); | |
69 } | |
70 } | |
71 | |
72 if (result) { | |
73 result = g_crashpad_client.Get().UseHandler(); | |
74 CHECK(result); | |
Mark Mentovai
2015/11/10 17:21:18
CHECK() seems a little heavy-handed. You didn’t CH
scottmg
2015/11/16 21:48:40
Agreed, it seems unnecessary now, and I can't thin
| |
75 } | |
76 | |
77 return database_path; | |
78 } | |
79 | |
80 // Crashes the process after generating a dump for the provided exception. Note | |
81 // that the crash reporter should be initialized before calling this function | |
82 // for it to do anything. | |
83 // NOTE: This function is used by SyzyASAN to invoke a crash. If you change the | |
84 // the name or signature of this function you will break SyzyASAN instrumented | |
85 // releases of Chrome. Please contact syzygy-team@chromium.org before doing so! | |
86 extern "C" int __declspec(dllexport) CrashForException( | |
87 EXCEPTION_POINTERS* info) { | |
88 g_crashpad_client.Get().DumpAndCrash(info); | |
89 return EXCEPTION_CONTINUE_SEARCH; | |
90 } | |
91 | |
92 #ifdef _WIN64 | |
Mark Mentovai
2015/11/10 17:21:17
ARCH_CPU_X86_64
scottmg
2015/11/16 21:48:40
Done.
| |
93 int CrashForExceptionInNonABICompliantCodeRange( | |
94 PEXCEPTION_RECORD ExceptionRecord, | |
95 ULONG64 EstablisherFrame, | |
96 PCONTEXT ContextRecord, | |
97 PDISPATCHER_CONTEXT DispatcherContext) { | |
98 EXCEPTION_POINTERS info = { ExceptionRecord, ContextRecord }; | |
99 return CrashForException(&info); | |
100 } | |
101 | |
102 // See http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx | |
Mark Mentovai
2015/11/10 17:21:18
https
scottmg
2015/11/16 21:48:40
Done.
| |
103 typedef struct _UNWIND_INFO { | |
104 unsigned char Version : 3; | |
105 unsigned char Flags : 5; | |
106 unsigned char SizeOfProlog; | |
107 unsigned char CountOfCodes; | |
108 unsigned char FrameRegister : 4; | |
109 unsigned char FrameOffset : 4; | |
110 ULONG ExceptionHandler; | |
111 } UNWIND_INFO, *PUNWIND_INFO; | |
112 | |
113 struct ExceptionHandlerRecord { | |
114 RUNTIME_FUNCTION runtime_function; | |
115 UNWIND_INFO unwind_info; | |
116 unsigned char thunk[12]; | |
117 }; | |
118 | |
119 // These are GetProcAddress()d from V8 binding code. | |
120 extern "C" void __declspec(dllexport) __cdecl | |
121 RegisterNonABICompliantCodeRange(void* start, size_t size_in_bytes) { | |
122 ExceptionHandlerRecord* record = | |
123 reinterpret_cast<ExceptionHandlerRecord*>(start); | |
124 | |
125 // We assume that the first page of the code range is executable and | |
126 // committed and reserved for breakpad. What could possibly go wrong? | |
127 | |
128 // All addresses are 32bit relative offsets to start. | |
129 record->runtime_function.BeginAddress = 0; | |
130 record->runtime_function.EndAddress = | |
131 base::checked_cast<DWORD>(size_in_bytes); | |
132 record->runtime_function.UnwindData = | |
133 offsetof(ExceptionHandlerRecord, unwind_info); | |
134 | |
135 // Create unwind info that only specifies an exception handler. | |
136 record->unwind_info.Version = 1; | |
137 record->unwind_info.Flags = UNW_FLAG_EHANDLER; | |
138 record->unwind_info.SizeOfProlog = 0; | |
139 record->unwind_info.CountOfCodes = 0; | |
140 record->unwind_info.FrameRegister = 0; | |
141 record->unwind_info.FrameOffset = 0; | |
142 record->unwind_info.ExceptionHandler = | |
143 offsetof(ExceptionHandlerRecord, thunk); | |
144 | |
145 // Hardcoded thunk. | |
146 // mov imm64, rax | |
147 record->thunk[0] = 0x48; | |
148 record->thunk[1] = 0xb8; | |
149 void* handler = &CrashForExceptionInNonABICompliantCodeRange; | |
150 memcpy(&record->thunk[2], &handler, 8); | |
151 | |
152 // jmp rax | |
153 record->thunk[10] = 0xff; | |
154 record->thunk[11] = 0xe0; | |
155 | |
cpu_(ooo_6.6-7.5)
2015/11/10 03:06:50
oh this brings back memories... carry on ...
scottmg
2015/11/16 21:48:40
I don't understand any of this, so I'm glad you're
| |
156 // Protect reserved page against modifications. | |
157 DWORD old_protect; | |
158 CHECK(VirtualProtect( | |
159 start, sizeof(ExceptionHandlerRecord), PAGE_EXECUTE_READ, &old_protect)); | |
160 CHECK(RtlAddFunctionTable( | |
161 &record->runtime_function, 1, reinterpret_cast<DWORD64>(start))); | |
162 } | |
163 | |
164 extern "C" void __declspec(dllexport) __cdecl | |
165 UnregisterNonABICompliantCodeRange(void* start) { | |
166 ExceptionHandlerRecord* record = | |
167 reinterpret_cast<ExceptionHandlerRecord*>(start); | |
168 | |
169 CHECK(RtlDeleteFunctionTable(&record->runtime_function)); | |
170 } | |
171 #endif | |
172 | |
173 } // namespace internal | |
174 } // namespace crash_reporter | |
OLD | NEW |