2372
2703
/* returning us to a safe state, though not soon enough. */
2375
#endif /* !GC_TEST_AND_SET_DEFINED */
2706
#endif /* !AO_HAVE_test_and_set_acquire */
2376
2707
#else /* !THREADS */
2377
2708
# define async_set_pht_entry_from_index(db, index) \
2378
2709
set_pht_entry_from_index(db, index)
2379
2710
#endif /* !THREADS */
2382
2712
#if !defined(DARWIN)
2383
# if defined (SUNOS4) || (defined(FREEBSD) && !defined(SUNOS5SIGS))
2384
void GC_write_fault_handler(sig, code, scp, addr)
2386
struct sigcontext *scp;
2389
# define SIG_OK (sig == SIGSEGV || sig == SIGBUS)
2390
# define CODE_OK (FC_CODE(code) == FC_PROT \
2391
|| (FC_CODE(code) == FC_OBJERR \
2392
&& FC_ERRNO(code) == FC_PROT))
2395
# define SIG_OK (sig == SIGBUS)
2396
# define CODE_OK TRUE
2398
# endif /* SUNOS4 || (FREEBSD && !SUNOS5SIGS) */
2400
# if defined(IRIX5) || defined(OSF1) || defined(HURD)
2401
2713
# include <errno.h>
2402
void GC_write_fault_handler(int sig, int code, struct sigcontext *scp)
2714
# if defined(FREEBSD)
2715
# define SIG_OK TRUE
2716
# define CODE_OK (code == BUS_PAGE_FAULT)
2717
# elif defined(OSF1)
2404
2718
# define SIG_OK (sig == SIGSEGV)
2405
2719
# define CODE_OK (code == 2 /* experimentally determined */)
2720
# elif defined(IRIX5)
2408
2721
# define SIG_OK (sig == SIGSEGV)
2409
2722
# define CODE_OK (code == EACCES)
2723
# elif defined(HURD)
2412
2724
# define SIG_OK (sig == SIGBUS || sig == SIGSEGV)
2413
2725
# define CODE_OK TRUE
2415
# endif /* IRIX5 || OSF1 || HURD */
2418
# if defined(ALPHA) || defined(M68K)
2419
void GC_write_fault_handler(int sig, int code, s_c * sc)
2421
# if defined(IA64) || defined(HP_PA) || defined(X86_64)
2422
void GC_write_fault_handler(int sig, siginfo_t * si, s_c * scp)
2425
void GC_write_fault_handler(int sig, int a2, int a3, int a4, s_c sc)
2427
void GC_write_fault_handler(int sig, s_c sc)
2431
# define SIG_OK (sig == SIGSEGV)
2432
# define CODE_OK TRUE
2726
# elif defined(LINUX)
2727
# define SIG_OK (sig == SIGSEGV)
2728
# define CODE_OK TRUE
2433
2729
/* Empirically c.trapno == 14, on IA32, but is that useful? */
2434
2730
/* Should probably consider alignment issues on other */
2435
2731
/* architectures. */
2438
# if defined(SUNOS5SIGS)
2440
void GC_write_fault_handler(int sig, SIGINFO_T *scp, void * context)
2442
void GC_write_fault_handler(sig, scp, context)
2732
# elif defined(HPUX)
2448
2733
# define SIG_OK (sig == SIGSEGV || sig == SIGBUS)
2449
# define CODE_OK (scp -> si_code == SEGV_ACCERR) \
2450
|| (scp -> si_code == BUS_ADRERR) \
2451
|| (scp -> si_code == BUS_UNKNOWN) \
2452
|| (scp -> si_code == SEGV_UNKNOWN) \
2453
|| (scp -> si_code == BUS_OBJERR)
2456
# define SIG_OK (sig == SIGBUS)
2457
# define CODE_OK (scp -> si_code == BUS_PAGE_FAULT)
2459
# define SIG_OK (sig == SIGSEGV)
2460
# define CODE_OK (scp -> si_code == SEGV_ACCERR)
2734
# define CODE_OK (si -> si_code == SEGV_ACCERR) \
2735
|| (si -> si_code == BUS_ADRERR) \
2736
|| (si -> si_code == BUS_UNKNOWN) \
2737
|| (si -> si_code == SEGV_UNKNOWN) \
2738
|| (si -> si_code == BUS_OBJERR)
2739
# elif defined(FREEBSD)
2740
# define SIG_OK (sig == SIGBUS)
2741
# define CODE_OK (si -> si_code == BUS_PAGE_FAULT)
2742
# elif defined(SUNOS5SIGS)
2743
# define SIG_OK (sig == SIGSEGV)
2744
# define CODE_OK (si -> si_code == SEGV_ACCERR)
2745
# elif defined(MSWIN32) || defined(MSWINCE)
2746
# define SIG_OK (exc_info -> ExceptionRecord -> ExceptionCode \
2747
== STATUS_ACCESS_VIOLATION)
2748
# define CODE_OK (exc_info -> ExceptionRecord -> ExceptionInformation[0] \
2749
== 1) /* Write fault */
2463
# endif /* SUNOS5SIGS */
2465
2752
# if defined(MSWIN32) || defined(MSWINCE)
2466
2753
LONG WINAPI GC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info)
2467
# define SIG_OK (exc_info -> ExceptionRecord -> ExceptionCode == \
2468
STATUS_ACCESS_VIOLATION)
2469
# define CODE_OK (exc_info -> ExceptionRecord -> ExceptionInformation[0] == 1)
2755
# include <ucontext.h>
2757
void GC_write_fault_handler(int sig, siginfo_t *si, void *raw_sc)
2471
2758
# endif /* MSWIN32 || MSWINCE */
2473
register unsigned i;
2475
char *addr = (char *) code;
2478
char * addr = (char *) (size_t) (scp -> sc_badvaddr);
2480
# if defined(OSF1) && defined(ALPHA)
2481
char * addr = (char *) (scp -> sc_traparg_a0);
2484
char * addr = (char *) (scp -> si_addr);
2488
char * addr = (char *) (sc.cr2);
2493
struct sigcontext *scp = (struct sigcontext *)(sc);
2495
int format = (scp->sc_formatvec >> 12) & 0xf;
2496
unsigned long *framedata = (unsigned long *)(scp + 1);
2499
if (format == 0xa || format == 0xb) {
2502
} else if (format == 7) {
2505
if (framedata[1] & 0x08000000) {
2506
/* correct addr on misaligned access */
2507
ea = (ea+4095)&(~4095);
2509
} else if (format == 4) {
2512
if (framedata[1] & 0x08000000) {
2513
/* correct addr on misaligned access */
2514
ea = (ea+4095)&(~4095);
2520
char * addr = get_fault_addr(sc);
2522
# if defined(IA64) || defined(HP_PA) || defined(X86_64)
2523
char * addr = si -> si_addr;
2524
/* I believe this is claimed to work on all platforms for */
2525
/* Linux 2.3.47 and later. Hopefully we don't have to */
2526
/* worry about earlier kernels on IA64. */
2528
# if defined(POWERPC)
2529
char * addr = (char *) (sc.regs->dar);
2532
char * addr = (char *)sc.fault_address;
2535
char * addr = (char *)sc.regs.csraddr;
2537
--> architecture not supported
2760
# if !defined(MSWIN32) && !defined(MSWINCE)
2761
int code = si -> si_code; /* Ignore gcc unused var. warning. */
2762
ucontext_t * scp = (ucontext_t *)raw_sc;
2763
/* Ignore gcc unused var. warning. */
2764
char *addr = si -> si_addr;
2546
2766
# if defined(MSWIN32) || defined(MSWINCE)
2547
2767
char * addr = (char *) (exc_info -> ExceptionRecord
2548
2768
-> ExceptionInformation[1]);
2549
2769
# define sig SIGSEGV
2552
2773
if (SIG_OK && CODE_OK) {
2553
2774
register struct hblk * h =
3513
3586
#define GC_mprotect_state GC_MP_NORMAL
3516
static void *GC_mprotect_thread(void *arg) {
3517
mach_msg_return_t r;
3518
/* These two structures contain some private kernel data. We don't need to
3519
access any of it so we don't bother defining a proper struct. The
3520
correct definitions are in the xnu source code. */
3522
mach_msg_header_t head;
3526
mach_msg_header_t head;
3527
mach_msg_body_t msgh_body;
3533
GC_darwin_register_mach_handler_thread(mach_thread_self());
3538
MACH_RCV_MSG|MACH_RCV_LARGE|
3539
(GC_mprotect_state == GC_MP_DISCARDING ? MACH_RCV_TIMEOUT : 0),
3543
GC_mprotect_state == GC_MP_DISCARDING ? 0 : MACH_MSG_TIMEOUT_NONE,
3546
id = r == MACH_MSG_SUCCESS ? msg.head.msgh_id : -1;
3548
#if defined(THREADS)
3549
if(GC_mprotect_state == GC_MP_DISCARDING) {
3550
if(r == MACH_RCV_TIMED_OUT) {
3551
GC_mprotect_state = GC_MP_STOPPED;
3552
GC_mprotect_thread_reply();
3555
if(r == MACH_MSG_SUCCESS && (id == ID_STOP || id == ID_RESUME))
3556
ABORT("out of order mprotect thread request");
3560
if(r != MACH_MSG_SUCCESS) {
3561
GC_err_printf2("mach_msg failed with %d %s\n",
3562
(int)r,mach_error_string(r));
3563
ABORT("mach_msg failed");
3567
#if defined(THREADS)
3569
if(GC_mprotect_state != GC_MP_NORMAL)
3570
ABORT("Called mprotect_stop when state wasn't normal");
3571
GC_mprotect_state = GC_MP_DISCARDING;
3574
if(GC_mprotect_state != GC_MP_STOPPED)
3575
ABORT("Called mprotect_resume when state wasn't stopped");
3576
GC_mprotect_state = GC_MP_NORMAL;
3577
GC_mprotect_thread_reply();
3579
#endif /* THREADS */
3581
/* Handle the message (calls catch_exception_raise) */
3582
if(!exc_server(&msg.head,&reply.head))
3583
ABORT("exc_server failed");
3584
/* Send the reply */
3588
reply.head.msgh_size,
3591
MACH_MSG_TIMEOUT_NONE,
3593
if(r != MACH_MSG_SUCCESS) {
3594
/* This will fail if the thread dies, but the thread shouldn't
3596
#ifdef BROKEN_EXCEPTION_HANDLING
3598
"mach_msg failed with %d %s while sending exc reply\n",
3599
(int)r,mach_error_string(r));
3601
ABORT("mach_msg failed while sending exception reply");
3589
static void *GC_mprotect_thread(void *arg)
3591
mach_msg_return_t r;
3592
/* These two structures contain some private kernel data. We don't need to
3593
access any of it so we don't bother defining a proper struct. The
3594
correct definitions are in the xnu source code. */
3596
mach_msg_header_t head;
3600
mach_msg_header_t head;
3601
mach_msg_body_t msgh_body;
3607
GC_darwin_register_mach_handler_thread(mach_thread_self());
3610
r = mach_msg(&msg.head, MACH_RCV_MSG | MACH_RCV_LARGE |
3611
(GC_mprotect_state == GC_MP_DISCARDING ? MACH_RCV_TIMEOUT : 0),
3612
0, sizeof(msg), GC_ports.exception,
3613
GC_mprotect_state == GC_MP_DISCARDING ? 0
3614
: MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
3616
id = r == MACH_MSG_SUCCESS ? msg.head.msgh_id : -1;
3618
# if defined(THREADS)
3619
if(GC_mprotect_state == GC_MP_DISCARDING) {
3620
if(r == MACH_RCV_TIMED_OUT) {
3621
GC_mprotect_state = GC_MP_STOPPED;
3622
GC_mprotect_thread_reply();
3625
if(r == MACH_MSG_SUCCESS && (id == ID_STOP || id == ID_RESUME))
3626
ABORT("out of order mprotect thread request");
3628
# endif /* THREADS */
3630
if(r != MACH_MSG_SUCCESS) {
3631
GC_err_printf("mach_msg failed with %d %s\n", (int)r,
3632
mach_error_string(r));
3633
ABORT("mach_msg failed");
3637
# if defined(THREADS)
3639
if(GC_mprotect_state != GC_MP_NORMAL)
3640
ABORT("Called mprotect_stop when state wasn't normal");
3641
GC_mprotect_state = GC_MP_DISCARDING;
3644
if(GC_mprotect_state != GC_MP_STOPPED)
3645
ABORT("Called mprotect_resume when state wasn't stopped");
3646
GC_mprotect_state = GC_MP_NORMAL;
3647
GC_mprotect_thread_reply();
3649
# endif /* THREADS */
3651
/* Handle the message (calls catch_exception_raise) */
3652
if(!exc_server(&msg.head, &reply.head))
3653
ABORT("exc_server failed");
3654
/* Send the reply */
3655
r = mach_msg(&reply.head, MACH_SEND_MSG, reply.head.msgh_size, 0,
3656
MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
3658
if(r != MACH_MSG_SUCCESS) {
3659
/* This will fail if the thread dies, but the thread */
3660
/* shouldn't die... */
3661
# ifdef BROKEN_EXCEPTION_HANDLING
3662
GC_err_printf("mach_msg failed with %d %s while sending"
3663
"exc reply\n", (int)r,mach_error_string(r));
3665
ABORT("mach_msg failed while sending exception reply");
3606
3670
/* NOT REACHED */
3610
3674
/* All this SIGBUS code shouldn't be necessary. All protection faults should
3613
3677
meaningless and safe to ignore. */
3614
3678
#ifdef BROKEN_EXCEPTION_HANDLING
3616
typedef void (* SIG_PF)();
3617
static SIG_PF GC_old_bus_handler;
3680
static SIG_HNDLR_PTR GC_old_bus_handler;
3619
3682
/* Updates to this aren't atomic, but the SIGBUSs seem pretty rare.
3620
3683
Even if this doesn't get updated property, it isn't really a problem */
3621
3684
static int GC_sigbus_count;
3623
static void GC_darwin_sigbus(int num,siginfo_t *sip,void *context) {
3624
if(num != SIGBUS) ABORT("Got a non-sigbus signal in the sigbus handler");
3626
/* Ugh... some seem safe to ignore, but too many in a row probably means
3627
trouble. GC_sigbus_count is reset for each mach exception that is
3629
if(GC_sigbus_count >= 8) {
3630
ABORT("Got more than 8 SIGBUSs in a row!");
3633
GC_err_printf0("GC: WARNING: Ignoring SIGBUS.\n");
3686
static void GC_darwin_sigbus(int num, siginfo_t *sip, void *context)
3689
ABORT("Got a non-sigbus signal in the sigbus handler");
3691
/* Ugh... some seem safe to ignore, but too many in a row probably means
3692
trouble. GC_sigbus_count is reset for each mach exception that is
3694
if(GC_sigbus_count >= 8) {
3695
ABORT("Got more than 8 SIGBUSs in a row!");
3698
WARN("Ignoring SIGBUS.\n", 0);
3636
3701
#endif /* BROKEN_EXCEPTION_HANDLING */
3638
void GC_dirty_init() {
3642
pthread_attr_t attr;
3643
exception_mask_t mask;
3646
GC_printf0("Inititalizing mach/darwin mprotect virtual dirty bit "
3647
"implementation\n");
3649
# ifdef BROKEN_EXCEPTION_HANDLING
3650
GC_err_printf0("GC: WARNING: Enabling workarounds for various darwin "
3651
"exception handling bugs.\n");
3653
GC_dirty_maintained = TRUE;
3654
if (GC_page_size % HBLKSIZE != 0) {
3655
GC_err_printf0("Page size not multiple of HBLKSIZE\n");
3656
ABORT("Page size not multiple of HBLKSIZE");
3659
GC_task_self = me = mach_task_self();
3661
r = mach_port_allocate(me,MACH_PORT_RIGHT_RECEIVE,&GC_ports.exception);
3662
if(r != KERN_SUCCESS) ABORT("mach_port_allocate failed (exception port)");
3664
r = mach_port_insert_right(me,GC_ports.exception,GC_ports.exception,
3665
MACH_MSG_TYPE_MAKE_SEND);
3666
if(r != KERN_SUCCESS)
3667
ABORT("mach_port_insert_right failed (exception port)");
3669
#if defined(THREADS)
3670
r = mach_port_allocate(me,MACH_PORT_RIGHT_RECEIVE,&GC_ports.reply);
3671
if(r != KERN_SUCCESS) ABORT("mach_port_allocate failed (reply port)");
3674
/* The exceptions we want to catch */
3675
mask = EXC_MASK_BAD_ACCESS;
3677
r = task_get_exception_ports(
3680
GC_old_exc_ports.masks,
3681
&GC_old_exc_ports.count,
3682
GC_old_exc_ports.ports,
3683
GC_old_exc_ports.behaviors,
3684
GC_old_exc_ports.flavors
3686
if(r != KERN_SUCCESS) ABORT("task_get_exception_ports failed");
3688
r = task_set_exception_ports(
3693
MACHINE_THREAD_STATE
3695
if(r != KERN_SUCCESS) ABORT("task_set_exception_ports failed");
3697
if(pthread_attr_init(&attr) != 0) ABORT("pthread_attr_init failed");
3698
if(pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED) != 0)
3699
ABORT("pthread_attr_setdetachedstate failed");
3701
# undef pthread_create
3702
/* This will call the real pthread function, not our wrapper */
3703
if(pthread_create(&thread,&attr,GC_mprotect_thread,NULL) != 0)
3704
ABORT("pthread_create failed");
3705
pthread_attr_destroy(&attr);
3707
/* Setup the sigbus handler for ignoring the meaningless SIGBUSs */
3708
#ifdef BROKEN_EXCEPTION_HANDLING
3703
void GC_dirty_init(void)
3708
pthread_attr_t attr;
3709
exception_mask_t mask;
3711
if (GC_print_stats == VERBOSE)
3712
GC_log_printf("Inititalizing mach/darwin mprotect virtual dirty bit "
3713
"implementation\n");
3714
# ifdef BROKEN_EXCEPTION_HANDLING
3715
WARN("Enabling workarounds for various darwin "
3716
"exception handling bugs.\n", 0);
3718
GC_dirty_maintained = TRUE;
3719
if (GC_page_size % HBLKSIZE != 0) {
3720
GC_err_printf("Page size not multiple of HBLKSIZE\n");
3721
ABORT("Page size not multiple of HBLKSIZE");
3724
GC_task_self = me = mach_task_self();
3726
r = mach_port_allocate(me, MACH_PORT_RIGHT_RECEIVE, &GC_ports.exception);
3727
if(r != KERN_SUCCESS)
3728
ABORT("mach_port_allocate failed (exception port)");
3730
r = mach_port_insert_right(me, GC_ports.exception, GC_ports.exception,
3731
MACH_MSG_TYPE_MAKE_SEND);
3732
if(r != KERN_SUCCESS)
3733
ABORT("mach_port_insert_right failed (exception port)");
3735
# if defined(THREADS)
3736
r = mach_port_allocate(me, MACH_PORT_RIGHT_RECEIVE, &GC_ports.reply);
3737
if(r != KERN_SUCCESS)
3738
ABORT("mach_port_allocate failed (reply port)");
3741
/* The exceptions we want to catch */
3742
mask = EXC_MASK_BAD_ACCESS;
3744
r = task_get_exception_ports(me, mask, GC_old_exc_ports.masks,
3745
&GC_old_exc_ports.count, GC_old_exc_ports.ports,
3746
GC_old_exc_ports.behaviors,
3747
GC_old_exc_ports.flavors);
3748
if(r != KERN_SUCCESS)
3749
ABORT("task_get_exception_ports failed");
3751
r = task_set_exception_ports(me, mask, GC_ports.exception, EXCEPTION_DEFAULT,
3752
GC_MACH_THREAD_STATE);
3753
if(r != KERN_SUCCESS)
3754
ABORT("task_set_exception_ports failed");
3755
if(pthread_attr_init(&attr) != 0)
3756
ABORT("pthread_attr_init failed");
3757
if(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
3758
ABORT("pthread_attr_setdetachedstate failed");
3760
# undef pthread_create
3761
/* This will call the real pthread function, not our wrapper */
3762
if(pthread_create(&thread, &attr, GC_mprotect_thread, NULL) != 0)
3763
ABORT("pthread_create failed");
3764
pthread_attr_destroy(&attr);
3766
/* Setup the sigbus handler for ignoring the meaningless SIGBUSs */
3767
# ifdef BROKEN_EXCEPTION_HANDLING
3710
struct sigaction sa, oldsa;
3711
sa.sa_handler = (SIG_PF)GC_darwin_sigbus;
3712
sigemptyset(&sa.sa_mask);
3713
sa.sa_flags = SA_RESTART|SA_SIGINFO;
3714
if(sigaction(SIGBUS,&sa,&oldsa) < 0) ABORT("sigaction");
3715
GC_old_bus_handler = (SIG_PF)oldsa.sa_handler;
3716
if (GC_old_bus_handler != SIG_DFL) {
3718
GC_err_printf0("Replaced other SIGBUS handler\n");
3769
struct sigaction sa, oldsa;
3770
sa.sa_handler = (SIG_HNDLR_PTR)GC_darwin_sigbus;
3771
sigemptyset(&sa.sa_mask);
3772
sa.sa_flags = SA_RESTART|SA_SIGINFO;
3773
if(sigaction(SIGBUS, &sa, &oldsa) < 0)
3775
GC_old_bus_handler = (SIG_HNDLR_PTR)oldsa.sa_handler;
3776
if (GC_old_bus_handler != SIG_DFL) {
3777
if (GC_print_stats == VERBOSE)
3778
GC_err_printf("Replaced other SIGBUS handler\n");
3722
#endif /* BROKEN_EXCEPTION_HANDLING */
3781
# endif /* BROKEN_EXCEPTION_HANDLING */
3725
3784
/* The source code for Apple's GDB was used as a reference for the exception
3726
forwarding code. This code is similar to be GDB code only because there is
3785
forwarding code. This code is similar to be GDB code only because there is
3727
3786
only one way to do it. */
3728
static kern_return_t GC_forward_exception(
3731
exception_type_t exception,
3732
exception_data_t data,
3733
mach_msg_type_number_t data_count
3738
exception_behavior_t behavior;
3739
thread_state_flavor_t flavor;
3741
thread_state_t thread_state;
3742
mach_msg_type_number_t thread_state_count = THREAD_STATE_MAX;
3744
for(i=0;i<GC_old_exc_ports.count;i++)
3745
if(GC_old_exc_ports.masks[i] & (1 << exception))
3747
if(i==GC_old_exc_ports.count) ABORT("No handler for exception!");
3749
port = GC_old_exc_ports.ports[i];
3750
behavior = GC_old_exc_ports.behaviors[i];
3751
flavor = GC_old_exc_ports.flavors[i];
3753
if(behavior != EXCEPTION_DEFAULT) {
3754
r = thread_get_state(thread,flavor,thread_state,&thread_state_count);
3755
if(r != KERN_SUCCESS)
3756
ABORT("thread_get_state failed in forward_exception");
3760
case EXCEPTION_DEFAULT:
3761
r = exception_raise(port,thread,task,exception,data,data_count);
3763
case EXCEPTION_STATE:
3764
r = exception_raise_state(port,thread,task,exception,data,
3765
data_count,&flavor,thread_state,thread_state_count,
3766
thread_state,&thread_state_count);
3768
case EXCEPTION_STATE_IDENTITY:
3769
r = exception_raise_state_identity(port,thread,task,exception,data,
3770
data_count,&flavor,thread_state,thread_state_count,
3771
thread_state,&thread_state_count);
3774
r = KERN_FAILURE; /* make gcc happy */
3775
ABORT("forward_exception: unknown behavior");
3779
if(behavior != EXCEPTION_DEFAULT) {
3780
r = thread_set_state(thread,flavor,thread_state,thread_state_count);
3781
if(r != KERN_SUCCESS)
3782
ABORT("thread_set_state failed in forward_exception");
3787
static kern_return_t GC_forward_exception(mach_port_t thread, mach_port_t task,
3788
exception_type_t exception,
3789
exception_data_t data,
3790
mach_msg_type_number_t data_count)
3795
exception_behavior_t behavior;
3796
thread_state_flavor_t flavor;
3798
thread_state_t thread_state = NULL;
3799
mach_msg_type_number_t thread_state_count = THREAD_STATE_MAX;
3801
for(i=0; i < GC_old_exc_ports.count; i++)
3802
if(GC_old_exc_ports.masks[i] & (1 << exception))
3804
if(i==GC_old_exc_ports.count)
3805
ABORT("No handler for exception!");
3807
port = GC_old_exc_ports.ports[i];
3808
behavior = GC_old_exc_ports.behaviors[i];
3809
flavor = GC_old_exc_ports.flavors[i];
3811
if(behavior != EXCEPTION_DEFAULT) {
3812
r = thread_get_state(thread, flavor, thread_state, &thread_state_count);
3813
if(r != KERN_SUCCESS)
3814
ABORT("thread_get_state failed in forward_exception");
3818
case EXCEPTION_DEFAULT:
3819
r = exception_raise(port, thread, task, exception, data, data_count);
3821
case EXCEPTION_STATE:
3822
r = exception_raise_state(port, thread, task, exception, data, data_count,
3823
&flavor, thread_state, thread_state_count,
3824
thread_state, &thread_state_count);
3826
case EXCEPTION_STATE_IDENTITY:
3827
r = exception_raise_state_identity(port, thread, task, exception, data,
3828
data_count, &flavor, thread_state,
3829
thread_state_count, thread_state,
3830
&thread_state_count);
3833
r = KERN_FAILURE; /* make gcc happy */
3834
ABORT("forward_exception: unknown behavior");
3838
if(behavior != EXCEPTION_DEFAULT) {
3839
r = thread_set_state(thread, flavor, thread_state, thread_state_count);
3840
if(r != KERN_SUCCESS)
3841
ABORT("thread_set_state failed in forward_exception");
3788
#define FWD() GC_forward_exception(thread,task,exception,code,code_count)
3847
#define FWD() GC_forward_exception(thread, task, exception, code, code_count)
3790
3849
/* This violates the namespace rules but there isn't anything that can be done
3791
3850
about it. The exception handling stuff is hard coded to call this */
3793
catch_exception_raise(
3794
mach_port_t exception_port,mach_port_t thread,mach_port_t task,
3795
exception_type_t exception,exception_data_t code,
3796
mach_msg_type_number_t code_count
3802
# if defined(POWERPC)
3803
# if CPP_WORDSZ == 32
3804
thread_state_flavor_t flavor = PPC_EXCEPTION_STATE;
3805
mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE_COUNT;
3806
ppc_exception_state_t exc_state;
3808
thread_state_flavor_t flavor = PPC_EXCEPTION_STATE64;
3809
mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE64_COUNT;
3810
ppc_exception_state64_t exc_state;
3812
# elif defined(I386)
3813
thread_state_flavor_t flavor = i386_EXCEPTION_STATE;
3814
mach_msg_type_number_t exc_state_count = i386_EXCEPTION_STATE_COUNT;
3815
i386_exception_state_t exc_state;
3817
# error FIXME for non-ppc/x86 darwin
3821
if(exception != EXC_BAD_ACCESS || code[0] != KERN_PROTECTION_FAILURE) {
3822
#ifdef DEBUG_EXCEPTION_HANDLING
3823
/* We aren't interested, pass it on to the old handler */
3824
GC_printf3("Exception: 0x%x Code: 0x%x 0x%x in catch....\n",
3826
code_count > 0 ? code[0] : -1,
3827
code_count > 1 ? code[1] : -1);
3832
r = thread_get_state(thread,flavor,
3833
(natural_t*)&exc_state,&exc_state_count);
3834
if(r != KERN_SUCCESS) {
3835
/* The thread is supposed to be suspended while the exception handler
3836
is called. This shouldn't fail. */
3837
#ifdef BROKEN_EXCEPTION_HANDLING
3838
GC_err_printf0("thread_get_state failed in "
3839
"catch_exception_raise\n");
3840
return KERN_SUCCESS;
3842
ABORT("thread_get_state failed in catch_exception_raise");
3852
catch_exception_raise(mach_port_t exception_port, mach_port_t thread,
3853
mach_port_t task, exception_type_t exception,
3854
exception_data_t code, mach_msg_type_number_t code_count)
3860
# if defined(POWERPC)
3861
# if CPP_WORDSZ == 32
3862
thread_state_flavor_t flavor = PPC_EXCEPTION_STATE;
3863
mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE_COUNT;
3864
ppc_exception_state_t exc_state;
3866
thread_state_flavor_t flavor = PPC_EXCEPTION_STATE64;
3867
mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE64_COUNT;
3868
ppc_exception_state64_t exc_state;
3870
# elif defined(I386) || defined(X86_64)
3871
# if CPP_WORDSZ == 32
3872
thread_state_flavor_t flavor = x86_EXCEPTION_STATE32;
3873
mach_msg_type_number_t exc_state_count = x86_EXCEPTION_STATE32_COUNT;
3874
x86_exception_state32_t exc_state;
3876
thread_state_flavor_t flavor = x86_EXCEPTION_STATE64;
3877
mach_msg_type_number_t exc_state_count = x86_EXCEPTION_STATE64_COUNT;
3878
x86_exception_state64_t exc_state;
3881
# error FIXME for non-ppc/x86 darwin
3885
if(exception != EXC_BAD_ACCESS || code[0] != KERN_PROTECTION_FAILURE) {
3886
# ifdef DEBUG_EXCEPTION_HANDLING
3887
/* We aren't interested, pass it on to the old handler */
3888
GC_printf("Exception: 0x%x Code: 0x%x 0x%x in catch....\n", exception,
3889
code_count > 0 ? code[0] : -1, code_count > 1 ? code[1] : -1);
3894
r = thread_get_state(thread, flavor, (natural_t*)&exc_state,
3896
if(r != KERN_SUCCESS) {
3897
/* The thread is supposed to be suspended while the exception handler
3898
is called. This shouldn't fail. */
3899
# ifdef BROKEN_EXCEPTION_HANDLING
3900
GC_err_printf("thread_get_state failed in catch_exception_raise\n");
3901
return KERN_SUCCESS;
3903
ABORT("thread_get_state failed in catch_exception_raise");
3846
3907
/* This is the address that caused the fault */
3847
#if defined(POWERPC)
3848
addr = (char*) exc_state.dar;
3849
#elif defined (I386)
3850
addr = (char*) exc_state.faultvaddr;
3908
# if defined(POWERPC)
3909
addr = (char*) exc_state. THREAD_FLD(dar);
3910
# elif defined (I386) || defined (X86_64)
3911
addr = (char*) exc_state. THREAD_FLD(faultvaddr);
3852
3913
# error FIXME for non POWERPC/I386
3855
3916
if((HDR(addr)) == 0) {
3856
/* Ugh... just like the SIGBUS problem above, it seems we get a bogus
3857
KERN_PROTECTION_FAILURE every once and a while. We wait till we get
3858
a bunch in a row before doing anything about it. If a "real" fault
3859
ever occurres it'll just keep faulting over and over and we'll hit
3860
the limit pretty quickly. */
3861
#ifdef BROKEN_EXCEPTION_HANDLING
3862
static char *last_fault;
3863
static int last_fault_count;
3865
if(addr != last_fault) {
3867
last_fault_count = 0;
3869
if(++last_fault_count < 32) {
3870
if(last_fault_count == 1)
3872
"GC: WARNING: Ignoring KERN_PROTECTION_FAILURE at %p\n",
3874
return KERN_SUCCESS;
3877
GC_err_printf1("Unexpected KERN_PROTECTION_FAILURE at %p\n",addr);
3878
/* Can't pass it along to the signal handler because that is
3879
ignoring SIGBUS signals. We also shouldn't call ABORT here as
3880
signals don't always work too well from the exception handler. */
3881
GC_err_printf0("Aborting\n");
3883
#else /* BROKEN_EXCEPTION_HANDLING */
3884
/* Pass it along to the next exception handler
3885
(which should call SIGBUS/SIGSEGV) */
3887
#endif /* !BROKEN_EXCEPTION_HANDLING */
3917
/* Ugh... just like the SIGBUS problem above, it seems we get a bogus
3918
KERN_PROTECTION_FAILURE every once and a while. We wait till we get
3919
a bunch in a row before doing anything about it. If a "real" fault
3920
ever occurres it'll just keep faulting over and over and we'll hit
3921
the limit pretty quickly. */
3922
# ifdef BROKEN_EXCEPTION_HANDLING
3923
static char *last_fault;
3924
static int last_fault_count;
3926
if(addr != last_fault) {
3928
last_fault_count = 0;
3930
if(++last_fault_count < 32) {
3931
if(last_fault_count == 1)
3932
WARN("Ignoring KERN_PROTECTION_FAILURE at %lx\n", (GC_word)addr);
3933
return KERN_SUCCESS;
3936
GC_err_printf("Unexpected KERN_PROTECTION_FAILURE at %p\n",addr);
3937
/* Can't pass it along to the signal handler because that is
3938
ignoring SIGBUS signals. We also shouldn't call ABORT here as
3939
signals don't always work too well from the exception handler. */
3940
GC_err_printf("Aborting\n");
3942
# else /* BROKEN_EXCEPTION_HANDLING */
3943
/* Pass it along to the next exception handler
3944
(which should call SIGBUS/SIGSEGV) */
3946
# endif /* !BROKEN_EXCEPTION_HANDLING */
3890
#ifdef BROKEN_EXCEPTION_HANDLING
3891
/* Reset the number of consecutive SIGBUSs */
3892
GC_sigbus_count = 0;
3949
# ifdef BROKEN_EXCEPTION_HANDLING
3950
/* Reset the number of consecutive SIGBUSs */
3951
GC_sigbus_count = 0;
3895
3954
if(GC_mprotect_state == GC_MP_NORMAL) { /* common case */
3896
h = (struct hblk*)((word)addr & ~(GC_page_size-1));
3897
UNPROTECT(h, GC_page_size);
3898
for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
3899
register int index = PHT_HASH(h+i);
3900
async_set_pht_entry_from_index(GC_dirty_pages, index);
3955
h = (struct hblk*)((word)addr & ~(GC_page_size-1));
3956
UNPROTECT(h, GC_page_size);
3957
for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
3958
register int index = PHT_HASH(h+i);
3959
async_set_pht_entry_from_index(GC_dirty_pages, index);
3902
3961
} else if(GC_mprotect_state == GC_MP_DISCARDING) {
3903
/* Lie to the thread for now. No sense UNPROTECT()ing the memory
3904
when we're just going to PROTECT() it again later. The thread
3905
will just fault again once it resumes */
3962
/* Lie to the thread for now. No sense UNPROTECT()ing the memory
3963
when we're just going to PROTECT() it again later. The thread
3964
will just fault again once it resumes */
3907
/* Shouldn't happen, i don't think */
3908
GC_printf0("KERN_PROTECTION_FAILURE while world is stopped\n");
3966
/* Shouldn't happen, i don't think */
3967
GC_printf("KERN_PROTECTION_FAILURE while world is stopped\n");
3911
3970
return KERN_SUCCESS;
3915
3974
/* These should never be called, but just in case... */
3916
kern_return_t catch_exception_raise_state(mach_port_name_t exception_port,
3917
int exception, exception_data_t code, mach_msg_type_number_t codeCnt,
3918
int flavor, thread_state_t old_state, int old_stateCnt,
3919
thread_state_t new_state, int new_stateCnt)
3976
catch_exception_raise_state(mach_port_name_t exception_port, int exception,
3977
exception_data_t code,
3978
mach_msg_type_number_t codeCnt, int flavor,
3979
thread_state_t old_state, int old_stateCnt,
3980
thread_state_t new_state, int new_stateCnt)
3921
ABORT("catch_exception_raise_state");
3922
return(KERN_INVALID_ARGUMENT);
3982
ABORT("catch_exception_raise_state");
3983
return(KERN_INVALID_ARGUMENT);
3924
kern_return_t catch_exception_raise_state_identity(
3925
mach_port_name_t exception_port, mach_port_t thread, mach_port_t task,
3926
int exception, exception_data_t code, mach_msg_type_number_t codeCnt,
3927
int flavor, thread_state_t old_state, int old_stateCnt,
3928
thread_state_t new_state, int new_stateCnt)
3987
catch_exception_raise_state_identity(mach_port_name_t exception_port,
3988
mach_port_t thread, mach_port_t task,
3989
int exception, exception_data_t code,
3990
mach_msg_type_number_t codeCnt, int flavor,
3991
thread_state_t old_state, int old_stateCnt,
3992
thread_state_t new_state, int new_stateCnt)
3930
ABORT("catch_exception_raise_state_identity");
3931
return(KERN_INVALID_ARGUMENT);
3994
ABORT("catch_exception_raise_state_identity");
3995
return(KERN_INVALID_ARGUMENT);