diff --git a/mps/code/prmci6.h b/mps/code/prmci6.h new file mode 100644 index 00000000000..e3fbc4f866c --- /dev/null +++ b/mps/code/prmci6.h @@ -0,0 +1,65 @@ +/* prmci3.h: PROTECTION MUTATOR CONTEXT (Intel 386) + * + * $Id$ + * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + * + * .readership: MPS developers. + */ + +#ifndef prmci3_h +#define prmci3_h + + +#include "mpm.h" + +typedef Word *MRef; /* pointer to a machine word */ + +MRef Prmci3AddressHoldingReg(MutatorFaultContext, unsigned int); + +void Prmci3DecodeFaultContext(MRef *, Byte **, MutatorFaultContext); + +void Prmci3StepOverIns(MutatorFaultContext, Size); + +#endif /* prmci3_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/prmci6w3.c b/mps/code/prmci6w3.c new file mode 100644 index 00000000000..dec14497988 --- /dev/null +++ b/mps/code/prmci6w3.c @@ -0,0 +1,120 @@ +/* prmci3w3.c: PROTECTION MUTATOR CONTEXT INTEL 386 (Win32) + * + * $Id$ + * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + * + * PURPOSE + * + * .purpose: This module implements the part of the protection module + * that decodes the MutatorFaultContext. + * + * SOURCES + * + * .source.i486: Intel486 Microprocessor Family Programmer's + * Reference Manual (book.intel92). + * + * ASSUMPTIONS + * + * .assume.regref: The resisters in the context can be modified by + * storing into an MRef pointer. + */ + +#include "prmcw3.h" +#include "prmci3.h" +#include "mpm.h" + +SRCID(prmci3w3, "$Id$"); + + +/* Prmci3AddressHoldingReg -- Return an address for a given machine register */ + +MRef Prmci3AddressHoldingReg(MutatorFaultContext context, unsigned int regnum) +{ + PCONTEXT wincont; + + AVER(regnum <= 7); + AVER(regnum >= 0); + + wincont = context->ep->ContextRecord; + + switch (regnum) { + case 0: return (MRef)&wincont->Eax; + case 1: return (MRef)&wincont->Ecx; + case 2: return (MRef)&wincont->Edx; + case 3: return (MRef)&wincont->Ebx; + case 4: return (MRef)&wincont->Esp; + case 5: return (MRef)&wincont->Ebp; + case 6: return (MRef)&wincont->Esi; + case 7: return (MRef)&wincont->Edi; + } + NOTREACHED; + return NULL; /* suppress warning */ +} + + +/* Prmci3DecodeFaultContext -- decode fault context */ + +void Prmci3DecodeFaultContext(MRef *faultmemReturn, Byte **insvecReturn, + MutatorFaultContext context) +{ + LPEXCEPTION_RECORD er; + + er = context->ep->ExceptionRecord; + + /* Assert that this is an access violation. The computation of */ + /* faultmem depends on this. */ + AVER(er->ExceptionCode == EXCEPTION_ACCESS_VIOLATION); + + *faultmemReturn = (MRef)er->ExceptionInformation[1]; + *insvecReturn = (Byte*)context->ep->ContextRecord->Eip; +} + + +/* Prmci3StepOverIns -- skip an instruction by changing the context */ + +void Prmci3StepOverIns(MutatorFaultContext context, Size inslen) +{ + context->ep->ContextRecord->Eip += (DWORD)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/proti6.c b/mps/code/proti6.c new file mode 100644 index 00000000000..221fd1376af --- /dev/null +++ b/mps/code/proti6.c @@ -0,0 +1,283 @@ +/* proti3.c: PROTECTION MUTATOR CONTEXT (INTEL 386) + * + * $Id$ + * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + * + * .design: See for the generic design of the interface + * which is implemented in this module, including the contracts for the + * functions. + * + * .purpose: This module implements the part of the protection module + * that implements the MutatorFaultContext type. + * + * .requirements: Current requirements are for limited support only, for + * stepping the sorts of instructions that the Dylan compiler might + * generate for table vector access - i.e., a restricted subset of MOV + * addressing modes. This avoids the need to scan entire weak tables at + * an inappropriate rank when a page fault occurs. + * + * + * SOURCES + * + * .source.i486: Intel486 Microprocessor Family Programmer's + * Reference Manual + * + * .source.dylan: Dylan table code implementation. Especially the + * following HOPE units: + * D-lib-dylan!table.dylan (class , slot entry-element) + * D-dfmc-harp-cg!harp-primitives.dylan (method op--repeated-slot-element) + * D-harp-pentium-harp!moves.dylan (pentium-template ld-index) + * + * + * ASSUMPTIONS + * + * .assume.null: It's always safe for Prot*StepInstruction to return + * ResUNIMPL. A null implementation of this module would be overly + * conservative but otherwise correct. + * + * .assume.want: The Dylan implementation is likely to access a + * weak table vector using either MOV r/m32,r32 or MOV r32,r/m32 + * instructions, where the r/m32 operand will be of one of the forms + * disp8[reg], disp8[reg1][reg2], disp8[reg1][reg2*4] (see .source.dylan + * and .source.i486) + * + * .assume.i3: Assume the following about the i386 environment: + * Steppable instructions (.assume.want) use the CS, DS & SS + * segment registers only (see .source.i486 Table 2-3). + * The procesor runs in 32 bit mode. + * The CS, DS and SS segment registers all describe identical 32- + * bit flat address spaces. + */ + +#include "mpm.h" +#include "prmci3.h" + +SRCID(proti3, "$Id$"); + + +/* DecodeCB -- Decode an Intel x86 control byte into Hi, Medium & Low fields */ + +static void DecodeCB(unsigned int *hReturn, + unsigned int *mReturn, + unsigned int *lReturn, + Byte op) +{ + /* see .source.i486 Figure 26-2 */ + unsigned int uop = (unsigned int)op; + *lReturn = uop & 7; + uop = uop >> 3; + *mReturn = uop & 7; + uop = uop >> 3; + *hReturn = uop & 3; +} + + +/* DecodeSIB -- Decode a Scale Index Base byte for an Intel x86 instruction */ + +static void DecodeSIB(unsigned int *sReturn, + unsigned int *iReturn, + unsigned int *bReturn, + Byte op) +{ + DecodeCB(sReturn, iReturn, bReturn, op); +} + + +/* DecodeModRM -- Decode a ModR/M byte for an Intel x86 instruction */ + +static void DecodeModRM(unsigned int *modReturn, + unsigned int *rReturn, + unsigned int *mReturn, + Byte op) +{ + DecodeCB(modReturn, rReturn, mReturn, op); +} + + +/* RegValue -- Return the value of a machine register from a context */ + +static Word RegValue(MutatorFaultContext context, unsigned int regnum) +{ + MRef addr; + + addr = Prmci3AddressHoldingReg(context, regnum); + return *addr; +} + + +/* Return a byte element of an instruction vector as a + * Word value, with sign extension + */ +static Word SignedInsElt(Byte insvec[], Count i) +{ + signed char eltb; + + eltb = ((signed char*)insvec)[i]; + return (Word)eltb; +} + + +/* If a MOV instruction is a sufficiently simple example of a + * move between a register and memory (in either direction), + * then find the register, the effective address and the size + * of the instruction. The instruction is considered sufficiently + * simple if it uses a single byte displacement, a base register, + * and either no index or a (possibly scaled) register. + */ +static Bool DecodeSimpleMov(unsigned int *regnumReturn, + MRef *memReturn, + Size *inslenReturn, + MutatorFaultContext context, + Byte insvec[]) +{ + unsigned int mod; + unsigned int r; + unsigned int m; + + DecodeModRM(&mod, &r, &m, insvec[1]); /* .source.i486 Table 26-3 */ + if(1 == mod) { + /* Only know about single byte displacements, .assume.want */ + Word base; + Word index; + Word disp; + + if(4 == m) { + /* There is an index. */ + unsigned int s; + unsigned int i; + unsigned int b; + + DecodeSIB(&s, &i, &b, insvec[2]); /* .source.i486 Table 26-3 */ + if(4 == i) { + return FALSE; /* degenerate SIB form - unused by Dylan compiler */ + } + disp = SignedInsElt(insvec, 3); + base = RegValue(context, b); + index = RegValue(context, i) << s; + *inslenReturn = 4; + } else { + /* MOV with reg1 & [reg2+byte] parameters */ + disp = SignedInsElt(insvec, 2); + base = RegValue(context, m); + index = 0; + *inslenReturn = 3; + } + *regnumReturn = r; + *memReturn = (MRef)(base + index + disp); /* .assume.i3 */ + return TRUE; + } + + return FALSE; +} + + +static Bool IsSimpleMov(Size *inslenReturn, + MRef *srcReturn, + MRef *destReturn, + MutatorFaultContext context) +{ + Byte *insvec; + unsigned int regnum; + MRef mem; + MRef faultmem; + + Prmci3DecodeFaultContext(&faultmem, &insvec, context); + + /* .assume.want */ + /* .source.i486 Page 26-210 */ + if((Byte)0x8b == insvec[0]) { + /* This is an instruction of type MOV reg, r/m32 */ + if(DecodeSimpleMov(®num, &mem, inslenReturn, context, insvec)) { + AVER(faultmem == mem); /* Ensure computed address matches exception */ + *srcReturn = mem; + *destReturn = Prmci3AddressHoldingReg(context, regnum); + return TRUE; + } + } else if((Byte)0x89 == insvec[0]) { + /* This is an instruction of type MOV r/m32, reg */ + if(DecodeSimpleMov(®num, &mem, inslenReturn, context, insvec)) { + AVER(faultmem == mem); /* Ensure computed address matches exception */ + *destReturn = mem; + *srcReturn = Prmci3AddressHoldingReg(context, regnum); + return TRUE; + } + } + + return FALSE; +} + + +Bool ProtCanStepInstruction(MutatorFaultContext context) +{ + Size inslen; + MRef src; + MRef dest; + + /* .assume.null */ + /* .assume.want */ + if(IsSimpleMov(&inslen, &src, &dest, context)) { + return TRUE; + } + + return FALSE; +} + + +Res ProtStepInstruction(MutatorFaultContext context) +{ + Size inslen; + MRef src; + MRef dest; + + /* .assume.null */ + /* .assume.want */ + if(IsSimpleMov(&inslen, &src, &dest, context)) { + *dest = *src; + Prmci3StepOverIns(context, inslen); + return ResOK; + } + + return ResUNIMPL; +} + + +/* 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. + */