diff --git a/mps/code/lii4gc.gmk b/mps/code/lii4gc.gmk index 2eceecb9827..6ed66a21f85 100644 --- a/mps/code/lii4gc.gmk +++ b/mps/code/lii4gc.gmk @@ -5,7 +5,7 @@ PFM = lii4gc -THREADSRC = lockli.c thlii4.c pthrdext.c +THREADSRC = lockli.c thli.c pthrdext.c THREADLIB = -lpthread # _XOPEN_SOURCE is to get the modern POSIX signal handling diff --git a/mps/code/lii6gc.gmk b/mps/code/lii6gc.gmk new file mode 100644 index 00000000000..d072f5f62fd --- /dev/null +++ b/mps/code/lii6gc.gmk @@ -0,0 +1,71 @@ +# lii6gc.gmk: BUILD FOR LINUX/x64/GCC PLATFORM +# +# $Id$ +# Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + +PFM = lii6gc + +THREADSRC = lockli.c thli.c pthrdext.c +THREADLIB = -lpthread + +# _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 protlii6.c proti6.c prmci6li.c ssixi6.c span.c +SWPF = than.c vmli.c protsw.c prmcan.c ssan.c + +LIBS = -lm ${THREADLIB} + +include gc.gmk + +CC = cc + +# Suppress some warnings (SuSE). +# .void: -Wpointer-arith cannot be used because the string.h header does +# arithmetic on void*. +CFLAGSCOMPILER := -pthread $(subst -Wpointer-arith,,$(CFLAGSCOMPILER)) + +include comm.gmk + + +# 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/mps.c b/mps/code/mps.c index 83ed13a477c..b2ddd0d2c1f 100644 --- a/mps/code/mps.c +++ b/mps/code/mps.c @@ -124,7 +124,7 @@ #elif defined(MPS_PF_LII4GC) #include "lockli.c" /* Linux locks */ -#include "thlii4.c" /* Linux on 32-bit Intel threading */ +#include "thli.c" /* Linux on 32-bit Intel threading */ #include "pthrdext.c" /* Posix thread extensions */ #include "vmix.c" /* Posix virtual memory */ #include "protix.c" /* Posix protection */ @@ -134,6 +134,21 @@ #include "span.c" /* generic stack probe */ #include "ssixi3.c" /* Posix on 32-bit Intel stack scan */ +/* Linux on 64-bit Intel with GCC */ + +#elif defined(MPS_PF_LII6GC) + +#include "lockli.c" /* Linux locks */ +#include "thli.c" /* Linux on 32-bit Intel threading */ +#include "pthrdext.c" /* Posix thread extensions */ +#include "vmix.c" /* Posix virtual memory */ +#include "protix.c" /* Posix protection */ +#include "protlii6.c" /* Linux on 32-bit Intel protection */ +#include "proti6.c" /* 32-bit Intel mutator context */ +#include "prmci6li.c" /* 32-bit Intel for Linux mutator context */ +#include "span.c" /* generic stack probe */ +#include "ssixi6.c" /* Posix on 32-bit Intel stack scan */ + /* Windows on 32-bit Intel with Microsoft Visual Studio */ #elif defined(MPS_PF_W3I3MV) diff --git a/mps/code/mpstd.h b/mps/code/mpstd.h index 423292c4b04..c6343b7db59 100644 --- a/mps/code/mpstd.h +++ b/mps/code/mpstd.h @@ -183,6 +183,23 @@ #define MPS_WORD_SHIFT 5 #define MPS_PF_ALIGN 4 +/* GCC 4.6.3, gcc -E -dM */ + +#elif defined(__linux__) && defined(__x86_64) && defined(__GNUC__) +#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_LII6GC) +#error "specified CONFIG_PF_... inconsistent with detected lii6gc" +#endif +#define MPS_PF_LII6GC +#define MPS_PF_STRING "lii6gc" +#define MPS_OS_LI +#define MPS_ARCH_I6 +#define MPS_BUILD_GC +#define MPS_T_WORD unsigned long +#define MPS_T_ULONGEST unsigned long +#define MPS_WORD_WIDTH 64 +#define MPS_WORD_SHIFT 6 +#define MPS_PF_ALIGN 8 + /* GCC 2.7.2, gcc -E -dM */ #elif defined(__linux__) && defined(__PPC__) && defined(__GNUC__) diff --git a/mps/code/prmci6li.c b/mps/code/prmci6li.c new file mode 100644 index 00000000000..e81a7cfd750 --- /dev/null +++ b/mps/code/prmci6li.c @@ -0,0 +1,123 @@ +/* prmci6li.c: PROTECTION MUTATOR CONTEXT x64 (LINUX) + * + * $Id$ + * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + * + * .purpose: This module implements the part of the protection module + * that decodes the MutatorFaultContext. + * + * + * SOURCES + * + * .source.linux.kernel: Linux kernel source files. + * + * + * ASSUMPTIONS + * + * .assume.regref: The resisters in the context can be modified by + * storing into an MRef pointer. + */ + +#include "prmcix.h" +#include "prmci6.h" + +SRCID(prmci6li, "$Id$"); + + +/* Prmci6AddressHoldingReg -- return an address of a register in a context */ + +MRef Prmci6AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum) +{ + Word *gregs; + + AVER(regnum <= 15); + AVER(regnum >= 0); + + gregs = (Word *)&mfc->ucontext->uc_mcontext.gregs; + + /* .assume.regref */ + /* The REG_EAX etc. symbols are only present if _GNU_SOURCE is defined. + * Currently this is in lii6gc.gmk in PFMDEFS. */ + switch (regnum) { + case 0: return &gregs[REG_RAX]; + case 1: return &gregs[REG_RCX]; + case 2: return &gregs[REG_RDX]; + case 3: return &gregs[REG_RBX]; + case 4: return &gregs[REG_RSP]; + case 5: return &gregs[REG_RBP]; + case 6: return &gregs[REG_RSI]; + case 7: return &gregs[REG_RDI]; + case 8: return &gregs[REG_R8]; + case 9: return &gregs[REG_R9]; + case 10: return &gregs[REG_R10]; + case 11: return &gregs[REG_R11]; + case 12: return &gregs[REG_R12]; + case 13: return &gregs[REG_R13]; + case 14: return &gregs[REG_R14]; + case 15: return &gregs[REG_R15]; + } + NOTREACHED; + return (MRef)NULL; /* Avoids compiler warning. */ +} + + +/* Prmci3DecodeFaultContext -- decode fault to find faulting address and IP */ + +void Prmci6DecodeFaultContext(MRef *faultmemReturn, + Byte **insvecReturn, + MutatorFaultContext mfc) +{ + /* .source.linux.kernel (linux/arch/x86/mm/fault.c). */ + *faultmemReturn = (MRef)mfc->info->si_addr; + *insvecReturn = (Byte*)mfc->ucontext->uc_mcontext.gregs[REG_RIP]; +} + + +/* Prmci3StepOverIns -- modify context to step over instruction */ + +void Prmci6StepOverIns(MutatorFaultContext mfc, Size inslen) +{ + mfc->ucontext->uc_mcontext.gregs[REG_RIP] += (Word)inslen; +} + + +/* 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/protlii6.c b/mps/code/protlii6.c new file mode 100644 index 00000000000..e149d5269ed --- /dev/null +++ b/mps/code/protlii6.c @@ -0,0 +1,180 @@ +/* protlii6.c: PROTECTION FOR LINUX (x64) + * + * $Id$ + * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + * + * SOURCES + * + * .source.linux.kernel: Linux kernel source files. + */ + +#include "prmcix.h" + +#ifndef MPS_OS_LI +#error "protlii6.c is Linux-specific, but MPS_OS_LI is not set" +#endif +#if !defined(MPS_ARCH_I6) +#error "protlii6.c is x64, but MPS_ARCH_I6 is not set" +#endif +#ifndef PROTECTION +#error "protlii6.c implements protection, but PROTECTION is not set" +#endif + +#include +#include +#include +#include +#include + +SRCID(protlii6, "$Id$"); + + + +/* The previously-installed signal action, as returned by */ +/* sigaction(3). See ProtSetup. */ + +static struct sigaction sigNext; + + +/* sigHandle -- protection signal handler + * + * This is the signal handler installed by ProtSetup to deal with + * protection faults. It is installed on the SIGSEGV signal. + * It decodes the protection fault details from the signal context + * and passes them to ArenaAccess, which attempts to handle the + * fault and remove its cause. If the fault is handled, then + * the handler returns and execution resumes. If it isn't handled, + * then sigHandle does its best to pass the signal on to the + * previously installed signal handler (sigNext). + * + * .sigh.context: We check si_code for being a memory access + * si_addr gives the fault address. See + * .source.linux.kernel (linux/arch/x86/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 */ + +#define PROT_SIGNAL SIGSEGV + +static void sigHandle(int sig, siginfo_t *info, void *context) /* .sigh.args */ +{ + int e; + /* sigset renamed to asigset due to clash with global on Darwin. */ + sigset_t asigset, oldset; + struct sigaction sa; + + AVER(sig == PROT_SIGNAL); + + if(info->si_code == SEGV_ACCERR) { /* .sigh.context */ + AccessSet mode; + Addr base; + ucontext_t *ucontext; + MutatorFaultContextStruct mfContext; + + ucontext = (ucontext_t *)context; + mfContext.ucontext = ucontext; + mfContext.info = info; + + /* 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)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. */ + + if(ArenaAccess(base, mode, &mfContext)) + return; + } + + /* The exception was not handled by any known protection structure, */ + /* so throw it to the previously installed handler. That handler won't */ + /* get an accurate context (the MPS would fail if it were the second in */ + /* line) but it's the best we can do. */ + + 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); +} + + +/* ProtSetup -- global protection setup + * + * Under Linux, the global setup involves installing a signal handler + * on SIGSEGV to catch and handle page faults (see sigHandle). + * The previous handler is recorded so that it can be reached from + * sigHandle if it fails to handle the fault. + * + * NOTE: There are problems with this approach: + * 1. we can't honor the sa_flags for the previous handler, + * 2. what if this thread is suspended just after calling signal(3)? + * The sigNext variable will never be initialized! + */ + +void ProtSetup(void) +{ + struct sigaction sa; + int result; + + sa.sa_sigaction = sigHandle; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_SIGINFO; + + result = sigaction(PROT_SIGNAL, &sa, &sigNext); + AVER(result == 0); +} + +/* 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/ssixi6.c b/mps/code/ssixi6.c index 6732f850b3b..6b425bed804 100644 --- a/mps/code/ssixi6.c +++ b/mps/code/ssixi6.c @@ -1,4 +1,4 @@ -/* ssixi6.c: UNIX/INTEL STACK SCANNING +/* ssixi6.c: UNIX/x64 STACK SCANNING * * $Id$ * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. @@ -49,22 +49,21 @@ SRCID(ssixi6, "$Id$"); Res StackScan(ScanState ss, Addr *stackBot) { + Addr calleeSaveRegs[6]; Addr *stackTop; Res res; - ASMV("push %rbp"); - ASMV("push %rbx"); - ASMV("push %r12"); - ASMV("push %r13"); - ASMV("push %r14"); - ASMV("push %r15"); - ASMV("mov %%rsp, %0" : "=r" (stackTop) :); /* stackTop = esp */ + ASMV("mov %%rbp, %0" : "=m" (calleeSaveRegs[0])); + ASMV("mov %%rbx, %0" : "=m" (calleeSaveRegs[1])); + ASMV("mov %%r12, %0" : "=m" (calleeSaveRegs[2])); + ASMV("mov %%r13, %0" : "=m" (calleeSaveRegs[3])); + ASMV("mov %%r14, %0" : "=m" (calleeSaveRegs[4])); + ASMV("mov %%r15, %0" : "=m" (calleeSaveRegs[5])); + ASMV("mov %%rsp, %0" : "=r" (stackTop) :); /* stackTop = rsp */ AVER(AddrIsAligned((Addr)stackTop, sizeof(Addr))); /* .assume.align */ res = TraceScanArea(ss, stackTop, stackBot); - ASMV("add $48, %rsp"); /* pop 6 regs to restore the stack pointer */ - return res; } diff --git a/mps/code/thlii4.c b/mps/code/thli.c similarity index 95% rename from mps/code/thlii4.c rename to mps/code/thli.c index 4f96e9c5fb1..a486e9ab9b6 100644 --- a/mps/code/thlii4.c +++ b/mps/code/thli.c @@ -1,4 +1,4 @@ -/* thlii4.c: Threads Manager for Intel x86 systems with LinuxThreads +/* thli.c: Threads Manager for LinuxThreads * * $Id$ * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. @@ -31,22 +31,26 @@ * but don't assume that the stack pointer is necessarily * word-aligned at the time of reading the context of another thread. * - * .sp: The stack pointer in the context is ESP. - * .context.regroots: The root regs are EDI, ESI, EBX, EDX, ECX, EAX are + * .sp: The stack pointer in the context is uc_stack.ss_sp. + * .context.regroots: The root regs are * assumed to be recorded in the context at pointer-aligned boundaries. */ #include "prmcix.h" #include "mpm.h" -#if !defined(MPS_OS_LI) || !defined(MPS_ARCH_I4) -#error "Compiling thlii4 when MPS_OS_LI or MPS_ARCH_I4 not defined." +#if !defined(MPS_OS_LI) +#error "Compiling thli when MPS_OS_LI is not defined." +#endif + +#if !(defined(MPS_ARCH_I4) || defined(MPS_ARCH_I6)) +#error "Need to check assumptions for thli.c are true for this architecture" #endif #include #include "pthrdext.h" -SRCID(thlii4, "$Id$"); +SRCID(thli, "$Id$"); /* ThreadStruct -- thread desriptor */ @@ -254,7 +258,7 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot) return ResOK; } - stackPtr = (Addr)mfc->ucontext->uc_stack.ss_sp; /* .i3.sp */ + stackPtr = (Addr)mfc->ucontext->uc_stack.ss_sp; /* .sp */ /* .stack.align */ stackBase = (Addr *)AddrAlignUp(stackPtr, sizeof(Addr)); stackLimit = (Addr *)stackBot;