Subject: Re: SIGTRAP for traced processes and COMPAT_MACH
To: Jaromir Dolecek <jdolecek@NetBSD.org>
From: Emmanuel Dreyfus <manu@netbsd.org>
List: tech-kern
Date: 11/27/2003 20:25:30
Jaromir Dolecek <jdolecek@NetBSD.org> wrote:

> I'd propose to first confirm that Darwin/MacOSX really delivers the
> exception even when the appropriate signal is blocked. If no, end
> of story and we don't need to do anything special.

It really does. Why do you doubt it? Darwin's kernel is just a non UNIX kernel
with a BSD API on the top of it. Mach doesn't care about signal masks, it does
not even know what it is.  

Consider the following program:

#include <mach/mach_types.h>
#include <mach/task.h>
#include <mach/mach.h>
#include <mach/message.h>

#include <stdio.h>
#include <ctype.h>
#include <pthread.h>
#include <signal.h>

void dump(char *data, size_t len) {
        int i, j;

        for (i = 0; i < len; i += 16) {
                printf("%p  ", &data[i]);
                for (j = i; j < i + 16; j += 4)
                        printf("0x%08x ", *((int *)(&data[j])));
                printf("  ");
                for (j = i; j < i + 16; j++)
                        if (isprint(data[j]))
                                printf("%c", data[j]);
                        else
                                printf(".");
                printf("\n");
        }
        return;
}

void
start(void) {
        task_t me;

        printf("thread running\n");
        me = mach_task_self();
        printf("child trying to raise an exception...\n");
        *(int *)(0xffffffff) = 0x1234567;
        printf("child exit\n");
        return;
}

int
main(void) {
        task_t  me;
        mach_port_t exc;
        kern_return_t err;
        char buf[1024];
        mach_msg_header_t *msgh;
        mach_msg_return_t ret;
        pthread_t th;
        sigset_t sigset;

        me = mach_task_self();
        printf("me = %x\n", me);

        err = mach_port_allocate(me, MACH_PORT_RIGHT_RECEIVE, &exc);
        printf("err = %x, exc = %x\n", err, exc);

        err = mach_port_insert_right(me, exc, exc,
            MACH_MSG_TYPE_MAKE_SEND);
        printf("err = %x, exc = %x\n", err, exc);

        err = task_set_exception_ports(me, 
            EXC_MASK_BAD_ACCESS, exc, EXCEPTION_DEFAULT, 1);
        printf("err = %x\n", err);

        sigemptyset(&sigset);
        sigaddset(&sigset, SIGSEGV);

        err = sigprocmask(SIG_BLOCK, &sigset, NULL);
        printf("err = %d\n", err);

        err = pthread_create(&th, NULL, (void *)start, NULL);

        sleep(1);
        printf("ready to receive an exception\n");

        msgh = (mach_msg_header_t *)&buf[0];
        msgh->msgh_bits = 0;
        msgh->msgh_size = 1024;
        msgh->msgh_remote_port = 0;
        msgh->msgh_local_port = exc;
        msgh->msgh_id = 0;

        ret = mach_msg_receive(msgh);
        printf("ret = %x\n", ret);

        dump((char *)msgh, msgh->msgh_size);

        return 0;
}

$ ./excsignal
me = 103
err = 0, exc = 907
err = 0, exc = 907
err = 0
err = 0
thread running
child trying to raise an exception...
ready to receive an exception
ret = 0
0xbffff9a0  0x80001112 0x0000004c 0x00000c03 0x00000907   .......L........
0xbffff9b0  0x0d9a3940 0x00000961 0x00000002 0x00000b03   ..9@...a........
0xbffff9c0  0x0d9a3960 0x24481100 0x00000103 0x0217280b   ..9`$H........(.
0xbffff9d0  0x00001100 0x00000000 0x00000000 0x00000001   ................
0xbffff9e0  0x00000002 0x00000001 0xffffffff 0x00000000   ................

-- 
Emmanuel Dreyfus
Il y a 10 sortes de personnes dans le monde: ceux qui comprennent 
le binaire et ceux qui ne le comprennent pas.
manu@netbsd.org