OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 #include "native_client/src/trusted/service_runtime/osx/mach_exception_handler.h
" | 7 #include "native_client/src/trusted/service_runtime/osx/mach_exception_handler.h
" |
8 | 8 |
9 #include <mach/mach.h> | 9 #include <mach/mach.h> |
10 #include <mach/mach_vm.h> | 10 #include <mach/mach_vm.h> |
(...skipping 26 matching lines...) Expand all Loading... |
37 | 37 |
38 /* | 38 /* |
39 * MIG generated message pump from /usr/include/mach/exc.defs | 39 * MIG generated message pump from /usr/include/mach/exc.defs |
40 * Tweaked to place in an isolated namespace. | 40 * Tweaked to place in an isolated namespace. |
41 */ | 41 */ |
42 boolean_t nacl_exc_server( | 42 boolean_t nacl_exc_server( |
43 mach_msg_header_t *InHeadP, | 43 mach_msg_header_t *InHeadP, |
44 mach_msg_header_t *OutHeadP); | 44 mach_msg_header_t *OutHeadP); |
45 | 45 |
46 | 46 |
47 /* Exception types to intercept. */ | 47 /* Exception types to intercept. This should be a superset of what Breakpad han
dles... */ |
48 #define NACL_MACH_EXCEPTION_MASK \ | 48 #define NACL_MACH_EXCEPTION_MASK \ |
49 (EXC_MASK_BAD_ACCESS | \ | 49 (EXC_MASK_BAD_ACCESS | \ |
50 EXC_MASK_BAD_INSTRUCTION | \ | 50 EXC_MASK_BAD_INSTRUCTION | \ |
51 EXC_MASK_ARITHMETIC | \ | 51 EXC_MASK_ARITHMETIC | \ |
52 EXC_MASK_BREAKPOINT) | 52 EXC_MASK_BREAKPOINT) |
53 | 53 |
54 /* | 54 /* |
55 * <mach/mach_types.defs> says that the arrays in MachExceptionParameters have | 55 * <mach/mach_types.defs> says that the arrays in MachExceptionParameters have |
56 * room for 32 elements. EXC_TYPES_COUNT, a smaller value, has grown over | 56 * room for 32 elements. EXC_TYPES_COUNT, a smaller value, has grown over |
57 * time in major SDK releases. task_get_exception_ports expects there to be | 57 * time in major SDK releases. task_get_exception_ports expects there to be |
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 * handlers don't provide a new thread state. They can set a new thread | 399 * handlers don't provide a new thread state. They can set a new thread |
400 * state on their own by calling thread_set_state. Returning KERN_SUCCESS | 400 * state on their own by calling thread_set_state. Returning KERN_SUCCESS |
401 * would allow the old state passed to | 401 * would allow the old state passed to |
402 * nacl_catch_exception_raise_state_identity to overwrite any new state set | 402 * nacl_catch_exception_raise_state_identity to overwrite any new state set |
403 * by the handler that the exception was forwarded to via exception_raise. | 403 * by the handler that the exception was forwarded to via exception_raise. |
404 */ | 404 */ |
405 return kr == KERN_SUCCESS ? MACH_RCV_PORT_DIED : kr; | 405 return kr == KERN_SUCCESS ? MACH_RCV_PORT_DIED : kr; |
406 } | 406 } |
407 | 407 |
408 | 408 |
| 409 static void ReportCrash(int exception_type, int is_untrusted) { |
| 410 char buf[128]; |
| 411 int len = snprintf(buf, sizeof(buf), |
| 412 "\n** Mach exception %d from %s code\n", |
| 413 exception_type, |
| 414 is_untrusted ? "untrusted" : "trusted"); |
| 415 write(2, buf, len); |
| 416 } |
| 417 |
| 418 |
409 kern_return_t nacl_catch_exception_raise( | 419 kern_return_t nacl_catch_exception_raise( |
410 mach_port_t exception_port, | 420 mach_port_t exception_port, |
411 mach_port_t thread, | 421 mach_port_t thread, |
412 mach_port_t task, | 422 mach_port_t task, |
413 exception_type_t exception, | 423 exception_type_t exception, |
414 exception_data_t code, | 424 exception_data_t code, |
415 mach_msg_type_number_t code_count) { | 425 mach_msg_type_number_t code_count) { |
416 /* MIG generated code expects this, but should never be called. */ | 426 /* MIG generated code expects this, but should never be called. */ |
417 UNREFERENCED_PARAMETER(exception_port); | 427 UNREFERENCED_PARAMETER(exception_port); |
418 UNREFERENCED_PARAMETER(thread); | 428 UNREFERENCED_PARAMETER(thread); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
491 * xnu-2050.18.24/osfmk/kern/exception.c. | 501 * xnu-2050.18.24/osfmk/kern/exception.c. |
492 * | 502 * |
493 * This is done instead of letting the kernel set the new thread state to | 503 * This is done instead of letting the kernel set the new thread state to |
494 * be the same as the old state because the kernel resets %cs to the | 504 * be the same as the old state because the kernel resets %cs to the |
495 * default value when setting a thread's state. This behavior is explained | 505 * default value when setting a thread's state. This behavior is explained |
496 * in more detail in HandleException. | 506 * in more detail in HandleException. |
497 */ | 507 */ |
498 return MACH_RCV_PORT_DIED; | 508 return MACH_RCV_PORT_DIED; |
499 } | 509 } |
500 | 510 |
| 511 ReportCrash(exception, is_untrusted); |
| 512 |
501 /* | 513 /* |
502 * Don't forward if the crash is untrusted, but unhandled. | 514 * Don't forward if the crash is untrusted, but unhandled. |
503 * (As we don't want things like Breakpad handling the crash.) | 515 * (As we don't want things like Breakpad handling the crash.) |
504 */ | 516 */ |
505 if (is_untrusted) { | 517 if (is_untrusted) { |
506 return KERN_FAILURE; | 518 return KERN_FAILURE; |
507 } | 519 } |
508 | 520 |
509 /* Forward on the exception to the old set of ports. */ | 521 /* Forward on the exception to the old set of ports. */ |
510 return ForwardException( | 522 return ForwardException( |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
652 if (data) { | 664 if (data) { |
653 if (MACH_PORT_NULL != data->exception_port) { | 665 if (MACH_PORT_NULL != data->exception_port) { |
654 mach_port_deallocate(current_task, data->exception_port); | 666 mach_port_deallocate(current_task, data->exception_port); |
655 } | 667 } |
656 free(data); | 668 free(data); |
657 } | 669 } |
658 return FALSE; | 670 return FALSE; |
659 } | 671 } |
660 | 672 |
661 #endif /* NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 */ | 673 #endif /* NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 */ |
OLD | NEW |