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.
109static int tgkill(pid_t tgid, pid_t tid, int sig) {
110  return syscall(__NR_tgkill, tgid, tid, sig);
111  return 0;
112}
113
114namespace google_breakpad {
115
116namespace {
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.
120const int kExceptionSignals[] = {
121  SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS
122};
123const int kNumHandledSignals =
124    sizeof(kExceptionSignals) / sizeof(kExceptionSignals[0]);
125struct sigaction old_handlers[kNumHandledSignals];
126bool 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.
130stack_t old_stack;
131stack_t new_stack;
132bool 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.
137void 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.
165void RestoreAlternateStackLocked() {
166  if (!stack_installed)
167    return;
168
169  stack_t current_stack;
170  if (sys_sigaltstack(NULL, &current_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
191void 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.
212std::vector<ExceptionHandler*>* g_handler_stack_ = NULL;
213pthread_mutex_t g_handler_stack_mutex_ = PTHREAD_MUTEX_INITIALIZER;
214
215}  // namespace
216
217// Runs before crashing: normal context.
218ExceptionHandler::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.
248ExceptionHandler::~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
264bool 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
298void 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
317void 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
386struct 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
397int 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.
410bool 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.
455bool 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.
467bool 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.
539void 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.
554void 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.
569bool 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
596bool 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
611bool 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
688void 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
706void 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
720void 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
729bool 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