diff --git a/src/client/mac/handler/exception_handler.cc b/src/client/mac/handler/exception_handler.cc index 686b980d..d28c0772 100644 --- a/src/client/mac/handler/exception_handler.cc +++ b/src/client/mac/handler/exception_handler.cc @@ -28,6 +28,8 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include +#include #include #include #include @@ -99,6 +101,7 @@ struct ExceptionReplyMessage { exception_mask_t s_exception_mask = EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC | EXC_MASK_BREAKPOINT; +#if !TARGET_OS_IPHONE extern "C" { // Forward declarations for functions that need "C" style compilation @@ -114,53 +117,98 @@ extern "C" exception_data_t code, mach_msg_type_number_t code_count) __attribute__((visibility("default"))); - - kern_return_t ForwardException(mach_port_t task, - mach_port_t failed_thread, - exception_type_t exception, - exception_data_t code, - mach_msg_type_number_t code_count); - - kern_return_t exception_raise(mach_port_t target_port, - mach_port_t failed_thread, - mach_port_t task, - exception_type_t exception, - exception_data_t exception_code, - mach_msg_type_number_t exception_code_count); - - kern_return_t - exception_raise_state(mach_port_t target_port, - mach_port_t failed_thread, - mach_port_t task, - exception_type_t exception, - exception_data_t exception_code, - mach_msg_type_number_t code_count, - thread_state_flavor_t *target_flavor, - thread_state_t in_thread_state, - mach_msg_type_number_t in_thread_state_count, - thread_state_t out_thread_state, - mach_msg_type_number_t *out_thread_state_count); - - kern_return_t - exception_raise_state_identity(mach_port_t target_port, - mach_port_t failed_thread, - mach_port_t task, - exception_type_t exception, - exception_data_t exception_code, - mach_msg_type_number_t exception_code_count, - thread_state_flavor_t *target_flavor, - thread_state_t in_thread_state, - mach_msg_type_number_t in_thread_state_count, - thread_state_t out_thread_state, - mach_msg_type_number_t *out_thread_state_count); } +#endif + +kern_return_t ForwardException(mach_port_t task, + mach_port_t failed_thread, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t code_count); + +#if TARGET_OS_IPHONE +// Implementation is based on the implementation generated by mig. +boolean_t breakpad_exc_server(mach_msg_header_t *InHeadP, + mach_msg_header_t *OutHeadP) { + OutHeadP->msgh_bits = + MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(InHeadP->msgh_bits), 0); + OutHeadP->msgh_remote_port = InHeadP->msgh_remote_port; + /* Minimal size: routine() will update it if different */ + OutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t); + OutHeadP->msgh_local_port = MACH_PORT_NULL; + OutHeadP->msgh_id = InHeadP->msgh_id + 100; + + if (InHeadP->msgh_id != 2401) { + ((mig_reply_error_t *)OutHeadP)->NDR = NDR_record; + ((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID; + return FALSE; + } + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + integer_t code[2]; + mach_msg_trailer_t trailer; + } Request; + + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + } Reply; +#ifdef __MigPackStructs +#pragma pack() +#endif + + Request *In0P = (Request *)InHeadP; + Reply *OutP = (Reply *)OutHeadP; + + if (In0P->task.name != mach_task_self()) { + return FALSE; + } + OutP->RetCode = ForwardException(In0P->task.name, + In0P->thread.name, + In0P->exception, + In0P->code, + In0P->codeCnt); + OutP->NDR = NDR_record; + return TRUE; +} +#else +boolean_t breakpad_exc_server(mach_msg_header_t *request, + mach_msg_header_t *reply) { + return exc_server(request, reply); +} + +// Callback from exc_server() +kern_return_t catch_exception_raise(mach_port_t port, mach_port_t failed_thread, + mach_port_t task, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t code_count) { + if (task != mach_task_self()) { + return KERN_FAILURE; + } + return ForwardException(task, failed_thread, exception, code, code_count); +} +#endif ExceptionHandler::ExceptionHandler(const string &dump_path, FilterCallback filter, MinidumpCallback callback, void *callback_context, bool install_handler, - const char *port_name) + const char *port_name) : dump_path_(), filter_(filter), callback_(callback), @@ -380,10 +428,7 @@ kern_return_t ForwardException(mach_port_t task, mach_port_t failed_thread, mach_port_t target_port = current.ports[found]; exception_behavior_t target_behavior = current.behaviors[found]; - thread_state_flavor_t target_flavor = current.flavors[found]; - mach_msg_type_number_t thread_state_count = THREAD_STATE_MAX; - breakpad_thread_state_data_t thread_state; kern_return_t result; switch (target_behavior) { case EXCEPTION_DEFAULT: @@ -391,38 +436,8 @@ kern_return_t ForwardException(mach_port_t task, mach_port_t failed_thread, code, code_count); break; - case EXCEPTION_STATE: - result = thread_get_state(failed_thread, target_flavor, thread_state, - &thread_state_count); - if (result == KERN_SUCCESS) - result = exception_raise_state(target_port, failed_thread, task, - exception, code, - code_count, &target_flavor, - thread_state, thread_state_count, - thread_state, &thread_state_count); - if (result == KERN_SUCCESS) - result = thread_set_state(failed_thread, target_flavor, thread_state, - thread_state_count); - break; - - case EXCEPTION_STATE_IDENTITY: - result = thread_get_state(failed_thread, target_flavor, thread_state, - &thread_state_count); - if (result == KERN_SUCCESS) - result = exception_raise_state_identity(target_port, failed_thread, - task, exception, code, - code_count, &target_flavor, - thread_state, - thread_state_count, - thread_state, - &thread_state_count); - if (result == KERN_SUCCESS) - result = thread_set_state(failed_thread, target_flavor, thread_state, - thread_state_count); - break; - default: - fprintf(stderr, "** Unknown exception behavior\n"); + fprintf(stderr, "** Unknown exception behavior: %d\n", target_behavior); result = KERN_FAILURE; break; } @@ -430,18 +445,6 @@ kern_return_t ForwardException(mach_port_t task, mach_port_t failed_thread, return result; } -// Callback from exc_server() -kern_return_t catch_exception_raise(mach_port_t port, mach_port_t failed_thread, - mach_port_t task, - exception_type_t exception, - exception_data_t code, - mach_msg_type_number_t code_count) { - if (task != mach_task_self()) { - return KERN_FAILURE; - } - return ForwardException(task, failed_thread, exception, code, code_count); -} - // static void *ExceptionHandler::WaitForMessage(void *exception_handler_class) { ExceptionHandler *self = @@ -561,7 +564,7 @@ void *ExceptionHandler::WaitForMessage(void *exception_handler_class) { // message and call catch_exception_raise() and put the return // code into the reply. ExceptionReplyMessage reply; - if (!exc_server(&receive.header, &reply.header)) + if (!breakpad_exc_server(&receive.header, &reply.header)) exit(1); // Send a reply and exit