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/browser/crash_handler_host_linux.h" | 5 #include "chrome/browser/crash_handler_host_linux.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 #include <stdlib.h> | 8 #include <stdlib.h> |
9 #include <sys/socket.h> | 9 #include <sys/socket.h> |
10 #include <sys/syscall.h> | 10 #include <sys/syscall.h> |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 void CrashHandlerHostLinux::OnFileCanReadWithoutBlocking(int fd) { | 121 void CrashHandlerHostLinux::OnFileCanReadWithoutBlocking(int fd) { |
122 DCHECK_EQ(fd, browser_socket_); | 122 DCHECK_EQ(fd, browser_socket_); |
123 | 123 |
124 // A process has crashed and has signaled us by writing a datagram | 124 // A process has crashed and has signaled us by writing a datagram |
125 // to the death signal socket. The datagram contains the crash context needed | 125 // to the death signal socket. The datagram contains the crash context needed |
126 // for writing the minidump as well as a file descriptor and a credentials | 126 // for writing the minidump as well as a file descriptor and a credentials |
127 // block so that they can't lie about their pid. | 127 // block so that they can't lie about their pid. |
128 // | 128 // |
129 // The message sender is in chrome/app/breakpad_linux.cc. | 129 // The message sender is in chrome/app/breakpad_linux.cc. |
130 | 130 |
| 131 #if !defined(ADDRESS_SANITIZER) |
131 const size_t kIovSize = 8; | 132 const size_t kIovSize = 8; |
| 133 #else |
| 134 const size_t kIovSize = 9; |
| 135 #endif |
| 136 |
132 struct msghdr msg = {0}; | 137 struct msghdr msg = {0}; |
133 struct iovec iov[kIovSize]; | 138 struct iovec iov[kIovSize]; |
134 | 139 |
135 // Freed in WriteDumpFile(); | 140 // Freed in WriteDumpFile(); |
136 char* crash_context = new char[kCrashContextSize]; | 141 char* crash_context = new char[kCrashContextSize]; |
137 // Freed in CrashDumpTask(); | 142 // Freed in CrashDumpTask(); |
138 char* guid = new char[kGuidSize + 1]; | 143 char* guid = new char[kGuidSize + 1]; |
139 char* crash_url = new char[kMaxActiveURLSize + 1]; | 144 char* crash_url = new char[kMaxActiveURLSize + 1]; |
140 char* distro = new char[kDistroSize + 1]; | 145 char* distro = new char[kDistroSize + 1]; |
| 146 #if defined(ADDRESS_SANITIZER) |
| 147 asan_report_str_ = new char[kMaxAsanReportSize + 1]; |
| 148 #endif |
141 | 149 |
142 char* tid_buf_addr = NULL; | 150 char* tid_buf_addr = NULL; |
143 int tid_fd = -1; | 151 int tid_fd = -1; |
144 uint64_t uptime; | 152 uint64_t uptime; |
145 size_t oom_size; | 153 size_t oom_size; |
146 char control[kControlMsgSize]; | 154 char control[kControlMsgSize]; |
147 const ssize_t expected_msg_size = | 155 const ssize_t expected_msg_size = |
148 kCrashContextSize + | 156 kCrashContextSize + |
149 kGuidSize + 1 + | 157 kGuidSize + 1 + |
150 kMaxActiveURLSize + 1 + | 158 kMaxActiveURLSize + 1 + |
151 kDistroSize + 1 + | 159 kDistroSize + 1 + |
152 sizeof(tid_buf_addr) + sizeof(tid_fd) + | 160 sizeof(tid_buf_addr) + sizeof(tid_fd) + |
153 sizeof(uptime) + | 161 sizeof(uptime) + |
| 162 #if defined(ADDRESS_SANITIZER) |
| 163 kMaxAsanReportSize + 1 + |
| 164 #endif |
154 sizeof(oom_size); | 165 sizeof(oom_size); |
155 | |
156 iov[0].iov_base = crash_context; | 166 iov[0].iov_base = crash_context; |
157 iov[0].iov_len = kCrashContextSize; | 167 iov[0].iov_len = kCrashContextSize; |
158 iov[1].iov_base = guid; | 168 iov[1].iov_base = guid; |
159 iov[1].iov_len = kGuidSize + 1; | 169 iov[1].iov_len = kGuidSize + 1; |
160 iov[2].iov_base = crash_url; | 170 iov[2].iov_base = crash_url; |
161 iov[2].iov_len = kMaxActiveURLSize + 1; | 171 iov[2].iov_len = kMaxActiveURLSize + 1; |
162 iov[3].iov_base = distro; | 172 iov[3].iov_base = distro; |
163 iov[3].iov_len = kDistroSize + 1; | 173 iov[3].iov_len = kDistroSize + 1; |
164 iov[4].iov_base = &tid_buf_addr; | 174 iov[4].iov_base = &tid_buf_addr; |
165 iov[4].iov_len = sizeof(tid_buf_addr); | 175 iov[4].iov_len = sizeof(tid_buf_addr); |
166 iov[5].iov_base = &tid_fd; | 176 iov[5].iov_base = &tid_fd; |
167 iov[5].iov_len = sizeof(tid_fd); | 177 iov[5].iov_len = sizeof(tid_fd); |
168 iov[6].iov_base = &uptime; | 178 iov[6].iov_base = &uptime; |
169 iov[6].iov_len = sizeof(uptime); | 179 iov[6].iov_len = sizeof(uptime); |
170 iov[7].iov_base = &oom_size; | 180 iov[7].iov_base = &oom_size; |
171 iov[7].iov_len = sizeof(oom_size); | 181 iov[7].iov_len = sizeof(oom_size); |
| 182 #if defined(ADDRESS_SANITIZER) |
| 183 iov[8].iov_base = asan_report_str_; |
| 184 iov[8].iov_len = kMaxAsanReportSize + 1; |
| 185 #endif |
172 msg.msg_iov = iov; | 186 msg.msg_iov = iov; |
173 msg.msg_iovlen = kIovSize; | 187 msg.msg_iovlen = kIovSize; |
174 msg.msg_control = control; | 188 msg.msg_control = control; |
175 msg.msg_controllen = kControlMsgSize; | 189 msg.msg_controllen = kControlMsgSize; |
176 | 190 |
177 const ssize_t msg_size = HANDLE_EINTR(recvmsg(browser_socket_, &msg, 0)); | 191 const ssize_t msg_size = HANDLE_EINTR(recvmsg(browser_socket_, &msg, 0)); |
178 if (msg_size != expected_msg_size) { | 192 if (msg_size != expected_msg_size) { |
179 LOG(ERROR) << "Error reading from death signal socket. Crash dumping" | 193 LOG(ERROR) << "Error reading from death signal socket. Crash dumping" |
180 << " is disabled." | 194 << " is disabled." |
181 << " msg_size:" << msg_size | 195 << " msg_size:" << msg_size |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 info->guid = guid; | 337 info->guid = guid; |
324 | 338 |
325 info->distro_length = strlen(distro); | 339 info->distro_length = strlen(distro); |
326 info->distro = distro; | 340 info->distro = distro; |
327 #if defined(OS_ANDROID) | 341 #if defined(OS_ANDROID) |
328 // Nothing gets uploaded in android. | 342 // Nothing gets uploaded in android. |
329 info->upload = false; | 343 info->upload = false; |
330 #else | 344 #else |
331 info->upload = (getenv(env_vars::kHeadless) == NULL); | 345 info->upload = (getenv(env_vars::kHeadless) == NULL); |
332 #endif | 346 #endif |
| 347 |
| 348 #if defined(ADDRESS_SANITIZER) |
| 349 info->asan_report_str = asan_report_str_; |
| 350 info->asan_report_length = strlen(asan_report_str_); |
| 351 #endif |
333 info->process_start_time = uptime; | 352 info->process_start_time = uptime; |
334 info->oom_size = oom_size; | 353 info->oom_size = oom_size; |
335 | 354 |
336 BrowserThread::PostTask( | 355 BrowserThread::PostTask( |
337 BrowserThread::FILE, FROM_HERE, | 356 BrowserThread::FILE, FROM_HERE, |
338 base::Bind(&CrashHandlerHostLinux::WriteDumpFile, | 357 base::Bind(&CrashHandlerHostLinux::WriteDumpFile, |
339 base::Unretained(this), | 358 base::Unretained(this), |
340 info, | 359 info, |
341 crashing_pid, | 360 crashing_pid, |
342 crash_context, | 361 crash_context, |
343 signal_fd)); | 362 signal_fd)); |
344 } | 363 } |
345 | 364 |
346 void CrashHandlerHostLinux::WriteDumpFile(BreakpadInfo* info, | 365 void CrashHandlerHostLinux::WriteDumpFile(BreakpadInfo* info, |
347 pid_t crashing_pid, | 366 pid_t crashing_pid, |
348 char* crash_context, | 367 char* crash_context, |
349 int signal_fd) { | 368 int signal_fd) { |
350 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 369 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
351 | 370 |
352 FilePath dumps_path("/tmp"); | 371 FilePath dumps_path("/tmp"); |
353 PathService::Get(base::DIR_TEMP, &dumps_path); | 372 PathService::Get(base::DIR_TEMP, &dumps_path); |
354 if (!info->upload) | 373 if (!info->upload) |
355 PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path); | 374 PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path); |
356 const uint64 rand = base::RandUint64(); | 375 const uint64 rand = base::RandUint64(); |
357 const std::string minidump_filename = | 376 const std::string minidump_filename = |
358 base::StringPrintf("%s/chromium-%s-minidump-%016" PRIx64 ".dmp", | 377 base::StringPrintf("%s/chromium-%s-minidump-%016" PRIx64 ".dmp", |
359 dumps_path.value().c_str(), | 378 dumps_path.value().c_str(), |
360 process_type_.c_str(), | 379 process_type_.c_str(), |
361 rand); | 380 rand); |
| 381 |
362 if (!google_breakpad::WriteMinidump(minidump_filename.c_str(), | 382 if (!google_breakpad::WriteMinidump(minidump_filename.c_str(), |
363 crashing_pid, crash_context, | 383 crashing_pid, crash_context, |
364 kCrashContextSize)) { | 384 kCrashContextSize)) { |
365 LOG(ERROR) << "Failed to write crash dump for pid " << crashing_pid; | 385 LOG(ERROR) << "Failed to write crash dump for pid " << crashing_pid; |
366 } | 386 } |
| 387 #if defined(ADDRESS_SANITIZER) |
| 388 // Create a temporary file holding the AddressSanitizer report. |
| 389 const std::string log_filename = |
| 390 base::StringPrintf("%s/chromium-%s-minidump-%016" PRIx64 ".log", |
| 391 dumps_path.value().c_str(), |
| 392 process_type_.c_str(), |
| 393 rand); |
| 394 FILE* logfile = fopen(log_filename.c_str(), "w"); |
| 395 CHECK(logfile); |
| 396 fprintf(logfile, "%s", asan_report_str_); |
| 397 fclose(logfile); |
| 398 #endif |
| 399 |
367 delete[] crash_context; | 400 delete[] crash_context; |
368 | 401 |
369 // Freed in CrashDumpTask(); | 402 // Freed in CrashDumpTask(); |
370 char* minidump_filename_str = new char[minidump_filename.length() + 1]; | 403 char* minidump_filename_str = new char[minidump_filename.length() + 1]; |
371 minidump_filename.copy(minidump_filename_str, minidump_filename.length()); | 404 minidump_filename.copy(minidump_filename_str, minidump_filename.length()); |
372 minidump_filename_str[minidump_filename.length()] = '\0'; | 405 minidump_filename_str[minidump_filename.length()] = '\0'; |
373 info->filename = minidump_filename_str; | 406 info->filename = minidump_filename_str; |
| 407 #if defined(ADDRESS_SANITIZER) |
| 408 char* minidump_log_filename_str = new char[minidump_filename.length() + 1]; |
| 409 minidump_filename.copy(minidump_log_filename_str, minidump_filename.length()); |
| 410 memcpy(minidump_log_filename_str + minidump_filename.length() - 3, "log", 3); |
| 411 minidump_log_filename_str[minidump_filename.length()] = '\0'; |
| 412 info->log_filename = minidump_log_filename_str; |
| 413 #endif |
374 info->pid = crashing_pid; | 414 info->pid = crashing_pid; |
375 | 415 |
376 BrowserThread::PostTask( | 416 BrowserThread::PostTask( |
377 BrowserThread::IO, FROM_HERE, | 417 BrowserThread::IO, FROM_HERE, |
378 base::Bind(&CrashHandlerHostLinux::QueueCrashDumpTask, | 418 base::Bind(&CrashHandlerHostLinux::QueueCrashDumpTask, |
379 base::Unretained(this), | 419 base::Unretained(this), |
380 info, | 420 info, |
381 signal_fd)); | 421 signal_fd)); |
382 } | 422 } |
383 | 423 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
486 } | 526 } |
487 | 527 |
488 void RendererCrashHandlerHostLinux::SetProcessType() { | 528 void RendererCrashHandlerHostLinux::SetProcessType() { |
489 process_type_ = "renderer"; | 529 process_type_ = "renderer"; |
490 } | 530 } |
491 | 531 |
492 // static | 532 // static |
493 RendererCrashHandlerHostLinux* RendererCrashHandlerHostLinux::GetInstance() { | 533 RendererCrashHandlerHostLinux* RendererCrashHandlerHostLinux::GetInstance() { |
494 return Singleton<RendererCrashHandlerHostLinux>::get(); | 534 return Singleton<RendererCrashHandlerHostLinux>::get(); |
495 } | 535 } |
OLD | NEW |