mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
86 lines
3.8 KiB
Diff
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;
|