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