gecko/toolkit/crashreporter/breakpad-patches/10-user-osx-handlers.patch

86 lines
3.8 KiB
Diff

commit 79a74a58644e515c61846b71b6da42cf9b486448
Author: Vladimir Vukicevic <vladimir@pobox.com>
Date: Mon Mar 18 18:50:19 2013 -0400
Add BreakpadUserExceptionHandler support to breakpad for first-chance handling
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 db605dc..70d75ec 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
@@ -133,6 +133,22 @@ struct ExceptionReplyMessage {
#pragma pack()
#endif
+// the type of function that an exception forwarder needs to have
+typedef boolean_t (*UserExceptionHandlerFunc) (exception_type_t exception,
+#if TARGET_OSX_USE_64BIT_EXCEPTIONS
+ mach_exception_data_t code,
+#else
+ exception_data_t code,
+#endif
+ mach_msg_type_number_t code_count,
+ mach_port_t thread);
+
+// If userspace needs to see exceptions before breakpad gets to it, it should
+// define an external symbol with the name BreakpadUserExceptionHandler or
+// BreakpadUserExceptionHandler64. The latter will be used with
+// TARGET_OSX_USE_64BIT_EXCEPTIONS.
+static UserExceptionHandlerFunc s_UserExceptionHandler = NULL;
+
// Only catch these three exceptions. The other ones are nebulously defined
// and may result in treating a non-fatal exception as fatal.
exception_mask_t s_exception_mask = EXC_MASK_BAD_ACCESS |
@@ -704,6 +720,38 @@ void* ExceptionHandler::WaitForMessage(void* exception_handler_class) {
if (receive.exception == EXC_BAD_ACCESS && receive.code_count > 1)
subcode = receive.code[1];
+ if (s_UserExceptionHandler &&
+ s_UserExceptionHandler(receive.exception, receive.code, receive.code_count,
+ receive.thread.name) == TRUE) {
+ // Userspace handler got it. Create an approriate reply indicating success,
+ // and send it back to the kernel.
+ ExceptionReplyMessage reply;
+
+ // the reply needs to have msgh_id + 100
+ reply.header.msgh_id = receive.header.msgh_id + 100;
+ reply.header.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(receive.header.msgh_bits), 0);
+ reply.header.msgh_size = sizeof(reply);
+ reply.header.msgh_remote_port = receive.header.msgh_remote_port;
+ reply.header.msgh_local_port = MACH_PORT_NULL;
+
+ reply.ndr = NDR_record;
+ reply.return_code = KERN_SUCCESS;
+
+ // actually send it off
+ result = mach_msg(&(reply.header), MACH_SEND_MSG,
+ reply.header.msgh_size, 0, MACH_PORT_NULL,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+ if (result != KERN_SUCCESS) {
+ // if this failed, we're likely hung; the thread will never continue.
+ // just bail.
+ fprintf(stderr, "mach_msg reply after user exception handler returned %d!\n", result);
+ exit(1);
+ }
+
+ // go back to waiting for messages
+ continue;
+ }
+
self->SuspendThreads();
#if USE_PROTECTED_ALLOCATIONS
@@ -779,6 +827,12 @@ bool ExceptionHandler::InstallHandler() {
return false;
}
+#if TARGET_OSX_USE_64BIT_EXCEPTIONS
+ s_UserExceptionHandler = (UserExceptionHandlerFunc) dlsym(RTLD_SELF, "BreakpadUserExceptionHandler64");
+#else
+ s_UserExceptionHandler = (UserExceptionHandlerFunc) dlsym(RTLD_SELF, "BreakpadUserExceptionHandler");
+#endif
+
#if TARGET_OS_IPHONE
if (!IsOutOfProcess()) {
struct sigaction sa;