/ src / client / linux / handler / exception_handler_unittest.cc
exception_handler_unittest.cc
   1  // Copyright 2010 Google LLC
   2  //
   3  // Redistribution and use in source and binary forms, with or without
   4  // modification, are permitted provided that the following conditions are
   5  // met:
   6  //
   7  //     * Redistributions of source code must retain the above copyright
   8  // notice, this list of conditions and the following disclaimer.
   9  //     * Redistributions in binary form must reproduce the above
  10  // copyright notice, this list of conditions and the following disclaimer
  11  // in the documentation and/or other materials provided with the
  12  // distribution.
  13  //     * Neither the name of Google LLC nor the names of its
  14  // contributors may be used to endorse or promote products derived from
  15  // this software without specific prior written permission.
  16  //
  17  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  20  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  21  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  22  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  23  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  24  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  25  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  27  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28  
  29  #ifdef HAVE_CONFIG_H
  30  #include <config.h>  // Must come first
  31  #endif
  32  
  33  #include <poll.h>
  34  #include <pthread.h>
  35  #include <stdint.h>
  36  #include <unistd.h>
  37  #include <signal.h>
  38  #include <sys/mman.h>
  39  #include <sys/socket.h>
  40  #include <sys/uio.h>
  41  #include <sys/wait.h>
  42  #if defined(__mips__)
  43  #include <sys/cachectl.h>
  44  #endif
  45  
  46  #include <string>
  47  
  48  #include "breakpad_googletest_includes.h"
  49  #include "client/linux/handler/exception_handler.h"
  50  #include "client/linux/minidump_writer/minidump_writer.h"
  51  #include "common/linux/eintr_wrapper.h"
  52  #include "common/linux/ignore_ret.h"
  53  #include "common/linux/linux_libc_support.h"
  54  #include "common/tests/auto_tempdir.h"
  55  #include "common/using_std_string.h"
  56  #include "third_party/lss/linux_syscall_support.h"
  57  #include "google_breakpad/processor/minidump.h"
  58  
  59  using namespace google_breakpad;
  60  
  61  namespace {
  62  
  63  // Flush the instruction cache for a given memory range.
  64  // Only required on ARM and mips.
  65  void FlushInstructionCache(const char* memory, uint32_t memory_size) {
  66  #if defined(__arm__)
  67    long begin = reinterpret_cast<long>(memory);
  68    long end = begin + static_cast<long>(memory_size);
  69  # if defined(__ANDROID__)
  70    // Provided by Android's <unistd.h>
  71    cacheflush(begin, end, 0);
  72  # elif defined(__linux__)
  73    // GLibc/ARM doesn't provide a wrapper for it, do a direct syscall.
  74  #  ifndef __ARM_NR_cacheflush
  75  #  define __ARM_NR_cacheflush 0xf0002
  76  #  endif
  77    syscall(__ARM_NR_cacheflush, begin, end, 0);
  78  # else
  79  #   error "Your operating system is not supported yet"
  80  # endif
  81  #elif defined(__mips__)
  82  # if defined(__ANDROID__)
  83    // Provided by Android's <unistd.h>
  84    long begin = reinterpret_cast<long>(memory);
  85    long end = begin + static_cast<long>(memory_size);
  86  #if _MIPS_SIM == _ABIO32
  87    cacheflush(begin, end, 0);
  88  #else
  89    syscall(__NR_cacheflush, begin, end, ICACHE);
  90  #endif
  91  # elif defined(__linux__)
  92    // See http://www.linux-mips.org/wiki/Cacheflush_Syscall.
  93    cacheflush(const_cast<char*>(memory), memory_size, ICACHE);
  94  # else
  95  #   error "Your operating system is not supported yet"
  96  # endif
  97  #endif
  98  }
  99  
 100  void sigchld_handler(int signo) { }
 101  
 102  int CreateTMPFile(const string& dir, string* path) {
 103    string file = dir + "/exception-handler-unittest.XXXXXX";
 104    const char* c_file = file.c_str();
 105    // Copy that string, mkstemp needs a C string it can modify.
 106    char* c_path = strdup(c_file);
 107    const int fd = mkstemp(c_path);
 108    if (fd >= 0)
 109      *path = c_path;
 110    free(c_path);
 111    return fd;
 112  }
 113  
 114  class ExceptionHandlerTest : public ::testing::Test {
 115   protected:
 116    void SetUp() {
 117      // We need to be able to wait for children, so SIGCHLD cannot be SIG_IGN.
 118      struct sigaction sa;
 119      memset(&sa, 0, sizeof(sa));
 120      sa.sa_handler = sigchld_handler;
 121      ASSERT_NE(sigaction(SIGCHLD, &sa, &old_action), -1);
 122    }
 123  
 124    void TearDown() {
 125      sigaction(SIGCHLD, &old_action, NULL);
 126    }
 127  
 128    struct sigaction old_action;
 129  };
 130  
 131  
 132  void WaitForProcessToTerminate(pid_t process_id, int expected_status) {
 133    int status;
 134    ASSERT_NE(HANDLE_EINTR(waitpid(process_id, &status, 0)), -1);
 135    ASSERT_TRUE(WIFSIGNALED(status));
 136    ASSERT_EQ(expected_status, WTERMSIG(status));
 137  }
 138  
 139  // Reads the minidump path sent over the pipe |fd| and sets it in |path|.
 140  void ReadMinidumpPathFromPipe(int fd, string* path) {
 141    struct pollfd pfd;
 142    memset(&pfd, 0, sizeof(pfd));
 143    pfd.fd = fd;
 144    pfd.events = POLLIN | POLLERR;
 145  
 146    const int r = HANDLE_EINTR(poll(&pfd, 1, 0));
 147    ASSERT_EQ(1, r);
 148    ASSERT_TRUE(pfd.revents & POLLIN);
 149  
 150    int32_t len;
 151    ASSERT_EQ(static_cast<ssize_t>(sizeof(len)), read(fd, &len, sizeof(len)));
 152    ASSERT_LT(len, 2048);
 153    char* filename = static_cast<char*>(malloc(len + 1));
 154    ASSERT_EQ(len, read(fd, filename, len));
 155    filename[len] = 0;
 156    close(fd);
 157    *path = filename;
 158    free(filename);
 159  }
 160  
 161  }  // namespace
 162  
 163  TEST(ExceptionHandlerTest, SimpleWithPath) {
 164    AutoTempDir temp_dir;
 165    ExceptionHandler handler(
 166        MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1);
 167    EXPECT_EQ(temp_dir.path(), handler.minidump_descriptor().directory());
 168    string temp_subdir = temp_dir.path() + "/subdir";
 169    handler.set_minidump_descriptor(MinidumpDescriptor(temp_subdir));
 170    EXPECT_EQ(temp_subdir, handler.minidump_descriptor().directory());
 171  }
 172  
 173  TEST(ExceptionHandlerTest, SimpleWithFD) {
 174    AutoTempDir temp_dir;
 175    string path;
 176    const int fd = CreateTMPFile(temp_dir.path(), &path);
 177    ExceptionHandler handler(MinidumpDescriptor(fd), NULL, NULL, NULL, true, -1);
 178    close(fd);
 179  }
 180  
 181  static bool DoneCallback(const MinidumpDescriptor& descriptor,
 182                           void* context,
 183                           bool succeeded) {
 184    if (!succeeded)
 185      return false;
 186  
 187    if (!descriptor.IsFD()) {
 188      int fd = reinterpret_cast<intptr_t>(context);
 189      uint32_t len = 0;
 190      len = my_strlen(descriptor.path());
 191      IGNORE_RET(HANDLE_EINTR(sys_write(fd, &len, sizeof(len))));
 192      IGNORE_RET(HANDLE_EINTR(sys_write(fd, descriptor.path(), len)));
 193    }
 194    return true;
 195  }
 196  
 197  #ifndef ADDRESS_SANITIZER
 198  
 199  // This is a replacement for "*reinterpret_cast<volatile int*>(NULL) = 0;"
 200  // It is needed because GCC is allowed to assume that the program will
 201  // not execute any undefined behavior (UB) operation. Further, when GCC
 202  // observes that UB statement is reached, it can assume that all statements
 203  // leading to the UB one are never executed either, and can completely
 204  // optimize them out. In the case of ExceptionHandlerTest::ExternalDumper,
 205  // GCC-4.9 optimized out the entire set up of ExceptionHandler, causing
 206  // test failure.
 207  volatile int* p_null;  // external linkage, so GCC can't tell that it
 208                         // remains NULL. Volatile just for a good measure.
 209  static void DoNullPointerDereference() {
 210    *p_null = 1;
 211  }
 212  
 213  void ChildCrash(bool use_fd) {
 214    AutoTempDir temp_dir;
 215    int fds[2] = {0};
 216    int minidump_fd = -1;
 217    string minidump_path;
 218    if (use_fd) {
 219      minidump_fd = CreateTMPFile(temp_dir.path(), &minidump_path);
 220    } else {
 221      ASSERT_NE(pipe(fds), -1);
 222    }
 223  
 224    const pid_t child = fork();
 225    if (child == 0) {
 226      {
 227        google_breakpad::scoped_ptr<ExceptionHandler> handler;
 228        if (use_fd) {
 229          handler.reset(new ExceptionHandler(MinidumpDescriptor(minidump_fd),
 230                                             NULL, NULL, NULL, true, -1));
 231        } else {
 232          close(fds[0]);  // Close the reading end.
 233          void* fd_param = reinterpret_cast<void*>(fds[1]);
 234          handler.reset(new ExceptionHandler(MinidumpDescriptor(temp_dir.path()),
 235                                             NULL, DoneCallback, fd_param,
 236                                             true, -1));
 237        }
 238        // Crash with the exception handler in scope.
 239        DoNullPointerDereference();
 240      }
 241    }
 242    if (!use_fd)
 243      close(fds[1]);  // Close the writting end.
 244  
 245    ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
 246  
 247    if (!use_fd)
 248      ASSERT_NO_FATAL_FAILURE(ReadMinidumpPathFromPipe(fds[0], &minidump_path));
 249  
 250    struct stat st;
 251    ASSERT_EQ(0, stat(minidump_path.c_str(), &st));
 252    ASSERT_GT(st.st_size, 0);
 253    unlink(minidump_path.c_str());
 254  }
 255  
 256  TEST(ExceptionHandlerTest, ChildCrashWithPath) {
 257    ASSERT_NO_FATAL_FAILURE(ChildCrash(false));
 258  }
 259  
 260  TEST(ExceptionHandlerTest, ChildCrashWithFD) {
 261    ASSERT_NO_FATAL_FAILURE(ChildCrash(true));
 262  }
 263  
 264  #if !defined(__ANDROID_API__) || __ANDROID_API__ >= __ANDROID_API_N__
 265  static void* SleepFunction(void* unused) {
 266    while (true) usleep(1000000);
 267    return NULL;
 268  }
 269  
 270  static void* CrashFunction(void* b_ptr) {
 271    pthread_barrier_t* b = reinterpret_cast<pthread_barrier_t*>(b_ptr);
 272    pthread_barrier_wait(b);
 273    DoNullPointerDereference();
 274    return NULL;
 275  }
 276  
 277  // Tests that concurrent crashes do not enter a loop by alternately triggering
 278  // the signal handler.
 279  TEST(ExceptionHandlerTest, ParallelChildCrashesDontHang) {
 280    AutoTempDir temp_dir;
 281    const pid_t child = fork();
 282    if (child == 0) {
 283      google_breakpad::scoped_ptr<ExceptionHandler> handler(
 284        new ExceptionHandler(MinidumpDescriptor(temp_dir.path()), NULL, NULL,
 285                              NULL, true, -1));
 286  
 287      // We start a number of threads to make sure handling the signal takes
 288      // enough time for the second thread to enter the signal handler.
 289      int num_sleep_threads = 100;
 290      google_breakpad::scoped_array<pthread_t> sleep_threads(
 291          new pthread_t[num_sleep_threads]);
 292      for (int i = 0; i < num_sleep_threads; ++i) {
 293        ASSERT_EQ(0, pthread_create(&sleep_threads[i], NULL, SleepFunction,
 294                                    NULL));
 295      }
 296  
 297      int num_crash_threads = 2;
 298      google_breakpad::scoped_array<pthread_t> crash_threads(
 299          new pthread_t[num_crash_threads]);
 300      // Barrier to synchronize crashing both threads at the same time.
 301      pthread_barrier_t b;
 302      ASSERT_EQ(0, pthread_barrier_init(&b, NULL, num_crash_threads + 1));
 303      for (int i = 0; i < num_crash_threads; ++i) {
 304        ASSERT_EQ(0, pthread_create(&crash_threads[i], NULL, CrashFunction, &b));
 305      }
 306      pthread_barrier_wait(&b);
 307      for (int i = 0; i < num_crash_threads; ++i) {
 308        ASSERT_EQ(0, pthread_join(crash_threads[i], NULL));
 309      }
 310    }
 311  
 312    // Poll the child to see if it crashed.
 313    int status, wp_pid;
 314    for (int i = 0; i < 100; i++) {
 315      wp_pid = HANDLE_EINTR(waitpid(child, &status, WNOHANG));
 316      ASSERT_NE(-1, wp_pid);
 317      if (wp_pid > 0) {
 318        ASSERT_TRUE(WIFSIGNALED(status));
 319        // If the child process terminated by itself,
 320        // it will have returned SIGSEGV.
 321        ASSERT_EQ(SIGSEGV, WTERMSIG(status));
 322        return;
 323      } else {
 324        usleep(100000);
 325      }
 326    }
 327  
 328    // Kill the child if it is still running.
 329    kill(child, SIGKILL);
 330  
 331    // If the child process terminated by itself, it will have returned SIGSEGV.
 332    // If however it got stuck in a loop, it will have been killed by the
 333    // SIGKILL.
 334    ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
 335  }
 336  #endif  // !defined(__ANDROID_API__) || __ANDROID_API__ >= __ANDROID_API_N__
 337  
 338  static bool DoneCallbackReturnFalse(const MinidumpDescriptor& descriptor,
 339                                      void* context,
 340                                      bool succeeded) {
 341    return false;
 342  }
 343  
 344  static bool DoneCallbackReturnTrue(const MinidumpDescriptor& descriptor,
 345                                     void* context,
 346                                     bool succeeded) {
 347    return true;
 348  }
 349  
 350  static bool DoneCallbackRaiseSIGKILL(const MinidumpDescriptor& descriptor,
 351                                       void* context,
 352                                       bool succeeded) {
 353    raise(SIGKILL);
 354    return true;
 355  }
 356  
 357  static bool FilterCallbackReturnFalse(void* context) {
 358    return false;
 359  }
 360  
 361  static bool FilterCallbackReturnTrue(void* context) {
 362    return true;
 363  }
 364  
 365  // SIGKILL cannot be blocked and a handler cannot be installed for it. In the
 366  // following tests, if the child dies with signal SIGKILL, then the signal was
 367  // redelivered to this handler. If the child dies with SIGSEGV then it wasn't.
 368  static void RaiseSIGKILL(int sig) {
 369    raise(SIGKILL);
 370  }
 371  
 372  static bool InstallRaiseSIGKILL() {
 373    struct sigaction sa;
 374    memset(&sa, 0, sizeof(sa));
 375    sa.sa_handler = RaiseSIGKILL;
 376    return sigaction(SIGSEGV, &sa, NULL) != -1;
 377  }
 378  
 379  static void CrashWithCallbacks(ExceptionHandler::FilterCallback filter,
 380                                 ExceptionHandler::MinidumpCallback done,
 381                                 string path) {
 382    ExceptionHandler handler(
 383        MinidumpDescriptor(path), filter, done, NULL, true, -1);
 384    // Crash with the exception handler in scope.
 385    DoNullPointerDereference();
 386  }
 387  
 388  TEST(ExceptionHandlerTest, RedeliveryOnFilterCallbackFalse) {
 389    AutoTempDir temp_dir;
 390  
 391    const pid_t child = fork();
 392    if (child == 0) {
 393      ASSERT_TRUE(InstallRaiseSIGKILL());
 394      CrashWithCallbacks(FilterCallbackReturnFalse, NULL, temp_dir.path());
 395    }
 396  
 397    ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
 398  }
 399  
 400  TEST(ExceptionHandlerTest, RedeliveryOnDoneCallbackFalse) {
 401    AutoTempDir temp_dir;
 402  
 403    const pid_t child = fork();
 404    if (child == 0) {
 405      ASSERT_TRUE(InstallRaiseSIGKILL());
 406      CrashWithCallbacks(NULL, DoneCallbackReturnFalse, temp_dir.path());
 407    }
 408  
 409    ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
 410  }
 411  
 412  TEST(ExceptionHandlerTest, NoRedeliveryOnDoneCallbackTrue) {
 413    AutoTempDir temp_dir;
 414  
 415    const pid_t child = fork();
 416    if (child == 0) {
 417      ASSERT_TRUE(InstallRaiseSIGKILL());
 418      CrashWithCallbacks(NULL, DoneCallbackReturnTrue, temp_dir.path());
 419    }
 420  
 421    ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
 422  }
 423  
 424  TEST(ExceptionHandlerTest, NoRedeliveryOnFilterCallbackTrue) {
 425    AutoTempDir temp_dir;
 426  
 427    const pid_t child = fork();
 428    if (child == 0) {
 429      ASSERT_TRUE(InstallRaiseSIGKILL());
 430      CrashWithCallbacks(FilterCallbackReturnTrue, NULL, temp_dir.path());
 431    }
 432  
 433    ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
 434  }
 435  
 436  TEST(ExceptionHandlerTest, RedeliveryToDefaultHandler) {
 437    AutoTempDir temp_dir;
 438  
 439    const pid_t child = fork();
 440    if (child == 0) {
 441      // Custom signal handlers, which may have been installed by a test launcher,
 442      // are undesirable in this child.
 443      signal(SIGSEGV, SIG_DFL);
 444  
 445      CrashWithCallbacks(FilterCallbackReturnFalse, NULL, temp_dir.path());
 446    }
 447  
 448    // As RaiseSIGKILL wasn't installed, the redelivery should just kill the child
 449    // with SIGSEGV.
 450    ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
 451  }
 452  
 453  // Check that saving and restoring the signal handler with 'signal'
 454  // instead of 'sigaction' doesn't make the Breakpad signal handler
 455  // crash. See comments in ExceptionHandler::SignalHandler for full
 456  // details.
 457  TEST(ExceptionHandlerTest, RedeliveryOnBadSignalHandlerFlag) {
 458    AutoTempDir temp_dir;
 459    const pid_t child = fork();
 460    if (child == 0) {
 461      // Install the RaiseSIGKILL handler for SIGSEGV.
 462      ASSERT_TRUE(InstallRaiseSIGKILL());
 463  
 464      // Create a new exception handler, this installs a new SIGSEGV
 465      // handler, after saving the old one.
 466      ExceptionHandler handler(
 467          MinidumpDescriptor(temp_dir.path()), NULL,
 468          DoneCallbackReturnFalse, NULL, true, -1);
 469  
 470      // Install the default SIGSEGV handler, saving the current one.
 471      // Then re-install the current one with 'signal', this loses the
 472      // SA_SIGINFO flag associated with the Breakpad handler.
 473      sighandler_t old_handler = signal(SIGSEGV, SIG_DFL);
 474      ASSERT_NE(reinterpret_cast<void*>(old_handler),
 475                reinterpret_cast<void*>(SIG_ERR));
 476      ASSERT_NE(reinterpret_cast<void*>(signal(SIGSEGV, old_handler)),
 477                reinterpret_cast<void*>(SIG_ERR));
 478  
 479      // Crash with the exception handler in scope.
 480      DoNullPointerDereference();
 481    }
 482    // SIGKILL means Breakpad's signal handler didn't crash.
 483    ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
 484  }
 485  
 486  TEST(ExceptionHandlerTest, StackedHandlersDeliveredToTop) {
 487    AutoTempDir temp_dir;
 488  
 489    const pid_t child = fork();
 490    if (child == 0) {
 491      ExceptionHandler bottom(MinidumpDescriptor(temp_dir.path()),
 492                              NULL,
 493                              NULL,
 494                              NULL,
 495                              true,
 496                              -1);
 497      CrashWithCallbacks(NULL, DoneCallbackRaiseSIGKILL, temp_dir.path());
 498    }
 499    ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
 500  }
 501  
 502  TEST(ExceptionHandlerTest, StackedHandlersNotDeliveredToBottom) {
 503    AutoTempDir temp_dir;
 504  
 505    const pid_t child = fork();
 506    if (child == 0) {
 507      ExceptionHandler bottom(MinidumpDescriptor(temp_dir.path()),
 508                              NULL,
 509                              DoneCallbackRaiseSIGKILL,
 510                              NULL,
 511                              true,
 512                              -1);
 513      CrashWithCallbacks(NULL, NULL, temp_dir.path());
 514    }
 515    ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
 516  }
 517  
 518  TEST(ExceptionHandlerTest, StackedHandlersFilteredToBottom) {
 519    AutoTempDir temp_dir;
 520  
 521    const pid_t child = fork();
 522    if (child == 0) {
 523      ExceptionHandler bottom(MinidumpDescriptor(temp_dir.path()),
 524                              NULL,
 525                              DoneCallbackRaiseSIGKILL,
 526                              NULL,
 527                              true,
 528                              -1);
 529      CrashWithCallbacks(FilterCallbackReturnFalse, NULL, temp_dir.path());
 530    }
 531    ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
 532  }
 533  
 534  TEST(ExceptionHandlerTest, StackedHandlersUnhandledToBottom) {
 535    AutoTempDir temp_dir;
 536  
 537    const pid_t child = fork();
 538    if (child == 0) {
 539      ExceptionHandler bottom(MinidumpDescriptor(temp_dir.path()),
 540                              NULL,
 541                              DoneCallbackRaiseSIGKILL,
 542                              NULL,
 543                              true,
 544                              -1);
 545      CrashWithCallbacks(NULL, DoneCallbackReturnFalse, temp_dir.path());
 546    }
 547    ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
 548  }
 549  
 550  namespace {
 551  const int kSimpleFirstChanceReturnStatus = 42;
 552  bool SimpleFirstChanceHandler(int, siginfo_t*, void*) {
 553    _exit(kSimpleFirstChanceReturnStatus);
 554  }
 555  }
 556  
 557  TEST(ExceptionHandlerTest, FirstChanceHandlerRuns) {
 558    AutoTempDir temp_dir;
 559  
 560    const pid_t child = fork();
 561    if (child == 0) {
 562      ExceptionHandler handler(
 563          MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1);
 564      google_breakpad::SetFirstChanceExceptionHandler(SimpleFirstChanceHandler);
 565      DoNullPointerDereference();
 566    }
 567    int status;
 568    ASSERT_NE(HANDLE_EINTR(waitpid(child, &status, 0)), -1);
 569    ASSERT_TRUE(WIFEXITED(status));
 570    ASSERT_EQ(kSimpleFirstChanceReturnStatus, WEXITSTATUS(status));
 571  }
 572  
 573  #endif  // !ADDRESS_SANITIZER
 574  
 575  const unsigned char kIllegalInstruction[] = {
 576  #if defined(__mips__)
 577    // mfc2 zero,Impl - usually illegal in userspace.
 578    0x48, 0x00, 0x00, 0x48
 579  #else
 580    // This crashes with SIGILL on x86/x86-64/arm.
 581    0xff, 0xff, 0xff, 0xff
 582  #endif
 583  };
 584  
 585  // Test that memory around the instruction pointer is written
 586  // to the dump as a MinidumpMemoryRegion.
 587  TEST(ExceptionHandlerTest, InstructionPointerMemory) {
 588    AutoTempDir temp_dir;
 589    int fds[2];
 590    ASSERT_NE(pipe(fds), -1);
 591  
 592    // These are defined here so the parent can use them to check the
 593    // data from the minidump afterwards.
 594    const uint32_t kMemorySize = 256;  // bytes
 595    const int kOffset = kMemorySize / 2;
 596  
 597    const pid_t child = fork();
 598    if (child == 0) {
 599      close(fds[0]);
 600      ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL,
 601                               DoneCallback, reinterpret_cast<void*>(fds[1]),
 602                               true, -1);
 603      // Get some executable memory.
 604      char* memory =
 605        reinterpret_cast<char*>(mmap(NULL,
 606                                     kMemorySize,
 607                                     PROT_READ | PROT_WRITE | PROT_EXEC,
 608                                     MAP_PRIVATE | MAP_ANON,
 609                                     -1,
 610                                     0));
 611      if (!memory)
 612        exit(0);
 613  
 614      // Write some instructions that will crash. Put them in the middle
 615      // of the block of memory, because the minidump should contain 128
 616      // bytes on either side of the instruction pointer.
 617      memcpy(memory + kOffset, kIllegalInstruction, sizeof(kIllegalInstruction));
 618      FlushInstructionCache(memory, kMemorySize);
 619  
 620      // Now execute the instructions, which should crash.
 621      typedef void (*void_function)(void);
 622      void_function memory_function =
 623          reinterpret_cast<void_function>(memory + kOffset);
 624      memory_function();
 625    }
 626    close(fds[1]);
 627  
 628    ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGILL));
 629  
 630    string minidump_path;
 631    ASSERT_NO_FATAL_FAILURE(ReadMinidumpPathFromPipe(fds[0], &minidump_path));
 632  
 633    struct stat st;
 634    ASSERT_EQ(0, stat(minidump_path.c_str(), &st));
 635    ASSERT_GT(st.st_size, 0);
 636  
 637    // Read the minidump. Locate the exception record and the
 638    // memory list, and then ensure that there is a memory region
 639    // in the memory list that covers the instruction pointer from
 640    // the exception record.
 641    Minidump minidump(minidump_path);
 642    ASSERT_TRUE(minidump.Read());
 643  
 644    MinidumpException* exception = minidump.GetException();
 645    MinidumpMemoryList* memory_list = minidump.GetMemoryList();
 646    ASSERT_TRUE(exception);
 647    ASSERT_TRUE(memory_list);
 648    ASSERT_LT(0U, memory_list->region_count());
 649  
 650    MinidumpContext* context = exception->GetContext();
 651    ASSERT_TRUE(context);
 652  
 653    uint64_t instruction_pointer;
 654    ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
 655  
 656    MinidumpMemoryRegion* region =
 657        memory_list->GetMemoryRegionForAddress(instruction_pointer);
 658    ASSERT_TRUE(region);
 659  
 660    EXPECT_EQ(kMemorySize, region->GetSize());
 661    const uint8_t* bytes = region->GetMemory();
 662    ASSERT_TRUE(bytes);
 663  
 664    uint8_t prefix_bytes[kOffset];
 665    uint8_t suffix_bytes[kMemorySize - kOffset - sizeof(kIllegalInstruction)];
 666    memset(prefix_bytes, 0, sizeof(prefix_bytes));
 667    memset(suffix_bytes, 0, sizeof(suffix_bytes));
 668    EXPECT_TRUE(memcmp(bytes, prefix_bytes, sizeof(prefix_bytes)) == 0);
 669    EXPECT_TRUE(memcmp(bytes + kOffset, kIllegalInstruction, 
 670                       sizeof(kIllegalInstruction)) == 0);
 671    EXPECT_TRUE(memcmp(bytes + kOffset + sizeof(kIllegalInstruction),
 672                       suffix_bytes, sizeof(suffix_bytes)) == 0);
 673  
 674    unlink(minidump_path.c_str());
 675  }
 676  
 677  // Test that the memory region around the instruction pointer is
 678  // bounded correctly on the low end.
 679  TEST(ExceptionHandlerTest, InstructionPointerMemoryMinBound) {
 680    AutoTempDir temp_dir;
 681    int fds[2];
 682    ASSERT_NE(pipe(fds), -1);
 683  
 684    // These are defined here so the parent can use them to check the
 685    // data from the minidump afterwards.
 686    const uint32_t kMemorySize = 256;  // bytes
 687    const int kOffset = 0;
 688  
 689    const pid_t child = fork();
 690    if (child == 0) {
 691      close(fds[0]);
 692      ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL,
 693                               DoneCallback, reinterpret_cast<void*>(fds[1]),
 694                               true, -1);
 695      // Get some executable memory.
 696      char* memory =
 697          reinterpret_cast<char*>(mmap(NULL,
 698                                       kMemorySize,
 699                                       PROT_READ | PROT_WRITE | PROT_EXEC,
 700                                       MAP_PRIVATE | MAP_ANON,
 701                                       -1,
 702                                       0));
 703      if (!memory)
 704        exit(0);
 705  
 706      // Write some instructions that will crash. Put them in the middle
 707      // of the block of memory, because the minidump should contain 128
 708      // bytes on either side of the instruction pointer.
 709      memcpy(memory + kOffset, kIllegalInstruction, sizeof(kIllegalInstruction));
 710      FlushInstructionCache(memory, kMemorySize);
 711  
 712      // Now execute the instructions, which should crash.
 713      typedef void (*void_function)(void);
 714      void_function memory_function =
 715          reinterpret_cast<void_function>(memory + kOffset);
 716      memory_function();
 717    }
 718    close(fds[1]);
 719  
 720    ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGILL));
 721  
 722    string minidump_path;
 723    ASSERT_NO_FATAL_FAILURE(ReadMinidumpPathFromPipe(fds[0], &minidump_path));
 724  
 725    struct stat st;
 726    ASSERT_EQ(0, stat(minidump_path.c_str(), &st));
 727    ASSERT_GT(st.st_size, 0);
 728  
 729    // Read the minidump. Locate the exception record and the
 730    // memory list, and then ensure that there is a memory region
 731    // in the memory list that covers the instruction pointer from
 732    // the exception record.
 733    Minidump minidump(minidump_path);
 734    ASSERT_TRUE(minidump.Read());
 735  
 736    MinidumpException* exception = minidump.GetException();
 737    MinidumpMemoryList* memory_list = minidump.GetMemoryList();
 738    ASSERT_TRUE(exception);
 739    ASSERT_TRUE(memory_list);
 740    ASSERT_LT(0U, memory_list->region_count());
 741  
 742    MinidumpContext* context = exception->GetContext();
 743    ASSERT_TRUE(context);
 744  
 745    uint64_t instruction_pointer;
 746    ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
 747  
 748    MinidumpMemoryRegion* region =
 749        memory_list->GetMemoryRegionForAddress(instruction_pointer);
 750    ASSERT_TRUE(region);
 751  
 752    EXPECT_EQ(kMemorySize / 2, region->GetSize());
 753    const uint8_t* bytes = region->GetMemory();
 754    ASSERT_TRUE(bytes);
 755  
 756    uint8_t suffix_bytes[kMemorySize / 2 - sizeof(kIllegalInstruction)];
 757    memset(suffix_bytes, 0, sizeof(suffix_bytes));
 758    EXPECT_TRUE(memcmp(bytes + kOffset, kIllegalInstruction, 
 759                       sizeof(kIllegalInstruction)) == 0);
 760    EXPECT_TRUE(memcmp(bytes + kOffset + sizeof(kIllegalInstruction),
 761                       suffix_bytes, sizeof(suffix_bytes)) == 0);
 762    unlink(minidump_path.c_str());
 763  }
 764  
 765  // Test that the memory region around the instruction pointer is
 766  // bounded correctly on the high end.
 767  TEST(ExceptionHandlerTest, InstructionPointerMemoryMaxBound) {
 768    AutoTempDir temp_dir;
 769    int fds[2];
 770    ASSERT_NE(pipe(fds), -1);
 771  
 772    // These are defined here so the parent can use them to check the
 773    // data from the minidump afterwards.
 774    // Use 4k here because the OS will hand out a single page even
 775    // if a smaller size is requested, and this test wants to
 776    // test the upper bound of the memory range.
 777    const uint32_t kMemorySize = 4096;  // bytes
 778    const int kOffset = kMemorySize - sizeof(kIllegalInstruction);
 779  
 780    const pid_t child = fork();
 781    if (child == 0) {
 782      close(fds[0]);
 783      ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL,
 784                               DoneCallback, reinterpret_cast<void*>(fds[1]),
 785                               true, -1);
 786      // Get some executable memory.
 787      char* memory =
 788          reinterpret_cast<char*>(mmap(NULL,
 789                                       kMemorySize,
 790                                       PROT_READ | PROT_WRITE | PROT_EXEC,
 791                                       MAP_PRIVATE | MAP_ANON,
 792                                       -1,
 793                                       0));
 794      if (!memory)
 795        exit(0);
 796  
 797      // Write some instructions that will crash. Put them in the middle
 798      // of the block of memory, because the minidump should contain 128
 799      // bytes on either side of the instruction pointer.
 800      memcpy(memory + kOffset, kIllegalInstruction, sizeof(kIllegalInstruction));
 801      FlushInstructionCache(memory, kMemorySize);
 802  
 803      // Now execute the instructions, which should crash.
 804      typedef void (*void_function)(void);
 805      void_function memory_function =
 806          reinterpret_cast<void_function>(memory + kOffset);
 807      memory_function();
 808    }
 809    close(fds[1]);
 810  
 811    ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGILL));
 812  
 813    string minidump_path;
 814    ASSERT_NO_FATAL_FAILURE(ReadMinidumpPathFromPipe(fds[0], &minidump_path));
 815  
 816    struct stat st;
 817    ASSERT_EQ(0, stat(minidump_path.c_str(), &st));
 818    ASSERT_GT(st.st_size, 0);
 819  
 820    // Read the minidump. Locate the exception record and the memory list, and
 821    // then ensure that there is a memory region in the memory list that covers
 822    // the instruction pointer from the exception record.
 823    Minidump minidump(minidump_path);
 824    ASSERT_TRUE(minidump.Read());
 825  
 826    MinidumpException* exception = minidump.GetException();
 827    MinidumpMemoryList* memory_list = minidump.GetMemoryList();
 828    ASSERT_TRUE(exception);
 829    ASSERT_TRUE(memory_list);
 830    ASSERT_LT(0U, memory_list->region_count());
 831  
 832    MinidumpContext* context = exception->GetContext();
 833    ASSERT_TRUE(context);
 834  
 835    uint64_t instruction_pointer;
 836    ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
 837  
 838    MinidumpMemoryRegion* region =
 839        memory_list->GetMemoryRegionForAddress(instruction_pointer);
 840    ASSERT_TRUE(region);
 841  
 842    const size_t kPrefixSize = 128;  // bytes
 843    EXPECT_EQ(kPrefixSize + sizeof(kIllegalInstruction), region->GetSize());
 844    const uint8_t* bytes = region->GetMemory();
 845    ASSERT_TRUE(bytes);
 846  
 847    uint8_t prefix_bytes[kPrefixSize];
 848    memset(prefix_bytes, 0, sizeof(prefix_bytes));
 849    EXPECT_TRUE(memcmp(bytes, prefix_bytes, sizeof(prefix_bytes)) == 0);
 850    EXPECT_TRUE(memcmp(bytes + kPrefixSize,
 851                       kIllegalInstruction, sizeof(kIllegalInstruction)) == 0);
 852  
 853    unlink(minidump_path.c_str());
 854  }
 855  
 856  #ifndef ADDRESS_SANITIZER
 857  
 858  // Ensure that an extra memory block doesn't get added when the instruction
 859  // pointer is not in mapped memory.
 860  TEST(ExceptionHandlerTest, InstructionPointerMemoryNullPointer) {
 861    AutoTempDir temp_dir;
 862    int fds[2];
 863    ASSERT_NE(pipe(fds), -1);
 864  
 865    const pid_t child = fork();
 866    if (child == 0) {
 867      close(fds[0]);
 868      ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL,
 869                               DoneCallback, reinterpret_cast<void*>(fds[1]),
 870                               true, -1);
 871      // Try calling a NULL pointer.
 872      typedef void (*void_function)(void);
 873      // Volatile markings are needed to keep Clang from generating invalid
 874      // opcodes.  See http://crbug.com/498354 for details.
 875      volatile void_function memory_function =
 876        reinterpret_cast<void_function>(NULL);
 877      memory_function();
 878      // not reached
 879      exit(1);
 880    }
 881    close(fds[1]);
 882  
 883    ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
 884  
 885    string minidump_path;
 886    ASSERT_NO_FATAL_FAILURE(ReadMinidumpPathFromPipe(fds[0], &minidump_path));
 887  
 888    struct stat st;
 889    ASSERT_EQ(0, stat(minidump_path.c_str(), &st));
 890    ASSERT_GT(st.st_size, 0);
 891  
 892    // Read the minidump. Locate the exception record and the
 893    // memory list, and then ensure that there is no memory region
 894    // in the memory list that covers the instruction pointer from
 895    // the exception record.
 896    Minidump minidump(minidump_path);
 897    ASSERT_TRUE(minidump.Read());
 898  
 899    MinidumpException* exception = minidump.GetException();
 900    ASSERT_TRUE(exception);
 901  
 902    MinidumpContext* exception_context = exception->GetContext();
 903    ASSERT_TRUE(exception_context);
 904  
 905    uint64_t instruction_pointer;
 906    ASSERT_TRUE(exception_context->GetInstructionPointer(&instruction_pointer));
 907    EXPECT_EQ(instruction_pointer, 0u);
 908  
 909    MinidumpMemoryList* memory_list = minidump.GetMemoryList();
 910    ASSERT_TRUE(memory_list);
 911  
 912    unsigned int region_count = memory_list->region_count();
 913    ASSERT_GE(region_count, 1u);
 914  
 915    for (unsigned int region_index = 0;
 916         region_index < region_count;
 917         ++region_index) {
 918      MinidumpMemoryRegion* region =
 919          memory_list->GetMemoryRegionAtIndex(region_index);
 920      uint64_t region_base = region->GetBase();
 921      EXPECT_FALSE(instruction_pointer >= region_base &&
 922                   instruction_pointer < region_base + region->GetSize());
 923    }
 924  
 925    unlink(minidump_path.c_str());
 926  }
 927  
 928  #endif  // !ADDRESS_SANITIZER
 929  
 930  // Test that anonymous memory maps can be annotated with names and IDs.
 931  TEST(ExceptionHandlerTest, ModuleInfo) {
 932    // These are defined here so the parent can use them to check the
 933    // data from the minidump afterwards.
 934    const uint32_t kMemorySize = sysconf(_SC_PAGESIZE);
 935    const char* kMemoryName = "a fake module";
 936    const uint8_t kModuleGUID[sizeof(MDGUID)] = {
 937      0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
 938      0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
 939    };
 940    const string module_identifier = "33221100554477668899AABBCCDDEEFF0";
 941  
 942    // Get some memory.
 943    char* memory =
 944        reinterpret_cast<char*>(mmap(NULL,
 945                                     kMemorySize,
 946                                     PROT_READ | PROT_WRITE,
 947                                     MAP_PRIVATE | MAP_ANON,
 948                                     -1,
 949                                     0));
 950    const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory);
 951    ASSERT_TRUE(memory);
 952  
 953    AutoTempDir temp_dir;
 954    ExceptionHandler handler(
 955        MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1);
 956  
 957    // Add info about the anonymous memory mapping.
 958    handler.AddMappingInfo(kMemoryName,
 959                           kModuleGUID,
 960                           kMemoryAddress,
 961                           kMemorySize,
 962                           0);
 963    ASSERT_TRUE(handler.WriteMinidump());
 964  
 965    const MinidumpDescriptor& minidump_desc = handler.minidump_descriptor();
 966    // Read the minidump. Load the module list, and ensure that the mmap'ed
 967    // |memory| is listed with the given module name and debug ID.
 968    Minidump minidump(minidump_desc.path());
 969    ASSERT_TRUE(minidump.Read());
 970  
 971    MinidumpModuleList* module_list = minidump.GetModuleList();
 972    ASSERT_TRUE(module_list);
 973    const MinidumpModule* module =
 974        module_list->GetModuleForAddress(kMemoryAddress);
 975    ASSERT_TRUE(module);
 976  
 977    EXPECT_EQ(kMemoryAddress, module->base_address());
 978    EXPECT_EQ(kMemorySize, module->size());
 979    EXPECT_EQ(kMemoryName, module->code_file());
 980    EXPECT_EQ(module_identifier, module->debug_identifier());
 981  
 982    unlink(minidump_desc.path());
 983  }
 984  
 985  #ifndef ADDRESS_SANITIZER
 986  
 987  static const unsigned kControlMsgSize =
 988      CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(struct ucred));
 989  
 990  static bool
 991  CrashHandler(const void* crash_context, size_t crash_context_size,
 992               void* context) {
 993    const int fd = (intptr_t) context;
 994    int fds[2];
 995    if (pipe(fds) == -1) {
 996      // There doesn't seem to be any way to reliably handle
 997      // this failure without the parent process hanging
 998      // At least make sure that this process doesn't access
 999      // unexpected file descriptors
1000      fds[0] = -1;
1001      fds[1] = -1;
1002    }
1003    struct kernel_msghdr msg = {0};
1004    struct kernel_iovec iov;
1005    iov.iov_base = const_cast<void*>(crash_context);
1006    iov.iov_len = crash_context_size;
1007    msg.msg_iov = &iov;
1008    msg.msg_iovlen = 1;
1009    char cmsg[kControlMsgSize];
1010    memset(cmsg, 0, kControlMsgSize);
1011    msg.msg_control = cmsg;
1012    msg.msg_controllen = sizeof(cmsg);
1013  
1014    struct cmsghdr* hdr = CMSG_FIRSTHDR(&msg);
1015    hdr->cmsg_level = SOL_SOCKET;
1016    hdr->cmsg_type = SCM_RIGHTS;
1017    hdr->cmsg_len = CMSG_LEN(sizeof(int));
1018    *((int*) CMSG_DATA(hdr)) = fds[1];
1019    hdr = CMSG_NXTHDR((struct msghdr*) &msg, hdr);
1020    hdr->cmsg_level = SOL_SOCKET;
1021    hdr->cmsg_type = SCM_CREDENTIALS;
1022    hdr->cmsg_len = CMSG_LEN(sizeof(struct ucred));
1023    struct ucred* cred = reinterpret_cast<struct ucred*>(CMSG_DATA(hdr));
1024    cred->uid = getuid();
1025    cred->gid = getgid();
1026    cred->pid = getpid();
1027  
1028    ssize_t ret = HANDLE_EINTR(sys_sendmsg(fd, &msg, 0));
1029    sys_close(fds[1]);
1030    if (ret <= 0)
1031      return false;
1032  
1033    char b;
1034    IGNORE_RET(HANDLE_EINTR(sys_read(fds[0], &b, 1)));
1035  
1036    return true;
1037  }
1038  
1039  TEST(ExceptionHandlerTest, ExternalDumper) {
1040    int fds[2];
1041    ASSERT_NE(socketpair(AF_UNIX, SOCK_DGRAM, 0, fds), -1);
1042    static const int on = 1;
1043    setsockopt(fds[0], SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
1044    setsockopt(fds[1], SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
1045  
1046    const pid_t child = fork();
1047    if (child == 0) {
1048      close(fds[0]);
1049      ExceptionHandler handler(MinidumpDescriptor("/tmp1"), NULL, NULL,
1050                               reinterpret_cast<void*>(fds[1]), true, -1);
1051      handler.set_crash_handler(CrashHandler);
1052      DoNullPointerDereference();
1053    }
1054    close(fds[1]);
1055    struct msghdr msg = {0};
1056    struct iovec iov;
1057    static const unsigned kCrashContextSize =
1058        sizeof(ExceptionHandler::CrashContext);
1059    char context[kCrashContextSize];
1060    char control[kControlMsgSize];
1061    iov.iov_base = context;
1062    iov.iov_len = kCrashContextSize;
1063    msg.msg_iov = &iov;
1064    msg.msg_iovlen = 1;
1065    msg.msg_control = control;
1066    msg.msg_controllen = kControlMsgSize;
1067  
1068    const ssize_t n = HANDLE_EINTR(recvmsg(fds[0], &msg, 0));
1069    ASSERT_EQ(static_cast<ssize_t>(kCrashContextSize), n);
1070    ASSERT_EQ(kControlMsgSize, msg.msg_controllen);
1071    ASSERT_EQ(static_cast<__typeof__(msg.msg_flags)>(0), msg.msg_flags);
1072    ASSERT_EQ(0, close(fds[0]));
1073  
1074    pid_t crashing_pid = -1;
1075    int signal_fd = -1;
1076    for (struct cmsghdr* hdr = CMSG_FIRSTHDR(&msg); hdr;
1077         hdr = CMSG_NXTHDR(&msg, hdr)) {
1078      if (hdr->cmsg_level != SOL_SOCKET)
1079        continue;
1080      if (hdr->cmsg_type == SCM_RIGHTS) {
1081        const unsigned len = hdr->cmsg_len -
1082            (((uint8_t*)CMSG_DATA(hdr)) - (uint8_t*)hdr);
1083        ASSERT_EQ(sizeof(int), len);
1084        signal_fd = *(reinterpret_cast<int*>(CMSG_DATA(hdr)));
1085      } else if (hdr->cmsg_type == SCM_CREDENTIALS) {
1086        const struct ucred* cred =
1087            reinterpret_cast<struct ucred*>(CMSG_DATA(hdr));
1088        crashing_pid = cred->pid;
1089      }
1090    }
1091  
1092    ASSERT_NE(crashing_pid, -1);
1093    ASSERT_NE(signal_fd, -1);
1094  
1095    AutoTempDir temp_dir;
1096    string templ = temp_dir.path() + "/exception-handler-unittest";
1097    ASSERT_TRUE(WriteMinidump(templ.c_str(), crashing_pid, context,
1098                              kCrashContextSize));
1099    static const char b = 0;
1100    ASSERT_EQ(1, (HANDLE_EINTR(write(signal_fd, &b, 1))));
1101    ASSERT_EQ(0, close(signal_fd));
1102  
1103    ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
1104  
1105    struct stat st;
1106    ASSERT_EQ(0, stat(templ.c_str(), &st));
1107    ASSERT_GT(st.st_size, 0);
1108    unlink(templ.c_str());
1109  }
1110  
1111  #endif  // !ADDRESS_SANITIZER
1112  
1113  TEST(ExceptionHandlerTest, WriteMinidumpExceptionStream) {
1114    AutoTempDir temp_dir;
1115    ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL, NULL,
1116                             NULL, false, -1);
1117    ASSERT_TRUE(handler.WriteMinidump());
1118  
1119    string minidump_path = handler.minidump_descriptor().path();
1120  
1121    // Read the minidump and check the exception stream.
1122    Minidump minidump(minidump_path);
1123    ASSERT_TRUE(minidump.Read());
1124    MinidumpException* exception = minidump.GetException();
1125    ASSERT_TRUE(exception);
1126    const MDRawExceptionStream* raw = exception->exception();
1127    ASSERT_TRUE(raw);
1128    EXPECT_EQ(MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED,
1129              raw->exception_record.exception_code);
1130  }
1131  
1132  TEST(ExceptionHandlerTest, GenerateMultipleDumpsWithFD) {
1133    AutoTempDir temp_dir;
1134    string path;
1135    const int fd = CreateTMPFile(temp_dir.path(), &path);
1136    ExceptionHandler handler(MinidumpDescriptor(fd), NULL, NULL, NULL, false, -1);
1137    ASSERT_TRUE(handler.WriteMinidump());
1138    // Check by the size of the data written to the FD that a minidump was
1139    // generated.
1140    off_t size = lseek(fd, 0, SEEK_CUR);
1141    ASSERT_GT(size, 0);
1142  
1143    // Generate another minidump.
1144    ASSERT_TRUE(handler.WriteMinidump());
1145    size = lseek(fd, 0, SEEK_CUR);
1146    ASSERT_GT(size, 0);
1147  }
1148  
1149  TEST(ExceptionHandlerTest, GenerateMultipleDumpsWithPath) {
1150    AutoTempDir temp_dir;
1151    ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL, NULL,
1152                             NULL, false, -1);
1153    ASSERT_TRUE(handler.WriteMinidump());
1154  
1155    const MinidumpDescriptor& minidump_1 = handler.minidump_descriptor();
1156    struct stat st;
1157    ASSERT_EQ(0, stat(minidump_1.path(), &st));
1158    ASSERT_GT(st.st_size, 0);
1159    string minidump_1_path(minidump_1.path());
1160    // Check it is a valid minidump.
1161    Minidump minidump1(minidump_1_path);
1162    ASSERT_TRUE(minidump1.Read());
1163    unlink(minidump_1.path());
1164  
1165    // Generate another minidump, it should go to a different file.
1166    ASSERT_TRUE(handler.WriteMinidump());
1167    const MinidumpDescriptor& minidump_2 = handler.minidump_descriptor();
1168    ASSERT_EQ(0, stat(minidump_2.path(), &st));
1169    ASSERT_GT(st.st_size, 0);
1170    string minidump_2_path(minidump_2.path());
1171    // Check it is a valid minidump.
1172    Minidump minidump2(minidump_2_path);
1173    ASSERT_TRUE(minidump2.Read());
1174    unlink(minidump_2.path());
1175  
1176    // 2 distinct files should be produced.
1177    ASSERT_STRNE(minidump_1_path.c_str(), minidump_2_path.c_str());
1178  }
1179  
1180  // Test that an additional memory region can be added to the minidump.
1181  TEST(ExceptionHandlerTest, AdditionalMemory) {
1182    const uint32_t kMemorySize = sysconf(_SC_PAGESIZE);
1183  
1184    // Get some heap memory.
1185    uint8_t* memory = new uint8_t[kMemorySize];
1186    const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory);
1187    ASSERT_TRUE(memory);
1188  
1189    // Stick some data into the memory so the contents can be verified.
1190    for (uint32_t i = 0; i < kMemorySize; ++i) {
1191      memory[i] = i % 255;
1192    }
1193  
1194    AutoTempDir temp_dir;
1195    ExceptionHandler handler(
1196        MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1);
1197  
1198    // Add the memory region to the list of memory to be included.
1199    handler.RegisterAppMemory(memory, kMemorySize);
1200    handler.WriteMinidump();
1201  
1202    const MinidumpDescriptor& minidump_desc = handler.minidump_descriptor();
1203  
1204    // Read the minidump. Ensure that the memory region is present
1205    Minidump minidump(minidump_desc.path());
1206    ASSERT_TRUE(minidump.Read());
1207  
1208    MinidumpMemoryList* dump_memory_list = minidump.GetMemoryList();
1209    ASSERT_TRUE(dump_memory_list);
1210    const MinidumpMemoryRegion* region =
1211      dump_memory_list->GetMemoryRegionForAddress(kMemoryAddress);
1212    ASSERT_TRUE(region);
1213  
1214    EXPECT_EQ(kMemoryAddress, region->GetBase());
1215    EXPECT_EQ(kMemorySize, region->GetSize());
1216  
1217    // Verify memory contents.
1218    EXPECT_EQ(0, memcmp(region->GetMemory(), memory, kMemorySize));
1219  
1220    delete[] memory;
1221  }
1222  
1223  // Test that a memory region that was previously registered
1224  // can be unregistered.
1225  TEST(ExceptionHandlerTest, AdditionalMemoryRemove) {
1226    const uint32_t kMemorySize = sysconf(_SC_PAGESIZE);
1227  
1228    // Get some heap memory.
1229    uint8_t* memory = new uint8_t[kMemorySize];
1230    const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory);
1231    ASSERT_TRUE(memory);
1232  
1233    AutoTempDir temp_dir;
1234    ExceptionHandler handler(
1235        MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1);
1236  
1237    // Add the memory region to the list of memory to be included.
1238    handler.RegisterAppMemory(memory, kMemorySize);
1239  
1240    // ...and then remove it
1241    handler.UnregisterAppMemory(memory);
1242    handler.WriteMinidump();
1243  
1244    const MinidumpDescriptor& minidump_desc = handler.minidump_descriptor();
1245  
1246    // Read the minidump. Ensure that the memory region is not present.
1247    Minidump minidump(minidump_desc.path());
1248    ASSERT_TRUE(minidump.Read());
1249  
1250    MinidumpMemoryList* dump_memory_list = minidump.GetMemoryList();
1251    ASSERT_TRUE(dump_memory_list);
1252    const MinidumpMemoryRegion* region =
1253      dump_memory_list->GetMemoryRegionForAddress(kMemoryAddress);
1254    EXPECT_FALSE(region);
1255  
1256    delete[] memory;
1257  }
1258  
1259  static bool SimpleCallback(const MinidumpDescriptor& descriptor,
1260                             void* context,
1261                             bool succeeded) {
1262    string* filename = reinterpret_cast<string*>(context);
1263    *filename = descriptor.path();
1264    return true;
1265  }
1266  
1267  TEST(ExceptionHandlerTest, WriteMinidumpForChild) {
1268    int fds[2];
1269    ASSERT_NE(-1, pipe(fds));
1270  
1271    const pid_t child = fork();
1272    if (child == 0) {
1273      close(fds[1]);
1274      char b;
1275      HANDLE_EINTR(read(fds[0], &b, sizeof(b)));
1276      close(fds[0]);
1277      syscall(__NR_exit);
1278    }
1279    close(fds[0]);
1280  
1281    AutoTempDir temp_dir;
1282    string minidump_filename;
1283    ASSERT_TRUE(
1284      ExceptionHandler::WriteMinidumpForChild(child, child,
1285                                              temp_dir.path(), SimpleCallback,
1286                                              (void*)&minidump_filename));
1287  
1288    Minidump minidump(minidump_filename);
1289    ASSERT_TRUE(minidump.Read());
1290    // Check that the crashing thread is the main thread of |child|
1291    MinidumpException* exception = minidump.GetException();
1292    ASSERT_TRUE(exception);
1293    uint32_t thread_id;
1294    ASSERT_TRUE(exception->GetThreadID(&thread_id));
1295    EXPECT_EQ(child, static_cast<int32_t>(thread_id));
1296  
1297    const MDRawExceptionStream* raw = exception->exception();
1298    ASSERT_TRUE(raw);
1299    EXPECT_EQ(MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED,
1300              raw->exception_record.exception_code);
1301  
1302    close(fds[1]);
1303    unlink(minidump_filename.c_str());
1304  }