diff --git a/mps/code/lii4gc.gmk b/mps/code/lii4gc.gmk index e51cc22a30d..2eceecb9827 100644 --- a/mps/code/lii4gc.gmk +++ b/mps/code/lii4gc.gmk @@ -8,7 +8,9 @@ PFM = lii4gc THREADSRC = lockli.c thlii4.c pthrdext.c THREADLIB = -lpthread -PFMDEFS = -D_REENTRANT +# _XOPEN_SOURCE is to get the modern POSIX signal handling +# _GNU_SOURCE is to get register numbers in prmci3li.c +PFMDEFS = -D_REENTRANT -D_XOPEN_SOURCE=500 -D_GNU_SOURCE MPMPF = ${THREADSRC} vmix.c \ protix.c protlii3.c proti3.c prmci3li.c ssixi3.c span.c @@ -23,7 +25,7 @@ CC = cc # Suppress some warnings (SuSE). # .void: -Wpointer-arith cannot be used because the string.h header does # arithmetic on void*. -CFLAGSCOMPILER := $(subst -Wpointer-arith,,$(CFLAGSCOMPILER)) +CFLAGSCOMPILER := -pthread $(subst -Wpointer-arith,,$(CFLAGSCOMPILER)) include comm.gmk diff --git a/mps/code/prmci3li.c b/mps/code/prmci3li.c index eb22ff78aa6..27d3ea9c565 100644 --- a/mps/code/prmci3li.c +++ b/mps/code/prmci3li.c @@ -21,8 +21,7 @@ * storing into an MRef pointer. */ -/* prmcli.h will include mpm.h after defining open sesame magic */ -#include "prmcli.h" +#include "prmcix.h" #include "prmci3.h" SRCID(prmci3li, "$Id$"); @@ -30,26 +29,26 @@ SRCID(prmci3li, "$Id$"); /* Prmci3AddressHoldingReg -- return an address of a register in a context */ -MRef Prmci3AddressHoldingReg(MutatorFaultContext context, unsigned int regnum) +MRef Prmci3AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum) { - struct sigcontext *scp; + gregset_t *gregs; AVER(regnum <= 7); AVER(regnum >= 0); - scp = context->scp; + gregs = &mfc->ucontext->uc_mcontext.gregs; /* .source.i486 */ /* .assume.regref */ switch (regnum) { - case 0: return (MRef)&scp->eax; - case 1: return (MRef)&scp->ecx; - case 2: return (MRef)&scp->edx; - case 3: return (MRef)&scp->ebx; - case 4: return (MRef)&scp->esp; - case 5: return (MRef)&scp->ebp; - case 6: return (MRef)&scp->esi; - case 7: return (MRef)&scp->edi; + case 0: return (MRef)&gregs[REG_EAX]; + case 1: return (MRef)&gregs[REG_ECX]; + case 2: return (MRef)&gregs[REG_EDX]; + case 3: return (MRef)&gregs[REG_EBX]; + case 4: return (MRef)&gregs[REG_ESP]; + case 5: return (MRef)&gregs[REG_EBP]; + case 6: return (MRef)&gregs[REG_ESI]; + case 7: return (MRef)&gregs[REG_EDI]; } NOTREACHED; return (MRef)NULL; /* Avoids compiler warning. */ @@ -60,29 +59,19 @@ MRef Prmci3AddressHoldingReg(MutatorFaultContext context, unsigned int regnum) void Prmci3DecodeFaultContext(MRef *faultmemReturn, Byte **insvecReturn, - MutatorFaultContext context) + MutatorFaultContext mfc) { - struct sigcontext *scp; - - scp = context->scp; - - /* Assert that this is a page fault exception. The computation of */ - /* faultmem depends on this. See .source.i486 (9.9.14). */ - AVER(scp->trapno == 14); - - /* cr2 contains the address which caused the fault. */ - /* See .source.i486 (9.9.14) and */ /* .source.linux.kernel (linux/arch/i386/mm/fault.c). */ - *faultmemReturn = (MRef)scp->cr2; - *insvecReturn = (Byte*)scp->eip; + *faultmemReturn = (MRef)mfc->info->si_addr; + *insvecReturn = (Byte*)mfc->ucontext->uc_mcontext.gregs[REG_EIP]; } /* Prmci3StepOverIns -- modify context to step over instruction */ -void Prmci3StepOverIns(MutatorFaultContext context, Size inslen) +void Prmci3StepOverIns(MutatorFaultContext mfc, Size inslen) { - context->scp->eip += (unsigned long)inslen; + mfc->ucontext->uc_mcontext.gregs[REG_EIP] += (unsigned long)inslen; } diff --git a/mps/code/prmcfr.h b/mps/code/prmcix.h similarity index 95% rename from mps/code/prmcfr.h rename to mps/code/prmcix.h index 5514b683aca..a5781118607 100644 --- a/mps/code/prmcfr.h +++ b/mps/code/prmcix.h @@ -1,4 +1,4 @@ -/* prmcfr.h: PROTECTION MUTATOR CONTEXT (FREEBSD) +/* prmcix.h: PROTECTION MUTATOR CONTEXT (UNIX) * * $Id$ * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. @@ -6,19 +6,20 @@ * .readership: MPS developers. */ -#ifndef prmcfr_h -#define prmcfr_h +#ifndef prmcix_h +#define prmcix_h #include "mpm.h" #include typedef struct MutatorFaultContextStruct { /* Protection fault context data */ + siginfo_t *info; ucontext_t *ucontext; } MutatorFaultContextStruct; -#endif /* prmcfr_h */ +#endif /* prmcix_h */ /* C. COPYRIGHT AND LICENSE diff --git a/mps/code/prmcli.h b/mps/code/prmcli.h deleted file mode 100644 index 0defd356b68..00000000000 --- a/mps/code/prmcli.h +++ /dev/null @@ -1,68 +0,0 @@ -/* prmcli.h: PROTECTION MUTATOR CONTEXT (Linux) - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .readership: MPS developers. - */ - -#ifndef prmcli_h -#define prmcli_h - - -/* open sesame magic */ -#define _BSD_SOURCE 1 -#define _XOPEN_SOURCE 500 - -#include "mpm.h" - -#include - -typedef struct MutatorFaultContextStruct { /* Protection fault context data */ - struct sigcontext *scp; /* Linux sigcontext */ -} MutatorFaultContextStruct; - - -#endif /* prmcli_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/protlii3.c b/mps/code/protlii3.c index 4984230acaa..b6067a19114 100644 --- a/mps/code/protlii3.c +++ b/mps/code/protlii3.c @@ -11,7 +11,7 @@ * .source.linux.kernel: Linux kernel source files. */ -#include "prmcli.h" +#include "prmcix.h" #ifndef MPS_OS_LI #error "protlii3.c is Linux-specific, but MPS_OS_LI is not set" @@ -27,20 +27,11 @@ #include #include #include +#include SRCID(protlii3, "$Id$"); -/* Useful stuff that doesn't appear to be in any header files. */ - -/* Interrupt number 14 is Page Fault. */ -#define TRAPNO_PAGE_FAULT 14 - -/* Bits in err field of sigcontext for interrupt 14 (page fault) */ -#define PAGE_FAULT_ERR_PAGEPROT 0x1 -#define PAGE_FAULT_ERR_WRITE 0x2 -#define PAGE_FAULT_ERR_USERMODE 0x4 - /* The previously-installed signal action, as returned by */ /* sigaction(3). See ProtSetup. */ @@ -62,39 +53,44 @@ typedef void (*__real_lii3_sighandler_t)(int, struct sigcontext); * then sigHandle does its best to pass the signal on to the * previously installed signal handler (sigNext). * - * .sigh.args: There is no officially documented way of getting the - * sigcontext, but on x86 Linux at least it is passed BY VALUE as a - * second argument to the signal handler. The prototype doesn't - * include this arg. - * See .source.linux.kernel (linux/arch/i386/kernel/signal.c). - * - * .sigh.context: We only know how to handle interrupt 14, where - * context.err gives the page fault error code and context.cr2 gives - * the fault address. See .source.i486 (9.9.14) and + * .sigh.context: We check si_code for being a memory access + * si_addr gives the fault address. See * .source.linux.kernel (linux/arch/i386/mm/fault.c). * * .sigh.addr: We assume that the OS decodes the address to something * sensible */ +/* This is defined here to keep the sources closer to those in protsgix.c + * They can't be merged yet because protsgix doesn't pass the context to + * ArenaAccess */ -static void sigHandle(int sig, struct sigcontext context) /* .sigh.args */ +#define PROT_SIGNAL SIGSEGV + +static void sigHandle(int sig, siginfo_t *info, void *context) /* .sigh.args */ { - AVER(sig == SIGSEGV); + int e; + /* sigset renamed to asigset due to clash with global on Darwin. */ + sigset_t asigset, oldset; + struct sigaction sa; - if(context.trapno == TRAPNO_PAGE_FAULT) { /* .sigh.context */ + AVER(sig == PROT_SIGNAL); + + if(info->si_code == SEGV_ACCERR) { /* .sigh.context */ AccessSet mode; - Addr base, limit; + Addr base; + ucontext_t *ucontext; MutatorFaultContextStruct mfContext; - mfContext.scp = &context; + ucontext = (ucontext_t *)context; + mfContext.ucontext = ucontext; + mfContext.info = info; - mode = ((context.err & PAGE_FAULT_ERR_WRITE) != 0) /* .sigh.context */ - ? (AccessREAD | AccessWRITE) - : AccessREAD; + /* on linux we used to be able to tell whether this was a read or a write */ + mode = AccessREAD | AccessWRITE; /* We assume that the access is for one word at the address. */ - base = (Addr)context.cr2; /* .sigh.addr */ - limit = AddrAdd(base, (Size)sizeof(Addr)); + base = (Addr)info->si_addr; /* .sigh.addr */ + /* limit = AddrAdd(base, (Size)sizeof(Addr)); */ /* Offer each protection structure the opportunity to handle the */ /* exception. If it succeeds, then allow the mutator to continue. */ @@ -106,21 +102,17 @@ static void sigHandle(int sig, struct sigcontext context) /* .sigh.args */ /* The exception was not handled by any known protection structure, */ /* so throw it to the previously installed handler. */ - /* @@@@ This is really weak. */ - /* Need to implement rest of the contract of sigaction */ - /* We might also want to set SA_RESETHAND in the flags and explicitly */ - /* reinstall the handler from withint itself so the SIG_DFL/SIG_IGN */ - /* case can work properly by just returning. */ - switch ((int)sigNext.sa_handler) { - case (int)SIG_DFL: - case (int)SIG_IGN: - abort(); - NOTREACHED; - break; - default: - (*(__real_lii3_sighandler_t)sigNext.sa_handler)(sig, context); - break; - } + e = sigaction(PROT_SIGNAL, &sigNext, &sa); + AVER(e == 0); + sigemptyset(&asigset); + sigaddset(&asigset, PROT_SIGNAL); + e = sigprocmask(SIG_UNBLOCK, &asigset, &oldset); + AVER(e == 0); + kill(getpid(), PROT_SIGNAL); + e = sigprocmask(SIG_SETMASK, &oldset, NULL); + AVER(e == 0); + e = sigaction(PROT_SIGNAL, &sa, NULL); + AVER(e == 0); } @@ -142,15 +134,14 @@ void ProtSetup(void) struct sigaction sa; int result; - sa.sa_handler = (__sighandler_t)sigHandle; /* .sigh.args */ + sa.sa_sigaction = sigHandle; sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; + sa.sa_flags = SA_SIGINFO; - result = sigaction(SIGSEGV, &sa, &sigNext); + result = sigaction(PROT_SIGNAL, &sa, &sigNext); AVER(result == 0); } - /* C. COPYRIGHT AND LICENSE * * Copyright (C) 2001-2002 Ravenbrook Limited . diff --git a/mps/code/pthrdext.c b/mps/code/pthrdext.c index ff2986a1b6f..ab50a999ff5 100644 --- a/mps/code/pthrdext.c +++ b/mps/code/pthrdext.c @@ -15,12 +15,6 @@ #include "mpm.h" -#if defined(MPS_OS_LI) -/* open sesame magic */ -#define _BSD_SOURCE 1 -#define _XOPEN_SOURCE 500 -#endif - #include #include #include @@ -79,34 +73,7 @@ static RingStruct suspendedRing; /* PThreadext suspend ring */ * suspend protocol. */ -#if defined(MPS_OS_LI) - -#include "prmcli.h" - -static void suspendSignalHandler(int sig, struct sigcontext scp) -{ - sigset_t signal_set; - MutatorFaultContextStruct mfContext; - - AVER(sig == PTHREADEXT_SIGSUSPEND); - UNUSED(sig); - - AVER(suspendingVictim != NULL); - mfContext.scp = &scp; - suspendingVictim->suspendedMFC = &mfContext; - /* Block all signals except PTHREADEXT_SIGRESUME while suspended. */ - sigfillset(&signal_set); - sigdelset(&signal_set, PTHREADEXT_SIGRESUME); - sem_post(&pthreadextSem); - sigsuspend(&signal_set); - - /* Once here, the resume signal handler has run to completion. */ - return; -} - -#elif defined(MPS_OS_FR) - -#include "prmcfr.h" +#include "prmcix.h" static void suspendSignalHandler(int sig, siginfo_t *info, @@ -135,8 +102,6 @@ static void suspendSignalHandler(int sig, return; } -#endif - /* resumeSignalHandler -- signal handler called when resuming a thread * @@ -184,15 +149,8 @@ static void PThreadextModuleInit(void) status = sigaddset(&pthreadext_sigsuspend.sa_mask, PTHREADEXT_SIGRESUME); AVER(status == 0); -#if defined(MPS_OS_LI) - pthreadext_sigsuspend.sa_flags = 0; - pthreadext_sigsuspend.sa_handler = (__sighandler_t)suspendSignalHandler; - -#elif defined(MPS_OS_FR) pthreadext_sigsuspend.sa_flags = SA_SIGINFO; pthreadext_sigsuspend.sa_sigaction = suspendSignalHandler; -#endif - pthreadext_sigresume.sa_flags = 0; pthreadext_sigresume.sa_handler = resumeSignalHandler; status = sigemptyset(&pthreadext_sigresume.sa_mask); diff --git a/mps/code/thfri4.c b/mps/code/thfri4.c index 5c3d70e16c4..8e109d2b788 100644 --- a/mps/code/thfri4.c +++ b/mps/code/thfri4.c @@ -36,7 +36,7 @@ * assumed to be recorded in the context at pointer-aligned boundaries. */ -#include "prmcfr.h" +#include "prmcix.h" #include "mpm.h" #if !defined(MPS_OS_FR) || !defined(MPS_ARCH_I4) diff --git a/mps/code/thlii4.c b/mps/code/thlii4.c index fbd376c6352..4f96e9c5fb1 100644 --- a/mps/code/thlii4.c +++ b/mps/code/thlii4.c @@ -1,4 +1,4 @@ -/* thlii3.c: Threads Manager for Intel x86 systems with LinuxThreads +/* thlii4.c: Threads Manager for Intel x86 systems with LinuxThreads * * $Id$ * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. @@ -36,7 +36,7 @@ * assumed to be recorded in the context at pointer-aligned boundaries. */ -#include "prmcli.h" +#include "prmcix.h" #include "mpm.h" #if !defined(MPS_OS_LI) || !defined(MPS_ARCH_I4) @@ -243,18 +243,18 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot) if(res != ResOK) return res; } else { - struct sigcontext *scp; + MutatorFaultContext mfc; Addr *stackBase, *stackLimit, stackPtr; - - scp = thread->mfc->scp; - if(scp == NULL) { + mcontext_t *mc; + mfc = thread->mfc; + if(mfc == NULL) { /* .error.suspend */ /* We assume that the thread must have been destroyed. */ /* We ignore the situation by returning immediately. */ return ResOK; } - stackPtr = (Addr)scp->esp; /* .i3.sp */ + stackPtr = (Addr)mfc->ucontext->uc_stack.ss_sp; /* .i3.sp */ /* .stack.align */ stackBase = (Addr *)AddrAlignUp(stackPtr, sizeof(Addr)); stackLimit = (Addr *)stackBot; @@ -273,8 +273,9 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot) * unecessarily scans the rest of the context. The optimisation * to scan only relevent parts would be machine dependent. */ - res = TraceScanAreaTagged(ss, (Addr *)scp, - (Addr *)((char *)scp + sizeof(*scp))); + mc = &mfc->ucontext->uc_mcontext; + res = TraceScanAreaTagged(ss, (Addr *)mc, + (Addr *)((char *)mc + sizeof(*mc))); if(res != ResOK) return res; }