OLD | NEW |
---|---|
1 // Copyright (c) 2010 Google Inc. | 1 // Copyright (c) 2010 Google Inc. |
2 // All rights reserved. | 2 // All rights reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
205 signal(sig, SIG_DFL); | 205 signal(sig, SIG_DFL); |
206 #endif | 206 #endif |
207 } | 207 } |
208 | 208 |
209 // The global exception handler stack. This is needed because there may exist | 209 // The global exception handler stack. This is needed because there may exist |
210 // multiple ExceptionHandler instances in a process. Each will have itself | 210 // multiple ExceptionHandler instances in a process. Each will have itself |
211 // registered in this stack. | 211 // registered in this stack. |
212 std::vector<ExceptionHandler*>* g_handler_stack_ = NULL; | 212 std::vector<ExceptionHandler*>* g_handler_stack_ = NULL; |
213 pthread_mutex_t g_handler_stack_mutex_ = PTHREAD_MUTEX_INITIALIZER; | 213 pthread_mutex_t g_handler_stack_mutex_ = PTHREAD_MUTEX_INITIALIZER; |
214 | 214 |
215 // sizeof(CrashContext) can be too big w.r.t the size of alternatate stack | |
216 // for SignalHandler(). Keep the crash context as a .bss field. Exception | |
217 // handlers are serialized by the |g_handler_stack_mutex_| and at most one at a | |
218 // time can use |g_crash_context_|. | |
219 ExceptionHandler::CrashContext g_crash_context_; | |
220 | |
215 } // namespace | 221 } // namespace |
216 | 222 |
217 // Runs before crashing: normal context. | 223 // Runs before crashing: normal context. |
218 ExceptionHandler::ExceptionHandler(const MinidumpDescriptor& descriptor, | 224 ExceptionHandler::ExceptionHandler(const MinidumpDescriptor& descriptor, |
219 FilterCallback filter, | 225 FilterCallback filter, |
220 MinidumpCallback callback, | 226 MinidumpCallback callback, |
221 void* callback_context, | 227 void* callback_context, |
222 bool install_handler, | 228 bool install_handler, |
223 const int server_fd) | 229 const int server_fd) |
224 : filter_(filter), | 230 : filter_(filter), |
225 callback_(callback), | 231 callback_(callback), |
226 callback_context_(callback_context), | 232 callback_context_(callback_context), |
227 minidump_descriptor_(descriptor), | 233 minidump_descriptor_(descriptor), |
228 crash_handler_(NULL) { | 234 crash_handler_(NULL) { |
229 if (server_fd >= 0) | 235 if (server_fd >= 0) |
230 crash_generation_client_.reset(CrashGenerationClient::TryCreate(server_fd)); | 236 crash_generation_client_.reset(CrashGenerationClient::TryCreate(server_fd)); |
231 | 237 |
232 if (!IsOutOfProcess() && !minidump_descriptor_.IsFD() && | 238 if (!IsOutOfProcess() && !minidump_descriptor_.IsFD() && |
233 !minidump_descriptor_.IsMicrodumpOnConsole()) | 239 !minidump_descriptor_.IsMicrodumpOnConsole()) |
234 minidump_descriptor_.UpdatePath(); | 240 minidump_descriptor_.UpdatePath(); |
235 | 241 |
236 #if defined(__ANDROID__) | 242 #if defined(__ANDROID__) |
237 if (minidump_descriptor_.IsMicrodumpOnConsole()) | 243 if (minidump_descriptor_.IsMicrodumpOnConsole()) |
238 logger::initializeCrashLogWriter(); | 244 logger::initializeCrashLogWriter(); |
239 #endif | 245 #endif |
240 | 246 |
241 pthread_mutex_lock(&g_handler_stack_mutex_); | 247 pthread_mutex_lock(&g_handler_stack_mutex_); |
248 | |
249 // Pre-fault the crash context struct. This is to avoid failing due to OOM | |
Mark Mentovai
2015/09/18 22:13:20
Smart.
| |
250 // if handling an exception when the process ran out of virtual memory. | |
251 memset(&g_crash_context_, 0, sizeof(g_crash_context_)); | |
252 | |
242 if (!g_handler_stack_) | 253 if (!g_handler_stack_) |
243 g_handler_stack_ = new std::vector<ExceptionHandler*>; | 254 g_handler_stack_ = new std::vector<ExceptionHandler*>; |
244 if (install_handler) { | 255 if (install_handler) { |
245 InstallAlternateStackLocked(); | 256 InstallAlternateStackLocked(); |
246 InstallHandlersLocked(); | 257 InstallHandlersLocked(); |
247 } | 258 } |
248 g_handler_stack_->push_back(this); | 259 g_handler_stack_->push_back(this); |
249 pthread_mutex_unlock(&g_handler_stack_mutex_); | 260 pthread_mutex_unlock(&g_handler_stack_mutex_); |
250 } | 261 } |
251 | 262 |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
417 if (filter_ && !filter_(callback_context_)) | 428 if (filter_ && !filter_(callback_context_)) |
418 return false; | 429 return false; |
419 | 430 |
420 // Allow ourselves to be dumped if the signal is trusted. | 431 // Allow ourselves to be dumped if the signal is trusted. |
421 bool signal_trusted = info->si_code > 0; | 432 bool signal_trusted = info->si_code > 0; |
422 bool signal_pid_trusted = info->si_code == SI_USER || | 433 bool signal_pid_trusted = info->si_code == SI_USER || |
423 info->si_code == SI_TKILL; | 434 info->si_code == SI_TKILL; |
424 if (signal_trusted || (signal_pid_trusted && info->si_pid == getpid())) { | 435 if (signal_trusted || (signal_pid_trusted && info->si_pid == getpid())) { |
425 sys_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); | 436 sys_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); |
426 } | 437 } |
427 CrashContext context; | 438 |
428 // Fill in all the holes in the struct to make Valgrind happy. | 439 // Fill in all the holes in the struct to make Valgrind happy. |
429 memset(&context, 0, sizeof(context)); | 440 memset(&g_crash_context_, 0, sizeof(g_crash_context_)); |
Mark Mentovai
2015/09/18 22:13:20
Necessary? You already wrote zeroes into it when y
Primiano Tucci (use gerrit)
2015/09/18 22:22:40
Right, should be safe from the production code any
Mark Mentovai
2015/09/18 22:34:56
Primiano Tucci wrote:
| |
430 memcpy(&context.siginfo, info, sizeof(siginfo_t)); | 441 memcpy(&g_crash_context_.siginfo, info, sizeof(siginfo_t)); |
431 memcpy(&context.context, uc, sizeof(struct ucontext)); | 442 memcpy(&g_crash_context_.context, uc, sizeof(struct ucontext)); |
432 #if defined(__aarch64__) | 443 #if defined(__aarch64__) |
433 struct ucontext *uc_ptr = (struct ucontext*)uc; | 444 struct ucontext* uc_ptr = (struct ucontext*)uc; |
434 struct fpsimd_context *fp_ptr = | 445 struct fpsimd_context* fp_ptr = |
435 (struct fpsimd_context*)&uc_ptr->uc_mcontext.__reserved; | 446 (struct fpsimd_context*)&uc_ptr->uc_mcontext.__reserved; |
436 if (fp_ptr->head.magic == FPSIMD_MAGIC) { | 447 if (fp_ptr->head.magic == FPSIMD_MAGIC) { |
437 memcpy(&context.float_state, fp_ptr, sizeof(context.float_state)); | 448 memcpy(&g_crash_context_.float_state, fp_ptr, |
449 sizeof(g_crash_context_.float_state)); | |
438 } | 450 } |
439 #elif !defined(__ARM_EABI__) && !defined(__mips__) | 451 #elif !defined(__ARM_EABI__) && !defined(__mips__) |
440 // FP state is not part of user ABI on ARM Linux. | 452 // FP state is not part of user ABI on ARM Linux. |
441 // In case of MIPS Linux FP state is already part of struct ucontext | 453 // In case of MIPS Linux FP state is already part of struct ucontext |
442 // and 'float_state' is not a member of CrashContext. | 454 // and 'float_state' is not a member of CrashContext. |
443 struct ucontext *uc_ptr = (struct ucontext*)uc; | 455 struct ucontext* uc_ptr = (struct ucontext*)uc; |
444 if (uc_ptr->uc_mcontext.fpregs) { | 456 if (uc_ptr->uc_mcontext.fpregs) { |
445 memcpy(&context.float_state, | 457 memcpy(&g_crash_context_.float_state, uc_ptr->uc_mcontext.fpregs, |
446 uc_ptr->uc_mcontext.fpregs, | 458 sizeof(g_crash_context_.float_state)); |
447 sizeof(context.float_state)); | |
448 } | 459 } |
449 #endif | 460 #endif |
450 context.tid = syscall(__NR_gettid); | 461 g_crash_context_.tid = syscall(__NR_gettid); |
451 if (crash_handler_ != NULL) { | 462 if (crash_handler_ != NULL) { |
452 if (crash_handler_(&context, sizeof(context), callback_context_)) { | 463 if (crash_handler_(&g_crash_context_, sizeof(g_crash_context_), |
464 callback_context_)) { | |
453 return true; | 465 return true; |
454 } | 466 } |
455 } | 467 } |
456 return GenerateDump(&context); | 468 return GenerateDump(&g_crash_context_); |
457 } | 469 } |
458 | 470 |
459 // This is a public interface to HandleSignal that allows the client to | 471 // This is a public interface to HandleSignal that allows the client to |
460 // generate a crash dump. This function may run in a compromised context. | 472 // generate a crash dump. This function may run in a compromised context. |
461 bool ExceptionHandler::SimulateSignalDelivery(int sig) { | 473 bool ExceptionHandler::SimulateSignalDelivery(int sig) { |
462 siginfo_t siginfo = {}; | 474 siginfo_t siginfo = {}; |
463 // Mimic a trusted signal to allow tracing the process (see | 475 // Mimic a trusted signal to allow tracing the process (see |
464 // ExceptionHandler::HandleSignal(). | 476 // ExceptionHandler::HandleSignal(). |
465 siginfo.si_code = SI_USER; | 477 siginfo.si_code = SI_USER; |
466 siginfo.si_pid = getpid(); | 478 siginfo.si_pid = getpid(); |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
745 descriptor.UpdatePath(); | 757 descriptor.UpdatePath(); |
746 if (!google_breakpad::WriteMinidump(descriptor.path(), | 758 if (!google_breakpad::WriteMinidump(descriptor.path(), |
747 child, | 759 child, |
748 child_blamed_thread)) | 760 child_blamed_thread)) |
749 return false; | 761 return false; |
750 | 762 |
751 return callback ? callback(descriptor, callback_context, true) : true; | 763 return callback ? callback(descriptor, callback_context, true) : true; |
752 } | 764 } |
753 | 765 |
754 } // namespace google_breakpad | 766 } // namespace google_breakpad |
OLD | NEW |