vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | Refs

commit f4d5f654a33bbe12490f381498200a624b76de61
parent 68aa00bb602dfe9315433cd7893c0ed91949b07f
Author: Russ Cox <rsc@swtch.com>
Date:   Sun, 29 Jun 2008 14:01:06 -0400

9vx/OSX: handle SIGTRAP and SIGFPE in Mach too

Diffstat:
src/9vx/osx/signal.c | 63++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 56 insertions(+), 7 deletions(-)

diff --git a/src/9vx/osx/signal.c b/src/9vx/osx/signal.c @@ -25,12 +25,17 @@ #include "fns.h" #include "error.h" -extern void sigsegv(int, siginfo_t*, void*); /* provided by Plan 9 VX */ +#define EFLAGS_TF 0x100 + extern int invx32; static x86_thread_state32_t normal; /* normal segment registers */ static void *altstack; +static void (*sigbus)(int, siginfo_t*, void*); +static void (*sigtrap)(int, siginfo_t*, void*); +static void (*sigfpe)(int, siginfo_t*, void*); + /* * Manipulate stack in regs. */ @@ -82,9 +87,10 @@ wrapper(siginfo_t *siginfo, /* Cause EXC_BAD_INSTRUCTION to "exit" signal handler */ asm volatile( "movl %0, %%eax\n" + "movl %1, %%ebx\n" "movl $0xdeadbeef, %%esp\n" ".long 0xffff0b0f\n" - : : "r" (mcontext)); + : : "r" (mcontext), "r" (siginfo)); } void @@ -130,6 +136,7 @@ catch_exception_raise(mach_port_t exception_port, kern_return_t ret; uint *sp; mcontext_t stk_mcontext; + void (*handler)(int, siginfo_t*, void*); n = x86_THREAD_STATE32_COUNT; ret = thread_get_state(thread, x86_THREAD_STATE32, (void*)&regs, &n); @@ -138,6 +145,8 @@ catch_exception_raise(mach_port_t exception_port, switch(exception){ case EXC_BAD_ACCESS: + case EXC_BREAKPOINT: + case EXC_ARITHMETIC: save_regs = regs; if(invx32) regs.esp = (uint)altstack; @@ -153,8 +162,24 @@ catch_exception_raise(mach_port_t exception_port, stk_mcontext = alloc(&regs, sizeof *stk_mcontext); memset(stk_siginfo, 0, sizeof *stk_siginfo); - stk_siginfo->si_signo = SIGBUS; - stk_siginfo->si_addr = (void*)code_vector[1]; + switch(exception){ + default: + panic("osx/signal.c missing case %d", exception); + case EXC_BAD_ACCESS: + stk_siginfo->si_signo = SIGBUS; + stk_siginfo->si_addr = (void*)code_vector[1]; + handler = sigbus; + break; + case EXC_BREAKPOINT: + stk_siginfo->si_signo = SIGTRAP; + handler = sigtrap; + regs.eflags &= ~EFLAGS_TF; + break; + case EXC_ARITHMETIC: + stk_siginfo->si_signo = SIGFPE; + handler = sigfpe; + break; + } stk_mcontext->ss = save_regs; n = x86_FLOAT_STATE32_COUNT; @@ -169,7 +194,7 @@ catch_exception_raise(mach_port_t exception_port, sp = alloc(&regs, 3*4); sp[0] = (uint)stk_siginfo; sp[1] = (uint)stk_mcontext; - sp[2] = (uint)sigsegv; + sp[2] = (uint)handler; push(&regs, regs.eip); /* for debugger; wrapper won't return */ regs.eip = (uint)wrapper; @@ -178,6 +203,10 @@ catch_exception_raise(mach_port_t exception_port, (void*)&regs, x86_THREAD_STATE32_COUNT); if(ret != KERN_SUCCESS) panic("mach set regs failed: %d", ret); + if(0 && stk_siginfo->si_signo != SIGBUS){ + iprint("call sig %d\n", stk_siginfo->si_signo); + dumpmcontext(stk_mcontext); + } return KERN_SUCCESS; case EXC_BAD_INSTRUCTION: @@ -188,6 +217,11 @@ catch_exception_raise(mach_port_t exception_port, panic("bad instruction eip=%p", regs.eip); } stk_mcontext = (mcontext_t)regs.eax; + stk_siginfo = (siginfo_t*)regs.ebx; + if(0 && stk_siginfo->si_signo != SIGBUS){ + iprint("return sig %d\n", stk_siginfo->si_signo); + dumpmcontext(stk_mcontext); + } ret = thread_set_state(thread, x86_THREAD_STATE32, (void*)&stk_mcontext->ss, x86_THREAD_STATE32_COUNT); if(ret != KERN_SUCCESS) @@ -219,6 +253,7 @@ machsiginit(void) mach_port_t port; pthread_t pid; stack_t ss; + struct sigaction act; int ret; extern int vx32_getcontext(x86_thread_state32_t*); @@ -228,10 +263,24 @@ machsiginit(void) panic("machsiginit: no alt stack"); altstack = ss.ss_sp + ss.ss_size; + if(sigaction(SIGBUS, nil, &act) < 0) + panic("sigaction bus"); + sigbus = (void*)act.sa_handler; + + if(sigaction(SIGTRAP, nil, &act) < 0) + panic("sigaction trap"); + sigtrap = (void*)act.sa_handler; + + if(sigaction(SIGFPE, nil, &act) < 0) + panic("sigaction fpe"); + sigfpe = (void*)act.sa_handler; + mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port); mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND); - ret = thread_set_exception_ports(mach_thread_self(), EXC_MASK_BAD_ACCESS|EXC_MASK_BAD_INSTRUCTION, port, - EXCEPTION_DEFAULT, MACHINE_THREAD_STATE); + ret = thread_set_exception_ports(mach_thread_self(), + EXC_MASK_BAD_ACCESS|EXC_MASK_BAD_INSTRUCTION| + EXC_MASK_BREAKPOINT|EXC_MASK_ARITHMETIC, + port, EXCEPTION_DEFAULT, MACHINE_THREAD_STATE); pthread_create(&pid, nil, handler, (void*)port); }