1 // Copyright (c) 2010 Google Inc. 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above 11 // copyright notice, this list of conditions and the following disclaimer 12 // in the documentation and/or other materials provided with the 13 // distribution. 14 // * Neither the name of Google Inc. nor the names of its 15 // contributors may be used to endorse or promote products derived from 16 // this software without specific prior written permission. 17 // 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30 // The ExceptionHandler object installs signal handlers for a number of 31 // signals. We rely on the signal handler running on the thread which crashed 32 // in order to identify it. This is true of the synchronous signals (SEGV etc), 33 // but not true of ABRT. Thus, if you send ABRT to yourself in a program which 34 // uses ExceptionHandler, you need to use tgkill to direct it to the current 35 // thread. 36 // 37 // The signal flow looks like this: 38 // 39 // SignalHandler (uses a global stack of ExceptionHandler objects to find 40 // | one to handle the signal. If the first rejects it, try 41 // | the second etc...) 42 // V 43 // HandleSignal ----------------------------| (clones a new process which 44 // | | shares an address space with 45 // (wait for cloned | the crashed process. This 46 // process) | allows us to ptrace the crashed 47 // | | process) 48 // V V 49 // (set signal handler to ThreadEntry (static function to bounce 50 // SIG_DFL and rethrow, | back into the object) 51 // killing the crashed | 52 // process) V 53 // DoDump (writes minidump) 54 // | 55 // V 56 // sys_exit 57 // 58 59 // This code is a little fragmented. Different functions of the ExceptionHandler 60 // class run in a number of different contexts. Some of them run in a normal 61 // context and are easy to code, others run in a compromised context and the 62 // restrictions at the top of minidump_writer.cc apply: no libc and use the 63 // alternative malloc. Each function should have comment above it detailing the 64 // context which it runs in. 65 66 #include "client/linux/handler/exception_handler.h" 67 68 #include <errno.h> 69 #include <fcntl.h> 70 #include <linux/limits.h> 71 #include <pthread.h> 72 #include <sched.h> 73 #include <signal.h> 74 #include <stdio.h> 75 #include <sys/mman.h> 76 #include <sys/prctl.h> 77 #include <sys/syscall.h> 78 #include <sys/wait.h> 79 #include <unistd.h> 80 81 #include <sys/signal.h> 82 #include <sys/ucontext.h> 83 #include <sys/user.h> 84 #include <ucontext.h> 85 86 #include <algorithm> 87 #include <utility> 88 #include <vector> 89 90 #include "common/basictypes.h" 91 #include "common/linux/linux_libc_support.h" 92 #include "common/memory.h" 93 #include "client/linux/log/log.h" 94 #include "client/linux/microdump_writer/microdump_writer.h" 95 #include "client/linux/minidump_writer/linux_dumper.h" 96 #include "client/linux/minidump_writer/minidump_writer.h" 97 #include "common/linux/eintr_wrapper.h" 98 #include "third_party/lss/linux_syscall_support.h" 99 100 #if defined(__ANDROID__) 101 #include "linux/sched.h" 102 #endif 103 104 #ifndef PR_SET_PTRACER 105 #define PR_SET_PTRACER 0x59616d61 106 #endif 107 108 // A wrapper for the tgkill syscall: send a signal to a specific thread. 109 static int tgkill(pid_t tgid, pid_t tid, int sig) { 110 return syscall(__NR_tgkill, tgid, tid, sig); 111 return 0; 112 } 113 114 namespace google_breakpad { 115 116 namespace { 117 // The list of signals which we consider to be crashes. The default action for 118 // all these signals must be Core (see man 7 signal) because we rethrow the 119 // signal after handling it and expect that it'll be fatal. 120 const int kExceptionSignals[] = { 121 SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS 122 }; 123 const int kNumHandledSignals = 124 sizeof(kExceptionSignals) / sizeof(kExceptionSignals[0]); 125 struct sigaction old_handlers[kNumHandledSignals]; 126 bool handlers_installed = false; 127 128 // InstallAlternateStackLocked will store the newly installed stack in new_stack 129 // and (if it exists) the previously installed stack in old_stack. 130 stack_t old_stack; 131 stack_t new_stack; 132 bool stack_installed = false; 133 134 // Create an alternative stack to run the signal handlers on. This is done since 135 // the signal might have been caused by a stack overflow. 136 // Runs before crashing: normal context. 137 void InstallAlternateStackLocked() { 138 if (stack_installed) 139 return; 140 141 memset(&old_stack, 0, sizeof(old_stack)); 142 memset(&new_stack, 0, sizeof(new_stack)); 143 144 // SIGSTKSZ may be too small to prevent the signal handlers from overrunning 145 // the alternative stack. Ensure that the size of the alternative stack is 146 // large enough. 147 static const unsigned kSigStackSize = std::max(16384, SIGSTKSZ); 148 149 // Only set an alternative stack if there isn't already one, or if the current 150 // one is too small. 151 if (sys_sigaltstack(NULL, &old_stack) == -1 || !old_stack.ss_sp || 152 old_stack.ss_size < kSigStackSize) { 153 new_stack.ss_sp = calloc(1, kSigStackSize); 154 new_stack.ss_size = kSigStackSize; 155 156 if (sys_sigaltstack(&new_stack, NULL) == -1) { 157 free(new_stack.ss_sp); 158 return; 159 } 160 stack_installed = true; 161 } 162 } 163 164 // Runs before crashing: normal context. 165 void RestoreAlternateStackLocked() { 166 if (!stack_installed) 167 return; 168 169 stack_t current_stack; 170 if (sys_sigaltstack(NULL, ¤t_stack) == -1) 171 return; 172 173 // Only restore the old_stack if the current alternative stack is the one 174 // installed by the call to InstallAlternateStackLocked. 175 if (current_stack.ss_sp == new_stack.ss_sp) { 176 if (old_stack.ss_sp) { 177 if (sys_sigaltstack(&old_stack, NULL) == -1) 178 return; 179 } else { 180 stack_t disable_stack; 181 disable_stack.ss_flags = SS_DISABLE; 182 if (sys_sigaltstack(&disable_stack, NULL) == -1) 183 return; 184 } 185 } 186 187 free(new_stack.ss_sp); 188 stack_installed = false; 189 } 190 191 void InstallDefaultHandler(int sig) { 192 #if defined(__ANDROID__) 193 // Android L+ expose signal and sigaction symbols that override the system 194 // ones. There is a bug in these functions where a request to set the handler 195 // to SIG_DFL is ignored. In that case, an infinite loop is entered as the 196 // signal is repeatedly sent to breakpad's signal handler. 197 // To work around this, directly call the system's sigaction. 198 struct sigaction sa; 199 memset(&sa, 0, sizeof(sa)); 200 sigemptyset(&sa.sa_mask); 201 sa.sa_handler = SIG_DFL; 202 sa.sa_flags = SA_RESTART; 203 syscall(__NR_rt_sigaction, sig, &sa, NULL); 204 #else 205 signal(sig, SIG_DFL); 206 #endif 207 } 208 209 // The global exception handler stack. This is needed because there may exist 210 // multiple ExceptionHandler instances in a process. Each will have itself 211 // registered in this stack. 212 std::vector<ExceptionHandler*>* g_handler_stack_ = NULL; 213 pthread_mutex_t g_handler_stack_mutex_ = PTHREAD_MUTEX_INITIALIZER; 214 215 } // namespace 216 217 // Runs before crashing: normal context. 218 ExceptionHandler::ExceptionHandler(const MinidumpDescriptor& descriptor, 219 FilterCallback filter, 220 MinidumpCallback callback, 221 void* callback_context, 222 bool install_handler, 223 const int server_fd) 224 : filter_(filter), 225 callback_(callback), 226 callback_context_(callback_context), 227 minidump_descriptor_(descriptor), 228 crash_handler_(NULL) { 229 if (server_fd >= 0) 230 crash_generation_client_.reset(CrashGenerationClient::TryCreate(server_fd)); 231 232 if (!IsOutOfProcess() && !minidump_descriptor_.IsFD() && 233 !minidump_descriptor_.IsMicrodumpOnConsole()) 234 minidump_descriptor_.UpdatePath(); 235 236 pthread_mutex_lock(&g_handler_stack_mutex_); 237 if (!g_handler_stack_) 238 g_handler_stack_ = new std::vector<ExceptionHandler*>; 239 if (install_handler) { 240 InstallAlternateStackLocked(); 241 InstallHandlersLocked(); 242 } 243 g_handler_stack_->push_back(this); 244 pthread_mutex_unlock(&g_handler_stack_mutex_); 245 } 246 247 // Runs before crashing: normal context. 248 ExceptionHandler::~ExceptionHandler() { 249 pthread_mutex_lock(&g_handler_stack_mutex_); 250 std::vector<ExceptionHandler*>::iterator handler = 251 std::find(g_handler_stack_->begin(), g_handler_stack_->end(), this); 252 g_handler_stack_->erase(handler); 253 if (g_handler_stack_->empty()) { 254 delete g_handler_stack_; 255 g_handler_stack_ = NULL; 256 RestoreAlternateStackLocked(); 257 RestoreHandlersLocked(); 258 } 259 pthread_mutex_unlock(&g_handler_stack_mutex_); 260 } 261 262 // Runs before crashing: normal context. 263 // static 264 bool ExceptionHandler::InstallHandlersLocked() { 265 if (handlers_installed) 266 return false; 267 268 // Fail if unable to store all the old handlers. 269 for (int i = 0; i < kNumHandledSignals; ++i) { 270 if (sigaction(kExceptionSignals[i], NULL, &old_handlers[i]) == -1) 271 return false; 272 } 273 274 struct sigaction sa; 275 memset(&sa, 0, sizeof(sa)); 276 sigemptyset(&sa.sa_mask); 277 278 // Mask all exception signals when we're handling one of them. 279 for (int i = 0; i < kNumHandledSignals; ++i) 280 sigaddset(&sa.sa_mask, kExceptionSignals[i]); 281 282 sa.sa_sigaction = SignalHandler; 283 sa.sa_flags = SA_ONSTACK | SA_SIGINFO; 284 285 for (int i = 0; i < kNumHandledSignals; ++i) { 286 if (sigaction(kExceptionSignals[i], &sa, NULL) == -1) { 287 // At this point it is impractical to back out changes, and so failure to 288 // install a signal is intentionally ignored. 289 } 290 } 291 handlers_installed = true; 292 return true; 293 } 294 295 // This function runs in a compromised context: see the top of the file. 296 // Runs on the crashing thread. 297 // static 298 void ExceptionHandler::RestoreHandlersLocked() { 299 if (!handlers_installed) 300 return; 301 302 for (int i = 0; i < kNumHandledSignals; ++i) { 303 if (sigaction(kExceptionSignals[i], &old_handlers[i], NULL) == -1) { 304 InstallDefaultHandler(kExceptionSignals[i]); 305 } 306 } 307 handlers_installed = false; 308 } 309 310 // void ExceptionHandler::set_crash_handler(HandlerCallback callback) { 311 // crash_handler_ = callback; 312 // } 313 314 // This function runs in a compromised context: see the top of the file. 315 // Runs on the crashing thread. 316 // static 317 void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) { 318 // All the exception signals are blocked at this point. 319 pthread_mutex_lock(&g_handler_stack_mutex_); 320 321 // Sometimes, Breakpad runs inside a process where some other buggy code 322 // saves and restores signal handlers temporarily with 'signal' 323 // instead of 'sigaction'. This loses the SA_SIGINFO flag associated 324 // with this function. As a consequence, the values of 'info' and 'uc' 325 // become totally bogus, generally inducing a crash. 326 // 327 // The following code tries to detect this case. When it does, it 328 // resets the signal handlers with sigaction + SA_SIGINFO and returns. 329 // This forces the signal to be thrown again, but this time the kernel 330 // will call the function with the right arguments. 331 struct sigaction cur_handler; 332 if (sigaction(sig, NULL, &cur_handler) == 0 && 333 (cur_handler.sa_flags & SA_SIGINFO) == 0) { 334 // Reset signal handler with the right flags. 335 sigemptyset(&cur_handler.sa_mask); 336 sigaddset(&cur_handler.sa_mask, sig); 337 338 cur_handler.sa_sigaction = SignalHandler; 339 cur_handler.sa_flags = SA_ONSTACK | SA_SIGINFO; 340 341 if (sigaction(sig, &cur_handler, NULL) == -1) { 342 // When resetting the handler fails, try to reset the 343 // default one to avoid an infinite loop here. 344 InstallDefaultHandler(sig); 345 } 346 pthread_mutex_unlock(&g_handler_stack_mutex_); 347 return; 348 } 349 350 bool handled = false; 351 for (int i = g_handler_stack_->size() - 1; !handled && i >= 0; --i) { 352 handled = (*g_handler_stack_)[i]->HandleSignal(sig, info, uc); 353 } 354 355 // Upon returning from this signal handler, sig will become unmasked and then 356 // it will be retriggered. If one of the ExceptionHandlers handled it 357 // successfully, restore the default handler. Otherwise, restore the 358 // previously installed handler. Then, when the signal is retriggered, it will 359 // be delivered to the appropriate handler. 360 if (handled) { 361 InstallDefaultHandler(sig); 362 } else { 363 RestoreHandlersLocked(); 364 } 365 366 pthread_mutex_unlock(&g_handler_stack_mutex_); 367 368 if (info->si_pid || sig == SIGABRT) { 369 // This signal was triggered by somebody sending us the signal with kill(). 370 // In order to retrigger it, we have to queue a new signal by calling 371 // kill() ourselves. The special case (si_pid == 0 && sig == SIGABRT) is 372 // due to the kernel sending a SIGABRT from a user request via SysRQ. 373 if (tgkill(getpid(), syscall(__NR_gettid), sig) < 0) { 374 // If we failed to kill ourselves (e.g. because a sandbox disallows us 375 // to do so), we instead resort to terminating our process. This will 376 // result in an incorrect exit code. 377 _exit(1); 378 } 379 } else { 380 // This was a synchronous signal triggered by a hard fault (e.g. SIGSEGV). 381 // No need to reissue the signal. It will automatically trigger again, 382 // when we return from the signal handler. 383 } 384 } 385 386 struct ThreadArgument { 387 pid_t pid; // the crashing process 388 const MinidumpDescriptor* minidump_descriptor; 389 ExceptionHandler* handler; 390 const void* context; // a CrashContext structure 391 size_t context_size; 392 }; 393 394 // This is the entry function for the cloned process. We are in a compromised 395 // context here: see the top of the file. 396 // static 397 int ExceptionHandler::ThreadEntry(void *arg) { 398 const ThreadArgument *thread_arg = reinterpret_cast<ThreadArgument*>(arg); 399 400 // Block here until the crashing process unblocks us when 401 // we're allowed to use ptrace 402 thread_arg->handler->WaitForContinueSignal(); 403 404 return thread_arg->handler->DoDump(thread_arg->pid, thread_arg->context, 405 thread_arg->context_size) == false; 406 } 407 408 // This function runs in a compromised context: see the top of the file. 409 // Runs on the crashing thread. 410 bool ExceptionHandler::HandleSignal(int sig, siginfo_t* info, void* uc) { 411 if (filter_ && !filter_(callback_context_)) 412 return false; 413 414 // Allow ourselves to be dumped if the signal is trusted. 415 bool signal_trusted = info->si_code > 0; 416 bool signal_pid_trusted = info->si_code == SI_USER || 417 info->si_code == SI_TKILL; 418 if (signal_trusted || (signal_pid_trusted && info->si_pid == getpid())) { 419 sys_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); 420 } 421 CrashContext context; 422 // Fill in all the holes in the struct to make Valgrind happy. 423 memset(&context, 0, sizeof(context)); 424 memcpy(&context.siginfo, info, sizeof(siginfo_t)); 425 memcpy(&context.context, uc, sizeof(struct ucontext)); 426 #if defined(__aarch64__) 427 struct ucontext *uc_ptr = (struct ucontext*)uc; 428 struct fpsimd_context *fp_ptr = 429 (struct fpsimd_context*)&uc_ptr->uc_mcontext.__reserved; 430 if (fp_ptr->head.magic == FPSIMD_MAGIC) { 431 memcpy(&context.float_state, fp_ptr, sizeof(context.float_state)); 432 } 433 #elif !defined(__ARM_EABI__) && !defined(__mips__) 434 // FP state is not part of user ABI on ARM Linux. 435 // In case of MIPS Linux FP state is already part of struct ucontext 436 // and 'float_state' is not a member of CrashContext. 437 struct ucontext *uc_ptr = (struct ucontext*)uc; 438 if (uc_ptr->uc_mcontext.fpregs) { 439 memcpy(&context.float_state, 440 uc_ptr->uc_mcontext.fpregs, 441 sizeof(context.float_state)); 442 } 443 #endif 444 context.tid = syscall(__NR_gettid); 445 if (crash_handler_ != NULL) { 446 if (crash_handler_(&context, sizeof(context), callback_context_)) { 447 return true; 448 } 449 } 450 return GenerateDump(&context); 451 } 452 453 // This is a public interface to HandleSignal that allows the client to 454 // generate a crash dump. This function may run in a compromised context. 455 bool ExceptionHandler::SimulateSignalDelivery(int sig) { 456 siginfo_t siginfo = {}; 457 // Mimic a trusted signal to allow tracing the process (see 458 // ExceptionHandler::HandleSignal(). 459 siginfo.si_code = SI_USER; 460 siginfo.si_pid = getpid(); 461 struct ucontext context; 462 getcontext(&context); 463 return HandleSignal(sig, &siginfo, &context); 464 } 465 466 // This function may run in a compromised context: see the top of the file. 467 bool ExceptionHandler::GenerateDump(CrashContext *context) { 468 if (IsOutOfProcess()) 469 return crash_generation_client_->RequestDump(context, sizeof(*context)); 470 471 // Allocating too much stack isn't a problem, and better to err on the side 472 // of caution than smash it into random locations. 473 static const unsigned kChildStackSize = 16000; 474 PageAllocator allocator; 475 uint8_t* stack = reinterpret_cast<uint8_t*>(allocator.Alloc(kChildStackSize)); 476 if (!stack) 477 return false; 478 // clone() needs the top-most address. (scrub just to be safe) 479 stack += kChildStackSize; 480 my_memset(stack - 16, 0, 16); 481 482 ThreadArgument thread_arg; 483 thread_arg.handler = this; 484 thread_arg.minidump_descriptor = &minidump_descriptor_; 485 thread_arg.pid = getpid(); 486 thread_arg.context = context; 487 thread_arg.context_size = sizeof(*context); 488 489 // We need to explicitly enable ptrace of parent processes on some 490 // kernels, but we need to know the PID of the cloned process before we 491 // can do this. Create a pipe here which we can use to block the 492 // cloned process after creating it, until we have explicitly enabled ptrace 493 if (sys_pipe(fdes) == -1) { 494 // Creating the pipe failed. We'll log an error but carry on anyway, 495 // as we'll probably still get a useful crash report. All that will happen 496 // is the write() and read() calls will fail with EBADF 497 static const char no_pipe_msg[] = "ExceptionHandler::GenerateDump " 498 "sys_pipe failed:"; 499 logger::write(no_pipe_msg, sizeof(no_pipe_msg) - 1); 500 logger::write(strerror(errno), strlen(strerror(errno))); 501 logger::write("\n", 1); 502 503 // Ensure fdes[0] and fdes[1] are invalid file descriptors. 504 fdes[0] = fdes[1] = -1; 505 } 506 507 const pid_t child = sys_clone( 508 ThreadEntry, stack, CLONE_FILES | CLONE_FS | CLONE_UNTRACED, 509 &thread_arg, NULL, NULL, NULL); 510 if (child == -1) { 511 sys_close(fdes[0]); 512 sys_close(fdes[1]); 513 return false; 514 } 515 516 // Allow the child to ptrace us 517 sys_prctl(PR_SET_PTRACER, child, 0, 0, 0); 518 SendContinueSignalToChild(); 519 int status; 520 const int r = HANDLE_EINTR(sys_waitpid(child, &status, __WALL)); 521 522 sys_close(fdes[0]); 523 sys_close(fdes[1]); 524 525 if (r == -1) { 526 static const char msg[] = "ExceptionHandler::GenerateDump waitpid failed:"; 527 logger::write(msg, sizeof(msg) - 1); 528 logger::write(strerror(errno), strlen(strerror(errno))); 529 logger::write("\n", 1); 530 } 531 532 bool success = r != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0; 533 if (callback_) 534 success = callback_(minidump_descriptor_, callback_context_, success); 535 return success; 536 } 537 538 // This function runs in a compromised context: see the top of the file. 539 void ExceptionHandler::SendContinueSignalToChild() { 540 static const char okToContinueMessage = 'a'; 541 int r; 542 r = HANDLE_EINTR(sys_write(fdes[1], &okToContinueMessage, sizeof(char))); 543 if (r == -1) { 544 static const char msg[] = "ExceptionHandler::SendContinueSignalToChild " 545 "sys_write failed:"; 546 logger::write(msg, sizeof(msg) - 1); 547 logger::write(strerror(errno), strlen(strerror(errno))); 548 logger::write("\n", 1); 549 } 550 } 551 552 // This function runs in a compromised context: see the top of the file. 553 // Runs on the cloned process. 554 void ExceptionHandler::WaitForContinueSignal() { 555 int r; 556 char receivedMessage; 557 r = HANDLE_EINTR(sys_read(fdes[0], &receivedMessage, sizeof(char))); 558 if (r == -1) { 559 static const char msg[] = "ExceptionHandler::WaitForContinueSignal " 560 "sys_read failed:"; 561 logger::write(msg, sizeof(msg) - 1); 562 logger::write(strerror(errno), strlen(strerror(errno))); 563 logger::write("\n", 1); 564 } 565 } 566 567 // This function runs in a compromised context: see the top of the file. 568 // Runs on the cloned process. 569 bool ExceptionHandler::DoDump(pid_t crashing_process, const void* context, 570 size_t context_size) { 571 if (minidump_descriptor_.IsMicrodumpOnConsole()) { 572 return google_breakpad::WriteMicrodump(crashing_process, 573 context, 574 context_size, 575 mapping_list_); 576 } 577 if (minidump_descriptor_.IsFD()) { 578 return google_breakpad::WriteMinidump(minidump_descriptor_.fd(), 579 minidump_descriptor_.size_limit(), 580 crashing_process, 581 context, 582 context_size, 583 mapping_list_, 584 app_memory_list_); 585 } 586 return google_breakpad::WriteMinidump(minidump_descriptor_.path(), 587 minidump_descriptor_.size_limit(), 588 crashing_process, 589 context, 590 context_size, 591 mapping_list_, 592 app_memory_list_); 593 } 594 595 // static 596 bool ExceptionHandler::WriteMinidump(const string& dump_path, 597 MinidumpCallback callback, 598 void* callback_context) { 599 MinidumpDescriptor descriptor(dump_path); 600 ExceptionHandler eh(descriptor, NULL, callback, callback_context, false, -1); 601 return eh.WriteMinidump(); 602 } 603 604 // In order to making using EBP to calculate the desired value for ESP 605 // a valid operation, ensure that this function is compiled with a 606 // frame pointer using the following attribute. This attribute 607 // is supported on GCC but not on clang. 608 #if defined(__i386__) && defined(__GNUC__) && !defined(__clang__) 609 __attribute__((optimize("no-omit-frame-pointer"))) 610 #endif 611 bool ExceptionHandler::WriteMinidump() { 612 if (!IsOutOfProcess() && !minidump_descriptor_.IsFD() && 613 !minidump_descriptor_.IsMicrodumpOnConsole()) { 614 // Update the path of the minidump so that this can be called multiple times 615 // and new files are created for each minidump. This is done before the 616 // generation happens, as clients may want to access the MinidumpDescriptor 617 // after this call to find the exact path to the minidump file. 618 minidump_descriptor_.UpdatePath(); 619 } else if (minidump_descriptor_.IsFD()) { 620 // Reposition the FD to its beginning and resize it to get rid of the 621 // previous minidump info. 622 lseek(minidump_descriptor_.fd(), 0, SEEK_SET); 623 ignore_result(ftruncate(minidump_descriptor_.fd(), 0)); 624 } 625 626 // Allow this process to be dumped. 627 sys_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); 628 629 CrashContext context; 630 int getcontext_result = getcontext(&context.context); 631 if (getcontext_result) 632 return false; 633 634 #if defined(__i386__) 635 // In CPUFillFromUContext in minidumpwriter.cc the stack pointer is retrieved 636 // from REG_UESP instead of from REG_ESP. REG_UESP is the user stack pointer 637 // and it only makes sense when running in kernel mode with a different stack 638 // pointer. When WriteMiniDump is called during normal processing REG_UESP is 639 // zero which leads to bad minidump files. 640 if (!context.context.uc_mcontext.gregs[REG_UESP]) { 641 // If REG_UESP is set to REG_ESP then that includes the stack space for the 642 // CrashContext object in this function, which is about 128 KB. Since the 643 // Linux dumper only records 32 KB of stack this would mean that nothing 644 // useful would be recorded. A better option is to set REG_UESP to REG_EBP, 645 // perhaps with a small negative offset in case there is any code that 646 // objects to them being equal. 647 context.context.uc_mcontext.gregs[REG_UESP] = 648 context.context.uc_mcontext.gregs[REG_EBP] - 16; 649 // The stack saving is based off of REG_ESP so it must be set to match the 650 // new REG_UESP. 651 context.context.uc_mcontext.gregs[REG_ESP] = 652 context.context.uc_mcontext.gregs[REG_UESP]; 653 } 654 #endif 655 656 #if !defined(__ARM_EABI__) && !defined(__aarch64__) && !defined(__mips__) 657 // FPU state is not part of ARM EABI ucontext_t. 658 memcpy(&context.float_state, context.context.uc_mcontext.fpregs, 659 sizeof(context.float_state)); 660 #endif 661 context.tid = sys_gettid(); 662 663 // Add an exception stream to the minidump for better reporting. 664 memset(&context.siginfo, 0, sizeof(context.siginfo)); 665 context.siginfo.si_signo = MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED; 666 #if defined(__i386__) 667 context.siginfo.si_addr = 668 reinterpret_cast<void*>(context.context.uc_mcontext.gregs[REG_EIP]); 669 #elif defined(__x86_64__) 670 context.siginfo.si_addr = 671 reinterpret_cast<void*>(context.context.uc_mcontext.gregs[REG_RIP]); 672 #elif defined(__arm__) 673 context.siginfo.si_addr = 674 reinterpret_cast<void*>(context.context.uc_mcontext.arm_pc); 675 #elif defined(__aarch64__) 676 context.siginfo.si_addr = 677 reinterpret_cast<void*>(context.context.uc_mcontext.pc); 678 #elif defined(__mips__) 679 context.siginfo.si_addr = 680 reinterpret_cast<void*>(context.context.uc_mcontext.pc); 681 #else 682 #error "This code has not been ported to your platform yet." 683 #endif 684 685 return GenerateDump(&context); 686 } 687 688 void ExceptionHandler::AddMappingInfo(const string& name, 689 const uint8_t identifier[sizeof(MDGUID)], 690 uintptr_t start_address, 691 size_t mapping_size, 692 size_t file_offset) { 693 MappingInfo info; 694 info.start_addr = start_address; 695 info.size = mapping_size; 696 info.offset = file_offset; 697 strncpy(info.name, name.c_str(), sizeof(info.name) - 1); 698 info.name[sizeof(info.name) - 1] = '\0'; 699 700 MappingEntry mapping; 701 mapping.first = info; 702 memcpy(mapping.second, identifier, sizeof(MDGUID)); 703 mapping_list_.push_back(mapping); 704 } 705 706 void ExceptionHandler::RegisterAppMemory(void* ptr, size_t length) { 707 AppMemoryList::iterator iter = 708 std::find(app_memory_list_.begin(), app_memory_list_.end(), ptr); 709 if (iter != app_memory_list_.end()) { 710 // Don't allow registering the same pointer twice. 711 return; 712 } 713 714 AppMemory app_memory; 715 app_memory.ptr = ptr; 716 app_memory.length = length; 717 app_memory_list_.push_back(app_memory); 718 } 719 720 void ExceptionHandler::UnregisterAppMemory(void* ptr) { 721 AppMemoryList::iterator iter = 722 std::find(app_memory_list_.begin(), app_memory_list_.end(), ptr); 723 if (iter != app_memory_list_.end()) { 724 app_memory_list_.erase(iter); 725 } 726 } 727 728 // static 729 bool ExceptionHandler::WriteMinidumpForChild(pid_t child, 730 pid_t child_blamed_thread, 731 const string& dump_path, 732 MinidumpCallback callback, 733 void* callback_context) { 734 // This function is not run in a compromised context. 735 MinidumpDescriptor descriptor(dump_path); 736 descriptor.UpdatePath(); 737 if (!google_breakpad::WriteMinidump(descriptor.path(), 738 child, 739 child_blamed_thread)) 740 return false; 741 742 return callback ? callback(descriptor, callback_context, true) : true; 743 } 744 745 } // namespace google_breakpad 746