aboutsummaryrefslogtreecommitdiff
path: root/src/client/mac/handler
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/mac/handler')
-rw-r--r--src/client/mac/handler/exception_handler.cc175
1 files changed, 89 insertions, 86 deletions
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 <map>
+#include <mach/exc.h>
+#include <mach/mig.h>
#include <pthread.h>
#include <signal.h>
#include <TargetConditionals.h>
@@ -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")));
+}
+#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
- 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);
+ 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