Chromium Code Reviews| 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 |