From 2153060e502ec1ebf8bf6ecc1dab1b3b1a421281 Mon Sep 17 00:00:00 2001 From: Ted Mielczarek Date: Mon, 16 Sep 2013 14:44:24 -0400 Subject: [PATCH] bug 717758 - handle abort() in Breakpad on OS X. r=mento --- .../client/mac/handler/exception_handler.cc | 2 - .../client/mac/handler/minidump_generator.cc | 13 ++++++ .../mac/tests/exception_handler_test.cc | 46 ++++++++++++++++--- 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/exception_handler.cc b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/exception_handler.cc index 98b8e069bc1b..a7e5725cf765 100644 --- a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/exception_handler.cc +++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/exception_handler.cc @@ -626,7 +626,6 @@ bool ExceptionHandler::InstallHandler() { if (gProtectedData.handler != NULL) { return false; } -#if TARGET_OS_IPHONE if (!IsOutOfProcess()) { struct sigaction sa; memset(&sa, 0, sizeof(sa)); @@ -646,7 +645,6 @@ bool ExceptionHandler::InstallHandler() { mprotect(gProtectedData.protected_buffer, PAGE_SIZE, PROT_READ); #endif } -#endif try { #if USE_PROTECTED_ALLOCATIONS diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator.cc b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator.cc index 85c53ebbb8f7..809e684fa0d2 100644 --- a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator.cc +++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator.cc @@ -787,9 +787,22 @@ bool MinidumpGenerator::GetThreadState(thread_act_t target_thread, *count = final_size; return true; } +#endif +#ifdef HAS_X86_SUPPORT + case CPU_TYPE_I386: + case CPU_TYPE_X86_64: { + size_t state_size = cpu_type_ == CPU_TYPE_I386 ? + sizeof(i386_thread_state_t) : sizeof(x86_thread_state64_t); + size_t final_size = + std::min(static_cast(*count), state_size); + memcpy(state, &task_context_->uc_mcontext->__ss, final_size); + *count = final_size; + return true; + } #endif } } + thread_state_flavor_t flavor; switch (cpu_type_) { #ifdef HAS_ARM_SUPPORT diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/tests/exception_handler_test.cc b/toolkit/crashreporter/google-breakpad/src/client/mac/tests/exception_handler_test.cc index d108d4321853..e19944d0871d 100644 --- a/toolkit/crashreporter/google-breakpad/src/client/mac/tests/exception_handler_test.cc +++ b/toolkit/crashreporter/google-breakpad/src/client/mac/tests/exception_handler_test.cc @@ -122,10 +122,46 @@ void ExceptionHandlerTest::InProcessCrash(bool aborting) { char minidump_file[PATH_MAX]; ssize_t nbytes = read(fds[0], minidump_file, sizeof(minidump_file)); ASSERT_NE(0, nbytes); - // Ensure that minidump file exists and is > 0 bytes. - struct stat st; - ASSERT_EQ(0, stat(minidump_file, &st)); - ASSERT_LT(0, st.st_size); + + Minidump minidump(minidump_file); + ASSERT_TRUE(minidump.Read()); + + MinidumpException* exception = minidump.GetException(); + ASSERT_TRUE(exception); + + const MDRawExceptionStream* raw_exception = exception->exception(); + ASSERT_TRUE(raw_exception); + + if (aborting) { + EXPECT_EQ(MD_EXCEPTION_MAC_SOFTWARE, + raw_exception->exception_record.exception_code); + EXPECT_EQ(MD_EXCEPTION_CODE_MAC_ABORT, + raw_exception->exception_record.exception_flags); + } else { + EXPECT_EQ(MD_EXCEPTION_MAC_BAD_ACCESS, + raw_exception->exception_record.exception_code); +#if defined(__x86_64__) + EXPECT_EQ(MD_EXCEPTION_CODE_MAC_INVALID_ADDRESS, + raw_exception->exception_record.exception_flags); +#elif defined(__i386__) + EXPECT_EQ(MD_EXCEPTION_CODE_MAC_PROTECTION_FAILURE, + raw_exception->exception_record.exception_flags); +#endif + } + + const MinidumpContext* context = exception->GetContext(); + ASSERT_TRUE(context); + + uint64_t instruction_pointer; + ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer)); + + // Ideally would like to sanity check that abort() is on the stack + // but that's hard. + MinidumpMemoryList* memory_list = minidump.GetMemoryList(); + ASSERT_TRUE(memory_list); + MinidumpMemoryRegion* region = + memory_list->GetMemoryRegionForAddress(instruction_pointer); + EXPECT_TRUE(region); // Child process should have exited with a zero status. int ret; @@ -138,11 +174,9 @@ TEST_F(ExceptionHandlerTest, InProcess) { InProcessCrash(false); } -#if TARGET_OS_IPHONE TEST_F(ExceptionHandlerTest, InProcessAbort) { InProcessCrash(true); } -#endif static bool DumpNameMDCallback(const char *dump_dir, const char *file_name, void *context, bool success) {