1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-04-27 08:43:40 -07:00

Port instruction stepper to x64 with stub instruction decode

Copied from Perforce
 Change: 178320
 ServerID: perforce.ravenbrook.com
This commit is contained in:
David Lovemore 2012-05-24 17:13:04 +01:00
parent 0ea1ae3aba
commit 1184e96675
4 changed files with 49 additions and 202 deletions

View file

@ -1,4 +1,4 @@
/* prmci3.h: PROTECTION MUTATOR CONTEXT (Intel 386)
/* prmci6.h: PROTECTION MUTATOR CONTEXT (x64)
*
* $Id$
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
@ -6,21 +6,21 @@
* .readership: MPS developers.
*/
#ifndef prmci3_h
#define prmci3_h
#ifndef prmci6_h
#define prmci6_h
#include "mpm.h"
typedef Word *MRef; /* pointer to a machine word */
MRef Prmci3AddressHoldingReg(MutatorFaultContext, unsigned int);
MRef Prmci6AddressHoldingReg(MutatorFaultContext, unsigned int);
void Prmci3DecodeFaultContext(MRef *, Byte **, MutatorFaultContext);
void Prmci6DecodeFaultContext(MRef *, Byte **, MutatorFaultContext);
void Prmci3StepOverIns(MutatorFaultContext, Size);
void Prmci6StepOverIns(MutatorFaultContext, Size);
#endif /* prmci3_h */
#endif /* prmci6_h */
/* C. COPYRIGHT AND LICENSE

View file

@ -1,4 +1,4 @@
/* prmci3w3.c: PROTECTION MUTATOR CONTEXT INTEL 386 (Win32)
/* prmci6w3.c: PROTECTION MUTATOR CONTEXT INTEL 386 (Win32)
*
* $Id$
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
@ -10,8 +10,6 @@
*
* SOURCES
*
* .source.i486: Intel486 Microprocessor Family Programmer's
* Reference Manual (book.intel92).
*
* ASSUMPTIONS
*
@ -20,41 +18,49 @@
*/
#include "prmcw3.h"
#include "prmci3.h"
#include "prmci6.h"
#include "mpm.h"
SRCID(prmci3w3, "$Id$");
SRCID(prmci6w3, "$Id$");
/* Prmci3AddressHoldingReg -- Return an address for a given machine register */
/* Prmci6AddressHoldingReg -- Return an address for a given machine register */
MRef Prmci3AddressHoldingReg(MutatorFaultContext context, unsigned int regnum)
MRef Prmci6AddressHoldingReg(MutatorFaultContext context, unsigned int regnum)
{
PCONTEXT wincont;
AVER(regnum <= 7);
AVER(regnum <= 16);
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;
case 0: return (MRef)&wincont->Rax;
case 1: return (MRef)&wincont->Rcx;
case 2: return (MRef)&wincont->Rdx;
case 3: return (MRef)&wincont->Rbx;
case 4: return (MRef)&wincont->Rsp;
case 5: return (MRef)&wincont->Rbp;
case 6: return (MRef)&wincont->Rsi;
case 7: return (MRef)&wincont->Rdi;
case 8: return (MRef)&wincont->R8;
case 9: return (MRef)&wincont->R9;
case 10: return (MRef)&wincont->R10;
case 11: return (MRef)&wincont->R11;
case 12: return (MRef)&wincont->R12;
case 13: return (MRef)&wincont->R13;
case 14: return (MRef)&wincont->R14;
case 15: return (MRef)&wincont->R15;
}
NOTREACHED;
return NULL; /* suppress warning */
}
/* Prmci3DecodeFaultContext -- decode fault context */
/* Prmci6DecodeFaultContext -- decode fault context */
void Prmci3DecodeFaultContext(MRef *faultmemReturn, Byte **insvecReturn,
void Prmci6DecodeFaultContext(MRef *faultmemReturn, Byte **insvecReturn,
MutatorFaultContext context)
{
LPEXCEPTION_RECORD er;
@ -66,15 +72,15 @@ void Prmci3DecodeFaultContext(MRef *faultmemReturn, Byte **insvecReturn,
AVER(er->ExceptionCode == EXCEPTION_ACCESS_VIOLATION);
*faultmemReturn = (MRef)er->ExceptionInformation[1];
*insvecReturn = (Byte*)context->ep->ContextRecord->Eip;
*insvecReturn = (Byte*)context->ep->ContextRecord->Rip;
}
/* Prmci3StepOverIns -- skip an instruction by changing the context */
/* Prmci6StepOverIns -- skip an instruction by changing the context */
void Prmci3StepOverIns(MutatorFaultContext context, Size inslen)
void Prmci6StepOverIns(MutatorFaultContext context, Size inslen)
{
context->ep->ContextRecord->Eip += (DWORD)inslen;
context->ep->ContextRecord->Rip += (DWORD64)inslen;
}

View file

@ -1,4 +1,4 @@
/* proti3.c: PROTECTION MUTATOR CONTEXT (INTEL 386)
/* proti6.c: PROTECTION MUTATOR CONTEXT (x64)
*
* $Id$
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
@ -10,23 +10,12 @@
* .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 <entry-vector>, 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)
* .source.amd64: AMD64 Architecture Programmers Manual Volume 3:
* General-Purpose and System Instructions
* <http://support.amd.com/us/Processor_TechDocs/24594_APM_v3.pdf>
*
*
* ASSUMPTIONS
@ -35,140 +24,12 @@
* 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"
#include "prmci6.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;
}
SRCID(proti6, "$Id$");
static Bool IsSimpleMov(Size *inslenReturn,
@ -177,32 +38,14 @@ static Bool IsSimpleMov(Size *inslenReturn,
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(&regnum, &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(&regnum, &mem, inslenReturn, context, insvec)) {
AVER(faultmem == mem); /* Ensure computed address matches exception */
*destReturn = mem;
*srcReturn = Prmci3AddressHoldingReg(context, regnum);
return TRUE;
}
}
Prmci6DecodeFaultContext(&faultmem, &insvec, context);
/* Unimplemented */
UNUSED(inslenReturn);
UNUSED(srcReturn);
UNUSED(destReturn);
return FALSE;
}
@ -214,7 +57,6 @@ Bool ProtCanStepInstruction(MutatorFaultContext context)
MRef dest;
/* .assume.null */
/* .assume.want */
if(IsSimpleMov(&inslen, &src, &dest, context)) {
return TRUE;
}
@ -230,10 +72,9 @@ Res ProtStepInstruction(MutatorFaultContext context)
MRef dest;
/* .assume.null */
/* .assume.want */
if(IsSimpleMov(&inslen, &src, &dest, context)) {
*dest = *src;
Prmci3StepOverIns(context, inslen);
Prmci6StepOverIns(context, inslen);
return ResOK;
}

View file

@ -20,7 +20,7 @@ MPM = <ring> <mpm> <bt> <protocol> <boot> \
<arenavm> <arenacl> <locus> <arena> <global> <tract> <reserv> \
<pool> <poolabs> <poolmfs> <poolmv> \
<root> <format> <buffer> <walk> <lockw3> \
<ref> <trace> <traceanc> <prmcan> <protw3> \
<ref> <trace> <traceanc> <protw3> <proti6> <prmci6w3> \
<shield> <vmw3> \
<thw3> <thw3i6> <ssw3i6> <mpsi> <mpsiw3> <ld> <span> \
<event> <seg> <sac> <poolmrg> <message> <dbgpool> <dbgpooli> \