1 // Copyright (c) 2010 Google Inc.
2 // All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
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
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.
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.
35 #include <sys/socket.h>
39 #include <sys/cachectl.h>
44 #include "breakpad_googletest_includes.h"
45 #include "client/linux/handler/exception_handler.h"
46 #include "client/linux/minidump_writer/minidump_writer.h"
47 #include "common/linux/eintr_wrapper.h"
48 #include "common/linux/file_id.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"
56 using namespace google_breakpad;
60 // Flush the instruction cache for a given memory range.
61 // Only required on ARM and mips.
62 void FlushInstructionCache(const char* memory, uint32_t memory_size) {
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
74 syscall(__ARM_NR_cacheflush, begin, end, 0);
76 # error "Your operating system is not supported yet"
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 cacheflush(begin, end, 0);
84 # elif defined(__linux__)
85 // See http://www.linux-mips.org/wiki/Cacheflush_Syscall.
86 cacheflush(const_cast<char*>(memory), memory_size, ICACHE);
88 # error "Your operating system is not supported yet"
93 // Length of a formatted GUID string =
94 // sizeof(MDGUID) * 2 + 4 (for dashes) + 1 (null terminator)
95 const int kGUIDStringSize = 37;
97 void sigchld_handler(int signo) { }
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);
111 class ExceptionHandlerTest : public ::testing::Test {
114 // We need to be able to wait for children, so SIGCHLD cannot be SIG_IGN.
116 memset(&sa, 0, sizeof(sa));
117 sa.sa_handler = sigchld_handler;
118 ASSERT_NE(sigaction(SIGCHLD, &sa, &old_action), -1);
122 sigaction(SIGCHLD, &old_action, NULL);
125 struct sigaction old_action;
129 void WaitForProcessToTerminate(pid_t process_id, int expected_status) {
131 ASSERT_NE(HANDLE_EINTR(waitpid(process_id, &status, 0)), -1);
132 ASSERT_TRUE(WIFSIGNALED(status));
133 ASSERT_EQ(expected_status, WTERMSIG(status));
136 // Reads the minidump path sent over the pipe |fd| and sets it in |path|.
137 void ReadMinidumpPathFromPipe(int fd, string* path) {
139 memset(&pfd, 0, sizeof(pfd));
141 pfd.events = POLLIN | POLLERR;
143 const int r = HANDLE_EINTR(poll(&pfd, 1, 0));
145 ASSERT_TRUE(pfd.revents & POLLIN);
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));
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());
170 TEST(ExceptionHandlerTest, SimpleWithFD) {
171 AutoTempDir temp_dir;
173 const int fd = CreateTMPFile(temp_dir.path(), &path);
174 ExceptionHandler handler(MinidumpDescriptor(fd), NULL, NULL, NULL, true, -1);
178 static bool DoneCallback(const MinidumpDescriptor& descriptor,
184 if (!descriptor.IsFD()) {
185 int fd = reinterpret_cast<intptr_t>(context);
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)));
194 #ifndef ADDRESS_SANITIZER
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
204 volatile int *p_null; // external linkage, so GCC can't tell that it
205 // remains NULL. Volatile just for a good measure.
206 static void DoNullPointerDereference() {
210 void ChildCrash(bool use_fd) {
211 AutoTempDir temp_dir;
213 int minidump_fd = -1;
214 string minidump_path;
216 minidump_fd = CreateTMPFile(temp_dir.path(), &minidump_path);
218 ASSERT_NE(pipe(fds), -1);
221 const pid_t child = fork();
224 google_breakpad::scoped_ptr<ExceptionHandler> handler;
226 handler.reset(new ExceptionHandler(MinidumpDescriptor(minidump_fd),
227 NULL, NULL, NULL, true, -1));
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,
235 // Crash with the exception handler in scope.
236 DoNullPointerDereference();
240 close(fds[1]); // Close the writting end.
242 ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
245 ASSERT_NO_FATAL_FAILURE(ReadMinidumpPathFromPipe(fds[0], &minidump_path));
248 ASSERT_EQ(0, stat(minidump_path.c_str(), &st));
249 ASSERT_GT(st.st_size, 0);
250 unlink(minidump_path.c_str());
253 TEST(ExceptionHandlerTest, ChildCrashWithPath) {
254 ASSERT_NO_FATAL_FAILURE(ChildCrash(false));
257 TEST(ExceptionHandlerTest, ChildCrashWithFD) {
258 ASSERT_NO_FATAL_FAILURE(ChildCrash(true));
261 #endif // !ADDRESS_SANITIZER
263 static bool DoneCallbackReturnFalse(const MinidumpDescriptor& descriptor,
269 static bool DoneCallbackReturnTrue(const MinidumpDescriptor& descriptor,
275 static bool DoneCallbackRaiseSIGKILL(const MinidumpDescriptor& descriptor,
282 static bool FilterCallbackReturnFalse(void* context) {
286 static bool FilterCallbackReturnTrue(void* context) {
290 // SIGKILL cannot be blocked and a handler cannot be installed for it. In the
291 // following tests, if the child dies with signal SIGKILL, then the signal was
292 // redelivered to this handler. If the child dies with SIGSEGV then it wasn't.
293 static void RaiseSIGKILL(int sig) {
297 static bool InstallRaiseSIGKILL() {
299 memset(&sa, 0, sizeof(sa));
300 sa.sa_handler = RaiseSIGKILL;
301 return sigaction(SIGSEGV, &sa, NULL) != -1;
304 #ifndef ADDRESS_SANITIZER
306 static void CrashWithCallbacks(ExceptionHandler::FilterCallback filter,
307 ExceptionHandler::MinidumpCallback done,
309 ExceptionHandler handler(
310 MinidumpDescriptor(path), filter, done, NULL, true, -1);
311 // Crash with the exception handler in scope.
312 DoNullPointerDereference();
315 TEST(ExceptionHandlerTest, RedeliveryOnFilterCallbackFalse) {
316 AutoTempDir temp_dir;
318 const pid_t child = fork();
320 ASSERT_TRUE(InstallRaiseSIGKILL());
321 CrashWithCallbacks(FilterCallbackReturnFalse, NULL, temp_dir.path());
324 ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
327 TEST(ExceptionHandlerTest, RedeliveryOnDoneCallbackFalse) {
328 AutoTempDir temp_dir;
330 const pid_t child = fork();
332 ASSERT_TRUE(InstallRaiseSIGKILL());
333 CrashWithCallbacks(NULL, DoneCallbackReturnFalse, temp_dir.path());
336 ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
339 TEST(ExceptionHandlerTest, NoRedeliveryOnDoneCallbackTrue) {
340 AutoTempDir temp_dir;
342 const pid_t child = fork();
344 ASSERT_TRUE(InstallRaiseSIGKILL());
345 CrashWithCallbacks(NULL, DoneCallbackReturnTrue, temp_dir.path());
348 ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
351 TEST(ExceptionHandlerTest, NoRedeliveryOnFilterCallbackTrue) {
352 AutoTempDir temp_dir;
354 const pid_t child = fork();
356 ASSERT_TRUE(InstallRaiseSIGKILL());
357 CrashWithCallbacks(FilterCallbackReturnTrue, NULL, temp_dir.path());
360 ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
363 TEST(ExceptionHandlerTest, RedeliveryToDefaultHandler) {
364 AutoTempDir temp_dir;
366 const pid_t child = fork();
368 CrashWithCallbacks(FilterCallbackReturnFalse, NULL, temp_dir.path());
371 // As RaiseSIGKILL wasn't installed, the redelivery should just kill the child
373 ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
376 // Check that saving and restoring the signal handler with 'signal'
377 // instead of 'sigaction' doesn't make the Breakpad signal handler
378 // crash. See comments in ExceptionHandler::SignalHandler for full
380 TEST(ExceptionHandlerTest, RedeliveryOnBadSignalHandlerFlag) {
381 AutoTempDir temp_dir;
382 const pid_t child = fork();
384 // Install the RaiseSIGKILL handler for SIGSEGV.
385 ASSERT_TRUE(InstallRaiseSIGKILL());
387 // Create a new exception handler, this installs a new SIGSEGV
388 // handler, after saving the old one.
389 ExceptionHandler handler(
390 MinidumpDescriptor(temp_dir.path()), NULL,
391 DoneCallbackReturnFalse, NULL, true, -1);
393 // Install the default SIGSEGV handler, saving the current one.
394 // Then re-install the current one with 'signal', this loses the
395 // SA_SIGINFO flag associated with the Breakpad handler.
396 sighandler_t old_handler = signal(SIGSEGV, SIG_DFL);
397 ASSERT_NE(reinterpret_cast<void*>(old_handler),
398 reinterpret_cast<void*>(SIG_ERR));
399 ASSERT_NE(reinterpret_cast<void*>(signal(SIGSEGV, old_handler)),
400 reinterpret_cast<void*>(SIG_ERR));
402 // Crash with the exception handler in scope.
403 DoNullPointerDereference();
405 // SIGKILL means Breakpad's signal handler didn't crash.
406 ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
409 TEST(ExceptionHandlerTest, StackedHandlersDeliveredToTop) {
410 AutoTempDir temp_dir;
412 const pid_t child = fork();
414 ExceptionHandler bottom(MinidumpDescriptor(temp_dir.path()),
420 CrashWithCallbacks(NULL, DoneCallbackRaiseSIGKILL, temp_dir.path());
422 ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
425 TEST(ExceptionHandlerTest, StackedHandlersNotDeliveredToBottom) {
426 AutoTempDir temp_dir;
428 const pid_t child = fork();
430 ExceptionHandler bottom(MinidumpDescriptor(temp_dir.path()),
432 DoneCallbackRaiseSIGKILL,
436 CrashWithCallbacks(NULL, NULL, temp_dir.path());
438 ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
441 TEST(ExceptionHandlerTest, StackedHandlersFilteredToBottom) {
442 AutoTempDir temp_dir;
444 const pid_t child = fork();
446 ExceptionHandler bottom(MinidumpDescriptor(temp_dir.path()),
448 DoneCallbackRaiseSIGKILL,
452 CrashWithCallbacks(FilterCallbackReturnFalse, NULL, temp_dir.path());
454 ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
457 TEST(ExceptionHandlerTest, StackedHandlersUnhandledToBottom) {
458 AutoTempDir temp_dir;
460 const pid_t child = fork();
462 ExceptionHandler bottom(MinidumpDescriptor(temp_dir.path()),
464 DoneCallbackRaiseSIGKILL,
468 CrashWithCallbacks(NULL, DoneCallbackReturnFalse, temp_dir.path());
470 ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
473 #endif // !ADDRESS_SANITIZER
475 const unsigned char kIllegalInstruction[] = {
476 #if defined(__mips__)
477 // mfc2 zero,Impl - usually illegal in userspace.
478 0x48, 0x00, 0x00, 0x48
480 // This crashes with SIGILL on x86/x86-64/arm.
481 0xff, 0xff, 0xff, 0xff
485 // Test that memory around the instruction pointer is written
486 // to the dump as a MinidumpMemoryRegion.
487 TEST(ExceptionHandlerTest, InstructionPointerMemory) {
488 AutoTempDir temp_dir;
490 ASSERT_NE(pipe(fds), -1);
492 // These are defined here so the parent can use them to check the
493 // data from the minidump afterwards.
494 const uint32_t kMemorySize = 256; // bytes
495 const int kOffset = kMemorySize / 2;
497 const pid_t child = fork();
500 ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL,
501 DoneCallback, reinterpret_cast<void*>(fds[1]),
503 // Get some executable memory.
505 reinterpret_cast<char*>(mmap(NULL,
507 PROT_READ | PROT_WRITE | PROT_EXEC,
508 MAP_PRIVATE | MAP_ANON,
514 // Write some instructions that will crash. Put them in the middle
515 // of the block of memory, because the minidump should contain 128
516 // bytes on either side of the instruction pointer.
517 memcpy(memory + kOffset, kIllegalInstruction, sizeof(kIllegalInstruction));
518 FlushInstructionCache(memory, kMemorySize);
520 // Now execute the instructions, which should crash.
521 typedef void (*void_function)(void);
522 void_function memory_function =
523 reinterpret_cast<void_function>(memory + kOffset);
528 ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGILL));
530 string minidump_path;
531 ASSERT_NO_FATAL_FAILURE(ReadMinidumpPathFromPipe(fds[0], &minidump_path));
534 ASSERT_EQ(0, stat(minidump_path.c_str(), &st));
535 ASSERT_GT(st.st_size, 0);
537 // Read the minidump. Locate the exception record and the
538 // memory list, and then ensure that there is a memory region
539 // in the memory list that covers the instruction pointer from
540 // the exception record.
541 Minidump minidump(minidump_path);
542 ASSERT_TRUE(minidump.Read());
544 MinidumpException* exception = minidump.GetException();
545 MinidumpMemoryList* memory_list = minidump.GetMemoryList();
546 ASSERT_TRUE(exception);
547 ASSERT_TRUE(memory_list);
548 ASSERT_LT(0U, memory_list->region_count());
550 MinidumpContext* context = exception->GetContext();
551 ASSERT_TRUE(context);
553 uint64_t instruction_pointer;
554 ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
556 MinidumpMemoryRegion* region =
557 memory_list->GetMemoryRegionForAddress(instruction_pointer);
560 EXPECT_EQ(kMemorySize, region->GetSize());
561 const uint8_t* bytes = region->GetMemory();
564 uint8_t prefix_bytes[kOffset];
565 uint8_t suffix_bytes[kMemorySize - kOffset - sizeof(kIllegalInstruction)];
566 memset(prefix_bytes, 0, sizeof(prefix_bytes));
567 memset(suffix_bytes, 0, sizeof(suffix_bytes));
568 EXPECT_TRUE(memcmp(bytes, prefix_bytes, sizeof(prefix_bytes)) == 0);
569 EXPECT_TRUE(memcmp(bytes + kOffset, kIllegalInstruction,
570 sizeof(kIllegalInstruction)) == 0);
571 EXPECT_TRUE(memcmp(bytes + kOffset + sizeof(kIllegalInstruction),
572 suffix_bytes, sizeof(suffix_bytes)) == 0);
574 unlink(minidump_path.c_str());
577 // Test that the memory region around the instruction pointer is
578 // bounded correctly on the low end.
579 TEST(ExceptionHandlerTest, InstructionPointerMemoryMinBound) {
580 AutoTempDir temp_dir;
582 ASSERT_NE(pipe(fds), -1);
584 // These are defined here so the parent can use them to check the
585 // data from the minidump afterwards.
586 const uint32_t kMemorySize = 256; // bytes
587 const int kOffset = 0;
589 const pid_t child = fork();
592 ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL,
593 DoneCallback, reinterpret_cast<void*>(fds[1]),
595 // Get some executable memory.
597 reinterpret_cast<char*>(mmap(NULL,
599 PROT_READ | PROT_WRITE | PROT_EXEC,
600 MAP_PRIVATE | MAP_ANON,
606 // Write some instructions that will crash. Put them in the middle
607 // of the block of memory, because the minidump should contain 128
608 // bytes on either side of the instruction pointer.
609 memcpy(memory + kOffset, kIllegalInstruction, sizeof(kIllegalInstruction));
610 FlushInstructionCache(memory, kMemorySize);
612 // Now execute the instructions, which should crash.
613 typedef void (*void_function)(void);
614 void_function memory_function =
615 reinterpret_cast<void_function>(memory + kOffset);
620 ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGILL));
622 string minidump_path;
623 ASSERT_NO_FATAL_FAILURE(ReadMinidumpPathFromPipe(fds[0], &minidump_path));
626 ASSERT_EQ(0, stat(minidump_path.c_str(), &st));
627 ASSERT_GT(st.st_size, 0);
629 // Read the minidump. Locate the exception record and the
630 // memory list, and then ensure that there is a memory region
631 // in the memory list that covers the instruction pointer from
632 // the exception record.
633 Minidump minidump(minidump_path);
634 ASSERT_TRUE(minidump.Read());
636 MinidumpException* exception = minidump.GetException();
637 MinidumpMemoryList* memory_list = minidump.GetMemoryList();
638 ASSERT_TRUE(exception);
639 ASSERT_TRUE(memory_list);
640 ASSERT_LT(0U, memory_list->region_count());
642 MinidumpContext* context = exception->GetContext();
643 ASSERT_TRUE(context);
645 uint64_t instruction_pointer;
646 ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
648 MinidumpMemoryRegion* region =
649 memory_list->GetMemoryRegionForAddress(instruction_pointer);
652 EXPECT_EQ(kMemorySize / 2, region->GetSize());
653 const uint8_t* bytes = region->GetMemory();
656 uint8_t suffix_bytes[kMemorySize / 2 - sizeof(kIllegalInstruction)];
657 memset(suffix_bytes, 0, sizeof(suffix_bytes));
658 EXPECT_TRUE(memcmp(bytes + kOffset, kIllegalInstruction,
659 sizeof(kIllegalInstruction)) == 0);
660 EXPECT_TRUE(memcmp(bytes + kOffset + sizeof(kIllegalInstruction),
661 suffix_bytes, sizeof(suffix_bytes)) == 0);
662 unlink(minidump_path.c_str());
665 // Test that the memory region around the instruction pointer is
666 // bounded correctly on the high end.
667 TEST(ExceptionHandlerTest, InstructionPointerMemoryMaxBound) {
668 AutoTempDir temp_dir;
670 ASSERT_NE(pipe(fds), -1);
672 // These are defined here so the parent can use them to check the
673 // data from the minidump afterwards.
674 // Use 4k here because the OS will hand out a single page even
675 // if a smaller size is requested, and this test wants to
676 // test the upper bound of the memory range.
677 const uint32_t kMemorySize = 4096; // bytes
678 const int kOffset = kMemorySize - sizeof(kIllegalInstruction);
680 const pid_t child = fork();
683 ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL,
684 DoneCallback, reinterpret_cast<void*>(fds[1]),
686 // Get some executable memory.
688 reinterpret_cast<char*>(mmap(NULL,
690 PROT_READ | PROT_WRITE | PROT_EXEC,
691 MAP_PRIVATE | MAP_ANON,
697 // Write some instructions that will crash. Put them in the middle
698 // of the block of memory, because the minidump should contain 128
699 // bytes on either side of the instruction pointer.
700 memcpy(memory + kOffset, kIllegalInstruction, sizeof(kIllegalInstruction));
701 FlushInstructionCache(memory, kMemorySize);
703 // Now execute the instructions, which should crash.
704 typedef void (*void_function)(void);
705 void_function memory_function =
706 reinterpret_cast<void_function>(memory + kOffset);
711 ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGILL));
713 string minidump_path;
714 ASSERT_NO_FATAL_FAILURE(ReadMinidumpPathFromPipe(fds[0], &minidump_path));
717 ASSERT_EQ(0, stat(minidump_path.c_str(), &st));
718 ASSERT_GT(st.st_size, 0);
720 // Read the minidump. Locate the exception record and the memory list, and
721 // then ensure that there is a memory region in the memory list that covers
722 // the instruction pointer from the exception record.
723 Minidump minidump(minidump_path);
724 ASSERT_TRUE(minidump.Read());
726 MinidumpException* exception = minidump.GetException();
727 MinidumpMemoryList* memory_list = minidump.GetMemoryList();
728 ASSERT_TRUE(exception);
729 ASSERT_TRUE(memory_list);
730 ASSERT_LT(0U, memory_list->region_count());
732 MinidumpContext* context = exception->GetContext();
733 ASSERT_TRUE(context);
735 uint64_t instruction_pointer;
736 ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
738 MinidumpMemoryRegion* region =
739 memory_list->GetMemoryRegionForAddress(instruction_pointer);
742 const size_t kPrefixSize = 128; // bytes
743 EXPECT_EQ(kPrefixSize + sizeof(kIllegalInstruction), region->GetSize());
744 const uint8_t* bytes = region->GetMemory();
747 uint8_t prefix_bytes[kPrefixSize];
748 memset(prefix_bytes, 0, sizeof(prefix_bytes));
749 EXPECT_TRUE(memcmp(bytes, prefix_bytes, sizeof(prefix_bytes)) == 0);
750 EXPECT_TRUE(memcmp(bytes + kPrefixSize,
751 kIllegalInstruction, sizeof(kIllegalInstruction)) == 0);
753 unlink(minidump_path.c_str());
756 #ifndef ADDRESS_SANITIZER
758 // Ensure that an extra memory block doesn't get added when the instruction
759 // pointer is not in mapped memory.
760 TEST(ExceptionHandlerTest, InstructionPointerMemoryNullPointer) {
761 AutoTempDir temp_dir;
763 ASSERT_NE(pipe(fds), -1);
765 const pid_t child = fork();
768 ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL,
769 DoneCallback, reinterpret_cast<void*>(fds[1]),
771 // Try calling a NULL pointer.
772 typedef void (*void_function)(void);
773 void_function memory_function = reinterpret_cast<void_function>(NULL);
778 ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
780 string minidump_path;
781 ASSERT_NO_FATAL_FAILURE(ReadMinidumpPathFromPipe(fds[0], &minidump_path));
784 ASSERT_EQ(0, stat(minidump_path.c_str(), &st));
785 ASSERT_GT(st.st_size, 0);
787 // Read the minidump. Locate the exception record and the
788 // memory list, and then ensure that there is a memory region
789 // in the memory list that covers the instruction pointer from
790 // the exception record.
791 Minidump minidump(minidump_path);
792 ASSERT_TRUE(minidump.Read());
794 MinidumpException* exception = minidump.GetException();
795 MinidumpMemoryList* memory_list = minidump.GetMemoryList();
796 ASSERT_TRUE(exception);
797 ASSERT_TRUE(memory_list);
798 ASSERT_EQ(static_cast<unsigned int>(1), memory_list->region_count());
800 unlink(minidump_path.c_str());
803 #endif // !ADDRESS_SANITIZER
805 // Test that anonymous memory maps can be annotated with names and IDs.
806 TEST(ExceptionHandlerTest, ModuleInfo) {
807 // These are defined here so the parent can use them to check the
808 // data from the minidump afterwards.
809 const uint32_t kMemorySize = sysconf(_SC_PAGESIZE);
810 const char* kMemoryName = "a fake module";
811 const uint8_t kModuleGUID[sizeof(MDGUID)] = {
812 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
813 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
815 char module_identifier_buffer[kGUIDStringSize];
816 FileID::ConvertIdentifierToString(kModuleGUID,
817 module_identifier_buffer,
818 sizeof(module_identifier_buffer));
819 string module_identifier(module_identifier_buffer);
822 while ((pos = module_identifier.find('-')) != string::npos) {
823 module_identifier.erase(pos, 1);
825 // And append a zero, because module IDs include an "age" field
826 // which is always zero on Linux.
827 module_identifier += "0";
831 reinterpret_cast<char*>(mmap(NULL,
833 PROT_READ | PROT_WRITE,
834 MAP_PRIVATE | MAP_ANON,
837 const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory);
840 AutoTempDir temp_dir;
841 ExceptionHandler handler(
842 MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1);
844 // Add info about the anonymous memory mapping.
845 handler.AddMappingInfo(kMemoryName,
850 ASSERT_TRUE(handler.WriteMinidump());
852 const MinidumpDescriptor& minidump_desc = handler.minidump_descriptor();
853 // Read the minidump. Load the module list, and ensure that the mmap'ed
854 // |memory| is listed with the given module name and debug ID.
855 Minidump minidump(minidump_desc.path());
856 ASSERT_TRUE(minidump.Read());
858 MinidumpModuleList* module_list = minidump.GetModuleList();
859 ASSERT_TRUE(module_list);
860 const MinidumpModule* module =
861 module_list->GetModuleForAddress(kMemoryAddress);
864 EXPECT_EQ(kMemoryAddress, module->base_address());
865 EXPECT_EQ(kMemorySize, module->size());
866 EXPECT_EQ(kMemoryName, module->code_file());
867 EXPECT_EQ(module_identifier, module->debug_identifier());
869 unlink(minidump_desc.path());
872 static const unsigned kControlMsgSize =
873 CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(struct ucred));
876 CrashHandler(const void* crash_context, size_t crash_context_size,
878 const int fd = (intptr_t) context;
880 if (pipe(fds) == -1) {
881 // There doesn't seem to be any way to reliably handle
882 // this failure without the parent process hanging
883 // At least make sure that this process doesn't access
884 // unexpected file descriptors
888 struct kernel_msghdr msg = {0};
889 struct kernel_iovec iov;
890 iov.iov_base = const_cast<void*>(crash_context);
891 iov.iov_len = crash_context_size;
894 char cmsg[kControlMsgSize];
895 memset(cmsg, 0, kControlMsgSize);
896 msg.msg_control = cmsg;
897 msg.msg_controllen = sizeof(cmsg);
899 struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg);
900 hdr->cmsg_level = SOL_SOCKET;
901 hdr->cmsg_type = SCM_RIGHTS;
902 hdr->cmsg_len = CMSG_LEN(sizeof(int));
903 *((int*) CMSG_DATA(hdr)) = fds[1];
904 hdr = CMSG_NXTHDR((struct msghdr*) &msg, hdr);
905 hdr->cmsg_level = SOL_SOCKET;
906 hdr->cmsg_type = SCM_CREDENTIALS;
907 hdr->cmsg_len = CMSG_LEN(sizeof(struct ucred));
908 struct ucred *cred = reinterpret_cast<struct ucred*>(CMSG_DATA(hdr));
909 cred->uid = getuid();
910 cred->gid = getgid();
911 cred->pid = getpid();
913 ssize_t ret = HANDLE_EINTR(sys_sendmsg(fd, &msg, 0));
919 IGNORE_RET(HANDLE_EINTR(sys_read(fds[0], &b, 1)));
924 #ifndef ADDRESS_SANITIZER
926 TEST(ExceptionHandlerTest, ExternalDumper) {
928 ASSERT_NE(socketpair(AF_UNIX, SOCK_DGRAM, 0, fds), -1);
929 static const int on = 1;
930 setsockopt(fds[0], SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
931 setsockopt(fds[1], SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
933 const pid_t child = fork();
936 ExceptionHandler handler(MinidumpDescriptor("/tmp1"), NULL, NULL,
937 reinterpret_cast<void*>(fds[1]), true, -1);
938 handler.set_crash_handler(CrashHandler);
939 DoNullPointerDereference();
942 struct msghdr msg = {0};
944 static const unsigned kCrashContextSize =
945 sizeof(ExceptionHandler::CrashContext);
946 char context[kCrashContextSize];
947 char control[kControlMsgSize];
948 iov.iov_base = context;
949 iov.iov_len = kCrashContextSize;
952 msg.msg_control = control;
953 msg.msg_controllen = kControlMsgSize;
955 const ssize_t n = HANDLE_EINTR(recvmsg(fds[0], &msg, 0));
956 ASSERT_EQ(static_cast<ssize_t>(kCrashContextSize), n);
957 ASSERT_EQ(kControlMsgSize, msg.msg_controllen);
958 ASSERT_EQ(static_cast<typeof(msg.msg_flags)>(0), msg.msg_flags);
959 ASSERT_EQ(0, close(fds[0]));
961 pid_t crashing_pid = -1;
963 for (struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); hdr;
964 hdr = CMSG_NXTHDR(&msg, hdr)) {
965 if (hdr->cmsg_level != SOL_SOCKET)
967 if (hdr->cmsg_type == SCM_RIGHTS) {
968 const unsigned len = hdr->cmsg_len -
969 (((uint8_t*)CMSG_DATA(hdr)) - (uint8_t*)hdr);
970 ASSERT_EQ(sizeof(int), len);
971 signal_fd = *(reinterpret_cast<int*>(CMSG_DATA(hdr)));
972 } else if (hdr->cmsg_type == SCM_CREDENTIALS) {
973 const struct ucred *cred =
974 reinterpret_cast<struct ucred*>(CMSG_DATA(hdr));
975 crashing_pid = cred->pid;
979 ASSERT_NE(crashing_pid, -1);
980 ASSERT_NE(signal_fd, -1);
982 AutoTempDir temp_dir;
983 string templ = temp_dir.path() + "/exception-handler-unittest";
984 ASSERT_TRUE(WriteMinidump(templ.c_str(), crashing_pid, context,
986 static const char b = 0;
987 ASSERT_EQ(1, (HANDLE_EINTR(write(signal_fd, &b, 1))));
988 ASSERT_EQ(0, close(signal_fd));
990 ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
993 ASSERT_EQ(0, stat(templ.c_str(), &st));
994 ASSERT_GT(st.st_size, 0);
995 unlink(templ.c_str());
998 #endif // !ADDRESS_SANITIZER
1000 TEST(ExceptionHandlerTest, WriteMinidumpExceptionStream) {
1001 AutoTempDir temp_dir;
1002 ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL, NULL,
1004 ASSERT_TRUE(handler.WriteMinidump());
1006 string minidump_path = handler.minidump_descriptor().path();
1008 // Read the minidump and check the exception stream.
1009 Minidump minidump(minidump_path);
1010 ASSERT_TRUE(minidump.Read());
1011 MinidumpException* exception = minidump.GetException();
1012 ASSERT_TRUE(exception);
1013 const MDRawExceptionStream* raw = exception->exception();
1015 EXPECT_EQ(MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED,
1016 raw->exception_record.exception_code);
1019 TEST(ExceptionHandlerTest, GenerateMultipleDumpsWithFD) {
1020 AutoTempDir temp_dir;
1022 const int fd = CreateTMPFile(temp_dir.path(), &path);
1023 ExceptionHandler handler(MinidumpDescriptor(fd), NULL, NULL, NULL, false, -1);
1024 ASSERT_TRUE(handler.WriteMinidump());
1025 // Check by the size of the data written to the FD that a minidump was
1027 off_t size = lseek(fd, 0, SEEK_CUR);
1030 // Generate another minidump.
1031 ASSERT_TRUE(handler.WriteMinidump());
1032 size = lseek(fd, 0, SEEK_CUR);
1036 TEST(ExceptionHandlerTest, GenerateMultipleDumpsWithPath) {
1037 AutoTempDir temp_dir;
1038 ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL, NULL,
1040 ASSERT_TRUE(handler.WriteMinidump());
1042 const MinidumpDescriptor& minidump_1 = handler.minidump_descriptor();
1044 ASSERT_EQ(0, stat(minidump_1.path(), &st));
1045 ASSERT_GT(st.st_size, 0);
1046 string minidump_1_path(minidump_1.path());
1047 // Check it is a valid minidump.
1048 Minidump minidump1(minidump_1_path);
1049 ASSERT_TRUE(minidump1.Read());
1050 unlink(minidump_1.path());
1052 // Generate another minidump, it should go to a different file.
1053 ASSERT_TRUE(handler.WriteMinidump());
1054 const MinidumpDescriptor& minidump_2 = handler.minidump_descriptor();
1055 ASSERT_EQ(0, stat(minidump_2.path(), &st));
1056 ASSERT_GT(st.st_size, 0);
1057 string minidump_2_path(minidump_2.path());
1058 // Check it is a valid minidump.
1059 Minidump minidump2(minidump_2_path);
1060 ASSERT_TRUE(minidump2.Read());
1061 unlink(minidump_2.path());
1063 // 2 distinct files should be produced.
1064 ASSERT_STRNE(minidump_1_path.c_str(), minidump_2_path.c_str());
1067 // Test that an additional memory region can be added to the minidump.
1068 TEST(ExceptionHandlerTest, AdditionalMemory) {
1069 const uint32_t kMemorySize = sysconf(_SC_PAGESIZE);
1071 // Get some heap memory.
1072 uint8_t* memory = new uint8_t[kMemorySize];
1073 const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory);
1074 ASSERT_TRUE(memory);
1076 // Stick some data into the memory so the contents can be verified.
1077 for (uint32_t i = 0; i < kMemorySize; ++i) {
1078 memory[i] = i % 255;
1081 AutoTempDir temp_dir;
1082 ExceptionHandler handler(
1083 MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1);
1085 // Add the memory region to the list of memory to be included.
1086 handler.RegisterAppMemory(memory, kMemorySize);
1087 handler.WriteMinidump();
1089 const MinidumpDescriptor& minidump_desc = handler.minidump_descriptor();
1091 // Read the minidump. Ensure that the memory region is present
1092 Minidump minidump(minidump_desc.path());
1093 ASSERT_TRUE(minidump.Read());
1095 MinidumpMemoryList* dump_memory_list = minidump.GetMemoryList();
1096 ASSERT_TRUE(dump_memory_list);
1097 const MinidumpMemoryRegion* region =
1098 dump_memory_list->GetMemoryRegionForAddress(kMemoryAddress);
1099 ASSERT_TRUE(region);
1101 EXPECT_EQ(kMemoryAddress, region->GetBase());
1102 EXPECT_EQ(kMemorySize, region->GetSize());
1104 // Verify memory contents.
1105 EXPECT_EQ(0, memcmp(region->GetMemory(), memory, kMemorySize));
1110 // Test that a memory region that was previously registered
1111 // can be unregistered.
1112 TEST(ExceptionHandlerTest, AdditionalMemoryRemove) {
1113 const uint32_t kMemorySize = sysconf(_SC_PAGESIZE);
1115 // Get some heap memory.
1116 uint8_t* memory = new uint8_t[kMemorySize];
1117 const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory);
1118 ASSERT_TRUE(memory);
1120 AutoTempDir temp_dir;
1121 ExceptionHandler handler(
1122 MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1);
1124 // Add the memory region to the list of memory to be included.
1125 handler.RegisterAppMemory(memory, kMemorySize);
1127 // ...and then remove it
1128 handler.UnregisterAppMemory(memory);
1129 handler.WriteMinidump();
1131 const MinidumpDescriptor& minidump_desc = handler.minidump_descriptor();
1133 // Read the minidump. Ensure that the memory region is not present.
1134 Minidump minidump(minidump_desc.path());
1135 ASSERT_TRUE(minidump.Read());
1137 MinidumpMemoryList* dump_memory_list = minidump.GetMemoryList();
1138 ASSERT_TRUE(dump_memory_list);
1139 const MinidumpMemoryRegion* region =
1140 dump_memory_list->GetMemoryRegionForAddress(kMemoryAddress);
1141 EXPECT_FALSE(region);
1146 static bool SimpleCallback(const MinidumpDescriptor& descriptor,
1149 string* filename = reinterpret_cast<string*>(context);
1150 *filename = descriptor.path();
1154 TEST(ExceptionHandlerTest, WriteMinidumpForChild) {
1156 ASSERT_NE(-1, pipe(fds));
1158 const pid_t child = fork();
1162 HANDLE_EINTR(read(fds[0], &b, sizeof(b)));
1168 AutoTempDir temp_dir;
1169 string minidump_filename;
1171 ExceptionHandler::WriteMinidumpForChild(child, child,
1172 temp_dir.path(), SimpleCallback,
1173 (void*)&minidump_filename));
1175 Minidump minidump(minidump_filename);
1176 ASSERT_TRUE(minidump.Read());
1177 // Check that the crashing thread is the main thread of |child|
1178 MinidumpException* exception = minidump.GetException();
1179 ASSERT_TRUE(exception);
1181 ASSERT_TRUE(exception->GetThreadID(&thread_id));
1182 EXPECT_EQ(child, static_cast<int32_t>(thread_id));
1184 const MDRawExceptionStream* raw = exception->exception();
1186 EXPECT_EQ(MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED,
1187 raw->exception_record.exception_code);
1190 unlink(minidump_filename.c_str());